From 4686bebfa72f4080a2c62673e24e501a339adcbf Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 30 Oct 2026 23:08:52 +0000 Subject: [PATCH] Web 0.13.36: Kommentare in Java (Lektion 6, Klammer-Kommentare in L14/L20, Glossar, Nachschlagen) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Ugz28VMPQvN81nLedJxfT7 --- CHANGELOG.md | 1 + web/lessons/de/06-eingabe-und-ausgabe.md | 85 ++++ web/lessons/de/14-verschachteln.md | 6 +- web/lessons/de/20-java.md | 6 +- web/lessons/de/begriffe.md | 4 + web/lessons/de/nachschlagen.md | 20 + web/lessons/en/06-eingabe-und-ausgabe.md | 85 ++++ web/lessons/en/14-verschachteln.md | 6 +- web/lessons/en/20-java.md | 6 +- web/lessons/en/begriffe.md | 4 + web/lessons/en/nachschlagen.md | 20 + web/lessons/pt/06-eingabe-und-ausgabe.md | 85 ++++ web/lessons/pt/14-verschachteln.md | 6 +- web/lessons/pt/20-java.md | 6 +- web/lessons/pt/begriffe.md | 4 + web/lessons/pt/nachschlagen.md | 20 + web/package-lock.json | 4 +- web/package.json | 2 +- .../{index-7CjHPKMA.js => index-C88ORUlN.js} | 375 +++++++++++++++++- ...tApp-BTFc4ICh.js => objectApp-F5rQTSyr.js} | 8 +- ...Zip-Btc0zjwE.js => projectZip-Dff7Prk7.js} | 2 +- ...obot3d-DUSoN3EA.js => robot3d-B_1PXRO1.js} | 2 +- website/app/index.html | 2 +- 23 files changed, 719 insertions(+), 40 deletions(-) rename website/app/assets/{index-7CjHPKMA.js => index-C88ORUlN.js} (99%) rename website/app/assets/{objectApp-BTFc4ICh.js => objectApp-F5rQTSyr.js} (99%) rename website/app/assets/{projectZip-Btc0zjwE.js => projectZip-Dff7Prk7.js} (99%) rename website/app/assets/{robot3d-DUSoN3EA.js => robot3d-B_1PXRO1.js} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6cda21d..b06f039e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is loosely inspired by Keep a Changelog. ### Added +- **Web 0.13.36, 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). - **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). - **Web 0.13.28, data type char:** lesson 4 now names `char` after the four data types (a single character in single quotation marks, e.g. `char note = 'C'`, more in lesson 17). Lesson 17 has its own step „Ein einzelnes Zeichen: char“: `'C'` vs. `"C"`, no empty char, `charAt`, comparing with `==`, and the character code from the ASCII table with `(int)` and `(char)` as preparation for the Caesar task, plus a competence, a checklist line and two quiz questions for it. Nachschlagen has a new table „Datentypen“ with int, double, String, boolean and char; the glossary has new entries char and Zeichencode, and Datentyp mentions char (de/en/pt). diff --git a/web/lessons/de/06-eingabe-und-ausgabe.md b/web/lessons/de/06-eingabe-und-ausgabe.md index eac891af..be363145 100644 --- a/web/lessons/de/06-eingabe-und-ausgabe.md +++ b/web/lessons/de/06-eingabe-und-ausgabe.md @@ -13,6 +13,7 @@ kurz: Werte abfragen, Ergebnisse anzeigen und das EVA-Prinzip anwenden. - 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 @@ -168,6 +169,75 @@ tipp: `int jahre = scanner.nextInt();` liest ein. `int tage = jahre * 365;` rech 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 @@ -283,6 +353,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - 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 @@ -328,4 +399,18 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] 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. ::: diff --git a/web/lessons/de/14-verschachteln.md b/web/lessons/de/14-verschachteln.md index 3673f13c..2ab27008 100644 --- a/web/lessons/de/14-verschachteln.md +++ b/web/lessons/de/14-verschachteln.md @@ -97,13 +97,15 @@ 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 Programmieren. +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 diff --git a/web/lessons/de/20-java.md b/web/lessons/de/20-java.md index 7184a51d..0c9ababd 100644 --- a/web/lessons/de/20-java.md +++ b/web/lessons/de/20-java.md @@ -98,10 +98,12 @@ public class Einmaleins { 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`. diff --git a/web/lessons/de/begriffe.md b/web/lessons/de/begriffe.md index 3d3874a1..43e90209 100644 --- a/web/lessons/de/begriffe.md +++ b/web/lessons/de/begriffe.md @@ -193,5 +193,9 @@ Eine Variable, die direkt in der Klasse steht und nicht in einer Methode. Mit `s ### 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. diff --git a/web/lessons/de/nachschlagen.md b/web/lessons/de/nachschlagen.md index 5e448afc..8c913ae5 100644 --- a/web/lessons/de/nachschlagen.md +++ b/web/lessons/de/nachschlagen.md @@ -138,3 +138,23 @@ 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. diff --git a/web/lessons/en/06-eingabe-und-ausgabe.md b/web/lessons/en/06-eingabe-und-ausgabe.md index f6107c4f..477e8982 100644 --- a/web/lessons/en/06-eingabe-und-ausgabe.md +++ b/web/lessons/en/06-eingabe-und-ausgabe.md @@ -13,6 +13,7 @@ kurz: Ask for values, show results and use the IPO model. - 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 @@ -168,6 +169,75 @@ tipp: `int years = scanner.nextInt();` reads. `int days = years * 365;` calculat 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 @@ -283,6 +353,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - 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 @@ -328,4 +399,18 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] 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. ::: diff --git a/web/lessons/en/14-verschachteln.md b/web/lessons/en/14-verschachteln.md index 132459b0..0d5e1b39 100644 --- a/web/lessons/en/14-verschachteln.md +++ b/web/lessons/en/14-verschachteln.md @@ -97,13 +97,15 @@ 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 Programming 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 diff --git a/web/lessons/en/20-java.md b/web/lessons/en/20-java.md index 656106a9..0dd86a5a 100644 --- a/web/lessons/en/20-java.md +++ b/web/lessons/en/20-java.md @@ -98,10 +98,12 @@ public class TimesTable { 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. diff --git a/web/lessons/en/begriffe.md b/web/lessons/en/begriffe.md index fe08c68f..cd95e47d 100644 --- a/web/lessons/en/begriffe.md +++ b/web/lessons/en/begriffe.md @@ -198,5 +198,9 @@ An error that only happens while the program runs, for example an index outside ### 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. diff --git a/web/lessons/en/nachschlagen.md b/web/lessons/en/nachschlagen.md index e4a48249..e8971a9a 100644 --- a/web/lessons/en/nachschlagen.md +++ b/web/lessons/en/nachschlagen.md @@ -138,3 +138,23 @@ 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. diff --git a/web/lessons/pt/06-eingabe-und-ausgabe.md b/web/lessons/pt/06-eingabe-und-ausgabe.md index 998c0dde..8578c047 100644 --- a/web/lessons/pt/06-eingabe-und-ausgabe.md +++ b/web/lessons/pt/06-eingabe-und-ausgabe.md @@ -13,6 +13,7 @@ kurz: Pedir valores, mostrar resultados e usar o modelo EPS. - 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 @@ -168,6 +169,75 @@ tipp: `int anos = scanner.nextInt();` lê. `int dias = anos * 365;` calcula, e ` 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 @@ -283,6 +353,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - 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 @@ -328,4 +399,18 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] 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. ::: diff --git a/web/lessons/pt/14-verschachteln.md b/web/lessons/pt/14-verschachteln.md index 883ca724..4440d3cb 100644 --- a/web/lessons/pt/14-verschachteln.md +++ b/web/lessons/pt/14-verschachteln.md @@ -97,13 +97,15 @@ 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 Programação. +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 diff --git a/web/lessons/pt/20-java.md b/web/lessons/pt/20-java.md index aef8b872..31556ed2 100644 --- a/web/lessons/pt/20-java.md +++ b/web/lessons/pt/20-java.md @@ -98,10 +98,12 @@ public class Tabuada { 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. diff --git a/web/lessons/pt/begriffe.md b/web/lessons/pt/begriffe.md index 7af94337..bf62466a 100644 --- a/web/lessons/pt/begriffe.md +++ b/web/lessons/pt/begriffe.md @@ -202,5 +202,9 @@ Uma variável que está diretamente na classe e não dentro de um método. Com ` ### 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. diff --git a/web/lessons/pt/nachschlagen.md b/web/lessons/pt/nachschlagen.md index 43a1c7e1..989e414b 100644 --- a/web/lessons/pt/nachschlagen.md +++ b/web/lessons/pt/nachschlagen.md @@ -138,3 +138,23 @@ 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. diff --git a/web/package-lock.json b/web/package-lock.json index 453c9fee..40bb0e42 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "visustruct-web", - "version": "0.13.35", + "version": "0.13.36", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "visustruct-web", - "version": "0.13.35", + "version": "0.13.36", "dependencies": { "@codemirror/autocomplete": "^6.20.4", "@codemirror/commands": "^6.11.1", diff --git a/web/package.json b/web/package.json index f702fe43..901842c9 100644 --- a/web/package.json +++ b/web/package.json @@ -1,7 +1,7 @@ { "name": "visustruct-web", "private": true, - "version": "0.13.35", + "version": "0.13.36", "type": "module", "scripts": { "dev": "vite", diff --git a/website/app/assets/index-7CjHPKMA.js b/website/app/assets/index-C88ORUlN.js similarity index 99% rename from website/app/assets/index-7CjHPKMA.js rename to website/app/assets/index-C88ORUlN.js index 2dd2b98c..1369c584 100644 --- a/website/app/assets/index-7CjHPKMA.js +++ b/website/app/assets/index-C88ORUlN.js @@ -1618,6 +1618,7 @@ kurz: Werte abfragen, Ergebnisse anzeigen und das EVA-Prinzip anwenden. - 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 @@ -1773,6 +1774,75 @@ tipp: \`int jahre = scanner.nextInt();\` liest ein. \`int tage = jahre * 365;\` 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 @@ -1888,6 +1958,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - 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 @@ -1933,6 +2004,20 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] 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. ::: `,bx=`--- titel: Simulation und Schreibtischtest @@ -4208,13 +4293,15 @@ 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 Programmieren. +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 @@ -6450,10 +6537,12 @@ public class Einmaleins { 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\`. @@ -12074,6 +12163,10 @@ Eine Variable, die direkt in der Klasse steht und nicht in einer Methode. Mit \` ### 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. `,Xx=`## Grundbausteine @@ -12216,6 +12309,26 @@ 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. `,Kx=`--- titel: What is a structure chart? bereich: First steps @@ -13537,6 +13650,7 @@ kurz: Ask for values, show results and use the IPO model. - 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 @@ -13692,6 +13806,75 @@ tipp: \`int years = scanner.nextInt();\` reads. \`int days = years * 365;\` calc 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 @@ -13807,6 +13990,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - 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 @@ -13852,6 +14036,20 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] 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. ::: `,s4=`--- titel: Simulation and desk check @@ -16127,13 +16325,15 @@ 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 Programming 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 @@ -18366,10 +18566,12 @@ public class TimesTable { 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. @@ -23989,6 +24191,10 @@ An error that only happens while the program runs, for example an index outside ### 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. `,N4=`## Basics @@ -24131,6 +24337,26 @@ 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. `,F4=`--- titel: O que é um estrutograma? bereich: Primeiros passos @@ -25459,6 +25685,7 @@ kurz: Pedir valores, mostrar resultados e usar o modelo EPS. - 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 @@ -25614,6 +25841,75 @@ tipp: \`int anos = scanner.nextInt();\` lê. \`int dias = anos * 365;\` calcula, 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 @@ -25729,6 +26025,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - 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 @@ -25774,6 +26071,20 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] 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. ::: `,q4=`--- titel: Simulação e teste de secretária @@ -28049,13 +28360,15 @@ 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 Programação. +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 @@ -30290,10 +30603,12 @@ public class Tabuada { 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. @@ -35917,6 +36232,10 @@ Uma variável que está diretamente na classe e não dentro de um método. Com \ ### 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. `,Ov=`## Elementos básicos @@ -36059,6 +36378,26 @@ 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. `,Av=`--- titel: Alter im Unterprogramm nach: 18 @@ -63528,7 +63867,7 @@ ${l}`)}Na=QD(((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,WB="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(WB,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function NB(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 FB(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:JB(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=NB(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 JB(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-DUSoN3EA.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 RB(i,e,t=!1){return og(i,e,t).box}function GB(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 HB(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(` + `;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,WB="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(WB,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function NB(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 FB(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:JB(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=NB(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 JB(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-B_1PXRO1.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 RB(i,e,t=!1){return og(i,e,t).box}function GB(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 HB(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=qB(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=QB(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($B(j.text)):j.text.includes(` `)?P.append(UB(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 qB(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 QB(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} @@ -63543,7 +63882,7 @@ ${l}`)}Na=QD(((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=_("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 hZ()){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),GB(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]:[]);cZ(this.body)?(this.host.showEditor(),lZ(this.body)&&this.host.reveal(["palette"])):uZ(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(),mZ(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",()=>{MB(),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 ZB(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 VB(e.game,ra);case"rescueGame":return YB(e.game,ra);case"caesar":return FB(e.key,e.text);case"cloze":return KB(e.cloze);case"pap":return sZ(e.pap);case"textFile":return ig(e.name,e.content);case"robotModel":return RB(e.focus,e.view,e.spin);case"robotQuiz":return HB(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",gZ(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 bZ=""+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 xZ=()=>c0()!==null;function Ir(i){try{localStorage.setItem(u0,i==="on"?"1":"0")}catch{}}const vZ=`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`
${e("off","VisuStruct")}${e("on","🤖 VisuBot")}${e("object","VisuObject")}
- ${mc(p(t))}`}class yZ{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")}

${wZ()}${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=ee(async()=>{const{Robot3D:e}=await import("./robot3d-DUSoN3EA.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 wZ(){const i=(t,n,a,s,r)=>``,e=(t,n,a)=>``;return`
🎛 ${p("web_visubot_controls")} + ${mc(p(t))}`}class yZ{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")}

${wZ()}${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=ee(async()=>{const{Robot3D:e}=await import("./robot3d-B_1PXRO1.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 wZ(){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)} @@ -63772,7 +64111,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=`${_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=ee(async()=>{const{Robot3D:e}=await import("./robot3d-DUSoN3EA.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=`${_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=ee(async()=>{const{Robot3D:e}=await import("./robot3d-B_1PXRO1.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=EJ(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&&gg(s.tone[0],s.tone[1]),this.showFrame(s,to-30),this.playTimer=window.setTimeout(n,to)};this.playTimer=window.setTimeout(n,to)}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 NJ={left:12,top:10},FJ=8,Ws=8e3,xi=16,no=12,t2="#fafafa";function n2(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 JJ(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,NJ),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=JJ(n2(i),r-2*no,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,FJ);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:t2}));const g=Se("text",{x:no,y:0,"font-family":Ns,"font-size":xi,"font-weight":600,fill:"black"});return l.forEach((f,b)=>{const x=Se("tspan",{x:no,y:b*u+xi});x.textContent=f,g.append(x)}),h.append(g,d),{svg:h,width:r,height:m}}function i2(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([i2(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=t2,r.fillRect(0,0,s.width,s.height),r.drawImage(a,0,0,s.width,s.height),s}finally{URL.revokeObjectURL(n)}}function RJ(i){return new Promise((e,t)=>i.toBlob(n=>n?e(n):t(new Error("PNG konnte nicht erzeugt werden.")),"image/png"))}function GJ(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 HJ(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 VJ(i,e,t,n,a){const{page:s,draw:r}=GJ(n.width,n.height),o=await HJ(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 @@ -63987,7 +64326,7 @@ ${m}
- ${E(p("web_about_version_fmt").replace("%@","0.13.35"))} + ${E(p("web_about_version_fmt").replace("%@","0.13.36"))}
@@ -64058,7 +64397,7 @@ ${m}

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

-

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

+

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

Holger Sebastiao

${e("about_web_label","https://www.visustruct.org","www.visustruct.org")} ${e("about_developer_label","https://www.sebastiao.org","www.sebastiao.org")} @@ -64080,4 +64419,4 @@ ${m}

${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 RJ(s));break}case"pdf":{const s=await cd(t,Math.max(a,3)),r=await VJ(qJ(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 pR(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 fR=$2();Promise.all([ah(fR,!1),ih(Q2(),!1)]).then(()=>{r2(),gR();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-BTFc4ICh.js").then(n=>n.g);return{ObjectApp:t}},[],import.meta.url).then(({ObjectApp:t})=>new t(e));new mR(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()||pR(i)});export{Qn as C,bJ as J,Hb as L,ee as _,iJ as a,TJ as b,Uf as c,zR as d,Ir as e,la as f,uR as g,OZ as h,se as i,_Z as j,s1 as k,wR as m,wJ as p,hc as r,DZ 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([i2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await cd(t,a);await this.offerDownload(`${n}.png`,await RJ(s));break}case"pdf":{const s=await cd(t,Math.max(a,3)),r=await VJ(qJ(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 pR(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 fR=$2();Promise.all([ah(fR,!1),ih(Q2(),!1)]).then(()=>{r2(),gR();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-F5rQTSyr.js").then(n=>n.g);return{ObjectApp:t}},[],import.meta.url).then(({ObjectApp:t})=>new t(e));new mR(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()||pR(i)});export{Qn as C,bJ as J,Hb as L,ee as _,iJ as a,TJ as b,Uf as c,zR as d,Ir as e,la as f,uR as g,OZ as h,se as i,_Z as j,s1 as k,wR as m,wJ as p,hc as r,DZ as s,p as t,Zo as w}; diff --git a/website/app/assets/objectApp-BTFc4ICh.js b/website/app/assets/objectApp-F5rQTSyr.js similarity index 99% rename from website/app/assets/objectApp-BTFc4ICh.js rename to website/app/assets/objectApp-F5rQTSyr.js index a6a1d919..47c8f366 100644 --- a/website/app/assets/objectApp-BTFc4ICh.js +++ b/website/app/assets/objectApp-F5rQTSyr.js @@ -1,5 +1,5 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./projectZip-Btc0zjwE.js","./index-7CjHPKMA.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-7CjHPKMA.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-C88ORUlN.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.35"))} + ${b(d("web_about_version_fmt").replace("%@","0.13.36"))}
@@ -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-Btc0zjwE.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-Btc0zjwE.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-Dff7Prk7.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-Dff7Prk7.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-Btc0zjwE.js b/website/app/assets/projectZip-Dff7Prk7.js similarity index 99% rename from website/app/assets/projectZip-Btc0zjwE.js rename to website/app/assets/projectZip-Dff7Prk7.js index 1129dd75..88841f79 100644 --- a/website/app/assets/projectZip-Btc0zjwE.js +++ b/website/app/assets/projectZip-Dff7Prk7.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-BTFc4ICh.js";import"./index-7CjHPKMA.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-F5rQTSyr.js";import"./index-C88ORUlN.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-DUSoN3EA.js b/website/app/assets/robot3d-B_1PXRO1.js similarity index 99% rename from website/app/assets/robot3d-DUSoN3EA.js rename to website/app/assets/robot3d-B_1PXRO1.js index 210ba473..61afd5ec 100644 --- a/website/app/assets/robot3d-DUSoN3EA.js +++ b/website/app/assets/robot3d-B_1PXRO1.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-7CjHPKMA.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-C88ORUlN.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 bbdf2f2e..a5a59b1a 100644 --- a/website/app/index.html +++ b/website/app/index.html @@ -6,7 +6,7 @@ VisuStruct Web - +