From 0317d26add58bcff114b4403e546e7637af43671 Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 21 Apr 2026 15:26:29 +0200 Subject: [PATCH] 06: Demos und Labor --- web/06/demos/helloworld/helloworld.go | 7 +++ web/06/demos/taskmanager/go.mod | 3 + web/06/demos/taskmanager/main.go | 82 +++++++++++++++++++++++++++ web/06/demos/taskmanager/task.go | 60 ++++++++++++++++++++ web/06/demos/taskmanager/tasks.json | 24 ++++++++ web/06/labor/06_aufgaben.md | 73 ++++++++++++++++++++++++ web/06/labor/workshop-anmeldung.html | 66 +++++++++++++++++++++ 7 files changed, 315 insertions(+) create mode 100644 web/06/demos/helloworld/helloworld.go create mode 100644 web/06/demos/taskmanager/go.mod create mode 100644 web/06/demos/taskmanager/main.go create mode 100644 web/06/demos/taskmanager/task.go create mode 100644 web/06/demos/taskmanager/tasks.json create mode 100644 web/06/labor/06_aufgaben.md create mode 100644 web/06/labor/workshop-anmeldung.html diff --git a/web/06/demos/helloworld/helloworld.go b/web/06/demos/helloworld/helloworld.go new file mode 100644 index 0000000..c048119 --- /dev/null +++ b/web/06/demos/helloworld/helloworld.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("hello world") +} diff --git a/web/06/demos/taskmanager/go.mod b/web/06/demos/taskmanager/go.mod new file mode 100644 index 0000000..f64ceb6 --- /dev/null +++ b/web/06/demos/taskmanager/go.mod @@ -0,0 +1,3 @@ +module example.com/taskmanager + +go 1.24.5 diff --git a/web/06/demos/taskmanager/main.go b/web/06/demos/taskmanager/main.go new file mode 100644 index 0000000..668daf3 --- /dev/null +++ b/web/06/demos/taskmanager/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // Frage: Was macht dieser Teil genau? + if len(os.Args) < 2 { + fmt.Println("Usage: add | list | done ") + return + } + + // Lädt alle Tasks aus JSON-Datei in eine Liste + // Gibt eine leere Liste zurück, falls die JSON-Datei noch nicht existiert + // Gibt Fehlermeldung vom Typ error zurück, falls etwas schief gelaufen ist + tasklist, err := LoadTasks("tasks.json") + + // TODO: Fehlerbehandlung + if err != nil { + fmt.Println("Fehler beim Laden der JSON-Datei: " + err.Error()) + } + + // Je nach Kommandozeilenargument wird: + // - Task neu erstellt und zur Liste hinzugefügt (auch in JSON-Datei) + // - Alle Tasks aus der Liste ausgegeben inkl. Status ("✓" für done, sonst " ") + // - Task als done markiert und Ergebnis ausgegeben + switch os.Args[1] { + case "add": + // TODO: Prüfen, ob 3. Kommandozeilenargument für Title vorliegt + if len(os.Args) < 3 { + fmt.Println("Geben Sie einen Titel ein.") + return + } + + // TODO: Task zur Liste hinzufügen + tasklist.Add(os.Args[2]) + + // TODO: Liste in JSON-Datei speichern + tasklist.Save("tasks.json") + + // Ergebnis ausgeben + fmt.Println("Task added.") + + case "list": + // TODO: Durch alle Tasks der Liste iterieren + for _, task := range tasklist.Tasks { + // TODO: Task-Status bestimmen und inklusive ID und Title ausgeben + status := " " + if task.Done { + status = "✓" + } + fmt.Printf("[%s] %d: %s\n", status, task.ID, task.Title) + + } + + case "done": + // TODO: Prüfen, ob 3. Kommandozeilenargument für ID vorliegen + if len(os.Args) < 3 { + fmt.Println("Geben Sie eine ID ein.") + return + } + + // TODO: Prüfen, ob ID vom Typ integer, sonst Fehlermeldung und Abbruch + // Tipp: strconv.Atoi(string) + id, err := strconv.Atoi(os.Args[2]) + if err != nil { + fmt.Println("Falsche Eingabe der ID") + return + } + // TODO: Task auf done setzen + tasklist.Complete(id) + + // TODO: Taskliste in JSON-Datei speichern + tasklist.Save("tasks.json") + + // Ergebnis ausgeben + fmt.Println("Task marked as done.") + } +} diff --git a/web/06/demos/taskmanager/task.go b/web/06/demos/taskmanager/task.go new file mode 100644 index 0000000..6816c96 --- /dev/null +++ b/web/06/demos/taskmanager/task.go @@ -0,0 +1,60 @@ +package main + +import ( + "encoding/json" + "os" +) + +// TODO: Task repräsentiert eine einzelne To-Do-Aufgabe mit ID, Titel und Status. +// Tipp: struct verwenden +type Task struct { + ID int `json:"id"` + Title string `json:"title"` + Done bool `json:"done"` +} + +// TODO: TaskList enthält eine Liste von Aufgaben (Tasks). +type TaskList struct { + Tasks []Task `json:"tasks"` +} + +// TODO: Fügt einen neuen Task mit übergebenen Titel in die Liste ein. +// Die neue ID entspricht der Anzahl der Elemente in der Liste. (ok, weil keine Tasks gelöscht werden) +func (tl *TaskList) Add(title string) { + id := len(tl.Tasks) + 1 + newTask := Task{ID: id, Title: title, Done: false} + tl.Tasks = append(tl.Tasks, newTask) +} + +// TODO: Setzt vorhandenen Task mit übergebener ID auf den Status done. +// Annahme: Wir wissen nicht, wie ID erstellt wird. +func (tl *TaskList) Complete(id int) { + for i := range tl.Tasks { + if tl.Tasks[i].ID == id { + tl.Tasks[i].Done = true + } + } +} + +// Liste wird im JSON-Format in einer Datei mit übergebenen Dateinamen gespeichert +func (tl *TaskList) Save(filename string) error { + data, err := json.MarshalIndent(tl, "", " ") + if err != nil { + return err + } + return os.WriteFile(filename, data, 0644) +} + +// TODO: Lädt eine Liste von Tasks aus einer JSON-Datei (Dateiname als Parameter übergeben) +// Falls die Datei noch nicht existiert, wird eine leere Liste (neu) zurückgegeben +// Tipp 1: Einlesen einer Datei: os.ReadFile(filename) +// Tipp 2: JSON-Daten in TaskList-Struktur umwandeln: json.Unmarshal(data, &tl) +func LoadTasks(filename string) (*TaskList, error) { + data, err := os.ReadFile(filename) + if err != nil { + return &TaskList{}, nil + } + var tl TaskList + jsonErr := json.Unmarshal(data, &tl) + return &tl, jsonErr +} diff --git a/web/06/demos/taskmanager/tasks.json b/web/06/demos/taskmanager/tasks.json new file mode 100644 index 0000000..dcbb27f --- /dev/null +++ b/web/06/demos/taskmanager/tasks.json @@ -0,0 +1,24 @@ +{ + "tasks": [ + { + "id": 1, + "title": "Vorlesung besuchen", + "done": true + }, + { + "id": 2, + "title": "Go by Example durcharbeiten", + "done": true + }, + { + "id": 3, + "title": "Webserver lokal installieren", + "done": false + }, + { + "id": 4, + "title": "Uebungen durcharbeiten", + "done": false + } + ] +} \ No newline at end of file diff --git a/web/06/labor/06_aufgaben.md b/web/06/labor/06_aufgaben.md new file mode 100644 index 0000000..c007bd7 --- /dev/null +++ b/web/06/labor/06_aufgaben.md @@ -0,0 +1,73 @@ +# Übungsblatt 06 + +## 1. SWAGGER-Übung: Workshop-API + +**Aufgabenstellung**: Erstellen Sie eine OpenAPI-Spezifikation für die Workshop-Anmeldung aus Übungsblatt 04 ([HTML-Formular](workshop-anmeldung.html)). + +#### Arbeitsschritte + +1. Setzen die OpenAPI-Version auf `3.0.0`. +2. Setzen Sie Meta-Daten wie Titel und API-Version im Info-Objekt. +3. Setzen Sie `https://web4-637691723779.europe-west1.run.app` als URL im Servers-Objekt. +4. Setzen Sie einen **Pfad** `/registrierung` für die HTTP-Methode `POST`. Definieren Sie eine Beschreibung, den Request-Body sowie mögliche Antworten des Servers. + 1. Request-Body für die Übergabe von **Formulardaten** + 2. Request-Body für die Übergabe von **JSON-Daten** + + _Tipp: Verwenden Sie das Components-Objekt._ + +5. Verwenden Sie Enums (https://swagger.io/docs/specification/v3_0/data-models/enums/) für die Spezifikation der Checkboxen und der Radiobuttons (s. Hinweis unten). + - Beispiel für `enum` in JSON-OpenAPI: + ```json + "farbe": { + "type": "string", + "enum": ["rot","gruen","blau"], + "example": "gruen" + }, + ``` +6. Testen Sie Ihre API-Spezifikation mit Swagger. + +#### Hinweis +Der serverseitige API-Endpunkt hat sich geändert (neue URL: `https://web4-637691723779.europe-west1.run.app`) und wurde nun folgendermaßen implementiert: + +1. Wenn die Checkbox aktiviert wurde, wird für **agb**, **newsletter** und **equipment** nur noch der Wert (`value`-Attribut) _ja_ akzeptiert. +2. Für **format** werden die Werte (`value`-Attribut) _online_ und _praesenz_ akzeptiert, je nach dem, welcher Radiobutton aktiviert wurde. +3. Die Eingabefelder zu Vorname, Nachname, AGB und Format sind nun Pflichtfelder. + +## 2. Go-Übung: Kommandozeilenprogramm + +**Aufgabenstellung**: Entwickeln Sie ein Kommandozeilenprogramm in Go, mit dem Nutzer:innen ihre persönliche Büchersammlung verwalten können. + +#### Arbeitsschritte + +Implementieren Sie ein Programm mit folgenden Funktionen: + +1. **Buch hinzufügen** + ```bash + go run main.go book.go add "Titel" "Autor" + ``` + → Fügt ein neues Buch zur Sammlung hinzu. + +2. **Bücher auflisten** + ```bash + go run main.go book.go list + ``` + → Zeigt alle Bücher mit ID, Titel, Autor und Lesestatus. + +3. **Buch als gelesen markieren** + ```bash + go run main.go book.go read + ``` + → Markiert das Buch mit der angegebenen ID als gelesen. + +4. **Persistenz** + - Die Bücher sollen in einer Datei `books.json` gespeichert und beim Programmstart wieder geladen werden. + - Verwenden Sie dafür das `encoding/json`-Paket und `os.ReadFile` / `os.WriteFile`. + +### Hinweise + +- Verwenden Sie `struct` für die Buch- und Bibliotheksdaten. +- Arbeiten Sie mit `slice` zur Verwaltung der Bücherliste. +- Nutzen Sie Methoden zur Kapselung von Logik (z. B. `Add`, `MarkRead`, `Save`). +- Behandeln Sie Fehler sinnvoll und benutzerfreundlich. +- Strukturieren Sie Ihr Projekt in mindestens zwei Dateien (`main.go`, `book.go`). + diff --git a/web/06/labor/workshop-anmeldung.html b/web/06/labor/workshop-anmeldung.html new file mode 100644 index 0000000..72403ff --- /dev/null +++ b/web/06/labor/workshop-anmeldung.html @@ -0,0 +1,66 @@ + + + + + + Workshop-Anmeldung + + + +
+
+ Persönliche Angaben: +
+
+ +
+
+ +
+
+ +
+

+
+ +
+ Kursauswahl: +
+

+ +
+
+
+ +
+ Zusätzliche Optionen: + +
+ + +
+ + +
+
+ +
+ Teilnahmeformat: + Format wählen:
+ +
+ + +
+
+
+ +
+ + + \ No newline at end of file