Skip to content
This repository was archived by the owner on Nov 7, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is loosely inspired by Keep a Changelog.

### Changed

- **Web 0.14.34, broken lesson steps repaired:** lesson 3 step „Ausprobieren“ ended with „probiere Folgendes aus:“ and no list, and the checklist sat in the same step without its own heading; now there are four things to try (title, save in the workspace, open again in a second tab, export PNG and PDF), the step comes before the game, and „Checkliste“ is its own step (de/en/pt). VisuBot lesson „Sensoren“ step „Was liefert der Sensor?“ had no text; it now explains that a sensor gives a value, that a comparison turns it into `true` or `false` (table with three conditions), the comparison operators and `==` vs. `=` (de/en). The cloze explanation in lesson 4 pointed to a lesson „Java“; it is called „Struktogramm und Code“ (de/en/pt). New tests: the checklist stands in its own step „Checkliste“, and no text ends with a colon with nothing after it.
- **Web 0.14.33, a game in every lesson:** every lesson now has at least one game before its checklist (Holger: Kompetenzen, game, checklist, quiz in every lesson). New: VisuStruct lesson 36 „Zahlenraten“ gets „Zu klein oder zu groß?“ (hints, smart guessing by halving, `Math.random` ranges, guess counter, `setEnabled`, 1 to 1000; de/en/pt). All 26 robot lessons without a game get one (de/en), using the existing game types: question rounds („Welcher Baustein?“, „Wie oft fährt er?“, „Welcher Datentyp?“, „Spiel den Computer“, „Befehl oder Sensor?“, „Kopf oder Fuß?“, „Linie oder nicht?“, „Wahr oder falsch?“, „Welcher Fall läuft?“, „Notbremse“, „Licht an oder aus?“, „Laut oder leise?“, „Zu schief?“, „Welche Farbe?“, „Welche LED leuchtet?“, „Welches Fach?“, „Was steht auf dem Bildschirm?“, „Wohin fährt er?“, „Stoppuhr und Akku“, „Welche Methode?“), „Bombe entschärfen“ with mBot2 code (L6 distance, L8 colours, L19 strings) and „Von tief nach hoch“ (order, L16 speaker). Robot lessons now end like the VisuStruct lessons with the steps game, „Checkliste“ and „Wissenstest“ (the last quiz moves from the last content step to its own step after the checklist; L2 and L22 keep their quizzes in place). Because steps were inserted, saved self-assessments and quiz answers in these lessons start fresh. Tests check that every lesson in both worlds has a game before the checklist. Ten robot lessons get a second „Bombe entschärfen“ round with mBot2 code (L3, L8, L10, L11, L15, L19, L20, L22, L23, L27). New game type `::: spiel fahrt` „Wo landet der mBot2?“ (`web/src/learn/driveGame.ts`, `web/src/ui/driveGameView.ts`): each round shows mBot2 code and a small map with walls, black and coloured fields; the pupil taps the field where the robot stops, then the robot drives the route on the map using the real simulation (L1, L3, L4, L7, L8, L10; a test drives every round and checks the target field). New game type `::: spiel kreuzwort` „Begriffe-Rätsel“: a standalone crossword with the terms of the lesson and a keyword (L5, L18, L24, L27, one per VisuBot part; de ROBOTER, SENSOR, AKTOR, METHODE, en ROBOT, SENSOR, SOUND, METHOD).
- **Web 0.14.32, VisuBot: missing basics added:** four new robot lessons, inserted by file name without renaming (the series now has 27 lessons): „Struktogramm und Editor“ at the start (algorithm, Nassi-Shneiderman, the three building blocks with mBot2 examples, inserting/moving/deleting, saving and the workspace; exercise „Um die Ecke“), „Schritt für Schritt testen“ after Variables (simulation controls, desk-check table, logic error exercise „Die Spirale reparieren“ with a faulty start diagram), „Erst fahren, dann prüfen“ after the while loop (do-while vs. while table, structogram exercise, Java „Schritte zählen“) and „Notbremse mit break“ after buttons/joystick (endless loop with exit, Java `while (true)` + `break` with button A). Every robot lesson from lesson 4 on now has a Java exercise „Warum läuft das nicht?“ (`vb-fehler-<lesson>`): Ludwig's version of the lesson's program has one mistake (wrong case, typo, missing argument, unknown variable, missing quotation marks); the student runs it, reads the error message and fixes it. Lesson 22 gets the Java exercise „Rechteck mit Umdrehungen“. A test checks that every start diagram fails its exercise (de/en).
- **Web 0.14.31, web app links point to visucode.de:** the website now lives on one subdomain per world (visustruct.visucode.de, visubot.visucode.de, visuobject.visucode.de, published from the GitLab repo visucode/website). The app's home, imprint and privacy links go to the start page of the current world there (relative on its own subdomain, e.g. `../de/index.html`, otherwise absolute); before, in VisuBot they pointed to `../de/visubot.html`, which no longer exists. On visubot.visucode.de and visuobject.visucode.de the app starts in that world when no world was chosen yet. The about link (web and Swift app) and the Messprotokoll links in lesson 22 use the new addresses (`web/src/ui/site.ts`, test `site.test.ts`).
Expand Down
15 changes: 12 additions & 3 deletions web/lessons/de/03-speichern-oeffnen-exportieren.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ Den [Titel](#zeige-titel) eines Diagramms trägst du in das Feld über dem Struk

Unter dem [Zahnrad](#zeige-textgroesse) oben rechts stellst du bei Textgröße die Schriftgröße ein. Ein größerer Text wirkt auch beim Exportieren als Bild.

## Ausprobieren

Öffne eine deiner Übungen aus Lektion 2 und probiere Folgendes aus:

1. Gib dem Diagramm im Feld [Titel](#zeige-titel) über dem Struktogramm einen Namen, zum Beispiel `Hallo Welt`.
2. [Speichere](#zeige-speichern) es in deinem Workspace. Schau in der Spalte [📁 Dateien](#zeige-dateien) nach: Steht es im Ordner von heute?
3. Öffne mit **+** einen zweiten Reiter und klicke dort in der Spalte Dateien auf dein Programm. Es öffnet sich wieder.
4. [Exportiere](#zeige-exportieren) es als **Bild (PNG)** und als **PDF (A4)**. Öffne beide Dateien und vergleiche sie.

Klappt alles? Dann weißt du, wo deine Programme liegen, und kannst sie weitergeben.

## Spiel: Wie gibst du es weiter?

::: spiel frage
Expand Down Expand Up @@ -122,9 +133,7 @@ richtig: PNG
> Ein PNG kann jeder sofort ansehen, ohne VisuStruct.
:::

## Ausprobieren

Öffne eine deiner Übungen aus Lektion 2 und probiere Folgendes aus:
## Checkliste

Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀️ kann ich sicher. Bei ⛅ und ☂️ hilft dir **Nachlesen**. Danach kommt der Wissenstest. Er zeigt dir, ob deine Einschätzung stimmt.

Expand Down
2 changes: 1 addition & 1 deletion web/lessons/de/04-variablen-und-datentypen.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ auftrag: Ergänze die fehlenden Wörter. Ganz außen steht der Rahmen, den jedes
}
}
```
erklärung: Ganze Zahlen sind `int`, Kommazahlen `double`, Texte `String` (groß geschrieben) und Wahrheitswerte `boolean`. `public class` und `public static void main` bilden den Rahmen. Im Bereich Code darfst du ihn weglassen, mehr dazu in der Lektion „Java“.
erklärung: Ganze Zahlen sind `int`, Kommazahlen `double`, Texte `String` (groß geschrieben) und Wahrheitswerte `boolean`. `public class` und `public static void main` bilden den Rahmen. Im Bereich Code darfst du ihn weglassen, mehr dazu in der Lektion „Struktogramm und Code“.
:::

## Fehler finden: Sekunden
Expand Down
12 changes: 12 additions & 0 deletions web/lessons/de/visubot/04-sensoren.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ lösung: vb-wand-vorn-loesung.visustruct

## Was liefert der Sensor?

Ein Sensor liefert einen **Wert**, so wie eine Variable. Fährt der mBot2 weiter, ändert sich der Wert: Der Abstand wird kleiner, je näher die Wand kommt. Erst ein **Vergleich** macht aus dem Wert eine Frage mit der Antwort `true` (wahr) oder `false` (falsch).

| Bedingung | Frage | Antwort bei 38 cm Abstand |
|---|---|---|
| `mbot.getDistance() < 20` | Ist die Wand näher als 20 cm? | `false` |
| `mbot.getDistance() > 30` | Ist mehr als 30 cm Platz? | `true` |
| `mbot.getLine() == 0` | Ist unter dem mBot2 alles hell? | hängt vom Boden ab |

Vergleichen kannst du mit `<` (kleiner), `>` (größer), `<=` (kleiner oder gleich), `>=` (größer oder gleich), `==` (gleich) und `!=` (ungleich).

> Für „gleich“ schreibst du **zwei** Gleichheitszeichen: `==`. Ein einzelnes `=` legt einen Wert in eine Variable, das ist etwas ganz anderes.

> 📘 **Mehr dazu ohne Roboter:** In VisuStruct gibt es die Lektion [„Verzweigung“](?visustruct&lektion=08-verzweigung). Sie öffnet sich in einem neuen Fenster.

::: übung vb-fehler-04-sensoren
Expand Down
15 changes: 12 additions & 3 deletions web/lessons/en/03-speichern-oeffnen-exportieren.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ With [Export](#zeige-exportieren) in the tools (icon with an arrow pointing up)

Under the [gear](#zeige-textgroesse) at the top right, Text size sets the font size. Larger text also shows when you export an image.

## Try it out

Open one of your exercises from lesson 2 and try the following:

1. Give the diagram a name in the [title](#zeige-titel) field above the structure chart, for example `Hello World`.
2. [Save](#zeige-speichern) it in your workspace. Look in the [📁 Files](#zeige-dateien) column: is it in today's folder?
3. Open a second tab with **+** and click your program in the Files column there. It opens again.
4. [Export](#zeige-exportieren) it as an **image (PNG)** and as a **PDF (A4)**. Open both files and compare them.

Did everything work? Then you know where your programs are and how to share them.

## Game: How do you pass it on?

::: spiel frage
Expand Down Expand Up @@ -122,9 +133,7 @@ richtig: PNG
> Anyone can look at a PNG straight away, without VisuStruct.
:::

## Try it out

Open one of your exercises from lesson 2 and try the following:
## Checklist

Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can do this confidently. For ⛅ and ☂️, **Review** helps you. Then comes the quiz. It shows you whether your self-assessment is right.

Expand Down
2 changes: 1 addition & 1 deletion web/lessons/en/04-variablen-und-datentypen.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ auftrag: Fill in the missing words. On the outside is the frame that every Java
}
}
```
erklärung: Whole numbers are `int`, decimal numbers `double`, texts `String` (with a capital S) and truth values `boolean`. `public class` and `public static void main` make up the frame. In the Code area you may leave it out, more on this in the lesson “Java”.
erklärung: Whole numbers are `int`, decimal numbers `double`, texts `String` (with a capital S) and truth values `boolean`. `public class` and `public static void main` make up the frame. In the Code area you may leave it out, more on this in the lesson “Structure chart and code”.
:::

## Find the bug: seconds
Expand Down
12 changes: 12 additions & 0 deletions web/lessons/en/visubot/04-sensoren.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ lösung: vb-wand-vorn-loesung.visustruct

## What does the sensor give you?

A sensor gives you a **value**, just like a variable. When the mBot2 drives on, the value changes: the distance gets smaller as the wall comes closer. Only a **comparison** turns the value into a question with the answer `true` or `false`.

| Condition | Question | Answer at a distance of 38 cm |
|---|---|---|
| `mbot.getDistance() < 20` | Is the wall closer than 20 cm? | `false` |
| `mbot.getDistance() > 30` | Is there more than 30 cm of space? | `true` |
| `mbot.getLine() == 0` | Is everything bright under the mBot2? | depends on the floor |

You can compare with `<` (less than), `>` (greater than), `<=` (less than or equal), `>=` (greater than or equal), `==` (equal) and `!=` (not equal).

> For "equal" you write **two** equals signs: `==`. A single `=` puts a value into a variable, which is something completely different.

> 📘 **More without the robot:** VisuStruct has the lesson ["Branch"](?visustruct&lektion=08-verzweigung). It opens in a new window.

::: übung vb-fehler-04-sensoren
Expand Down
15 changes: 12 additions & 3 deletions web/lessons/pt/03-speichern-oeffnen-exportieren.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ Com [Exportar](#zeige-exportieren) nas ferramentas (ícone com uma seta para cim

Na [roda dentada](#zeige-textgroesse) em cima à direita, em Tamanho do texto, defines o tamanho da letra. O texto maior também se nota quando exportas uma imagem.

## Experimenta

Abre um dos teus exercícios da lição 2 e experimenta o seguinte:

1. Dá um nome ao diagrama no campo [título](#zeige-titel) por cima do estrutograma, por exemplo `Olá Mundo`.
2. [Guarda-o](#zeige-speichern) no teu espaço de trabalho. Vê na coluna [📁 Ficheiros](#zeige-dateien): está na pasta de hoje?
3. Abre um segundo separador com **+** e clica lá no teu programa na coluna Ficheiros. Volta a abrir-se.
4. [Exporta-o](#zeige-exportieren) como **imagem (PNG)** e como **PDF (A4)**. Abre os dois ficheiros e compara-os.

Correu tudo bem? Então sabes onde estão os teus programas e como os partilhar.

## Jogo: Como o partilhas?

::: spiel frage
Expand Down Expand Up @@ -122,9 +133,7 @@ richtig: PNG
> Um PNG pode ser visto logo por qualquer pessoa, sem VisuStruct.
:::

## Experimenta

Abre um dos teus exercícios da lição 2 e experimenta o seguinte:
## Lista de verificação

Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ consigo com segurança. Com ⛅ e ☂️, **Rever** ajuda-te. Depois vem o teste de conhecimentos. Mostra-te se a tua autoavaliação está certa.

Expand Down
2 changes: 1 addition & 1 deletion web/lessons/pt/04-variablen-und-datentypen.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ auftrag: Preenche as palavras que faltam. Por fora está a moldura de que qualqu
}
}
```
erklärung: Números inteiros são `int`, números decimais `double`, textos `String` (com S maiúsculo) e valores lógicos `boolean`. `public class` e `public static void main` formam a moldura. Na área Código podes deixá-la de fora, há mais sobre isto na lição “Java”.
erklärung: Números inteiros são `int`, números decimais `double`, textos `String` (com S maiúsculo) e valores lógicos `boolean`. `public class` e `public static void main` formam a moldura. Na área Código podes deixá-la de fora, há mais sobre isto na lição “Estrutograma e código”.
:::

## Encontra o erro: segundos
Expand Down
4 changes: 2 additions & 2 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "visustruct-web",
"private": true,
"version": "0.14.33",
"version": "0.14.34",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
28 changes: 28 additions & 0 deletions web/test/lessons.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,34 @@ describe.each(contentLanguages)('Lernbereich: Inhalte (%s)', (lang) => {
}
})

it('die Checkliste steht in einem eigenen Schritt „Checkliste“', () => {
const title = { de: 'Checkliste', en: 'Checklist', pt: 'Lista de verificação' }[lang]
for (const lesson of lessons) {
const step = lesson.steps.find((s) => s.blocks.some((b) => b.kind === 'checklist'))
expect(step?.title, lesson.id).toBe(title)
}
})

it('kein Text endet mit einem Doppelpunkt, ohne dass etwas folgt', () => {
// „probiere Folgendes aus:“ ohne Liste darunter (Lektion 3 hatte das)
const problems: string[] = []
for (const lesson of lessons) {
for (const step of lesson.steps) {
step.blocks.forEach((block, i) => {
if (block.kind !== 'markdown') return
const parts = block.text.trim().split(/\n\s*\n/).map((p) => p.trim())
const next = step.blocks[i + 1]
parts.forEach((part, k) => {
if (!part.endsWith(':') || part.includes('\n')) return
const follows = k + 1 < parts.length || (next && next.kind !== 'markdown' && next.kind !== 'checklist')
if (!follows) problems.push(`${lesson.id} / ${step.title}: ${part}`)
})
})
}
}
expect(problems).toEqual([])
})

it('jedes verwendete Diagramm existiert und lässt sich laden', () => {
for (const { where, block } of allBlocks()) {
const files =
Expand Down
Loading
Loading