add slide content improvements and dev server setup

223015b:
- add WTF hex code explanation slide (89=137 decimal, PNG signature)
- add ASCII lead slide with historical context
- remove Hilbert-Studie reference from title

223015c termin 2:
- add OSI layer 5 (session) and layer 6 (presentation) slides
- add URL/domain anatomy slide
- mark HTTP/S section as klausur
- improve status codes formatting with client/server examples
- add CRUD column to HTTP methods table

infrastructure:
- add dev-server.sh for multi-course development
- update generate-index.sh with course-specific colors
- add QR codes for slide URLs
This commit is contained in:
2025-12-30 16:24:44 +01:00
parent 0ff5e94e20
commit 1b9b2f315a
36 changed files with 837 additions and 230 deletions

View File

@@ -7,14 +7,18 @@
COURSES = 223015b 223015c
COURSE_DIR = courses
# Port configuration (index starts at BASE_PORT, courses increment from there)
BASE_PORT = 1310
INDEX_PORT = $(BASE_PORT)
# Course-specific settings
223015b_NAME = Dateiformate, Schnittstellen, Speichermedien
223015b_PORT = 1312
223015b_PORT = 1311
223015b_TERMINS = 2025-12-19-termin-0-intro 2025-12-19-termin-1-grundlagen-text-audio 2026-01-09-termin-2-bild-audio-video 2026-01-23-termin-3-speichermedien-schnittstellen 2026-01-30-termin-4-distribution-apis-zukunft 2026-xx-xx-termin-5-vertiefung-offene-fragen
223015b_DEPLOY_PATH = /home/tengo/html/hdm/223015b
223015c_NAME = Internettechnologien
223015c_PORT = 1313
223015c_PORT = 1312
223015c_TERMINS = 2025-12-20-termin-1-geschichte-grundlagen-html 2026-01-10-termin-2-netzwerke-protokolle-css 2026-01-24-termin-3-interaktivitaet-javascript
223015c_DEPLOY_PATH = /home/tengo/html/hdm/223015c
@@ -59,33 +63,23 @@ build/.exists:
@touch $@
# Development servers
dev: dev-index
@echo "Starting all dev servers..."
@echo ""
@echo " Index: http://localhost:1311"
@echo " 223015b: http://localhost:1312"
@echo " 223015c: http://localhost:1313"
@echo ""
@echo "Press Ctrl+C to stop all servers"
@trap 'kill 0' INT; \
PORT=1312 npx @marp-team/marp-cli --server $(COURSE_DIR)/223015b/slides/ & \
PORT=1313 npx @marp-team/marp-cli --server $(COURSE_DIR)/223015c/slides/ & \
python3 -m http.server 1311 --directory .dev-index & \
wait
dev:
@./scripts/dev-server.sh
dev-index:
@mkdir -p .dev-index
@echo '<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8"><title>HdM Slides</title><style>*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;max-width:600px;margin:0 auto;padding:2rem;background:#1a1a2e;color:#eee}h1{color:#fff}a{display:block;background:#16213e;border-radius:8px;padding:1.5rem;margin:1rem 0;text-decoration:none;color:#fff;transition:all .2s}a:hover{background:#1f4068;transform:translateX(5px)}a small{color:#4ecca3;display:block;margin-top:.5rem}</style></head><body><h1>HdM Slides</h1><p style="color:#888">Development Server</p><a href="http://localhost:1312">223015b - Dateiformate<small>Port 1312</small></a><a href="http://localhost:1313">223015c - Internettechnik<small>Port 1313</small></a></body></html>' > .dev-index/index.html
dev-kill:
@-pkill -f "python3 -m http.server" 2>/dev/null || true
@-pkill -f "marp-cli.*--server" 2>/dev/null || true
@sleep 0.5
dev-b:
@echo "Starting 223015b dev server on port 1312..."
@echo "Open: http://localhost:1312"
PORT=1312 npx @marp-team/marp-cli --server $(COURSE_DIR)/223015b/slides/
@echo "Starting 223015b dev server on port $(223015b_PORT)..."
@echo "Open: http://localhost:$(223015b_PORT)"
PORT=$(223015b_PORT) npx @marp-team/marp-cli --server $(COURSE_DIR)/223015b/slides/
dev-c:
@echo "Starting 223015c dev server on port 1313..."
@echo "Open: http://localhost:1313"
PORT=1313 npx @marp-team/marp-cli --server $(COURSE_DIR)/223015c/slides/
@echo "Starting 223015c dev server on port $(223015c_PORT)..."
@echo "Open: http://localhost:$(223015c_PORT)"
PORT=$(223015c_PORT) npx @marp-team/marp-cli --server $(COURSE_DIR)/223015c/slides/
# Build functions
define build_course
@@ -188,10 +182,18 @@ else
@echo "Done! Originals in assets-original/"
endif
# Root index for /hdm/
HDM_DEPLOY_PATH = /home/tengo/html/hdm
build-index: build/.exists
@echo "Building root index..."
@echo '<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>HdM Vorlesungen</title><style>*{box-sizing:border-box;margin:0;padding:0}body{font-family:-apple-system,BlinkMacSystemFont,"SF Pro Display","Segoe UI",Roboto,sans-serif;max-width:720px;margin:0 auto;padding:3rem 1.5rem;background:#fafafa;color:#1d1d1f;line-height:1.5}h1{font-size:2rem;font-weight:600;letter-spacing:-0.02em;margin-bottom:.5rem}.subtitle{color:#86868b;font-size:1rem}.courses{margin-top:2rem;display:flex;flex-direction:column;gap:.75rem}a.course{display:block;background:#fff;border-radius:12px;padding:1.5rem;text-decoration:none;color:inherit;box-shadow:0 1px 3px rgba(0,0,0,0.08);transition:all .2s ease;cursor:pointer}a.course:hover{transform:translateY(-2px);box-shadow:0 4px 12px rgba(0,0,0,0.12)}.course-label{font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em}.course-b .course-label{color:#5da9e9}.course-c .course-label{color:#d63384}.course-title{font-size:1.15rem;font-weight:500;color:#1d1d1f;margin:.25rem 0}.course-info{font-size:.85rem;color:#86868b}footer{margin-top:2.5rem;padding-top:1.5rem;border-top:1px solid #e5e5e7;color:#86868b;font-size:.85rem}footer a{color:#1d1d1f;text-decoration:none}footer a:hover{text-decoration:underline}</style></head><body><h1>HdM Vorlesungen</h1><p class="subtitle">Wintersemester 2025/26 · Michael Czechowski</p><div class="courses"><a class="course course-b" href="223015b/"><span class="course-label">223015b</span><div class="course-title">Dateiformate, Schnittstellen, Speichermedien & Distributionswege</div><span class="course-info">6 Termine · Modul "Technik 1"</span></a><a class="course course-c" href="223015c/"><span class="course-label">223015c</span><div class="course-title">Grundlagen IT- und Internettechnik</div><span class="course-info">3 Termine · Modul "Technik 1"</span></a></div><footer><a href="mailto:mail@librete.ch">Kontakt</a></footer></body></html>' > build/index.html
# Deploy
define deploy_course
@echo "Deploying $(1)..."
scp build/$(1)/*.html $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/
scp build/$(1)/*.pdf $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/ 2>/dev/null || true
scp -r build/$(1)/assets/ $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/
scp -r build/$(1)/materials/ $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/ 2>/dev/null || true
@echo "$(1) deployed!"
@@ -203,7 +205,12 @@ deploy-b: build-b
deploy-c: build-c
$(call deploy_course,223015c)
deploy: deploy-b deploy-c
deploy-index: build-index
@echo "Deploying root index..."
scp build/index.html $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/
@echo "Root index deployed!"
deploy: build-index deploy-b deploy-c deploy-index
@echo "All courses deployed!"
# Clean

View File

@@ -58,7 +58,7 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://git.librete.ch/hdm/223015b](https://git.librete.ch/hdm/223015b)
[https://librete.ch/hdm/223015b/](https://librete.ch/hdm/223015b/)
---

View File

@@ -64,7 +64,7 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://git.librete.ch/hdm/223015b](https://git.librete.ch/hdm/223015b)
[https://librete.ch/hdm/223015b/](https://librete.ch/hdm/223015b/)
---
@@ -99,6 +99,32 @@ Hochschule der Medien Stuttgart
---
![bg right:40%](./assets/matrix-code.png)
# WTF!? Auflösung
```
89 50 4E 47 ...
```
| Hex | Dezimal | ASCII |
|-----|---------|-------|
| `89` | 137 | ✗ (> 127, nicht druckbar) |
| `50` | 80 | **P** |
| `4E` | 78 | **N** |
| `47` | 71 | **G** |
**PNG**-Signatur! (Das `89` markiert: "Ich bin binär, kein Text!")
<!--
Hex = 2 Ziffern = 1 Byte = 8 Bit
89 hex = 8×16 + 9 = 137 dezimal
ASCII geht nur bis 127, also nicht druckbar
50, 4E, 47 = P, N, G in ASCII
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
@@ -278,25 +304,30 @@ Digital explodierte: IoT, Social Media, Cloud, Video
<!-- _class: klausur -->
<!-- _footer: '' -->
# Der digitale Wendepunkt (Hilbert-Studie)
# Der digitale Wendepunkt
| Jahr | Analog | Digital | Digital-Anteil |
|------|--------|---------|----------------|
| **1986** | 2,57 EB | 0,02 EB | **1%** |
| **2000** | ~37 EB | ~13 EB | 25% |
| **1986** | 2,6 EB | 0,02 EB | **1%** |
| **2002** | — | — | **50%** (Wendepunkt) |
| **2007** | ~18 EB | ~277 EB | **94%** |
| **2007** | 18 EB | 277 EB | **94%** |
**Beobachtung:** Analog blieb nahezu konstant (~2,6 → ~18 EB)
Digital explodierte: ×14.000 in 21 Jahren
**Perspektive:**
- 1986: "Petabyte" war ein theoretisches Konzept
- 2025: ~181 Zettabyte jährlich produziert
**Magnetband lebt:** LTO-Tapes bleiben günstigstes Archivmedium
(AWS Glacier, Film-Archive, Rechenzentren)
<!--
Hilbert & López (2011): "The World's Technological Capacity to Store, Communicate, and Compute Information", Science
Erste systematische Studie zur weltweiten Speicherkapazität
60 analoge und digitale Technologien untersucht (1986-2007)
2002 = Beginn des "digitalen Zeitalters"
Analog: Bücher, Zeitungen, Vinyl, VHS, Fotos
Digital: Festplatten, CDs, DVDs, Flash-Speicher
QUELLE: Hilbert & López (2011): "The World's Technological Capacity to Store, Communicate, and Compute Information", Science
METHODIK: 60 analoge + digitale Technologien untersucht (1986-2007)
WENDEPUNKT 2002: Erstmals mehr digital als analog gespeichert
ANALOG damals: Bücher, Zeitungen, Vinyl, VHS, Filmrollen, Fotos
DIGITAL damals: Festplatten, CDs, DVDs, frühe Flash-Speicher
HEUTE: LTO-9 (2021) speichert 18 TB pro Band, ~$5/TB für Cold Storage
VERGLEICH: SSD ~$50/TB, HDD ~$15/TB, LTO ~$5/TB
PRÜFUNGSRELEVANT: Wendepunkt 2002, Speichereinheiten (KB→MB→GB→TB→PB→EB→ZB), Magnetband als Archivmedium
-->
---
@@ -345,6 +376,38 @@ Model Collapse: AI trainiert auf AI-Output → Qualitätsverlust
---
<!-- _class: lead -->
# ASCII
## Ein Zeichensatz to rule them all
<!--
WARUM 7 BIT STATT 8?
- 1963: Fernschreiber (Teletype) arbeiteten mit 7-Bit-Codes
- Das 8. Bit diente der Paritätsprüfung (Fehlererkennung bei Übertragung)
- Speicher war kostspielig: jedes eingesparte Bit zählte
- 128 Zeichen galten als ausreichend für den englischsprachigen Raum
KULTURHISTORISCHER KONTEXT:
- "American Standard Code for Information Interchange" (1963)
- Entwickelt für US-amerikanische Bedürfnisse
- Keine Unterstützung für: Umlaute (ä, ö, ü), ß, diakritische Zeichen (é, ñ, ç)
- Nicht-lateinische Schriftsysteme (Kyrillisch, Arabisch, CJK) wurden nicht berücksichtigt
- Führte zu zahlreichen inkompatiblen Erweiterungen (ISO-8859-1, Windows-1252, etc.)
WARUM NOCH HEUTE RELEVANT?
- Abwärtskompatibilität: UTF-8 ist vollständig ASCII-kompatibel (Zeichen 0-127 identisch)
- Internetprotokolle basieren auf ASCII: HTTP-Header, SMTP, URLs
- Programmiersprachen: Schlüsselwörter und Syntax sind ASCII
- Ein 60 Jahre alter Standard, der durch Kompatibilitätszwänge fortbesteht
HISTORISCHE RANDNOTIZ:
- Das @-Zeichen wurde nachträglich aufgenommen
- Heute unverzichtbar für E-Mail-Adressen weltweit
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
@@ -837,22 +900,36 @@ Visualisierung der beiden Philosophien
---
# Zwei Philosophien
<!-- _class: klausur -->
<!-- _footer: '' -->
**Lossless (Verlustfrei):**
- Original exakt wiederherstellbar
- ZIP, PNG, FLAC
- 30-50% Ersparnis
# Kompression: Zwei Philosophien
**Lossy (Verlustbehaftet):**
- Daten irreversibel verändert
- JPEG, MP3, H.264
- 90%+ Ersparnis
| | Lossless | Lossy |
|---|---|---|
| **Prinzip** | Redundanz entfernen | Irrelevanz entfernen |
| **Reversibel** | Ja (bitgenau) | Nein |
| **Kompression** | 30-50% | 80-99% |
| **Algorithmen** | RLE, Huffman, LZW, DEFLATE | DCT, Psychoakustik |
**Lossless:** ZIP, PNG, FLAC, GIF
**Lossy:** JPEG, MP3, AAC, H.264, H.265, AV1
**Entscheidung:** Archiv/Code → Lossless, Medien → Lossy
<!--
Lossless: Findet Muster, beschreibt effizienter
Lossy: Wirft "Unwichtiges" weg (Psychoakustik/Psychovisuell)
Trade-off: Größe vs. Qualität
REDUNDANZ: Wiederholende Muster (z.B. "AAAA" → "4A")
IRRELEVANZ: Für Menschen nicht wahrnehmbar (Psychoakustik, Psychovisuell)
LOSSLESS-ALGORITHMEN:
- RLE (Run-Length Encoding): Wiederholungen zählen
- Huffman: Häufige Zeichen = kurze Codes
- LZW: Wörterbuch aufbauen (GIF, TIFF)
- DEFLATE: Huffman + LZ77 (ZIP, PNG, gzip)
LOSSY-ALGORITHMEN:
- DCT (Discrete Cosine Transform): Frequenzanalyse (JPEG, MP3)
- Psychoakustik: Maskierungseffekte nutzen (MP3, AAC)
- Bewegungskompensation: Nur Differenzen speichern (H.264, H.265)
PRÜFUNGSRELEVANT: Unterschied Redundanz vs. Irrelevanz, Beispiele für beide Kategorien
-->
---

View File

@@ -42,6 +42,12 @@ code {
a {
color: var(--color-highlight);
}
section.klausur {
background: #e3f2fd !important;
}
section.klausur footer {
display: none;
}
</style>
<!-- _class: invert -->
@@ -59,7 +65,14 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://git.librete.ch/hdm/223015b](https://git.librete.ch/hdm/223015b)
[https://librete.ch/hdm/223015b/](https://librete.ch/hdm/223015b/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-223015b.png)
---
@@ -104,70 +117,123 @@ Smartphone-Speicher wäre schnell voll ohne Kompression
---
<!-- _class: klausur -->
<!-- _footer: '' -->
# Rastergrafiken (Bitmaps)
**Pixelraster:** Jeder Bildpunkt hat Koordinate + Farbwert
**Aufbau:** 2D-Array von Pixeln mit Farbwerten
**Eigenschaften:**
- Je größer das Bild → größere Datei
- **Verkleinern:** Meist ohne Qualitätsverlust
- **Vergrößern:** Wird unscharf/pixelig!
**Speicherbedarf (unkomprimiert):**
Breite × Höhe × Farbtiefe (in Bytes)
→ 1920×1080 × 3 Byte (RGB) = **6,2 MB**
**Formate:** JPEG, PNG, GIF, BMP, TIFF, WebP
**Farbtiefe:**
- 1 Bit = 2 Farben (S/W)
- 8 Bit = 256 Farben (Graustufen/Palette)
- 24 Bit = 16,7 Mio. Farben (True Color)
- 32 Bit = True Color + Alpha (Transparenz)
**Verwendung:** Fotos, Screenshots, komplexe Bilder
**Skalierung:** Interpolation (Nearest Neighbor, Bilinear, Bicubic)
<!--
Bitmap = Bit-mapped graphics
Digitalkameras erzeugen immer Rastergrafiken
Kompression nötig wegen Dateigrößen (PNG, JPEG, GIF)
Skalierungsproblem: Interpolation erzeugt Unschärfe
DEFINITION: Bitmap = Bit-mapped graphics, 2D-Matrix aus Pixeln
BERECHNUNG SPEICHERBEDARF: Breite × Höhe × (Farbtiefe / 8)
BEISPIEL: 1920×1080 × 24 Bit = 1920×1080×3 = 6.220.800 Bytes ≈ 6,2 MB
FARBTIEFE erklärt:
- 1 Bit: 2^1 = 2 Farben (Schwarz/Weiß, Fax)
- 8 Bit: 2^8 = 256 Farben (GIF, Graustufen)
- 24 Bit: 2^24 = 16.777.216 Farben (True Color, RGB je 8 Bit)
- 32 Bit: 24 Bit + 8 Bit Alpha-Kanal (Transparenz)
INTERPOLATION bei Skalierung:
- Nearest Neighbor: Schnell, pixelig (Pixel-Art)
- Bilinear: Mittelwert aus 4 Nachbarn (Standard)
- Bicubic: 16 Nachbarn, glatter (Photoshop-Standard)
- Lanczos: Beste Qualität, rechenintensiv
PRÜFUNGSRELEVANT: Speicherberechnung, Farbtiefe-Tabelle, warum Vergrößern problematisch
-->
---
<!-- _class: klausur -->
<!-- _footer: '' -->
# Vektorgrafiken
**Mathematische Beschreibung statt Pixel**
**Speicherung als geometrische Primitive:**
- Pfade (Bézierkurven mit Kontrollpunkten)
- Grundformen (Rechteck, Ellipse, Polygon)
- Text (Glyphen als Outlines)
**Kreis speichern:**
- Rastergrafik: Tausende Pixel
- Vektorgrafik: Mittelpunkt + Radius (2 Werte!)
**SVG-Beispiel:**
`<circle cx="50" cy="50" r="40" fill="#ff0000"/>`
→ 3 Parameter statt 5.027 Pixel (r=40)
**Gespeichert werden:**
- Form (Kreis, Linie, Pfad...)
- Position, Farbe, Strichstärke, Füllung
**Rendering-Pipeline:**
Vektordaten → Rasterisierung → Framebuffer → Display
**Vorteil:** Beliebig skalierbar ohne Qualitätsverlust!
**Formate:** SVG, PDF, AI, EPS
**Auflösungsunabhängig:** Gleiche Datei für Icon (32px) und Plakat (3m)
<!--
Vektorgrafik = geometrische Primitive + Attribute
SVG = Scalable Vector Graphics (Web-Standard)
AI = Adobe Illustrator
Ideal für Logos, Icons, Infografiken
PRIMITIVE: Grundbausteine der Vektorgrafik
- Pfade: Sequenz von Punkten, verbunden durch Linien/Kurven
- Bézierkurven: Quadratisch (3 Kontrollpunkte), Kubisch (4 Kontrollpunkte)
- Formen: Rechteck, Ellipse, Polygon (intern als Pfade)
SVG-SYNTAX Beispiele:
- <rect x="0" y="0" width="100" height="50"/>
- <circle cx="50" cy="50" r="25"/>
- <path d="M 0 0 L 100 100"/> (MoveTo, LineTo)
BERECHNUNG: Kreis mit r=40 → Fläche = π×40² ≈ 5.027 Pixel vs. 3 Parameter
RENDERING-PIPELINE: Vector → Tessellation → Rasterization → Framebuffer
FORMATE:
- SVG: XML-basiert, Web-Standard, editierbar
- PDF: Seiten-Beschreibungssprache, Vektoren + Raster gemischt
- AI/EPS: Adobe-proprietär, Druckvorstufe
PRÜFUNGSRELEVANT: Warum Vektoren skalierbar, SVG-Grundsyntax, Rendering-Pipeline
-->
---
# Raster vs. Vektor
<!-- _class: klausur -->
<!-- _footer: '' -->
| | Rastergrafik | Vektorgrafik |
# Raster vs. Vektor: Entscheidungskriterien
| Kriterium | Raster | Vektor |
|---|---|---|
| **Basis** | Pixelraster | Mathematische Objekte |
| **Speicherung** | Pixelmatrix | Geometrie + Attribute |
| **Skalierung** | Qualitätsverlust | Verlustfrei |
| **Dateigröße** | Abhängig von Auflösung | Abhängig von Komplexität |
| **Gut für** | Fotos | Logos, Icons, Text |
| **Formate** | JPEG, PNG, GIF | SVG, PDF, AI |
| **Komplexität** | O(Breite × Höhe) | O(Anzahl Objekte) |
| **Bearbeitung** | Pixelbasiert | Objektbasiert |
**Rasterung:** Vektorgrafik → Rastergrafik (für Bildschirm/Druck)
**Wann Raster?** Fotos, Texturen, komplexe Farbverläufe
**Wann Vektor?** Logos, Icons, Typografie, technische Zeichnungen
**Konvertierung:**
- Raster → Vektor: Tracing (verlustbehaftet, approximiert)
- Vektor → Raster: Rasterisierung (exakt, aber auflösungsgebunden)
<!--
Bildschirme sind Rastergeräte (Framebuffer)
Jede Vektorgrafik muss gerastert werden zur Anzeige
Browser rastert SVG in Echtzeit
Firmenlogos: Immer als Vektor anlegen!
KOMPLEXITÄT erklärt:
- Raster O(w×h): Speicher wächst mit Pixelanzahl
- Vektor O(n): Speicher wächst mit Objektanzahl
BEISPIEL: Foto einer Wiese
- Raster: 1920×1080 = 2 Mio. Pixel, komprimiert ~500 KB
- Vektor: Jeder Grashalm ein Pfad → Millionen Objekte, unkomprimierbar
KONVERTIERUNG:
- Raster→Vektor (Tracing): Kantenerkennung, verlustbehaftet
- Tools: Potrace (Open Source), Adobe Live Trace, Inkscape
- Funktioniert gut: Logos, Zeichnungen, Text
- Funktioniert schlecht: Fotos, Farbverläufe
- Vektor→Raster (Rasterisierung): Exakt, aber Auflösung fixiert
- Jeder Bildschirm macht das (GPU)
- Export: "Auflösung" wählen = Ziel-Pixelgröße
ENTSCHEIDUNGSBAUM:
- Foto/Screenshot? → Raster
- Logo/Icon/Diagramm? → Vektor
- Druckvorlage? → Vektor (Auflösungsunabhängig)
- Web-Animation? → SVG (Vektor) oder Video (Raster)
PRÜFUNGSRELEVANT: Wann welches Format, Konvertierungsrichtungen und deren Eigenschaften
-->
---
@@ -365,8 +431,6 @@ GIF überlebte kulturell (Meme-Format)
- HDR-Unterstützung
- Patent-frei
**Problem:** Browser-Support dauert Jahre
<!--
WebP: Von Google entwickelt, deshalb Skepsis
AVIF: Alliance for Open Media (Google, Netflix, Amazon, Mozilla...)
@@ -728,8 +792,7 @@ Hardware-Encoder kommen (ab 2020er-GPUs)
- 480p (1 Mbps)
- 240p (0,5 Mbps)
Segmente: 2-10 Sekunden
Player wählt dynamisch
Segmente: 2-10 Sekunden (Player wählt dynamisch)
<!--
DASH = Dynamic Adaptive Streaming over HTTP
@@ -756,19 +819,11 @@ Bandbreite schwankt → Player reagiert
# Container im Detail
**MP4:**
- Standard für Web, Mobile
- H.264, H.265, AV1
- DRM-fähig
**MP4:** Standard für Web/Mobile, DRM-fähig (H.264, H.265, AV1)
**MKV (Matroska):**
- Open Source, extrem flexibel
- Beliebig viele Audio-/Untertitel-Spuren
- Fast jeden Codec
**MKV:** Open Source, beliebig viele Spuren (fast jeder Codec)
**WebM:**
- Google, Web-optimiert
- Nur VP9/AV1 + Opus/Vorbis
**WebM:** Google/Web-optimiert (nur VP9/AV1 + Opus/Vorbis)
<!--
MP4 = MPEG-4 Part 14 (ISO-Standard)
@@ -783,15 +838,15 @@ MKV vs. MP4: Offenheit vs. Kompatibilität
**Aufgabe (40 Min):**
**Tool:** FFmpeg (CLI) oder HandBrake (GUI)
**Tools:**
- Desktop: FFmpeg, HandBrake, [MediaInfo](https://mediaarea.net/MediaInfoOnline)
- Browser: [Squoosh.app](https://squoosh.app) (Bilder), [MediaInfo Online](https://mediaarea.net/MediaInfoOnline)
- iOS/Android: MediaInfo App, VLC
1. Download: CC-Video (Big Buck Bunny, ~1 Min)
2. Analysiere: `ffmpeg -i video.mp4` oder MediaInfo
3. Notiere: Container, Codec, Bitrate, Auflösung
4. Konvertiere:
- H.264, 1080p, 5 Mbps
- H.265, 1080p, 2,5 Mbps
5. Vergleiche: Größen, Encoding-Zeit, Qualität
2. Analysiere: Container, Codec, Bitrate, Auflösung
3. Konvertiere: H.264 vs. H.265 (gleiche Qualität)
4. Vergleiche: Größen, Encoding-Zeit
<!--
Big Buck Bunny: Open-Source-Film (Blender Foundation)

View File

@@ -58,7 +58,14 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://git.librete.ch/hdm/223015b](https://git.librete.ch/hdm/223015b)
[https://librete.ch/hdm/223015b/](https://librete.ch/hdm/223015b/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-223015b.png)
---

View File

@@ -59,7 +59,14 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://git.librete.ch/hdm/223015b](https://git.librete.ch/hdm/223015b)
[https://librete.ch/hdm/223015b/](https://librete.ch/hdm/223015b/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-223015b.png)
---

View File

@@ -59,7 +59,14 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://git.librete.ch/hdm/223015b](https://git.librete.ch/hdm/223015b)
[https://librete.ch/hdm/223015b/](https://librete.ch/hdm/223015b/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-223015b.png)
---

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 956 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

View File

@@ -65,7 +65,14 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://git.librete.ch/hdm/223015c](https://git.librete.ch/hdm/223015c)
[https://librete.ch/hdm/223015c/](https://librete.ch/hdm/223015c/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-223015c.png)
---
@@ -608,9 +615,17 @@ Euer Laptop, euer Handy, der Server dieser Präsentation
**Wichtig:** Programme und Daten **gemeinsam** im Speicher!
<!--
ALU = Arithmetic Logic Unit
Bus = Datenautobahn zwischen Komponenten
Speicher enthält beides: Was zu tun ist (Programm) + Womit (Daten)
VON-NEUMANN-ARCHITEKTUR (1945): Grundlage aller modernen Computer
5 KOMPONENTEN:
- ALU (Arithmetic Logic Unit): Rechnet (+, -, ×, ÷) und vergleicht (>, <, =)
- Steuerwerk: Holt Befehle, dekodiert sie, steuert Ausführung (Fetch-Decode-Execute)
- Speicherwerk: RAM (flüchtig) + ROM (permanent), enthält Code UND Daten
- Ein-/Ausgabe (I/O): Tastatur, Maus, Bildschirm, Netzwerk, USB, Sensoren
- Bus-System: Adressbus (wo), Datenbus (was), Steuerbus (wie)
KERNPRINZIP: Stored Program Concept - Programme im selben Speicher wie Daten
VORHER (z.B. ENIAC): Programme durch Umstecken von Kabeln, tagelange Arbeit
NACHHER: Programme als austauschbare Daten → Flexibilität, Software-Industrie möglich
PRÜFUNGSRELEVANT: 5 Komponenten benennen und erklären können, Stored Program Concept
-->
---
@@ -632,9 +647,19 @@ Laptop, Smartphone, Server, Spielkonsole...
(separate Speicher für Code und Daten → schneller für Echtzeitanwendungen)
<!--
Harvard-Architektur: AVR, PIC, viele ARM-Prozessoren
Modified Harvard in modernen CPUs (separate Caches)
Für Medienwirtschaft: Von-Neumann-Konzept reicht
BEDEUTUNG VON-NEUMANN-ARCHITEKTUR:
- Betriebssystem möglich: Lädt verschiedene Programme aus gleichem Speicher
- Apps installierbar: Können gelöscht/installiert werden ohne Hardware-Änderung
- Multitasking: Mehrere Programme gleichzeitig im Speicher
- Updates: Software austauschbar, Hardware bleibt gleich
- Universalrechner: Gleiche Hardware für Text, Spiele, Video, Wissenschaft
HARVARD-ARCHITEKTUR (Alternative):
- Separate Speicher für Code und Daten
- Vorteil: Schneller (paralleler Zugriff), sicherer (Code nicht überschreibbar)
- Nachteil: Weniger flexibel, aufwändiger
- Anwendung: Mikrocontroller (Arduino, ESP32), DSPs, einige ARM-Chips
MODERNE CPUs: Modified Harvard (L1-Cache getrennt für Speed, RAM gemeinsam für Flexibilität)
PRÜFUNGSRELEVANT: Warum Von-Neumann revolutionär, Unterschied zu Harvard, Beispiele
-->
---
@@ -1033,20 +1058,35 @@ Formattierungssprache
<html>
<head>
<title>Im Browsertab als Überschrift sichtbar</title>
<meta name="description" content="" />
<meta name="og:image" content="https://...." />
</head>
...
</html>
```
* <small>*Webseiten werden nicht nur von Menschen besucht, sondern auch von Suchmaschinen, Programmen, Bots etc.*</small>
* <small>*Metadaten helfen bspw. auch Screen-Readern beim "Verstehen" der Inhalte*</small>
<!--
HEAD-BEREICH: Metadaten, nicht sichtbar im Browser-Fenster
WICHTIGE META-TAGS:
- <title>: Browser-Tab, Lesezeichen, Suchergebnis-Titel
- <meta name="description">: Suchergebnis-Snippet (max. 160 Zeichen)
- <meta name="viewport">: Mobile Darstellung (width=device-width)
- <meta charset="UTF-8">: Zeichenkodierung (Umlaute!)
OPEN GRAPH (og:*): Social Media Vorschau (Facebook, LinkedIn, WhatsApp)
- og:title, og:description, og:image, og:url
TWITTER CARDS: twitter:card, twitter:title, twitter:image
SEO-RELEVANZ: Google nutzt title + description für Ranking und Snippet
ACCESSIBILITY: <html lang="de"> für Screenreader-Aussprache
PRÜFUNGSRELEVANT: Was gehört in <head>, Unterschied zu <body>, wichtigste Meta-Tags
-->
---
# HTML-Tags und Attribute

View File

@@ -65,6 +65,15 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://librete.ch/hdm/223015c/](https://librete.ch/hdm/223015c/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-223015c.png)
---
<!-- _class: lead -->
@@ -165,10 +174,19 @@ Internet nutzt beides: TCP = verbindungsorientiert, UDP = verbindungslos
| 1 | Bitübertragung | Kabel, WLAN |
<!--
OSI = Open Systems Interconnection
ISO-Standard
Theoretisches Modell
TCP/IP ist die praktische Implementierung
OSI-MODELL: Open Systems Interconnection (1984, ISO 7498)
ZWECK: Standardisierte Beschreibung von Netzwerkkommunikation
7 SCHICHTEN (von unten nach oben):
1. Physical: Bits über Kabel/Funk (Ethernet-Kabel, WLAN-Frequenzen)
2. Data Link: Frames, MAC-Adressen (Ethernet, Switch)
3. Network: Pakete, IP-Adressen, Routing (Router)
4. Transport: Segmente, Ports, Zuverlässigkeit (TCP/UDP)
5. Session: Verbindungsmanagement (selten separat implementiert)
6. Presentation: Datenformat, Verschlüsselung (TLS gehört hierher)
7. Application: Nutzer-Protokolle (HTTP, SMTP, FTP)
MERKSATZ: "Please Do Not Throw Salami Pizza Away" (Physical→Application)
REALITÄT: OSI ist Theorie, TCP/IP ist Praxis (fasst Schichten zusammen)
PRÜFUNGSRELEVANT: 7 Schichten mit Beispielen, Unterschied OSI vs. TCP/IP
-->
---
@@ -189,8 +207,18 @@ TCP/IP ist die praktische Implementierung
**TCP/IP = Transmission Control Protocol / Internet Protocol**
<!--
TCP/IP einfacher als OSI
Praktisch gewachsen, nicht theoretisch geplant
TCP/IP-STACK: Praktische Implementierung des Internets
4 SCHICHTEN statt 7:
1. Network Access (OSI 1-2): Ethernet, WLAN, physische Übertragung
2. Internet (OSI 3): IP-Protokoll, Routing, Adressierung
3. Transport (OSI 4): TCP (zuverlässig) oder UDP (schnell)
4. Application (OSI 5-7): HTTP, DNS, SMTP, SSH
TCP vs. UDP:
- TCP: Verbindungsorientiert, garantierte Zustellung, Reihenfolge (Web, E-Mail)
- UDP: Verbindungslos, schneller, keine Garantie (Video-Streaming, Gaming, DNS)
IP-PROTOKOLL: Adressierung + Routing, "Best Effort" (keine Garantie)
ENTSTEHUNG: ARPANET 1969, TCP/IP 1983 (Flag Day)
PRÜFUNGSRELEVANT: 4 Schichten, TCP vs. UDP Unterschied, wann welches Protokoll
-->
---
@@ -463,6 +491,50 @@ ACK bestätigt Empfang
---
# Schicht 5: Sitzung (Session)
**Verwaltet Verbindungen zwischen Anwendungen:**
- **Sessions** → Login-Sitzungen, "eingeloggt bleiben"
- **Dialogsteuerung** → Wer darf wann senden?
- **Synchronisation** → Wiederaufnahme nach Abbruch
**Beispiele:**
- Web-Sessions (Cookies, Tokens)
- RPC (Remote Procedure Call)
- NetBIOS
<!--
Session-Layer oft in Anwendung integriert
Web: Session-ID in Cookie speichern
Beispiel: Online-Banking Session-Timeout
-->
---
# Schicht 6: Darstellung (Presentation)
**Übersetzt Datenformate:**
| Funktion | Beispiel |
|----------|----------|
| **Encoding** | UTF-8, ASCII, Unicode |
| **Verschlüsselung** | TLS/SSL (HTTPS) |
| **Kompression** | gzip, deflate |
| **Serialisierung** | JSON, XML, Protobuf |
**TLS/SSL:** Transport Layer Security
→ Verschlüsselt HTTP zu HTTPS
<!--
Presentation Layer = Dolmetscher
TLS: Handshake für Schlüsselaustausch
Zertifikate für Authentifizierung
Heute: Fast nur noch HTTPS
-->
---
<!-- _class: klausur -->
# Schicht 7: Anwendung
@@ -479,8 +551,21 @@ ACK bestätigt Empfang
| **SSH** | 22 | Sichere Fernsteuerung |
<!--
Anwendungsschicht = was NutzerInnen "sehen"
Ports = "Türnummern" auf Server
ANWENDUNGSSCHICHT: Protokolle, die NutzerInnen direkt betreffen
PORTS erklärt:
- Server lauscht auf Port (wie Türnummer in Hochhaus)
- Client verbindet sich zu IP:Port
- Well-Known Ports: 0-1023 (brauchen Admin-Rechte)
- Registered Ports: 1024-49151
- Dynamic/Private: 49152-65535 (für Clients)
WICHTIGE PROTOKOLLE:
- HTTP/HTTPS: Hypertext Transfer Protocol, Webseiten (80/443)
- DNS: Domain Name System, Namensauflösung (53, UDP+TCP)
- SMTP/IMAP/POP3: E-Mail senden/empfangen (25,587/993/995)
- SSH: Secure Shell, verschlüsselte Fernsteuerung (22)
- FTP/SFTP: Dateitransfer (21/22)
HTTPS = HTTP + TLS: Verschlüsselung, Authentifizierung, Integrität
PRÜFUNGSRELEVANT: Wichtige Ports auswendig, HTTP vs. HTTPS, was macht DNS
-->
---
@@ -572,12 +657,41 @@ MX = Mail Exchange
---
<!-- _class: lead -->
# URLs & Domains
# HTTP im Detail
**URL** = Uniform Resource Locator
```
https://www.example.com:443/pfad/seite.html?suche=test#kapitel2
└─┬──┘ └──────┬──────┘└┬┘ └──────┬──────┘ └───┬────┘ └──┬───┘
Protokoll Hostname Port Pfad Query Fragment
```
| Begriff | Erklärung |
|---------|-----------|
| **Domain** | `example.com` (registrierter Name) |
| **Subdomain** | `www`, `mail`, `api` (Prefix) |
| **Hostname** | `www.example.com` (vollständig) |
| **Port** | Standard: 80 (HTTP), 443 (HTTPS) |
<!--
URL = Adresse einer Ressource im Web
Hostname = Domain + optionale Subdomain
Port wird oft weggelassen (Standardports)
Fragment (#) geht nicht an Server, nur Browser
Query-String für Parameter
-->
---
<!-- _class: lead klausur -->
# HTTP/S im Detail
---
<!-- _class: klausur -->
# HTTP-Request
```http
@@ -603,6 +717,8 @@ Body kommt nach leerem Zeile (bei POST)
---
<!-- _class: klausur -->
# HTTP-Response
```http
@@ -614,7 +730,11 @@ Content-Length: 1234
**Status-Codes:**
- **2xx** Erfolg
<!--
- **3xx** Umleitung
- **4xx** Client-Fehler (Browser, App, WhatsApp)
- **5xx** Server-Fehler (Instagram, Google, HdM)
<!--
200 OK, 404 Not Found, 500 Internal Error
-->
@@ -622,18 +742,17 @@ Content-Length: 1234
<!-- _class: klausur -->
# HTTP-Methoden
| Methode | CRUD | Zweck | Beispiel |
|---------|------|-------|----------|
| **GET** | Daten abrufen | Seite laden |
| **POST** | Daten senden | Formular absenden |
| **PUT** | Daten ersetzen | Profil aktualisieren |
| **PATCH** | Daten teilweise ändern | Einzelnes Feld |
| **DELETE** | Daten löschen | Account löschen |
**CRUD:** Create, Read, Update, Delete
→ POST, GET, PUT/PATCH, DELETE
<!--
| **GET** | Read | Daten abrufen | Seite laden |
| **POST** | Create | Daten senden | Formular absenden |
| **PUT** | Update | Daten ersetzen | Profil aktualisieren |
| **PATCH** | Update | Daten teilweise ändern | Einzelnes Feld |
| **DELETE** | Delete | Daten löschen | Account löschen |
<!--
REST-APIs nutzen diese Methoden
GET = idempotent (mehrfach = gleiches Ergebnis)
POST = nicht idempotent
@@ -987,10 +1106,20 @@ vw/vh = Viewport (sichtbarer Bereich)
<!--
ACCESSIBILITY (a11y): a + 11 Buchstaben + y
STATISTIK: ~15% der Weltbevölkerung haben eine Behinderung (WHO)
Temporäre Einschränkungen: gebrochener Arm, helle Sonne
Situative Einschränkungen: laute Umgebung, Baby auf dem Arm
-->
ARTEN VON EINSCHRÄNKUNGEN:
- Permanent: Blindheit, Taubheit, motorische Einschränkungen
- Temporär: Gebrochener Arm, Augen-OP, Ohrenentzündung
- Situativ: Helle Sonne (Kontrast), laute Umgebung (kein Audio), Baby auf Arm (eine Hand)
ASSISTIVE TECHNOLOGIEN:
- Screenreader: NVDA (Windows, kostenlos), VoiceOver (Apple), JAWS (kommerziell)
- Braillezeilen: Taktile Ausgabe für Blinde
- Switch-Geräte: Für motorische Einschränkungen
- Spracheingabe: Dragon NaturallySpeaking, Siri, Google Assistant
WCAG: Web Content Accessibility Guidelines (A, AA, AAA)
EUROPEAN ACCESSIBILITY ACT: Seit Juni 2025 verpflichtend!
PRÜFUNGSRELEVANT: Arten von Einschränkungen, Screenreader-Beispiele, WCAG
-->
---
<!-- _class: klausur -->
@@ -1012,9 +1141,21 @@ Situative Einschränkungen: laute Umgebung, Baby auf dem Arm
<!--
RECHTLICHER RAHMEN:
- European Accessibility Act (EAA): EU-Richtlinie, seit 28. Juni 2025 in Kraft
Curb-Cut-Effekt: Rampen helfen auch Kinderwagen, Koffern...
-->
- Betrifft: E-Commerce, Banking, Telekommunikation, Transport, E-Books
- BITV 2.0: Barrierefreie Informationstechnik-Verordnung (DE, öffentliche Stellen)
- BFSG: Barrierefreiheitsstärkungsgesetz (DE-Umsetzung des EAA)
- Strafen: Bis zu 100.000€ Bußgeld möglich
CURB-CUT-EFFEKT:
- Bordsteinabsenkung für Rollstuhlfahrer → hilft auch Kinderwagen, Rollkoffern, Fahrrädern
- Untertitel für Gehörlose → helfen in lauter Umgebung, beim Sprachlernen
- Kontrastreiche Farben → besser bei Sonnenlicht, für ältere Menschen
BUSINESS CASE:
- 15% Zielgruppe (Menschen mit Behinderung)
- +20% ältere Menschen (Sehschwäche, motorische Einschränkungen)
- SEO-Vorteile: Alt-Texte, semantisches HTML = besser für Google
PRÜFUNGSRELEVANT: EAA kennen, Curb-Cut-Effekt erklären können, Business Case
-->
---
# WCAG: Der Standard

View File

@@ -59,6 +59,15 @@ Hochschule der Medien Stuttgart
**Wintersemester 2025/26**
[https://librete.ch/hdm/223015c/](https://librete.ch/hdm/223015c/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-223015c.png)
---
<!-- _class: lead -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

61
flake.lock generated Normal file
View File

@@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1766902085,
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

106
scripts/dev-server.sh Executable file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/env bash
# Development server script for HdM slides
# Starts index server + marp servers for each course
set -e
# Configuration
INDEX_PORT=1310
COURSE_B_PORT=1311
COURSE_C_PORT=1312
COURSE_DIR="courses"
DEV_INDEX_DIR=".dev-index"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Cleanup function
cleanup() {
echo -e "\n${RED}Shutting down servers...${NC}"
kill $PID_INDEX $PID_B $PID_C 2>/dev/null || true
exit 0
}
# Kill existing processes on our ports
kill_existing() {
echo -e "${BLUE}Cleaning up existing processes...${NC}"
# Kill marp processes first
pkill -9 -f "marp-cli" 2>/dev/null || true
pkill -f "python3 -m http.server" 2>/dev/null || true
# Kill ports including marp's WebSocket ports (37717-37720 range)
fuser -k $INDEX_PORT/tcp $COURSE_B_PORT/tcp $COURSE_C_PORT/tcp 2>/dev/null || true
fuser -k 37717/tcp 37718/tcp 37719/tcp 37720/tcp 2>/dev/null || true
sleep 2
}
# Generate dev index
generate_index() {
mkdir -p "$DEV_INDEX_DIR"
cat > "$DEV_INDEX_DIR/index.html" << 'EOF'
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>HdM Slides - Dev</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,"SF Pro Display","Segoe UI",Roboto,sans-serif;max-width:720px;margin:0 auto;padding:3rem 1.5rem;background:#fafafa;color:#1d1d1f;line-height:1.5}
h1{font-size:2rem;font-weight:600;letter-spacing:-0.02em;margin-bottom:.5rem}
.subtitle{color:#86868b;font-size:1rem}
.courses{margin-top:2rem;display:flex;flex-direction:column;gap:.75rem}
a.course{display:block;background:#fff;border-radius:12px;padding:1.5rem;text-decoration:none;color:inherit;box-shadow:0 1px 3px rgba(0,0,0,0.08);transition:all .2s ease;cursor:pointer}
a.course:hover{transform:translateY(-2px);box-shadow:0 4px 12px rgba(0,0,0,0.12)}
.course-label{font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em}
.course-b .course-label{color:#5da9e9}
.course-c .course-label{color:#d63384}
.course-title{font-size:1.15rem;font-weight:500;color:#1d1d1f;margin:.25rem 0}
.course-info{font-size:.85rem;color:#86868b}
</style>
</head>
<body>
<h1>HdM Slides</h1>
<p class="subtitle">Development Server</p>
<div class="courses">
EOF
echo " <a class=\"course course-b\" href=\"http://localhost:$COURSE_B_PORT\"><span class=\"course-label\">223015b</span><div class=\"course-title\">Dateiformate, Schnittstellen, Speichermedien & Distributionswege</div><span class=\"course-info\">Port $COURSE_B_PORT</span></a>" >> "$DEV_INDEX_DIR/index.html"
echo " <a class=\"course course-c\" href=\"http://localhost:$COURSE_C_PORT\"><span class=\"course-label\">223015c</span><div class=\"course-title\">Grundlagen IT- und Internettechnik</div><span class=\"course-info\">Port $COURSE_C_PORT</span></a>" >> "$DEV_INDEX_DIR/index.html"
cat >> "$DEV_INDEX_DIR/index.html" << 'EOF'
</div>
</body>
</html>
EOF
}
# Main
trap cleanup SIGINT SIGTERM
kill_existing
generate_index
echo -e "${GREEN}Starting development servers...${NC}"
echo ""
echo -e " Index: ${BLUE}http://localhost:$INDEX_PORT${NC}"
echo -e " 223015b: ${BLUE}http://localhost:$COURSE_B_PORT${NC}"
echo -e " 223015c: ${BLUE}http://localhost:$COURSE_C_PORT${NC}"
echo ""
echo -e "Press ${RED}Ctrl+C${NC} to stop all servers"
echo ""
# Start servers
python3 -m http.server $INDEX_PORT --directory "$DEV_INDEX_DIR" &
PID_INDEX=$!
PORT=$COURSE_B_PORT npx @marp-team/marp-cli --server "$COURSE_DIR/223015b/slides/" &
PID_B=$!
sleep 3 # Stagger starts to avoid WebSocket port collision
PORT=$COURSE_C_PORT npx @marp-team/marp-cli --server "$COURSE_DIR/223015c/slides/" &
PID_C=$!
# Wait for any process to exit
wait

View File

@@ -8,22 +8,40 @@ BUILD_DIR="${2:-build/$COURSE}"
# Course-specific configuration
case "$COURSE" in
223015b)
TITLE="223015b - Dateiformate, Schnittstellen, Speichermedien"
SUBTITLE="Dateiformate, Schnittstellen, Speichermedien & Distributionswege"
REPO_URL="https://git.librete.ch/hdm/223015b"
TITLE="Dateiformate, Schnittstellen, Speichermedien & Distributionswege"
SUBTITLE="223015b · Modul \"Technik 1\" · 1. Semester"
SLIDES_URL="https://librete.ch/hdm/223015b"
ACCENT_COLOR="#5da9e9"
ACCENT_LIGHT="#e8f4fc"
;;
223015c)
TITLE="223015c - Internettechnologien"
SUBTITLE="Internettechnologien"
REPO_URL="https://git.librete.ch/hdm/223015c"
TITLE="Grundlagen IT- und Internettechnik"
SUBTITLE="223015c · Modul \"Technik 1\" · 1. Semester"
SLIDES_URL="https://librete.ch/hdm/223015c"
ACCENT_COLOR="#d63384"
ACCENT_LIGHT="#fce4ec"
;;
*)
TITLE="$COURSE - HdM Slides"
SUBTITLE="Lecture Slides"
REPO_URL="https://git.librete.ch/hdm/$COURSE"
SLIDES_URL="https://librete.ch/hdm/$COURSE"
ACCENT_COLOR="#0066cc"
ACCENT_LIGHT="#e8f4fc"
;;
esac
# Topic mappings for nice German titles
declare -A TOPIC_MAP
TOPIC_MAP["intro"]="Einführung"
TOPIC_MAP["grundlagen-text-audio"]="Grundlagen, Text & Audio"
TOPIC_MAP["bild-audio-video"]="Bild, Audio & Video"
TOPIC_MAP["speichermedien-schnittstellen"]="Speichermedien & Schnittstellen"
TOPIC_MAP["distribution-apis-zukunft"]="Distribution, APIs & Zukunft"
TOPIC_MAP["vertiefung-offene-fragen"]="Vertiefung & Offene Fragen"
TOPIC_MAP["geschichte-grundlagen-html"]="Geschichte, Grundlagen & HTML"
TOPIC_MAP["netzwerke-protokolle-css"]="Netzwerke, Protokolle & CSS"
TOPIC_MAP["interaktivitaet-javascript"]="Interaktivität & JavaScript"
cat > "$BUILD_DIR/index.html" << HEADER
<!DOCTYPE html>
<html lang="de">
@@ -32,65 +50,142 @@ cat > "$BUILD_DIR/index.html" << HEADER
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>$TITLE</title>
<style>
* { box-sizing: border-box; }
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
max-width: 800px;
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, sans-serif;
max-width: 720px;
margin: 0 auto;
padding: 2rem;
background: #1a1a2e;
color: #eee;
padding: 3rem 1.5rem;
background: #fafafa;
color: #1d1d1f;
line-height: 1.5;
}
h1 { color: #fff; margin-bottom: 0.5rem; }
.subtitle { color: #888; margin-bottom: 2rem; }
.termin-row {
header { margin-bottom: 2rem; }
h1 {
font-size: 1.75rem;
font-weight: 600;
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
color: $ACCENT_COLOR;
}
.subtitle {
color: #86868b;
font-size: 0.95rem;
}
.meta {
color: #86868b;
font-size: 0.875rem;
margin-top: 0.25rem;
}
.termine {
margin-top: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.termin-card {
position: relative;
background: #fff;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
transition: all 0.2s ease;
display: grid;
grid-template-columns: 1fr auto auto;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.termin {
background: #16213e;
border-radius: 8px;
padding: 1.5rem;
text-decoration: none;
.termin-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.12);
}
.termin-link {
display: block;
flex: 1;
transition: transform 0.2s, background 0.2s;
}
.termin:hover { background: #1f4068; transform: translateX(5px); }
.termin h2 { color: #fff; margin: 0 0 0.5rem 0; font-size: 1.2rem; }
.termin .date { color: #4ecca3; font-size: 0.9rem; }
.termin .topic { color: #aaa; font-size: 0.95rem; margin-left: 1rem; }
.pdf {
background: #e94560;
color: #fff;
padding: 0.5rem 1rem;
border-radius: 4px;
padding: 1.25rem 1.5rem;
text-decoration: none;
font-size: 0.85rem;
color: inherit;
grid-column: 1;
}
.termin-label {
font-size: 0.7rem;
font-weight: 600;
color: $ACCENT_COLOR;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.termin-title {
font-size: 1.05rem;
font-weight: 500;
transition: background 0.2s;
color: #1d1d1f;
margin: 0.15rem 0;
}
.pdf:hover { background: #ff6b6b; }
.qr-section {
margin-top: 2rem;
text-align: center;
.termin-date {
font-size: 0.8rem;
color: #86868b;
}
.qr-section img {
max-width: 150px;
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
border-radius: 8px;
background: #fff;
padding: 0.5rem;
text-decoration: none;
font-size: 0.8rem;
font-weight: 500;
transition: all 0.2s;
white-space: nowrap;
position: relative;
z-index: 1;
}
.btn-slides {
background: $ACCENT_COLOR;
color: #fff;
margin-right: 0.5rem;
}
.btn-slides:hover {
filter: brightness(1.1);
}
.btn-pdf {
background: #f5f5f7;
color: #1d1d1f;
margin-right: 1rem;
}
.btn-pdf:hover { background: #e8e8ed; }
/* Make entire card clickable via overlay */
.termin-link::after {
content: '';
position: absolute;
inset: 0;
border-radius: 12px;
}
footer {
margin-top: 2.5rem;
padding-top: 1.5rem;
border-top: 1px solid #e5e5e7;
color: #86868b;
font-size: 0.85rem;
}
footer a { color: $ACCENT_COLOR; text-decoration: none; }
footer a:hover { text-decoration: underline; }
@media (max-width: 600px) {
.termin-card {
grid-template-columns: 1fr;
}
.termin-link {
padding-bottom: 0.75rem;
}
.btn-slides, .btn-pdf {
margin: 0 1rem 1rem 1.5rem;
}
}
footer { margin-top: 2rem; color: #666; font-size: 0.85rem; text-align: center; }
footer a { color: #4ecca3; }
</style>
</head>
<body>
<h1>$COURSE</h1>
<p class="subtitle">$SUBTITLE<br>
HdM Stuttgart - WS 2025/26 - Michael Czechowski</p>
<header>
<h1>$TITLE</h1>
<p class="subtitle">$SUBTITLE</p>
<p class="meta">HdM Stuttgart · Wintersemester 2025/26 · Michael Czechowski</p>
</header>
<div class="termine">
HEADER
# Generate links for each termin (sorted)
@@ -98,23 +193,26 @@ for html in $(ls "$BUILD_DIR"/2*.html 2>/dev/null | sort); do
filename=$(basename "$html")
# Extract components from filename
date=$(echo "$filename" | grep -oE '^[0-9]{4}-[0-9]{2}-[0-9]{2}')
date=$(echo "$filename" | grep -oE '^[0-9]{4}-[0-9x]{2}-[0-9x]{2}')
termin_num=$(echo "$filename" | grep -oE 'termin-[0-9]+' | grep -oE '[0-9]+')
topic_raw=$(echo "$filename" | sed -E 's/^[0-9]{4}-[0-9]{2}-[0-9]{2}-termin-[0-9]+-//' | sed 's/\.html$//')
topic_raw=$(echo "$filename" | sed -E 's/^[0-9]{4}-[0-9x]{2}-[0-9x]{2}-termin-[0-9]+-//' | sed 's/\.html$//')
# Format topic: replace - with space, capitalize
topic=$(echo "$topic_raw" | sed 's/-/ /g' | sed 's/.*/\u&/')
# Look up nice topic name or fallback
topic="${TOPIC_MAP[$topic_raw]}"
if [[ -z "$topic" ]]; then
topic=$(echo "$topic_raw" | sed 's/-/ /g' | sed 's/.*/\u&/')
fi
# Format date
if [[ "$date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
formatted_date=$(date -d "$date" "+%d.%m.%Y" 2>/dev/null || echo "$date")
if [[ "$date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && [[ ! "$date" =~ xx ]]; then
formatted_date=$(date -d "$date" "+%d. %B %Y" 2>/dev/null || echo "$date")
else
formatted_date="TBA"
formatted_date="Termin folgt"
fi
# Handle termin number
if [[ "$termin_num" == "0" ]]; then
termin_label="Einfuhrung"
termin_label="Einführung"
else
termin_label="Termin $termin_num"
fi
@@ -124,35 +222,27 @@ for html in $(ls "$BUILD_DIR"/2*.html 2>/dev/null | sort); do
# Check if PDF exists
pdf_link=""
if [[ -f "$BUILD_DIR/$pdf_filename" ]]; then
pdf_link="<a href=\"$pdf_filename\" class=\"pdf\">PDF</a>"
pdf_link="<a href=\"$pdf_filename\" class=\"btn btn-pdf\">PDF</a>"
fi
cat >> "$BUILD_DIR/index.html" << LINK
<div class="termin-row">
<a href="$filename" class="termin">
<h2>$termin_label</h2>
<span class="date">$formatted_date</span>
<span class="topic">$topic</span>
</a>
$pdf_link
</div>
<div class="termin-card">
<a href="$filename" class="termin-link">
<div class="termin-label">$termin_label</div>
<div class="termin-title">$topic</div>
<div class="termin-date">$formatted_date</div>
</a>
<a href="$filename" class="btn btn-slides">Folien</a>
$pdf_link
</div>
LINK
done
# Add QR code if exists
if [[ -f "$BUILD_DIR/qr-$COURSE.png" ]]; then
cat >> "$BUILD_DIR/index.html" << QRSECTION
<div class="qr-section">
<img src="qr-$COURSE.png" alt="QR Code">
<p style="color: #888; font-size: 0.8rem;">Scan to open on mobile</p>
</div>
QRSECTION
fi
cat >> "$BUILD_DIR/index.html" << FOOTER
</div>
<footer>
<a href="$REPO_URL">Git Repository</a> -
<a href="mailto:mail@librete.ch">Kontakt</a>
<a href="mailto:mail@librete.ch">Kontakt</a> ·
<a href="../">Alle Kurse</a>
</footer>
</body>
</html>