From 0ad7ca40e4dc21dd868619bb8966a5164d39eb15 Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 12 May 2026 08:50:25 +0200 Subject: [PATCH 1/5] 09: Demos mit SQL --- .../demos/db/sql/personen/create_personen.sql | 4 + .../demos/db/sql/personen/insert_personen.sql | 1 + .../demos/db/sql/personen/select_personen.sql | 1 + web/09/demos/hobbies/01_save_db.go | 86 +++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 web/09/demos/db/sql/personen/create_personen.sql create mode 100644 web/09/demos/db/sql/personen/insert_personen.sql create mode 100644 web/09/demos/db/sql/personen/select_personen.sql create mode 100644 web/09/demos/hobbies/01_save_db.go diff --git a/web/09/demos/db/sql/personen/create_personen.sql b/web/09/demos/db/sql/personen/create_personen.sql new file mode 100644 index 0000000..256f6b5 --- /dev/null +++ b/web/09/demos/db/sql/personen/create_personen.sql @@ -0,0 +1,4 @@ +CREATE TABLE personen ( + name TEXT NOT NULL, + hobbies TEXT +); \ No newline at end of file diff --git a/web/09/demos/db/sql/personen/insert_personen.sql b/web/09/demos/db/sql/personen/insert_personen.sql new file mode 100644 index 0000000..83293bf --- /dev/null +++ b/web/09/demos/db/sql/personen/insert_personen.sql @@ -0,0 +1 @@ +INSERT INTO personen (name, hobbies) VALUES ('Siri', 'Lesen, Wandern, Kochen'),('Alexa', 'Kochen, Gitarre spielen'); \ No newline at end of file diff --git a/web/09/demos/db/sql/personen/select_personen.sql b/web/09/demos/db/sql/personen/select_personen.sql new file mode 100644 index 0000000..6aa87aa --- /dev/null +++ b/web/09/demos/db/sql/personen/select_personen.sql @@ -0,0 +1 @@ +SELECT * FROM personen; \ No newline at end of file diff --git a/web/09/demos/hobbies/01_save_db.go b/web/09/demos/hobbies/01_save_db.go new file mode 100644 index 0000000..73fd09d --- /dev/null +++ b/web/09/demos/hobbies/01_save_db.go @@ -0,0 +1,86 @@ +package main + +import ( + "database/sql" + "fmt" + "log" + "net/http" + + _ "github.com/lib/pq" +) + +type formExampleDBHandler int + +func (formHandler formExampleDBHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + + //Datenbank-Verbindung herstellen + + // Verbindungszeichenfolge: Benutzername, Passwort, DB-Name, Host, Port + connStr := "user=devuser password=devpass dbname=devdb host=localhost port=5432 sslmode=disable" + + // Verbindung zur Datenbank öffnen + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Println("Fehler beim Öffnen der Verbindung:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + defer db.Close() + + // Verbindung testen + err = db.Ping() + if err != nil { + log.Println("Datenbank nicht erreichbar:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + log.Println("Verbindung erfolgreich hergestellt.") + + // INSERT-Anweisung vorbereiten + query := `INSERT INTO personen (name, hobbies) VALUES ($1, $2)` + // INSERT-Anweisung ausführen + _, err = db.Exec(query, "Louise", "Lesen, Wandern") + if err != nil { + log.Println("Fehler beim Einfügen:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + log.Println("Datensatz erfolgreich eingefügt.") + + // SELECT-Abfrage vorbereiten + rows, err := db.Query(`SELECT name, hobbies FROM personen`) + if err != nil { + log.Println("Fehler bei der Abfrage:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + defer rows.Close() + + // Ergebnisse durchlaufen + for rows.Next() { + var name string + var hobbies string + + err := rows.Scan(&name, &hobbies) + if err != nil { + log.Println("Fehler beim Auslesen:", err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + + fmt.Printf("Name: %s, Hobbies: %s\n", name, hobbies) + } + + // Fehler beim Iterieren prüfen + if err = rows.Err(); err != nil { + log.Println(err) + http.Error(w, "Interner Server-Fehler.", http.StatusInternalServerError) + return + } + +} + +func main() { + var r formExampleDBHandler + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} From 5cbe3c0553d15ff0277716b16c871a66b1a070ef Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 12 May 2026 15:18:24 +0200 Subject: [PATCH 2/5] 09: Labor --- web/09/labor/db/09_aufgaben.md | 41 +++++++++ web/09/labor/db/anleitung_db.md | 23 +++++ web/09/labor/db/create_personen.sql | 5 ++ web/09/labor/db/hobbiesapi.json | 129 ++++++++++++++++++++++++++++ web/09/labor/db/insert_personen.sql | 1 + web/09/labor/db/select_personen.sql | 1 + web/09/labor/db/workshop-api.json | 119 +++++++++++++++++++++++++ 7 files changed, 319 insertions(+) create mode 100644 web/09/labor/db/09_aufgaben.md create mode 100644 web/09/labor/db/anleitung_db.md create mode 100644 web/09/labor/db/create_personen.sql create mode 100644 web/09/labor/db/hobbiesapi.json create mode 100644 web/09/labor/db/insert_personen.sql create mode 100644 web/09/labor/db/select_personen.sql create mode 100644 web/09/labor/db/workshop-api.json diff --git a/web/09/labor/db/09_aufgaben.md b/web/09/labor/db/09_aufgaben.md new file mode 100644 index 0000000..2e01283 --- /dev/null +++ b/web/09/labor/db/09_aufgaben.md @@ -0,0 +1,41 @@ +# Übungsblatt 09 + +## 1. Go-Übung: Datenbank INSERT + +**Aufgabenstellung**: Erstellen Sie ein Webserver-Programm in Go, dass beim Aufruf eines Endpunkts `/insert` einen neuen Datensatz in der Datenbank speichert. + +## 2. Go-Übung: Datenbank UPDATE + +**Aufgabenstellung**: Erweitern Sie das Programm aus Aufgabe 1 um einen neuen Endpunkt `/update`, der einen vorhandenen Datensatz in der Datenbank aktualisiert. + +### Hinweise zu Aufgaben 1 und 2 +1. Erstellen Sie zunächst die benötigten Tabellen und Datensätze in Ihrer Datenbank. Eine Anleitung hierfür finden Sie hier: [Datenbank vorbereiten](db/anleitung_db.md) +2. Verwenden Sie folgende Schnittstellen-Definition für Ihre Implementierung: [Swagger-API](hobbiesapi.json) +3. Tipp: Um die Elemente eines Slice in einem String zusammenzufügen, können Sie das Paket `strings` aus der Standard-Bibliothek verwenden: [strings.Join](https://pkg.go.dev/strings#Join) + +## 3. HTML-Übung: Formular + +**Aufgabenstellung**: Schreiben Sie ein HTML-Formular, dass die Schnittstelle [Swagger-API](hobbiesapi.json) implementiert und Benutzereingaben an das in Aufgabe 1 + 2 implementierte Backend sendet. + +## 4. Go-Übung: CORS + +_Keine Abgabe erforderlich_ + +**Aufgabenstellung**: Erweitern Sie die beiden serverseitigen Go-Programme zur Workshop-Anmeldung aus den vorangegangen Übungsblättern 07 und 08 so, dass beim Ausführen der "Try Out"-Funktion in der SwaggerUI-Preview kein CORS-Fehler mehr auftaucht. + +#### Arbeitsschritte + +1. Fügen Sie folgende Zeile am Anfang in Ihrer Handler `func` oder in der `ServeHTTP`-Funktion ihres `http.Handler` auf: + + ```go + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + + if r.Method == "OPTIONS" { + w.WriteHeader(http.StatusNoContent) + return + } + ``` + +2. Testen Sie Ihr(e) Programm(e) mit dieser [Workshop-API](workshop-api.json). \ No newline at end of file diff --git a/web/09/labor/db/anleitung_db.md b/web/09/labor/db/anleitung_db.md new file mode 100644 index 0000000..04f1759 --- /dev/null +++ b/web/09/labor/db/anleitung_db.md @@ -0,0 +1,23 @@ +# Tooling für die Entwicklung mit einer PostGreSQL-DB + +Diese Anleitung beschreibt die Schritte zur Verbindung mit einer PostGreSQL-DB sowie das Erstellen von Tabellen mit Hilfe der VS Code Extension _PostgreSQL_ und der im Dev-Container enthaltenen Datenbank. + +## Neue Verbindung + +1. Prüfen Sie, ob Sie sich im Dev-Container befinden +2. Klicken Sie auf das PostGreSQL-Symbol (VS Code Extension) in der Activity Bar (default: linke Leiste) +3. Wählen Sie "Add New Connection" und "CONNECTIONS" in der Primary Side Bar (meistens: links) + 1. Füllen Sie die geforderten Felder aus. Sie finden die Daten zu Ihrer Datenbank-Installation in der Datei `.env` innerhalb des `.devcontainer`- Ordners. + 2. Testen Sie die Verbindung ("Test Connection") + 3. Vergeben Sie einen geeigneten Namen und speichern Sie die Verbindung ("Save & Connect") + +## Tabellen +4. Öffnen Sie die Datei `create_personen.sql`. +5. Auf der rechten Seite der Tab-Leiste erscheinen nun mehrere Symbole. Wählen Sie "Connect" aus und geben Sie ggf. Ihr Datenbank-Passwort ein (`POSTGRES_PASSWORD` in `.env`) +6. Wählen Sie nun das Symbol für "Change PostGreSQL Database" aus und wählen Ihre Datenbank aus (`POSTGRES_DB` in `.env`) +7. Wählen Sie nun das Symbol für "Execute PostGreSQL Query" aus: Es wird eine neue Tabelle in Ihrer Datenbank erstellt. + +## Einfügen und Anzeigen +8. Führen Sie die Schritte 5.-7. nun auch für die Dateien `insert_personen.sql` und `select_personen.sql` durch. +9. Alternativ oder zusätzlich können Sie natürlich auch eigene Queries ausführen. + diff --git a/web/09/labor/db/create_personen.sql b/web/09/labor/db/create_personen.sql new file mode 100644 index 0000000..27ac3bb --- /dev/null +++ b/web/09/labor/db/create_personen.sql @@ -0,0 +1,5 @@ +CREATE TABLE personen ( + name TEXT NOT NULL, + hobbies TEXT, + alter SMALLINT +); \ No newline at end of file diff --git a/web/09/labor/db/hobbiesapi.json b/web/09/labor/db/hobbiesapi.json new file mode 100644 index 0000000..46b295c --- /dev/null +++ b/web/09/labor/db/hobbiesapi.json @@ -0,0 +1,129 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Hobbies API", + "version": "1.0.0" + }, + "servers": [ + { + "url": "http://localhost:8080" + } + ], + "paths": { + "/insert": { + "post": { + "summary": "Erstellt eine:n neue:n Benutzer:in mit einer Liste von Hobbies", + "requestBody": { + "description": "Name und Hobbies des neuen Benutzers/der neuen Benutzerin", + "required": true, + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Hobbies" + } + } + } + }, + "responses": { + "200": { + "$ref": "#/components/responses/SuccessResponse" + }, + "400": { + "$ref": "#/components/responses/BadRequestResponse" + }, + "405": { + "$ref": "#/components/responses/MethodNotAllowedResponse" + } + } + } + }, + "/update": { + "post": { + "summary": "Aktualisiert eine:n vorhandene:n Benutzer:in mit einer Liste von Hobbies", + "requestBody": { + "description": "Name und Hobbies des/der vorhandenen Benutzer:in", + "required": true, + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Hobbies" + } + } + } + }, + "responses": { + "200": { + "$ref": "#/components/responses/SuccessResponse" + }, + "400": { + "$ref": "#/components/responses/BadRequestResponse" + }, + "405": { + "$ref": "#/components/responses/MethodNotAllowedResponse" + } + } + } + } + }, + "components": { + "schemas": { + "Hobbies": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "Lea" + }, + "hobby": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "reiten", + "backen" + ] + }, + "alter": { + "type": "integer", + "example": 23 + } + } + } + }, + "responses": { + "SuccessResponse": { + "description": "Success", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + }, + "BadRequestResponse": { + "description": "Bad Request", + "content": { + "text/html": { + "schema": { + "type": "string", + "example": "Kein POST-Formular gesendet" + } + } + } + }, + "MethodNotAllowedResponse": { + "description": "Method not allowed", + "content": { + "text/html": { + "schema": { + "type": "string", + "example": "Nur POST-Methode erlaubt." + } + } + } + } + } + } +} \ No newline at end of file diff --git a/web/09/labor/db/insert_personen.sql b/web/09/labor/db/insert_personen.sql new file mode 100644 index 0000000..987a7a6 --- /dev/null +++ b/web/09/labor/db/insert_personen.sql @@ -0,0 +1 @@ +INSERT INTO personen (name, hobbies, alter) VALUES ('Siri', 'Lesen, Wandern, Kochen', 14),('Alexa', 'Kochen, Gitarre spielen', 11); \ No newline at end of file diff --git a/web/09/labor/db/select_personen.sql b/web/09/labor/db/select_personen.sql new file mode 100644 index 0000000..6aa87aa --- /dev/null +++ b/web/09/labor/db/select_personen.sql @@ -0,0 +1 @@ +SELECT * FROM personen; \ No newline at end of file diff --git a/web/09/labor/db/workshop-api.json b/web/09/labor/db/workshop-api.json new file mode 100644 index 0000000..60c76d7 --- /dev/null +++ b/web/09/labor/db/workshop-api.json @@ -0,0 +1,119 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Workshop API", + "version": "1.0.0" + }, + "servers": [ + { + "url": "http://localhost:8080" + } + ], + "paths": { + "/registrierung": { + "post": { + "summary": "Sends all information needed for registering at a workshop", + "requestBody": { + "required": false, + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/RegistrierungForm" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegistrierungForm" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "text/plain": { + "schema": { + "type": "string", + "example": "Kein Formular gesendet" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "RegistrierungForm": { + "type": "object", + "required": [ + "vorname", + "nachname", + "agb", + "format" + ], + "properties": { + "vorname": { + "type": "string", + "example": "Zoya" + }, + "nachname": { + "type": "string", + "example": "Akhtar" + }, + "email": { + "type": "string", + "example": "z.akhtar@test.de" + }, + "telefon": { + "type": "string", + "example": "Zoya" + }, + "sessions": { + "type": "array", + "items": { + "type": "string", + "example": "vormittag" + }, + "example": [ + "vormittag", + "nachmittag" + ] + }, + "agb": { + "type": "string", + "enum": ["ja"], + "example": "ja" + }, + "newsletter": { + "type": "string", + "enum": ["ja"], + "example": "ja" + }, + "equipment": { + "type": "string", + "enum": ["ja"], + "example": "ja" + }, + "format": { + "type": "string", + "enum": ["online","praesenz"], + "example": "online" + } + } + } + } + } +} \ No newline at end of file From 87ff1d8cf70db0bc2efab91119e01b9119fba3cb Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 19 May 2026 09:40:24 +0200 Subject: [PATCH 3/5] =?UTF-8?q?08:=20L=C3=B6sungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/08/labor/08_loesungen/02/go.mod | 5 ++ web/08/labor/08_loesungen/02/go.sum | 2 + web/08/labor/08_loesungen/02/uebung02.go | 46 +++++++++++++++ web/08/labor/08_loesungen/03/go.mod | 5 ++ web/08/labor/08_loesungen/03/go.sum | 2 + web/08/labor/08_loesungen/03/uebung03.go | 75 ++++++++++++++++++++++++ web/08/labor/08_loesungen/uebung01.go | 20 +++++++ 7 files changed, 155 insertions(+) create mode 100644 web/08/labor/08_loesungen/02/go.mod create mode 100644 web/08/labor/08_loesungen/02/go.sum create mode 100644 web/08/labor/08_loesungen/02/uebung02.go create mode 100644 web/08/labor/08_loesungen/03/go.mod create mode 100644 web/08/labor/08_loesungen/03/go.sum create mode 100644 web/08/labor/08_loesungen/03/uebung03.go create mode 100644 web/08/labor/08_loesungen/uebung01.go diff --git a/web/08/labor/08_loesungen/02/go.mod b/web/08/labor/08_loesungen/02/go.mod new file mode 100644 index 0000000..bdf4f1f --- /dev/null +++ b/web/08/labor/08_loesungen/02/go.mod @@ -0,0 +1,5 @@ +module uebung03/cookies + +go 1.24.5 + +require github.com/google/uuid v1.6.0 diff --git a/web/08/labor/08_loesungen/02/go.sum b/web/08/labor/08_loesungen/02/go.sum new file mode 100644 index 0000000..7790d7c --- /dev/null +++ b/web/08/labor/08_loesungen/02/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/web/08/labor/08_loesungen/02/uebung02.go b/web/08/labor/08_loesungen/02/uebung02.go new file mode 100644 index 0000000..9589ce1 --- /dev/null +++ b/web/08/labor/08_loesungen/02/uebung02.go @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" + "log" + "net/http" + + "github.com/google/uuid" +) + +func createCookie(w http.ResponseWriter, r *http.Request) { + uuid := uuid.New().String() + cookie := &http.Cookie{ + Name: "keks", + Value: uuid, + } + http.SetCookie(w, cookie) + fmt.Fprintf(w, "Cookie gesetzt: keks = %s\n", uuid) +} + +func showCookie(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie("keks") + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + fmt.Fprintf(w, "Cookie gefunden: keks = %s\n", cookie.Value) +} + +func deleteCookie(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie("keks") + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + cookie.MaxAge = -1 + http.SetCookie(w, cookie) + fmt.Fprintf(w, "Cookie gelöscht.\n") +} + +func main() { + http.HandleFunc("/create-cookie", createCookie) + http.HandleFunc("/show-cookie", showCookie) + http.HandleFunc("/delete-cookie", deleteCookie) + log.Fatal(http.ListenAndServe("localhost:8080", nil)) +} diff --git a/web/08/labor/08_loesungen/03/go.mod b/web/08/labor/08_loesungen/03/go.mod new file mode 100644 index 0000000..4e61f87 --- /dev/null +++ b/web/08/labor/08_loesungen/03/go.mod @@ -0,0 +1,5 @@ +module uebung04/sessions + +go 1.24.5 + +require github.com/google/uuid v1.6.0 diff --git a/web/08/labor/08_loesungen/03/go.sum b/web/08/labor/08_loesungen/03/go.sum new file mode 100644 index 0000000..7790d7c --- /dev/null +++ b/web/08/labor/08_loesungen/03/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/web/08/labor/08_loesungen/03/uebung03.go b/web/08/labor/08_loesungen/03/uebung03.go new file mode 100644 index 0000000..46cc4fb --- /dev/null +++ b/web/08/labor/08_loesungen/03/uebung03.go @@ -0,0 +1,75 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + "sync" + + "github.com/google/uuid" +) + +type UserData struct { + Username string `json:"username"` + Nickname string `json:"nickname"` + Admin bool `json:"admin"` +} + +var ( + sessions = make(map[string]UserData) + mu sync.Mutex +) + +func checkSessionID(r *http.Request) (string, error) { + cookie, err := r.Cookie("session_id") + if err != nil { + return "", errors.New("keine session-ID") + } + return cookie.Value, nil +} + +func signup(w http.ResponseWriter, r *http.Request) { + var user UserData + err := json.NewDecoder(r.Body).Decode(&user) + if err != nil || user.Nickname == "" || user.Username == "" { + http.Error(w, "Daten konnten nicht verarbeitet werden.", http.StatusBadRequest) + return + } + + newID := uuid.New().String() + newCookie := http.Cookie{ + Name: "session_id", + Value: newID, + } + http.SetCookie(w, &newCookie) + + mu.Lock() + sessions[newID] = user + mu.Unlock() +} + +func whoami(w http.ResponseWriter, r *http.Request) { + sessionID, err := checkSessionID(r) + if err != nil { + fmt.Fprintf(w, "Du bist noch niemand.") + } else { + mu.Lock() + user, ok := sessions[sessionID] + mu.Unlock() + if ok { + fmt.Fprintf(w, "Hallo %s!\n", user.Nickname) + if user.Admin { + fmt.Fprintln(w, "Du bist als Admin registriert.") + } else { + fmt.Fprintln(w, "Du bist nicht als Admin registriert.") + } + } + } +} + +func main() { + http.HandleFunc("/signup", signup) + http.HandleFunc("/whoami", whoami) + http.ListenAndServe("localhost:8080", nil) +} \ No newline at end of file diff --git a/web/08/labor/08_loesungen/uebung01.go b/web/08/labor/08_loesungen/uebung01.go new file mode 100644 index 0000000..6d9fb90 --- /dev/null +++ b/web/08/labor/08_loesungen/uebung01.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + "net/http" +) + +func loginFunc(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "Sie wurden erfolgreich eingeloggt.") +} + +func logoutFunc(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "Sie wurden erfolgreich ausgeloggt") +} + +func main() { + http.HandleFunc("/login", loginFunc) + http.HandleFunc("/logout", logoutFunc) + http.ListenAndServe("localhost:8080", nil) +} From 5bdaf3b26fb50e3f6e42dd2f71a0965f5b78bfd7 Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 19 May 2026 11:22:24 +0200 Subject: [PATCH 4/5] 09: Korrektur Ordnerstruktur --- web/09/labor/{db => }/09_aufgaben.md | 0 web/09/labor/{db => }/hobbiesapi.json | 0 web/09/labor/{db => }/workshop-api.json | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename web/09/labor/{db => }/09_aufgaben.md (100%) rename web/09/labor/{db => }/hobbiesapi.json (100%) rename web/09/labor/{db => }/workshop-api.json (100%) diff --git a/web/09/labor/db/09_aufgaben.md b/web/09/labor/09_aufgaben.md similarity index 100% rename from web/09/labor/db/09_aufgaben.md rename to web/09/labor/09_aufgaben.md diff --git a/web/09/labor/db/hobbiesapi.json b/web/09/labor/hobbiesapi.json similarity index 100% rename from web/09/labor/db/hobbiesapi.json rename to web/09/labor/hobbiesapi.json diff --git a/web/09/labor/db/workshop-api.json b/web/09/labor/workshop-api.json similarity index 100% rename from web/09/labor/db/workshop-api.json rename to web/09/labor/workshop-api.json From 7cc840a932c092b15d8bfcec91eb75eeed4dc645 Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 19 May 2026 15:43:58 +0200 Subject: [PATCH 5/5] 10: Demos und Labor --- web/10/demos/01_hello.html | 15 +++++ web/10/demos/02_hello.html | 18 ++++++ web/10/demos/02_hello.js | 1 + web/10/demos/03_basics.js | 105 +++++++++++++++++++++++++++++++++++ web/10/demos/04_functions.js | 53 ++++++++++++++++++ web/10/demos/05_dom.html | 48 ++++++++++++++++ web/10/labor/10_aufgaben.md | 43 ++++++++++++++ 7 files changed, 283 insertions(+) create mode 100644 web/10/demos/01_hello.html create mode 100644 web/10/demos/02_hello.html create mode 100644 web/10/demos/02_hello.js create mode 100644 web/10/demos/03_basics.js create mode 100644 web/10/demos/04_functions.js create mode 100644 web/10/demos/05_dom.html create mode 100644 web/10/labor/10_aufgaben.md diff --git a/web/10/demos/01_hello.html b/web/10/demos/01_hello.html new file mode 100644 index 0000000..6db8560 --- /dev/null +++ b/web/10/demos/01_hello.html @@ -0,0 +1,15 @@ + + + + + + + + Hello Studierende + + + +

Grüße an alle Studierenden

+ + + \ No newline at end of file diff --git a/web/10/demos/02_hello.html b/web/10/demos/02_hello.html new file mode 100644 index 0000000..b2de9af --- /dev/null +++ b/web/10/demos/02_hello.html @@ -0,0 +1,18 @@ + + + + + + + Hello World + + + +

Grüße an alle

+

TH Mannheim

+ +

Welt

+ + + + \ No newline at end of file diff --git a/web/10/demos/02_hello.js b/web/10/demos/02_hello.js new file mode 100644 index 0000000..4fde3b0 --- /dev/null +++ b/web/10/demos/02_hello.js @@ -0,0 +1 @@ +alert("Hallo Studierende!"); \ No newline at end of file diff --git a/web/10/demos/03_basics.js b/web/10/demos/03_basics.js new file mode 100644 index 0000000..c324e65 --- /dev/null +++ b/web/10/demos/03_basics.js @@ -0,0 +1,105 @@ +// DATENTYPEN +let zahl = 42; +let text = "Hallo Welt"; +let wahr = true; +let undefiniert; +let leer = null; +let symbol = Symbol("id"); // erzeugt einzigartigen Wert +let gross = 123n; // bigint: für sehr große Ganzzahlen + +// UNTERSCHIED ZWISCHEN null UND undefined +console.log(typeof undefiniert); // "undefined" +console.log(typeof leer); // "object" +console.log(undefiniert == null); // true → lose Gleichheit, beide gelten als "leer" +console.log(undefiniert === null); // false → strikte Gleichheit, Typen sind verschieden + +// OBJEKTE MIT METHODEN + +// Beispiel: const mit Objekt +const person = { name: "Moritz" }; +person.name = "Max"; +// person = {} //nicht erlaubt, weil const + +// Beispiel: Objekt mit Methode +let benutzer = { + name: "Galinda", + alter: 25, + begruessen: function() { + console.log("Hallo, ich bin " + this.name); + } +}; +benutzer.begruessen(); // Methode aufrufen +console.log(benutzer["alter"]); // Zugriff via Schlüssel + +// KONTROLLFLUSS +if (zahl > 40) { + console.log("Zahl ist größer als 40"); +} else if (zahl === 40) { + console.log("Zahl ist genau 40"); +} else { + console.log("Zahl ist kleiner als 40"); +} + +switch (text) { + case "Hallo Welt": + console.log("Begrüßung erkannt"); + break; + case "Hi": + console.log("Kurzform erkannt"); + break; + default: + console.log("Unbekannter Text"); +} + +switch (42) { + case "42": // kein Match, da Typ unterschiedlich -> Vergleich basiert auf strikter Gleichheit (===) + console.log("String"); + break; + case 42: + console.log("Number"); + break; +} + +for (let i = 0; i < 3; i++) { + console.log("Zähler:", i); +} + +// ARRAYS +let obst = ["Apfel", "Banane", "Kirsche"]; +obst.push("Mango"); +console.log(obst[1]); +obst.forEach(function(f) { + console.log("Frucht:", f); +}); +const zahlen = [1, 2, 3]; +// map erzeugt ein neues Array +const verdoppelt = zahlen.map(n => n * 2); +console.log(verdoppelt); // [2, 4, 6] + +// SPREAD-OPERATOR +const extendedZahlen = [...zahlen, 4]; +console.log(extendedZahlen); + +const extendedBenutzer = {...benutzer, beiname: "die Gute"} +console.log(extendedBenutzer["name"] + " " + extendedBenutzer["beiname"]) + +// ERROR HANDLING +// try-catch-finally funktioniert ähnlich wie in Java +try { + // Fehler absichtlich auslösen + throw new Error("Etwas ist schiefgelaufen"); +} catch (e) { + console.error("Fehler:", e.message); // Fehlerbehandlung +} finally { + console.log("Cleanup abgeschlossen"); // wird immer ausgeführt +} + +// JSON +// Objekt → JSON-String +const obj = { name: "Margaret", alter: 13 }; +const jsonStr = JSON.stringify(obj); +console.log(jsonStr); + +// JSON-String → Objekt +const parsed = JSON.parse(jsonStr); +console.log(parsed.alter); \ No newline at end of file diff --git a/web/10/demos/04_functions.js b/web/10/demos/04_functions.js new file mode 100644 index 0000000..afed174 --- /dev/null +++ b/web/10/demos/04_functions.js @@ -0,0 +1,53 @@ +// Normale Funktionsdeklaration +function add(a, b) { + return a + b; +} +console.log("Normale Funktion:", add(2, 3)); + + +// Anonyme Funktion +const multiply = function(x, y) { + return x * y; +}; +console.log("Anonyme Funktion:", multiply(4, 5)); + + +// Arrow Function +const subtract = (a, b) => a - b; +console.log("Arrow Function:", subtract(10, 3)); + +const square = x => x * x; +console.log("Quadrat:", square(6)); + +const greet = (name) => { + return "Hallo " + name; +}; +console.log(greet("Hans")); + + +// Funktionen als Parameter (Callbacks) +function doMath(a, b, operation) { + return operation(a, b); +} + +// Übergabe einer anonymen Funktion +console.log("Callback anonym:", doMath(3, 4, function(x, y) { + return x + y; +})); + +// Übergabe einer Arrow Function +console.log("Callback arrow:", doMath(3, 4, (x, y) => x * y)); + + +// Higher-Order Functions mit Arrays (map) +let zahlen = [1, 2, 3, 4, 5]; + +// Mit anonymer Funktion +let verdoppelt = zahlen.map(function(n) { + return n * 2; +}); +console.log("Verdoppelt (anonym):", verdoppelt); + +// Mit Arrow Function +let verdoppeltArrow = zahlen.map(n => n * 2); +console.log("Verdoppelt (arrow):", verdoppeltArrow); \ No newline at end of file diff --git a/web/10/demos/05_dom.html b/web/10/demos/05_dom.html new file mode 100644 index 0000000..30e394c --- /dev/null +++ b/web/10/demos/05_dom.html @@ -0,0 +1,48 @@ + + + + + + Node-Typen und Manipulation + + + +

Hallo Welt!

+

...

+
    +
  • Eintrag 1
  • +
+ + + + + \ No newline at end of file diff --git a/web/10/labor/10_aufgaben.md b/web/10/labor/10_aufgaben.md new file mode 100644 index 0000000..5751db6 --- /dev/null +++ b/web/10/labor/10_aufgaben.md @@ -0,0 +1,43 @@ +# Übungsblatt 10 + +## 1. Javascript-Übung: Grundlagen + +**Aufgabenstellung**: Machen Sie sich zunächst mit den Grundlagen der Programmiersprache vertraut und schreiben Sie dann ein Programm, das über ein vorgegebenes Array von Zahlen iteriert und für jede Zahl ausgibt: + - "Null" wenn die Zahl 0 ist + - "Gerade Zahl" wenn die Zahl gerade ist + - "Ungerade Zahl" wenn die Zahl ungerade ist + +*Ausgangsdaten*: +```js +const zahlen = [38, 0, 226, 384, 111, 500383]; +``` + +#### Arbeitsschritte +1. Arbeiten Sie mindestens die folgenden Kapitel auf [Javascript Tutorial](https://www.w3schools.com/js/default.asp) durch: + - JS Syntax + - JS Variables + - JS If Conditions + - JS Loops +2. Verwenden Sie zur Lösung der Aufgabe eine **for‑Schleife** und den **ternären Operator**. +3. _Tipp_: `zahlen.length` liefert die aktuelle Länge des Arrays. + +## 2. Javascript-Übung: Arrow-Function + +**Aufgabenstellung**: Die Produktdaten eines kleinen Online-Supermarkts liegen als Array von Objekten vor, jedes Objekt enthält den Namen und den Preis eines Produkts. Schreiben Sie eine kleine Javascript-Funktion, die ein neues Array erstellt, in dem alle Preise um 10 % reduziert sind. Die Preise sollen dabei auf zwei Nachkommastellen gerundet werden. + +*Ausgangsdaten*: + +```json +[ + { "produkt": "Joghurt", "preis": 2.49 }, + { "produkt": "Brot", "preis": 3.29 }, + { "produkt": "Käse", "preis": 8.99 }, + { "produkt": "Duschgel","preis": 2.79 } +] +``` + +#### Arbeitsschritte +1. Verwenden Sie `map`, um ein neues Array zu erzeugen. +2. Nutzen Sie eine Arrow-Function, um den Rabatt zu berechnen. +3. Mit `.toFixed(2)` können Sie die Preise auf zwei Nachkommastellen formatieren. +4. Geben Sie das neue Array in der Konsole aus. \ No newline at end of file