Compare commits

..
52 Commits
Author SHA1 Message Date
libretechandClaude Opus 4.8 9a4b4536cd 223015b+c klausurfragen: stand 03.07
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 23:03:26 +02:00
libretechandClaude Opus 4.8 102a6d53e5 223015b+c klausurfragen: sose26-klausurset kuratiert + wording-fixes
- 223015c: G7 id-selektor neu (ersetzt spezifität-ansatz), B10 encapsulation
  + E3 gesamtablauf disabled (tcp-handshake nie ausreichend behandelt),
  G6 ohne hsl + farbname/color code, H6 curb-cut-wording (genau zwei
  beispiele, klickflächen/kontrast/tab+enter), H7 attribute statt tags
  + screenreader-distraktor + tastatur-wording, B7b dns: domain->ip
- 223015b: J22 ohne buch-lesen + überwiegend unabhängig, K2 sie-form
  + taschenrechner-hinweis, strg/cmd+f
- .gitignore: slides/**/*-INTERN.md (lokale klausur-previews, nie deployen)
- 223015b/CLAUDE.md: deck-doku + downstream-verweis aufs klausur-repo

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 13:37:01 +02:00
libretech 983cdea235 223015b klausurfragen: disabled-fragen + j6/j7/j8/j16 entfernt, j14a (farbwerte pro byte) ergänzt, ecc-zeile raus, j22-frage layout entzerrt 2026-07-02 19:23:26 +02:00
libretech 2d926f153e 223015c klausurfragen: alle disabled-fragen entfernt, kuratierung reduziert 2026-07-02 19:23:26 +02:00
libretech a1381dc717 223015c: kapitel 3 (javascript) aus deploy-kapiteln entfernt 2026-07-02 19:23:25 +02:00
libretech c7045d96e4 223015b+c klausurfragen: frage-folie ohne lösung je aktiver frage vorangestellt, bestehende als (lösung) markiert; sortiere->sortieren sie 2026-06-24 13:39:01 +02:00
libretech b500e2f647 223015b klausurfragen: auf sie umgestellt + emojis raus, fragen-set kuratiert (j/l/m/n/o aktiviert bzw. ausgegraut), l1 auf vorwiegend verlustbehaftet präzisiert, bandbreite-fragen ergänzt, stand 24.06 2026-06-24 13:28:10 +02:00
libretech fdd4bbaa54 223015c klausurfragen: client-server-modell + ip/mac/port/dns-glossar ergänzt, stand 24.06 2026-06-24 13:14:56 +02:00
libretech b8ca038153 223015c klausurfragen: nicht-prüfungsrelevante fragen ausgegraut 2026-06-24 13:01:23 +02:00
libretech c7811f4001 index: 223015b klausurfragen freigeschaltet 2026-06-17 14:27:13 +02:00
libretech 3ae2f6881a index: klausurfolien/klausurfragen-karten per-kurs schaltbar; 223015b klausurfolien freigeschaltet, 223015c klausurfragen 2026-06-17 14:13:15 +02:00
libretech a13440b519 223015c: klausurfragen auf sie vereinheitlicht + 6 fragen ergänzt (a5/c11/c12/f4/g5/g6), emojis raus, stand aktualisiert; index: kapitel 03 + klausurfragen freigeschaltet 2026-06-17 13:57:20 +02:00
libretech 800a7d6ff9 223015c: farben-overflow gefixt (intro gekürzt, code kompakt), klausurfolien regeneriert 2026-06-17 13:34:55 +02:00
libretech d01253d0d0 223015c 02: anwendungsschicht benannt + an abstraktion angeknüpft (browser/app -> anwendung) 2026-06-17 13:01:00 +02:00
libretech 7885aee8fc 223015c 02: schicht-nummern auf 4-schichten-modell vereinheitlicht, alle abkürzungen bei erstnennung aufgelöst 2026-06-17 12:17:55 +02:00
libretech 27199ee1cc 223015c 03: hands-on-imperative auf ihr-plural vereinheitlicht 2026-06-17 12:17:55 +02:00
libretech 1dd983a453 223015c 01: tippfehler/grammatik/fachfehler korrigiert, frage-headings entschärft 2026-06-17 12:17:55 +02:00
libretech 4cd9975017 223015c 00: frage-headings/sie-anrede/drama entschärft 2026-06-17 12:17:55 +02:00
libretech a64382d2de 223015c 01: byte/bit ohne plural-s 2026-06-17 12:03:40 +02:00
libretech 45c554c875 223015c 02: alltagsmetaphern entschlackt, vertiefung sortiert, dns-hierarchie präzisiert, byte/bit ohne plural-s 2026-06-17 12:03:39 +02:00
libretech 841d8b5944 223015c demos: port-grafik baseline-fix, handshake-caption vervollständigt, dingbat raus 2026-06-17 12:03:38 +02:00
libretech 613f37983e 223015c 02: osi/tcp-ip-grafik korrekt gemappt + headline-umbruch fix 2026-06-17 10:39:08 +02:00
libretech 2658251bcb 223015c 03: datum/emoji raus, frage-headings entschärft, du-konsistenz 2026-06-17 10:36:16 +02:00
libretech 3d6059c070 223015c 02: deutsch-qualität, fragmente/anglizismen raus, neutraler ton 2026-06-17 10:36:16 +02:00
libretech ed756461e6 223015c 02: anrede durchgängig duzen, emoji raus, http/2.0 vereinheitlicht 2026-06-17 09:59:58 +02:00
libretech 028f5f0fb8 223015b kap2: demos + barn rgb/cmyk
- 18 demos aus refactor/didaktik-rewrite-2026 cherry-picked (aliasing-paar, byte-fuer-byte, container-vs-codec, drei-dateien, jpeg-pipeline, kap02-05-eroeffner, kb-vs-kib, nyquist-diagram, pivot-signal-zu-byte, psychoakustik/psychovisualitaet-grafik, raster-vs-vektor, summary-kap02, summary-organizer, usb-c-drei-achsen)
- barn-rgb.png + barn-cmyk.png neu generiert (analog zu ybcbr.webp, kanaltrennung mit korrekter k-extraktion)
- lv-original-vs-fake.jpg + 02-bild-audio-video.md slides wired up
2026-06-11 09:55:58 +02:00
libretech 7ae2a9964a 223015c 02: layer 1 (bit) ergänzt, tabellen-refactor, http/2.0, dimmed/klausur-klassen 2026-05-22 09:47:58 +02:00
libretech abc8dece9c 223015b 01: edit-müll raus (style-tag-injection + eof-tippfehler) 2026-05-15 22:06:58 +02:00
libretech a5f890ae24 hdm fixes 2026-05-15 09:44:50 +02:00
libretech 56901d6068 update logos 2026-05-14 22:58:35 +02:00
libretech 2184870e0b dhbw 01-intro: über-mich collage refresh + wording-fixes + index-script polish
- collage.png neu: 11 marken (3 spalten brick-staggered + breite kombi-row für klett+pons+langenscheidt), normalisiert mit padding rechts, dhbw-dark + uni-stuttgart-dark variants (light-svgs unsichtbar auf weiß)
- neue logos: pons.svg (wikimedia, ersetzt gecropptes pons.jpg), bosch.svg, leibniz-fh.svg (alle wikimedia), hdm.jpg, libretech.png (gitea avatar), nextlevelshit.png (github avatar), pons-langenscheidt-klett.png (kombi)
- 01-intro slide: "Web App" -> "Web Applikation" (PWA-fachbegriff bleibt), "Betriebssystem (GNU/Linux, Windows, macOS, iOS, Android)" als erste kategorie ergänzt + OSs aus desktop/mobile rausgezogen, "ODER" -> "XOR"
- scripts/generate-index: dhbw spezifisch — KONTAKT_URL/LABEL pro course, QR_IMG-pfad pro course, footer 'Kursübersicht'-link conditional auf BREADCRUMB_URL, dhbw-subtitle ohne hdm-modul-name
2026-05-09 20:47:03 +02:00
libretech 755aadbc6a scripts/generate-index: per-course BREADCRUMB_URL + EXAM_URL/EXAM_LABEL — dhbw ohne 'kursübersicht'-link (ging fälschlich auf homepage), dhbw mit prüfungsleistung-link (git.librete.ch/DHBW/pruefungsleistung) 2026-05-08 21:49:55 +02:00
libretech 3554908246 scripts/generate-index: dhbw-case ergänzt (web engineering, dhbw stuttgart, himbeer-akzent, sitzung statt kapitel), HEADLINE+INSTITUTION+KAPITEL_TERM pro course, dhbw-topics in TOPIC_MAP (html-css, js-frameworks, nodejs-basics, express, testing, typescript, docker, best-practices) 2026-05-08 21:39:55 +02:00
libretech 2ac3303167 dhbw: file-namen auf dash-convention vereinheitlicht (consistent mit hdm), Makefile dhbw_KAPITEL aktualisiert 2026-05-08 21:36:59 +02:00
libretech 7970ba84d1 dhbw 09_best_practices: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:57:44 +02:00
libretech bb7c2730ca dhbw 08_docker: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:57:14 +02:00
libretech 4f4e989721 dhbw 07_typescript: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:56:42 +02:00
libretech 32a633188a dhbw 06_testing: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:56:09 +02:00
libretech 8ae050baad dhbw 05_express: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:55:33 +02:00
libretech 19d05252ef dhbw 04_nodejs_basics: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:54:53 +02:00
libretech e1c75a1ba3 dhbw 03_js_frameworks: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:54:17 +02:00
libretech c21a073984 dhbw 02_html_css: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:53:36 +02:00
libretech bd473fc890 dhbw 01_intro: qr-code-folie nach cover (zeigt auf librete.ch/dhbw/) + url unter cover, mirror hdm-pattern 2026-05-08 13:52:40 +02:00
libretech 95ff4a08d7 dhbw assets: qr-code zu librete.ch/dhbw/ (slides-dhbw.png) für post-cover-folien 2026-05-08 13:51:54 +02:00
libretech 29403e0f78 dhbw 01_intro: was-keine-webapp-folie auf * statt - bullets für marp-fragmented-list 2026-05-08 13:35:44 +02:00
libretech 0a7730ad9a dhbw 01_intro: vorstellungsrunde-folie zwischen über-mich und vorlesungsplan (gap aus original-PDF slide 4 — wer bist du, was machst du) 2026-05-08 13:32:43 +02:00
libretech c4c6119b8a dhbw 01_intro: was-ist-keine-webapp-block (cover + content) zwischen prüfungsleistung-abgabe und internet-timeline (gap aus original-PDF slides 8/9) 2026-05-08 13:30:43 +02:00
libretech a830480100 dhbw 01_intro: erwartungen-und-wünsche-folie zwischen vorlesungsplan und prüfungsleistung (gap aus original-PDF slide 6) 2026-05-08 13:27:46 +02:00
libretech a56b487bd4 dhbw 01_intro: editor-folie titel präzisiert (Editor → Editor (IDE)) 2026-05-08 13:24:27 +02:00
libretech 81f233b61a dhbw slides: 1 file pro sitzung (issue #2)
01_web_eng.md (103 slides) aufgesplittet:
- 01_intro.md: cover, ueber-mich, vorlesungsplan, pruefungsleistung, internet 101, onboarding
- 02_html_css.md: html, a11y/wcag, css basics + css extended (aus 02_css_extended.md gemergt)
- 03_js_frameworks.md: ecmascript, js, dom, fetch, async, frameworks, build tools, microfrontends

renames (03-08 -> 04-09):
- 03_nodejs_basics -> 04_nodejs_basics
- 04_nodejs_advanced -> 05_express
- 05_testing -> 06_testing
- 06_typescript -> 07_typescript
- 07_docker -> 08_docker
- 08_best_practices -> 09_best_practices

02_css_extended.md geloescht (inhalte in 02_html_css.md)
makefile: dhbw_KAPITEL + dhbw_NAME aktualisiert
2026-05-08 09:06:19 +02:00
libretech 0774b8652d dhbw 01: pruefungsleistung aktualisiert (100 basis + 15 bonus statt 75+10)
punkteverteilung nach source-of-truth (git.librete.ch/DHBW/pruefungsleistung):
- grundanforderungen 30p (projektgrundlagen 15 + praesentation 15)
- clean code 25p (struktur 10 + qualitaet 10 + doku 5)
- accessibility & ux 25p (a11y 15 + responsive 10) — neu
- technische umsetzung 20p — neu
- bonus max 15p (6 bereiche statt 8, je 5p)
2026-05-08 08:54:40 +02:00
libretech dde33f108f dhbw 01: fix pruefungsleistung link (git.librete.ch) 2026-05-08 08:46:23 +02:00
94 changed files with 6591 additions and 4559 deletions

No files matched your search

+3 -3
View File
@@ -35,6 +35,6 @@ hdm-internettechnik-slides/
*.bak
.idea
# Image-Backups (Original-Quellen vor optimize-images)
slides/*/assets-original/
slides/*/assets/*-original/
# Interne Klausur-Previews – NIE committen/deployen
slides/**/*-INTERN.md
slides/*-INTERN.md
+81 -108
View File
@@ -1,59 +1,48 @@
# AGENTS.md - Agent Guidelines for Uni Slides (HdM + DHBW)
# AGENTS.md - Agent Guidelines for HdM Slides
This file contains comprehensive guidelines for agentic coding agents working on the Uni Slides project. For the short version, see `CLAUDE.md`.
This file contains comprehensive guidelines for agentic coding agents working on the HdM Slides project.
## Project Overview
This project builds presentation decks for Marp, supporting multiple courses:
- **223015b** – Dateiformate, Schnittstellen, Speichermedien (HdM, 6 Kapitel + Klausur)
- **223015c** – Internettechnologien (HdM, 3 Kapitel + Klausur)
- **dhbw** – Technik I – Grundlagen IT (DHBW, 8 Kapitel)
- **223015b** - Dateiformate, Schnittstellen, Speichermedien (6 Kapitel)
- **223015c** - Internettechnologien (3 Kapitel)
## Development Workflow
### Build Commands
Unified per-course pattern: `make <target>-<course>`. Group targets without suffix run for all courses. Single dev server serves all courses.
```bash
# Dev (all courses, single port)
make dev # Live server (HMR), port 1312
# Development
make dev # Start single dev server on port 3000
npm run dev # Alternative command for development server
# Per-course build/deploy (replace <c> with: 223015b, 223015c, dhbw)
make build-<c> # Build HTML + PDF
make html-<c> # HTML only
make pdf-<c> # PDF only
make klausur-<c> # Extract klausur slides (HdM only)
make deploy-<c> # Build + deploy single course (ASK FIRST!)
# Build
make build # Build all courses (HTML + PDF)
make build-b # Build 223015b only
make build-c # Build 223015c only
make html # HTML only builds
make pdf # PDF only builds
# All courses
make build # Build everything
make html / pdf # HTML / PDF only
make klausur # Extract klausur (HdM courses only)
make deploy # Deploy everything (ASK FIRST!)
# Klausur Folien
make klausur # Extract klausurfolien for all courses
make klausur-b # Extract klausurfolien for 223015b
make klausur-c # Extract klausurfolien for 223015c
# Deployment
make deploy # Deploy all courses (requires explicit permission)
make deploy-b # Deploy 223015b only
make deploy-c # Deploy 223015c only
# Utilities
make qr URL=... # Generate QR code
make qr-slides COURSE=<c> # QR for course URL
make optimize-images COURSE=<c> # Resize images
make clean # Remove generated files
make install # npm install
```
**Adding a new course:** add id to `COURSES` in `Makefile` + define `<id>_NAME`, `<id>_KAPITEL`, `<id>_DEPLOY`, `<id>_KLAUSUR`. No new targets needed.
### Nix Flake
```bash
nix develop # Dev shell with all tools (node 22, npm, make)
make qr URL=... # Generate QR code
make optimize-images COURSE=223015b # Resize images
make clean # Remove generated files
```
### Testing
No formal test framework. To validate changes:
No specific test framework is used. To validate changes:
1. Start dev server: `make dev`
2. Open http://localhost:1312/223015b/, /223015c/, or /dhbw/
2. Open http://localhost:3000/223015b/ or /223015c/
3. Verify slides render correctly
4. Run `make build` to ensure no build errors
5. Check generated files in `build/` directory
@@ -61,18 +50,7 @@ No formal test framework. To validate changes:
## Code Style Guidelines
### File Structure
```
slides/
├── 223015b/ # HdM: Dateiformate
├── 223015c/ # HdM: Internettechnik
└── dhbw/ # DHBW: Technik I
scripts/ # Shared scripts
themes/ # Custom Marp themes
build/ # Generated output (gitignored)
```
- Slides in `slides/<course>/` following `NN-topic.md` (HdM) or `NN_topic.md` (DHBW)
- Slides in `slides/<course>/` following naming pattern `NN-topic.md`
- Assets in `slides/<course>/assets/`
- Always reference images as `./assets/filename.png`
- Scripts in `scripts/`
@@ -80,22 +58,20 @@ build/ # Generated output (gitignored)
- Generated output in `build/` (gitignored)
### Naming Conventions
- Slide files: `NN-topic.md` (HdM, e.g. `01-grundlagen.md`) or `NN_topic.md` (DHBW, e.g. `01_web_eng.md`)
- Slide files: `NN-topic.md` (e.g., `01-grundlagen.md`, `02-bilder.md`)
- Images: `snake_case.jpg` or `kebab-case.jpg`
- Klausur files: `klausurfolien.md` / `klausurfragen.md` (auto-generated, HdM only)
- Function/variable names in scripts: `snake_case`
- Klausur files: `klausurfolien.md` (auto-generated)
- Function names in scripts: `snake_case`
- Variable names in scripts: `snake_case`
### Markdown Style
- Use ATX-style headers (`# ## ###`)
- YAML frontmatter for slide metadata at top of each file
- Never include a final `---` (creates empty slide)
- Use `<!-- _class: klausur -->` for exam-relevant slides (HdM)
- Use `<!-- _class: klausur -->` for exam-relevant slides
- Use relative paths for assets: `./assets/image.png`
### Script Style
- Use `#!/usr/bin/env bash` shebang
- Use `set -e` for error handling
- Use `2>/dev/null || true` for optional operations
@@ -103,7 +79,6 @@ build/ # Generated output (gitignored)
- Use colors for terminal output: `\033[0;32m` etc.
### Git Workflow
- Commit messages: ALWAYS lowercase
- NEVER add co-authoring lines or generated footers
- Follow semantic naming: "add-...", "fix-...", "update-..."
@@ -112,113 +87,111 @@ build/ # Generated output (gitignored)
## Agent Restrictions
### Security
- NEVER run commands outside `/home/libretech/Repos/uni`
- NEVER run commands outside `/home/mwc/Coding/hdm` folder
- NEVER run build/deploy commands without explicit user request
- NEVER run deploy commands (`make deploy`, `scp`, etc.) without explicit permission
- NEVER run `git checkout --` or `git restore` on files with uncommitted work. To undo specific changes, use targeted Edit operations instead.
- NEVER run deploy commands (make deploy, scp, etc.) without explicit permission
### File Protection
Slide files in `slides/*/*.md` are main content files:
- **ALLOWED**: Adding slides, adjusting content, fixing typos, enhancing sections
- **FORBIDDEN** (without permission): Deleting slides, removing sections, bulk deletions
- Before ANY deletion: ALWAYS ask user for confirmation
### Klausur Handling (HdM only)
- Klausur files (`klausurfolien.md`, `klausurfragen.md`) are auto-generated
- NEVER edit klausur files directly
- To update klausur: edit source slides with `<!-- _class: klausur -->` markers
- Run `make klausur` (or `make klausur-<c>`) to regenerate
- DHBW course has no klausur extraction (`dhbw_KLAUSUR =` is empty)
### Klausur Handling
- Klausur files (`klausurfolien.md`) are auto-generated
- NEVER edit klausurfolien.md files directly
- To update klausurfolien: edit source slides with `<!-- _class: klausur -->` markers
- Run `make klausur` to regenerate
## Development Patterns
### Adding New Slides
1. Create new file following naming convention (`NN-topic.md` for HdM, `NN_topic.md` for DHBW)
1. Create new file following `NN-topic.md` pattern
2. Copy frontmatter from existing slides in the same course
3. Add stem to `<course>_KAPITEL` in `Makefile`
3. Update Makefile `_KAPITEL` variable if needed
4. Test with `make dev`
### Modifying Existing Slides
1. Edit the appropriate markdown file in `slides/<course>/`
2. Maintain consistent styling with course theme
3. Preserve image paths as `./assets/...`
4. Test changes with dev server
### Working with Assets
1. Place images in `slides/<course>/assets/`
2. Use descriptive names: `diagram-network.jpg`, `example-code.png`
3. Optimize with `make optimize-images COURSE=<c>`
3. Optimize with `make optimize-images COURSE=223015b`
4. Reference as `./assets/filename.ext`
### Course-Specific Configuration
Each course has these per-course settings in `Makefile`:
- `<c>_NAME` – Display name
- `<c>_KAPITEL` – Ordered list of slide file stems (without `.md`)
- `<c>_DEPLOY` – Remote deploy path
- `<c>_KLAUSUR` – `1` to enable klausur extraction, empty to disable
Each course has specific settings in Makefile:
- Course name and title
- Kapitel list (slide files)
- Deploy path
- Theme colors (in generate-index.sh)
## Common Tasks
### Debugging Build Issues
1. Check Makefile syntax: `make -n build-<c>`
2. Verify Marp CLI: `npx @marp-team/marp-cli --version`
1. Check Makefile syntax: `make -n build`
2. Verify Marp CLI installation: `npx @marp-team/marp-cli --version`
3. Check file permissions: `ls -la slides/`
4. Validate markdown via dev server
4. Validate markdown syntax with dev server
### Updating Course Structure
1. Update `<c>_KAPITEL` in `Makefile`
1. Update `_KAPITEL` variables in Makefile
2. Ensure slide files follow naming convention
3. Update course-specific themes if needed
4. Test both `make dev` and `make build-<c>`
4. Test both dev and build processes
### Working with Themes
- Custom theme in `themes/custom-theme.css`
- Course themes referenced in individual slide frontmatter
- Course themes defined in individual slide frontmatter
- Use consistent color schemes per course
- Test theme changes across all slides
## Deployment Process
Deployment to production server requires explicit permission:
1. Build: `make build` (HTML + PDF) or per-course `make build-<c>`
2. Index generation: handled by `scripts/generate-index.sh` (per course) and `scripts/generate-root-index.sh` (root)
3. Deploy: `scp` to `tengo@tuttle.uberspace.de` via `make deploy-<c>` or `make deploy`
4. Root index deployed by `make deploy-index` (or as part of `make deploy`)
1. Build process: `make build` (HTML + PDF)
2. Index generation: automatically handled
3. Deploy to remote server via SCP
4. Root index deployment
**IMPORTANT**: Never run deployment commands without explicit user permission.
## Tools and Dependencies
### Core
- Marp CLI for slide rendering (via `npx @marp-team/marp-cli`)
- Bash scripts for automation (`scripts/`)
### Core Dependencies
- Marp CLI for slide rendering
- Bash scripts for automation
- Make for build orchestration
- Git for version control
### Optional
- `qrencode` for QR generation (via nix-shell)
- ImageMagick for image optimization (via nix-shell)
### Optional Tools
- qrencode for QR generation (via nix)
- ImageMagick for image optimization
- Python 3 for simple HTTP server (legacy)
## Testing Strategy
Since there's no formal test suite:
1. Manual testing with dev server
2. Build process validation
3. Slide rendering checks
4. Asset path verification
5. Cross-browser compatibility checks (important)
## Troubleshooting
### Common Issues
- **Port conflicts**: kill the dev-server process holding port 1312
- **Build failures**: check file permissions and Marp CLI availability via `npx`
- **Asset loading**: verify relative paths and file existence in `slides/<c>/assets/`
- **Deploy issues**: check SSH keys for `tengo@tuttle.uberspace.de` and remote permissions
- **Port conflicts**: Use `make dev-kill` to clean up processes
- **Build failures**: Check file permissions and Marp CLI installation
- **Asset loading**: Verify relative paths and file existence
- **Deploy issues**: Check SSH keys and remote permissions
### Getting Help
1. Check this `AGENTS.md` first
2. Review `Makefile` targets and `scripts/`
1. Check this AGENTS.md file first
2. Review Makefile targets and scripts
3. Test changes incrementally
4. Maintain backup of working configurations
4. Maintain backup of working configurations
+2 -37
View File
@@ -4,45 +4,10 @@ This project builds presentation decks for Marp, supporting multiple courses.
## Courses
- **223015b** - Dateiformate, Schnittstellen, Speichermedien (HdM, 6 Kapitel + Klausur) — Fokus: **Dateien und Inhalte**
- **223015c** - Internettechnologien (HdM, 3 Kapitel + Klausur) — Fokus: **Internet und Web**
- **223015b** - Dateiformate, Schnittstellen, Speichermedien (HdM, 6 Kapitel + Klausur)
- **223015c** - Internettechnologien (HdM, 3 Kapitel + Klausur)
- **dhbw** - Technik I – Grundlagen IT (DHBW, 8 Kapitel)
## Didaktisches Fundament (für alle HdM-Kurse)
Diese drei Meta-Lernziele sind der Maßstab für jede inhaltliche Entscheidung — Folien, Reihenfolge, Beispiele, Übungen, Sprache. Jede Folie soll mindestens eines davon bedienen.
1. **Gelernte Hilflosigkeit ablegen.** Studierende sollen am Ende fühlen, dass Technik kein Mysterium ist, das sie überfordert. Konsequenz: keine Insider-Sprache ohne Erklärung, jeder Begriff wird beim ersten Auftreten geöffnet, abstrakte Konzepte werden über konkrete Beispiele eingeführt (nicht andersrum).
2. **Berührungspunkte schaffen.** Studierende sollen das Material mit ihrer eigenen Lebenswelt verknüpfen. Konsequenz: jedes Kapitel braucht mindestens einen Anker im Alltag der Studierenden (Smartphone, WhatsApp, Foto, Instagram-Story, eigener Laptop, eigener Browser, eigene Hex-Farbe). Theorie ohne Anker streichen oder umbauen.
3. **Erstes fundiertes Wissen und Gefühl für Technik.** Nicht Auswendiglernen. Nicht „Klausurwissen". Ein belastbarer mentaler Bauplan, der sich später erweitern lässt. Konsequenz: lieber drei Konzepte in Tiefe als zwölf in Breite. Vereinfachen ist erlaubt, solange das Modell nicht falsch wird.
### Didaktische Werkzeuge, die wir anwenden
- **Constructive Alignment (Biggs):** Lernziele → Aktivitäten → Prüfung → Folien (in dieser Reihenfolge). Keine Folien-Restrukturierung ohne benannte Lernziele.
- **Advance Organizer (Ausubel):** Jeder Themenblock öffnet mit einem visuellen Schema, das die Struktur des Bogens (nicht ein konkretes Beispiel) zeigt. Ankert Vorwissen, gibt Orientierung.
- **Mayer Multimedia (12 Prinzipien):** Coherence (Deko-frei), Signaling (visuelle Cues), Redundancy-Vermeidung (Folientext ≠ Vorlesungstext), Spatial Contiguity (Text + Bild zusammen), Pre-Training (Grundbegriffe vor Komplexem), Personalisation.
- **Informatikdidaktik (Magenheim / Romeike / Hartmann):** Abstrakt-Konkret-Brücke ist nicht optional, sondern Pflicht. Beispiele aus der Lebenswelt zuerst, Formalisierung danach.
### Validierungs-Kriterien (vor Commit / Deploy prüfbar)
Jede neue oder geänderte Folie soll folgende Fragen positiv beantworten können:
- [ ] Welches der drei Meta-Lernziele bedient diese Folie?
- [ ] Welches konkrete Lernziel des Themenblocks (formuliert mit Verb: analysieren, identifizieren, herleiten, begründen, einordnen, anwenden) wird hier vorbereitet, gestützt oder geprüft?
- [ ] Gibt es einen Berührungspunkt zur Lebenswelt der Studierenden auf dieser Folie oder im direkten Umfeld?
- [ ] Würde ein Student ohne Vorkenntnisse den Begriffsapparat dieser Folie verstehen — oder gibt es ungeöffnete Insider-Sprache?
- [ ] Folientext ≠ wortwörtlicher Vorlesungstext (Mayer Redundancy)?
- [ ] Wäre die Folie ohne den vorhergehenden Block verständlich? (Sollte NEIN sein — Folien sind nicht Inseln, sondern Schritte.)
Wenn eine dieser Fragen verneint wird: nicht committen, sondern umbauen oder begründen warum die Ausnahme akzeptabel ist.
### Anti-Pattern, die wir vermeiden
- **Bullet-Vorlesen:** Folientext ist nicht das, was der Dozent sagt. Es ist der visuelle Anker für das, was der Dozent sagt.
- **Motivations-Cringe:** Keine Anbiederung an Studierende durch billige Provokationen („Wer hat schon mal..." als Selbstzweck). Anker müssen substanziell sein.
- **Theorie-First:** Niemals Definition vor Beispiel, wenn das Beispiel die Definition selbst-erklärend macht.
- **Folien-Patchen:** Bei kaputtem Bogen keine Brücken-Folien einbauen — sondern die Lernziel-Struktur prüfen und ggf. den ganzen Block neu denken.
## Agent Restrictions
- Agent NEVER runs commands outside this folder
+3 -3
View File
@@ -18,12 +18,12 @@ DEPLOY_HOST = tengo@tuttle.uberspace.de
223015b_KLAUSUR = 1
223015c_NAME = Internettechnologien
223015c_KAPITEL = 01-geschichte-grundlagen-html 02-netzwerke-protokolle-css 03-interaktivitaet-javascript klausurfolien klausurfragen
223015c_KAPITEL = 01-geschichte-grundlagen-html 02-netzwerke-protokolle-css klausurfolien klausurfragen
223015c_DEPLOY = /home/tengo/html/hdm/223015c
223015c_KLAUSUR = 1
dhbw_NAME = Technik I – Grundlagen IT
dhbw_KAPITEL = 01_web_eng 02_css_extended 03_nodejs_basics 04_nodejs_advanced 05_testing 06_typescript 07_docker 08_best_practices
dhbw_NAME = Web Engineering
dhbw_KAPITEL = 01-intro 02-html-css 03-js-frameworks 04-nodejs-basics 05-express 06-testing 07-typescript 08-docker 09-best-practices
dhbw_DEPLOY = /home/tengo/html/dhbw
dhbw_KLAUSUR =
+5 -15
View File
@@ -4,21 +4,11 @@ Combined presentation slides for DHBW and HdM Stuttgart courses, built with [Mar
## Courses
| Code | Title | Origin | Fokus |
|------|-------|--------|-------|
| 223015b | Dateiformate, Schnittstellen, Speichermedien | HdM | **Dateien und Inhalte** |
| 223015c | Internettechnologien | HdM | **Internet und Web** |
| dhbw | Technik I – Grundlagen IT | DHBW | Grundlagen |
## Didaktisches Fundament (HdM)
Drei Meta-Lernziele bilden den Maßstab für jede inhaltliche Entscheidung:
1. **Gelernte Hilflosigkeit ablegen** — Technik ist kein Mysterium. Keine Insider-Sprache ohne Erklärung; abstrakte Konzepte über konkrete Beispiele.
2. **Berührungspunkte schaffen** — Inhalte mit der Lebenswelt der Studierenden verknüpfen. Jedes Kapitel braucht mindestens einen Alltags-Anker.
3. **Erstes fundiertes Wissen und Gefühl für Technik** — kein Auswendiglernen, sondern ein belastbarer mentaler Bauplan. Lieber drei Konzepte in Tiefe als zwölf in Breite.
Die operative Umsetzung (Werkzeuge, Validierungs-Kriterien, Anti-Pattern) ist in [CLAUDE.md](./CLAUDE.md#didaktisches-fundament-für-alle-hdm-kurse) dokumentiert und gilt für alle Beiträge — menschlich wie agentisch.
| Code | Title | Origin |
|------|-------|--------|
| 223015b | Dateiformate, Schnittstellen, Speichermedien | HdM |
| 223015c | Internettechnologien | HdM |
| dhbw | Technik I – Grundlagen IT | DHBW |
## Project Structure
-112
View File
@@ -1,112 +0,0 @@
# Lernziele 223015b — Dateiformate, Schnittstellen, Speichermedien
**Status:** Vorschlag für Dozent-Review (Phase 1, 2026-05-14)
**Kurs-Fokus:** Dateien und Inhalte
**Klausur-Blöcke gelockt:** 9 Blöcke (siehe `docs/klausur-themen-2026.md`)
Die Lernziele sind als **Vorschläge** formuliert — der Dozent setzt die endgültige Latte. Default-Ambitionslevel: Verstehen/Unterscheiden/Einordnen, nicht Berechnen.
---
## Meta-Lernziele (aus CLAUDE.md)
- Studierende legen gelernte Hilflosigkeit ab. Technik ist kein Mysterium.
- Studierende verknüpfen das Material mit ihrer eigenen Lebenswelt.
- Studierende verfügen über erstes fundiertes Wissen und Gefühl für Technik.
---
## Hinweis zur Begriffsverwendung „Block"
Ein **Klausur-Block** in diesem Dokument ist ein **thematischer Lernziel-Cluster** — z.B. „Block 1: Datenfundamentale" fasst alle Lernziele rund um Bit/Byte/Hex/Encoding/Magic Numbers zusammen. Das entspricht der bestehenden Konvention in `klausurfragen.md` (BLOCK J, K, L, …).
**Wichtig:** Die einzelnen klausur-markierten Folien (`<!-- _class: klausur -->`) bleiben über den Vorlesungs-Fluss **verstreut** — sie werden im pädagogischen Kontext erlebt, nicht als physischer Klausur-Abschnitt am Kapitelende gesammelt. Die Auto-Extraktion via `make klausur-223015b` fasst sie für die Prüfungs-Repetition zusammen, ohne die Vorlesungs-Reihenfolge zu verändern.
---
## Operative Lernziele pro Klausur-Block
### Block 1 — Datenfundamentale
- Studierende können den Wert einer Byte-Zahl in Binär, Dezimal und Hex erkennen und zuordnen, in welcher Schreibweise sie ihnen typischerweise begegnet (CSS-Farbcodes, Hex-Editor, Programmcode).
- Studierende können die Beziehung zwischen Bit, Byte, Nibble und Hex-Ziffer erklären.
- Studierende können nachvollziehen, warum ein deutscher Umlaut in UTF-8 mehr Speicher braucht als ein englischer Buchstabe und ein Emoji noch mehr.
- Studierende können in einem Hex-Dump die ersten Byte einer Datei als Format-Signatur erkennen und daraus das Dateiformat ableiten.
- Studierende können einordnen, warum eine als „1 TB" verkaufte SSD im Betriebssystem als „931 GB" erscheint.
### Block 2 — Vom Signal zum Byte
- Studierende können Abtastung und Quantisierung am Beispiel einer Audio-Aufnahme erklären.
- Studierende können die Größenordnung des Speicherbedarfs einer Audio-Aufnahme aus Abtastrate und Bittiefe abschätzen.
- Studierende können einordnen, warum CDs mit 44,1 kHz abgetastet werden und nicht mit weniger.
- Studierende können Aliasing als Phänomen erkennen — sowohl als Klang-Artefakt in alten MP3s als auch als Moiré-Muster auf Hemden im Fernsehen.
### Block 3 — Kompression: Prinzipien
- Studierende können verlustfreie und verlustbehaftete Kompression bei Text, Audio, Bild und Video unterscheiden.
- Studierende können an einem einfachen Muster zeigen, wie Lauflängenkodierung (RLE) Wiederholungen kompakter darstellt.
- Studierende können für ein Anwendungsszenario (Foto-Backup, Streaming, Code-Archiv) begründen, ob Lossless oder Lossy sinnvoller ist.
- Studierende können Psychoakustik und Psychovisualität als Grundlage einordnen, warum Lossy-Kompression überhaupt funktioniert.
### Block 4 — Bilder: Raster und Vektor
- Studierende können Raster- und Vektorgrafiken anhand von Skalierungsverhalten und typischen Anwendungen unterscheiden (Logo vs Foto).
- Studierende können die sechs Stationen der JPEG-Pipeline benennen und je in einem Satz erklären, was dort passiert (Farbraum → Subsampling → Blöcke → DCT → Quantisierung → Huffman).
- Studierende können erklären, was eine Quantisierungstabelle bei JPEG bewirkt und warum hohe Frequenzen zuerst geopfert werden.
- Studierende können für ein Bildanliegen (Logo, Foto, Screenshot, Icon, animierte Reaktion) das passende Format begründet auswählen.
- Studierende können einordnen, warum sich WebP schneller verbreitet hat als JPEG XL, obwohl JPEG XL technisch im Vorteil ist.
### Block 5 — Audio
- Studierende können den MP3-Trick (Maskierung, Hörschwelle) als gezieltes Auslassen für Menschen unhörbarer Anteile erklären.
- Studierende können die Spotify-Streaming-Bitrate-Stufen (Normal/Hoch/Sehr hoch) mit dem hörbaren Qualitätsunterschied und dem Datenvolumen verknüpfen.
- Studierende können für ein Audio-Anliegen (Spotify-Stream, Studio-Master, Sprachnachricht, Podcast) das passende Format begründet auswählen.
### Block 6 — Video
- Studierende können Container und Codec trennen: eine .mp4-Datei ist nur die Hülle, drinnen können H.264, H.265 oder AV1 stecken.
- Studierende können I-, P- und B-Frames auseinanderhalten und erklären, warum Video so viel besser komprimiert als eine Folge einzelner Bilder.
- Studierende können einordnen, warum AV1 als offener Standard gegen die Patent-Pools von H.265 entstanden ist (Alliance for Open Media).
- Studierende können die Größenordnung der Bitrate eines 4K-Streams gegen die übliche Internet-Bandbreite stellen.
### Block 7 — Speichermedien
- Studierende können HDD und SSD anhand von Mechanik, Latenz, Lebensdauer und Preis pro Terabyte unterscheiden.
- Studierende können für ein Anwendungsszenario (OS-Disk, Foto-Archiv, Server-Storage, Backup-Medium) HDD oder SSD begründet wählen.
- Studierende können die wichtigsten Filesystem-Familien (FAT32, exFAT, NTFS, APFS, ext4) ihren typischen Anwendungsbereichen zuordnen.
- Studierende können die 3-2-1-Backup-Regel erklären und auf den eigenen Foto-Archiv-Fall anwenden.
### Block 8 — Schnittstellen
- Studierende können bei einer USB-C-Verbindung zwischen Stecker, Kabel und Protokoll unterscheiden und erklären, warum nicht jedes USB-C-Kabel jeden USB-C-Anwendungsfall trägt.
- Studierende können für ein Anwendungsszenario (4K-Monitor anschließen, SD-Karte auslesen, Laptop laden) die passende Schnittstelle wählen.
- Studierende können HDMI, DisplayPort, Thunderbolt, Ethernet und WiFi anhand typischer Bandbreite und Anwendung einordnen.
### Block 9 — Distribution & Metadaten
- Studierende können das CDN-Prinzip am Beispiel Netflix Open Connect erklären (PoPs, Edge-Caching, geografische Verteilung).
- Studierende können bei einer REST-API erkennen, welche Operation (GET/POST/PUT/DELETE) zu welcher Absicht passt.
- Studierende können in EXIF- oder ID3-Metadaten enthaltene Informationen als Privacy-Risiko erkennen (McAfee-GPS-Fall, Blair-PDF-Fall).
- Studierende können Vendor-Lockin-Effekte proprietärer Formate (Adobe PSD, Apple .pages) als Risiko einordnen.
---
## Kapitel-Mapping (5 Kapitel)
| Kap | Titel | bedient Blöcke | Kern-Bogenkonzept |
|-----|-------|----------------|--------------------|
| **01** | Datenfundamentale + Signal zum Byte | Block 1 + 2 | Zahlen, Notation, Encoding, Sampling — die Atome |
| **02** | Kompression: Prinzipien und Pipelines | Block 3 | Redundanz vs Irrelevanz, RLE und Psycho-* |
| **03** | Inhalte: Bild, Audio, Video | Block 4 + 5 + 6 | Pipelines + Format-Wahl |
| **04** | Speicher und Schnittstellen | Block 7 + 8 | Wie Bytes physikalisch existieren und reisen |
| **05** | Distribution und Metadaten | Block 9 | Wie Bytes zur Endnutzerin kommen, was sie verraten |
---
## Validierungs-Status
- [x] Pro Block 3–5 Vorschläge
- [x] Default-Ambitionslevel: Verstehen/Unterscheiden, nicht Berechnen
- [x] Anker im Studierenden-Alltag wo sinnvoll
- [ ] Dozent-Review und Lock
- [ ] Phase 2: Folien-Skelett pro Kapitel
-131
View File
@@ -1,131 +0,0 @@
# Kapitel 1 — Datenfundamentale + Signal zum Byte
**Bedient Klausur-Blöcke:** 1 (Datenfundamentale) + 2 (Vom Signal zum Byte)
**Slide-Budget:** ~40 (90-min-Termin)
## Bogen
Eine Stunde, eine Frage: **„Was steckt in einer Datei, und wie kommt es da rein?"**
1. Wir öffnen mit dem Alltag: Foto, Sprachnachricht, PDF. Drei vertraute Dinge — alle haben dasselbe Innenleben.
2. Wir machen eine Datei roh auf (Hex-Editor) und sehen: Zahlen. Nichts als Zahlen.
3. Wir lernen die Zahlen lesen (Bit/Byte/Hex als drei Schreibweisen einer Sache).
4. Wir lernen, was die Zahlen *bedeuten* (ASCII → Unicode → Magic Numbers).
5. Pivot: aber wie kommen die Zahlen überhaupt in die Datei? Wenn man ein Foto macht, eine Stimme aufnimmt — Signal aus der Welt → Zahl.
6. Sampling und Quantisierung — die zwei Schritte, die jedes Signal digitalisieren.
7. Rechnung am CD-Beispiel, Nyquist-Theorem als Begründung warum gerade 44,1 kHz.
8. Aliasing als „was schiefgehen kann" — Audio-Knack und Moiré als gleiches Phänomen in zwei Modalitäten.
## Advance Organizer (Eröffnungs-Folie, NEU)
Visuelles Schema, das den ganzen Bogen zeigt — keine konkrete Datei, sondern die Bewegung:
```
Welt (analog) Datei (Byte-Strom) Mensch (Bedeutung)
╲ ╱╲ ╱
╲ Sampling + ╱ ╲ Notation (Hex) ╱
╲ Quantisierung ╱ ╲ Encoding (ASCII/UTF-8) ╱
╲ ╱ ╲ Format (Magic Numbers) ╱
▼ ▼ ▼ ▼
000101001001010001001110010100100111100100...
```
Aussage: dieses Kapitel überbrückt zwei Richtungen — *rein* (analog → digital) und *raus* (digital → bedeutsam). Beide treffen sich am Byte.
→ neue Demo-Datei: `docs/223015b/assets/demos/kap01-advance-organizer.html`
## Folien-Skelett
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 1 | Cover | Kapitel 1 — Datenfundamentale | — | — | reuse cover |
| 2 | Lead | Was steckt in einer Datei? | Kapitel-Hook | Foto · Sprachnachricht · PDF | NEU collage |
| 3 | Inhalt | Drei Dateien — dasselbe Innenleben | Hook | derselbe Trio | NEU mit Hex-Preview |
| 4 | Advance Organizer | Welt → Datei → Bedeutung | Roter Faden | — | **NEU kap01-advance-organizer** |
| 5 | Demo | WTF!? Rohe Bytes einer PNG-Datei | Schock-Hook | — | reuse matrix-code bg |
| 6 | Inhalt | Eine Datei ist ein Byte-Strom | L1.2 | — | — |
| 7 | Inhalt | Was ist ein Byte? 8 Bit, 256 Zustände | L1.2 | — | reuse why-8-bit |
| 8 | Inhalt | Drei Schreibweisen, eine Zahl | L1.1 | — | reuse byte-fuer-byte |
| 9 | Demo | Byte → Nibble → Hex | L1.1, L1.2 | — | reuse byte-nibble-hex |
| 10 | Demo | Hex ↔ Dezimal-Tabelle | L1.1 | — | reuse hex-dec-table |
| 11 | Inhalt | Lesbarkeit: 01010000 vs 50 | L1.1 | CSS-Farbe `#FF5733` | — |
| 12 | Inhalt | Wo trifft man Hex im Alltag | L1.1 | CSS · MAC · Errorcode · Unicode | reuse hex-im-alltag-table |
| 13 | Demo | Bin/Hex/ASCII parallel | L1.1, L1.3 | — | reuse byte-flow |
| 14 | Demo | 8 Byte einer PNG, drei Sichten | L1.3, L1.4 | — | reuse three-views |
| 15 | Lead | Was bedeutet die Zahl 80? | Übergang zu Encoding | — | — |
| 16 | Inhalt | ASCII (1963, 7 Bit, 128 Zeichen) | L1.3 | — | reuse ascii-table |
| 17 | Inhalt | ASCII reicht für Englisch — aber? | L1.3 | ä, é, 中, 🌸 | — |
| 18 | Inhalt | Unicode + UTF-8 (1991, variable Länge) | L1.3 | — | — |
| 19 | Demo | Byte zählen: 29 Zeichen, 42 Byte | L1.3 | „Hello·🌸·こんにちは" | reuse byte-zählen-tabelle |
| 20 | Lead | Wie weiß der Computer was das ist? | Übergang zu Magic | — | — |
| 21 | Inhalt | Magic Numbers — erste Byte verraten Format | L1.4 | 89 50 4E 47 = PNG | reuse what-the-hex |
| 22 | Demo | Echte Datei im Hex-Editor | L1.4 | hexed.it im Browser | reuse hex-code |
| 23 | Demo | Zoom: ein Byte „P" | L1.1, L1.4 | — | reuse 8bit-P-character |
| 24 | Selbstlernen | hex-Datei identifizieren | L1.4 | — | bestehende Übung |
| 25 | Inhalt | KB vs KiB — warum 931 GB? | L1.5 | 1-TB-SSD-Etikett | NEU diagram |
| 26 | Inhalt | Dateneinheiten-Übersicht | L1.5 | — | reuse dateneinheiten-table |
| 27 | **Pivot** | Aber wie kommen die Bytes da rein? | Strang-Wechsel | — | NEU split-pivot-folie |
| 28 | Inhalt | Analog vs Digital — Druckwelle als Beispiel | L2.1 | — | reuse druckwelle |
| 29 | Inhalt | Sampling: Wie oft messen wir? | L2.1 | — | reuse sampling |
| 30 | Demo | Sampling-Animation | L2.1 | — | reuse sampling-grid |
| 31 | Inhalt | Quantisierung: Wie genau? | L2.1 | — | reuse quantisierung |
| 32 | Demo | Quantisierungsstufen | L2.1 | — | reuse quantisierung-stufen |
| 33 | Inhalt | Datenrate = Abtastrate × Bittiefe × Kanäle | L2.2 | CD-Audio · Spotify | — |
| 34 | Inhalt | CD-Audio: 44,1 kHz × 16 bit × 2 = 1,4 Mbit/s | L2.2 | — | — |
| 35 | Inhalt | Nyquist-Theorem | L2.3 | — | NEU nyquist-diagram |
| 36 | Inhalt | Warum gerade 44,1 kHz | L2.3 | — | — |
| 37 | Inhalt | Aliasing — wenn Sampling zu grob | L2.4 | Klang-Knack · Moiré | NEU aliasing-paar (audio + bild) |
| 38 | Demo | Aliasing live: Spotify-Bitrate-Vergleich | L2.4 | Spotify-Stream-Setting | NEU oder reuse |
| 39 | Selbstlernen | Audacity-Sample-Rate-Vergleich | L2.1, L2.4 | — | bestehende Übung |
| 40 | Zusammenfassung | Was wir in 90 Minuten gelernt haben | alle | — | NEU summary-organizer |
## Selbstlernen Übungen (mindestens eine, hier zwei)
- **Übung 1 (~10 min):** In hexed.it eine vom Dozenten bereitgestellte Datei ohne Endung öffnen, anhand der ersten Byte das Format identifizieren. Spielt L1.4 (Magic Numbers).
- **Übung 2 (~10 min):** In Audacity eine kurze Aufnahme machen, dann auf 8 kHz / 22 kHz / 44,1 kHz resamplen und hören. Spielt L2.1, L2.3, L2.4.
## Streichungs-Liste (Folien aus dem aktuellen Stand, die wegfallen)
Aus dem aktuellen `01-grundlagen-text-audio.md` (~120 Slides) werden in der neuen Version Folgendes gestrichen oder verlagert:
- **Datenwachstum der Menschheit / Zettabyte** — gehört konzeptuell in Kap 0 (Intro/Motivation), nicht in Datenfundamentale
- **Bandbreite-Mathematik-Slides** (3 Stück) — gehört in Speicher/Schnittstellen-Kapitel, nicht hier
- **Upload Flaschenhals** — gehört in Speicher-/Schnittstellen-Kapitel
- **Kompressionsraten Tabelle** + **Album-MB-Größe** + **Artemis-Slide** — gehört in Kapitel 2 (Kompression), nicht in Fundamentale
- **„Verlustfreie/Verlustbehaftete Kompression"-Folien** (3 Slides + Vergleichstabelle) — gehört in Kapitel 2
- **Vertiefungs-Folie Kompression mit Shannon-Entropy** — Klausurirrelevant, raus
- **Bit/Byte Verwirrung (Mbit/s)** — gehört in Speicher/Schnittstellen
- **CD-Audio Vertiefung** — eindampfen oder als Speaker-Note in Folie 34
- **AI-generierte Inhalte 2025** — out (Zukunfts-Thema, per D2 gelockt)
- **Bilder-Aspekt Folien (Pixel-Berechnungen)** — gehört in Kapitel 3 (Bilder)
- **„Lossless für 35 Sek = 10 MB"-Audio-Beispiele** — eindampfen
- **Diverse Vertiefungen die Hauptfolien wörtlich wiederholen** — alle raus (Mayer Redundancy)
Geschätzte Reduktion: 120 → 40 Slides (-67%).
## Visualisierungen — neu zu bauen
| Demo-Datei | Was zeigt sie | Stil-Referenz |
|------------|---------------|---------------|
| `kap01-advance-organizer.html` | Welt → Datei → Bedeutung Schema | `three-views.html` |
| `kb-vs-kib.html` | „1 TB" verkauft vs „931 GB" angezeigt | neue Tabelle + Erklärung |
| `nyquist-diagram.html` | Sampling-Frequenz vs Signal-Frequenz | wissenschaftliches Diagramm |
| `aliasing-paar.html` | Aliasing in Audio + Moiré in Bild parallel | zweispaltig |
| `pivot-signal-zu-byte.html` | „aber wie kommen die Bytes rein?" — Übergangsbild | NEU |
| `summary-organizer.html` | Zusammenfassung am Kapitel-Ende | reuse advance-organizer-Stil, alle Konzepte erfüllt |
Reuse-Demos (alle in `slides/223015b/assets/demos/`):
- byte-fuer-byte, byte-nibble-hex, hex-dec-table, byte-flow, three-views
- why-8-bit, ascii-table-colored, hex-code, 8bit-P-character
## Validierungs-Status
- [x] Bogen formuliert (eine Stunde, eine Frage)
- [x] Advance Organizer skizziert
- [x] Folien-Skelett mit Lernziel-Bezug pro Folie
- [x] Mindestens ein Selbstlernen (hier zwei)
- [x] Streichungsliste mit Begründungen
- [x] Visualisierungs-TODO mit Reuse-Markierung
- [ ] Dozent-Review und Lock
- [ ] Phase 3: Visualisierungen bauen
- [ ] Phase 4: Folien schreiben
-100
View File
@@ -1,100 +0,0 @@
# Kapitel 2 — Kompression: Prinzipien und Pipelines
**Bedient Klausur-Block:** 3 (Kompression: Prinzipien)
**Slide-Budget:** ~22 (90-min-Termin, das kürzeste Kapitel — Vorbereitung für Kapitel 3)
## Bogen
Eine Stunde, eine Frage: **„Wie machen wir Daten kleiner — und was darf dabei verloren gehen?"**
1. Wir öffnen mit dem Alltag: WhatsApp-Bild vs Original-Foto (Dateigröße-Schock).
2. Zwei fundamental verschiedene Wege werden eingeführt: Redundanz raus (verlustfrei) vs Irrelevanz raus (verlustbehaftet).
3. Verlustfrei wird an RLE durchgespielt — manuell, am Whiteboard, anfassbar.
4. Verlustbehaftet wirft die Frage auf: was darf verloren gehen? Antwort kommt aus der Wahrnehmungsforschung — Psychoakustik (Audio), Psychovisualität (Bild). Hier nur das Prinzip, die Pipelines folgen in Kap 3.
5. Entscheidungsmatrix für den Alltag: Foto-Archiv (Lossless), Streaming (Lossy), Code-Repo (Lossless), Backup (kommt drauf an).
6. Selbstlernen: ZIP-Test mit drei Dateitypen, der zeigt warum schon-komprimierte Dateien nicht weiter komprimieren.
## Advance Organizer
```
Daten sind unhandlich.
│
┌───────────┴───────────┐
▼ ▼
VERLUSTFREI VERLUSTBEHAFTET
Redundanz raus Irrelevanz raus
(umkehrbar) (nicht umkehrbar)
│ │
RLE · Huffman Psychoakustik (MP3)
ZIP · PNG · FLAC Psychovisualität (JPEG)
│ │
└───────────┬───────────┘
▼
Wann was?
(Entscheidungsmatrix)
```
→ neue Demo-Datei: `kap02-kompression-bogen.html`
## Folien-Skelett
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 1 | Cover | Kapitel 2 — Kompression | — | — | reuse cover |
| 2 | Lead | Daten sind unhandlich | Hook | WhatsApp · Spotify · ZIP | — |
| 3 | Inhalt | Foto-Größenschock | Hook | Original 12 MB → WhatsApp 200 KB | NEU vergleich |
| 4 | Advance Organizer | Zwei Wege der Kompression | Roter Faden | — | **NEU kap02-bogen** |
| 5 | Lead | Verlustfrei (Lossless) | L3.1 | — | — |
| 6 | Inhalt | Prinzip: Redundanz raus, umkehrbar | L3.1 | — | — |
| 7 | Demo | RLE manuell: AAAAABBBCCCCCCCC → 5A3B8C | L3.2 | — | reuse RLE-Beispiel |
| 8 | Inhalt | Wo wird Lossless eingesetzt | L3.1, L3.3 | ZIP · PNG · FLAC · RAW | — |
| 9 | Inhalt | LV-Tasche-Analogie: Original vs Fälschung | L3.1 | — | reuse lv-original-vs-fake |
| 10 | Lead | Verlustbehaftet (Lossy) | L3.1 | — | — |
| 11 | Inhalt | Prinzip: Irrelevanz raus, nicht umkehrbar | L3.1, L3.4 | Spotify-Stream | — |
| 12 | Inhalt | Was nimmt ein Mensch nicht wahr? | L3.4 | — | — |
| 13 | Inhalt | Psychoakustik: Maskierung, Hörschwelle | L3.4 | Vorgriff auf MP3 | NEU psychoakustik-grafik |
| 14 | Inhalt | Psychovisualität: Luminanz vor Chrominanz | L3.4 | Vorgriff auf JPEG | NEU psychovisualität-grafik |
| 15 | Inhalt | Wo wird Lossy eingesetzt | L3.1, L3.3 | MP3 · JPEG · H.264 · WebP | — |
| 16 | Klausur | Vergleichstabelle Lossless vs Lossy | L3.1, L3.3 | — | reuse vergleichstabelle |
| 17 | Demo | Bild in 100% / 50% / 10% Qualität | L3.3 | — | reuse jpeg-qualität-vergleich |
| 18 | Inhalt | Kompressionsraten in der Praxis | L3.1 | Song 10× · Foto 12× · 4K-Video 120× | reuse kompressionsraten-tabelle |
| 19 | Inhalt | Wann verwendet man was? | L3.3 | Foto-Archiv · Stream · Code · Backup | NEU entscheidungsmatrix |
| 20 | Selbstlernen | ZIP-Test: txt vs bmp vs jpeg | L3.1, L3.2, L3.3 | — | — |
| 21 | Inhalt | Warum komprimiert ZIP-auf-JPEG nicht mehr | L3.1, L3.2 | — | — |
| 22 | Zusammenfassung | Was wir gelernt haben | alle B3 | — | NEU summary |
## Selbstlernen Übung
- **ZIP-Test (~10 min):** Drei Dateien gleicher Originalgröße zippen: (a) Textdatei mit wiederholten Mustern, (b) unkomprimierte BMP, (c) JPEG. Vergleich der ZIP-Größen liefert die Aha-Erkenntnis: schon-komprimierte Dateien lassen sich nicht weiter komprimieren (Entropie-Grenze ohne Mathematik).
## Streichungs-Liste (Verlagerungen aus Kap 1)
Aktuell stehen diese Inhalte in `01-grundlagen-text-audio.md` und werden hierher verschoben (nicht erfunden):
- Verlustfreie/Verlustbehaftete Kompression (3 Slides + Vergleichstabelle)
- Kompressionsraten-in-der-Praxis-Tabelle
- LV-Original-vs-Fake-Bridge-Folie
Diese Vertiefungen entfallen:
- Vertiefungs-Slide „Claude Shannon Entropie"-Math — Klausurirrelevant, raus
- „Cola-Sirup für Sodastream"-Analogie-Sammlung in Speaker-Notes — Auswahl reduzieren auf max 2 Analogien
## Visualisierungen — neu zu bauen
| Demo-Datei | Was zeigt sie |
|------------|---------------|
| `kap02-bogen.html` | Advance Organizer für Kompression |
| `psychoakustik-grafik.html` | Maskierung visualisieren (lauter Ton überdeckt leisen) |
| `psychovisualität-grafik.html` | Luminanz-Detail vs Chrominanz-Detail nebeneinander |
| `entscheidungsmatrix-kompression.html` | Wann-was-Tabelle (Archiv/Stream/Code/Backup) |
| `summary-kap02.html` | Zusammenfassung |
Reuse: lv-original-vs-fake, RLE-Beispiel, kompressionsraten-tabelle, vergleichstabelle (alle in Bestand).
## Validierungs-Status
- [x] Bogen formuliert
- [x] Advance Organizer skizziert
- [x] Folien-Skelett mit Lernziel-Bezug
- [x] Selbstlernen geplant
- [x] Verlagerungen aus Kap 1 dokumentiert
- [ ] Dozent-Review und Lock
@@ -1,173 +0,0 @@
# Kapitel 3 — Inhalte: Bild, Audio, Video
**Bedient Klausur-Blöcke:** 4 (Bilder) + 5 (Audio) + 6 (Video)
**Slide-Budget:** ~49 (das umfangreichste Kapitel, ggf. 2 Vorlesungstermine)
## Bogen
Eine längere Sitzung (oder zwei), eine Linie: **„Drei Modalitäten — Bild, Audio, Video — drei Pipelines, drei Format-Politiken. Was passiert technisch und was politisch, und wie wählt man im Alltag?"**
1. Wir öffnen damit, dass *alle drei* Modalitäten Lossy-Kompression nutzen — und dass diese Lossy-Kompression nur funktioniert weil sie Wahrnehmungs-Lücken ausnutzt. Brücke zu Kapitel 2 (Psychoakustik/Psychovisualität).
2. **Bilder** zuerst — am stärksten visualisierbar, JPEG-Pipeline ist die didaktische Königsdisziplin. Alle 6 Schritte durchspielen.
3. **Audio** als zweite Modalität — MP3-Trick konkret, Spotify-Stufen am Handy, Format-Wahl-Matrix.
4. **Video** als „Bild + Zeit". Container/Codec-Trennung als entscheidendes Konzept. I/P/B-Frames. Patent-Politik (AV1 vs HEVC) als Industrie-Geschichte.
## Advance Organizer
```
Wahrnehmung als Hebel (aus Kap 2)
│
┌───────────┼───────────┐
▼ ▼ ▼
BILD AUDIO VIDEO
│ │ │
Raster/Vektor Sampling Container
JPEG-Pipeline MP3-Trick + Codec
Format-Wahl Format-Wahl I/P/B
│ │ │
└───────────┴───────────┘
│
Patent · Adoption · Politik
(JPEG XL · WebP · AV1)
```
→ neue Demo-Datei: `kap03-modalitäten-bogen.html`
## Folien-Skelett
### Eröffnung (3 Slides)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 1 | Cover | Kapitel 3 — Inhalte: Bild, Audio, Video | — | — | reuse |
| 2 | Lead | Drei Modalitäten, ein Prinzip | Hook | Instagram · Spotify · YouTube | NEU collage |
| 3 | Advance Organizer | Wahrnehmung als gemeinsamer Hebel | Roter Faden | — | **NEU kap03-bogen** |
### Sub-Sektion A — Bilder (18 Slides, bedient Block 4)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 4 | Lead | Bilder | — | — | — |
| 5 | Inhalt | Pixel — ein Bild als Zahlen-Gitter | L4.1 | Smartphone-Foto-Auflösung | NEU pixel-gitter |
| 6 | Inhalt | Rastergrafik: viele Pixel | L4.1 | Smartphone-Foto | NEU raster-zoom |
| 7 | Inhalt | Vektorgrafik: mathematische Anweisungen | L4.1 | Logo · Icon | NEU vektor-skalierung |
| 8 | Klausur | Raster vs Vektor (Tabelle + Skalierung) | L4.1 | — | reuse vergleichs-tabelle |
| 9 | Inhalt | Wann welches? | L4.1, L4.4 | Logo (V), Foto (R), Icon (V) | — |
| 10 | Lead | JPEG: das Foto-Workhorse seit 1992 | — | — | — |
| 11 | Inhalt | JPEG-Pipeline-Übersicht (6 Schritte) | L4.2 | — | NEU pipeline-übersicht |
| 12 | Inhalt | Schritt 1: RGB → Y'CbCr (Farbraumkonversion) | L4.2 | — | reuse yuv-zerlegung |
| 13 | Inhalt | Schritt 2: Chroma-Subsampling 4:2:0 | L4.2 | — | NEU chroma-subsampling-grafik |
| 14 | Inhalt | Schritt 3: 8×8 Blöcke | L4.2 | — | NEU block-aufteilung |
| 15 | Inhalt | Schritt 4: DCT (Diskrete Kosinus-Transformation) | L4.2, L4.3 | — | NEU dct-frequenzraum |
| 16 | Inhalt | Schritt 5: Quantisierung | L4.2, L4.3 | — | NEU quantisierungstabelle |
| 17 | Inhalt | Schritt 6: Huffman-Coding | L4.2 | — | NEU huffman-zip |
| 18 | Klausur | Die 6 Schritte als Memo-Liste | L4.2 | — | NEU |
| 19 | Demo | JPEG-Artefakte sichtbar machen | L4.2, L4.3 | Squoosh im Browser | reuse jpeg-artifacts |
| 20 | Lead | Andere Bildformate | — | — | — |
| 21 | Inhalt | PNG · GIF · WebP · AVIF · SVG | L4.4 | — | reuse format-grid |
| 22 | Klausur | Wann-welches-Format-Matrix | L4.4 | Logo · Foto · Screenshot · Icon · Animation | NEU entscheidungsmatrix |
| 23 | Inhalt | Patent-Politik: warum WebP > JPEG XL | L4.5 | Chrome-Adoption · Apple | NEU patent-zeitleiste |
### Sub-Sektion B — Audio (8 Slides, bedient Block 5)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 24 | Lead | Audio | — | — | — |
| 25 | Inhalt | Sampling + Bittiefe Recap | L5.1 | aus Kap 1 | — |
| 26 | Inhalt | MP3-Trick: Maskierung | L5.1 | — | NEU maskierung-grafik |
| 27 | Inhalt | MP3-Trick: Hörschwelle | L5.1 | — | NEU hörschwelle-grafik |
| 28 | Inhalt | Bitrate-Stufen 128/192/320 kbit/s | L5.2 | Spotify-Setting | NEU bitrate-vergleich |
| 29 | Inhalt | Audio-Format-Landschaft | L5.3 | WAV · MP3 · FLAC · AAC · OGG · Opus | NEU format-tabelle |
| 30 | Klausur | Format-Wahl: Stream · Master · Sprachnachricht · Podcast | L5.3 | — | NEU entscheidungsmatrix-audio |
| 31 | Demo | Spotify-Stream-Bitrate live anhören | L5.2 | Spotify-App | — |
### Sub-Sektion C — Video (14 Slides, bedient Block 6)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 32 | Lead | Video — Bild plus Zeit | — | — | — |
| 33 | Inhalt | Pixel × Pixel × Hz = Datenflut | L6.4 | 4K@60fps roh | NEU datenflut-rechnung |
| 34 | Klausur | **Container ≠ Codec** | L6.1 | .mp4 öffnen | NEU container-codec-trennung |
| 35 | Inhalt | Was ist ein Container | L6.1 | MP4 · MKV · WebM | NEU container-anatomie |
| 36 | Inhalt | Was ist ein Codec | L6.1 | H.264 · H.265 · VP9 · AV1 | — |
| 37 | Inhalt | Inter-Frame-Kompression — die zentrale Idee | L6.2 | — | NEU inter-frame-diagram |
| 38 | Klausur | I- · P- · B-Frames | L6.2 | — | reuse IPB-frame-diagram |
| 39 | Inhalt | Motion Compensation | L6.2 | — | NEU motion-compensation |
| 40 | Lead | Die Codec-Landschaft | — | — | — |
| 41 | Inhalt | H.264 / AVC — der Workhorse | L6.3 | YouTube · Zoom | reuse h264-folie |
| 42 | Inhalt | H.265 / HEVC — Patent-Chaos | L6.3 | Apple-Adoption | reuse h265-folie |
| 43 | Inhalt | VP9 + AV1 — Antwort von Google + Alliance | L6.3 | YouTube-Streaming | reuse av1-folie |
| 44 | Klausur | Patent vs Open: warum AV1 | L6.3 | Netflix · YouTube · Twitch | NEU patent-vergleich |
| 45 | Inhalt | 4K-Stream-Bitrate vs Heim-Bandbreite | L6.4 | 25 Mbit/s eigener Anschluss | NEU bandbreite-vergleich |
### Selbstlernen + Zusammenfassung (4 Slides)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 46 | Selbstlernen | Bild in Squoosh.app komprimieren | L4.2, L4.4 | Squoosh im Browser | — |
| 47 | Selbstlernen | MP3 vs FLAC unterscheidbar? | L5.1, L5.2 | Spotify HiFi-Test | — |
| 48 | Selbstlernen | mediainfo auf eine Videodatei | L6.1, L6.2 | mediainfo CLI | — |
| 49 | Zusammenfassung | Drei Modalitäten, gleiches Prinzip | alle | — | NEU summary |
## Streichungs-Liste
Aus dem aktuellen `02-bild-audio-video.md` (~70 Slides):
- Diverse Vertiefungs-Slides die Hauptfolien wörtlich wiederholen — raus (Mayer Redundancy)
- DCT-Math-Tiefe in einer eigenen Folie — eindampfen auf Schritt 4 (Slide 15)
- Doppelte „Container vs Codec"-Folien — eine reicht (Slide 34)
- AV1-Emmy-Award als eigene Folie — als Speaker-Note in Slide 43
Aus dem aktuellen `01-grundlagen-text-audio.md` werden Bilder/Audio/Video-Folien hierher verschoben:
- MP3-Psychoakustik-Slides
- Sampling-Recap nur als Vorgriff (Recap statt Vollerklärung — die kam in Kap 1)
## Visualisierungen — neu zu bauen
| Demo-Datei | Was zeigt sie |
|------------|---------------|
| `kap03-modalitäten-bogen.html` | Advance Organizer drei Modalitäten |
| `pixel-gitter.html` | Bild als Zahlen-Gitter |
| `raster-zoom.html` | Rasterbild beim Skalieren pixelig |
| `vektor-skalierung.html` | Vektorbild bleibt scharf |
| `pipeline-übersicht.html` | JPEG 6 Schritte als Pipeline |
| `chroma-subsampling-grafik.html` | 4:4:4 vs 4:2:0 visuell |
| `dct-frequenzraum.html` | Bildblock im Frequenzraum |
| `quantisierungstabelle.html` | Tabelle + Effekt |
| `huffman-zip.html` | Huffman als finale Kompression |
| `entscheidungsmatrix-bildformate.html` | Wann-welches-Bildformat |
| `patent-zeitleiste.html` | JPEG XL vs WebP Adoption |
| `maskierung-grafik.html` | Lauter-Ton-überdeckt-leisen |
| `hörschwelle-grafik.html` | Hörschwelle im Frequenzraum |
| `bitrate-vergleich.html` | 128/192/320 kbit/s mit Größenvergleich |
| `format-tabelle-audio.html` | WAV/MP3/FLAC/AAC/OGG/Opus |
| `entscheidungsmatrix-audio.html` | Wann-welches-Audio-Format |
| `datenflut-rechnung.html` | 4K@60fps roh: Datenrate |
| `container-codec-trennung.html` | MP4-Hülle, drinnen verschiedene Codecs |
| `container-anatomie.html` | MP4-Container-Aufbau |
| `inter-frame-diagram.html` | Inter-Frame als Konzept |
| `motion-compensation.html` | Block aus vorigem Frame verschieben |
| `patent-vergleich.html` | H.264/H.265/AV1 Patent-Politik |
| `bandbreite-vergleich.html` | 4K-Bitrate vs Internet-Bandbreite |
| `summary-kap03.html` | Zusammenfassung |
Reuse: yuv-zerlegung, jpeg-artifacts, format-grid, IPB-frame-diagram, h264/h265/av1-Slides, vergleichs-tabelle (alle Bestand in `slides/223015b/assets/`).
## Hinweis Zeitlich
50 Slides für 90 Min ist eng (~1,8 min pro Slide inkl Erklärung). Optionen:
- **Variante A:** Als zwei Termine planen (Termin 1: Bilder, Termin 2: Audio+Video). Sauberster pädagogischer Schnitt.
- **Variante B:** In einem Termin durchziehen, Selbstlernens als Hausaufgabe.
- **Variante C:** Audio kürzen (Sub-Sektion B als reduzierte Vertiefungs-Stunde mit Verweis auf Kap 1).
Entscheidung Dozent.
## Validierungs-Status
- [x] Bogen formuliert
- [x] Advance Organizer skizziert
- [x] Folien-Skelett (3 Sub-Sektionen)
- [x] Selbstlernen in jeder Sub-Sektion
- [x] Streichungs-Liste
- [x] Visualisierungs-TODO
- [x] Zeit-Hinweis für Dozent
- [ ] Dozent-Review und Lock
@@ -1,125 +0,0 @@
# Kapitel 4 — Speicher und Schnittstellen
**Bedient Klausur-Blöcke:** 7 (Speichermedien) + 8 (Schnittstellen)
**Slide-Budget:** ~30 (90-min-Termin)
## Bogen
Eine Stunde, eine Frage: **„Wo wohnen die Bytes — und wie reisen sie zwischen Geräten?"**
1. Wir öffnen mit dem eigenen Setup: Laptop hat SSD, Server hat HDDs, Handy hat Flash, externe Disk steht im Schrank. Jedes Medium löst ein anderes Problem — und alle haben Tradeoffs.
2. **HDD und SSD** technisch ausgepackt: Mechanik vs Flash-Zellen, Latenz, Lebensdauer, Preis/TB. Entscheidungsmatrix.
3. **Filesystems** als die Sprache, in der ein Speichermedium organisiert wird. FAT32 / NTFS / APFS / ext4 — wann was. USB-Stick-FAT32-Limit als Alltagsproblem.
4. **Backup** als Praxis: 3-2-1-Regel am eigenen Foto-Archiv durchgespielt.
5. **Pivot zu Schnittstellen** — wie kommen die Bytes von einem Medium zum anderen?
6. **USB-C-Chaos** als zentrales Berührungs-Phänomen — drei separate Achsen (Stecker, Kabel, Protokoll) entwirren. Das ist die Aha-Folie.
7. **HDMI · DisplayPort · Thunderbolt · Ethernet · WiFi** anhand Bandbreite und typischer Anwendung einordnen.
## Advance Organizer
```
Bytes wohnen + reisen
│
┌───────────┴───────────┐
▼ ▼
WO? Speicher WIE? Schnittstellen
│ │
HDD · SSD · Flash USB-C · HDMI · DP
Filesystems Thunderbolt
Backup 3-2-1 Ethernet · WiFi
│ │
└───────────┬───────────┘
▼
Anwendungs-Wahl
```
→ neue Demo-Datei: `kap04-bogen.html`
## Folien-Skelett
### Eröffnung (3 Slides)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 1 | Cover | Kapitel 4 — Speicher und Schnittstellen | — | — | reuse |
| 2 | Lead | Wo wohnen die Bytes, wie reisen sie? | Hook | Eigenes Setup im Hörsaal | — |
| 3 | Advance Organizer | Wohnen + Reisen | Roter Faden | — | **NEU kap04-bogen** |
### Sub-Sektion A — Speichermedien (15 Slides, Block 7)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 4 | Lead | Speicher | — | — | — |
| 5 | Inhalt | HDD: Magnetscheibe, Mechanik | L7.1 | externe Backup-Platte | reuse hdd-internals |
| 6 | Inhalt | HDD: Spuren, Sektoren, Latenz | L7.1 | — | NEU hdd-anatomie |
| 7 | Inhalt | SSD: Flash-Zellen, keine Mechanik | L7.1 | Laptop-SSD | reuse ssd-internals |
| 8 | Inhalt | SSD: Schreibzyklen, Wear Leveling | L7.1 | — | NEU ssd-wear-leveling |
| 9 | Klausur | HDD vs SSD: Vergleichstabelle | L7.1 | — | reuse hdd-ssd-comparison |
| 10 | Klausur | Wann welches? Entscheidungsmatrix | L7.2 | OS-Disk · Foto-Archiv · Server · Backup | NEU entscheidungsmatrix-speicher |
| 11 | Lead | Filesystems | — | — | — |
| 12 | Inhalt | Was macht ein Filesystem? | L7.3 | USB-Stick formatieren | — |
| 13 | Inhalt | FAT32 / exFAT / NTFS / APFS / ext4 | L7.3 | „warum kann ich 5-GB-Datei nicht auf USB ziehen" | reuse filesystem-vergleich |
| 14 | Inhalt | Filesystem-Limits konkret | L7.3 | FAT32 4-GB-Grenze | NEU filesystem-limits |
| 15 | Lead | Backup — die unangenehme Pflicht | — | — | — |
| 16 | Inhalt | Pixar verlor Toy Story 2 fast | L7.4 | Pixar-Story | reuse backup-disaster |
| 17 | Klausur | Die 3-2-1-Regel | L7.4 | eigenes Foto-Archiv | reuse 3-2-1 |
| 18 | Inhalt | Backup-Typen: full · incremental · differential | L7.4 | — | NEU backup-typen |
### Sub-Sektion B — Schnittstellen (12 Slides, Block 8)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 19 | Pivot | Wie kommen Bytes von A nach B? | — | — | — |
| 20 | Lead | USB-C — das Berührungspunkt-Phänomen | L8.1 | „warum lädt mein Laptop am einen Port und am anderen nicht" | — |
| 21 | Klausur | **USB-C: drei separate Achsen** | L8.1 | — | NEU usb-c-drei-achsen |
| 22 | Inhalt | Achse 1: Stecker (mechanisch) | L8.1 | — | NEU |
| 23 | Inhalt | Achse 2: Kabel (was es kann) | L8.1 | Aldi-Kabel vs Apple-Kabel | NEU |
| 24 | Inhalt | Achse 3: Protokoll (was drüber läuft) | L8.1 | USB 2/3, Thunderbolt | NEU |
| 25 | Demo | „Warum lädt es nicht?" — drei Achsen prüfen | L8.1, L8.2 | — | — |
| 26 | Inhalt | HDMI: Video + Audio + HDCP | L8.3 | Monitor anschließen | — |
| 27 | Inhalt | DisplayPort: HDMI's offenes Pendant | L8.3 | — | — |
| 28 | Inhalt | Thunderbolt: Tunnel für alles | L8.3 | Mac mit Hub | — |
| 29 | Inhalt | Ethernet vs WiFi: Bandbreite + Latenz | L8.3 | Gaming · Streaming | NEU bandbreite-tabelle |
| 30 | Klausur | Entscheidungsmatrix Schnittstellen | L8.2 | 4K-Monitor · SD-Karte · Laden | NEU |
### Selbstlernen + Zusammenfassung (3 Slides)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 31 | Selbstlernen | eigenes Backup-Konzept aufschreiben | L7.4 | eigene Foto-Library | — |
| 32 | Selbstlernen | USB-C-Kabel-Check | L8.1, L8.2 | mitgebrachte Kabel | — |
| 33 | Zusammenfassung | Wohnen + Reisen — Recap | alle B7+B8 | — | NEU summary |
## Streichungs-Liste
Aus dem aktuellen `03-speichermedien-schnittstellen.md` (~38 Slides) bleibt der Stoff größtenteils, aber:
- Doppelte HDD/SSD-Vertiefungen — eine reicht (Slide 5+6, 7+8)
- Schnittstellen-Slides ohne Bezug (z.B. legacy-Kabel-Sammlung) — raus
- Wiederholte „latenz vs Throughput"-Slides — eindampfen
## Visualisierungen — neu zu bauen
| Demo-Datei | Was zeigt sie |
|------------|---------------|
| `kap04-bogen.html` | Advance Organizer Speicher+Schnittstellen |
| `hdd-anatomie.html` | HDD-Schnitt: Platter, Heads, Spuren |
| `ssd-wear-leveling.html` | SSD-Zellen, P/E-Zyklen, Wear Leveling |
| `entscheidungsmatrix-speicher.html` | HDD/SSD pro Anwendungsfall |
| `filesystem-limits.html` | Konkrete Limits (FAT32 4 GB, NTFS, ext4) |
| `backup-typen.html` | full · incremental · differential visuell |
| `usb-c-drei-achsen.html` | Stecker · Kabel · Protokoll als 3 unabhängige Dimensionen |
| `bandbreite-tabelle.html` | HDMI/DP/TB/Ethernet/WiFi mit Bandbreite + Latenz |
| `entscheidungsmatrix-schnittstellen.html` | Welche Schnittstelle für welchen Use Case |
| `summary-kap04.html` | Zusammenfassung |
Reuse: hdd-internals, ssd-internals, hdd-ssd-comparison, filesystem-vergleich, backup-disaster, 3-2-1 (alle Bestand).
## Validierungs-Status
- [x] Bogen mit klarem Pivot Speicher → Schnittstellen
- [x] Advance Organizer
- [x] Folien-Skelett (2 Sub-Sektionen + Selbstlernen)
- [x] USB-C-Aufklärung als zentraler Berührungspunkt
- [x] Streichungs-Liste
- [x] Visualisierungs-TODO
- [ ] Dozent-Review und Lock
@@ -1,125 +0,0 @@
# Kapitel 5 — Distribution und Metadaten
**Bedient Klausur-Block:** 9 (Distribution & Metadaten)
**Slide-Budget:** ~25 (90-min-Termin)
## Bogen
Eine Stunde, eine Frage: **„Wie kommen die Bytes von der Quelle zur Endnutzerin — und was verraten sie auf dem Weg?"**
1. Wir öffnen mit dem Alltag: Netflix-Stream startet in unter einer Sekunde. Wie kann das? Antwort: CDN.
2. **CDN-Prinzip** am Netflix-Open-Connect-Beispiel — PoPs, Edge-Caching, geografische Verteilung. Selbstlernen: DevTools-Tab Network einsehen.
3. **REST-APIs** als die Sprache, in der Apps Daten austauschen — GET/POST/PUT/DELETE auf Resources abgebildet. Tools: curl, Postman, JSONPlaceholder.
4. **Pivot zu Metadaten** — Dateien tragen nicht nur Inhalt, sondern auch versteckte Daten über sich selbst.
5. **EXIF in Fotos** — der McAfee-Fall (GPS verraten Aufenthaltsort). Privacy-Schock.
6. **ID3 in MP3s · PDF-Metadaten** — der Tony-Blair-Fall (PDF-Edits verraten Quellen).
7. **Vendor-Lockin** — Adobe PSD, Apple .pages: proprietäre Formate als Geschäftsmodell.
8. **Selbstlernen:** exiftool auf eigene Fotos werfen.
## Advance Organizer
```
Eine Datei reist und erzählt
│
┌───────────┴───────────┐
▼ ▼
WEG GEPÄCK
CDN Metadaten
REST-API EXIF · ID3 · PDF
│ │
Latenz · Caching Privacy-Leak
Open Connect Vendor-Lockin
│ │
└───────────┬───────────┘
▼
Aufmerksamkeit für
das was wir nicht
sehen
```
→ neue Demo-Datei: `kap05-bogen.html`
## Folien-Skelett
### Eröffnung (3 Slides)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 1 | Cover | Kapitel 5 — Distribution und Metadaten | — | — | reuse |
| 2 | Lead | Eine Datei reist — was passiert dabei? | Hook | Netflix-Stream startet sofort | — |
| 3 | Advance Organizer | Weg + Gepäck | Roter Faden | — | **NEU kap05-bogen** |
### Sub-Sektion A — Distribution (10 Slides, L9.1 + L9.2)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 4 | Lead | CDN — Content Delivery Network | — | — | — |
| 5 | Inhalt | Warum sind Streams überhaupt schnell? | L9.1 | YouTube-Latenz | NEU latenz-frage |
| 6 | Klausur | CDN-Prinzip: PoP + Edge-Caching | L9.1 | — | NEU cdn-prinzip |
| 7 | Inhalt | Netflix Open Connect: 15 % des Welt-Traffics | L9.1 | Netflix-App | reuse netflix-cdn |
| 8 | Demo | DevTools-Tab Network live | L9.1 | im Browser | — |
| 9 | Lead | REST-APIs | — | — | — |
| 10 | Inhalt | Was ist eine API? | L9.2 | Wetter-App holt Daten | NEU api-konzept |
| 11 | Klausur | GET · POST · PUT · DELETE | L9.2 | — | NEU rest-methods |
| 12 | Demo | JSONPlaceholder im Browser | L9.2 | jsonplaceholder.typicode.com | — |
| 13 | Inhalt | JSON als Datenformat | L9.2 | — | NEU json-anatomie |
### Sub-Sektion B — Metadaten (10 Slides, L9.3 + L9.4)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 14 | Pivot | Dateien tragen auch Gepäck | — | — | — |
| 15 | Inhalt | EXIF: was ein Foto über sich verrät | L9.3 | eigenes Smartphone-Foto | NEU exif-grafik |
| 16 | Klausur | Der John-McAfee-GPS-Fall | L9.3 | — | reuse mcafee-fall |
| 17 | Inhalt | Social-Media-EXIF-Stripping | L9.3 | Twitter · WhatsApp · Facebook | reuse social-stripping-tabelle |
| 18 | Inhalt | ID3 in MP3-Dateien | L9.3 | iTunes · MusicBrainz | — |
| 19 | Inhalt | PDF-Metadaten: Tony Blair 2003 | L9.3 | — | reuse blair-fall |
| 20 | Lead | Vendor-Lockin | — | — | — |
| 21 | Inhalt | Adobe PSD, INDD: das Geschäftsmodell | L9.4 | InDesign-Abo | NEU vendor-lockin-grafik |
| 22 | Inhalt | Apple .pages, .numbers, .keynote | L9.4 | iPad-User | — |
| 23 | Klausur | Vendor-Lockin als Risiko | L9.4 | „was wenn Adobe das Format ändert?" | — |
### Selbstlernen + Zusammenfassung (2 Slides)
| # | Typ | Titel/Kern | Lernziel | Berührungspunkt | Visualisierung |
|---|-----|-----------|---------|-----------------|----------------|
| 24 | Selbstlernen | exiftool auf eigene Fotos | L9.3 | Terminal · GUI | — |
| 25 | Zusammenfassung | Datei = Inhalt + Gepäck | alle B9 | — | NEU summary |
## Streichungs-Liste
Aus dem aktuellen `04-distribution-apis-zukunft.md` (~89 Slides) — **deutliche Reduktion**:
- BitTorrent/P2P-Detail-Slides — eindampfen auf eine Folie (Verweis als Kontext)
- IPFS — raus (nicht Klausurthema, kein Berührungspunkt)
- WebSockets, gRPC — raus (zu speziell, gehört in Internettechnik-Kurs 223015c)
- **Komplette Zukunfts-Sektion** (AI-Kompression, JPEG XL, DNA-Storage, holographische Speicher, Web3, 8K-VR, Cloud Gaming, Sustainability) — **raus** (per D2-Lock)
- Sneakernet/AWS-Snowball — raus (Klausurirrelevant)
- Diverse Vertiefungs-Slides ohne Bezug — raus
Geschätzte Reduktion: 89 → 25 Slides (-72%).
## Visualisierungen — neu zu bauen
| Demo-Datei | Was zeigt sie |
|------------|---------------|
| `kap05-bogen.html` | Advance Organizer Distribution+Metadaten |
| `latenz-frage.html` | Warum Streams schnell starten |
| `cdn-prinzip.html` | PoP + Edge-Caching Schema |
| `api-konzept.html` | App ↔ API ↔ Datenbank |
| `rest-methods.html` | GET/POST/PUT/DELETE auf Resource-Modell |
| `json-anatomie.html` | JSON-Beispiel mit Anmerkungen |
| `exif-grafik.html` | Foto mit eingeblendeten EXIF-Daten |
| `vendor-lockin-grafik.html` | Proprietäres Format als geschlossener Kreis |
| `summary-kap05.html` | Zusammenfassung |
Reuse: netflix-cdn, mcafee-fall, social-stripping-tabelle, blair-fall (alle Bestand).
## Validierungs-Status
- [x] Bogen mit Pivot Distribution → Metadaten
- [x] Advance Organizer
- [x] Folien-Skelett (2 Sub-Sektionen)
- [x] Privacy als zentraler Berührungspunkt (McAfee, Blair, Vendor-Lockin)
- [x] Aggressive Streichungs-Liste (89 → 25)
- [x] Visualisierungs-TODO
- [ ] Dozent-Review und Lock
-64
View File
@@ -1,64 +0,0 @@
# Refactor-Status · `refactor/didaktik-rewrite-2026`
Letzter Stand: 2026-05-14
## Was steht
### Foundation (Phasen 0–1)
- [x] `CLAUDE.md` · `README.md` · `AGENTS.md` mit didaktischem Fundament (auf `main`)
- [x] `docs/klausur-themen-2026.md` — 9 Klausur-Blöcke für 223015b gelockt (D1–D4 entschieden)
- [x] `docs/223015b-lernziele.md` — 33 operative Lernziele im Fließsatz-Eichmaß
- [x] `docs/223015b/01-…-bogen.md` bis `05-…-bogen.md` — 5 Kapitel-Skelette mit Folien-Plan, Streichungs-Liste, Demo-TODO
### Demos (Phase 3)
- [x] `kap02-eroeffner.png` — Lossless vs Lossy Wellenform-Vergleich (FLAC vs MP3 128)
- [x] `kap03-eroeffner.png` — Drei Modalitäten Datei-Größen-Tabelle (Bild/Audio/Video)
- [ ] **Kap 4 Eröffner** — Datei-Reise-Pfad (SSD → SATA → USB-C → HDMI → Display mit Datenraten)
- [ ] **Kap 5 Eröffner** — Foto mit EXIF-Overlay (Privacy-Reveal)
- [ ] Übrige ~40 unterstützende Demos pro Kapitel (siehe Visualisierungs-Listen in den Bogen-Docs)
### Erste 5 Eröffner-Versuche (verworfen)
Frühere Advance Organizer (`kap01-advance-organizer`, `kap02-bogen`, `kap03-modalitäten-bogen`, `kap04-bogen`, `kap05-bogen`) waren plump, gleichförmig und nicht erkenntnisgewinnend. Per Commit `1c8185b` gelöscht. Begründung: Topic-Boxen mit Pfeilen statt konkrete Daten in Transformation. Neue Strategie: pro Kapitel eigene Konkret-Komposition.
### Slides selbst (Phase 4)
- [ ] Komplett offen — die Bogen-Docs sind das Skelett, daraus werden in Phase 4 die Marp-Markdown-Files erzeugt
- Reihenfolge laut Plan: 01-fundamentale → 02-kompression → 03-inhalte → 04-speicher → 05-distribution
- Aktuelle Slide-Files (`01-grundlagen-text-audio.md` etc.) bleiben unangetastet bis die neuen Files stehen — kein „halb migriert"-Zustand
- Make-Pattern erlaubt es, die alten Files weiterzulaufen während neue gebaut werden (gleicher Build-Befehl)
## Wo weitermachen
**Empfohlene nächste Schritte (in dieser Reihenfolge):**
1. Kap 4 Eröffner-Demo bauen — Datei-Reise-Pfad
2. Kap 5 Eröffner-Demo bauen — EXIF-Overlay
3. Pro Kapitel die 3–4 wichtigsten neuen Demos (z.B. JPEG-Pipeline-Stationen, USB-C-drei-Achsen, CDN-Schema)
4. Phase 4 starten: Slide-MD-Files pro Kapitel schreiben, dabei existierende + neue Demos einbinden
5. Build-Test (`make build-223015b`), Render-Spot-Check
6. Erste Dozenten-Lesart durch Kapitel 1+2, justieren
7. Iterativ Kap 3–5
8. PR auf `main`, Review, Merge, Deploy
## Wichtige Konventionen
- **Keine Emojis** — auch nicht als Icons in HTML-Demos
- **„Bit"/„Byte" sind Maßwörter** — kein s-Plural („Bits"/„Bytes")
- **„Selbstlernen"**, nicht „Hands-On"
- **Klausur-Folien bleiben verstreut** — kein Sammelblock am Kapitel-Ende
- **Lernziele = Vorschläge** an den Dozenten, nicht gesetzte Anforderungen; Default Bloom-Level Verstehen
- **Render vor Layout-Aussage** — chromium-headless, dann PNG mit Read-Tool inspizieren
- **Advance Organizer = Erkenntnisgewinn**, nicht Topic-Boxen mit Pfeilen
## Branch-Operationen
```bash
# Stand sehen
git log --oneline refactor/didaktik-rewrite-2026
# Auf neuesten Stand bringen
git switch refactor/didaktik-rewrite-2026
git pull origin refactor/didaktik-rewrite-2026
# Plan-Datei
cat ~/.claude/plans/1-infinity-2-neue-wild-ember.md
```
-79
View File
@@ -1,79 +0,0 @@
# Klausur-Themen 2026 — HdM-Kurse
Status: **LOCK 223015b · Entwurf 223015c · pending dhbw**
Maßstab: Die drei Meta-Lernziele aus `CLAUDE.md` (gelernte Hilflosigkeit ablegen · Berührungspunkte schaffen · Gefühl für Technik). Jeder Klausur-Block muss mindestens eines davon nachweisbar bedienen.
---
## 223015b — Dateiformate, Schnittstellen, Speichermedien
**Kurs-Fokus:** Dateien und Inhalte
**Klausur-Format (bisher):** 90 Min digital, offene Fragen, kein Code
**Bestehende Klausur-Blöcke (Stand vor Rewrite):** J,K,L,M,N,O (6 Blöcke) — Grundbegriffe, Bild/Raster vs Vektor, JPEG, Bildformate PNG/GIF/WebP/SVG, Video-Kompression, Speicher/Schnittstellen
**Bestand ohne Klausur-Marker:** komplettes Kapitel 4 (Distribution, APIs, Metadaten, Zukunft — 89 Slides)
### Vorgeschlagene Klausur-Themen-Architektur (Tabula rasa, 9 Themen-Blöcke)
| # | Block | Kern | Was reinkommt | Berührungspunkt |
|---|---|---|---|---|
| 1 | **Datenfundamentale** | Daten als Zahlen begreifen | Bit/Byte/Hex, Dateneinheiten (KB vs KiB), Encoding (ASCII/Unicode/UTF-8), Magic Numbers | „warum spielt mein USB-Stick mit 32 GB nur 29 GB an" |
| 2 | **Vom Signal zum Byte** | Analog → Digital | Sampling, Quantisierung, Bittiefe, Abtastrate, Nyquist | „warum klingen alte MP3s blechern" |
| 3 | **Kompression: Prinzipien** | Redundanz vs Irrelevanz | Lossless vs Lossy, RLE/Huffman/LZ77 konzeptuell, Psychoakustik, Psychovisualität | WhatsApp-Bilder vs Original |
| 4 | **Bilder: Raster und Vektor** | Wann welches Bildformat | Raster vs Vektor, JPEG-Pipeline (6 Schritte), PNG/GIF/WebP/AVIF/SVG-Vergleich, Wann-Welches-Format | Instagram-Story-Qualitätsverlust, Logo skalieren |
| 5 | **Audio** | MP3-Trick verstehen | Sampling-Recap, MP3-Psychoakustik, WAV/MP3/FLAC/AAC, Spotify-Quality-Math | Spotify-Bitrate-Setting, AirPod-Streaming |
| 6 | **Video** | Container vs Codec | I/P/B-Frames, H.264/265/VP9/AV1 (Politik+Technik), Streaming-Bitrate | Netflix-Quality, YouTube-1080p vs 4K |
| 7 | **Speichermedien** | HDD vs SSD entscheiden | HDD-Mechanik, SSD-Zellen, Filesystems-Übersicht, 3-2-1-Backup | „warum ist meine SSD voll obwohl ich nichts habe" |
| 8 | **Schnittstellen** | USB-C-Chaos entwirren | USB-Generationen, USB-C-Stecker vs Protokoll, Thunderbolt, HDMI/DP, Ethernet vs WiFi | „warum lädt mein Laptop am einen USB-C-Port und am anderen nicht" |
| 9 | **Distribution & Metadaten** | Wie Inhalte ins Netz kommen | CDN-Prinzip, REST-API, EXIF/ID3, Vendor-Lockin | Netflix-Stream-Latenz, Instagram strippt EXIF |
### Lock-Entscheidungen (Dozent, 2026-05-13)
- **D1 — Block 9 Distribution & Metadaten:** **PFLICHT-KLAUSUR.** Schließt den Bogen „vom Bit bis zum Bildschirm der Endnutzerin".
- **D2 — Zukunfts-Themen** (AI-Kompression, JPEG XL, DNA-Storage, Web3): **RAUS.** Werden nicht aufgenommen, weder Klausur noch Lehre.
- **D3 — JPEG-Pipeline-Tiefe:** **VOLLE TIEFE** inkl. DCT und Quantisierungstabellen. Härteste konzeptuelle Nuss bleibt als „Verstehen-statt-Auswendiglernen"-Test drin. Reduzieren passiert nötigenfalls im Live-Vortrag, nicht in der Architektur.
- **D4 — Granularität:** **9 granulare Blöcke** (Dozent-agnostisch zur Wahl, granular liegt näher an Inhalt).
Leitprinzip aus dem Workshop: **„nicht reduzieren — skippen passiert während der Vorlesung."** Architektur bleibt ambitioniert, Live-Anpassung übernimmt die Skalierung.
### Verhältnis zu den Kapiteln
Vorgeschlagene Themen ↔ Kapitel-Mapping (welches Kapitel liefert das Material für welchen Block):
- Block 1 (Fundamentale) ← Kap 0 (Intro) + Kap 1 (Grundlagen)
- Block 2 (Signal→Byte) ← Kap 1 (Text+Audio)
- Block 3 (Kompression) ← Kap 1 + Kap 2 (übergreifend)
- Block 4 (Bilder) ← Kap 2 (Bild+Video)
- Block 5 (Audio) ← Kap 1 (Text+Audio)
- Block 6 (Video) ← Kap 2 (Bild+Video)
- Block 7 (Speicher) ← Kap 3
- Block 8 (Schnittstellen) ← Kap 3
- Block 9 (Distribution) ← Kap 4 (falls drin) / sonst raus
→ Daraus folgt eine Kapitel-Neugliederung mit 5 Kapiteln (statt aktuell 6 mit Platzhalter):
- Kap 1: Fundamentale + Signal→Byte
- Kap 2: Kompression
- Kap 3: Bilder + Audio + Video
- Kap 4: Speicher + Schnittstellen
- Kap 5: Distribution + Metadaten (optional, Zukunfts-Bonus integriert)
### Lock-Status
- [x] D1–D4 entschieden (2026-05-13)
- [x] Block-Architektur (9 Blöcke) festgelegt
- [x] Kapitel-Neugliederung (6→5) festgelegt
- [ ] Phase 1: Operative Lernziele pro Block formuliert
- [ ] Phase 2: Folien-Skelett pro Kapitel
---
## 223015c — Internettechnologien
**Status:** wird nach 223015b bearbeitet (Reihenfolge laut Plan: b → c → dhbw).
Platzhalter — Vorschlag folgt nach Abschluss von 223015b.
---
## DHBW Technik I
**Status:** keine Klausur, separate Prüfungsleistungs-Architektur in `docs/dhbw-pruefungsleistung-2026.md` (Phase 0).
+159 -29
View File
@@ -13,6 +13,15 @@ case "$COURSE" in
SLIDES_URL="https://librete.ch/hdm/223015b"
ACCENT_COLOR="#1e5f8a"
ACCENT_LIGHT="#e8f4fc"
INSTITUTION="HdM Stuttgart"
HEADLINE="HdM Vorlesungen"
KAPITEL_TERM="Kapitel"
BREADCRUMB_URL="../"
EXAM_URL=""
EXAM_LABEL=""
KONTAKT_URL="mailto:mail@librete.ch"
KONTAKT_LABEL="Kontakt"
QR_IMG="qr-index.svg"
;;
223015c)
TITLE="Grundlagen IT- und Internettechnik"
@@ -20,16 +29,72 @@ case "$COURSE" in
SLIDES_URL="https://librete.ch/hdm/223015c"
ACCENT_COLOR="#d63384"
ACCENT_LIGHT="#fce4ec"
INSTITUTION="HdM Stuttgart"
HEADLINE="HdM Vorlesungen"
KAPITEL_TERM="Kapitel"
BREADCRUMB_URL="../"
EXAM_URL=""
EXAM_LABEL=""
KONTAKT_URL="mailto:mail@librete.ch"
KONTAKT_LABEL="Kontakt"
QR_IMG="qr-index.svg"
;;
dhbw)
TITLE="Web Engineering"
SUBTITLE="Informatik / Wirtschaftsinformatik"
SLIDES_URL="https://librete.ch/dhbw"
ACCENT_COLOR="#a02060"
ACCENT_LIGHT="#fce4ec"
INSTITUTION="DHBW Stuttgart"
HEADLINE="DHBW Vorlesungen"
KAPITEL_TERM="Sitzung"
BREADCRUMB_URL=""
EXAM_URL="https://git.librete.ch/DHBW/pruefungsleistung"
EXAM_LABEL="Prüfungsleistung"
KONTAKT_URL="mailto:michael.czechowski@lehre.dhbw-stuttgart.de"
KONTAKT_LABEL="Kontakt"
QR_IMG="assets/slides-dhbw.png"
;;
*)
TITLE="$COURSE - HdM Slides"
TITLE="$COURSE - Slides"
SUBTITLE="Lecture Slides"
SLIDES_URL="https://librete.ch/hdm/$COURSE"
SLIDES_URL="https://librete.ch/$COURSE"
ACCENT_COLOR="#0066cc"
ACCENT_LIGHT="#e8f4fc"
INSTITUTION="Stuttgart"
HEADLINE="Vorlesungen"
KAPITEL_TERM="Kapitel"
BREADCRUMB_URL=""
EXAM_URL=""
EXAM_LABEL=""
KONTAKT_URL="mailto:mail@librete.ch"
KONTAKT_LABEL="Kontakt"
QR_IMG="qr-index.svg"
;;
esac
# Optional breadcrumb HTML (empty if no parent overview)
if [[ -n "$BREADCRUMB_URL" ]]; then
BREADCRUMB_HTML="<p class=\"breadcrumb\"><a href=\"$BREADCRUMB_URL\">← Kursübersicht</a></p>"
else
BREADCRUMB_HTML=""
fi
# Optional exam-link HTML
if [[ -n "$EXAM_URL" ]]; then
EXAM_HTML="<p class=\"exam-link\"><a href=\"$EXAM_URL\">$EXAM_LABEL →</a></p>"
else
EXAM_HTML=""
fi
# Footer kursübersicht link only when breadcrumb parent exists
if [[ -n "$BREADCRUMB_URL" ]]; then
FOOTER_KURS_HTML=" ·
<a href=\"$BREADCRUMB_URL\">Kursübersicht</a>"
else
FOOTER_KURS_HTML=""
fi
# Topic mappings for nice German titles
declare -A TOPIC_MAP
TOPIC_MAP["intro"]="Einführung"
@@ -41,6 +106,14 @@ 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"
TOPIC_MAP["html-css"]="HTML & CSS"
TOPIC_MAP["js-frameworks"]="JS, Frameworks & Build Tools"
TOPIC_MAP["nodejs-basics"]="Node.js: Scripting, Running & Building"
TOPIC_MAP["express"]="Express API, CRUD & Middlewares"
TOPIC_MAP["testing"]="Testing"
TOPIC_MAP["typescript"]="TypeScript"
TOPIC_MAP["docker"]="Docker, Proxies & DBs"
TOPIC_MAP["best-practices"]="Wrap-up & Best Practices"
# Configure which topics should appear disabled per course
# Two modes: fully disabled (non-clickable card) and buttons-disabled (link remains clickable, buttons are disabled)
@@ -48,8 +121,17 @@ declare -A DISABLED_FULL
declare -A DISABLED_BUTTONS
# For course B: chapters 3,4,5 should be fully disabled
DISABLED_FULL["223015b"]="speichermedien-schnittstellen distribution-apis-zukunft vertiefung-offene-fragen"
# For course C: chapter 3 should keep link clickable but buttons disabled
DISABLED_BUTTONS["223015c"]="interaktivitaet-javascript"
# For course C: all chapters fully active
DISABLED_BUTTONS["223015c"]=""
# Courses where the "Klausurrelevante Folien" card should be active (clickable)
declare -A KLAUSURFOLIEN_ACTIVE
KLAUSURFOLIEN_ACTIVE["223015b"]=1
# Courses where the "Klausurfragen" card should be active (clickable)
declare -A KLAUSURFRAGEN_ACTIVE
KLAUSURFRAGEN_ACTIVE["223015b"]=1
KLAUSURFRAGEN_ACTIVE["223015c"]=1
cat > "$BUILD_DIR/index.html" << HEADER
<!DOCTYPE html>
@@ -101,6 +183,16 @@ cat > "$BUILD_DIR/index.html" << HEADER
font-size: 0.875rem;
margin-top: 0.25rem;
}
.exam-link {
margin-top: 1rem;
font-size: 0.95rem;
}
.exam-link a {
color: $ACCENT_COLOR;
text-decoration: none;
font-weight: 500;
}
.exam-link a:hover { text-decoration: underline; }
/* Use the .termine wrapper and add a gap between cards */
.termine {
margin-top: 1.5rem;
@@ -226,11 +318,12 @@ cat > "$BUILD_DIR/index.html" << HEADER
</head>
<body>
<header>
<p class="breadcrumb"><a href="../">← Kursübersicht</a></p>
<h1>HdM Vorlesungen</h1>
$BREADCRUMB_HTML
<h1>$HEADLINE</h1>
<h2 class="course-heading">$TITLE</h2>
<p class="subtitle">$SUBTITLE</p>
<p class="meta">HdM Stuttgart · Sommersemester 2026 · Michael Czechowski</p>
<p class="meta">$INSTITUTION · Sommersemester 2026 · Michael Czechowski</p>
$EXAM_HTML
</header>
<div class="termine">
HEADER
@@ -253,7 +346,7 @@ for html in $(ls "$BUILD_DIR"/[0-9][0-9]-*.html 2>/dev/null | sort); do
if [[ "$kapitel_num" == "0" ]] || [[ -z "$kapitel_num" ]]; then
kapitel_label="Einführung"
else
kapitel_label="Kapitel $kapitel_num"
kapitel_label="$KAPITEL_TERM $kapitel_num"
fi
pdf_filename="${filename%.html}.pdf"
@@ -320,13 +413,29 @@ LINK
done
# Add klausurfolien entry if it exists (disabled — wird noch überarbeitet)
# Add klausurfolien entry if it exists (active per KLAUSURFOLIEN_ACTIVE, else disabled)
if [[ -f "$BUILD_DIR/klausurfolien.html" ]]; then
pdf_disabled=""
if [[ -f "$BUILD_DIR/klausurfolien.pdf" ]]; then
pdf_disabled="<span class=\"btn btn-pdf btn-disabled\">PDF</span>"
fi
cat >> "$BUILD_DIR/index.html" << KLAUSUR
if [[ "${KLAUSURFOLIEN_ACTIVE[$COURSE]}" == "1" ]]; then
pdf_active=""
if [[ -f "$BUILD_DIR/klausurfolien.pdf" ]]; then
pdf_active="<a href=\"klausurfolien.pdf\" class=\"btn btn-pdf\">PDF</a>"
fi
cat >> "$BUILD_DIR/index.html" << KLAUSUR
<div class="kapitel-card" style="border-left: 3px solid $ACCENT_COLOR;">
<a href="klausurfolien.html" class="kapitel-link">
<div class="kapitel-label">Prüfung</div>
<div class="kapitel-title">Klausurrelevante Folien</div>
</a>
<a href="klausurfolien.html" class="btn btn-slides">Folien</a>
$pdf_active
</div>
KLAUSUR
else
pdf_disabled=""
if [[ -f "$BUILD_DIR/klausurfolien.pdf" ]]; then
pdf_disabled="<span class=\"btn btn-pdf btn-disabled\">PDF</span>"
fi
cat >> "$BUILD_DIR/index.html" << KLAUSUROFF
<div class="kapitel-card disabled" style="border-left: 3px solid $ACCENT_COLOR;">
<div class="kapitel-link">
<div class="kapitel-label">Prüfung</div>
@@ -335,20 +444,41 @@ if [[ -f "$BUILD_DIR/klausurfolien.html" ]]; then
<span class="btn btn-slides btn-disabled">Folien</span>
$pdf_disabled
</div>
KLAUSUR
KLAUSUROFF
fi
fi
# Add klausurfragen entry if it exists (disabled — wird noch überarbeitet)
# Add klausurfragen entry if it exists (active per KLAUSURFRAGEN_ACTIVE, else disabled)
if [[ -f "$BUILD_DIR/klausurfragen.html" ]] || [[ -f "$BUILD_DIR/klausurfragen.pdf" ]]; then
pdf_disabled=""
if [[ -f "$BUILD_DIR/klausurfragen.pdf" ]]; then
pdf_disabled="<span class=\"btn btn-pdf btn-disabled\">PDF</span>"
fi
slides_disabled=""
if [[ -f "$BUILD_DIR/klausurfragen.html" ]]; then
slides_disabled="<span class=\"btn btn-slides btn-disabled\">Folien</span>"
fi
cat >> "$BUILD_DIR/index.html" << KLAUSURFRAGEN
if [[ "${KLAUSURFRAGEN_ACTIVE[$COURSE]}" == "1" ]]; then
pdf_active=""
if [[ -f "$BUILD_DIR/klausurfragen.pdf" ]]; then
pdf_active="<a href=\"klausurfragen.pdf\" class=\"btn btn-pdf\">PDF</a>"
fi
slides_active=""
if [[ -f "$BUILD_DIR/klausurfragen.html" ]]; then
slides_active="<a href=\"klausurfragen.html\" class=\"btn btn-slides\">Folien</a>"
fi
cat >> "$BUILD_DIR/index.html" << KLAUSURFRAGEN
<div class="kapitel-card" style="border-left: 3px solid $ACCENT_COLOR;">
<a href="klausurfragen.html" class="kapitel-link">
<div class="kapitel-label">Prüfung</div>
<div class="kapitel-title">Klausurfragen</div>
</a>
$slides_active
$pdf_active
</div>
KLAUSURFRAGEN
else
pdf_disabled=""
if [[ -f "$BUILD_DIR/klausurfragen.pdf" ]]; then
pdf_disabled="<span class=\"btn btn-pdf btn-disabled\">PDF</span>"
fi
slides_disabled=""
if [[ -f "$BUILD_DIR/klausurfragen.html" ]]; then
slides_disabled="<span class=\"btn btn-slides btn-disabled\">Folien</span>"
fi
cat >> "$BUILD_DIR/index.html" << KLAUSURFRAGENOFF
<div class="kapitel-card disabled" style="border-left: 3px solid $ACCENT_COLOR;">
<div class="kapitel-link">
<div class="kapitel-label">Prüfung</div>
@@ -357,18 +487,18 @@ if [[ -f "$BUILD_DIR/klausurfragen.html" ]] || [[ -f "$BUILD_DIR/klausurfragen.p
$slides_disabled
$pdf_disabled
</div>
KLAUSURFRAGEN
KLAUSURFRAGENOFF
fi
fi
cat >> "$BUILD_DIR/index.html" << FOOTER
</div>
<div class="qr-section">
<img src="qr-index.svg" alt="QR Code" class="qr-code">
<img src="$QR_IMG" alt="QR Code" class="qr-code">
<p class="qr-url">$SLIDES_URL</p>
</div>
<footer>
<a href="mailto:mail@librete.ch">Kontakt</a> ·
<a href="../">Kursübersicht</a>
<a href="$KONTAKT_URL">$KONTAKT_LABEL</a>$FOOTER_KURS_HTML
</footer>
</body>
</html>
+138 -259
View File
@@ -9,6 +9,7 @@ title: Dateiformate, Schnittstellen, Speichermedien & Distributionswege
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #1e5f8a;
@@ -713,19 +714,14 @@ Kinofilm in üblicher Länge (~120min) über **5 TB (Terabyte)**
---
<!-- _header: "" -->
<!-- _footer: "" -->
<!-- _paginate: false -->
![bg](./assets/lv-original-vs-fake.jpg)
<!--
Analogie: Original vs Fake-Tasche
Was ist überhaupt KOMPRESSION?
- Links: Original — jedes Detail erhalten (Lossless)
- Rechts: Fälschung — sieht ähnlich aus, Details verloren (Lossy)
- Weitere Analogien: Luftdruck im Reifen, LNG, Tripsdrill-Schlange,
Telenovela-Zusammenfassung, Sodastream-Sirup
- Luftdruck in Auto/Fahrradreifen
- LNG Flüssiggas
- Tripsdrill, Disneyland
- Oper/Theater/Telenovela
- Cola Sirup für den Sodastream
-->
---
@@ -805,7 +801,7 @@ Komprimiert: 5A3B8C (6 Zeichen)
* Das Ohr hört nicht alle Frequenzen (hohe und tiefe Töne) gleich gut
* Laute Töne überdecken leise Töne (Maskierung)
* Das Auge sieht nicht alle Farbnuancen gleich scharf
* Luminanz (Helligkeit/Dunkelheit) besser erkennbar als Chrominanz (Farbunterschiede/Farbigkeit)
* Luminanz (Helligkeit/Dunkelheit) besser erkennen als Chrominanz (Farbunterschiede/Farbigkeit)
* und Vieles mehr
<!--
@@ -1150,6 +1146,135 @@ Sog. RGB Tuple (geordnete endliche Liste)
---
# Unicode: Ein Standard für alle
**Unicode (1991):** Jedes Schriftsystem der Welt
**>150.000 Zeichen:**
- Latein, Kyrillisch, Arabisch, Chinesisch, Japanisch...
- Mathematische Symbole, Emoji, historische Schriften
**UTF-8:** Variable Länge (1–4 Byte pro Zeichen)
- **Zeichen 0–127: identisch mit ASCII** (Abwärtskompatibilität!)
- 1.112.064 gültige Codepunkte
- Umlaute: 2 Byte · CJK: 3 Byte · Emoji: 4 Byte
<!--
- Unicode Consortium: Non-Profit, gegründet 1991
- Unicode 16.0 (2024): 154.998 Zeichen
- UTF-8 = Unicode Transformation Format, 8-bit (Ken Thompson & Rob Pike, 1992)
- Die ersten 128 Zeichen in UTF-8 sind exakt ASCII — Grund warum ASCII nie verschwinden wird
- UTF-8 ist seit 2008 das häufigste Encoding im Web (W3Techs)
-->
---
# Beispiel: Byte zählen
**Text:** `"Hello·🌸·こんにちは·(Kon-ni-chi-wa)"`
| Zeichen | Byte |
|---------|-------|
| `Hello·` | 6 × 1 = **6 Byte** (ASCII) |
| `🌸` | **4 Byte** (Emoji) |
| `·` | **1 Byte** |
| `こんにちは` | 5 × 3 = **15 Byte** (Hiragana) |
| `·(Kon-ni-chi-wa)` | **16 Byte** (ASCII) |
**Gesamt: 42 Byte** für 29 sichtbare Zeichen
<!--
- ASCII (Hello, Klammern) = 1 Byte pro Zeichen
- Emoji 🌸 (Cherry Blossom U+1F338) = 4 Bytes
- Hiragana こんにちは = 3 Byte pro Zeichen (U+3040–309F)
- は wird hier "wa" ausgesprochen (Partikel), nicht "ha"
-->
---
<!-- _class: lead -->
# Hexadezimal
## Die Sprache der Datei-Analyse
---
# Hexadezimal: Lesbarkeit
**Für den Menschen ungeeignet:**
`01010000 01001110 01000111`
**Hexadezimal (Base 16):**
`50 4E 47`
`5 = 0101` `0 = 0000` = 5 * 16 + 0 = 80
`4 = 0100` `E = 1110` = 4 * 16 + ? = ?
`4 = 0100` `7 = 0111` = ?
**Jede Hex-Ziffer = 4 Bits (ein "Nibble")**
0–9, A–F (10=A, 11=B, ..., 15=F)
<!--
- Dezimalsystem passt unelegant ins binäre System: 0–15 (1111) braucht 1–2 Dezimalziffern, immer 1 Hex-Ziffer
- Hexadezimal (16 = 2⁴) passt perfekt: 4 Bits = 1 Hex-Ziffer, 8 Bits = 2 Hex-Ziffern
- "Nibble" = 4 Bits = halbes Byte (Wortspiel: nibble = knabbern, byte = beißen)
- ASCII geht nur bis 127 — Werte 128–255 sind nicht im ASCII-Raum
-->
---
# Wo begegnet Ihnen Hex-Code?
| Kontext | Beispiel |
|---------|----------|
| CSS-Farben | `#FF5733` |
| MAC-Adressen | `00:1A:2B:3C:4D:5E` |
| Fehlercodes | `0x80070005` |
| Speicheradressen | `0xA04F20` |
| Unicode | `U+00E4` (ä) |
| Datei-Signaturen | `89 50 4E 47` (PNG) |
<!--
Präfixe:
- 0x = "das ist Hexadezimal" (C, JavaScript, Python)
- U+ = Unicode-Codepoint (Standard für Zeichenkodierung)
- # = CSS-Konvention für Farben
ABKÜRZUNGEN:
- MAC = Media Access Control (eindeutige Hardware-Adresse einer Netzwerkkarte)
- Unicode = universeller Zeichensatz für alle Schriftsysteme
Speicheradressen erklärt:
- 64-Bit-System → Adresse hat 64 Bit = 16 Hex-Ziffern
- Beispiel vollständig: 0x0000000000A04F20 (führende Nullen weggelassen)
- "0x" = Präfix, sagt nur "jetzt kommt Hex"
Fehlercodes: Windows zeigt diese bei Bluescreens
-->
---
# Bit vs. Byte: Die Verwirrung
**1 Byte = 8 Bit** → Bit ÷ 8 = Byte
| Einheit (Bit) | Einheit (Byte) |
|---------------|----------------|
| 1 Kbit = 1.000 Bit | 1 KB = 1.000 Byte = 8.000 Bit |
| 1 Mbit = 1.000.000 Bit | 1 MB = 1.000.000 Byte = 8 Mbit |
| 1 Gbit = 1 Mrd. Bit | 1 GB = 1 Mrd. Byte = 8 Gbit |
100 Mbit/s Bandbreite = **12,5 MB/s** Downloadrate
<!--
Bits = kleines b, Bytes = großes B
Internetanbieter: Mbit/s (klingt größer!)
100 Mbit/s ÷ 8 = 12,5 MB/s
Marketing - 100 klingt besser als 12,5
-->
---
<!-- _class: lead -->
# ASCII
@@ -1197,85 +1322,6 @@ US-ASCII (1967) Code Chart
---
<!-- _class: lead -->
# ASCII reicht für Englisch.
## Aber was ist mit *ä, é, 中, 🌸*?
<!--
Brücke: ASCII löst das Problem nur für englischen Text.
Sobald Umlaute, Akzente, asiatische Schriften oder Emoji ins Spiel kommen,
sprengt es den 7-Bit-Raum. Lösung: Unicode + UTF-8.
-->
---
# Unicode: Ein Standard für alle
**Unicode (1991):** Jedes Schriftsystem der Welt
**>150.000 Zeichen:**
- Latein, Kyrillisch, Arabisch, Chinesisch, Japanisch...
- Mathematische Symbole, Emoji, historische Schriften
**UTF-8:** Variable Länge (1–4 Byte pro Zeichen)
- **Zeichen 0–127: identisch mit ASCII** (Abwärtskompatibilität!)
- 1.112.064 gültige Codepunkte
- Umlaute: 2 Byte · CJK: 3 Byte · Emoji: 4 Byte
<!--
- Unicode Consortium: Non-Profit, gegründet 1991
- Unicode 16.0 (2024): 154.998 Zeichen
- UTF-8 = Unicode Transformation Format, 8-bit (Ken Thompson & Rob Pike, 1992)
- Die ersten 128 Zeichen in UTF-8 sind exakt ASCII — Grund warum ASCII nie verschwinden wird
- UTF-8 ist seit 2008 das häufigste Encoding im Web (W3Techs)
-->
---
# Beispiel: Byte zählen
**Text:** `"Hello·🌸·こんにちは·(Kon-ni-chi-wa)"`
| Zeichen | Byte |
|---------|-------|
| `Hello·` | 6 × 1 = **6 Byte** (ASCII) |
| `🌸` | **4 Byte** (Emoji) |
| `·` | **1 Byte** |
| `こんにちは` | 5 × 3 = **15 Byte** (Hiragana) |
| `·(Kon-ni-chi-wa)` | **16 Byte** (ASCII) |
**Gesamt: 42 Byte** für 29 sichtbare Zeichen
<!--
- ASCII (Hello, Klammern) = 1 Byte pro Zeichen
- Emoji 🌸 (Cherry Blossom U+1F338) = 4 Bytes
- Hiragana こんにちは = 3 Byte pro Zeichen (U+3040–309F)
- は wird hier "wa" ausgesprochen (Partikel), nicht "ha"
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-fuer-byte.png)
<!--
Brücke / Strang-Wechsel:
Bis hier: Wie speichern wir Buchstaben als Byte? (Encoding)
Ab jetzt: Wie schauen Byte aus, wenn man die Datei roh anstarrt? (Darstellung)
Aussage der Grafik:
- Fenster 1 (Bin): rohe 0/1 — was tatsächlich auf der Platte steht
- Fenster 2 (Hex): 2 Ziffern pro Byte — kompakt lesbar
- Fenster 3 (Text): ASCII-Zeichen wenn ≤ 126, sonst ✗
- Schon ein Byte > 126 → Binärdatei (z.B. PNG, MP3, ZIP)
- Nur Werte ≤ 126 → reine Textdatei (z.B. .txt, .csv, .md)
-->
---
![bg right:40%](./assets/matrix-code.png)
# WTF!?
@@ -1288,108 +1334,6 @@ Aussage der Grafik:
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/why-8-bit.png)
<!--
Warum gerade 8 Bit?
- CPU adressiert byteweise — kleinste adressierbare Einheit
- Halbe Byte (z.B. 0x0000.5) existieren nicht
- Speichercontroller, Bus, CPU-Register alle auf 8-Bit-Häppchen ausgelegt
- Einzelne Bit lesen: erst Byte holen, dann mit Bitmaske isolieren (byte & 0b1000_0000)
- Hardware-Geschichte: IBM System/360 (1964) setzte 8-Bit-Standard, 7-Bit-ASCII + 1 Paritätsbit
-->
---
<!-- _class: lead -->
# Hexadezimal
## Die Sprache der Datei-Analyse
---
# Hexadezimal: Lesbarkeit
**Für den Menschen ungeeignet:**
`01010000 01001110 01000111`
**Hexadezimal (Base 16):**
`50 4E 47`
`5 = 0101` `0 = 0000` = 5 * 16 + 0 = 80
`4 = 0100` `E = 1110` = 4 * 16 + ? = ?
`4 = 0100` `7 = 0111` = ?
**Jede Hex-Ziffer = 4 Bits (ein "Nibble")**
0–9, A–F (10=A, 11=B, ..., 15=F)
<!--
- Dezimalsystem passt unelegant ins binäre System: 0–15 (1111) braucht 1–2 Dezimalziffern, immer 1 Hex-Ziffer
- Hexadezimal (16 = 2⁴) passt perfekt: 4 Bits = 1 Hex-Ziffer, 8 Bits = 2 Hex-Ziffern
- "Nibble" = 4 Bits = halbes Byte (Wortspiel: nibble = knabbern, byte = beißen)
- ASCII geht nur bis 127 — Werte 128–255 sind nicht im ASCII-Raum
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-nibble-hex.png)
<!--
Kernidee: jedes Byte lässt sich sauber in zwei 4-Bit-Hälften (Nibbles) zerlegen. Jede Hälfte hat 2⁴ = 16 Zustände – und genau 16 Symbole hat Hex (0-F). Deshalb passt Hex perfekt: 1 Nibble = 1 Hex-Ziffer, 1 Byte = 2 Hex-Ziffern. Keine krumme Umrechnung.
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/hex-dec-table.png)
<!--
Hex ↔ Dezimal Lookup-Tabelle: 0–F = 0–15
A=10, B=11, C=12, D=13, E=14, F=15
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-flow.png)
<!--
1 Byte = 8 Bit = 2 Hex-Ziffern = 1 ASCII-Zeichen
- Dieselbe Datei, drei Schreibweisen
- Jeder Rahmen = ein Byte
- Byte ändern sich nicht, nur unsere Anzeige
- ↵ (0x0A) = nicht druckbar → Hex-Editoren zeigen . als Platzhalter
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/three-views.png)
<!--
Dieselben 8 Byte (PNG-Dateianfang: 89 50 4E 47 0D 0A 1A 0A) — drei Perspektiven:
1. Bitstream — was wirklich gespeichert wird (unleserlich)
2. Hex — gruppiert in 8-Bit-Häppchen (kompakt)
3. Bedeutung — was die Byte signalisieren:
- 89: Magic Byte (>127 → "ich bin Binärdatei")
- 50 4E 47: P N G (ASCII-Format-Kürzel)
- 0D 0A 1A 0A: CR LF EOF LF (erkennt kaputte Übertragung)
-->
---
![bg right:30%](./assets/matrix-code.png)
# What the HEX-Code
@@ -1449,71 +1393,6 @@ Dieselben 8 Byte (PNG-Dateianfang: 89 50 4E 47 0D 0A 1A 0A) — drei Perspektive
---
<!-- _class: lead -->
# Hex ist überall.
## Schon mal *gesehen*?
<!--
Brücke vom Theorie-Block zum Alltags-Recall.
Bis hier: Was ist Hex und wie liest man es?
Ab jetzt: Wo siehst du Hex in der Praxis (CSS, MAC, Errorcodes, Unicode, Magic Numbers)?
-->
---
# Wo begegnet Ihnen Hex-Code?
| Kontext | Beispiel |
|---------|----------|
| CSS-Farben | `#FF5733` |
| MAC-Adressen | `00:1A:2B:3C:4D:5E` |
| Fehlercodes | `0x80070005` |
| Speicheradressen | `0xA04F20` |
| Unicode | `U+00E4` (ä) |
| Datei-Signaturen | `89 50 4E 47` (PNG) |
<!--
Präfixe:
- 0x = "das ist Hexadezimal" (C, JavaScript, Python)
- U+ = Unicode-Codepoint (Standard für Zeichenkodierung)
- # = CSS-Konvention für Farben
ABKÜRZUNGEN:
- MAC = Media Access Control (eindeutige Hardware-Adresse einer Netzwerkkarte)
- Unicode = universeller Zeichensatz für alle Schriftsysteme
Speicheradressen erklärt:
- 64-Bit-System → Adresse hat 64 Bit = 16 Hex-Ziffern
- Beispiel vollständig: 0x0000000000A04F20 (führende Nullen weggelassen)
- "0x" = Präfix, sagt nur "jetzt kommt Hex"
Fehlercodes: Windows zeigt diese bei Bluescreens
-->
---
# Bit vs. Byte: Die Verwirrung
**1 Byte = 8 Bit** → Bit ÷ 8 = Byte
| Einheit (Bit) | Einheit (Byte) |
|---------------|----------------|
| 1 Kbit = 1.000 Bit | 1 KB = 1.000 Byte = 8.000 Bit |
| 1 Mbit = 1.000.000 Bit | 1 MB = 1.000.000 Byte = 8 Mbit |
| 1 Gbit = 1 Mrd. Bit | 1 GB = 1 Mrd. Byte = 8 Gbit |
100 Mbit/s Bandbreite = **12,5 MB/s** Downloadrate
<!--
Bits = kleines b, Bytes = großes B
Internetanbieter: Mbit/s (klingt größer!)
100 Mbit/s ÷ 8 = 12,5 MB/s
Marketing - 100 klingt besser als 12,5
-->
---
# Magic Numbers
**Dateityp-Identifikation durch erste Bytes**
@@ -2194,4 +2073,4 @@ Vollständige Lizenz: https://creativecommons.org/licenses/by-sa/4.0/
- hex5: ZIP (50 4B 03 04)
- Gruppenarbeit: 3-4 Personen
- Ziel: Hex-Dump lesen lernen, Dateiformate verstehen
-->
-->
+57 -61
View File
@@ -220,7 +220,7 @@ Jeder Pixel speichert einen RGB-Farbwert (3 Bytes).
**Aufbau:** Liste von Pixeln mit Farbwerten (2D-Array)
**Speicherbedarf (unkomprimiert):**
Breite × Höhe × Farbtiefe (in Bytes)
Breite × Höhe × Farbtiefe (in Byte)
**Beispiele:** JPEG, PNG, WebP
@@ -361,6 +361,15 @@ Vektorgrafiken speichern keine Pixel, sondern mathematische Beschreibungen: Koor
- Frage: "Warum verschickt euch der Grafiker das Logo als .ai oder .svg?"
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/raster-vs-vektor.png)
---
<!-- _class: lead -->
@@ -374,6 +383,14 @@ Vektorgrafiken speichern keine Pixel, sondern mathematische Beschreibungen: Koor
- Wir nutzen seine Schwächen aus
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/lv-original-vs-fake.jpg)
---
<!-- _class: klausur -->
@@ -498,6 +515,16 @@ Das Auge ist ein Tiefpassfilter: Hohe Frequenzen (feine Details) werden schwäch
- Interaktive Demo: https://claude.ai/public/artifacts/452e62f1-8525-442d-aa88-bf3795cab2c5
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/jpeg-pipeline.png)
---
<!-- _class: klausur -->
@@ -507,7 +534,7 @@ Das Auge ist ein Tiefpassfilter: Hohe Frequenzen (feine Details) werden schwäch
![bg right:20%](./assets/Barn-yuv.png)
# JPEG Schritt 1: Farbraumkonversion
# JPEG Schritt 1: Farbraumkonvertierung
**RGB → Y'CbCr**
@@ -530,11 +557,33 @@ KLAUSURRELEVANT:
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/ybcbr.webp)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/Barn-rgb.png)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/Barn-cmyk.png)
---
<!-- _class: erklaerung -->
<!-- _header: '' -->
<!-- _footer: '' -->
# Farbraumkonversion – Vertiefung
# Farbraumkonvertierung – Vertiefung
RGB→YCbCr nutzt die Biologie des menschlichen Auges: 120 Mio. Stäbchen (Helligkeit) vs. nur 6 Mio. Zapfen (Farbe) – ein 20:1-Verhältnis. Die Transformation erfolgt über eine lineare Matrix:
@@ -546,7 +595,7 @@ Cr = 0.500·R − 0.419·G − 0.081·B + 128
Die Gewichtung (G dominiert mit 59%) entspricht der spektralen Empfindlichkeit des Auges bei Tageslicht. Y enthält alle Schärfeinformation; Cb/Cr können reduziert werden.
**Chroma Subsampling – Notation J:a:b** (bezogen auf 4×2 Pixel):
**Chroma Subsampling – Notation `J:a:b`** (bezogen auf 4×2 Pixel):
| Schema | Farbdaten | Einsatz |
|--------|-----------|---------|
@@ -713,11 +762,6 @@ KLAUSURRELEVANT:
---
<!-- _class: klausur -->
<!-- _header: '' -->
<!-- _footer: '' -->
<!-- _backgroundColor: #e3f2fd -->
# JPEG Schritt 6: Huffman-Coding
**Verlustfreie Kompression der Restwerte**
@@ -770,37 +814,10 @@ JPEG verwendet zwei Huffman-Tabellen: eine für DC-Koeffizienten (Durchschnittsw
---
<!-- _class: klausur -->
<!-- _header: '' -->
<!-- _footer: '' -->
<!-- _backgroundColor: #e3f2fd -->
<!--
# Huffman-Coding: Beispiel
**Originaltext:** `ABRACADABRA` (11 Zeichen × 8 Bit = 88 Bit)
**Häufigkeitsanalyse:**
A=5, B=2, R=2, C=1, D=1
**Huffman-Baum → Codes:**
| Zeichen | Häufigkeit | Code |
|---------|------------|------|
| A | 5 | `0` |
| B | 2 | `10` |
| R | 2 | `110` |
| C | 1 | `1110` |
| D | 1 | `1111` |
**Codiert:** `0 10 110 0 1110 0 1111 0 10 110 0` = **23 Bit**
**Kompression:** 88 → 23 Bit = **74% gespart**
- Beispiel Schritt für Schritt durchrechnen
- Warum funktioniert's? A kommt 5× vor, bekommt kürzesten Code
- Präfix-Eigenschaft: Kein Code ist Anfang eines anderen → eindeutig dekodierbar
- Frage: "Was passiert, wenn alle Zeichen gleich häufig sind?" → Keine Ersparnis
- In JPEG: Nicht Buchstaben, sondern DCT-Koeffizienten werden so codiert
-->
![bg](./assets/demos/summary-kap02.png)
---
@@ -824,8 +841,6 @@ A=5, B=2, R=2, C=1, D=1
# Andere Bildformate
## PNG, GIF, WebP, AVIF
15:33 Uhr weiter
<!--
- JPEG ist nicht für alles geeignet
- Jetzt: Alternativen und ihre Stärken
@@ -1117,29 +1132,10 @@ KLAUSURRELEVANT:
---
# Container + Codec = Video
<!-- _header: '' -->
<!-- _footer: '' -->
```
┌─────────────────────────────┐
│ Container (z.B. MP4) │
│ ┌────────────────────────┐ │
│ │ Video-Stream (H.264) │ │
│ ├────────────────────────┤ │
│ │ Audio-Stream (AAC) │ │
│ ├────────────────────────┤ │
│ │ Untertitel (SRT) │ │
│ ├────────────────────────┤ │
│ │ Metadaten │ │
│ └────────────────────────┘ │
└─────────────────────────────┘
```
<!--
- Container = Verpackung
- Codec = wie der Inhalt komprimiert ist
- Ein MP4 mit H.264 und ein MP4 mit H.265 haben dieselbe Endung
- Wichtig für Kompatibilität: Player muss Codec unterstützen
-->
![bg fit](./assets/demos/container-vs-codec.png)
---
@@ -119,7 +119,7 @@ Hochschule der Medien Stuttgart
<!-- _class: lead -->
# Kapitel 3 – 23.01.2026
# Kapitel 3
## Speichermedien & Schnittstellen
---
@@ -369,8 +369,7 @@ Seitdem native Linux-Unterstützung.
**Features:**
- Journaling (Crash-Sicherheit)
- Dateirechte (ACLs)
- Kompression, Verschlüsselung
- Große Dateien und Volumes
- Kompression, Verschlüsselung, große Dateien und Volumes
**Nachteile:**
- Nur Windows schreibt nativ
@@ -629,11 +628,6 @@ Millionen von Websites und Spielen verloren.
- 30 Jahre Haltbarkeit
- Für Cold Storage ideal
**M-DISC:**
- Spezielle DVD/Blu-ray
- 1.000+ Jahre Haltbarkeit (Herstellerangabe)
- Für kleine, wichtige Daten
**Cloud:**
- Glacier, Backblaze B2
- Günstig für Langzeit
+34
View File
@@ -0,0 +1,34 @@
# CLAUDE.md — 223015b lecture deck
Marp lecture slides + master question catalog for HdM Stuttgart course **223015b — „Dateiformate, Schnittstellen, Speichermedien & Distributionswege"**. Author: Michael Czechowski, SoSe 2026. This directory is the **source of truth**; the exam artifacts (Moodle XML) are derived downstream (see [Downstream](#downstream)).
## Files
| File | Role |
|---|---|
| `00-intro.md` | Intro / organizational deck |
| `01-grundlagen-text-audio.md` | Grundlagen: Text & Audio |
| `02-bild-audio-video.md` | Bild, Audio, Video |
| `03-speichermedien-schnittstellen.md` | Speichermedien & Schnittstellen |
| `04-distribution-apis-zukunft.md` | Distribution, APIs, Zukunft |
| `05-vertiefung-offene-fragen.md` | Vertiefung / offene Fragen |
| `klausurfolien.md` | Exam-review slides |
| `klausurfragen.md` | **Master question catalog — 122 Fragen** (`[MC]/[MM]/[MATCH]/[ORDER]/[ESSAY]/[SHORTANS]/[NUMERIC]/[CLOZE]`) |
| `assets/`, `materials/` | Images and supporting material |
All decks are **Marp** Markdown (`marp: true`, theme `gaia`) with a shared inline `<style>` block. Highlight color for this course: `#1e5f8a` (blue). Sibling deck: `../223015c/` (Internettechnik, highlight `#d63384`).
## Conventions
- Each question in `klausurfragen.md` = `### <ID> – <title>` + `**Thema:**` + `**Punkte:**` + `**Typ:**` + body + `> **Feedback:**`/`> **Musterlösung:**`. Keep this shape — downstream tooling parses `**Thema:**` and `**Typ:**`.
- Correct MC options marked `- [x] **…** ✅`; matching as a 2-column table; ordering as a numbered list.
- `marp` CLI renders to HTML/PDF: `marp <file>.md` (see marp-team/marp-cli).
## Downstream
The **exam question bank + Moodle Quiz XML** live in a separate repo:
- Local: `/home/mwc/Documents/HDM/klausur/`
- Git: `ssh://tengo@git.librete.ch:41240/libretech/2026-hdm-klausur.git`
There, `klausurfragen-b-course-dateiformate.md` is a **curated subset (81/122)** of this deck's `klausurfragen.md`, and the questions are exported as Moodle XML for import. **Edit questions here first**, then sync the subset + regenerate/patch the XML downstream (that repo's CLAUDE.md + `moodle-quiz-xml` skill document the XML format and workflow).
Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

@@ -0,0 +1,205 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Aliasing — derselbe Fehler in zwei Sinnen</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--audio: #ea580c;
--bild: #2563eb;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pair {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.modality {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.modality.audio { border-color: var(--audio); }
.modality.bild { border-color: var(--bild); }
.mod-head { display: flex; justify-content: space-between; align-items: baseline; }
.mod-name { font-size: 1.25rem; font-weight: 700; }
.modality.audio .mod-name { color: var(--audio); }
.modality.bild .mod-name { color: var(--bild); }
.mod-tag { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); }
.canvas {
background: var(--soft);
border-radius: 8px;
overflow: hidden;
}
.canvas svg { display: block; }
.scene-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.scene { display: flex; flex-direction: column; gap: 4px; }
.scene-label {
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
}
.scene-cap {
font-size: 0.78rem;
color: var(--muted);
line-height: 1.4;
font-family: ui-monospace, monospace;
}
.scene-cap strong { color: var(--dark); }
.ear-eye {
font-size: 0.86rem;
line-height: 1.5;
color: var(--dark);
}
.ear-eye .arrow { color: var(--hl); font-weight: 700; }
.ear-eye-headline {
font-size: 0.9rem;
font-weight: 700;
}
.modality.audio .ear-eye-headline { color: var(--audio); }
.modality.bild .ear-eye-headline { color: var(--bild); }
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Aliasing — derselbe Fehler in zwei Sinnen</h1>
<div class="sub">Was im Ohr <strong>Brummen</strong> macht, macht im Auge <strong>Moiré</strong>. Wurzel: Sampling zu grob.</div>
<div class="pair">
<div class="modality audio">
<div class="mod-head">
<span class="mod-name">Audio</span>
<span class="mod-tag">Unterabtastung</span>
</div>
<div class="scene-pair">
<div class="scene">
<div class="scene-label">Original (18 kHz)</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<line x1="0" y1="40" x2="280" y2="40" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M0,40 Q7,5 14,40 T28,40 T42,40 T56,40 T70,40 T84,40 T98,40 T112,40 T126,40 T140,40 T154,40 T168,40 T182,40 T196,40 T210,40 T224,40 T238,40 T252,40 T266,40 T280,40"
stroke="#ea580c" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="scene-cap">20 Schwingungen<br>schnelle Welle</div>
</div>
<div class="scene">
<div class="scene-label">Bei 22 kHz gesampelt</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<line x1="0" y1="40" x2="280" y2="40" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M0,40 Q7,5 14,40 T28,40 T42,40 T56,40 T70,40 T84,40 T98,40 T112,40 T126,40 T140,40 T154,40 T168,40 T182,40 T196,40 T210,40 T224,40 T238,40 T252,40 T266,40 T280,40"
stroke="#fed7aa" stroke-width="1.2" fill="none"/>
<path d="M0,40 Q70,10 140,40 T280,40"
stroke="#ea580c" stroke-width="2.5" fill="none"/>
</svg>
</div>
<div class="scene-cap"><strong>2 Schwingungen</strong><br>Brumm-Frequenz</div>
</div>
</div>
<div class="ear-eye">
<div class="ear-eye-headline">Was das Ohr hört</div>
Ein schriller 18-kHz-Ton wird zu einem dumpfen 4-kHz-Brumm. Das hohe ist <strong>nicht leiser</strong> — es ist <strong>verloren und falsch ersetzt</strong>.
</div>
</div>
<div class="modality bild">
<div class="mod-head">
<span class="mod-name">Bild</span>
<span class="mod-tag">Moiré-Effekt</span>
</div>
<div class="scene-pair">
<div class="scene">
<div class="scene-label">Original (feine Streifen)</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<defs>
<pattern id="fine-real" x="0" y="0" width="3" height="80" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="1.5" height="80" fill="#1e3a8a"/>
</pattern>
</defs>
<rect x="0" y="0" width="280" height="80" fill="url(#fine-real)"/>
</svg>
</div>
<div class="scene-cap">93 Linien<br>volle Auflösung</div>
</div>
<div class="scene">
<div class="scene-label">In niedriger DPI gerendert</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<defs>
<linearGradient id="moire-bands" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#1e3a8a"/>
<stop offset="10%" stop-color="#bfdbfe"/>
<stop offset="20%" stop-color="#1e3a8a"/>
<stop offset="30%" stop-color="#bfdbfe"/>
<stop offset="40%" stop-color="#1e3a8a"/>
<stop offset="50%" stop-color="#bfdbfe"/>
<stop offset="60%" stop-color="#1e3a8a"/>
<stop offset="70%" stop-color="#bfdbfe"/>
<stop offset="80%" stop-color="#1e3a8a"/>
<stop offset="90%" stop-color="#bfdbfe"/>
<stop offset="100%" stop-color="#1e3a8a"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="280" height="80" fill="url(#moire-bands)"/>
</svg>
</div>
<div class="scene-cap"><strong>5 breite Bänder</strong><br>Moiré-Frequenz</div>
</div>
</div>
<div class="ear-eye">
<div class="ear-eye-headline">Was das Auge sieht</div>
Feine Linien sind weg, dafür <strong>breite Streifen</strong>, die nie da waren. Aus 93 Linien werden 5 Bänder — das Bild lügt.
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Aliasing kennt keine Modalität. Es ist ein <strong>mathematischer</strong> Fehler — kein technischer.</div>
<div class="verdict-a">Egal ob Ton, Bild, Video, Radar, GPS — Sampling muss immer mindestens <strong>doppelt</strong> so dicht sein wie das Signal. Sonst tauscht die Realität Frequenzen aus.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

@@ -0,0 +1,172 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Container ≠ Codec</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--container: #2563eb;
--video: #7c3aed;
--audio: #ea580c;
--subs: #16a34a;
--meta: #94a3b8;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.scene {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.container-box {
border: 3px dashed var(--container);
border-radius: 14px;
padding: 14px 16px 18px;
background: #fff;
position: relative;
}
.container-tag {
position: absolute;
top: -12px;
left: 18px;
background: #fff;
padding: 0 10px;
font-family: ui-monospace, monospace;
font-size: 0.78rem;
font-weight: 700;
color: var(--container);
}
.container-label {
text-align: center;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
margin-bottom: 10px;
}
.track {
display: grid;
grid-template-columns: 90px 1fr;
gap: 12px;
align-items: center;
background: var(--soft);
border-left: 4px solid;
border-radius: 6px;
padding: 9px 14px;
margin-bottom: 6px;
}
.track.video { border-left-color: var(--video); }
.track.audio { border-left-color: var(--audio); }
.track.subs { border-left-color: var(--subs); }
.track.meta { border-left-color: var(--meta); }
.track-label {
font-size: 0.78rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.track.video .track-label { color: var(--video); }
.track.audio .track-label { color: var(--audio); }
.track.subs .track-label { color: var(--subs); }
.track.meta .track-label { color: var(--meta); }
.codec-pill {
display: inline-block;
font-family: ui-monospace, monospace;
font-size: 0.82rem;
background: #fff;
border: 1px solid var(--border);
padding: 2px 9px;
border-radius: 4px;
color: var(--dark);
}
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
.verdict-a code { font-family: ui-monospace, monospace; background: var(--soft); padding: 1px 5px; border-radius: 4px; }
</style>
</head>
<body>
<h1>Container ≠ Codec</h1>
<div class="sub">Die <strong>Hülle</strong> sagt nichts darüber, <strong>wie</strong> der Inhalt komprimiert wurde.</div>
<div class="scene">
<div class="container-box">
<span class="container-tag">.mp4</span>
<div class="container-label">Datei A — älterer Stand</div>
<div class="track video">
<span class="track-label">Video</span>
<span><span class="codec-pill">H.264 / AVC</span> · 1080p · 8 Mbit/s</span>
</div>
<div class="track audio">
<span class="track-label">Audio</span>
<span><span class="codec-pill">AAC</span> · 192 kbit/s · Stereo</span>
</div>
<div class="track subs">
<span class="track-label">Untertitel</span>
<span><span class="codec-pill">TTML</span> · de + en</span>
</div>
<div class="track meta">
<span class="track-label">Metadaten</span>
<span>Titel · Dauer · Datum · Bitrate</span>
</div>
</div>
<div class="container-box">
<span class="container-tag">.mp4</span>
<div class="container-label">Datei B — modern</div>
<div class="track video">
<span class="track-label">Video</span>
<span><span class="codec-pill">AV1</span> · 4K · 25 Mbit/s</span>
</div>
<div class="track audio">
<span class="track-label">Audio</span>
<span><span class="codec-pill">Opus</span> · 128 kbit/s · 5.1 Surround</span>
</div>
<div class="track subs">
<span class="track-label">Untertitel</span>
<span><span class="codec-pill">WebVTT</span> · de + en + ja</span>
</div>
<div class="track meta">
<span class="track-label">Metadaten</span>
<span>Titel · Dauer · Datum · HDR-Info</span>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Gleiche Endung. Anderes Innenleben.</div>
<div class="verdict-a"><strong>Container</strong> = Verpackung (<code>.mp4</code>, <code>.mkv</code>, <code>.webm</code>). <strong>Codec</strong> = Komprimierer (H.264 / AV1 / AAC / Opus). <strong>Tool:</strong> <code>mediainfo &lt;datei&gt;</code> zeigt beides.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

@@ -0,0 +1,200 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Drei Dateien — dasselbe Innenleben</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--foto: #2563eb;
--audio: #ea580c;
--pdf: #7c3aed;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 28px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.files {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.file {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.file.foto { border-color: var(--foto); }
.file.audio { border-color: var(--audio); }
.file.pdf { border-color: var(--pdf); }
.file-head { display: flex; justify-content: space-between; align-items: baseline; }
.file-name { font-size: 1.2rem; font-weight: 700; }
.file.foto .file-name { color: var(--foto); }
.file.audio .file-name { color: var(--audio); }
.file.pdf .file-name { color: var(--pdf); }
.file-ext { font-family: ui-monospace, monospace; font-size: 0.78rem; color: var(--muted); }
.preview {
border-radius: 8px;
border: 1px solid var(--border);
overflow: hidden;
display: block;
height: 130px;
background: var(--soft);
}
.hex-strip {
background: #0f0f23;
border-radius: 6px;
padding: 8px 10px;
font-family: ui-monospace, monospace;
font-size: 0.78rem;
line-height: 1.6;
color: #cbd5e1;
overflow: hidden;
}
.hex-strip .magic { color: #fff; font-weight: 700; padding: 0 2px; border-radius: 2px; }
.hex-strip.foto-magic .magic { background: var(--foto); }
.hex-strip.audio-magic .magic { background: var(--audio); }
.hex-strip.pdf-magic .magic { background: var(--pdf); }
.hex-label {
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
font-weight: 700;
margin-bottom: 2px;
}
.magic-caption {
font-size: 0.78rem;
color: var(--muted);
text-align: center;
font-family: ui-monospace, monospace;
}
.magic-caption .magic-word {
color: var(--dark);
font-weight: 700;
}
.verdict {
margin-top: 26px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.15rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.95rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Drei Dateien — dasselbe Innenleben</h1>
<div class="sub">Außen <strong>völlig verschieden</strong>. Innen reden alle dieselbe Sprache: <strong>Byte für Byte</strong>.</div>
<div class="files">
<div class="file foto">
<div class="file-head">
<span class="file-name">Foto</span>
<span class="file-ext">.png</span>
</div>
<svg class="preview" viewBox="0 0 220 130" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="sky-f" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="60%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="220" height="130" fill="url(#sky-f)"/>
<circle cx="160" cy="50" r="18" fill="#fef3c7" opacity="0.95"/>
<path d="M0,95 L40,80 L80,90 L120,72 L160,86 L220,75 L220,130 L0,130 Z" fill="#1e1b4b"/>
<path d="M0,110 L60,100 L120,108 L180,98 L220,105 L220,130 L0,130 Z" fill="#0f172a" opacity="0.7"/>
</svg>
<div>
<div class="hex-label">Erste Bytes der Datei</div>
<div class="hex-strip foto-magic">
<span class="magic">89 50 4E 47</span> 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
</div>
</div>
<div class="magic-caption"><span class="magic-word">50 4E 47</span> = <span class="magic-word">"PNG"</span></div>
</div>
<div class="file audio">
<div class="file-head">
<span class="file-name">Sprachnachricht</span>
<span class="file-ext">.mp3</span>
</div>
<svg class="preview" viewBox="0 0 220 130" preserveAspectRatio="none">
<rect x="0" y="0" width="220" height="130" fill="#0f0f23"/>
<line x1="0" y1="65" x2="220" y2="65" stroke="#374151" stroke-width="1"/>
<path d="M0,65 L8,65 L12,55 L16,75 L20,40 L24,90 L28,30 L32,95 L36,35 L40,90
L48,45 L56,82 L64,50 L72,78 L80,52 L88,75 L96,55 L104,72
L116,58 L128,72 L140,60 L152,70 L168,62 L184,68 L200,64 L220,65
L220,130 L0,130 Z" fill="#fb923c" stroke="#ea580c" stroke-width="1"/>
</svg>
<div>
<div class="hex-label">Erste Bytes der Datei</div>
<div class="hex-strip audio-magic">
<span class="magic">49 44 33</span> 03 00 00 00 00 03 76 54 49 54 32 00 00
</div>
</div>
<div class="magic-caption"><span class="magic-word">49 44 33</span> = <span class="magic-word">"ID3"</span></div>
</div>
<div class="file pdf">
<div class="file-head">
<span class="file-name">PDF-Dokument</span>
<span class="file-ext">.pdf</span>
</div>
<svg class="preview" viewBox="0 0 220 130" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="220" height="130" fill="#f8fafc"/>
<rect x="50" y="14" width="120" height="102" rx="4" fill="#fff" stroke="#cbd5e1" stroke-width="1"/>
<rect x="58" y="24" width="80" height="4" rx="1" fill="#7c3aed"/>
<rect x="58" y="34" width="104" height="2" fill="#cbd5e1"/>
<rect x="58" y="40" width="98" height="2" fill="#cbd5e1"/>
<rect x="58" y="46" width="92" height="2" fill="#cbd5e1"/>
<rect x="58" y="52" width="100" height="2" fill="#cbd5e1"/>
<rect x="58" y="62" width="80" height="2" fill="#cbd5e1"/>
<rect x="58" y="68" width="96" height="2" fill="#cbd5e1"/>
<rect x="58" y="74" width="88" height="2" fill="#cbd5e1"/>
<rect x="58" y="84" width="40" height="3" rx="1" fill="#7c3aed" opacity="0.7"/>
<rect x="58" y="92" width="92" height="2" fill="#cbd5e1"/>
<rect x="58" y="98" width="86" height="2" fill="#cbd5e1"/>
<rect x="58" y="104" width="78" height="2" fill="#cbd5e1"/>
</svg>
<div>
<div class="hex-label">Erste Bytes der Datei</div>
<div class="hex-strip pdf-magic">
<span class="magic">25 50 44 46</span> 2D 31 2E 37 0A 25 E2 E3 CF D3 0A 0A
</div>
</div>
<div class="magic-caption"><span class="magic-word">25 50 44 46</span> = <span class="magic-word">"%PDF"</span></div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Drei verschiedene Dinge — eine Sprache.</div>
<div class="verdict-a">Jede Datei beginnt mit ihrer <strong>Visitenkarte</strong> (Magic Number) und besteht ab da aus nichts als Byte. Foto, Audio, PDF — alle dieselben Bauteile, nur anders zusammengesetzt.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>JPEG-Pipeline — 6 Schritte vom Foto zur Datei</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--lossless-step: #2563eb;
--lossy-step: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 26px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pipeline {
display: grid;
grid-template-columns: 110px repeat(6, 1fr) 110px;
gap: 4px;
max-width: 1200px;
margin: 0 auto;
align-items: stretch;
}
.endpoint {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 6px;
text-align: center;
}
.endpoint-art { width: 88px; height: 60px; display: block; }
.endpoint-label {
font-size: 0.92rem;
font-weight: 700;
color: var(--dark);
}
.endpoint-size {
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--muted);
}
.step {
border: 2px solid;
border-radius: 8px;
padding: 8px 6px;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
text-align: center;
}
.step.lossless { border-color: var(--lossless-step); }
.step.lossy { border-color: var(--lossy-step); }
.step-num {
font-family: ui-monospace, monospace;
font-size: 0.72rem;
font-weight: 700;
color: var(--muted);
}
.step-name {
font-size: 0.78rem;
font-weight: 700;
line-height: 1.2;
}
.step.lossless .step-name { color: var(--lossless-step); }
.step.lossy .step-name { color: var(--lossy-step); }
.step-desc {
font-size: 0.66rem;
color: var(--muted);
line-height: 1.3;
}
.arrow {
display: flex;
align-items: center;
justify-content: center;
color: var(--muted);
font-family: ui-monospace, monospace;
font-size: 1rem;
}
.legend {
margin-top: 16px;
display: flex;
justify-content: center;
gap: 24px;
font-size: 0.84rem;
color: var(--dark);
}
.legend-item { display: flex; align-items: center; gap: 6px; }
.legend-swatch {
width: 14px;
height: 14px;
border-radius: 3px;
display: inline-block;
}
.legend-swatch.lossless { background: var(--lossless-step); }
.legend-swatch.lossy { background: var(--lossy-step); }
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>JPEG-Pipeline — 6 Schritte vom Foto zur Datei</h1>
<div class="sub">Nur <strong>einer</strong> dieser Schritte verliert Information. Die anderen fünf sind verlustfrei.</div>
<div class="pipeline">
<div class="endpoint">
<svg class="endpoint-art" viewBox="0 0 88 60">
<defs>
<linearGradient id="photo-grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="88" height="60" rx="3" fill="url(#photo-grad)"/>
<circle cx="66" cy="22" r="9" fill="#fef3c7"/>
<path d="M0,42 L18,34 L40,40 L60,30 L80,38 L88,33 L88,60 L0,60 Z" fill="#1e1b4b"/>
</svg>
<div class="endpoint-label">Foto (Roh)</div>
<div class="endpoint-size">~36 MB</div>
</div>
<div class="step lossless">
<div class="step-num">1</div>
<div class="step-name">Farbraum</div>
<div class="step-desc">RGB → Y'CbCr<br>Helligkeit von Farbe trennen</div>
</div>
<div class="step lossy">
<div class="step-num">2</div>
<div class="step-name">Chroma-Subsampling</div>
<div class="step-desc">Cb &amp; Cr auf <strong>¼</strong><br>Auge sieht Farbe grob</div>
</div>
<div class="step lossless">
<div class="step-num">3</div>
<div class="step-name">8×8 Blöcke</div>
<div class="step-desc">Bild in Kacheln<br>jeder Block einzeln</div>
</div>
<div class="step lossless">
<div class="step-num">4</div>
<div class="step-name">DCT</div>
<div class="step-desc">Frequenz-Zerlegung<br>häufige Muster</div>
</div>
<div class="step lossy">
<div class="step-num">5</div>
<div class="step-name">Quantisierung</div>
<div class="step-desc"><strong>Hier</strong> wird weggeworfen<br>hohe Frequenzen raus</div>
</div>
<div class="step lossless">
<div class="step-num">6</div>
<div class="step-name">Huffman</div>
<div class="step-desc">Verlustfrei kürzen<br>häufig → kurz</div>
</div>
<div class="endpoint">
<svg class="endpoint-art" viewBox="0 0 88 60">
<rect x="0" y="0" width="88" height="60" rx="3" fill="url(#photo-grad)"/>
<circle cx="66" cy="22" r="9" fill="#fef3c7"/>
<path d="M0,42 L18,34 L40,40 L60,30 L80,38 L88,33 L88,60 L0,60 Z" fill="#1e1b4b"/>
</svg>
<div class="endpoint-label">JPEG</div>
<div class="endpoint-size">~3,5 MB</div>
</div>
</div>
<div class="legend">
<span class="legend-item"><span class="legend-swatch lossless"></span>verlustfrei (umkehrbar)</span>
<span class="legend-item"><span class="legend-swatch lossy"></span>verlustbehaftet (Information weg)</span>
</div>
<div class="verdict">
<div class="verdict-q">Der <strong>Quanten-Schritt</strong> ist das ganze Geheimnis von JPEG.</div>
<div class="verdict-a">Schritte 1, 3, 4, 6 verlieren nichts. Schritt 2 wirft Farb-Detail weg (Auge merkt nicht). Schritt 5 entscheidet — je nach Qualitäts-Stufe — wie viel <strong>Frequenz-Detail</strong> verloren geht. Niedrige Quality = aggressivere Schritt-5-Quantisierung.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

@@ -0,0 +1,182 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Die Reise einer Datei</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--slot1: #0891b2;
--slot2: #2563eb;
--slot3: #7c3aed;
--slot4: #be185d;
--slot5: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 30px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.journey {
display: grid;
grid-template-columns: 1fr auto 1fr auto 1fr auto 1fr auto 1fr;
gap: 6px;
align-items: stretch;
max-width: 1200px;
margin: 0 auto;
}
.station {
border: 2px solid;
border-radius: 10px;
padding: 14px 12px 12px;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.station.s1 { border-color: var(--slot1); }
.station.s2 { border-color: var(--slot2); }
.station.s3 { border-color: var(--slot3); }
.station.s4 { border-color: var(--slot4); }
.station.s5 { border-color: var(--slot5); }
.station-tag { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); }
.station-name { font-size: 1.05rem; font-weight: 700; text-align: center; line-height: 1.2; }
.station.s1 .station-name { color: var(--slot1); }
.station.s2 .station-name { color: var(--slot2); }
.station.s3 .station-name { color: var(--slot3); }
.station.s4 .station-name { color: var(--slot4); }
.station.s5 .station-name { color: var(--slot5); }
.station-detail { font-size: 0.78rem; color: var(--muted); text-align: center; }
.link {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 0 4px;
justify-content: center;
}
.link-rate {
font-family: ui-monospace, monospace;
font-size: 0.88rem;
font-weight: 700;
color: var(--dark);
white-space: nowrap;
}
.link-protocol {
font-size: 0.7rem;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.link-arrow svg { width: 32px; height: 14px; }
.scenario {
margin-top: 28px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 16px 22px;
}
.scenario-head { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: 6px; }
.scenario-body { font-size: 0.98rem; line-height: 1.55; }
.scenario-body code { font-family: ui-monospace, monospace; background: #fff; padding: 1px 6px; border-radius: 4px; border: 1px solid var(--border); }
.verdict {
margin-top: 18px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.92rem; color: var(--dark); margin-top: 4px; }
</style>
</head>
<body>
<h1>Die Reise einer Datei</h1>
<div class="sub">Ein 4K-Trailer (<strong>1,2 GB</strong>) reist von der externen SSD auf den Monitor — jede Etappe ist ein eigener Engpass.</div>
<div class="journey">
<div class="station s1">
<div class="station-tag">Quelle</div>
<div class="station-name">SSD<br>extern</div>
<div class="station-detail">NVMe-Stick</div>
</div>
<div class="link">
<div class="link-rate">3 200 MB/s</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">USB 4 / TB4</div>
</div>
<div class="station s2">
<div class="station-tag">Aufnahme</div>
<div class="station-name">Laptop</div>
<div class="station-detail">RAM &amp; CPU</div>
</div>
<div class="link">
<div class="link-rate">~7 000 MB/s</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">PCIe 4.0</div>
</div>
<div class="station s3">
<div class="station-tag">Decoder</div>
<div class="station-name">GPU</div>
<div class="station-detail">H.264-Hardware</div>
</div>
<div class="link">
<div class="link-rate">2 200 MB/s</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">HDMI 2.1</div>
</div>
<div class="station s4">
<div class="station-tag">Display</div>
<div class="station-name">4K-Monitor</div>
<div class="station-detail">3840 × 2160</div>
</div>
<div class="link">
<div class="link-rate">visuell</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">Licht</div>
</div>
<div class="station s5">
<div class="station-tag">Ziel</div>
<div class="station-name">Auge</div>
<div class="station-detail">Bewusstsein</div>
</div>
</div>
<div class="scenario">
<div class="scenario-head">Was hier passiert</div>
<div class="scenario-body">
Die <code>1,2 GB</code> liegen verschlüsselt komprimiert auf dem Stick. Sie reisen über <strong>USB-C</strong> in den RAM, werden vom GPU <strong>dekodiert</strong> (H.264 → roher RGB-Strom), und über <strong>HDMI</strong> als unkomprimiertes Bild an den Monitor geschickt. Dort entstehen pro Sekunde 60 Bilder mit je rund <code>24 MB</code> — also <strong>1,4 GB/s an rohem Pixelstrom</strong>, der niemals als Datei vorliegt.
</div>
</div>
<div class="verdict">
<div class="verdict-q">Speicher und Schnittstelle sind keine zwei Themen — sie sind die zwei Seiten desselben Engpasses.</div>
<div class="verdict-a">Wo Bytes wohnen entscheidet, wie schnell sie reisen können. Wo sie reisen entscheidet, wo sie wohnen müssen.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

@@ -0,0 +1,254 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Eine Datei reist — und erzählt</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--visible: #2563eb;
--hidden: #7c3aed;
--transit: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.scene {
display: grid;
grid-template-columns: 1fr 1.2fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.panel {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 10px;
}
.panel.visible { border-color: var(--visible); }
.panel.hidden { border-color: var(--hidden); }
.panel-head { display: flex; justify-content: space-between; align-items: baseline; }
.panel-tag {
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--muted);
}
.panel-name { font-size: 1.25rem; font-weight: 700; }
.panel.visible .panel-name { color: var(--visible); }
.panel.hidden .panel-name { color: var(--hidden); }
.photo {
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border);
display: block;
}
.photo-meta {
display: flex;
justify-content: space-between;
font-family: ui-monospace, monospace;
font-size: 0.78rem;
color: var(--muted);
padding: 0 2px;
}
.exif-list {
display: grid;
grid-template-columns: 130px 1fr;
gap: 4px 12px;
font-size: 0.86rem;
line-height: 1.4;
}
.exif-key {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted);
padding-top: 3px;
}
.exif-val { font-family: ui-monospace, monospace; color: var(--dark); }
.exif-val.gps { color: var(--hl); font-weight: 700; }
.transit-strip {
max-width: 1200px;
margin: 18px auto 0;
border: 2px solid var(--transit);
border-radius: 12px;
padding: 14px 18px;
background: #fff;
display: grid;
grid-template-columns: auto 1fr;
gap: 16px;
align-items: center;
}
.transit-tag {
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--transit);
writing-mode: vertical-rl;
transform: rotate(180deg);
text-align: center;
}
.transit-body { display: flex; flex-direction: column; gap: 8px; }
.transit-route {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.92rem;
font-weight: 700;
flex-wrap: wrap;
}
.hop {
background: var(--soft);
border: 1.5px solid var(--border);
padding: 4px 10px;
border-radius: 6px;
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--dark);
}
.hop.origin { border-color: var(--visible); color: var(--visible); }
.hop.dest { border-color: var(--visible); color: var(--visible); }
.hop.edge { border-color: var(--transit); color: var(--transit); }
.arrow { color: var(--muted); font-family: ui-monospace, monospace; }
.transit-headers {
font-family: ui-monospace, monospace;
font-size: 0.78rem;
color: var(--muted);
line-height: 1.5;
}
.transit-headers strong { color: var(--dark); }
.verdict {
margin-top: 18px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Eine Datei reist — und erzählt</h1>
<div class="sub">Ein Smartphone-Foto geht von <strong>Stuttgart</strong> nach <strong>Tokyo</strong>. Was sieht der Empfänger — und was bekommt er noch dazu?</div>
<div class="scene">
<div class="panel visible">
<div class="panel-head">
<span class="panel-name">Inhalt</span>
<span class="panel-tag">Was du siehst</span>
</div>
<svg class="photo" viewBox="0 0 420 280" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fda4af"/>
<stop offset="100%" stop-color="#9333ea"/>
</linearGradient>
<linearGradient id="hills" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#312e81"/>
<stop offset="100%" stop-color="#0f172a"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="420" height="280" fill="url(#sky)"/>
<circle cx="320" cy="105" r="32" fill="#fff7ed" opacity="0.95"/>
<path d="M0,200 L60,170 L110,185 L160,160 L210,178 L260,150 L310,172 L360,148 L420,168 L420,280 L0,280 Z" fill="url(#hills)"/>
<path d="M0,225 L50,210 L100,222 L150,205 L200,220 L250,202 L300,218 L350,200 L420,215 L420,280 L0,280 Z" fill="#1e1b4b" opacity="0.7"/>
<rect x="80" y="225" width="14" height="42" fill="#0f172a"/>
<rect x="180" y="232" width="10" height="35" fill="#0f172a"/>
<rect x="240" y="220" width="18" height="48" fill="#0f172a"/>
<rect x="300" y="234" width="11" height="34" fill="#0f172a"/>
<rect x="86" y="232" width="3" height="3" fill="#fbbf24"/>
<rect x="188" y="240" width="2" height="2" fill="#fbbf24"/>
<rect x="248" y="228" width="3" height="3" fill="#fbbf24"/>
<rect x="307" y="240" width="2" height="2" fill="#fbbf24"/>
</svg>
<div class="photo-meta">
<span>HEIC · 4032 × 3024</span>
<span>3,2 MB</span>
</div>
</div>
<div class="panel hidden">
<div class="panel-head">
<span class="panel-name">Gepäck</span>
<span class="panel-tag">Was die Datei über sich weiß</span>
</div>
<div class="exif-list">
<div class="exif-key">Kamera</div>
<div class="exif-val">Apple iPhone 15 Pro · 24 mm · ƒ/1.78</div>
<div class="exif-key">Belichtung</div>
<div class="exif-val">1/250 s · ISO 100 · EV 0</div>
<div class="exif-key">Aufgenommen</div>
<div class="exif-val">2026-04-12 · 18:47:12 · +02:00</div>
<div class="exif-key">GPS</div>
<div class="exif-val gps">48.7847° N · 9.1825° E · 248 m<br><span style="font-weight:400">(Stuttgart, Königstraße 28)</span></div>
<div class="exif-key">Software</div>
<div class="exif-val">iOS 18.4.1 · HDR · Live Photo</div>
<div class="exif-key">Farbprofil</div>
<div class="exif-val">Display P3</div>
</div>
</div>
</div>
<div class="transit-strip">
<div class="transit-tag">Weg</div>
<div class="transit-body">
<div class="transit-route">
<span class="hop origin">Stuttgart</span>
<span class="arrow">→</span>
<span class="hop">DNS</span>
<span class="arrow">→</span>
<span class="hop">TLS 1.3</span>
<span class="arrow">→</span>
<span class="hop edge">CDN-Edge Tokyo</span>
<span class="arrow">→</span>
<span class="hop dest">Tokyo</span>
</div>
<div class="transit-headers">
<strong>HTTP/3 200 OK</strong> · content-type: image/heic · content-length: 3 220 480 · <strong>RTT 47 ms</strong> · cache: HIT (Edge tok-7) · age: 312 s
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Eine Datei = Inhalt + Gepäck + Weg.</div>
<div class="verdict-a"><strong>Inhalt</strong> sieht der Empfänger. <strong>Gepäck</strong> verrät, wer sie gemacht hat — und wo. <strong>Weg</strong> entscheidet, wie schnell sie ankommt. Drei Schichten, eine Datei.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

+194
View File
@@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>1 TB verkauft, 931 GB angezeigt — wo gehen die 69 GB hin?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--marketing: #2563eb;
--os: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.compare {
display: grid;
grid-template-columns: 1fr 80px 1fr;
gap: 18px;
max-width: 1100px;
margin: 0 auto;
align-items: stretch;
}
.side {
border: 2px solid;
border-radius: 12px;
padding: 18px 22px;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.side.marketing { border-color: var(--marketing); }
.side.os { border-color: var(--os); }
.side-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.side.marketing .side-name { color: var(--marketing); }
.side.os .side-name { color: var(--os); }
.side-name { font-size: 1.15rem; font-weight: 700; }
.label-mock {
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 8px;
padding: 14px 22px;
min-width: 240px;
text-align: center;
font-family: ui-monospace, monospace;
font-size: 0.85rem;
color: var(--muted);
line-height: 1.5;
}
.label-mock .big {
font-family: system-ui, sans-serif;
font-size: 2.2rem;
font-weight: 900;
display: block;
color: var(--dark);
line-height: 1.05;
}
.side.marketing .label-mock .big { color: var(--marketing); }
.side.os .label-mock .big { color: var(--os); }
.label-mock .small-line { font-size: 0.78rem; }
.formel {
font-family: ui-monospace, monospace;
font-size: 0.85rem;
color: var(--muted);
text-align: center;
line-height: 1.6;
}
.formel strong { color: var(--dark); }
.arrow-col {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
color: var(--muted);
}
.arrow-col svg { display: block; }
.arrow-col .why {
font-size: 0.78rem;
font-weight: 700;
color: var(--hl);
text-align: center;
line-height: 1.25;
}
.math-box {
margin-top: 22px;
max-width: 1100px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 16px 22px;
}
.math-box-head { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: 8px; }
.math-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 22px; font-family: ui-monospace, monospace; font-size: 0.9rem; line-height: 1.6; }
.math-grid .key { color: var(--muted); }
.math-grid .val { color: var(--dark); font-weight: 700; }
.math-grid .val.hl { color: var(--hl); }
.verdict {
margin-top: 18px;
max-width: 1100px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.05rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a code { font-family: ui-monospace, monospace; background: #fff; padding: 1px 5px; border-radius: 4px; border: 1px solid var(--border); }
</style>
</head>
<body>
<h1>„1 TB" gekauft — 931 GB im Finder. Wo sind die 69 GB hin?</h1>
<div class="sub">Nirgendwo. Es sind <strong>dieselben Byte</strong>. Nur zwei Welten zählen anders.</div>
<div class="compare">
<div class="side marketing">
<div class="side-tag">Auf der Verpackung</div>
<div class="side-name">Marketing</div>
<div class="label-mock">
<span class="big">1 TB</span>
<span class="small-line">externe SSD</span>
</div>
<div class="formel">
1 TB = <strong>10<sup>12</sup></strong> Byte<br>
= 1 000 000 000 000
</div>
</div>
<div class="arrow-col">
<svg viewBox="0 0 60 30" width="56" height="30"><path d="M5,15 L48,15 M42,7 L52,15 L42,23" stroke="#d63384" stroke-width="2.5" fill="none"/></svg>
<div class="why">geteilt durch<br>2<sup>30</sup></div>
</div>
<div class="side os">
<div class="side-tag">Im Finder · Explorer</div>
<div class="side-name">Betriebssystem</div>
<div class="label-mock">
<span class="big">931 GB</span>
<span class="small-line">eigentlich: 931 GiB</span>
</div>
<div class="formel">
1 GiB = <strong>2<sup>30</sup></strong> Byte<br>
= 1 073 741 824
</div>
</div>
</div>
<div class="math-box">
<div class="math-box-head">Die Rechnung</div>
<div class="math-grid">
<span class="key">Marketing schreibt</span>
<span class="val">1 TB = 1 000 000 000 000 Byte (Basis 10)</span>
<span class="key">Betriebssystem rechnet</span>
<span class="val">1 TiB = 1 099 511 627 776 Byte (Basis 2)</span>
<span class="key">1 TB in GiB umrechnen</span>
<span class="val hl">10<sup>12</sup> ÷ 2<sup>30</sup> ≈ 931,3 GiB — der Finder zeigt also „931 GB"</span>
<span class="key">Was die Studis sehen</span>
<span class="val">Etikett: GB · Anzeige: GB · Bedeutung: zwei verschiedene Dinge</span>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Es fehlt nichts. Es wird nur in zwei Sprachen gezählt.</div>
<div class="verdict-a">Korrekt wären <code>GiB</code> (binär, 1024) und <code>GB</code> (dezimal, 1000). In der Realität verwenden beide Welten <code>GB</code> und meinen verschiedene Zahlen.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

@@ -0,0 +1,232 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Nyquist-Shannon — wie oft muss man messen?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--bad: #ef4444;
--warn: #f59e0b;
--good: #16a34a;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.cases {
display: flex;
flex-direction: column;
gap: 12px;
max-width: 1180px;
margin: 0 auto;
}
.case {
display: grid;
grid-template-columns: 200px 1fr;
gap: 18px;
align-items: center;
border: 2px solid;
border-radius: 10px;
padding: 10px 14px;
background: #fff;
}
.case.bad { border-color: var(--bad); }
.case.warn { border-color: var(--warn); }
.case.good { border-color: var(--good); }
.case-meta { display: flex; flex-direction: column; gap: 4px; }
.case-tag {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.case-name { font-size: 1.05rem; font-weight: 700; }
.case.bad .case-name { color: var(--bad); }
.case.warn .case-name { color: var(--warn); }
.case.good .case-name { color: var(--good); }
.case-rate { font-family: ui-monospace, monospace; font-size: 0.82rem; color: var(--dark); }
.case-note { font-size: 0.78rem; color: var(--muted); line-height: 1.35; }
.plot { background: var(--soft); border-radius: 8px; }
.plot svg { display: block; }
.verdict {
margin-top: 20px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.05rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.92rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
.verdict-a code { font-family: ui-monospace, monospace; background: var(--soft); padding: 1px 5px; border-radius: 4px; }
</style>
</head>
<body>
<h1>Nyquist-Shannon — wie oft müssen wir messen?</h1>
<div class="sub">Dieselbe Welle, drei Sample-Raten. Eine fällt durch, eine reicht knapp, eine ist sicher.</div>
<div class="cases">
<div class="case bad">
<div class="case-meta">
<div class="case-tag">Zu wenig</div>
<div class="case-name">Aliasing</div>
<div class="case-rate">f<sub>s</sub> = 0,9 · f</div>
<div class="case-note">Die Sample-Punkte sitzen auf der Welle — aber verbunden sehen sie aus wie eine <strong>ganz andere, langsamere</strong> Welle.</div>
</div>
<div class="plot">
<svg viewBox="0 0 880 140" width="100%" height="140" preserveAspectRatio="none">
<line x1="20" y1="70" x2="860" y2="70" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M 20,70 Q 46.25,-20 72.5,70 T 125,70 T 177.5,70 T 230,70 T 282.5,70 T 335,70 T 387.5,70 T 440,70 T 492.5,70 T 545,70 T 597.5,70 T 650,70 T 702.5,70 T 755,70 T 807.5,70 T 860,70"
stroke="#cbd5e1" stroke-width="1.5" fill="none"/>
<polyline points="20,70 136.7,41 253.4,25.7 370.1,31.2 486.8,54.9 603.5,85.8 720.2,109.2 836.9,114.2"
stroke="#ef4444" stroke-width="2.5" fill="none"/>
<circle cx="20" cy="70" r="5" fill="#ef4444"/>
<circle cx="136.7" cy="41" r="5" fill="#ef4444"/>
<circle cx="253.4" cy="25.7" r="5" fill="#ef4444"/>
<circle cx="370.1" cy="31.2" r="5" fill="#ef4444"/>
<circle cx="486.8" cy="54.9" r="5" fill="#ef4444"/>
<circle cx="603.5" cy="85.8" r="5" fill="#ef4444"/>
<circle cx="720.2" cy="109.2" r="5" fill="#ef4444"/>
<circle cx="836.9" cy="114.2" r="5" fill="#ef4444"/>
</svg>
</div>
</div>
<div class="case warn">
<div class="case-meta">
<div class="case-tag">Genau</div>
<div class="case-name">Nyquist-Grenze</div>
<div class="case-rate">f<sub>s</sub> = 2 · f</div>
<div class="case-note">Sample exakt auf <strong>Peak und Tal</strong>. Mathematisch reicht das — visuell sieht es kaputt aus.</div>
</div>
<div class="plot">
<svg viewBox="0 0 880 140" width="100%" height="140" preserveAspectRatio="none">
<line x1="20" y1="70" x2="860" y2="70" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M 20,70 Q 46.25,-20 72.5,70 T 125,70 T 177.5,70 T 230,70 T 282.5,70 T 335,70 T 387.5,70 T 440,70 T 492.5,70 T 545,70 T 597.5,70 T 650,70 T 702.5,70 T 755,70 T 807.5,70 T 860,70"
stroke="#cbd5e1" stroke-width="1.5" fill="none"/>
<polyline points="46.25,25 98.75,115 151.25,25 203.75,115 256.25,25 308.75,115 361.25,25 413.75,115 466.25,25 518.75,115 571.25,25 623.75,115 676.25,25 728.75,115 781.25,25 833.75,115"
stroke="#f59e0b" stroke-width="2" fill="none" opacity="0.5"/>
<circle cx="46.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="98.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="151.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="203.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="256.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="308.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="361.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="413.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="466.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="518.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="571.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="623.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="676.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="728.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="781.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="833.75" cy="115" r="5" fill="#f59e0b"/>
</svg>
</div>
</div>
<div class="case good">
<div class="case-meta">
<div class="case-tag">Sicher</div>
<div class="case-name">Überabtastung</div>
<div class="case-rate">f<sub>s</sub> = 8 · f</div>
<div class="case-note">Genug Punkte — die Welle wird Punkt für Punkt nachgezeichnet. So macht es eine CD.</div>
</div>
<div class="plot">
<svg viewBox="0 0 880 140" width="100%" height="140" preserveAspectRatio="none">
<line x1="20" y1="70" x2="860" y2="70" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M 20,70 Q 46.25,-20 72.5,70 T 125,70 T 177.5,70 T 230,70 T 282.5,70 T 335,70 T 387.5,70 T 440,70 T 492.5,70 T 545,70 T 597.5,70 T 650,70 T 702.5,70 T 755,70 T 807.5,70 T 860,70"
stroke="#16a34a" stroke-width="2.5" fill="none" opacity="0.9"/>
<circle cx="20" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="33.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="46.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="59.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="72.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="85.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="98.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="111.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="125" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="138.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="151.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="164.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="177.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="190.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="203.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="216.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="230" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="243.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="256.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="269.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="282.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="295.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="308.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="321.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="335" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="348.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="361.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="374.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="387.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="400.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="413.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="426.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="440" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="453.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="466.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="479.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="492.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="505.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="518.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="531.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="545" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="558.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="571.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="584.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="597.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="610.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="623.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="636.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="650" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="663.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="676.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="689.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="702.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="715.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="728.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="741.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="755" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="768.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="781.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="794.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="807.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="820.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="833.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="846.9" cy="101.8" r="2.5" fill="#16a34a"/>
</svg>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">f<sub>s</sub> ≥ 2 · f<sub>max</sub>. So einfach. So endgültig.</div>
<div class="verdict-a">Das Ohr hört bis <strong>20 kHz</strong>. 2 × 20 = 40 kHz. Die CD nimmt <code>44,1 kHz</code> — die 4,1 sind Sicherheits-Marge.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Wir haben gelernt zu lesen — jetzt: wie kommt es rein?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--done: #94a3b8;
--next: #d63384;
--bytes: #0891b2;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.7rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 36px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pivot {
display: grid;
grid-template-columns: 200px 1fr 240px 1fr 200px;
gap: 8px;
max-width: 1200px;
margin: 0 auto;
align-items: center;
}
.station {
border: 2px solid var(--border);
border-radius: 12px;
padding: 18px 14px;
background: #fff;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.station.bytes { border-color: var(--bytes); background: #0f0f23; color: #fff; }
.station-tag {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.station.bytes .station-tag { color: #94a3b8; }
.station-name { font-size: 1.3rem; font-weight: 700; }
.station.bytes .station-name { color: #67e8f9; }
.station-detail { font-size: 0.85rem; color: var(--muted); }
.station.bytes .station-detail { color: #94a3b8; font-family: ui-monospace, monospace; font-size: 0.78rem; line-height: 1.4; }
.station-art { display: flex; align-items: center; justify-content: center; height: 70px; }
.station-art svg { width: 80%; height: 100%; }
.strang {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 0 6px;
}
.strang-arrow svg { display: block; width: 100%; height: 28px; }
.strang-label {
font-size: 0.95rem;
font-weight: 700;
text-align: center;
line-height: 1.3;
}
.strang.next .strang-label { color: var(--next); }
.strang.done .strang-label { color: var(--done); text-decoration: line-through; text-decoration-color: var(--done); text-decoration-thickness: 1.5px; }
.strang-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
text-align: center;
}
.strang.next .strang-tag { color: var(--next); }
.strang.done .strang-tag { color: var(--done); }
.verdict {
margin-top: 28px;
max-width: 1100px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.95rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Wir haben gelernt zu <strong>lesen</strong>. Jetzt: wie kommt es <strong>rein</strong>?</h1>
<div class="sub">Die rechte Seite haben wir abgearbeitet. Die linke ist die nächste Stunde.</div>
<div class="pivot">
<div class="station">
<div class="station-tag">Quelle</div>
<div class="station-name">Welt</div>
<div class="station-art">
<svg viewBox="0 0 120 70" preserveAspectRatio="xMidYMid meet">
<path d="M5,35 Q15,10 25,35 T45,35 T65,35 T85,35 T105,35 T115,35"
stroke="#d63384" stroke-width="2.5" fill="none"/>
<circle cx="115" cy="35" r="3" fill="#d63384"/>
</svg>
</div>
<div class="station-detail">Schallwelle · Lichtwelle<br>kontinuierlich · analog</div>
</div>
<div class="strang next">
<div class="strang-tag">jetzt dran</div>
<div class="strang-arrow">
<svg viewBox="0 0 220 28" preserveAspectRatio="none">
<line x1="6" y1="14" x2="200" y2="14" stroke="#d63384" stroke-width="2.5"/>
<path d="M195,7 L208,14 L195,21" stroke="#d63384" stroke-width="2.5" fill="none"/>
</svg>
</div>
<div class="strang-label">Sampling + Quantisierung</div>
</div>
<div class="station bytes">
<div class="station-tag">Mitte</div>
<div class="station-name">Datei</div>
<div class="station-detail">
89 50 4E 47<br>
0D 0A 1A 0A<br>
00 00 00 0D
</div>
</div>
<div class="strang done">
<div class="strang-tag">schon durch</div>
<div class="strang-arrow">
<svg viewBox="0 0 220 28" preserveAspectRatio="none">
<line x1="6" y1="14" x2="200" y2="14" stroke="#94a3b8" stroke-width="2"/>
<path d="M195,7 L208,14 L195,21" stroke="#94a3b8" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="strang-label">Notation · Encoding · Format</div>
</div>
<div class="station">
<div class="station-tag">Ziel</div>
<div class="station-name">Mensch</div>
<div class="station-art">
<svg viewBox="0 0 120 70" preserveAspectRatio="xMidYMid meet">
<rect x="14" y="14" width="92" height="14" rx="2" fill="#1a1a2e"/>
<rect x="14" y="34" width="68" height="6" rx="1" fill="#cbd5e1"/>
<rect x="14" y="44" width="78" height="6" rx="1" fill="#cbd5e1"/>
<rect x="14" y="54" width="56" height="6" rx="1" fill="#cbd5e1"/>
</svg>
</div>
<div class="station-detail">Text · Bild · Klang<br>Bedeutung</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Die Datei ist die Mitte. Beide Wege führen durch sie hindurch.</div>
<div class="verdict-a"><strong>Rechts:</strong> aus Byte wird Bedeutung — gerade gelernt. &nbsp;&nbsp; <strong>Links:</strong> aus Welt wird Byte — jetzt.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

@@ -0,0 +1,159 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Psychoakustik — was MP3 weglässt</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--kept: #16a34a;
--tossed: #94a3b8;
--masker: #2563eb;
--threshold: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.chart-wrap {
max-width: 1180px;
margin: 0 auto;
background: #fff;
border: 1.5px solid var(--border);
border-radius: 12px;
padding: 16px 20px;
}
.chart-head {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 8px;
}
.chart-title { font-size: 1rem; font-weight: 700; }
.legend {
display: flex;
gap: 16px;
font-size: 0.78rem;
color: var(--muted);
}
.legend-item { display: flex; align-items: center; gap: 4px; }
.legend-swatch {
width: 14px;
height: 14px;
border-radius: 3px;
display: inline-block;
}
.legend-swatch.kept { background: var(--kept); }
.legend-swatch.tossed { background: var(--tossed); }
.legend-swatch.masker { background: var(--masker); }
.legend-swatch.threshold {
background: transparent;
border-top: 2px dashed var(--threshold);
height: 8px;
margin-top: 5px;
}
.verdict {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Psychoakustik — was MP3 wegwirft</h1>
<div class="sub">Ein lauter Ton macht leise Nachbarn <strong>unhörbar</strong>. Was nicht hörbar ist, muss man nicht speichern.</div>
<div class="chart-wrap">
<div class="chart-head">
<div class="chart-title">Lautstärke (dB SPL) über Frequenz (Hz, logarithmisch)</div>
<div class="legend">
<span class="legend-item"><span class="legend-swatch masker"></span>lauter Ton (Masker)</span>
<span class="legend-item"><span class="legend-swatch kept"></span>hörbar · bleibt</span>
<span class="legend-item"><span class="legend-swatch tossed"></span>maskiert · raus</span>
<span class="legend-item"><span class="legend-swatch threshold"></span>Hörschwelle</span>
</div>
</div>
<svg viewBox="0 0 1100 380" width="100%" height="380">
<line x1="80" y1="340" x2="1060" y2="340" stroke="#1a1a2e" stroke-width="1.5"/>
<line x1="80" y1="20" x2="80" y2="340" stroke="#1a1a2e" stroke-width="1.5"/>
<text x="20" y="30" font-size="11" fill="#6b7280">dB</text>
<text x="40" y="50" font-size="10" fill="#6b7280" text-anchor="end">100</text>
<text x="40" y="125" font-size="10" fill="#6b7280" text-anchor="end">75</text>
<text x="40" y="200" font-size="10" fill="#6b7280" text-anchor="end">50</text>
<text x="40" y="275" font-size="10" fill="#6b7280" text-anchor="end">25</text>
<text x="40" y="345" font-size="10" fill="#6b7280" text-anchor="end">0</text>
<line x1="75" y1="50" x2="80" y2="50" stroke="#1a1a2e"/>
<line x1="75" y1="125" x2="80" y2="125" stroke="#1a1a2e"/>
<line x1="75" y1="200" x2="80" y2="200" stroke="#1a1a2e"/>
<line x1="75" y1="275" x2="80" y2="275" stroke="#1a1a2e"/>
<text x="100" y="360" font-size="10" fill="#6b7280">20</text>
<text x="260" y="360" font-size="10" fill="#6b7280">100</text>
<text x="420" y="360" font-size="10" fill="#6b7280">500</text>
<text x="580" y="360" font-size="10" fill="#6b7280">1k</text>
<text x="740" y="360" font-size="10" fill="#6b7280">5k</text>
<text x="900" y="360" font-size="10" fill="#6b7280">10k</text>
<text x="1040" y="360" font-size="10" fill="#6b7280">20k</text>
<text x="540" y="378" font-size="11" fill="#6b7280" text-anchor="middle">Frequenz [Hz]</text>
<path d="M100,80 Q170,130 260,200 Q350,290 420,310 Q500,335 580,330 Q670,310 740,295 Q820,280 900,250 Q970,200 1040,80"
stroke="#ea580c" stroke-width="2" stroke-dasharray="5,5" fill="none"/>
<path d="M460,340 L460,210 Q480,165 580,80 Q680,165 700,210 L700,340 Z"
fill="#2563eb" opacity="0.15"/>
<path d="M460,340 L460,210 Q480,165 580,80 Q680,165 700,210 L700,340"
stroke="#2563eb" stroke-width="2" fill="none" stroke-dasharray="2,3"/>
<rect x="572" y="80" width="16" height="260" fill="#2563eb"/>
<circle cx="240" cy="270" r="6" fill="#16a34a"/>
<text x="240" y="260" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<circle cx="420" cy="240" r="6" fill="#16a34a"/>
<text x="420" y="230" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<circle cx="510" cy="180" r="6" fill="#94a3b8"/>
<text x="510" y="170" font-size="10" fill="#94a3b8" text-anchor="middle">raus</text>
<circle cx="660" cy="200" r="6" fill="#94a3b8"/>
<text x="660" y="190" font-size="10" fill="#94a3b8" text-anchor="middle">raus</text>
<circle cx="640" cy="155" r="6" fill="#94a3b8"/>
<text x="640" y="145" font-size="10" fill="#94a3b8" text-anchor="middle">raus</text>
<circle cx="860" cy="220" r="6" fill="#16a34a"/>
<text x="860" y="210" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<circle cx="960" cy="170" r="6" fill="#16a34a"/>
<text x="960" y="160" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<text x="595" y="76" font-size="11" fill="#2563eb" font-weight="700">1 kHz · 90 dB · "Masker"</text>
<text x="780" y="105" font-size="11" fill="#ea580c" font-weight="700">Hörschwelle (in Ruhe)</text>
<text x="540" y="160" font-size="11" fill="#2563eb" font-weight="700" text-anchor="middle">Maskierungs-Bereich</text>
</svg>
</div>
<div class="verdict">
<div class="verdict-q">MP3 kodiert nur, was über der <strong>kombinierten Schwelle</strong> liegt.</div>
<div class="verdict-a">Alles unterhalb wird weggeworfen — das Ohr hört es ohnehin nicht. So spart MP3 typischerweise <strong>~90 % der Daten</strong>, ohne dass der Mensch im Alltag etwas vermisst.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

@@ -0,0 +1,222 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Psychovisualität — Luminanz vor Chrominanz</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--full: #2563eb;
--reduced: #7c3aed;
--y: #1a1a2e;
--cb: #2563eb;
--cr: #ef4444;
--bar-bg: #e2e8f0;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.compare {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1180px;
margin: 0 auto;
}
.col {
border: 2px solid;
border-radius: 12px;
padding: 16px 20px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.col.full { border-color: var(--full); }
.col.reduced { border-color: var(--reduced); }
.col-head { display: flex; justify-content: space-between; align-items: baseline; }
.col-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.col-name { font-size: 1.25rem; font-weight: 700; }
.col.full .col-name { color: var(--full); }
.col.reduced .col-name { color: var(--reduced); }
.col-format {
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--muted);
}
.preview {
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border);
}
.preview svg { display: block; }
.channels {
display: flex;
flex-direction: column;
gap: 6px;
}
.channel { display: grid; grid-template-columns: 90px 1fr 60px; gap: 8px; align-items: center; font-size: 0.85rem; }
.channel-label {
font-family: ui-monospace, monospace;
font-weight: 700;
}
.channel-bar { height: 14px; background: var(--bar-bg); border-radius: 3px; overflow: hidden; }
.channel-bar .fill { height: 100%; border-radius: 3px; }
.channel-bar .fill.y { background: var(--y); }
.channel-bar .fill.cb { background: var(--cb); }
.channel-bar .fill.cr { background: var(--cr); }
.channel-pct {
font-family: ui-monospace, monospace;
font-size: 0.78rem;
color: var(--muted);
text-align: right;
}
.summary-line {
display: flex;
justify-content: space-between;
background: var(--soft);
border-radius: 6px;
padding: 6px 12px;
font-family: ui-monospace, monospace;
font-size: 0.85rem;
color: var(--dark);
}
.summary-line strong { color: var(--hl); }
.verdict {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Psychovisualität — Luminanz vor Chrominanz</h1>
<div class="sub">Das Auge sieht <strong>Helligkeit</strong> scharf. <strong>Farbe</strong> darf grob bleiben — und das Bild sieht trotzdem identisch aus.</div>
<div class="compare">
<div class="col full">
<div class="col-head">
<span class="col-name">Ohne Subsampling</span>
<span class="col-tag">4:4:4</span>
</div>
<div class="col-format">jedes Pixel speichert Y · Cb · Cr in voller Auflösung</div>
<svg class="preview" viewBox="0 0 320 130" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="full-sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="320" height="130" fill="url(#full-sky)"/>
<circle cx="230" cy="50" r="22" fill="#fef3c7"/>
<path d="M0,90 L40,75 L90,87 L140,68 L190,82 L240,66 L290,80 L320,72 L320,130 L0,130 Z" fill="#1e1b4b"/>
<path d="M0,108 L60,100 L120,108 L180,98 L240,106 L300,98 L320,103 L320,130 L0,130 Z" fill="#0f172a" opacity="0.7"/>
</svg>
<div class="channels">
<div class="channel">
<span class="channel-label">Y</span>
<div class="channel-bar"><div class="fill y" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
<div class="channel">
<span class="channel-label">Cb</span>
<div class="channel-bar"><div class="fill cb" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
<div class="channel">
<span class="channel-label">Cr</span>
<div class="channel-bar"><div class="fill cr" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
</div>
<div class="summary-line">
<span>Datenmenge:</span>
<span><strong>100 %</strong></span>
</div>
</div>
<div class="col reduced">
<div class="col-head">
<span class="col-name">JPEG · H.264 Standard</span>
<span class="col-tag">4:2:0</span>
</div>
<div class="col-format">Y voll · Cb &amp; Cr nur in 2×2-Pixel-Blöcken</div>
<svg class="preview" viewBox="0 0 320 130" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="red-sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="320" height="130" fill="url(#red-sky)"/>
<circle cx="230" cy="50" r="22" fill="#fef3c7"/>
<path d="M0,90 L40,75 L90,87 L140,68 L190,82 L240,66 L290,80 L320,72 L320,130 L0,130 Z" fill="#1e1b4b"/>
<path d="M0,108 L60,100 L120,108 L180,98 L240,106 L300,98 L320,103 L320,130 L0,130 Z" fill="#0f172a" opacity="0.7"/>
</svg>
<div class="channels">
<div class="channel">
<span class="channel-label">Y</span>
<div class="channel-bar"><div class="fill y" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
<div class="channel">
<span class="channel-label">Cb</span>
<div class="channel-bar"><div class="fill cb" style="width:25%"></div></div>
<span class="channel-pct">25 %</span>
</div>
<div class="channel">
<span class="channel-label">Cr</span>
<div class="channel-bar"><div class="fill cr" style="width:25%"></div></div>
<span class="channel-pct">25 %</span>
</div>
</div>
<div class="summary-line">
<span>Datenmenge:</span>
<span><strong>50 %</strong></span>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Halbe Datenmenge. Identisches Bild — für dein Auge.</div>
<div class="verdict-a">JPEG, H.264, H.265, WebP — alle reduzieren die Farb-Auflösung auf <strong>ein Viertel</strong>. Das ist Psychovisualität: was wir nicht scharf sehen, muss man nicht scharf speichern.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -0,0 +1,212 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Raster vs. Vektor — Pixel oder Anweisung?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--raster: #ea580c;
--vektor: #2563eb;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pair {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1180px;
margin: 0 auto;
}
.col {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 10px;
}
.col.raster { border-color: var(--raster); }
.col.vektor { border-color: var(--vektor); }
.col-head { display: flex; justify-content: space-between; align-items: baseline; }
.col-name { font-size: 1.3rem; font-weight: 700; }
.col.raster .col-name { color: var(--raster); }
.col.vektor .col-name { color: var(--vektor); }
.col-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.col-desc { font-size: 0.85rem; color: var(--muted); line-height: 1.4; }
.views {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.view { display: flex; flex-direction: column; gap: 4px; }
.view-label {
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
text-align: center;
}
.view-canvas {
background: var(--soft);
border: 1px solid var(--border);
border-radius: 6px;
aspect-ratio: 1.4;
overflow: hidden;
}
.view-canvas svg { display: block; width: 100%; height: 100%; }
.stats {
background: var(--soft);
border-radius: 6px;
padding: 8px 12px;
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--dark);
line-height: 1.5;
}
.stats .key { color: var(--muted); }
.stats .val { font-weight: 700; }
.verdict {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Raster vs. Vektor — Pixel oder Anweisung?</h1>
<div class="sub">Beide zeigen ein Häkchen. Wenn man <strong>reinzoomt</strong>, kommt die Wahrheit raus.</div>
<div class="pair">
<div class="col raster">
<div class="col-head">
<span class="col-name">Raster</span>
<span class="col-tag">PNG · JPEG · GIF</span>
</div>
<div class="col-desc">Ein Gitter aus Pixel-Farbwerten. Jede Position ist festgelegt.</div>
<div class="views">
<div class="view">
<div class="view-label">Original (32 × 22 px)</div>
<div class="view-canvas">
<svg viewBox="0 0 320 220" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<g shape-rendering="crispEdges">
<rect x="20" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="40" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="60" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="80" y="180" width="20" height="20" fill="#ea580c"/>
<rect x="100" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="120" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="140" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="160" y="100" width="20" height="20" fill="#ea580c"/>
<rect x="180" y="80" width="20" height="20" fill="#ea580c"/>
<rect x="200" y="60" width="20" height="20" fill="#ea580c"/>
<rect x="220" y="40" width="20" height="20" fill="#ea580c"/>
<rect x="240" y="20" width="20" height="20" fill="#ea580c"/>
</g>
</svg>
</div>
</div>
<div class="view">
<div class="view-label">4× Zoom</div>
<div class="view-canvas">
<svg viewBox="80 60 160 160" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<g shape-rendering="crispEdges">
<rect x="20" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="40" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="60" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="80" y="180" width="20" height="20" fill="#ea580c"/>
<rect x="100" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="120" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="140" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="160" y="100" width="20" height="20" fill="#ea580c"/>
<rect x="180" y="80" width="20" height="20" fill="#ea580c"/>
<rect x="200" y="60" width="20" height="20" fill="#ea580c"/>
<rect x="220" y="40" width="20" height="20" fill="#ea580c"/>
<rect x="240" y="20" width="20" height="20" fill="#ea580c"/>
</g>
</svg>
</div>
</div>
</div>
<div class="stats">
<div><span class="key">Speicher:</span> <span class="val">32 × 22 × 3 Byte = 2 112 Byte</span></div>
<div><span class="key">Beim Zoom:</span> <span class="val">pixelig — Information ist erschöpft</span></div>
</div>
</div>
<div class="col vektor">
<div class="col-head">
<span class="col-name">Vektor</span>
<span class="col-tag">SVG · PDF · Schriftarten</span>
</div>
<div class="col-desc">Mathematische Anweisungen: <code style="background:#0f0f23;color:#5fb3e4;padding:0 4px;border-radius:3px;">polyline 30,110 → 90,170 → 250,30</code></div>
<div class="views">
<div class="view">
<div class="view-label">Original</div>
<div class="view-canvas">
<svg viewBox="0 0 320 220" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<polyline points="30,130 90,190 270,30" stroke="#2563eb" stroke-width="14" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
<div class="view">
<div class="view-label">4× Zoom</div>
<div class="view-canvas">
<svg viewBox="80 60 160 160" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<polyline points="30,130 90,190 270,30" stroke="#2563eb" stroke-width="14" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
</div>
<div class="stats">
<div><span class="key">Speicher:</span> <span class="val">3 Punkte + Strichbreite = ~80 Byte</span></div>
<div><span class="key">Beim Zoom:</span> <span class="val">scharf — wird neu berechnet</span></div>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Pixel sind festgenagelt. Vektoren werden bei jedem Zoom <strong>neu berechnet</strong>.</div>
<div class="verdict-a">Faustregel: <strong>Foto → Raster</strong> (kann nicht „neu berechnet" werden). <strong>Logo, Icon, Schrift → Vektor</strong> (skalierbar ohne Verlust).</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Was wir über Kompression gelernt haben</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--lossless: #16a34a;
--lossy: #ef4444;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 26px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.compare {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1180px;
margin: 0 auto;
}
.col {
border: 2px solid;
border-radius: 12px;
padding: 18px 22px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.col.lossless { border-color: var(--lossless); }
.col.lossy { border-color: var(--lossy); }
.col-head { display: flex; justify-content: space-between; align-items: baseline; }
.col-name { font-size: 1.4rem; font-weight: 700; }
.col.lossless .col-name { color: var(--lossless); }
.col.lossy .col-name { color: var(--lossy); }
.col-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.row { display: grid; grid-template-columns: 120px 1fr; gap: 10px 14px; }
.row-key {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted);
padding-top: 3px;
}
.row-val { font-size: 0.92rem; line-height: 1.5; color: var(--dark); }
.row-val strong {
font-family: ui-monospace, monospace;
background: var(--soft);
padding: 1px 6px;
border-radius: 4px;
}
.matrix {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 14px 22px;
}
.matrix-head {
font-size: 0.78rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
margin-bottom: 8px;
}
.matrix-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 8px 16px;
font-size: 0.88rem;
}
.matrix-grid .scenario { font-weight: 700; color: var(--dark); }
.matrix-grid .answer {
font-family: ui-monospace, monospace;
color: var(--dark);
}
.matrix-grid .answer.lossless { color: var(--lossless); font-weight: 700; }
.matrix-grid .answer.lossy { color: var(--lossy); font-weight: 700; }
.verdict {
margin-top: 18px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Was wir über Kompression gelernt haben</h1>
<div class="sub">Zwei fundamental verschiedene Wege, dasselbe Ziel: <strong>Daten kleiner machen.</strong></div>
<div class="compare">
<div class="col lossless">
<div class="col-head">
<span class="col-name">Verlustfrei</span>
<span class="col-tag">Lossless</span>
</div>
<div class="row">
<div class="row-key">Was passiert</div>
<div class="row-val">Redundanz raus — Wiederholungen kürzer schreiben</div>
<div class="row-key">Umkehrbar</div>
<div class="row-val">Ja. Aus der komprimierten Datei wird das <strong>exakte</strong> Original wieder.</div>
<div class="row-key">Verfahren</div>
<div class="row-val">RLE, Huffman, Deflate, LZ77/LZ78</div>
<div class="row-key">Formate</div>
<div class="row-val">ZIP · PNG · FLAC · TIFF · RAW</div>
<div class="row-key">Faktor</div>
<div class="row-val">2× – 5× (typisch)</div>
</div>
</div>
<div class="col lossy">
<div class="col-head">
<span class="col-name">Verlustbehaftet</span>
<span class="col-tag">Lossy</span>
</div>
<div class="row">
<div class="row-key">Was passiert</div>
<div class="row-val">Irrelevanz raus — was Mensch nicht wahrnimmt, wird weggeworfen</div>
<div class="row-key">Umkehrbar</div>
<div class="row-val">Nein. Einmal weg, für immer weg.</div>
<div class="row-key">Trick</div>
<div class="row-val">Psychoakustik (MP3) · Psychovisualität (JPEG)</div>
<div class="row-key">Formate</div>
<div class="row-val">MP3 · AAC · JPEG · WebP · H.264 · H.265</div>
<div class="row-key">Faktor</div>
<div class="row-val">10× – 100× (typisch)</div>
</div>
</div>
</div>
<div class="matrix">
<div class="matrix-head">Entscheidungsmatrix — wann nehme ich welches?</div>
<div class="matrix-grid">
<div class="scenario">Foto-Archiv (RAW)</div>
<div class="answer lossless">Lossless</div>
<div class="scenario">Spotify-Stream</div>
<div class="answer lossy">Lossy</div>
<div class="scenario">Code-Repository</div>
<div class="answer lossless">Lossless (ZIP)</div>
<div class="scenario">Instagram-Foto</div>
<div class="answer lossy">Lossy (JPEG)</div>
<div class="scenario">Studio-Master-Track</div>
<div class="answer lossless">Lossless (FLAC)</div>
<div class="scenario">YouTube-Video</div>
<div class="answer lossy">Lossy (H.264)</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Lossless für Archiv und Code. Lossy für Streaming und Anzeige.</div>
<div class="verdict-a">Faustregel: <strong>Werkzeug</strong> (du arbeitest noch dran) → Lossless. <strong>Konsum</strong> (du schaust/hörst nur) → Lossy.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

@@ -0,0 +1,188 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Was wir in 90 Minuten gelernt haben</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--left: #d63384;
--right: #0891b2;
--bytes: #0891b2;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 28px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.recap {
display: grid;
grid-template-columns: 160px 1fr 200px 1fr 160px;
gap: 10px;
max-width: 1200px;
margin: 0 auto;
align-items: center;
}
.station {
border: 2px solid var(--border);
border-radius: 10px;
padding: 18px 12px;
background: #fff;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
.station.bytes { border-color: var(--bytes); background: #0f0f23; color: #fff; }
.station-tag {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.station.bytes .station-tag { color: #94a3b8; }
.station-name { font-size: 1.3rem; font-weight: 700; }
.station.bytes .station-name { color: #67e8f9; }
.station-detail { font-size: 0.78rem; color: var(--muted); line-height: 1.35; }
.station.bytes .station-detail { color: #94a3b8; font-family: ui-monospace, monospace; font-size: 0.76rem; line-height: 1.35; }
.strang {
display: flex;
flex-direction: column;
gap: 6px;
padding: 0 6px;
}
.strang-arrow { text-align: center; }
.strang-arrow svg { width: 100%; height: 18px; }
.strang-title {
font-size: 0.92rem;
font-weight: 700;
text-align: center;
line-height: 1.3;
}
.strang.left .strang-title { color: var(--left); }
.strang.right .strang-title { color: var(--right); }
.strang-list {
display: flex;
flex-direction: column;
gap: 3px;
list-style: none;
margin: 0;
padding: 0;
background: var(--soft);
border: 1px solid var(--border);
border-radius: 8px;
padding: 8px 12px;
}
.strang-list li {
font-size: 0.82rem;
color: var(--dark);
padding-left: 12px;
position: relative;
line-height: 1.4;
}
.strang-list li::before {
content: "·";
position: absolute;
left: 0;
top: 0;
font-weight: 700;
}
.strang.left .strang-list li::before { color: var(--left); }
.strang.right .strang-list li::before { color: var(--right); }
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.95rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Was wir in 90 Minuten gelernt haben</h1>
<div class="sub">Beide Wege gehen durch <strong>dieselbe Mitte</strong>. Du kennst jetzt alle Stationen.</div>
<div class="recap">
<div class="station">
<div class="station-tag">Quelle</div>
<div class="station-name">Welt</div>
<div class="station-detail">Schallwelle<br>Lichtwelle<br>kontinuierlich · analog</div>
</div>
<div class="strang left">
<div class="strang-arrow">
<svg viewBox="0 0 200 18" preserveAspectRatio="none">
<line x1="6" y1="9" x2="180" y2="9" stroke="#d63384" stroke-width="2"/>
<path d="M174,3 L188,9 L174,15" stroke="#d63384" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="strang-title">Welt → Byte</div>
<ul class="strang-list">
<li>Sampling-Rate</li>
<li>Bittiefe · Quantisierung</li>
<li>Datenrate-Formel</li>
<li>Nyquist · 2·f<sub>max</sub></li>
<li>Aliasing &amp; Moiré</li>
<li>44,1 kHz = 2·20 kHz + Marge</li>
</ul>
</div>
<div class="station bytes">
<div class="station-tag">Mitte</div>
<div class="station-name">Datei</div>
<div class="station-detail">
Byte-Strom<br>
89 50 4E 47<br>
nichts als Zahlen
</div>
</div>
<div class="strang right">
<div class="strang-arrow">
<svg viewBox="0 0 200 18" preserveAspectRatio="none">
<line x1="6" y1="9" x2="180" y2="9" stroke="#0891b2" stroke-width="2"/>
<path d="M174,3 L188,9 L174,15" stroke="#0891b2" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="strang-title">Byte → Bedeutung</div>
<ul class="strang-list">
<li>Bit · Byte · Hex</li>
<li>8 Bit = 256 Zustände</li>
<li>ASCII · UTF-8</li>
<li>Magic Number</li>
<li>KB vs KiB</li>
<li>Hex im Alltag (CSS, MAC)</li>
</ul>
</div>
<div class="station">
<div class="station-tag">Ziel</div>
<div class="station-name">Mensch</div>
<div class="station-detail">Text · Bild · Klang<br>Bedeutung<br>verstehen</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Eine Datei ist kein Mysterium. Es ist eine <strong>Reihe von Zahlen</strong> mit zwei Geschichten dran.</div>
<div class="verdict-a">Eine Geschichte erzählt, <strong>woher</strong> die Zahlen kommen. Die andere, <strong>was</strong> sie bedeuten. Beide kennst du jetzt.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -0,0 +1,217 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>USB-C — drei Achsen, eine Verwirrung</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--stecker: #2563eb;
--kabel: #ea580c;
--protokoll: #7c3aed;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.axes {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 18px;
max-width: 1200px;
margin: 0 auto;
}
.axis {
border: 2px solid;
border-radius: 12px;
padding: 14px 16px;
background: #fff;
display: flex;
flex-direction: column;
gap: 10px;
}
.axis.stecker { border-color: var(--stecker); }
.axis.kabel { border-color: var(--kabel); }
.axis.protokoll { border-color: var(--protokoll); }
.axis-head { display: flex; justify-content: space-between; align-items: baseline; }
.axis-num {
font-family: ui-monospace, monospace;
font-size: 0.72rem;
font-weight: 700;
color: var(--muted);
}
.axis-name { font-size: 1.15rem; font-weight: 700; }
.axis.stecker .axis-name { color: var(--stecker); }
.axis.kabel .axis-name { color: var(--kabel); }
.axis.protokoll .axis-name { color: var(--protokoll); }
.axis-tagline {
font-size: 0.82rem;
color: var(--muted);
line-height: 1.4;
}
.axis-tagline strong { color: var(--dark); }
.icon {
background: var(--soft);
border-radius: 6px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.icon svg { display: block; }
.options {
font-size: 0.82rem;
line-height: 1.6;
color: var(--dark);
background: var(--soft);
border-radius: 6px;
padding: 10px 14px;
}
.options strong {
font-family: ui-monospace, monospace;
font-size: 0.78rem;
padding: 1px 5px;
border-radius: 3px;
background: #fff;
border: 1px solid var(--border);
}
.axis.stecker .options strong { color: var(--stecker); }
.axis.kabel .options strong { color: var(--kabel); }
.axis.protokoll .options strong { color: var(--protokoll); }
.scenario {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 14px 22px;
}
.scenario-head {
font-size: 0.74rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
margin-bottom: 6px;
}
.scenario-body {
font-size: 0.92rem;
line-height: 1.5;
}
.scenario-body code {
font-family: ui-monospace, monospace;
background: #fff;
padding: 1px 6px;
border-radius: 4px;
border: 1px solid var(--border);
}
.verdict {
margin-top: 16px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.05rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.92rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>USB-C — drei Achsen, eine Verwirrung</h1>
<div class="sub">Derselbe Stecker. <strong>Aber Kabel ≠ Kabel.</strong> <strong>Protokoll ≠ Protokoll.</strong></div>
<div class="axes">
<div class="axis stecker">
<div class="axis-head">
<span class="axis-name">Stecker</span>
<span class="axis-num">1 · MECHANIK</span>
</div>
<div class="axis-tagline">Die <strong>Form</strong>. Was reinsteckt, oval, beidseitig.</div>
<div class="icon">
<svg viewBox="0 0 120 30" width="140" height="40">
<rect x="6" y="9" width="108" height="12" rx="6" fill="#2563eb" opacity="0.18" stroke="#2563eb" stroke-width="2"/>
<rect x="22" y="13" width="76" height="4" rx="2" fill="#2563eb"/>
</svg>
</div>
<div class="options">
Nur eine Sorte: <strong>USB-C</strong> (auch USB Type-C). 24 Pins. Beidseitig steckbar. Andere Stecker-Typen: USB-A, USB-B, Micro-USB — nicht mit C kompatibel.
</div>
</div>
<div class="axis kabel">
<div class="axis-head">
<span class="axis-name">Kabel</span>
<span class="axis-num">2 · WAS DURCH-PASST</span>
</div>
<div class="axis-tagline">Die <strong>Adern</strong>. Was elektrisch transportiert werden kann.</div>
<div class="icon">
<svg viewBox="0 0 160 30" width="180" height="40">
<path d="M10,15 L150,15" stroke="#ea580c" stroke-width="3"/>
<rect x="2" y="8" width="14" height="14" rx="3" fill="#ea580c" opacity="0.4" stroke="#ea580c"/>
<rect x="144" y="8" width="14" height="14" rx="3" fill="#ea580c" opacity="0.4" stroke="#ea580c"/>
</svg>
</div>
<div class="options">
<strong>Charge-only</strong> · billig, nur Strom · 5 W<br>
<strong>USB 2.0</strong> · 480 Mbit/s · 60 W (3 A)<br>
<strong>USB 3.2 Gen 2</strong> · 10 Gbit/s · 100 W<br>
<strong>Thunderbolt 4</strong> · 40 Gbit/s · 240 W
</div>
</div>
<div class="axis protokoll">
<div class="axis-head">
<span class="axis-name">Protokoll</span>
<span class="axis-num">3 · WAS LÄUFT</span>
</div>
<div class="axis-tagline">Die <strong>Sprache</strong>. Was die zwei Geräte miteinander reden.</div>
<div class="icon">
<svg viewBox="0 0 160 30" width="180" height="40">
<circle cx="20" cy="15" r="6" fill="#7c3aed"/>
<path d="M30,15 L130,15" stroke="#7c3aed" stroke-width="2" stroke-dasharray="6,4"/>
<circle cx="140" cy="15" r="6" fill="#7c3aed"/>
</svg>
</div>
<div class="options">
<strong>USB-PD</strong> · Power Delivery (Laden)<br>
<strong>USB 2/3/4</strong> · Datenübertragung<br>
<strong>Thunderbolt 3/4</strong> · Daten + Display<br>
<strong>DisplayPort Alt</strong> · Monitor anschließen<br>
<strong>HDMI Alt</strong> · weiter HDMI rausführen
</div>
</div>
</div>
<div class="scenario">
<div class="scenario-head">Konkret: warum lädt der Laptop nicht?</div>
<div class="scenario-body">
USB-C-Port am Laptop ist da (<strong>Stecker</strong> stimmt). Aber der Aldi-Kabel ist <code>Charge-only</code> mit <code>5 W</code> (<strong>Kabel</strong> kann nicht genug Strom liefern). Oder der Port am Laptop unterstützt nur <code>USB-PD</code> mit 100 W, das Netzteil meldet aber nur 65 W (<strong>Protokoll</strong>-Handshake scheitert). <em>Eine der drei Achsen passt nicht.</em>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Drei Achsen. Drei unabhängige Fragen. Drei Gründe, warum's nicht funktioniert.</div>
<div class="verdict-a">Beim nächsten „USB-C-Kabel funktioniert nicht": <strong>Stecker passt → Kabel-Spec checken → Protokoll-Support prüfen.</strong> In dieser Reihenfolge.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because it is too large. Load diff
+7 -7
View File
@@ -97,7 +97,7 @@ Hochschule der Medien Stuttgart
<!-- _class: lead -->
# Herzlich willkommen!
# Herzlich willkommen
## Einführung
---
@@ -116,13 +116,13 @@ Hochschule der Medien Stuttgart
---
# Warum dieses Modul?
# Motivation für dieses Modul
**Das Internet ist überall** – aber was steckt dahinter?
* Warum sehen Webseiten auf dem Handy anders aus?
* Wie funktioniert eigentlich das Internet?
* Wie erkennen Sie, ob eine Werbeagentur gute Arbeit leistet?
* Wie erkennt ihr, ob eine Werbeagentur gute Arbeit leistet?
* Was hat ein Unterseekabel mit meiner E-Mail zu tun?
* **→ Die Technik dahinter verstehen und fundierte Entscheidungen treffen**
@@ -136,13 +136,13 @@ Als Digital- und MedienwirtschaftlerInnen werdet ihr täglich mit technischen Fr
* Wie baue ich eine barrierearme Webseite?
* Welches Protokoll für welchen Zweck?
* Wie funktioniert das Web hinter den Kulissen?
* **→ Mitreden können – und selbst Webseiten bauen!**
* **→ Mitreden können – und selbst Webseiten bauen**
---
# Was Sie hier lernen werden
# Lernziele
**In dieser Veranstaltung erwerben Sie folgende Kompetenzen:**
**In dieser Veranstaltung erwerbt ihr folgende Kompetenzen:**
* Geschichte des Computers und Internets
* HTML-Grundlagen und semantisches Markup
@@ -172,7 +172,7 @@ Als Digital- und MedienwirtschaftlerInnen werdet ihr täglich mit technischen Fr
2. Netzwerke, Protokolle, **semantisches HTML** & **CSS**
3. Interaktivität, Animationen & **JavaScript**
**Ziel:** "Gelernte Hilflosigkeit" ablegen
**Ziel:** Technische Scheu abbauen und Web-Grundlagen selbst beherrschen
---
+27 -27
View File
@@ -126,7 +126,7 @@ Hochschule der Medien Stuttgart
2. Netzwerke, Protokolle, **semantisches HTML** & **CSS**
3. Interaktivität, Animationen & **JavaScript**
**Ziel:** "Gelernte Hilflosigkeit" ablegen
**Ziel:** Technische Scheu abbauen und Web-Grundlagen selbst beherrschen
---
@@ -403,10 +403,10 @@ Der Turing-Test (1950): Ein Interrogator kommuniziert per Text mit einem Mensche
- Implosions-Simulationen
- Nuklearphysik-Gleichungen
**Lösung 1943:** Menschliche "Computer"
**Lösung 1943:** Die Berechnungen übernehmen menschliche "Computer"
→ Mathematikerinnen mit Taschenrechnern & IBM-Lochkarten
**Zu langsam** → Bedarf an automatischer Berechnung
**Das ist zu langsam** → es entsteht der Bedarf an automatischer Berechnung
**Schlüsselfigur:** John von Neumann (Mathematik & Stoßwellen)
@@ -427,7 +427,7 @@ Das ENIAC-Projekt in Philadelphia sollte die Berechnungen beschleunigen.
# John von Neumann (1903–1957)
- Geboren in Budapest, Österreich-Ungarn
- Mit 8: Konnte Telefonbücher auswendig
- Mit 8: Konnte ganze Telefonbücher auswendig aufsagen
- Mit 22: Doktor in Mathematik
**Beiträge:**
@@ -623,7 +623,7 @@ COBOL läuft heute noch auf Bankensystemen
- Jeder Befehl entspricht direkt einer CPU-Instruktion
- Hardwarenah, aber für Menschen lesbar
**Fun Fact:** Chris Sawyer schrieb **RollerCoaster Tycoon** (1999) fast komplett in x86-Assembly
**Kuriosum:** Chris Sawyer schrieb **RollerCoaster Tycoon** (1999) fast komplett in x86-Assembly
<!--
KATHLEEN BOOTH (1922–2022):
@@ -893,7 +893,7 @@ Geprägt 1948 von Claude Shannon
<!--
Alles Digitale basiert darauf
Transistoren in CPUs: Milliarden Bits schalten Millionen Mal pro Sekunde
Transistoren in CPUs: Milliarden Bit schalten Millionen Mal pro Sekunde
Shannon: Begründer der Informationstheorie
-->
@@ -940,19 +940,19 @@ binary 00101010 = decimal 42
- ASCII (1963) brauchte 7 Bit für 128 Zeichen
- 8 Bit = praktisch für Hardware (Zweierpotenz: 2³ = 8)
- 8 Bit = 2 Hexadezimalziffern (elegante Darstellung)
- Kleinste adressierbare Einheit im Speicher: Prozessor kann nicht einzelne Bits direkt ansprechen, immer Bytes
- Kleinste adressierbare Einheit im Speicher: Prozessor kann nicht einzelne Bit direkt ansprechen, immer Byte
-->
---
# Was kann man mit 256 Zuständen machen?
# 256 Zustände – was sich damit darstellen lässt
- **256 Zeichen** (Buchstaben, Zahlen, Symbole)
- **256 Graustufen** (0 = Schwarz, 255 = Weiß)
- **256 Lautstärkestufen**
- **Zahlen 0-255**
**Für Farbe:** 3 Bytes pro Pixel (RGB)
**Für Farbe:** 3 Byte pro Pixel (RGB)
R=0-255, G=0-255, B=0-255 → **16,7 Millionen Farben**
<!--
@@ -1004,7 +1004,7 @@ Warum gerade 8 Bit?
<!--
Dezimal = was wir im Alltag nutzen (10 Finger → 10 Ziffern)
Binär = was Computer nutzen (Strom an/aus → 2 Zustände)
Hexadezimal = Kompromiss: kompakter als Binär, aber passt perfekt auf Bytes (2 Hex-Ziffern = 1 Byte = 8 Bit)
Hexadezimal = Kompromiss: kompakter als Binär, aber passt perfekt auf Byte (2 Hex-Ziffern = 1 Byte = 8 Bit)
Die Basis bestimmt, wie viele Symbole pro Stelle zur Verfügung stehen:
- Dezimal: 10 (0–9)
- Binär: 2 (0, 1)
@@ -1021,7 +1021,7 @@ Die Basis bestimmt, wie viele Symbole pro Stelle zur Verfügung stehen:
**Hexadezimal (Base 16):**
`4D 50 33` (= "MP3" in ASCII)
**Jede Hex-Ziffer = 4 Bits (ein "Nibble")**
**Jede Hex-Ziffer = 4 Bit (ein "Nibble")**
0-9, A-F (A=10, B=11, ..., F=15)
`4 = 0100` `D = 1101`
@@ -1031,7 +1031,7 @@ Die Basis bestimmt, wie viele Symbole pro Stelle zur Verfügung stehen:
<!--
Hex = Shortcut für Menschen
1 Byte = 2 Hex-Ziffern (00-FF)
"Nibble" = 4 Bits = halbes Byte (Wortspiel: nibble = knabbern, byte = beißen)
"Nibble" = 4 Bit = halbes Byte (Wortspiel: nibble = knabbern, byte = beißen)
CSS (Cascading Style Sheets)-Farben nutzen Hex: #FF0000 = Rot
-->
@@ -1076,7 +1076,7 @@ Dieselben 8 Byte (PNG-Dateianfang: 89 50 4E 47 0D 0A 1A 0A) — drei Perspektive
---
# Wo begegnet Ihnen Hex-Code?
# Wo euch Hex-Code begegnet
| Kontext | Beispiel |
|---------|----------|
@@ -1112,7 +1112,7 @@ Fehlercodes: Windows zeigt diese bei Bluescreens
---
# Bit vs. Byte: Die Verwirrung
# Bit vs. Byte: der Unterschied
**1 Byte = 8 Bit** → Bit ÷ 8 = Byte
@@ -1126,7 +1126,7 @@ Fehlercodes: Windows zeigt diese bei Bluescreens
<!--
Bits = kleines b, Bytes = großes B
Bit = kleines b, Byte = großes B
Internetanbieter: Mbit/s (klingt größer!)
100 Mbit/s ÷ 8 = 12,5 MB/s
Warum? Marketing - 100 klingt besser als 12,5
@@ -1146,7 +1146,7 @@ Warum? Marketing - 100 klingt besser als 12,5
**H**yper**T**ext **M**arkup **L**anguage
* **Keine** Programmiersprache
* Am ehesten eine Formattierungssprache
* Am ehesten eine Auszeichnungssprache (Markup)
* Beschreibt **Struktur und Aufbau** einer Webseite
* ```html
<p>Das ist ein Absatz.</p>
@@ -1167,8 +1167,8 @@ Aktuelle Version: HTML5 (seit 2014)
# Was ist HTML? (2/2)
* Mit HTML werden **HTML-Dokumente** beschrieben (bspw. `index.html`)
* Ein HTML-Dokument beschreibt das/den `Document Object Model (DOM)`
* Der DOM ist eine **hierarchische Baumstruktur** (Kind- und Elternelemente)
* Ein HTML-Dokument beschreibt das **Document Object Model (DOM)**
* Das DOM ist eine **hierarchische Baumstruktur** (Kind- und Elternelemente)
* *parent nodes / elements*
* *child nodes / elements*
* *sibling nodes / elements*
@@ -1178,12 +1178,12 @@ Aktuelle Version: HTML5 (seit 2014)
# HTML-Anatomie (1/2)
Formattierungssprache
HTML ist eine Auszeichnungssprache (Markup).
* HTML folgt einer strengen **Syntax** zur Formattieren von digitalen Inhalten
* HTML folgt einer strengen **Syntax** zum Auszeichnen digitaler Inhalte
* Syntax: `<element attribute="value"> ... </element>`
* Öffnende und schließende HTML-Tags müssen identisch sein
* Das schließende Tag muss ein `/` nach der Spitzenklammer haben
* Das schließende Tag hat ein `/` direkt nach der öffnenden spitzen Klammer (`</p>`)
---
@@ -1199,7 +1199,7 @@ Formattierungssprache
* `<b> ... </b>` fett-gedruckter Text (inline)
* `<a> ... </a>` Hyperlink (Verlinkung zu anderen Webseiten, Bildern)
* `<body> ... </body>` Sichtbarer Teil eines HTML-Dokuments
* `<details> ... </details>` Collapsable / Akkordion / Aufklapp-Text
* `<details> ... </details>` Aufklapp-Text (Akkordion)
* **Selbst-schließend**
* `<img />` Bild, Vektorgrafik etc.
* `<input />` Eingabefeld
@@ -1385,7 +1385,7 @@ a = anchor (Anker)
# Natives HTML
Was noch üblicherweise mit Skriptsprachen wie JavaScript und anderen umgesetzt werden musste, kann nun HTML selber. Wer dieses dennoch verwendet, hat das einen sog. *"Code smell"*.
Vieles, was früher JavaScript erforderte, beherrscht HTML inzwischen selbst. Wer es dennoch per Skript löst, produziert einen sogenannten *"Code Smell"*.
| Funktion | HTML-Element |
|----------|--------------|
@@ -1510,7 +1510,7 @@ Accessibility ist eingebaut
<!-- _class: lead -->
# Wie nutzen Menschen das Web?
# Wie Menschen das Web nutzen
---
@@ -1554,7 +1554,7 @@ Accessibility ist eingebaut
---
# Wie nutzen Menschen das Web?
# Wie Menschen das Web nutzen
| Eingabe | Nutzungsweise |
|---------|---------------|
@@ -1613,10 +1613,10 @@ Screenreader lesen den DOM sequenziell – semantisches HTML (`<nav>`, `<main>`,
---
# Warum "Barrierefreiheit"?
# Bedeutung von "Barrierefreiheit"
**Rechtlich:**
- EU: European Accessibility Act (seit Juni 2025 in Kraft!)
- EU: European Accessibility Act (seit Juni 2025 in Kraft)
- DE: BITV 2.0 (Behörden), Privatwirtschaft betroffen
**Ethisch:**
+189 -183
View File
@@ -91,6 +91,9 @@ section.erklaerung p {
section.erklaerung table {
font-size: 0.9rem;
}
section.dimmed {
opacity: 0.2;
}
</style>
<!-- _class: invert -->
@@ -197,26 +200,14 @@ SPEAKER NOTES:
Das Web folgt dem **Client-Server-Modell**: Ein Client (Browser) sendet einen **Request**, ein Server liefert eine **Response** – nach den Regeln eines **Protokolls**.
| Begriff | Was ist das? | Analogie |
|---------|--------------|----------|
| **Host** | Ein Rechner im Netz | Ein Haus mit Adresse |
| **Client** | Der, der fragt (Browser) | Gast im Restaurant |
| **Server** | Der, der antwortet | Küche im Restaurant |
| **Request** | Die Anfrage | Bestellung |
| **Response** | Die Antwort | Das Essen |
| **Protokoll** | Regeln für Kommunikation (z. B. TCP, HTTP) | Speisekarte + Bestellablauf |
<!--
SPEAKER NOTES:
- 6 Grundbegriffe – tauchen überall auf
- Client/Server = Grundstruktur des Webs
- Browser = Client
- Google/HdM/Netflix = Server
- Request/Response = Kommunikationsmuster
- Protokoll = Regelwerk
- Analogie: Restaurant in Japan ohne Regeln zu kennen
- Host = Rechner mit Adresse im Netz
-->
| Begriff | Was ist das? |
|---------------|--------------------------------------------------------------------------|
| **Host** | Ein netzwerkfähiger Rechner (Laptop, Smartphone, Display in S-Bahn etc.) |
| **Client** | Host bzw. Anwendung mit einer Anfrage (bspw. Browser) |
| **Server** | Host bzw. Anwendung mit der Antwort (bspw. Webserver) |
| **Request** | Die Anfrage des Clients |
| **Response** | Die Antwort des Servers |
| **Protokoll** | Regeln für Kommunikation (z. B. TCP, HTTP) |
---
@@ -224,13 +215,13 @@ SPEAKER NOTES:
# Glossar: Adressen & Identitäten
Jedes Gerät im Netz braucht Adressen: eine **IP** für das globale Routing, eine **MAC** für das lokale Netz und einen **Port** für das richtige Programm.
Jedes Gerät im Netz braucht Adressen: eine **IP** (Internet Protocol) für das globale Routing, eine **MAC** (Media Access Control) für das lokale Netz und einen **Port** für das richtige Programm.
| Begriff | Was ist das? | Beispiel |
|---------|--------------|----------|
| **IP-Adresse** | Globale Adresse im Internet | `212.132.79.37` |
| **MAC-Adresse** | Hardware-Adresse der Netzwerkkarte | `aa:bb:cc:dd:ee:ff` |
| **Port** | "Türnummer" auf einem Rechner | `80`, `443`, `22` |
| **Port** | Nummer eines Programms bzw. Dienstes | `80`, `443`, `22` |
| **DNS** | Telefonbuch: Name → IP | hdm-stuttgart.de → IP |
| **Domain** | Menschenlesbarer Name | `hdm-stuttgart.de` |
@@ -253,13 +244,15 @@ SPEAKER NOTES:
Daten werden Schicht für Schicht verpackt — jede Schicht fügt einen eigenen **Header** hinzu und erzeugt so eine neue Dateneinheit.
| Begriff | Was ist das? | Schicht |
|---------|--------------|---------|
| **Paket** | Daten + IP-Header | Internet (Layer 3) |
| **Segment** | Daten + TCP-Header | Transport (Layer 4) |
| **Frame** | Daten + MAC-Header | Netzzugang (Layer 2) |
| **Header** | Metadaten am Anfang | Jede Schicht |
| **Payload** | Die eigentlichen Nutzdaten | Der Inhalt |
| Begriff | Was ist das? | Schicht |
|-------------|-------------------------------------------------------|--------------------------|
| **Payload** | Die eigentlichen Nutzdaten (bspw. Request, Response) | Anwendung |
| **Header** | Metadaten vor und nach dem Payload | Jedes Layer |
| **Segment** | Payload + TCP-Header (Anwendungsport) | Transport (Layer 3) |
| **Paket** | Payload + IP-Header (WLAN-Router) | Internet (Layer 2) |
| **Frame** | Payload + MAC-Header (Netzwerkkarte) | Netzzugang (Layer 1) |
| **Bit** | Abfolge von Signalen (Licht, Strom, Kabel, Mobilfunk) | Netzzugang (Layer 1) |
<!--
SPEAKER NOTES:
@@ -268,7 +261,6 @@ SPEAKER NOTES:
- Header = Metadaten (wer, wohin, wie groß)
- Paket/Segment/Frame = gleiche Daten, verschiedene Verpackung
- Wie Matroschka: Schicht packt Schicht ein
- Wird klarer beim Schichtenmodell gleich
-->
---
@@ -279,13 +271,13 @@ SPEAKER NOTES:
**Latenz** und **Bandbreite** bestimmen, wie schnell Daten ankommen — Latenz misst die Verzögerung, Bandbreite die Kapazität.
| Begriff | Was ist das? | Einheit |
|---------|--------------|---------|
| **Latenz** | Verzögerung (hin + zurück) | Millisekunden |
| **Bandbreite** | Datenmenge pro Zeiteinheit | Mbit/s |
| **Hop** | Ein Sprung zum nächsten Router | – |
| **Round-Trip** | Hin- und Rückweg | – |
| **Ping** | "Bist du da?" + Antwort | ms |
| Begriff | Was ist das? | Einheit |
|----------------|-------------------------------------------------|--------------------|
| **Latenz** | Verzögerung (hin + zurück) | Millisekunden (ms) |
| **Bandbreite** | Datenmenge pro Zeiteinheit | Mbit/s |
| **Hop** | Ein Sprung zum nächsten Router (im Internet) | – |
| **Round-Trip** | Hin- und Rückweg | – |
| **Ping** | Client sendet "ping", bekommt von Server "pong" | ms |
<!--
SPEAKER NOTES:
@@ -309,14 +301,17 @@ SPEAKER NOTES:
Protokolle regeln die Kommunikation auf jeder Schicht — von der Anwendung (HTTP) über den Transport (TCP/UDP) bis zum Routing (IP).
| Protokoll | Wofür? | Port | Schicht |
|-----------|--------|------|---------|
| **HTTP** | Webseiten übertragen | 80 | Anwendung |
| **HTTPS** | HTTP + Verschlüsselung | 443 | Anwendung |
| **TCP** | Zuverlässige Übertragung | – | Transport |
| **UDP** | Schnelle Übertragung | – | Transport |
| **IP** | Routing durchs Internet | – | Internet |
| **DNS** | Namen → IP-Adressen | 53 | Anwendung |
| Protokoll | Wofür? | Port | Schicht |
|-----------|--------------------------------|------|---------------------|
| **HTTP** | Webseiten + Inhalte übertragen | 80 | Anwendung (Layer 4) |
| **HTTPS** | HTTP + Verschlüsselung | 443 | Anwendung (Layer 4) |
| **DNS** | Namen → IP-Adressen | 53 | Anwendung (Layer 4) |
| **TCP** | Zuverlässige Übertragung | – | Transport (Layer 3) |
| **UDP** | Schnelle Übertragung | – | Transport (Layer 3) |
| **IP** | Routing durchs Internet | – | Internet (Layer 2) |
<i><small>HTTP(S) = Hypertext Transfer Protocol (Secure)</small> · <small>DNS = Domain Name System</small> · <small>TCP = Transmission Control Protocol</small> · <small>UDP = User Datagram Protocol</small> · <small>IP = Internet Protocol</small>
</i>
<!--
SPEAKER NOTES:
@@ -350,23 +345,23 @@ SPEAKER NOTES:
![bg right:40% fit](./assets/demos/network-chain.png)
Zwischen Ihnen und einer Webseite liegen viele Stationen.
Zwischen Klick und fertiger Webseite liegen viele Stationen.
Jede Komponente "spricht" anders:
Jede Schicht spricht eine andere Sprache:
- Browser → **HTTP**
- Netzwerkkarte → **Bits / Signale**
- Netzwerkkarte → **Bit und Signale**
- Router → **IP-Pakete**
- Provider → **Routing**
Wie zusammenbringen?
Diese Sprachen müssen zusammenspielen.
<!--
SPEAKER NOTES:
- Browser→Server: min. 7-8 Stationen
- Jede Station: andere Aufgabe
- Browser versteht HTTP
- Netzwerkkarte versteht nur Bits (Strom an/aus)
- Netzwerkkarte versteht nur Bit (Strom an/aus)
- Router versteht IP
- Wie zusammenbringen?
-->
@@ -375,11 +370,11 @@ SPEAKER NOTES:
# Die Lösung: Arbeitsteilung
Statt dass jedes Programm alles können muss: **Aufgaben aufteilen.**
Statt dass jedes Programm alles können muss, teilen sich mehrere Schichten die Aufgaben.
| Wer? | Aufgabe | Typische Geräte |
|------|---------|-----------------|
| **Browser/App** | Was will ich? | Laptop, Handy, Server |
| **Browser/Anwendung** | Was will ich? | Laptop, Handy, Server |
| **TCP/UDP** | Kommt alles an? | – (Software) |
| **IP** | Welcher Rechner? | Router, Firewall |
| **Ethernet/WLAN** | Nächstes Gerät? | Switch, Access Point |
@@ -402,15 +397,19 @@ SPEAKER NOTES:
# Das TCP/IP-Modell
| Schicht | Name | Aufgabe | Protokolle |
|---------|------|---------|------------|
| **4** | Anwendung | Was? Welcher Dienst? | HTTP, DNS, SMTP |
| **3** | Transport | Zuverlässigkeit, Ports | TCP, UDP |
| **2** | Internet | Routing, globale Adressen | IP |
| **1** | Netzzugang | Lokale Übertragung | Ethernet, WLAN |
| Schicht | Name | Aufgabe | Protokolle |
|---------|------|------------------------------------------|-------------------|
| **4** | Anwendung | Dienste steuern, Daten austauschen etc. | HTTP, DNS, SMTP |
| **3** | Transport | Zuverlässige Verbindung aufbauen (Ports) | TCP, UDP |
| **2** | Internet | Routing, global eindeutige Adressen | IP |
| **1** | Netzzugang | Lokale Übertragung | Ethernet, WLAN |
Jede Schicht hat genau eine Aufgabe und nutzt nur die Schicht direkt darunter.
Die oberste Schicht ist die **Anwendungsschicht** — die Ebene eurer Programme (Browser, Mail). Sie nutzt die unteren Schichten, ohne deren Details zu kennen: genau die Abstraktion, die ihr bereits kennt.
<small>SMTP = Simple Mail Transfer Protocol</small>
<!--
SPEAKER NOTES:
- TCP/IP = das echte Internet
@@ -419,18 +418,17 @@ SPEAKER NOTES:
- Transport: Kommt an? Welches Programm? (TCP, UDP)
- Internet: Wie zum Zielrechner? (IP)
- Netzzugang: Wie zum nächsten Gerät? (Ethernet, WLAN)
- KLAUSUR: Welches Protokoll → welche Schicht
-->
---
<!-- _class: erklaerung -->
<!-- _class: "erklaerung dimmed" -->
<!-- _header: '' -->
<!-- _footer: '' -->
# TCP/IP-Modell – Vertiefung
Das TCP/IP-Modell entstand praktisch aus dem ARPANET (1970er), im Gegensatz zum theoretischen OSI-Modell (7 Schichten, 1984). TCP/IP hat sich durchgesetzt, weil es das reale Internet beschreibt.
Das TCP/IP-Modell entstand praktisch aus dem ARPANET (1970er), im Gegensatz zum theoretischen OSI-Modell (Open Systems Interconnection, 7 Schichten, 1984). TCP/IP hat sich durchgesetzt, weil es das reale Internet beschreibt.
**Schicht-Aufgaben im Detail:**
@@ -447,15 +445,17 @@ Das TCP/IP-Modell entstand praktisch aus dem ARPANET (1970er), im Gegensatz zum
**Warum Schichten?** Abstraktion. HTTP muss nicht wissen, ob Ethernet oder WLAN verwendet wird. Änderungen in einer Schicht betreffen andere nicht.
<small>FTP = File Transfer Protocol · ICMP = Internet Control Message Protocol · PPP = Point-to-Point Protocol</small>
---
# Schichten verpacken Daten
![bg right:52% fit](./assets/demos/encap-layers.png)
**Encapsulation:** Jede Schicht packt ein.
**Encapsulation:** Jede Schicht verpackt die Daten der darüberliegenden Schicht.
**Decapsulation:** Beim Empfang wird ausgepackt.
**Decapsulation:** Beim Empfang packt jede Schicht ihren Teil wieder aus.
<!--
SPEAKER NOTES:
@@ -464,7 +464,7 @@ SPEAKER NOTES:
- TCP: eigener Header dazu (Ports, Seq-Nr) → weiter
- IP: eigener Header dazu (IPs) → weiter
- Ethernet: Header + Trailer (MACs, Prüfsumme)
- Am Ende: Bits → elektrische Signale / Funk
- Am Ende: Bit → elektrische Signale / Funk
- Empfang: Rückwärts auspacken
-->
@@ -507,32 +507,31 @@ SPEAKER NOTES:
| Schicht | Einheit | Header-Inhalte |
|---------|---------|----------------|
| Anwendung | Daten | HTTP-Header, Cookies, Content-Type |
| Transport | Segment | Quell-/Zielport, Sequenznummer, Flags (SYN, ACK) |
| Internet | Paket | Quell-/Ziel-IP, TTL, Protokoll (TCP=6, UDP=17) |
| Netzzugang | Frame | Quell-/Ziel-MAC, EtherType, CRC-Prüfsumme |
| Transport | Segment | Quell-/Zielport, Sequenznummer, Flags (SYN = Synchronize, ACK = Acknowledge) |
| Internet | Paket | Quell-/Ziel-IP, TTL (Time To Live), Protokoll (TCP=6, UDP=17) |
| Netzzugang | Frame | Quell-/Ziel-MAC, EtherType, CRC-Prüfsumme (Cyclic Redundancy Check) |
**Overhead-Rechnung (1 Byte HTTP-Body):**
- Ethernet: 14 + 4 Bytes (Header + Trailer)
- IP: 20 Bytes (ohne Optionen)
- TCP: 20 Bytes (ohne Optionen)
- **Minimum: 58 Bytes für 1 Byte Nutzlast**
- Ethernet: 14 + 4 Byte (Header + Trailer)
- IP: 20 Byte (ohne Optionen)
- TCP: 20 Byte (ohne Optionen)
- **Minimum: 58 Byte für 1 Byte Nutzlast**
**Decapsulation:** Empfänger packt in umgekehrter Reihenfolge aus. Jede Schicht prüft ihren Header (z.B. CRC) und reicht Nutzdaten nach oben.
---
# Warum ist das clever?
# Vorteile der Schichtung
**Ohne Schichten:**
Jede App müsste wissen, wie Ethernet-Frames gebaut werden, wie WLAN funktioniert, wie Router Pakete weiterleiten...
Jede Anwendung müsste wissen, wie Ethernet-Frames gebaut werden, wie WLAN funktioniert und wie Router Pakete weiterleiten.
**Mit Schichten:**
Der Browser sagt: "Ich will diese Seite."
Alles andere übernehmen die Schichten darunter.
Die Anwendungsschicht (z.B. der Browser) fordert nur die Seite an. Alles Weitere übernehmen die Schichten darunter.
**Austauschbarkeit:**
WLAN statt Ethernet? Nur Schicht 1 ändert sich.
HTTP/2 statt HTTP/1? Nur Schicht 4 ändert sich.
Wechselt WLAN zu Ethernet, ändert sich nur Schicht 1.
Löst HTTP/2 die Version HTTP/1 ab, ändert sich nur Schicht 4.
<!--
SPEAKER NOTES:
@@ -545,9 +544,9 @@ SPEAKER NOTES:
---
# Exkurs: OSI vs. TCP/IP
# OSI vs. TCP/IP
![bg right:50% fit](./assets/demos/osi-tcpip-diagram.png)
![bg right:48% fit](./assets/demos/osi-tcpip-diagram.png)
OSI (7 Schichten) ist ein theoretisches Referenzmodell — TCP/IP (4 Schichten) beschreibt das reale Internet.
@@ -565,7 +564,7 @@ SPEAKER NOTES:
<!-- _class: lead -->
# Die drei Adressen
## IP, MAC und Port – wer braucht was?
## IP, MAC und Port im Zusammenspiel
<!--
SPEAKER NOTES:
@@ -584,10 +583,8 @@ SPEAKER NOTES:
- **Global eindeutig** (im gesamten Internet)
- Identifiziert einen **Rechner**
- **Bleibt gleich** auf dem gesamten Weg
- Analogie: **Empfänger auf einem Brief**
Router lesen die IP und entscheiden:
"Ist das für mich? Nein → in welche Richtung weiterleiten?"
Router lesen die Ziel-IP und leiten das Paket in die passende Richtung weiter.
<!--
SPEAKER NOTES:
@@ -608,9 +605,8 @@ aa:bb:cc:dd:ee:ff
- **Lokal eindeutig** (nur im lokalen Netzwerk relevant)
- Identifiziert eine **Netzwerkkarte**
- **Ändert sich bei jedem Hop**
- Analogie: **"Nächstes Postamt: XY"**
Funktioniert nur innerhalb eines Netzwerksegments.
Sie funktioniert nur innerhalb eines Netzwerksegments.
<!--
SPEAKER NOTES:
@@ -629,11 +625,11 @@ SPEAKER NOTES:
![bg right:35% fit](./assets/demos/port-highlight.png)
Ein Port identifiziert ein **Programm** auf einem Rechner — wie eine **Wohnungstür im Mehrfamilienhaus**.
Ein Port identifiziert ein bestimmtes **Programm** (bzw. einen Dienst) auf einem Rechner.
- **80** → HTTP
- **443** → HTTPS
- **22** → SSH
- **22** → SSH (Secure Shell)
- **53** → DNS
<!--
@@ -682,6 +678,11 @@ SPEAKER NOTES:
Drei Adressebenen lösen drei verschiedene Probleme:
**Port (Schicht 3 – Transport):**
- 16 Bit → 65.535 mögliche Ports
- Well-Known Ports (0–1023): HTTP=80, HTTPS=443, SSH=22
- Ephemeral Ports (49152–65535): Dynamisch für Client-Verbindungen
**IP-Adresse (Schicht 2 – Internet):**
- Hierarchisch aufgebaut: Netzwerk-Teil + Host-Teil
- Router lesen nur den Netzwerk-Teil für Routing-Entscheidungen
@@ -693,19 +694,14 @@ Drei Adressebenen lösen drei verschiedene Probleme:
- Nur relevant für den **nächsten Hop** – wird bei jedem Router ersetzt
- ARP (Address Resolution Protocol) übersetzt IP → MAC
**Port (Schicht 3 – Transport):**
- 16 Bit → 65.535 mögliche Ports
- Well-Known Ports (0–1023): HTTP=80, HTTPS=443, SSH=22
- Ephemeral Ports (49152–65535): Dynamisch für Client-Verbindungen
**Warum ändert sich nur MAC?** IP ist das Endziel (Brief-Adresse), MAC ist der aktuelle Bote (wer trägt den Brief gerade?).
**Nur die MAC-Adresse ändert sich unterwegs:** Die IP bezeichnet das Endziel und bleibt konstant, die MAC nur den jeweils nächsten Hop und wird an jedem Router ersetzt.
---
<!-- _class: lead -->
# Die Reise eines Klicks
## Was passiert, wenn Sie `www.hdm-stuttgart.de` aufrufen?
## Was passiert, wenn ihr `www.hdm-stuttgart.de` aufruft?
<!--
SPEAKER NOTES:
@@ -719,13 +715,13 @@ SPEAKER NOTES:
# Das Szenario
Sie sind im WLAN der HdM und rufen auf:
Ihr seid im WLAN der HdM und ruft auf:
```
https://www.hdm-stuttgart.de
```
**Zwischen Enter und fertiger Seite:** ~200 Millisekunden.
Zwischen Enter und fertiger Seite vergehen rund 200 Millisekunden.
In dieser Zeit passieren hunderte Operationen.
@@ -781,11 +777,11 @@ SPEAKER NOTES:
www.hdm-stuttgart.de → 212.132.79.37
```
Ihr Laptop fragt sich durch:
Euer Laptop arbeitet die Quellen der Reihe nach ab:
1. **Browser-Cache:** "War ich da kürzlich?" → Nein
2. **OS-Cache:** "Kennt das Betriebssystem die IP?" → Nein
3. **Router/Provider:** DNS-Server wird gefragt
1. **Browser-Cache** prüfen → kein Eintrag
2. **OS-Cache** prüfen → kein Eintrag
3. **Router/Provider:** DNS-Server anfragen
<!--
SPEAKER NOTES:
@@ -802,12 +798,12 @@ SPEAKER NOTES:
![bg right:45% fit](./assets/demos/dns-tree.png)
**Dezentral:** Niemand kennt alles.
DNS ist **dezentral** organisiert: Kein Server kennt alle Namen.
Jede Ebene kennt nur die nächste:
Jede Ebene verweist nur auf die Ebene darunter:
- Root → .de, .com, .org
- .de → alle .de-Domains
- Root → TLDs (Top-Level-Domains: .de, .com, .org)
- .de → autoritative Server jeder .de-Domain
- hdm-stuttgart.de → www, mail, …
<!--
@@ -842,7 +838,7 @@ SPEAKER NOTES:
# DNS ist selbst Netzwerk
Die DNS-Anfrage ist ein ganz normales Paket:
Die DNS-Anfrage ist ein gewöhnliches Paket:
| Eigenschaft | Wert |
|-------------|------|
@@ -858,7 +854,7 @@ SPEAKER NOTES:
- DNS = normales Netzwerk-Protokoll
- Nutzt UDP (schneller, kleine Anfragen)
- Port 53
- Wird auch verpackt: UDP→IP→Ethernet→Bits
- Wird auch verpackt: UDP→IP→Ethernet→Bit
-->
---
@@ -873,7 +869,7 @@ www.hdm-stuttgart.de = 212.132.79.37
Diese Information wird gecached (für Minuten bis Stunden).
**Nächster Schritt:** Verbindung aufbauen.
Der nächste Schritt ist der Verbindungsaufbau.
<!--
SPEAKER NOTES:
@@ -900,7 +896,7 @@ SPEAKER NOTES:
---
# Warum ein Handshake?
# Zweck des Handshakes
TCP ist **verbindungsorientiert**:
@@ -909,9 +905,7 @@ TCP ist **verbindungsorientiert**:
- Verlorene Pakete können erkannt und neu angefordert werden
**Analogie:**
Telefonat: Klingeln → Abheben → "Hallo?" → Gespräch beginnt
Nicht: Einfach losreden und hoffen, dass jemand zuhört.
Telefonat: Klingeln → Abheben → Gespräch beginnt
<!--
SPEAKER NOTES:
@@ -971,7 +965,7 @@ Der Handshake synchronisiert **Sequenznummern** – essenziell für TCPs Zuverl
- SYN-Flood-Attacke: Millionen SYNs ohne ACK → Server-Ressourcen erschöpft
- Schutz: SYN-Cookies (Server speichert keinen State bis ACK kommt)
**Verbindungsabbau:** 4-Way-Handshake (FIN → ACK → FIN → ACK) oder RST für sofortigen Abbruch.
**Verbindungsabbau:** 4-Way-Handshake (FIN = Finish → ACK → FIN → ACK) oder RST (Reset) für sofortigen Abbruch.
---
@@ -981,7 +975,7 @@ Der Handshake synchronisiert **Sequenznummern** – essenziell für TCPs Zuverl
![bg right:42% fit](./assets/demos/client-server-ports.png)
**Jetzt erst** kann HTTP gesprochen werden.
Erst jetzt kann HTTP übertragen werden.
<!--
SPEAKER NOTES:
@@ -1006,10 +1000,10 @@ SPEAKER NOTES:
---
# Was Ihr Browser sendet
# Was euer Browser sendet
```http
GET / HTTP/1.1
GET / HTTP/2.0
Host: www.hdm-stuttgart.de
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html
@@ -1017,19 +1011,19 @@ Accept-Language: de-DE
Connection: keep-alive
```
~200 Bytes Text.
Der Request umfasst rund 200 Byte Text.
**GET** = "Gib mir" (im Gegensatz zu POST = "Nimm das")
**/** = "Die Startseite"
**GET** ruft Daten ab (im Gegensatz zu **POST**, das Daten sendet).
**/** bezeichnet die Startseite.
<!--
SPEAKER NOTES:
- HTTP-Request: lesbar, menschlich verständlich
- GET = "hol mir was" (POST = "hier Daten für Sie")
- GET = "hol mir was" (POST = "hier Daten für euch")
- "/" = Wurzel = Startseite
- HTTP/1.1 = Protokollversion
- HTTP/2.0 = Protokollversion
- Header: Kontext (Host, Browser, Sprache)
- ~200 Bytes Text → müssen durchs Internet
- ~200 Byte Text → müssen durchs Internet
-->
---
@@ -1041,7 +1035,7 @@ SPEAKER NOTES:
<!--
SPEAKER NOTES:
- 200 Bytes Request → was passiert damit?
- 200 Byte Request → was passiert damit?
- Schicht für Schicht verpacken
-->
@@ -1109,13 +1103,16 @@ SPEAKER NOTES:
---
# Woher kennt Ihr Laptop die Router-MAC?
<!-- _class: dimmed -->
# Router-MAC per ARP ermitteln
**ARP** – Address Resolution Protocol
![w:900 center](./assets/demos/arp-lookup.png)
Das passiert automatisch. Die Info wird gecached.
Das geschieht automatisch. Die Information wird gecached.
<!--
SPEAKER NOTES:
@@ -1130,7 +1127,7 @@ SPEAKER NOTES:
# Layer 1: Physical
Frame wird zu **Bits** – Bits werden zu Signalen:
Frame wird zu **Bit** – Bit werden zu Signalen:
| Medium | Signal |
|--------|--------|
@@ -1142,12 +1139,12 @@ Frame wird zu **Bits** – Bits werden zu Signalen:
01001000 01010100 01010100 01010000 ...
```
Ab hier übernimmt die Physik.
Ab Schicht 1 erfolgt die Übertragung physikalisch.
<!--
SPEAKER NOTES:
- Ganz unten: Physik
- Frame → Bits → Signale
- Frame → Bit → Signale
- Je nach Medium:
- Kupfer: Spannung High/Low
- Glasfaser: Licht an/aus
@@ -1170,22 +1167,22 @@ SPEAKER NOTES:
---
# Der erste Hop: Ihr Router
# Der erste Hop: Euer Router
**Laptop** → [Frame] → **Router**
Der Router empfängt:
Der Router verarbeitet das Frame in drei Schritten:
1. **Layer 1:** Signale → Bits
2. **Layer 2:** Frame prüfen. MAC okay? → Auspacken
3. **Layer 3:** IP lesen. "212.132.79.37 – nicht mein Netz"
1. **Layer 1:** Signale werden zu Bit.
2. **Layer 2:** Frame und MAC-Adresse werden geprüft, dann ausgepackt.
3. **Layer 3:** Die Ziel-IP liegt außerhalb des lokalen Netzes.
**Routing-Entscheidung:** "Ich schicke es Richtung Internet."
**Routing-Entscheidung:** Das Paket geht Richtung Internet weiter.
<!--
SPEAKER NOTES:
- Router empfängt Frame
- Physik: Signale → Bits
- Physik: Signale → Bit
- Ethernet: MAC okay? Prüfsumme okay? → auspacken
- IP: Ziel-IP lesen → 212.132.79.37 → nicht mein Netz
- Routing-Tabelle: In welche Richtung?
@@ -1193,7 +1190,7 @@ SPEAKER NOTES:
---
# Der Router verpackt NEU
# Der Router verpackt neu
![w:900 center](./assets/demos/ethernet-rehop.png)
@@ -1216,7 +1213,7 @@ SPEAKER NOTES:
![bg right:35% fit](./assets/demos/hop-chain.png)
Bei jedem Hop:
Bei jedem Hop laufen drei Schritte ab:
1. Auspacken bis Layer 3 (IP)
2. Routing-Entscheidung
@@ -1252,14 +1249,14 @@ SPEAKER NOTES:
![bg right:42% fit](./assets/demos/server-decap.png)
Jede Schicht prüft "ist das für mich?" und packt dann die nächste aus.
Jede Schicht prüft, ob das Paket für sie bestimmt ist, und packt dann die nächste aus.
Am Ende versteht der Webserver: "Jemand will die Startseite."
Am Ende erkennt der Webserver die Anfrage nach der Startseite.
<!--
SPEAKER NOTES:
- Schicht für Schicht auspacken:
- Physik → Bits
- Physik → Bit
- Ethernet → Frame prüfen → auspacken
- IP → Ziel-IP = meine? Ja → auspacken
- TCP → Port 443 = Webserver-Prozess → auspacken
@@ -1272,7 +1269,7 @@ SPEAKER NOTES:
# Der Server antwortet
```http
HTTP/1.1 200 OK
HTTP/2.0 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 45231
@@ -1283,13 +1280,13 @@ Content-Length: 45231
...
```
~45 KB HTML müssen jetzt zu Ihnen.
Rund 45 KB HTML müssen nun zu euch übertragen werden.
<!--
SPEAKER NOTES:
- Antwort: 200 OK = alles gut
- Content-Type: HTML
- Content-Length: 45231 Bytes
- Content-Length: 45231 Byte
- Dann: eigentlicher HTML-Code
-->
@@ -1297,7 +1294,7 @@ SPEAKER NOTES:
# Encapsulation beim Server
Der Server macht **dasselbe** – nur in die andere Richtung:
Der Server durchläuft dieselben Schritte – nur in umgekehrter Richtung:
![bg right:40% fit](./assets/demos/encap-stack.png)
@@ -1316,7 +1313,7 @@ SPEAKER NOTES:
![bg right:38% fit](./assets/demos/response-hops.png)
Gleiches Spiel wie der Hinweg:
Der Rückweg funktioniert wie der Hinweg:
- Hop für Hop durchs Internet
- **IP bleibt gleich** (Start/Ziel)
@@ -1331,13 +1328,13 @@ SPEAKER NOTES:
---
# Decapsulation bei Ihnen
# Decapsulation bei euch
![bg right:42% fit](./assets/demos/decap-stack.png)
Rückweg = Encapsulation umgekehrt.
Der Rückweg ist die umgekehrte Encapsulation.
Jede Schicht prüft "ist das für mich?" und packt dann die nächste aus.
Jede Schicht prüft, ob das Paket für sie bestimmt ist, und packt dann die nächste aus.
<!--
SPEAKER NOTES:
@@ -1406,7 +1403,7 @@ Beide sind Transport-Protokolle (Schicht 3), aber mit fundamental unterschiedlic
**UDP (User Datagram Protocol):**
- Verbindungslos (Fire-and-Forget)
- Keine Sequenznummern, keine ACKs
- Header nur 8 Bytes (TCP: 20+ Bytes)
- Header nur 8 Byte (TCP: 20+ Byte)
- Anwendung muss selbst für Zuverlässigkeit sorgen
| Anwendung | Protokoll | Grund |
@@ -1420,7 +1417,7 @@ Beide sind Transport-Protokolle (Schicht 3), aber mit fundamental unterschiedlic
---
# Warum UDP bei Video-Calls?
# UDP bei Video-Calls
**Szenario:** Ein Paket geht verloren.
@@ -1441,13 +1438,15 @@ SPEAKER NOTES:
---
<!-- _class: dimmed -->
# MTU & Fragmentierung
**MTU** = Maximum Transmission Unit
Ethernet-Frame kann maximal **1500 Bytes** Nutzdaten transportieren.
Ein Ethernet-Frame kann maximal **1500 Byte** Nutzdaten transportieren.
**Problem:** Ein Foto hat 3.000.000 Bytes.
**Problem:** Ein Foto hat 3.000.000 Byte.
**Lösung:** TCP zerschneidet die Daten in ~2000 Segmente.
Jedes Segment hat eine Sequenznummer.
@@ -1456,7 +1455,7 @@ Der Empfänger setzt sie zusammen.
<!--
SPEAKER NOTES:
- MTU = physikalisches Limit
- Ethernet-Frame: max 1500 Bytes Nutzdaten
- Ethernet-Frame: max 1500 Byte Nutzdaten
- Webseite 100KB, Video Gigabytes?
- TCP zerschneidet in passende Stücke
- Jedes mit Sequenznummer
@@ -1465,21 +1464,24 @@ SPEAKER NOTES:
---
<!-- _class: klausur -->
<!-- _header: '' -->
<!-- _footer: '' -->
# HTTP-Methoden
HTTP-Methoden beschreiben, **was** der Client mit einer Ressource tun will.
| Methode | Bedeutung | Beispiel |
|---------|-----------|----------|
| **GET** | Daten abrufen | Seite laden |
| **POST** | Daten senden | Formular absenden |
| **PUT** | Daten ersetzen | Profil aktualisieren |
| **DELETE** | Daten löschen | Account löschen |
| Methode | Bedeutung | Beispiel |
|---------|-----------|-----------------------------------------------|
| **GET** | Daten abrufen | Seite laden `GET /index.html HTTP/2.0` |
| **POST** | Daten senden | Formular absenden `POST /login HTTP/2.0` |
| **PUT** | Daten ersetzen | Profil aktualisieren `PUT /users/42 HTTP/2.0` |
| **DELETE** | Daten löschen | Account löschen `DELETE /users/42 HTTP/2.0` |
<small>CRUD = Create, Read, Update, Delete</small>
```http
GET /index.html HTTP/1.1
POST /login HTTP/1.1
```
<!--
SPEAKER NOTES:
@@ -1518,7 +1520,7 @@ HTTP-Methoden definieren die **Semantik** der Anfrage – was der Client vom Ser
**Idempotent:** Mehrfaches Ausführen hat denselben Effekt wie einmaliges (GET, PUT, DELETE).
**Safe:** Ändert nichts am Server (nur GET, HEAD, OPTIONS).
**REST-Prinzip:** URLs identifizieren Ressourcen, Methoden definieren Aktionen.
**REST-Prinzip** (Representational State Transfer): URLs identifizieren Ressourcen, Methoden definieren Aktionen.
```
GET /users/42 → Benutzer 42 abrufen
PUT /users/42 → Benutzer 42 vollständig ersetzen
@@ -1528,14 +1530,18 @@ POST /users → Neuen Benutzer erstellen
---
<!-- _class: klausur -->
<!-- _header: '' -->
<!-- _footer: '' -->
# HTTP Status-Codes
Jede HTTP-Response enthält einen dreistelligen Status-Code — die erste Ziffer verrät die Kategorie.
```http
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found
HTTP/1.1 500 Internal Server Error
HTTP/2.0 200 OK
HTTP/2.0 404 Not Found
HTTP/2.0 500 Internal Server Error
```
| Code-Bereich | Bedeutung |
@@ -1582,10 +1588,13 @@ Die erste Ziffer kategorisiert die Antwort:
- **301 vs. 302:** 301 = permanent umgezogen (Cache-fähig), 302 = temporär (nicht cachen)
- **304 Not Modified:** Browser hat Cache, Server bestätigt: noch aktuell → spart Bandbreite
**API-Design:** Korrekte Status-Codes sind wichtig für Clients. `200` bei Fehler mit `{"error": "..."}` im Body ist schlechtes Design.
**API-Design** (Application Programming Interface): Korrekte Status-Codes sind wichtig für Clients. `200` bei Fehler mit `{"error": "..."}` im Body ist schlechtes Design.
---
<!-- _class: dimmed -->
# Zusammenfassung Teil 1
**Der Ablauf:**
@@ -1632,11 +1641,11 @@ Die vier Kernkonzepte für Web-Entwickelnde:
- Caching auf jeder Ebene (TTL = Time To Live)
**2. TCP-Verbindungsaufbau:**
- 3-Way-Handshake vor jeder HTTP-Anfrage (HTTP/1.1)
- 3-Way-Handshake vor jeder HTTP(S)-Anfrage (HTTP/2.0)
- Keep-Alive: Verbindung bleibt offen für mehrere Requests
- HTTP/2: Multiplexing – viele Requests über eine Verbindung
**3. HTTP Request/Response:**
**3. HTTP(S) Request/Response:**
```
Request: Methode + URL + Header + (Body)
Response: Status + Header + Body
@@ -1696,7 +1705,7 @@ HTML definiert die Struktur – was ist auf der Seite. CSS definiert das Aussehe
---
# Was ist CSS?
# CSS im Überblick
![bg right:35%](./assets/demos/css-anatomie.png)
@@ -1709,7 +1718,7 @@ p {
}
```
- Trennt **Inhalt** (HTML) von **Darstellung** (CSS)
- Trennt **Inhalt** (HTML – Hypertext Markup Language) von **Darstellung** (CSS)
- "Cascading" = Regeln können überschrieben werden
- Eine CSS-Datei kann viele HTML-Seiten stylen
@@ -1729,7 +1738,7 @@ Vorteil: Ihr könnt das Design der ganzen Website ändern, indem ihr eine Datei
# CSS einbinden
**Option 1: Externe Datei** ✓
**Option 1: Externe Datei** (empfohlen)
```html
<link rel="stylesheet" href="style.css">
```
@@ -1739,7 +1748,7 @@ Vorteil: Ihr könnt das Design der ganzen Website ändern, indem ihr eine Datei
<style>p { color: blue; }</style>
```
**Option 3: Inline** ✗
**Option 3: Inline** (vermeiden)
```html
<p style="color: blue;">...</p>
```
@@ -1875,7 +1884,7 @@ Eine Klasse kann auf beliebig viele Elemente angewendet werden. Ein Element kann
**Raute** vor dem Namen = ID
⚠️ IDs sollten **einmalig** pro Seite sein.
**Achtung:** IDs sollten **einmalig** pro Seite sein.
<!--
SPEAKER NOTES:
@@ -1923,7 +1932,7 @@ Element.Klasse: Das Element muss beides sein. "p.wichtig" heißt: nur p-Elemente
---
# Spezifität: Welche Regel gewinnt?
# Spezifität von Selektoren
![bg right:35%](./assets/demos/css-specificity.png)
@@ -1979,7 +1988,7 @@ Spezifität bestimmt, welche CSS-Regel gewinnt, wenn mehrere auf dasselbe Elemen
- Eine ID schlägt jede Anzahl von Klassen
- `!important` bricht alles → vermeiden, da schwer zu überschreiben
**Best Practice:** Flache Spezifität anstreben. BEM-Methodik (`.block__element--modifier`) hält Spezifität gleichmäßig niedrig.
**Best Practice:** Flache Spezifität anstreben. BEM-Methodik (Block Element Modifier, `.block__element--modifier`) hält Spezifität gleichmäßig niedrig.
---
@@ -2059,22 +2068,19 @@ Best Practice: Setzt das global für alle Elemente.
![bg right:35%](./assets/demos/css-colors.png)
CSS kennt fünf Notationen für Farben: **Keyword**, **Hex**, **RGB**, **RGBA** (mit Transparenz) und **HSL**.
CSS kennt fünf Farb-Notationen: **Keyword**, **Hex**, **RGB**, **RGBA** und **HSL**.
```css
/* Keyword */
color: red;
color: rebeccapurple;
/* Hex */
color: #FF0000;
color: #F00;
/* RGB / RGBA */
/* RGB = Red Green Blue, RGBA mit Alpha */
color: rgb(255, 0, 0);
color: rgba(255, 0, 0, 0.5);
/* HSL */
/* HSL = Hue, Saturation, Lightness */
color: hsl(0, 100%, 50%);
```
@@ -2307,7 +2313,7 @@ Einheiten: rem für Schrift, relative Einheiten für Layout.
# Fragen & Diskussion
**Nächster Termin:** 24.01.2026 – JavaScript
**Nächstes Thema:** JavaScript
**Kontakt:** lb-czechowski@hdm-stuttgart.de
+26 -27
View File
@@ -98,7 +98,7 @@ Hochschule der Medien Stuttgart
<!-- _class: lead -->
# Kapitel 3 – 24.01.2026
# Kapitel 3
## Interaktivität & JavaScript
---
@@ -119,16 +119,15 @@ Hochschule der Medien Stuttgart
---
# Was ist JavaScript?
# JavaScript im Überblick
**Die einzige Programmiersprache, die im Browser läuft!**
JavaScript ist die einzige Programmiersprache, die nativ im Browser läuft.
- **1995:** In 10 Tagen entwickelt (Brendan Eich, Netscape)
- **Heute:** Überall – Browser, Server, Apps, IoT
**Nicht verwechseln:**
- Java ≠ JavaScript (komplett unterschiedlich!)
- "JavaScript ist zu Java wie Carpet zu Car"
- Java und JavaScript sind zwei völlig verschiedene Sprachen.
<!--
Ursprünglich "Mocha", dann "LiveScript", dann "JavaScript" (Marketing!)
@@ -159,7 +158,7 @@ ES6 = großes Update mit vielen Features
# JavaScript einbinden
**Option 1: Externe Datei (empfohlen!)**
**Option 1: Externe Datei (empfohlen)**
```html
<body>
<!-- Inhalt -->
@@ -174,7 +173,7 @@ ES6 = großes Update mit vielen Features
</script>
```
⚠️ Script am **Ende** des `<body>` – damit HTML zuerst lädt!
**Wichtig:** Das Script gehört ans **Ende** des `<body>`, damit das HTML zuerst lädt.
<!--
Externe Datei = wiederverwendbar, cachebar
@@ -184,7 +183,7 @@ Oder: defer-Attribut
---
# Die Konsole: Euer bester Freund
# Die JavaScript-Konsole
**Browser DevTools → Console**
- Windows/Linux: `F12` oder `Strg+Shift+I`
@@ -196,7 +195,7 @@ console.log(42);
console.log("Die Antwort ist:", 42);
```
**Direkt in der Konsole tippen und Enter!**
Befehle lassen sich direkt in der Konsole eingeben und mit Enter ausführen.
<!--
Console = REPL (Read-Eval-Print-Loop)
@@ -348,20 +347,20 @@ true || false // true (ODER)
**In der Browser-Konsole:**
1. Erstellen Sie Variablen für sich:
1. Erstellt Variablen für euch:
```javascript
const name = "Your Name";
let age = 20;
const hobbies = ["Hobby1", "Hobby2"];
```
2. Gib sie aus:
2. Gebt sie aus:
```javascript
console.log(`I am ${name}, ${age} years old.`);
console.log("My hobbies:", hobbies);
```
3. Erstelle ein `person`-Objekt und greife auf Properties zu
3. Erstellt ein `person`-Objekt und greift auf Properties zu
---
@@ -491,7 +490,7 @@ Funktionale Programmierung, Original-Array bleibt unverändert
---
# Was ist das DOM?
# Das DOM im Überblick
**D**ocument **O**bject **M**odel
@@ -512,7 +511,7 @@ Jedes Element ist ein Objekt
# Elemente finden
```javascript
// Einzelnes Element (erstes gefundene)
// Einzelnes Element (erstes gefundenes)
document.getElementById("meinId");
document.querySelector(".meineKlasse");
document.querySelector("nav > a");
@@ -632,10 +631,10 @@ remove = aus DOM entfernen
**Aufgaben (in script.js):**
1. Ändere den Text von `#output`
2. Füge 5 `<li>`-Elemente zur Liste hinzu (mit Schleife!)
3. Gib jedem geraden Element eine Klasse `highlight`
4. Style `.highlight` in CSS (z.B. andere Farbe)
1. Ändert den Text von `#output`
2. Fügt 5 `<li>`-Elemente zur Liste hinzu (mit Schleife)
3. Gebt jedem geraden Element eine Klasse `highlight`
4. Gestaltet `.highlight` in CSS (z. B. andere Farbe)
---
@@ -646,7 +645,7 @@ remove = aus DOM entfernen
---
# Was sind Events?
# Events im Überblick
**NutzerInnen interagieren mit der Seite:**
- Klicken
@@ -654,7 +653,7 @@ remove = aus DOM entfernen
- Scrollen
- Formulare absenden
**JavaScript kann darauf reagieren!**
JavaScript kann auf diese Ereignisse reagieren.
<!--
Event = Ereignis
@@ -784,9 +783,9 @@ toggleButton.addEventListener("click", () => {
// Button-Text ändern
if (body.classList.contains("dark-mode")) {
toggleButton.textContent = "☀️ Light Mode";
toggleButton.textContent = "Light Mode";
} else {
toggleButton.textContent = "🌙 Dark Mode";
toggleButton.textContent = "Dark Mode";
}
});
```
@@ -1002,21 +1001,21 @@ Frameworks für größere Apps, Komponenten-basiert
---
# Ihr könnt jetzt...
# Das könnt ihr jetzt
- Den historischen Kontext von IT verstehen
- Erklären wie das Internet funktioniert
- HTML-Seiten strukturieren
- CSS für Layout und Design nutzen
- JavaScript für Interaktivität einsetzen
- **Mit EntwicklerInnen auf Augenhöhe sprechen!**
- **Mit EntwicklerInnen auf Augenhöhe sprechen**
---
# Feedback – Eure Meinung zählt!
# Feedback
Euer ehrliches Feedback hilft mir, den Kurs zu verbessern.
**Es gibt keine falschen Antworten!**
Es gibt keine falschen Antworten.
- Was hat gut funktioniert?
- Was könnte besser sein?
@@ -1028,7 +1027,7 @@ Euer ehrliches Feedback hilft mir, den Kurs zu verbessern.
<!-- _class: lead -->
# Danke!
# Danke
**Kontakt:** lb-czechowski@hdm-stuttgart.de
@@ -6,47 +6,70 @@
<style>
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
body { padding: 30px 40px; display: inline-block; }
.wrap { display: flex; gap: 36px; align-items: flex-start; }
.col { display: flex; flex-direction: column; gap: 4px; }
h3 { margin: 0 0 10px; font-size: 1.1rem; color: #1a1a2e; text-align: center; }
.headers {
display: grid;
grid-template-columns: 240px 240px;
column-gap: 36px;
margin-bottom: 10px;
}
.headers h3 { margin: 0; font-size: 1.1rem; color: #1a1a2e; text-align: center; }
.grid {
display: grid;
grid-template-columns: 240px 240px;
grid-template-rows: repeat(7, 48px);
column-gap: 36px;
row-gap: 6px;
}
.box {
border: 2px solid #4a4a6a;
padding: 10px 20px;
min-width: 230px;
font-size: 0.95rem;
background: #f3f4f6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
font-size: 0.95rem;
text-align: center;
padding: 0 12px;
}
.osi .box { background: #dbeafe; border-color: #1e40af; color: #1e3a8a; }
.tcpip .box { background: #fce7d6; border-color: #c2410c; color: #7c2d12; font-weight: 600; }
.tcpip .app { min-height: 126px; }
.tcpip .trans { min-height: 40px; }
.tcpip .net { min-height: 40px; }
.tcpip .link { min-height: 82px; }
.osi {
background: #dbeafe;
border-color: #1e40af;
color: #1e3a8a;
}
.tcpip {
background: #fce7d6;
border-color: #c2410c;
color: #7c2d12;
font-weight: 600;
}
/* OSI: column 1, one box per row */
.o7 { grid-area: 1 / 1; } .o6 { grid-area: 2 / 1; } .o5 { grid-area: 3 / 1; }
.o4 { grid-area: 4 / 1; } .o3 { grid-area: 5 / 1; } .o2 { grid-area: 6 / 1; }
.o1 { grid-area: 7 / 1; }
/* TCP/IP: column 2, each block spans its OSI equivalents */
.t-app { grid-area: 1 / 2 / 4 / 2; } /* OSI 5-7 */
.t-tra { grid-area: 4 / 2 / 5 / 2; } /* OSI 4 */
.t-net { grid-area: 5 / 2 / 6 / 2; } /* OSI 3 */
.t-link { grid-area: 6 / 2 / 8 / 2; } /* OSI 1-2 */
</style>
</head>
<body>
<div class="wrap">
<div class="col osi">
<h3>OSI (7 Schichten)</h3>
<div class="box">7. Anwendung</div>
<div class="box">6. Darstellung</div>
<div class="box">5. Sitzung</div>
<div class="box">4. Transport</div>
<div class="box">3. Vermittlung</div>
<div class="box">2. Sicherung</div>
<div class="box">1. Bitübertragung</div>
</div>
<div class="col tcpip">
<h3>TCP/IP (4 Schichten)</h3>
<div class="box app">Anwendung</div>
<div class="box trans">Transport</div>
<div class="box net">Internet</div>
<div class="box link">Netzzugang</div>
</div>
<div class="headers">
<h3>OSI (7 Schichten)</h3>
<h3>TCP/IP (4 Schichten)</h3>
</div>
<div class="grid">
<div class="box osi o7">7. Anwendung</div>
<div class="box osi o6">6. Darstellung</div>
<div class="box osi o5">5. Sitzung</div>
<div class="box osi o4">4. Transport</div>
<div class="box osi o3">3. Vermittlung</div>
<div class="box osi o2">2. Sicherung</div>
<div class="box osi o1">1. Bitübertragung</div>
<div class="box tcpip t-app">Anwendung</div>
<div class="box tcpip t-tra">Transport</div>
<div class="box tcpip t-net">Internet</div>
<div class="box tcpip t-link">Netzzugang</div>
</div>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 63 KiB

+16 -11
View File
@@ -5,18 +5,17 @@
<title>Port-Highlight</title>
<style>
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, sans-serif; }
body { padding: 28px 40px; display: inline-block; }
body { padding: 28px 40px 110px; display: inline-block; }
.line {
font-family: ui-monospace, "SF Mono", monospace;
font-size: 2.2rem;
color: #1a1a2e;
display: flex;
align-items: center;
align-items: baseline;
}
.port-wrap {
display: inline-flex;
flex-direction: column;
align-items: center;
position: relative;
display: inline-block;
margin-left: 4px;
}
.port {
@@ -26,11 +25,20 @@
border-radius: 4px;
font-weight: 700;
}
.below {
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
margin-top: 4px;
}
.connector {
width: 2px;
height: 18px;
background: #c2410c;
margin-top: 4px;
}
.caption-text {
background: #fed7aa;
@@ -42,16 +50,13 @@
font-size: 1rem;
font-family: system-ui, sans-serif;
margin-top: 2px;
white-space: nowrap;
}
</style>
</head>
<body>
<div class="line">
212.132.79.37:<div class="port-wrap">
<span class="port">443</span>
<div class="connector"></div>
<div class="caption-text">Port 443 = HTTPS</div>
</div>
212.132.79.37:<span class="port-wrap"><span class="port">443</span><span class="below"><span class="connector"></span><span class="caption-text">Port 443 = HTTPS</span></span></span>
</div>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

@@ -104,7 +104,7 @@
<!-- SYN-ACK -->
<div class="msg arrow-left msg-reverse" style="left: 83px; right: 80px; top: 180px;">
<div class="label reply" style="left: 50%; transform: translateX(-50%);">SYN-ACK · Seq=5000, Ack=1001</div>
<div class="quote" style="left: 50%; transform: translateX(-50%);">"OK, ich starte bei 5000"</div>
<div class="quote" style="left: 50%; transform: translateX(-50%);">"OK, ich starte bei 5000 und erwarte 1001"</div>
</div>
<!-- ACK -->
@@ -113,7 +113,7 @@
<div class="quote" style="left: 50%; transform: translateX(-50%);">"Verstanden, los geht's"</div>
</div>
<div class="final">✓ Verbindung steht</div>
<div class="final">Verbindung steht</div>
</div>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 63 KiB

+94 -411
View File
@@ -5,7 +5,7 @@ paginate: true
backgroundColor: #fff
header: "Grundlagen IT- und Internettechnik (223015c)"
footer: "Michael Czechowski – HdM Stuttgart – SoSe 2026"
title: "Kapitel 1: Geschichte, Grundlagen & HTML"
title: Grundlagen IT- und Internettechnik
---
<style>
:root {
@@ -20,13 +20,13 @@ section {
font-size: 1.7rem;
}
h1 {
color: #a02060; /* darker raspberry */
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937; /* dark gray, almost black */
color: #1f2937;
}
pre {
background: #0f0f23;
@@ -82,10 +82,9 @@ section.aufgabe footer {
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _footer: '' -->
<!-- _backgroundColor: black -->
<!-- _backgroundColor: #000 -->
![bg fit opacity:0.2](./assets/background-termin-2.png)
![bg cover opacity:0.2](./assets/background-termin-1.png)
# Grundlagen IT- und Internettechnik
@@ -103,39 +102,6 @@ Hochschule der Medien Stuttgart
<!-- _footer: "" -->
# Die 5 Komponenten
| Komponente | Funktion |
|------------|----------|
| **Rechenwerk (ALU)** | Führt Berechnungen durch |
| **Steuerwerk** | Interpretiert Befehle, steuert Ablauf |
| **Speicherwerk** | Speichert Programme UND Daten |
| **Ein-/Ausgabe** | Tastatur, Bildschirm, Netzwerk |
| **Bus-System** | Verbindet alle Komponenten |
**Wichtig:** Programme und Daten **gemeinsam** im Speicher!
<!--
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
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Von-Neumann-Architektur: Bedeutung
**Ohne Von-Neumann-Architektur:**
@@ -173,117 +139,18 @@ PRÜFUNGSRELEVANT: Warum Von-Neumann revolutionär, Unterschied zu Harvard, Beis
<!-- _footer: "" -->
# HTML Metadaten
```html
<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
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Wie nutzen Menschen das Web?
| Eingabe | Nutzungsweise |
|---------|---------------|
| **Maus** | Klicken, Scrollen |
| **Tastatur** | Tab-Navigation, Enter, Pfeiltasten |
| **Screenreader** | Vorlesen von Inhalten (NVDA, VoiceOver, JAWS) |
| **Sprachsteuerung** | "Klicke auf Anmelden" |
| **Augensteuerung** | Eye-Tracking |
| **Switch-Geräte** | Ein-/Aus-Schalter |
→ **Nicht alle nutzen Maus + Bildschirm!**
<!--
ACCESSIBILITY (a11y): a + 11 Buchstaben + y
STATISTIK: ~15% der Weltbevölkerung haben eine Behinderung (WHO)
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
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Warum "Barrierefreiheit"?
**Rechtlich:**
- EU: European Accessibility Act (seit Juni 2025 in Kraft!)
- DE: BITV 2.0 (Behörden), Privatwirtschaft betroffen
**Ethisch:**
- Teilhabe für alle Menschen
- Digitale Inklusion
**Praktisch:**
- Bessere UX für **alle** (SEO, Mobile, ältere Menschen)
- Größerer Markt (~15% der Bevölkerung)
<!--
RECHTLICHER RAHMEN:
- European Accessibility Act (EAA): EU-Richtlinie, seit 28. Juni 2025 in Kraft
- 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
-->
# HTML-Anatomie (2/2)
- Wir unterscheiden zwischen **umschließende** und **selbst-schließende** HTML-Tags
- **Umschließend**
- `<b> ... </b>` fett-gedruckter Text (inline)
- `<a> ... </a>` Hyperlink (Verlinkung zu anderen Webseiten, Bildern)
- `<body> ... </body>` Sichtbarer Teil eines HTML-Dokuments
- `<details> ... </details>` Aufklapp-Text (Akkordion)
- **Selbst-schließend**
- `<img />` Bild, Vektorgrafik etc.
- `<input />` Eingabefeld
- `<meta />` Metadaten
---
@@ -294,17 +161,16 @@ PRÜFUNGSRELEVANT: EAA kennen, Curb-Cut-Effekt erklären können, Business Case
# Barrieren im Netz vermeiden (a11y)
**Tastatur-Test:**
- Alle Funktionen nur mit Tab + Enter nutzbar?
- Fokus immer sichtbar?
- Logische Tab-Reihenfolge?
- Alle Funktionen sind nur mit Tab + Enter nutzbar
- Fokus immer sichtbar: Textlinks, Buttons, Texteingabe etc.
- Logische Tab-Reihenfolge: "Skip to main", Navigation, Hauptinhalt
**Screenreader-Test:**
- VoiceOver (Mac): `Cmd + F5`
- NVDA (Windows): Gratis-Download
**Tools:**
- axe DevTools, WAVE (Browser-Extensions)
- Lighthouse (in Chrome DevTools)
**Tools/Browser-Extensions:**
- [WAVE](https://wave.webaim.org/), [axe DevTools](https://www.deque.com/axe/devtools/), [Web Disability Simulator](https://chromewebstore.google.com/detail/web-disability-simulator/olioanlbgbpmdlgjnnampnnlohigkjla)
<!--
Automatische Tests finden ~30% der Probleme
@@ -319,168 +185,19 @@ Echte NutzerInnen einbeziehen = Gold-Standard
<!-- _footer: "" -->
# Das TCP/IP-Modell
| Schicht | Name | Aufgabe | Protokolle |
|---------|------|---------|------------|
| **4** | Anwendung | Was? Welcher Dienst? | HTTP, DNS, SMTP |
| **3** | Transport | Zuverlässigkeit, Ports | TCP, UDP |
| **2** | Internet | Routing, globale Adressen | IP |
| **1** | Netzzugang | Lokale Übertragung | Ethernet, WLAN |
**4 Schichten. Das reicht, um das Internet zu verstehen.**
<!--
SPEAKER NOTES:
- TCP/IP = das echte Internet
- 4 Schichten:
- Anwendung: Was will ich? (HTTP, DNS, Mail)
- Transport: Kommt an? Welches Programm? (TCP, UDP)
- Internet: Wie zum Zielrechner? (IP)
- Netzzugang: Wie zum nächsten Gerät? (Ethernet, WLAN)
- KLAUSUR: Welches Protokoll → welche Schicht
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Dateneinheiten pro Schicht
| Schicht | Name | Dateneinheit | Was kommt hinzu? |
|---------|------|--------------|------------------|
| Anwendung | HTTP, DNS | **Daten** | – |
| Transport | TCP, UDP | **Segment** | Ports, Sequenznummern |
| Internet | IP | **Paket** | IP-Adressen |
| Netzzugang | Ethernet | **Frame** | MAC-Adressen, Prüfsumme |
Merkhilfe: **D**aten → **S**egment → **P**aket → **F**rame
(„**D**er **S**ache **P**raktischer **F**olgen")
<!--
SPEAKER NOTES:
- Glossar-Begriffe jetzt eingeordnet:
- Anwendung: Daten/Message
- Transport: Segment
- Internet: Paket
- Netzzugang: Frame
- Merkhilfe: D-S-P-F (eigene erfinden!)
- KLAUSUR: Begriff → Schicht
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# IP vs. MAC vs. Port
| | IP-Adresse | MAC-Adresse | Port |
|---|-----------|-------------|------|
| **Frage** | Welcher Rechner? | Welches Gerät nebenan? | Welches Programm? |
| **Reichweite** | Global | Lokal (1 Hop) | Auf einem Rechner |
| **Ändert sich?** | Nein | Ja, bei jedem Hop | Nein |
| **Schicht** | Internet (IP) | Netzzugang (Ethernet) | Transport (TCP/UDP) |
| **Beispiel** | 212.132.79.37 | aa:bb:cc:dd:ee | 443 |
<!--
SPEAKER NOTES:
- KLAUSUR: Diese Tabelle
- IP: Welcher Rechner? Global. Bleibt gleich.
- MAC: Welcher Nachbar? Lokal. Ändert sich.
- Port: Welches Programm? Bleibt gleich.
- Merken: NUR MAC ändert sich unterwegs
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Der 3-Way-Handshake
```
Client (dein Laptop) Server
| |
|-------- SYN (Seq=1000) --------------->|
| "Ich will reden" |
| |
|<--- SYN-ACK (Seq=5000, Ack=1001) ------|
| "OK, ich auch. Ich starte bei 5000"|
| |
|-------- ACK (Ack=5001) --------------->|
| "Verstanden, los geht's" |
| |
| [ Verbindung steht ] |
```
**SYN** = Synchronize · **ACK** = Acknowledge
<!--
SPEAKER NOTES:
- 3 Pakete → Verbindung steht
- 1. Client SYN: "Will Verbindung, starte bei 1000"
- 2. Server SYN-ACK: "OK, ich starte bei 5000, erwarte 1001"
- 3. Client ACK: "Verstanden, erwarte 5001"
- Seq-Nr wichtig: Beide wissen nächstes erwartetes Byte
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# TCP vs. UDP
| | TCP | UDP |
|---|-----|-----|
| **Verbindung** | Ja (Handshake) | Nein |
| **Reihenfolge** | Garantiert | Nicht garantiert |
| **Verlorene Pakete** | Werden nachgefordert | Gehen verloren |
| **Overhead** | Höher | Niedriger |
| **Use Cases** | Web, Email, Downloads | Video-Calls, Gaming, DNS |
<!--
SPEAKER NOTES:
- Zwei Transport-Protokolle
- TCP: zuverlässig
- Handshake, Seq-Nr, Bestätigungen, Neuübertragung
- Perfekt für Web, Downloads (nichts darf fehlen)
- UDP: schneller
- Kein Handshake, keine Bestätigungen
- Verloren = weg
- Perfekt für Video-Calls (Verzögerung schlimmer als Verlust)
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# HTTP-Methoden
| Methode | Bedeutung | Beispiel |
|---------|-----------|----------|
| **GET** | Daten abrufen | Seite laden |
| **POST** | Daten senden | Formular absenden |
| **PUT** | Daten ersetzen | Profil aktualisieren |
| **DELETE** | Daten löschen | Account löschen |
HTTP-Methoden beschreiben, **was** der Client mit einer Ressource tun will.
| Methode | Bedeutung | Beispiel |
|---------|-----------|-----------------------------------------------|
| **GET** | Daten abrufen | Seite laden `GET /index.html HTTP/2.0` |
| **POST** | Daten senden | Formular absenden `POST /login HTTP/2.0` |
| **PUT** | Daten ersetzen | Profil aktualisieren `PUT /users/42 HTTP/2.0` |
| **DELETE** | Daten löschen | Account löschen `DELETE /users/42 HTTP/2.0` |
<small>CRUD = Create, Read, Update, Delete</small>
```http
GET /index.html HTTP/1.1
POST /login HTTP/1.1
```
<!--
SPEAKER NOTES:
@@ -505,10 +222,12 @@ Das wird wichtiger, wenn ihr mit REST-APIs arbeitet.
# HTTP Status-Codes
Jede HTTP-Response enthält einen dreistelligen Status-Code — die erste Ziffer verrät die Kategorie.
```http
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found
HTTP/1.1 500 Internal Server Error
HTTP/2.0 200 OK
HTTP/2.0 404 Not Found
HTTP/2.0 500 Internal Server Error
```
| Code-Bereich | Bedeutung |
@@ -539,112 +258,76 @@ Status-Codes sagen euch, was passiert ist.
<!-- _footer: "" -->
# Zusammenfassung Teil 1
# Selektoren: ID
**Der Ablauf:**
1. DNS (UDP:53) → Name zu IP
2. TCP-Handshake (SYN → SYN-ACK → ACK)
3. HTTP-Request (GET /...)
4. HTTP-Response (200 OK + HTML)
![bg right:35%](./assets/demos/css-selector-id.png)
**Die Konzepte:**
- 4 Schichten: Anwendung → Transport → Internet → Netzzugang
- IP bleibt gleich, MAC ändert sich pro Hop
- Ports identifizieren Programme
- Encapsulation: Jede Schicht verpackt die darüberliegende
<!--
SPEAKER NOTES:
Das ist die Zusammenfassung für Teil 1. Das solltet ihr können:
Den Ablauf: DNS, TCP-Handshake, HTTP-Request, HTTP-Response.
Die Schichten und ihre Protokolle.
Den Unterschied zwischen IP und MAC – was bleibt gleich, was ändert sich.
Was Ports tun.
Wie Encapsulation funktioniert.
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Spezifität: Welche Regel gewinnt?
| Selektor | Spezifität |
|----------|------------|
| Element (`p`) | 0,0,0,1 |
| Klasse (`.wichtig`) | 0,0,1,0 |
| ID (`#header`) | 0,1,0,0 |
| Inline (`style="..."`) | 1,0,0,0 |
```css
p { color: blue; } /* 0,0,0,1 */
.text { color: green; } /* 0,0,1,0 → gewinnt */
#intro { color: red; } /* 0,1,0,0 → gewinnt über beide */
```html
<nav id="hauptnavigation">...</nav>
```
<!--
SPEAKER NOTES:
Wenn mehrere Regeln auf ein Element zutreffen, gewinnt die spezifischere.
Spezifität wird in vier Zahlen gemessen. Von links nach rechts: Inline, IDs, Klassen, Elemente.
Ein Element-Selektor hat 0,0,0,1. Eine Klasse hat 0,0,1,0. Eine ID hat 0,1,0,0.
0,0,1,0 schlägt 0,0,0,99 – auch hundert Element-Selektoren schlagen keine Klasse.
Inline-Styles schlagen alles – außer !important, was ihr vermeiden solltet.
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Responsive Design
```css
/* Mobile First: Basis-Styles */
.container {
#hauptnavigation {
background: #333;
padding: 1rem;
background: white;
}
/* Ab 768px (Tablet): Anpassungen */
@media (min-width: 768px) {
.container {
padding: 2rem;
background: red;
}
}
/* Ab 1024px (Desktop): Weitere Anpassungen */
@media (min-width: 1024px) {
.container {
background: green;
}
}
```
**Raute** vor dem Namen = ID
**Achtung:** IDs sollten **einmalig** pro Seite sein.
<!--
SPEAKER NOTES:
Responsive Design: Die Seite passt sich der Bildschirmgröße an.
ID-Selektoren sind noch spezifischer. Raute vor dem Namen.
Mobile First: Ihr schreibt zuerst die Styles für kleine Screens. Dann fügt ihr mit @media-Queries Anpassungen für größere Screens hinzu.
IDs sollten auf einer Seite nur einmal vorkommen. Für Navigation, Header, Footer, Main – einmalige Elemente.
min-width heißt: "ab dieser Breite". Also: Basis gilt für alle. Ab 768px gelten zusätzliche Regeln. Ab 1024px noch mehr.
Das Gegenteil wäre Desktop First mit max-width – aber Mobile First ist heute Standard.
In der Praxis: Klassen sind meist besser. IDs haben hohe Spezifität und sind unflexibel.
-->
---
<!-- _header: "" -->
<!-- _footer: "" -->
# Farben
![bg right:35%](./assets/demos/css-colors.png)
CSS kennt fünf Farb-Notationen: **Keyword**, **Hex**, **RGB**, **RGBA** und **HSL**.
```css
/* Keyword */
color: red;
color: rebeccapurple;
/* Hex */
color: #FF0000;
color: #F00;
/* RGB = Red Green Blue, RGBA mit Alpha */
color: rgb(255, 0, 0);
color: rgba(255, 0, 0, 0.5);
/* HSL = Hue, Saturation, Lightness */
color: hsl(0, 100%, 50%);
```
MDN-Referenz: [CSS `<color>`](https://developer.mozilla.org/de/docs/Web/CSS/Reference/Values/color_value)
<!--
SPEAKER NOTES:
Farben können auf verschiedene Arten angegeben werden.
Keywords: red, blue, rebeccapurple. Begrenzte Auswahl, aber lesbar.
Hex: Sechs Zeichen, je zwei für Rot, Grün, Blau. #FF0000 ist reines Rot.
RGB: Gleiche Idee, aber dezimal. rgb(255, 0, 0).
RGBA: Mit Alpha-Kanal für Transparenz. 0 ist unsichtbar, 1 ist voll sichtbar.
HSL: Hue, Saturation, Lightness. Manchmal intuitiver für Farbanpassungen.
-->
File diff suppressed because it is too large. Load diff
+666
View File
@@ -0,0 +1,666 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2026"
title: Intro
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #d63384;
--color-dimmed: #4a4a6a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.4rem;
}
h1 {
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937;
}
section.invert h2 {
color: #f48fb1;
}
pre {
background: #0f0f23;
color: #f48fb1;
border-radius: 8px;
border-left: 3px solid #d63384;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a1a2e;
color: #f48fb1;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
![bg cover opacity:0.2](./assets/background.png)
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026**
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
# Ressourcen zum Selbstlernen
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
- **MDN** (Mozilla Developer Network) — [developer.mozilla.org/de/](https://developer.mozilla.org/de/)
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
---
<!-- _class: lead -->
# Herzlich Willkommen!
## 1. Sitzung: 08.05.2026
---
# Über mich
![bg right:33% fit](./assets/logos/collage.png)
**Michael Werner Czechowski**
- Systems and Platform Engineer
- Schwerpunkte:
- Web-Technologien, Barriere-Armut, Open Source
- Hintergrund:
- Philosophie (Uni Stuttgart)
- Wirtschaftsinformatik (Leibniz-FH Hannover)
- Honorardozent (DHBW Stuttgart, HdM Stuttgart, Leibniz-FH)
- Kontakt: michael.czechowski@lehre.dhbw-stuttgart.de
---
# Vorstellungsrunde
## Wer bist du, was machst du?
> Ich bin \_\_\_, mache bei \_\_\_ \_\_\_ und ein Fun Fact über mich ist, dass ich ...
- ... sämtliche One Piece Bände gelesen habe.
- ... alle XKCD Comics mit Titel kenne.
- ... irgendwann bei \_\_\_ arbeiten möchte.
- ... Paulaner Spezi im Blindtest herausschmecken kann.
---
# Vorlesungsplan
<style scoped>
.lp-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-top: 0.5rem;
}
.lp-card {
border: 1px solid #d63384;
border-radius: 8px;
padding: 10px 12px;
background: #fff;
font-size: 0.95em;
display: flex;
flex-direction: column;
gap: 4px;
}
.lp-card .head {
font-weight: bold;
color: #a02060;
display: flex;
justify-content: space-between;
align-items: baseline;
font-size: 0.85em;
}
.lp-card .head .num {
font-size: 1.1em;
}
.lp-card .topic {
color: #1a1a2e;
line-height: 1.25;
}
.lp-card.milestone {
background: #fce4ec;
border-color: #a02060;
border-width: 2px;
}
.lp-card.milestone .topic {
font-weight: bold;
}
</style>
<div class="lp-grid">
<div class="lp-card"><div class="head"><span class="num">1</span><span>08.05.</span></div><div class="topic">Intro · Projektgruppen · Internet 101</div></div>
<div class="lp-card"><div class="head"><span class="num">2</span><span>15.05.</span></div><div class="topic">HTML und CSS (Frameworks)</div></div>
<div class="lp-card"><div class="head"><span class="num">3</span><span>22.05.</span></div><div class="topic">JS (Frameworks) und npm</div></div>
<div class="lp-card"><div class="head"><span class="num">4</span><span>29.05.</span></div><div class="topic">nodeJS: Scripting, Running, Building</div></div>
<div class="lp-card"><div class="head"><span class="num">5</span><span>05.06.</span></div><div class="topic">Express API, CRUD, Middlewares</div></div>
<div class="lp-card milestone"><div class="head"><span class="num">6</span><span>12.06.</span></div><div class="topic">Projektwerkstattbericht</div></div>
<div class="lp-card"><div class="head"><span class="num">7</span><span>19.06.</span></div><div class="topic">Testing (Unit · Integration · E2E)</div></div>
<div class="lp-card"><div class="head"><span class="num">8</span><span>26.06.</span></div><div class="topic">TypeScript</div></div>
<div class="lp-card"><div class="head"><span class="num">9</span><span>03.07.</span></div><div class="topic">Docker · Proxies · DBs</div></div>
<div class="lp-card"><div class="head"><span class="num">10</span><span>10.07.</span></div><div class="topic">Wrap-up & Projektsupport</div></div>
<div class="lp-card milestone"><div class="head"><span class="num">11</span><span>17.07.</span></div><div class="topic">Präsentation</div></div>
</div>
---
# Erwartungen und Wünsche
- Was haben wir bisher gelernt?
- Was kennen wir bereits aus dem Arbeitskontext?
- Welche Technologien nutzen wir bereits?
- Was möchte ich hier lernen: Frontend, Backend, DevOps?
- Eigene FOSS entwickeln?
- CLI-Skills verbessern?
- Cloud, Cloud, Cloud?
---
# Prüfungsleistung – Übersicht
Eigenes Projekt: **Web-Applikation** XOR **Backend** (API/CLI).
| Punkte | Bereich |
|--------|---------|
| 30 | Grundanforderungen (Projektgrundlagen + Präsentation) |
| 25 | Clean Code Prinzipien |
| 25 | Accessibility & UX |
| 20 | Technische Umsetzung |
| **100** | **Basispunkte** |
| +15 | Bonuspunkte (max. 3 Features a 5 P.) |
---
# Prüfungsleistung – Grundanforderungen (30 P.)
**Projektgrundlagen (15 P.)**
- Funktionsfähige Anwendung (8 P.)
- Repository mit Versionskontrolle (4 P.)
- Projektdokumentation / README (3 P.)
**Präsentation (15 P.)**
- Elevator Pitch (5 P.)
- Technische Präsentation (5 P.)
- Projektevolution: wie hat sich das Projekt vs. Ursprungsidee verändert? (5 P.)
---
# Prüfungsleistung – Clean Code (25 P.)
**Projektstruktur (10 P.)**
- Ordnerstruktur (5 P.)
- Datei-Organisation (5 P.)
**Code-Qualität (10 P.)**
- KISS – Keep It Simple, Stupid (3 P.)
- Beschreibende Namen (3 P.)
- Funktionsverantwortlichkeiten (4 P.)
**Kommentierung & Dokumentation (5 P.)**
---
# Prüfungsleistung – Accessibility & UX (25 P.)
**Web Accessibility (15 P.)**
- Semantisches HTML (5 P.)
- ARIA Labels & Alt-Texte (5 P.)
- Tastaturnavigation (5 P.)
**Responsive Design (10 P.)**
- Mobile First Approach (5 P.)
- Flexbox/Grid Layout (5 P.)
---
# Prüfungsleistung – Technische Umsetzung (20 P.)
- Plattformunabhängigkeit (5 P.)
- Package Management (5 P.)
- Build Tools & Optimierung (5 P.)
- Live-Demo (5 P.)
---
# Prüfungsleistung – Bonuspunkte (max. 15 P.)
Mindestens 2 Bereiche wählen, je 5 Punkte:
- API Integration
- Local Storage / State Management
- Progressive Web App Features
- Testing
- Erweiterte Responsive Features (3+ Breakpoints)
- Security Features
---
# Prüfungsleistung – Abgabe & Termine
- **Code-Upload:** bis 27.07.
- **Präsentation:** 17.07. (Gruppen, ~10 Min.)
Details: https://git.librete.ch/DHBW/pruefungsleistung
---
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# Was ist (k)eine Web Applikation?
## Exkurs
---
# Was ist (k)eine Web Applikation?
**Keine Web Applikation ist:**
* Betriebssystem (GNU/Linux, Windows, macOS, iOS, Android)
* Desktop-Applikation
* Mobile-Applikation
* Embedded System (Microcontroller, IoT)
**Eine Web Applikation ist:**
* plattformunabhängig (läuft im Browser)
* nutzt in der Regel HTTP-Requests
* keine Installation nötig — serverseitig aktualisiert
* gebaut in Web-Technologien (HTML, CSS, JS/TS)
* skalierbar durch verteilte Architektur
---
# Internet-Timeline
| Jahr | Meilenstein |
|------|-------------|
| **1966** | ARPANET-Projekt startet (DARPA) |
| **1969** | Erste Verbindung zwischen UCLA und Stanford |
| **1974** | TCP/IP-Protokoll entwickelt |
| **1989** | Tim Berners-Lee erfindet das WWW (CERN) |
| **1993** | Mosaic — erster grafischer Browser |
| **1994** | W3C gegründet (HTML, CSS, SVG, WCAG) |
| **1995** | ECMAScript / JavaScript wird Standard |
| **2008** | V8 JavaScript Engine (Chrome / Node.js) |
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/arpanet.jpg)
---
# Das WWW (1989)
**Tim Berners-Lee** am **CERN** (Genf)
**Problem:** Wissenschaftler:innen können Forschungsdokumente nicht verlinken — Inkompatible Systeme, kein gemeinsames Format.
**Lösung — drei Bausteine:**
- **HTML** — Auszeichnungssprache für Dokumente
- **HTTP** — Protokoll zur Übertragung
- **URL** — eindeutige Adressen
**1991:** erste Webseite geht online · 1993 vom CERN gemeinfrei freigegeben.
→ WWW ≠ Internet. Das WWW ist eine **Anwendung auf** dem Internet.
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/mosaic.jpg)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg cover](./assets/img_633d7b91366e0-1025x538-768x403.jpg)
---
# Heute: Physische Infrastruktur
- **5,5 Milliarden** Menschen online
- **> 400 Unterseekabel**, ca. **1,3 Mio. km** Glasfaser
- Daten reisen mit **Lichtgeschwindigkeit**
- Latenz Frankfurt — New York: ~80 ms
→ Keine "Cloud" ohne Kabel. Das Internet ist **physische** Infrastruktur — und damit angreifbar.
**Geopolitik:** Five-Eyes-Allianz (USA, UK, CA, AU, NZ) zapft Unterseekabel ab (Programm "Tempora", aufgedeckt 2013 durch Snowden). DE ist Teil der Fourteen Eyes.
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/browser-server-sequence.png)
---
# HTTP – Hypertext Transfer Protocol
**Request:**
```
GET /products HTTP/1.1
Host: localhost:8080
```
**Response:**
```
HTTP/1.1 200 OK
Content-Type: application/json
[{"id": 1, "name": "Produkt A"}, ...]
```
---
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# Onboarding
## Tools, Runtimes, Workflows
---
# Werkzeuge & Betriebssystem
**Erforderliche Werkzeuge:**
- **Terminal** (zsh / bash / fish / pwsh) — Kommandozeile
- **Editor** (siehe folgende Folie)
- **JavaScript-Runtime** (Node.js / Bun / Deno)
- **Browser mit DevTools** (Chromium / Firefox / Safari)
- **Git** — verteiltes Versionskontrollsystem (Stand der Industrie)
**OS-Empfehlung:**
| OS | Status |
|----|--------|
| **macOS** | First-class, viele Tools "just work" |
| **Linux** | First-class, beste Server-Parität |
| **Windows + WSL2** | Empfohlen — Windows-CLI hat Edge Cases |
| **Windows nativ** (PowerShell) | Funktioniert, aber holpriger Pfad |
---
# Node.js installieren – macOS
Empfohlen: **LTS** (aktuell **Node.js 24** — Stand 2026).
Paketmanager: **[Homebrew](https://brew.sh)**
```bash
# Homebrew installieren (falls nicht vorhanden)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Node.js LTS installieren
brew install node@24
# Version prüfen
node --version
npm --version
```
Alternative: Installer von [nodejs.org](https://nodejs.org)
---
# Node.js installieren – Linux
Empfohlen: **LTS** (aktuell **Node.js 24**).
**Debian / Ubuntu** ([NodeSource](https://github.com/nodesource/distributions)):
```bash
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs
```
**Arch / Manjaro:**
```bash
sudo pacman -S nodejs npm
```
**Fedora / RHEL:**
```bash
sudo dnf module install nodejs:24/common
```
→ Distro-Pakete sind oft **veraltet**. Versionsmanager (folgende Folie) bevorzugen.
---
# Node.js installieren – Windows
Empfohlen: **LTS** (aktuell **Node.js 24**).
**Option 1: winget** (empfohlen, Win 10/11):
```powershell
winget install OpenJS.NodeJS.LTS
```
**Option 2: Chocolatey** ([chocolatey.org](https://chocolatey.org)):
```powershell
choco install nodejs-lts
```
**Option 3: Scoop** ([scoop.sh](https://scoop.sh)):
```powershell
scoop install nodejs-lts
```
**Option 4:** Installer von [nodejs.org](https://nodejs.org)
→ **Empfehlung:** WSL2 + Linux-Workflow nutzen.
---
# Direkt-Install: Wenn es eng wird
**Typisches Szenario** — drei parallele Projekte mit unterschiedlichen Anforderungen:
| Projekt | Stack | Node-Version |
|---------|-------|--------------|
| Praktikums-API | Express (Legacy) | 18.x (LTS Hydrogen) |
| Studienarbeit | Next.js 15 | 22.x (LTS Jod) |
| Aktuelles Lab-Projekt | neueste Features | 24.x (Iron, current LTS) |
System-Install kennt nur **eine** Node-Version global → Konflikt.
---
# Symptome im Alltag
- `npm install` bricht mit `engines`-Warning ab
- native Module (z. B. `node-sass`) bauen nicht
- CI-Pipeline ist grün, lokal rot — oder umgekehrt
- erheblicher Zeitverlust beim Debuggen von Versions-Konflikten
→ Lösung: **Versionsmanager** und Node-Version pro Projekt pinnen.
---
# Node-Versionsmanager
Verschiedene Projekte brauchen oft verschiedene Node-Versionen. **Lösung:** Versionsmanager.
| Tool | Sprache | Geschwindigkeit | Plattform |
|------|---------|-----------------|-----------|
| **nvm** | Bash | langsam (Shell-Funktion) | macOS, Linux |
| **fnm** | Rust | sehr schnell | macOS, Linux, Windows |
| **asdf** | Bash | mittel, multi-language | macOS, Linux |
| **volta** | Rust | schnell, pinning per `package.json` | alle |
```bash
# fnm
curl -fsSL https://fnm.vercel.app/install | bash
fnm install --lts # aktuell Node 24
fnm use lts-latest
# .nvmrc / .node-version automatisch
echo "lts/*" > .nvmrc
fnm use # liest .nvmrc
```
---
# Alternative Runtimes
| Runtime | Erschienen | Engine | USP |
|---------|------------|--------|-----|
| **Node.js** | 2009 | V8 (C++) | Standard, größtes Ökosystem |
| **Deno** | 2020 | V8 (Rust) | Sicherheit, TypeScript nativ, Std-Lib |
| **Bun** | 2022 | JavaScriptCore (Zig) | Geschwindigkeit, all-in-one |
```bash
# Deno
curl -fsSL https://deno.land/install.sh | sh
deno run main.ts
# Bun
curl -fsSL https://bun.sh/install | bash
bun install
bun run dev
```
→ Im Kurs primär **Node.js**. Bun und Deno sind ebenfalls zulässig.
---
# Editor (IDE)
- **VS Code** (empfohlen) — kostenlos, große Plugin-Auswahl
- **JetBrains WebStorm** — sehr mächtig, kostenpflichtig
- kostenlos für Studierende via [JetBrains Education](https://www.jetbrains.com/community/education/#students)
- **Vim / Neovim / Emacs** — für CLI-Profis
- **Zed** — modern, schnell
---
# Browser DevTools
Chromium / Firefox / Safari — `F12` oder `Cmd+Opt+I`
<small>Chromium = Open-Source-Basis von Chrome, Edge, Brave, Opera, Vivaldi etc.</small>
**Wichtigste Panels:**
- **Network** — HTTP-Requests, Responses, Timing
- **Console** — `console.log`, JS-Errors, REPL
- **Elements** — DOM-Inspektor, Live-CSS-Editor
- **Sources** — Debugger, Breakpoints, Source-Maps
- **Performance** — Profiling, Frame-Rate, FPS
- **Application** — LocalStorage, Cookies, Service Workers
---
# HTTP-Clients
- **Bruno** ([usebruno.com](https://usebruno.com)) — open source, git-friendly
- **Hoppscotch** ([hoppscotch.io](https://hoppscotch.io)) — open source, browser-basiert (vormals Postwoman)
- **Insomnia** / **Postman** — etabliert, freemium
- **curl** / **httpie** — CLI (Command-Line Interface, scriptbar)
---
# Git Setup & Workflow
**Einmalige Konfiguration:**
```bash
git config --global user.name "Vorname Nachname"
git config --global user.email "vorname.nachname@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase true
```
**SSH-Key für GitHub/GitLab:**
```bash
ssh-keygen -t ed25519 -C "vorname.nachname@example.com"
cat ~/.ssh/id_ed25519.pub # → in GitHub-Settings einfügen
```
**Tägliche Befehle:**
```bash
git status # was hat sich geändert?
git add <file> # für Commit vormerken
git commit -m "feat: ..." # Conventional Commits
git push # hochladen
git pull --rebase # neueste Änderungen holen
```
---
# Projekt-Skeleton
```bash
mkdir mein-projekt && cd mein-projekt
git init
npm init -y # erzeugt package.json
echo "node_modules" > .gitignore
echo ".env" >> .gitignore
npm install express
```
**`package.json` minimal:**
```json
{
"name": "mein-projekt",
"version": "0.1.0",
"type": "module",
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js"
}
}
```
`.env` für Secrets (nie committen!), `.env.example` mit Dummy-Werten committen.
---
File diff suppressed because it is too large. Load diff
-292
View File
@@ -1,292 +0,0 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2026"
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #d63384;
--color-dimmed: #4a4a6a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.4rem;
}
h1 {
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937;
}
section.invert h2 {
color: #f48fb1;
}
pre {
background: #0f0f23;
color: #f48fb1;
border-radius: 8px;
border-left: 3px solid #d63384;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a1a2e;
color: #f48fb1;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026** · Sitzung 2 — HTML & CSS (Frameworks)
---
# Ressourcen zum Selbstlernen
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
- **MDN** (Mozilla Developer Network) — [developer.mozilla.org/de/](https://developer.mozilla.org/de/)
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
---
# Inhalt
Aufbauend auf den Grundlagen aus Sitzung 1.
1. Attribut-Selektoren
2. Combinators (vertieft)
3. Pseudo-Klassen — erweitert
4. Shorthand Properties
5. Flexbox-Shorthands
6. Custom Properties (Variables)
7. CSS Functions (`calc`, `clamp`, ...)
8. Transition & Animation
9. CSS Frameworks (Tailwind & Co.)
---
<!-- _class: invert -->
<!-- _backgroundColor: #000 -->
# CSS: Extended
---
# CSS Selectors – Attribut-Selektoren
```css
/* presence */
[disabled] { opacity: 0.5; }
/* exact value */
[type="email"] { border-color: blue; }
/* contains word */
[class~="btn"] { cursor: pointer; }
/* starts with */
[href^="https"] { color: green; }
/* ends with */
[src$=".png"] { border: 1px solid #ccc; }
/* contains substring */
[class*="icon"] { padding-left: 20px; }
```
---
# CSS Combinators
```css
/* Child (direkt) */
div > p { margin: 0; }
/* Descendant (Nachkomme) */
div p { margin: 0; }
/* Next Sibling */
h1 + p { font-size: 1.2em; }
/* Subsequent Sibling */
h1 ~ p { color: #666; }
/* Selector List */
h1, h2, h3 { font-weight: bold; }
```
---
# Pseudo Classes – Erweitert
```css
/* Form States */
:valid { border-color: green; }
:invalid { border-color: red; }
:placeholder-shown { color: #999; }
/* Content */
:before { content: "→ "; }
:after { content: " [Wichtig]"; }
:first-letter { font-size: 2em; }
:first-line { font-weight: bold; }
/* NOT */
:not(.disabled) { pointer-events: auto; }
:not(:last-child) { border-bottom: 1px solid #ccc; }
```
---
# Shorthand Properties
```css
/* margin: top right bottom left */
margin: 10px 20px 10px 20px;
/* centering */
margin: 0 auto;
/* padding same */
padding: 20px;
/* border: width style color */
border: 1px solid #333;
/* background: color image position/size repeat */
background: #fff url(logo.png) 0 0 no-repeat;
/* font: style variant weight size/line-height family */
font: italic normal bold 16px/1.5 Arial, sans-serif;
```
---
# Flexbox Shorthands
```css
/* flex: grow shrink basis */
flex: 1 0 auto;
/* place-items: align-items justify-items */
place-items: center stretch;
/* place-content: align-content justify-content */
place-content: space-between center;
/* gap: row-gap column-gap */
gap: 20px 40px;
```
---
# CSS Custom Properties (Variables)
```css
:root {
--primary-color: #d63384;
--spacing: 20px;
--radius: 8px;
}
.button {
background: var(--primary-color);
padding: var(--spacing);
border-radius: var(--radius);
}
```
---
# CSS Functions
```css
/* calc */
width: calc(100% - 40px);
/* min/max/clamp */
width: min(100%, 600px);
font-size: clamp(14px, 2vw, 20px);
/* var with fallback */
color: var(--text-color, #333);
/* rgb/rgba/hsl/hsla */
color: hsl(200, 100%, 50%);
background: rgba(0, 0, 0, 0.5);
```
---
# Transition & Animation
```css
/* transition: property duration timing-function */
transition: all 0.3s ease-in-out;
transition: background 0.2s, transform 0.1s;
/* animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-out;
}
```
---
# CSS Frameworks
| Framework | Stil |
|-----------|------|
| **Bootstrap** | Komponenten + Grid, opinionated |
| **Tailwind CSS** | Utility-First, atomar |
| **Bulma** | klassisch, ohne JS |
| **shadcn/ui** | kopierbare Komponenten (Tailwind-basiert) |
| **Flowbite** | Tailwind-Komponentenbib. |
---
# Tailwind CSS – Beispiel
```html
<button class="bg-blue-600 hover:bg-blue-700
text-white font-semibold
px-4 py-2 rounded-lg
transition shadow-sm">
Klick mich
</button>
```
- Keine eigenen CSS-Klassen mehr
- JIT-Compiler erzeugt nur genutzte Klassen
- Design-System via `tailwind.config.js`
+412
View File
@@ -0,0 +1,412 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2026"
title: JavaScript & Frameworks
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #d63384;
--color-dimmed: #4a4a6a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.4rem;
}
h1 {
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937;
}
section.invert h2 {
color: #f48fb1;
}
pre {
background: #0f0f23;
color: #f48fb1;
border-radius: 8px;
border-left: 3px solid #d63384;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a1a2e;
color: #f48fb1;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
![bg cover opacity:0.2](./assets/background.png)
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026** · Sitzung 3 — JS, Frameworks & Build Tools
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
# Ressourcen zum Selbstlernen
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
- **MDN** (Mozilla Developer Network) — [developer.mozilla.org/de/](https://developer.mozilla.org/de/)
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# JavaScript
---
# ECMAScript
- **Ecma International** — European Computer Manufacturers Association
- Seit **1997** standardisiert als **ECMA-262**
- Implementierungen: **JavaScript** (Netscape, später Mozilla), **JScript** (Microsoft), **ActionScript** (Adobe Flash) etc.
- Aktuelle Version: **ECMAScript 2024 (ES15)**, jährliche Releases
**Browser-Kompatibilität:**
- Faustregel: **ES2017+** läuft in allen modernen Browsern
- Ältere Targets via Transpiler (Babel, esbuild, swc, tsc)
- Kompatibilitätstabelle: [kangax.github.io/compat-table](https://kangax.github.io/compat-table/)
---
# JavaScript Grundlagen
```javascript
// Variablen
let name = "Welt";
const alter = 25;
// Funktionen
function gruss(name) {
return `Hallo, ${name}!`;
}
// Arrow Functions
const add = (a, b) => a + b;
// Arrays
const arr = [1, 2, 3];
arr.map(x => x * 2); // [2, 4, 6]
```
---
# DOM Manipulation
```javascript
// Element auswählen
const title = document.querySelector('h1');
// Inhalt ändern
title.textContent = 'Neue Überschrift';
// Event Listener
button.addEventListener('click', () => {
alert('Geklickt!');
});
```
---
# Fetch API
```javascript
fetch('/api/products')
.then(res => res.json())
.then(data => {
console.log(data);
})
.catch(err => console.error(err));
```
---
# Async/Await
```javascript
async function loadProducts() {
try {
const res = await fetch('/api/products');
const data = await res.json();
return data;
} catch (err) {
console.error('Fehler:', err);
}
}
```
---
<!-- _header: '' -->
<!-- _footer: '' -->
<!-- _backgroundColor: #050517 -->
![bg fit](./assets/demos/web-engineering-mandala.png)
---
<!-- _backgroundColor: #050517 -->
<!-- _color: #e2e8f0 -->
# Web Engineering Mandala
Interaktive version: [nextlevelshit.github.io/web-engineering-mandala](https://nextlevelshit.github.io/web-engineering-mandala/)
3 Schichten:
- **Core Layer** — JS, HTML, CSS (vanilla)
- **Build Layer** — bundlers, runtimes, template engines, pre/post processors
- **Application Layer** — frontend, backend, frameworks, SSR, CSS-utilities
3 Segmente: HTML (blau) · JavaScript (rot) · CSS (grün) · Mittelpunkt: `package.json`
---
# JavaScript Frameworks – Kategorien
| Kategorie | Beispiele |
|-----------|-----------|
| **CSS Frameworks** | Tailwind, Bootstrap, shadcn/ui |
| **Frontend Frameworks** | React, Vue, Svelte, Astro |
| **Rendering / Meta** | Next.js, Nuxt, Gatsby |
| **Build Tools / Bundler** | Webpack, Vite, Parcel, esbuild |
| **Backend Frameworks** | Express, Fastify, NestJS |
---
# Vanilla JS – Counter
```html
<button id="myButton">Clicked 0 times</button>
<script>
let count = 0;
const btn = document.getElementById('myButton');
btn.addEventListener('click', () => {
count++;
btn.textContent = `Clicked ${count} times`;
});
</script>
```
**Pro:** hohe Kompatibilität, simpel
**Contra:** State-Management und Re-Rendering werden schnell komplex
---
# React – Counter (JSX)
![bg right:25% fit](./assets/logos/frameworks/react.svg)
```jsx
import { useState } from "react";
function MyButton() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}
```
- **Component-Based** Architecture
- **Virtual DOM**, JSX, Hooks
- großes Ökosystem (React Router, Redux, …)
---
# Vue 3 – Composition API
![bg right:25% fit](./assets/logos/frameworks/vue.svg)
```vue
<script setup>
import { ref } from "vue";
const count = ref(0);
</script>
<template>
<button @click="count++">
Clicked {{ count }} times
</button>
</template>
```
- **Reactive Data Binding**
- Single-File Components (`.vue`)
- Vue Router, Pinia (State)
---
# Svelte – Counter
![bg right:25% fit](./assets/logos/frameworks/svelte.svg)
```svelte
<script>
let count = 0;
</script>
<button on:click={() => count += 1}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
```
- **Compiler-Based** – kein Runtime-Framework
- Reactive Assignments (`let`)
- Built-in Animationen
---
# Astro – Content-First
![bg right:25% fit](./assets/logos/frameworks/astro.svg)
```astro
---
const greeting = "Hallo DHBW";
---
<html>
<body>
<h1>{greeting}</h1>
<MyReactButton client:load />
</body>
</html>
```
- **Islands Architecture** – Komponenten mehrerer Frameworks mischen
- Default: kein JS im Output (nur statisches HTML)
- Hydration on demand (`client:load`, `client:visible`)
---
# Rendering Frameworks
| | Frontend | SSR | SSG | File Routing |
|---|---|---|---|---|
| **Next.js** | React | ja | ja | `/app/page.js` |
| **Nuxt** | Vue | ja | ja | `/pages/*.vue` |
| **Gatsby** | React | nein | ja | GraphQL Data |
---
# Build Tools – Webpack
![bg right:25% fit](./assets/logos/frameworks/webpack.svg)
- Module Bundling (JS, CSS, Images)
- Module Loaders + großes Plugin-Ökosystem
- Code Splitting, HMR
- Konfigurations-lastig (`webpack.config.js`)
→ Standard für viele Legacy-Setups.
---
# Build Tools – Vite
![bg right:25% fit](./assets/logos/frameworks/vite.svg)
```javascript
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
server: {
proxy: {
"/api": {
target: "http://localhost:4567",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, "")
}
}
}
});
```
- Rollup unter der Haube, **HMR mit ES Modules**
- Tree-Shaking, Code Splitting, React + Vue out-of-the-box
---
# Build Tools – Parcel
![bg right:25% fit](./assets/logos/frameworks/parcel.png)
```json
{
"name": "my-project",
"source": "src/index.html",
"browserslist": "> 0.5%, last 2 versions, not dead",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"devDependencies": {
"parcel": "latest"
}
}
```
- **Zero-Config**
- Auto-Resolution, HMR
- TS / CSS-Preprocessors out-of-the-box
---
# Microfrontends
- Mehrere unabhängige Frontend-Apps in einer Page
- Module Federation (Webpack 5)
- **single-spa**: https://single-spa.js.org/
- Anwendungsfall: große Teams, unterschiedliche Tech-Stacks pro Domain
→ Komplexitätskosten: nur bei echtem Skalierungsbedarf.
---
# Demo-Repos
- https://github.com/nextlevelshit/dhbw-client-js (Counter, multi-framework)
- https://github.com/nextlevelshit/node-cache-api (API + Tests)
- https://github.com/nextlevelshit/dhbw-docker (Compose-Stack)
@@ -62,6 +62,15 @@ a {
**Sommersemester 2026** · Sitzung 4 — Node.js: Scripting, Running and Building
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
# Ressourcen zum Selbstlernen
@@ -62,6 +62,15 @@ a {
**Sommersemester 2026** · Sitzung 5 — Express API, CRUD und Middlewares
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
# Ressourcen zum Selbstlernen
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 7 — Testing
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
# Ressourcen zum Selbstlernen
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 8 — TypeScript
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
<!-- _class: invert -->
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 9 — Docker, Proxies and DBs
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
<!-- _class: invert -->
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 10 — Wrap-up & Projektsupport
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
<!-- _class: invert -->
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+15
View File
@@ -0,0 +1,15 @@
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" width="433" height="97" viewBox="0 0 433 97">
<g>
<g id="logotype">
<path id="logotype-b-47" d="M185.2,46.88a13.77,13.77,0,0,0,8.8-13c0-11.7-8.3-17.5-19.7-17.5H144.4V80h32.5c10,0,19.8-7,19.8-17.7C196.7,49.58,185.2,47,185.2,46.88ZM160,29.58h11.6a5.66,5.66,0,0,1,6,5.31q0,.34,0,.69a5.93,5.93,0,0,1-6,5.81H159.9Zm11.7,37.1H160.1V54.18h11.3c5.7,0,8.4,2.5,8.4,6.2C179.8,65,176.4,66.68,171.7,66.68Z" style="fill: #ed0007;fill-rule: evenodd"/>
<path id="logotype-o-47" d="M231.1,14.78c-18.4,0-29.2,14.7-29.2,33.3s10.8,33.3,29.2,33.3,29.2-14.6,29.2-33.3S249.6,14.78,231.1,14.78Zm0,51.4c-9,0-13.5-8.1-13.5-18.1s4.5-18,13.5-18,13.6,8.1,13.6,18C244.7,58.18,240.1,66.18,231.1,66.18Z" style="fill: #ed0007;fill-rule: evenodd"/>
<path id="logotype-s-47" d="M294.2,41.38l-2.2-.5c-5.4-1.1-9.7-2.5-9.7-6.4,0-4.2,4.1-5.9,7.7-5.9a17.86,17.86,0,0,1,13,5.9l9.9-9.8c-4.5-5.1-11.8-10-23.2-10-13.4,0-23.6,7.5-23.6,20,0,11.4,8.2,17,18.2,19.1l2.2.5c8.3,1.7,11.4,3,11.4,7,0,3.8-3.4,6.3-8.6,6.3-6.2,0-11.8-2.7-16.1-8.2l-10.1,10c5.6,6.7,12.7,11.9,26.4,11.9,11.9,0,24.6-6.8,24.6-20.7C314.3,46.08,303.3,43.28,294.2,41.38Z" style="fill: #ed0007;fill-rule: evenodd"/>
<path id="logotype-c-47" d="M349.7,66.18c-7,0-14.3-5.8-14.3-18.5,0-11.3,6.8-17.6,13.9-17.6,5.6,0,8.9,2.6,11.5,7.1l12.8-8.5c-6.4-9.7-14-13.8-24.5-13.8-19.2,0-29.6,14.9-29.6,32.9,0,18.9,11.5,33.7,29.4,33.7,12.6,0,18.6-4.4,25.1-13.8L361.1,59C358.5,63.18,355.7,66.18,349.7,66.18Z" style="fill: #ed0007;fill-rule: evenodd"/>
<polygon id="logotype-h-47" points="416.3 16.38 416.3 39.78 397 39.78 397 16.38 380.3 16.38 380.3 79.98 397 79.98 397 54.88 416.3 54.88 416.3 79.98 433 79.98 433 16.38 416.3 16.38" style="fill: #ed0007;fill-rule: evenodd"/>
</g>
<g id="symbol">
<path d="M48.2.18a48.2,48.2,0,1,0,48.2,48.2A48.2,48.2,0,0,0,48.2.18Zm0,91.9a43.7,43.7,0,1,1,43.7-43.7,43.71,43.71,0,0,1-43.7,43.7Z"/>
<path d="M68.1,18.28H64.8v16.5H31.7V18.28H28.3a36.06,36.06,0,0,0,0,60.2h3.4V62H64.8v16.5h3.3a36.05,36.05,0,0,0,0-60.2ZM27.1,72A31.59,31.59,0,0,1,24.47,27.4a32.51,32.51,0,0,1,2.63-2.62Zm37.7-14.6H31.7V39.28H64.8Zm4.5,14.5v-10h0V34.78h0v-10a31.65,31.65,0,0,1,2.39,44.71A33.68,33.68,0,0,1,69.3,71.88Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

+1
View File
@@ -0,0 +1 @@
<svg width="189" height="45" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M-46-32h1440V68H-46z"/><g fill-rule="nonzero"><g fill="#0E1111"><path d="M133.298 34.907v-1.509L142.48 20.1h-8.71v-1.982h11.44v1.513l-9.183 13.296h9.494v1.981h-12.222M129.365 35.163c-2.235 0-2.145-.927-2.145-3.611V18.117h2.132V31.82l.013 3.343M120.61 34.907v-12.19c0-2.181-1.192-2.854-3.135-2.854-2.037 0-3.071.371-4.23 1.075v13.97h-2.194v-16.79h1.223l.471 1.41c1.472-1.175 3.07-1.746 4.73-1.746 3.728 0 5.327 1.812 5.327 5.039v12.086h-2.193M100.87 33.163c-2.038 0-3.168-.37-4.389-1.075v-11.15c1.221-.704 2.351-1.075 4.388-1.075 3.76 0 4.229 3.325 4.229 6.65s-.47 6.65-4.229 6.65zm0-15.381a7.795 7.795 0 00-4.389 1.376V9.723h-2.193v25.184h1.221l.47-1.377c1.63 1.109 3.196 1.714 4.89 1.714 5.045 0 6.422-3.896 6.422-8.731s-1.377-8.731-6.422-8.731zM89.417 35.24c-2.256 0-2.148-1.004-2.148-3.688V18.117h2.13V31.82l.018 3.42M72.667 25.674c.092-3.023.751-5.811 4.387-5.811 3.603 0 3.76 2.822 3.76 5.81h-8.147zm10.34.839c0-4.835-.627-8.731-5.953-8.731-5.297 0-6.581 3.896-6.581 8.73 0 4.836 1.284 8.732 6.581 8.732 1.534 0 3.413-.168 5.17-1.008v-2.013c-1.535.704-2.914.94-5.17.94-3.542 0-4.263-2.653-4.387-5.574h10.34v-1.076zM54.492 34.907V9.723h2.131v23.07h10.874v2.114H54.492M188.975 34.9V9.723h-2.12v11.011h-11.658V9.724h-2.119V34.9h2.12V22.848h11.657V34.9h2.12M158.053 11.837h11.128V9.723h-13.248V34.9h2.12V22.848h10.037v-2.114h-10.037v-8.897M87.261 15.025h2.142v-2.24h-2.142zM127.222 15.025h2.142v-2.24h-2.142z"/></g><path d="M.195 1.476l9.617-.42v43.75L.2 42.284C.2 23.158.197 8.006.195 1.476M39.777 43.49l-9.655.422V.162l9.65 2.953c0 19.392.002 34.192.005 40.375" fill="#0288d1"/><path fill="#74BEE6" d="M9.812 34.613v10.193l15.285-.67V33.888l-15.285.725M15.11.837v10.285l15.012-.724V.161L15.11.837"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

+78
View File
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" width="123.1184" height="38" id="svg2">
<defs id="defs4"/>
<g transform="translate(-4.113659e-8,-8.1875909)" id="g2881">
<g transform="matrix(0.8227318,0,0,0.8227318,0,8.1875911)" id="g3725">
<path d="m 5.9058686,3.5864545 c 0,1.6289778 -1.3205475,2.9495254 -2.9495254,2.9495254 -1.628978,0 -2.9495254,-1.3205476 -2.9495254,-2.9495254 0,-1.6289779 1.3205474,-2.94952547 2.9495254,-2.94952547 1.6289779,0 2.9495254,1.32054757 2.9495254,2.94952547 l 0,0 z" id="path2492" style="fill:#022d6f;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/>
<use transform="translate(123.33173,0.52756266)" id="use2494" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(12.995121,0.24968358)" id="use3266" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.0021669,6.4942292)" id="use3268" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.00100324,13.007016)" id="use3270" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(1.6068057e-4,19.515151)" id="use3272" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(5.6386012,22.744639)" id="use3274" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.00681775,26.008952)" id="use3276" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(12.102606,22.633932)" id="use3278" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(19.117759,2.4186714)" id="use3280" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(22.403372,8.0486075)" id="use3282" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(18.008113,19.840656)" id="use3284" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(21.756631,14.51843)" id="use3286" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.00100325,32.490405)" id="use3290" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(0.00132398,38.988066)" id="use3292" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(37.905739,3.6984537)" id="use3294" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(65.078186,33.204228)" id="use3296" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(33.398214,8.5473695)" id="use3298" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(30.724945,14.638897)" id="use3300" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(30.159334,21.213576)" id="use3302" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(31.812768,27.679762)" id="use3304" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(35.421974,33.202782)" id="use3306" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(40.652784,37.299478)" id="use3308" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(43.733988,0.5434759)" id="use3310" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(50.271054,-0.58340514)" id="use3312" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(56.815356,0.50441766)" id="use3314" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(46.959848,39.447642)" id="use3316" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(62.637816,3.6608425)" id="use3318" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(53.579391,39.44039)" id="use3320" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(67.139555,8.5531567)" id="use3322" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(69.779551,14.64179)" id="use3324" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(70.340823,21.210681)" id="use3326" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.933056,19.51385)" id="use3328" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(59.8575,37.257529)" id="use3330" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(68.722105,27.673974)" id="use3332" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(6.4702426,5.7452075e-4)" id="use3334" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.938844,13.014391)" id="use3336" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.933047,0.00245617)" id="use3338" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.934503,6.494682)" id="use3340" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(85.563127,3.2586948)" id="use3342" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(89.846429,8.1177379)" id="use3344" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(94.152881,13.004267)" id="use3346" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.938841,26.013309)" id="use3348" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(98.462222,17.886454)" id="use3350" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(102.76578,22.745497)" id="use3352" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.930164,32.496854)" id="use3354" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40887,26.016202)" id="use3356" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40597,0.00390394)" id="use3358" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40887,6.4888947)" id="use3360" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40742,13.012946)" id="use3362" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.41031,19.509501)" id="use3364" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.933058,38.984738)" id="use3366" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40308,32.498301)" id="use3368" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40308,38.98329)" id="use3370" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(118.86037,5.2694337)" id="use3372" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(118.33815,11.771784)" id="use3374" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(122.73574,16.555607)" id="use3376" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(129.72991,-0.63692924)" id="use3378" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(136.11652,0.46102075)" id="use3380" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(128.89236,18.606849)" id="use3382" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(135.21099,20.106946)" id="use3384" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(142.06329,3.0879996)" id="use3386" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(141.06815,22.998648)" id="use3388" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(118.41627,34.426578)" id="use3390" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(143.73998,28.915145)" id="use3392" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(123.96821,37.788408)" id="use3394" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(130.21596,39.651611)" id="use3396" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(136.68652,38.987622)" id="use3398" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(141.93608,35.149863)" id="use3400" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B