165 lines
6.4 KiB
Python
165 lines
6.4 KiB
Python
|
|
"""Migration 2026-05-25: Software-Karten initial befuellen.
|
||
|
|
|
||
|
|
Etappe 3 — schlankes Karten-Konzept (siehe docs/decisions.md, neue Entscheidung
|
||
|
|
zur Software-Sektion). Wir halten uns raus: SuS haben die Software auf den
|
||
|
|
Schul-PCs / im Browser und machen eigene Erfahrungen. Wir liefern nur die
|
||
|
|
Auswahl und ein paar Tutorials.
|
||
|
|
|
||
|
|
Inhalte pro Karte: 1-2 Satz Beschreibung, Hauptlink, optional Tutorial-Link.
|
||
|
|
Apps zusaetzlich App-Store + Play-Store-URLs (QR-Codes folgen in Folge-Schritt).
|
||
|
|
|
||
|
|
Idempotent: INSERT OR REPLACE auf slug. Achtung: ueberschreibt Inline-Edits
|
||
|
|
des Lehrers. Nur fuer Initial-Seed gedacht.
|
||
|
|
"""
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||
|
|
from database import get_db, init_db
|
||
|
|
|
||
|
|
|
||
|
|
SOFTWARE = [
|
||
|
|
# ---------- Slicer (Pflicht) ----------
|
||
|
|
{
|
||
|
|
"slug": "bambu-studio",
|
||
|
|
"titel": "Bambu Studio",
|
||
|
|
"kurzbeschreibung": "Slicer fuer unsere Drucker. Modell oeffnen, Drucker waehlen, drucken.",
|
||
|
|
"url": "https://bambulab.com/de/download/studio",
|
||
|
|
"tutorial_url": "https://wiki.bambulab.com/en/software/bambu-studio/studio-quick-start",
|
||
|
|
"plattform": "Windows / macOS / Linux",
|
||
|
|
"kategorie": "software",
|
||
|
|
"sortierung": 10,
|
||
|
|
},
|
||
|
|
# ---------- App ----------
|
||
|
|
{
|
||
|
|
"slug": "bambu-handy",
|
||
|
|
"titel": "Bambu Handy",
|
||
|
|
"kurzbeschreibung": "Drucker live am Handy beobachten, pausieren, Kamera ansehen.",
|
||
|
|
"url": "https://bambulab.com/de/download",
|
||
|
|
"tutorial_url": None,
|
||
|
|
"plattform": "iOS + Android",
|
||
|
|
"app_store_url": "https://apps.apple.com/de/app/bambu-handy/id1620054970",
|
||
|
|
"play_store_url": "https://play.google.com/store/apps/details?id=com.bambulab.bambu_link",
|
||
|
|
"kategorie": "app",
|
||
|
|
"sortierung": 20,
|
||
|
|
},
|
||
|
|
# ---------- Modell-Plattformen ----------
|
||
|
|
{
|
||
|
|
"slug": "printables",
|
||
|
|
"titel": "Printables",
|
||
|
|
"kurzbeschreibung": "Modell-Plattform von Prusa. Werbefrei, deutsche UI — erste Adresse fuer fertige Modelle.",
|
||
|
|
"url": "https://www.printables.com",
|
||
|
|
"tutorial_url": "https://www.printables.com/education",
|
||
|
|
"plattform": "Browser",
|
||
|
|
"kategorie": "software",
|
||
|
|
"sortierung": 30,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"slug": "makerworld",
|
||
|
|
"titel": "MakerWorld",
|
||
|
|
"kurzbeschreibung": "Bambu-eigene Modell-Plattform mit Customizer — Modelle mit eigenem Namen oder Wunschmassen.",
|
||
|
|
"url": "https://makerworld.com",
|
||
|
|
"tutorial_url": "https://makerworld.com/en/models/1320280", # Parametric Name Keychain als Erst-Customizer
|
||
|
|
"plattform": "Browser (Konto noetig)",
|
||
|
|
"kategorie": "software",
|
||
|
|
"sortierung": 40,
|
||
|
|
},
|
||
|
|
# ---------- CAD ----------
|
||
|
|
{
|
||
|
|
"slug": "tinkercad",
|
||
|
|
"titel": "TinkerCAD",
|
||
|
|
"kurzbeschreibung": "Visuelles 3D-CAD im Browser. Grundkoerper ziehen, kombinieren, exportieren. Einstieg ins eigene Modellieren.",
|
||
|
|
"url": "https://www.tinkercad.com",
|
||
|
|
"tutorial_url": "https://www.tinkercad.com/learn",
|
||
|
|
"plattform": "Browser",
|
||
|
|
"kategorie": "software",
|
||
|
|
"sortierung": 50,
|
||
|
|
},
|
||
|
|
# OpenSCAD bewusst nicht aufgenommen — solange wir keine Lektion dafuer
|
||
|
|
# haben, wuerden wir's nur als Karte "in den Raum stellen". Wenn spaeter
|
||
|
|
# eine OpenSCAD-Lektion entsteht (Bruecke zur Informatik), kann die Karte
|
||
|
|
# via Admin-GUI oder Folge-Migration nachgezogen werden.
|
||
|
|
{
|
||
|
|
"slug": "onshape",
|
||
|
|
"titel": "Onshape",
|
||
|
|
"kurzbeschreibung": "Professionelles CAD im Browser. Was Profis nutzen — fuer Schulen kostenlos, ab 13 Jahren.",
|
||
|
|
"url": "https://www.onshape.com/de/education/",
|
||
|
|
"tutorial_url": "https://www.youtube.com/watch?v=VyVqG8ZPvaM", # stolz3D Anfaenger Grundkurs
|
||
|
|
"plattform": "Browser + iOS + Android",
|
||
|
|
"kategorie": "software",
|
||
|
|
"sortierung": 70,
|
||
|
|
},
|
||
|
|
# ---------- Online-Generatoren ----------
|
||
|
|
{
|
||
|
|
"slug": "gridfinity",
|
||
|
|
"titel": "Gridfinity Builder",
|
||
|
|
"kurzbeschreibung": "Online-Generator fuer Gridfinity-Boxen — modulare Werkstatt-Ordnungssysteme nach Mass.",
|
||
|
|
"url": "https://gridfinity.perplexinglabs.com/pr/gridfinity-rebuilt/0/1",
|
||
|
|
"tutorial_url": None,
|
||
|
|
"plattform": "Browser",
|
||
|
|
"kategorie": "generator",
|
||
|
|
"sortierung": 80,
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
# Felder, die als Spalten gepflegt werden (alle anderen Keys werden ignoriert)
|
||
|
|
SPALTEN = (
|
||
|
|
"slug", "titel", "kurzbeschreibung", "url", "tutorial_url",
|
||
|
|
"plattform", "app_store_url", "play_store_url", "bild_pfad",
|
||
|
|
"kategorie", "sortierung",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
init_db()
|
||
|
|
conn = get_db()
|
||
|
|
angelegt = 0
|
||
|
|
aktualisiert = 0
|
||
|
|
for s in SOFTWARE:
|
||
|
|
# Default-Werte fuer optionale Felder, damit das UPDATE/INSERT einheitlich ist
|
||
|
|
werte = {sp: s.get(sp) for sp in SPALTEN}
|
||
|
|
|
||
|
|
existiert = conn.execute(
|
||
|
|
"SELECT 1 FROM software_seite WHERE slug = ?", (werte["slug"],)
|
||
|
|
).fetchone()
|
||
|
|
if existiert:
|
||
|
|
conn.execute(
|
||
|
|
"""UPDATE software_seite SET
|
||
|
|
titel = :titel,
|
||
|
|
kurzbeschreibung = :kurzbeschreibung,
|
||
|
|
url = :url,
|
||
|
|
tutorial_url = :tutorial_url,
|
||
|
|
plattform = :plattform,
|
||
|
|
app_store_url = :app_store_url,
|
||
|
|
play_store_url = :play_store_url,
|
||
|
|
bild_pfad = :bild_pfad,
|
||
|
|
kategorie = :kategorie,
|
||
|
|
sortierung = :sortierung,
|
||
|
|
aktiv = 1
|
||
|
|
WHERE slug = :slug""",
|
||
|
|
werte
|
||
|
|
)
|
||
|
|
aktualisiert += 1
|
||
|
|
else:
|
||
|
|
conn.execute(
|
||
|
|
"""INSERT INTO software_seite
|
||
|
|
(slug, titel, kurzbeschreibung, url, tutorial_url,
|
||
|
|
plattform, app_store_url, play_store_url, bild_pfad,
|
||
|
|
kategorie, sortierung, aktiv)
|
||
|
|
VALUES
|
||
|
|
(:slug, :titel, :kurzbeschreibung, :url, :tutorial_url,
|
||
|
|
:plattform, :app_store_url, :play_store_url, :bild_pfad,
|
||
|
|
:kategorie, :sortierung, 1)""",
|
||
|
|
werte
|
||
|
|
)
|
||
|
|
angelegt += 1
|
||
|
|
conn.commit()
|
||
|
|
conn.close()
|
||
|
|
print(f"[migration] software_seite: {angelegt} angelegt, {aktualisiert} aktualisiert "
|
||
|
|
f"({len(SOFTWARE)} Karten total).")
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|