Sprache: 'Modell' -> '3D-Modell' konsequent durchgesetzt

Herb-Beobachtung: 'Fremdes Modell waehlen + drucken' liest sich
mehrdeutig — kurz dachte er, es waeren fremde Drucker (Prusa) gemeint.
Konvention im Glossar dokumentiert: '3D-Modell' fuer Druckdateien,
'Drucker'/'Druckermodell' fuer die Maschinen.

Geaendert:
- L2-Titel: 'Fremdes Modell waehlen + drucken'
    -> '3D-Modell aus dem Netz drucken'
- L3-Titel: 'Customizer / parametrisches Modell'
    -> 'Customizer — parametrisches 3D-Modell anpassen'
- L1-aufgabe_md: punktuelle Praezisierungen ('baut ein Modell' etc.)
- L2/L3-aufgabe_md: durchgaengig '3D-Modell'
- Startseite + selbstlern-loop.md + kurskonzept.md: dito
- docs/glossar.md: neue Sektion 'Sprach-Konvention: Modell' mit
  Disambiguierungs-Hinweis

Migration migrations/2026-05-24_lektion_sprache_3d_modell.py
(idempotent via Marker SPRACHE_3D_MODELL_V1 in L1, Titel-Vergleich
fuer L2/L3).

seed.py vereinfacht — L1/L2/L3 sind nur noch Minimal-Stubs, die volle
Texte kommen aus den Migrationen. Bei voller Doku-Installation:
seed.py + alle migrations/ laufen lassen.
This commit is contained in:
2026-05-24 19:41:36 +02:00
parent 81fb3224f0
commit f534256a0a
6 changed files with 166 additions and 29 deletions

View File

@@ -10,6 +10,15 @@ tags: [glossar, begriffe]
> Begriffe, die in [[../kurskonzept]] und den Lektionen vorkommen. Für SuS und
> für Markus (falls noch nicht 3D-Druck-vertraut).
## Sprach-Konvention: „Modell" — welches Modell?
Auf der Site **bewusst auseinandergehalten**:
- **3D-Modell** — die digitale Druckvorlage (STL- oder 3MF-Datei). Das, was wir slicen und drucken.
- **Druckermodell** oder einfach **Drucker** — die Maschine (z.B. P2S, A1 mini). Bei Bedarf auch: „unsere P-Serie" (P1S/X1C/P2S) vs. „der A1 mini".
**Wenn nur „Modell" geschrieben steht und der Kontext unklar ist, schreib es bitte aus** — sowohl Lehrer (beim Inline-Edit) als auch SuS in eigenen Texten. Sonst entstehen Missverständnisse wie „mit fremdem Modell drucken" → meint das einen Prusa-Drucker oder eine STL aus dem Netz? (Korrekt: letzteres = fremdes **3D-Modell**.)
## Drucker + Hardware
- **AMS** (Automatic Material System) — Bambu-Wechslerbox für bis zu 4 Filamentrollen, ermöglicht Multi-Color-Druck oder automatischen Rollenwechsel.

View File

