Files
3d.lehrstun.de/tiere.py
Hans Puettmann 4658d4931a Initial commit: Konzept v2 + Etappe 1 (Blueprints + Login + Profile)
Schwester-Projekt zu arduino.lehrstun.de fuer die 3D-Druck-AG am
Lessing-Gymnasium. Offene jahrelange Nachmittags-AG (kein Trimester),
8-10 Einzel-SuS mit optionalen 2er-Paarungen, 4 Bambu-Lab-Drucker
(3 geschlossen + 1 A1 mini).

Konzept v2 (Reality-Check-Iteration 2026-05-24):
- Onboarding-Pfad statt Pflicht-Lektionen (L1-L3 selbst-zertifiziert)
- Selbstlern-Loop als Kern: SuS-Projekte wachsen die interne Bibliothek
- Drill-Down-Lehrer-Dashboard (Wer ist hier / Wartet Review / Haengt fest)
- Cockpit progressiv: zeigt nur was zum Status passt
- Bambu-Cloud-API fuer Drucker-Live-Status (fragil + Fallback manuell)
- Three.js-Vorschau fuer Cover-aus-3D-Ansicht (Etappe 6)
- Vollstaendige Doku als Obsidian-Vault (24 Markdown-Dateien)
- Entscheidungen E-001 bis E-022 in docs/decisions.md

Etappe 1 lauffaehig (~1800 Zeilen Code):
- Blueprint-Struktur (V8): routes/oeffentlich+profil+admin+api,
  services/auth+bambu+datei
- Komplettes Schema in database.py (14 Tabellen, idempotent)
- Login mit bcrypt + persistentem Lockout in DB (V7, verbessert ggue
  Arduino-Kurs der In-Memory-Dict nutzt)
- Admin-Login + Profile-CRUD + PIN-Reset + PIN-Karten-Druckbogen
- Inline-Edit-Endpunkt mit Whitelist + Audit-Log
- Seeds: AG lessing-3d-ag + 4 Drucker + Default-Einstellungen
- Smoke-Test bestanden (Login, Profil-Anlage, Lockout-Logging)

Nicht im Repo (.gitignore): .env, *.db, venv/, .obsidian/workspace.json
2026-05-24 18:56:59 +02:00

40 lines
1.6 KiB
Python

"""Tier-Set für Profil-Icons.
Anders als beim Arduino-Kurs (16 Tiere = 16 Gruppen) reichen hier 10-12 für
eine AG. Die Tiere sind nicht Gruppen-gebunden, sondern werden zusammen mit
dem Vornamen als visuelles Unterscheidungs-Merkmal verwendet.
Falls zwei SuS denselben Vornamen haben, müssen sie unterschiedliche Tiere
wählen — der UNIQUE-Constraint auf (kurs, vorname, tier) erzwingt das.
"""
TIERE = [
{"slug": "fuchs", "emoji": "\U0001F98A", "name": "Fuchs"},
{"slug": "otter", "emoji": "\U0001F9A6", "name": "Otter"},
{"slug": "igel", "emoji": "\U0001F994", "name": "Igel"},
{"slug": "eule", "emoji": "\U0001F989", "name": "Eule"},
{"slug": "pinguin", "emoji": "\U0001F427", "name": "Pinguin"},
{"slug": "krake", "emoji": "\U0001F419", "name": "Krake"},
{"slug": "biene", "emoji": "\U0001F41D", "name": "Biene"},
{"slug": "marienkaefer","emoji": "\U0001F41E", "name": "Marienkäfer"},
{"slug": "waschbaer", "emoji": "\U0001F99D", "name": "Waschbär"},
{"slug": "lama", "emoji": "\U0001F999", "name": "Lama"},
{"slug": "flamingo", "emoji": "\U0001F9A9", "name": "Flamingo"},
{"slug": "pfau", "emoji": "\U0001F9DA", "name": "Pfau"},
]
def tier_emoji(slug: str) -> str:
"""Findet das Emoji zum Tier-Slug, oder Fragezeichen falls unbekannt."""
for t in TIERE:
if t["slug"] == slug:
return t["emoji"]
return "?"
def tier_name(slug: str) -> str:
for t in TIERE:
if t["slug"] == slug:
return t["name"]
return slug