@@ -40,11 +40,11 @@ Wahl, was sie machen wollen.
| Lektion | Inhalt | Pflicht für | Nach Abschluss freigeschaltet |
|---|---|---|---|
| **L1 Drucker-Kennenlernen + Sicherheit** | Drucker-Übersicht, A1-mini-Hands-Off, Bambu Handy App einrichten, vorbereitetes Modell drucken | Neue | **Slot-Buchung** (V2 — siehe [[../decisions#E-020]]) |
| **L2 Fremdes Modell wählen + drucken** | Modell auf Printables/MakerWorld suchen, in Bambu Studio slicen, drucken | Neue | Eigene Projekte aus Katalog |
| **L3 Customizer / parametrisches Modell** | MakerWorld-Customizer: Schlüsselanhänger mit eigenem Namen | Neue | Eigenes-Projekt-Vollzugriff |
| **L4+ Eigene Modelle zeichnen** | TinkerCAD → OpenSCAD | Frei | — |
| **Eigene Projekte (Dauer-Modus)** | Idee → Modell → Druck → Iteration → Abschluss mit Reflexion → in Katalog | Frei | — |
| **L1 Drucker-Kennenlernen + Sicherheit** | Drucker-Übersicht, A1-mini-Hands-Off, Bambu Handy App einrichten, vorbereitetes 3D-Modell drucken | Neue | **Slot-Buchung** (V2 — siehe [[../decisions#E-020]]) |
| **L2 3D-Modell aus dem Netz drucken** | 3D-Modell auf Printables/MakerWorld suchen, in Bambu Studio slicen, drucken | Neue | Eigene Projekte aus Katalog |
| **L3 Customizer parametrisches 3D-Modell anpassen** | MakerWorld-Customizer: Schlüsselanhänger mit eigenem Namen | Neue | Eigenes-Projekt-Vollzugriff |
| **L4+ Eigene 3D-Modelle zeichnen** | TinkerCAD → OpenSCAD | Frei | — |
| **Eigene Projekte (Dauer-Modus)** | Idee → 3D-Modell → Druck → Iteration → Abschluss mit Reflexion → in Katalog | Frei | — |
Nach Onboarding **verschwindet die Onboarding-Karte** aus dem Cockpit (V1 — progressives Cockpit, [[../decisions#E-020]]). Erfahrene SuS sehen nur noch ihre laufenden Projekte, Druckaufträge, Slots.
@@ -60,7 +60,7 @@ Quellen: PHBern IdeenSet, inf-schule.de, ZSL Baden-Württemberg.
**Was die Site vom Arduino-Kurs grundsätzlich unterscheidet:** Jedes
abgeschlossene Projekt wird nach Lehrer-Freigabe in die interne Bibliothek
aufgenommen. Über die Jahre wächst eine **eigene Projekt-Sammlung** — wertvoller
als jeder externe Modell-Katalog, weil sie zeigt: „Das wurde bei uns
als jeder externe 3D-Modell-Katalog, weil sie zeigt: „Das wurde bei uns
schonmal gemacht."
Vollständiger Workflow: [[selbstlern-loop]].
@@ -217,7 +217,7 @@ UI im Cockpit beim ersten Aufruf eines Besuchstages:
| **Bambu Studio** | Slicer (PC), Pflicht | L1 |
| **Bambu Handy** | Live-Kamera, Druck-Steuerung | L1 |
| **Bambu Academy** | Kostenloser Drucker-Kurs mit Zertifikat | L1 |
| **Printables.com** | Modell-Plattform (sauber, kein NSFW) | L2 |
| **Printables.com** | 3D-Modell-Plattform (sauber, kein NSFW) | L2 |
| **MakerWorld.com** | Bambu-eigene Plattform + Customizer | L2 + L3 |
| **TinkerCAD** | Visuelles CAD im Browser, Klassenraum-Modus | L4 |
| **OpenSCAD** | Parametrisches CAD (Code) | L4+ |

View File

@@ -11,7 +11,7 @@ tags: [konzept, selbstlern-loop, projekte, kern]
> Die Site **wächst durch die SuS selbst**. Jedes abgeschlossene Projekt landet
> nach Lehrer-Freigabe in der internen Bibliothek. Neue SuS sehen: "Bei uns
> hat das schonmal jemand gemacht — und so ging's aus." Das schlägt jeden
> externen Modell-Katalog.
> externen 3D-Modell-Katalog.
Architektur-Einbettung: [[architektur]]. Datenmodell: [[datenmodell#projekt]],
[[datenmodell#projekt_datei]], [[datenmodell#projekt_tag]]. Lehrer-Sicht: [[lehrer-dashboard]].
@@ -56,7 +56,7 @@ stateDiagram-v2
Drei Optionen:
1. **Aus Katalog**: SuS klickt auf eine Karte → „Sowas mache ich auch" → neues Projekt-Datensatz mit `vorlage_projekt_id` befüllt. Titel + Tags vorausgefüllt, SuS kann anpassen.
2. **Komplett eigene Idee**: leerer Titel + Beschreibung.
3. **Onboarding-Pflicht-Projekt** (z.B. L2 „erstes Modell drucken"): die Lektion legt automatisch ein Projekt an.
3. **Onboarding-Pflicht-Projekt** (z.B. L2 „erstes 3D-Modell drucken"): die Lektion legt automatisch ein Projekt an.
## Station 3: Arbeiten

View File

@@ -0,0 +1,138 @@
"""Migration 2026-05-24: Sprachliche Klärung 'Modell''3D-Modell'.
Hintergrund: Herb hat angemerkt, dass 'Modell' mehrdeutig ist —
sowohl Druckermodell (P2S, A1 mini) als auch 3D-Modell (die STL-Datei).
Beim Lesen von L2 ('Fremdes Modell waehlen + drucken') hat er kurz
gedacht, es waere von fremden Druckern (Prusa) die Rede.
Loesung: konsequent '3D-Modell' fuer die Druckdateien, 'Drucker' fuer
die Maschinen.
Aenderungen:
- L2-Titel: 'Fremdes Modell waehlen + drucken' -> '3D-Modell aus dem Netz drucken'
- L3-Titel: 'Customizer / parametrisches Modell' -> 'Customizer — parametrisches 3D-Modell anpassen'
- L1-Text: 'baut ein Modell' -> 'baut ein 3D-Modell' (Schicht fuer Schicht)
+ andere mehrdeutige Stellen praezisiert
- L1-Text: 'vorbereitetes Modell' -> 'vorbereitetes 3D-Modell'
Idempotent ueber Marker im jeweiligen Text.
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from database import get_db
MARKER_L1 = "SPRACHE_3D_MODELL_V1"
MARKER_L2_TITEL = "3D-Modell aus dem Netz drucken"
MARKER_L3_TITEL = "parametrisches 3D-Modell anpassen"
def update_l1(conn):
"""L1 aufgabe_md: Praezisierungen 'Modell' -> '3D-Modell' wo es um Druckdateien geht."""
row = conn.execute("SELECT aufgabe_md FROM lektion WHERE nummer = 1").fetchone()
if not row:
return False
text = row["aufgabe_md"] or ""
if MARKER_L1 in text:
return False # schon migriert
# Konkrete Ersetzungen — gezielt, nicht global, damit "Druckermodell"-Stellen
# nicht versehentlich getroffen werden
ersetzungen = [
("baut ein Modell", "baut ein 3D-Modell"),
("entsteht so dein Modell", "entsteht so dein 3D-Modell"),
("vorbereitetes Modell drucken", "vorbereitetes 3D-Modell drucken"),
("vorbereitetes Modell zeigen", "vorbereitetes 3D-Modell zeigen"),
("ein kleines, getestetes Modell", "ein kleines, getestetes 3D-Modell"),
# "vorbereitetes Modell" generisch falls noch wo
("vorbereitetes Modell", "vorbereitetes 3D-Modell"),
]
geaendert = text
for alt, neu in ersetzungen:
geaendert = geaendert.replace(alt, neu)
# Marker am Ende ergaenzen, damit Re-Run erkennt: schon durch
geaendert += f"\n<!-- {MARKER_L1} -->"
conn.execute("UPDATE lektion SET aufgabe_md = ? WHERE nummer = 1", (geaendert,))
return True
def update_l2(conn):
"""L2: Titel + Platzhalter-Text praeziser."""
row = conn.execute("SELECT titel, aufgabe_md FROM lektion WHERE nummer = 2").fetchone()
if not row:
return False
if row["titel"] == MARKER_L2_TITEL:
return False # schon migriert
neuer_titel = MARKER_L2_TITEL
# aufgabe_md neu formulieren — Inhalt bleibt Platzhalter,
# aber sprachlich klar mit "3D-Modell"
neuer_text = (
"**Was du in dieser Lektion lernst:**\n\n"
"- Auf **Printables** oder **MakerWorld** ein fertiges 3D-Modell finden, das du drucken willst.\n"
"- Das 3D-Modell in **Bambu Studio** importieren und slicen (in Druckanweisungen umwandeln).\n"
"- Druckzeit und Materialbedarf abschaetzen.\n"
"- Den Druck planen und drucken — auf einem unserer 4 Drucker (welcher gerade frei ist).\n\n"
"**Aufgabe:** Such dir ein 3D-Modell aus, das unter 1 h Druckzeit liegt. "
"Etwas, das du wirklich haben willst — der Druck dauert mindestens so lange wie ein Schulfilm.\n\n"
"*Detaillierter Inhalt wird mit Markus ausgearbeitet — bis dahin: "
"fragt den Lehrer, der zeigt euch das Suchen + Slicen direkt am Drucker.*"
)
conn.execute(
"UPDATE lektion SET titel = ?, aufgabe_md = ? WHERE nummer = 2",
(neuer_titel, neuer_text)
)
return True
def update_l3(conn):
"""L3: Titel + Platzhalter-Text praeziser."""
row = conn.execute("SELECT titel, aufgabe_md FROM lektion WHERE nummer = 3").fetchone()
if not row:
return False
if row["titel"] == MARKER_L3_TITEL:
return False # schon migriert
neuer_titel = MARKER_L3_TITEL
neuer_text = (
"**Was du in dieser Lektion lernst:**\n\n"
"- Was ein **parametrisches 3D-Modell** ist: ein Modell, bei dem du Werte "
"(Name, Groesse, Schriftart) veraenderst und das Modell sich automatisch anpasst.\n"
"- Den **MakerWorld-Customizer** im Browser bedienen — kein eigenes CAD-Programm noetig.\n"
"- Ein Modell mit deinem **eigenen Namen** drucken (z.B. Schluesselanhaenger).\n\n"
"**Aufgabe:** Mach einen Schluesselanhaenger mit deinem Vornamen drauf — "
"veraendere Schriftart, Groesse, Loch-Position. Dann slicen + drucken.\n\n"
"**Tipp:** Das 3D-Modell *Parametric Name Keychain Creator* auf MakerWorld "
"ist ein guter Einstieg.\n\n"
"*Detaillierter Inhalt wird mit Markus ausgearbeitet.*"
)
conn.execute(
"UPDATE lektion SET titel = ?, aufgabe_md = ? WHERE nummer = 3",
(neuer_titel, neuer_text)
)
return True
def main():
conn = get_db()
geaendert = []
if update_l1(conn):
geaendert.append("L1 (Text-Klärungen)")
if update_l2(conn):
geaendert.append("L2 (Titel + Text neu)")
if update_l3(conn):
geaendert.append("L3 (Titel + Text neu)")
conn.commit()
conn.close()
if geaendert:
print(f"[migration] Sprache 3D-Modell durchgesetzt in: {', '.join(geaendert)}")
else:
print("[migration] Alle Lektionen bereits auf neuer Sprache — nichts zu tun.")
if __name__ == "__main__":
main()

26
seed.py
View File

@@ -66,25 +66,15 @@ def seed_lektionen():
"*Inhalt kommt mit Migration 2026-05-24_l1_inhalt_v2.py.*",
"Frag den Lehrer, wenn du irgendwas nicht verstehst — Sicherheit geht vor.",
"https://wiki.bambulab.com/de/p2s/manual/p2s-intro"),
(2, "Fremdes Modell waehlen + drucken",
"**Was du in dieser Lektion lernst:**\n\n"
"- Auf Printables (oder MakerWorld) ein passendes Modell finden.\n"
"- Das Modell in Bambu Studio importieren und slicen.\n"
"- Druckzeit + Material abschaetzen, Slot reservieren, drucken.\n\n"
"**Aufgabe:** Such dir auf Printables ein Modell, das unter 1 h "
"Druckzeit liegt. Such was, das du wirklich haben willst.\n\n"
"*Inhalt wird mit Markus weiter ausgearbeitet.*",
"Lizenz-Symbole sind nicht wichtig fuer uns — wir drucken nur fuer uns selbst, "
"geben nichts weiter.",
# L2/L3: Sprache angepasst per Migration 2026-05-24_lektion_sprache_3d_modell
# — 'Modell' ist mehrdeutig (Drucker- vs. 3D-Modell), durchgehend 3D-Modell verwendet.
(2, "3D-Modell aus dem Netz drucken",
"*Inhalt kommt mit Migration 2026-05-24_lektion_sprache_3d_modell.*",
"Lizenz-Symbole sind nicht wichtig fuer uns — wir drucken nur fuer uns selbst, geben nichts weiter.",
"https://www.printables.com/"),
(3, "Customizer / parametrisches Modell",
"**Was du in dieser Lektion lernst:**\n\n"
"- Was 'parametrisch' bedeutet (du veraenderst Werte, das Modell passt sich an).\n"
"- Mit dem MakerWorld-Customizer ein Modell mit deinem eigenen Namen drucken.\n\n"
"**Aufgabe:** Mach einen Schluesselanhaenger mit deinem Vornamen drauf — "
"veraendere Schriftart, Groesse, Loch-Position.\n\n"
"*Inhalt wird mit Markus weiter ausgearbeitet.*",
"Tipp: Das Modell 'Parametric Name Keychain Creator' auf MakerWorld ist ein guter Einstieg.",
(3, "Customizer parametrisches 3D-Modell anpassen",
"*Inhalt kommt mit Migration 2026-05-24_lektion_sprache_3d_modell.*",
"Tipp: Das 3D-Modell 'Parametric Name Keychain Creator' auf MakerWorld ist ein guter Einstieg.",
"https://makerworld.com/en/models/1320280"),
]
conn = get_db()

View File

@@ -5,7 +5,7 @@
<div style="text-align: center; margin-bottom: 2rem;">
<h1 style="font-size: 2rem;">3D-Druck-AG</h1>
<p style="color: var(--text-light); font-size: 1.1rem;">
Vom fertigen Modell zum eigenen Druck &mdash; Schritt fuer Schritt.
Vom fertigen 3D-Modell zum eigenen Druck &mdash; Schritt fuer Schritt.
</p>
</div>
@@ -30,7 +30,7 @@
<a href="/lektionen" class="card bereich-card" style="text-decoration:none; color:inherit; border-top: 5px solid var(--success); text-align:center; padding: 2.5rem 1.5rem;">
<div style="font-size: 3.5rem; margin-bottom: 0.5rem;">&#x1F4DA;</div>
<h2 style="color: var(--success);">Lektionen</h2>
<p style="margin: 0.8rem 0;">L1 Drucker-Kennenlernen &middot; L2 Modell drucken &middot; L3 Customizer &middot; danach frei.</p>
<p style="margin: 0.8rem 0;">L1 Drucker-Kennenlernen &middot; L2 3D-Modell drucken &middot; L3 Customizer &middot; danach frei.</p>
<span class="btn" style="background: var(--success); color: white;">Lektionen ansehen</span>
</a>