feat: Demo-Examples (Python/Rust/Go/C) mit Protokoll-Templates und Restore-Skript
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fb4e96919a
commit
64c2b7f0fd
21 changed files with 614 additions and 0 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -1,3 +1,10 @@
|
||||||
*.bak
|
*.bak
|
||||||
node_modules/
|
node_modules/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Build-Artefakte (Examples)
|
||||||
|
examples/rust-wordcount/target/
|
||||||
|
examples/**/__pycache__/
|
||||||
|
examples/**/.pytest_cache/
|
||||||
|
examples/**/Cargo.lock
|
||||||
|
examples/**/ll_demo
|
||||||
|
|
|
||||||
74
examples/README.md
Normal file
74
examples/README.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# pi-coder Beispielprojekte
|
||||||
|
|
||||||
|
Vier kleine, eigenständige Projekte als Demonstrationsgrundlage für die pi-coder-Features.
|
||||||
|
Jedes Projekt startet bewusst unvollständig — genau der Ausgangspunkt, für den pi-coder gebaut ist.
|
||||||
|
|
||||||
|
## Übersicht
|
||||||
|
|
||||||
|
| Verzeichnis | Sprache | Demonstriert |
|
||||||
|
|---|---|---|
|
||||||
|
| `python-calculator/` | Python | `/optimize` mit `--test-cmd pytest` |
|
||||||
|
| `rust-wordcount/` | Rust | `/optimize` mit `--test-cmd "cargo test"` + `/version` |
|
||||||
|
| `go-fibonacci/` | Go | `/optimize --interactive` + `/continue` + `/shipit` |
|
||||||
|
| `c-linkedlist/` | C | `/quick_check` + `/fix` + `/patch` |
|
||||||
|
|
||||||
|
## Demo-Workflow
|
||||||
|
|
||||||
|
### Schritt 1 — Vorbereitung: Sub-Repos anlegen
|
||||||
|
|
||||||
|
Jedes Example braucht ein eigenes git-Repo, damit pi-coder commit-basierte
|
||||||
|
Features nutzen kann (Loop-Erkennung, Diff-Anzeige, `/version`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
for dir in python-calculator rust-wordcount go-fibonacci c-linkedlist; do
|
||||||
|
cd examples/$dir
|
||||||
|
git init && git add -A && git commit -m "feat: initial $dir"
|
||||||
|
cd ../..
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
Für `/version` im rust-wordcount-Beispiel zusätzlich:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd examples/rust-wordcount && git tag v0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 2 — Demo ausführen
|
||||||
|
|
||||||
|
In pi das jeweilige Unterverzeichnis als Arbeitsverzeichnis öffnen.
|
||||||
|
Die genauen Befehle stehen im README.md des jeweiligen Examples.
|
||||||
|
Zeitmessung: Systemuhr notieren oder Terminal-Kommando `time` nutzen.
|
||||||
|
|
||||||
|
### Schritt 3 — Protokoll ausfüllen
|
||||||
|
|
||||||
|
Jedes Example enthält eine `PROTOKOLL.md`.
|
||||||
|
Startzeit, Endzeit, Rundenanzahl und Endergebnis eintragen.
|
||||||
|
|
||||||
|
### Schritt 4 — Ausgangszustand wiederherstellen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash examples/restore-all.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Skript löscht Sub-Repos, restauriert alle Quelldateien aus dem Haupt-Repo
|
||||||
|
und bereinigt Build-Artefakte (`target/`, `__pycache__` etc.).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Empfohlene Demo-Reihenfolge
|
||||||
|
|
||||||
|
| # | Beispiel | Geschätzte Dauer | Highlights |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | `python-calculator` | ~5–10 min | Einstieg, Test-Loop |
|
||||||
|
| 2 | `c-linkedlist` | ~5 min | `/quick_check` + `/fix`, kein Loop |
|
||||||
|
| 3 | `rust-wordcount` | ~10–15 min | Loop + `/version` |
|
||||||
|
| 4 | `go-fibonacci` | ~15–20 min | `--interactive` + `/shipit` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Weitere Details
|
||||||
|
|
||||||
|
[python-calculator](python-calculator/README.md) ·
|
||||||
|
[rust-wordcount](rust-wordcount/README.md) ·
|
||||||
|
[go-fibonacci](go-fibonacci/README.md) ·
|
||||||
|
[c-linkedlist](c-linkedlist/README.md)
|
||||||
35
examples/c-linkedlist/PROTOKOLL.md
Normal file
35
examples/c-linkedlist/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Demo-Protokoll: c-linkedlist
|
||||||
|
|
||||||
|
## Lauf 1
|
||||||
|
|
||||||
|
**Datum:**
|
||||||
|
|
||||||
|
**Befehl /quick_check:**
|
||||||
|
```
|
||||||
|
/quick_check "Gibt es Speicherlecks oder sonstige Probleme in diesem C-Projekt?"
|
||||||
|
```
|
||||||
|
**Startzeit:**
|
||||||
|
**Endzeit:**
|
||||||
|
**Dauer (min):**
|
||||||
|
**Ergebnis:** OK / PROBLEM (Kurzbeschreibung):
|
||||||
|
|
||||||
|
**Befehl /fix:**
|
||||||
|
```
|
||||||
|
/fix "Implementiere list_free() korrekt, sodass valgrind --leak-check=full sauber ist."
|
||||||
|
```
|
||||||
|
**Startzeit:**
|
||||||
|
**Endzeit:**
|
||||||
|
**Dauer (min):**
|
||||||
|
**Ergebnis:** erledigt / fehlgeschlagen
|
||||||
|
|
||||||
|
**Befehl /patch (optional):**
|
||||||
|
```
|
||||||
|
/patch "Ergänze list_search(head, value) in Header und Implementierung.
|
||||||
|
Gibt den ersten Node* mit dem gesuchten Wert zurück, oder NULL."
|
||||||
|
```
|
||||||
|
**Startzeit:**
|
||||||
|
**Endzeit:**
|
||||||
|
**Dauer (min):**
|
||||||
|
**Besonderheiten / Beobachtungen:**
|
||||||
|
|
||||||
|
---
|
||||||
48
examples/c-linkedlist/README.md
Normal file
48
examples/c-linkedlist/README.md
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# C Linked List
|
||||||
|
|
||||||
|
Vollständige einfach-verkettete Liste — bis auf `list_free()`, das als leerer Stub vorliegt.
|
||||||
|
Jeder Programmlauf leckt den gesamten Listen-Speicher.
|
||||||
|
|
||||||
|
## Aktueller Stand
|
||||||
|
|
||||||
|
```
|
||||||
|
linked_list.h Interface: node_new, list_prepend, list_append, list_print, list_free, list_length
|
||||||
|
linked_list.c Alles implementiert — außer list_free() (Stub, tut nichts)
|
||||||
|
main.c Baut Liste 1–5, gibt sie aus, ruft list_free() auf (ohne Wirkung)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo 1: `/quick_check` als Diagnose
|
||||||
|
|
||||||
|
```
|
||||||
|
/quick_check "Gibt es Speicherlecks oder sonstige Probleme in diesem C-Projekt?"
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Judge analysiert den Code und identifiziert das leere `list_free()` als Speicherleck-Quelle.
|
||||||
|
|
||||||
|
## Demo 2: `/fix` für gezieltes Nacharbeiten
|
||||||
|
|
||||||
|
```
|
||||||
|
/fix "Implementiere list_free() korrekt, sodass valgrind --leak-check=full sauber ist."
|
||||||
|
```
|
||||||
|
|
||||||
|
Coder implementiert die Funktion, committet. Kein vollständiger Judge-Loop —
|
||||||
|
ideal für kleine, klar abgegrenzte Fixes.
|
||||||
|
|
||||||
|
## Demo 3: `/patch` für Minimal-Erweiterungen
|
||||||
|
|
||||||
|
```
|
||||||
|
/patch "Ergänze list_search(head, value) in Header und Implementierung.
|
||||||
|
Gibt den ersten Node* mit dem gesuchten Wert zurück, oder NULL."
|
||||||
|
```
|
||||||
|
|
||||||
|
pi-coder wendet einen unified diff an (`apply_patch`-Tool), ohne den vollständigen Loop.
|
||||||
|
|
||||||
|
## Manueller Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gcc -Wall -Wextra -o ll_demo linked_list.c main.c
|
||||||
|
./ll_demo
|
||||||
|
|
||||||
|
# Mit Leak-Check:
|
||||||
|
valgrind --leak-check=full ./ll_demo
|
||||||
|
```
|
||||||
43
examples/c-linkedlist/linked_list.c
Normal file
43
examples/c-linkedlist/linked_list.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
Node *node_new(int value) {
|
||||||
|
Node *n = malloc(sizeof(Node));
|
||||||
|
n->value = value;
|
||||||
|
n->next = NULL;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *list_prepend(Node *head, int value) {
|
||||||
|
Node *n = node_new(value);
|
||||||
|
n->next = head;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *list_append(Node *head, int value) {
|
||||||
|
Node *n = node_new(value);
|
||||||
|
if (!head) return n;
|
||||||
|
Node *cur = head;
|
||||||
|
while (cur->next) cur = cur->next;
|
||||||
|
cur->next = n;
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_print(const Node *head) {
|
||||||
|
for (const Node *cur = head; cur; cur = cur->next)
|
||||||
|
printf("%d ", cur->value);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BUG: Speicher wird nicht freigegeben — valgrind meldet Leaks. */
|
||||||
|
void list_free(Node *head) {
|
||||||
|
(void)head; /* TODO: implementieren */
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_length(const Node *head) {
|
||||||
|
int len = 0;
|
||||||
|
for (const Node *cur = head; cur; cur = cur->next)
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
16
examples/c-linkedlist/linked_list.h
Normal file
16
examples/c-linkedlist/linked_list.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef LINKED_LIST_H
|
||||||
|
#define LINKED_LIST_H
|
||||||
|
|
||||||
|
typedef struct Node {
|
||||||
|
int value;
|
||||||
|
struct Node *next;
|
||||||
|
} Node;
|
||||||
|
|
||||||
|
Node *node_new(int value);
|
||||||
|
Node *list_prepend(Node *head, int value);
|
||||||
|
Node *list_append(Node *head, int value);
|
||||||
|
void list_print(const Node *head);
|
||||||
|
void list_free(Node *head);
|
||||||
|
int list_length(const Node *head);
|
||||||
|
|
||||||
|
#endif
|
||||||
16
examples/c-linkedlist/main.c
Normal file
16
examples/c-linkedlist/main.c
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
Node *list = NULL;
|
||||||
|
|
||||||
|
for (int i = 1; i <= 5; i++)
|
||||||
|
list = list_append(list, i);
|
||||||
|
|
||||||
|
printf("Liste: ");
|
||||||
|
list_print(list);
|
||||||
|
printf("Länge: %d\n", list_length(list));
|
||||||
|
|
||||||
|
list_free(list); /* leckt wegen unvollständigem TODO */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
37
examples/go-fibonacci/PROTOKOLL.md
Normal file
37
examples/go-fibonacci/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Demo-Protokoll: go-fibonacci
|
||||||
|
|
||||||
|
## Lauf 1
|
||||||
|
|
||||||
|
**Datum:**
|
||||||
|
**Befehl:**
|
||||||
|
```
|
||||||
|
/optimize "Ersetze die naive Rekursion durch Memoization.
|
||||||
|
fib(50) soll in unter 1ms abgeschlossen sein.
|
||||||
|
Bestehende Tests müssen weiterhin grün bleiben." \
|
||||||
|
--test-cmd "go test ./..." --interactive
|
||||||
|
```
|
||||||
|
**Startzeit:**
|
||||||
|
**Ende Loop (PASS):**
|
||||||
|
**Dauer Loop (min):**
|
||||||
|
**Runden:**
|
||||||
|
**Endergebnis Loop:** PASS / PASS WITH CONCERNS
|
||||||
|
|
||||||
|
**Befehl im --interactive-Checkpoint:**
|
||||||
|
```
|
||||||
|
/continue "Gib zusätzlich die Berechnungszeit in Mikrosekunden aus."
|
||||||
|
```
|
||||||
|
*(oder: `/continue` ohne Zusatzauftrag)*
|
||||||
|
|
||||||
|
**Startzeit /continue:**
|
||||||
|
**Ende /continue:**
|
||||||
|
|
||||||
|
**Befehl /shipit:**
|
||||||
|
```
|
||||||
|
/shipit
|
||||||
|
```
|
||||||
|
**Startzeit /shipit:**
|
||||||
|
**Endzeit /shipit:**
|
||||||
|
**Endergebnis /shipit:** SHIP / NO-SHIP
|
||||||
|
**Besonderheiten / Beobachtungen:**
|
||||||
|
|
||||||
|
---
|
||||||
48
examples/go-fibonacci/README.md
Normal file
48
examples/go-fibonacci/README.md
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Go Fibonacci
|
||||||
|
|
||||||
|
Naive rekursive Fibonacci-Implementierung — korrekt, aber exponentiell langsam.
|
||||||
|
`fib(45)` dauert mehrere Sekunden; `fib(50)` läuft praktisch nicht durch.
|
||||||
|
|
||||||
|
## Aktueller Stand
|
||||||
|
|
||||||
|
```
|
||||||
|
main.go fib(n) — rekursiv, O(2^n)
|
||||||
|
main_test.go TestFib mit 5 Tabellen-Tests (alle grün)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo 1: `/optimize --interactive`
|
||||||
|
|
||||||
|
```
|
||||||
|
/optimize "Ersetze die naive Rekursion durch Memoization.
|
||||||
|
fib(50) soll in unter 1ms abgeschlossen sein.
|
||||||
|
Bestehende Tests müssen weiterhin grün bleiben." \
|
||||||
|
--test-cmd "go test ./..." --interactive
|
||||||
|
```
|
||||||
|
|
||||||
|
Nach dem ersten PASS hält pi-coder im **interaktiven Checkpoint** an.
|
||||||
|
Hier kann ein Zusatzauftrag erteilt werden:
|
||||||
|
|
||||||
|
```
|
||||||
|
/continue "Gib zusätzlich die Berechnungszeit in Mikrosekunden aus."
|
||||||
|
```
|
||||||
|
|
||||||
|
Oder einfach bestätigen:
|
||||||
|
|
||||||
|
```
|
||||||
|
/continue
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo 2: Abschluss mit `/shipit`
|
||||||
|
|
||||||
|
```
|
||||||
|
/shipit
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Judge prüft nochmals explizit auf Produktionsreife und gibt SHIP oder NO-SHIP zurück.
|
||||||
|
|
||||||
|
## Manueller Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test ./...
|
||||||
|
go run main.go
|
||||||
|
```
|
||||||
3
examples/go-fibonacci/go.mod
Normal file
3
examples/go-fibonacci/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module fibonacci
|
||||||
|
|
||||||
|
go 1.21
|
||||||
18
examples/go-fibonacci/main.go
Normal file
18
examples/go-fibonacci/main.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// fib berechnet die n-te Fibonacci-Zahl rekursiv.
|
||||||
|
// Korrekt, aber für n > 40 sehr langsam (exponentiell).
|
||||||
|
func fib(n int) int {
|
||||||
|
if n <= 1 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
return fib(n-1) + fib(n-2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for i := 0; i <= 10; i++ {
|
||||||
|
fmt.Printf("fib(%2d) = %d\n", i, fib(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
20
examples/go-fibonacci/main_test.go
Normal file
20
examples/go-fibonacci/main_test.go
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestFib(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
n, want int
|
||||||
|
}{
|
||||||
|
{0, 0},
|
||||||
|
{1, 1},
|
||||||
|
{2, 1},
|
||||||
|
{5, 5},
|
||||||
|
{10, 55},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
if got := fib(c.n); got != c.want {
|
||||||
|
t.Errorf("fib(%d) = %d, want %d", c.n, got, c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
examples/python-calculator/PROTOKOLL.md
Normal file
19
examples/python-calculator/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Demo-Protokoll: python-calculator
|
||||||
|
|
||||||
|
## Lauf 1
|
||||||
|
|
||||||
|
**Datum:**
|
||||||
|
**Befehl:**
|
||||||
|
```
|
||||||
|
/optimize "Ergänze multiply, divide (wirft ZeroDivisionError bei 0) und power.
|
||||||
|
Schreibe pytest-Tests für alle neuen Funktionen." \
|
||||||
|
--test-cmd "pytest test_calculator.py -v"
|
||||||
|
```
|
||||||
|
**Startzeit:**
|
||||||
|
**Endzeit:**
|
||||||
|
**Dauer (min):**
|
||||||
|
**Runden:**
|
||||||
|
**Endergebnis:** PASS / PASS WITH CONCERNS / SHIP / NO-SHIP
|
||||||
|
**Besonderheiten / Beobachtungen:**
|
||||||
|
|
||||||
|
---
|
||||||
51
examples/python-calculator/README.md
Normal file
51
examples/python-calculator/README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Python Calculator
|
||||||
|
|
||||||
|
Einfacher Taschenrechner mit `add()` und `subtract()`.
|
||||||
|
Multiply, divide, power und Fehlerbehandlung fehlen noch.
|
||||||
|
|
||||||
|
## Aktueller Stand
|
||||||
|
|
||||||
|
```
|
||||||
|
calculator.py add(), subtract()
|
||||||
|
test_calculator.py 5 pytest-Tests (alle grün)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo: `/optimize` mit Test-Integration
|
||||||
|
|
||||||
|
```
|
||||||
|
/optimize "Ergänze multiply, divide (wirft ZeroDivisionError bei 0) und power.
|
||||||
|
Schreibe pytest-Tests für alle neuen Funktionen." \
|
||||||
|
--test-cmd "pytest test_calculator.py -v"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Was pi-coder hier zeigt:**
|
||||||
|
- Coder implementiert, committet
|
||||||
|
- Extension führt `pytest` aus und übergibt das Ergebnis an den Judge
|
||||||
|
- Judge bewertet Korrektheit anhand der Testergebnisse
|
||||||
|
- Bei FAIL: Coder fixt, nächste Runde
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Weitere Demo-Befehle nach dem `/optimize`-Lauf
|
||||||
|
|
||||||
|
```
|
||||||
|
/quick_check "Sind alle Randfälle (negative Zahlen, floats) korrekt behandelt?"
|
||||||
|
```
|
||||||
|
Schnelle Einzel-Beurteilung ohne neuen Fix-Loop.
|
||||||
|
|
||||||
|
```
|
||||||
|
/update_doku
|
||||||
|
```
|
||||||
|
Lässt den Coder Code-Kommentare ergänzen, README aktualisieren und eine
|
||||||
|
Bedienungsanleitung erzeugen.
|
||||||
|
|
||||||
|
## Manueller Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pytest test_calculator.py -v
|
||||||
|
python calculator.py
|
||||||
|
```
|
||||||
11
examples/python-calculator/calculator.py
Normal file
11
examples/python-calculator/calculator.py
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
def add(a, b):
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
|
||||||
|
def subtract(a, b):
|
||||||
|
return a - b
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(add(3, 4)) # 7
|
||||||
|
print(subtract(10, 3)) # 7
|
||||||
18
examples/python-calculator/test_calculator.py
Normal file
18
examples/python-calculator/test_calculator.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import pytest
|
||||||
|
from calculator import add, subtract
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_positive():
|
||||||
|
assert add(2, 3) == 5
|
||||||
|
|
||||||
|
def test_add_negative():
|
||||||
|
assert add(-1, 1) == 0
|
||||||
|
|
||||||
|
def test_add_zero():
|
||||||
|
assert add(0, 0) == 0
|
||||||
|
|
||||||
|
def test_subtract_basic():
|
||||||
|
assert subtract(5, 3) == 2
|
||||||
|
|
||||||
|
def test_subtract_negative_result():
|
||||||
|
assert subtract(3, 5) == -2
|
||||||
31
examples/restore-all.sh
Executable file
31
examples/restore-all.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Stellt den Ausgangszustand aller Examples wieder her.
|
||||||
|
# Löscht erzeugte Sub-Repos, restauriert Quelldateien aus dem Haupt-Repo
|
||||||
|
# und bereinigt Build-Artefakte.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(git -C "$(dirname "$0")" rev-parse --show-toplevel)"
|
||||||
|
EXAMPLES="$ROOT/examples"
|
||||||
|
|
||||||
|
echo "Stelle Examples-Ausgangszustand wieder her..."
|
||||||
|
|
||||||
|
for dir in python-calculator rust-wordcount go-fibonacci c-linkedlist; do
|
||||||
|
path="$EXAMPLES/$dir"
|
||||||
|
if [ -d "$path/.git" ]; then
|
||||||
|
rm -rf "$path/.git"
|
||||||
|
echo " ✓ Sub-Repo entfernt: $dir"
|
||||||
|
fi
|
||||||
|
git -C "$ROOT" checkout -- "examples/$dir/"
|
||||||
|
echo " ✓ Dateien restauriert: $dir"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build-Artefakte bereinigen
|
||||||
|
rm -rf "$EXAMPLES/rust-wordcount/target"
|
||||||
|
find "$EXAMPLES" -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
find "$EXAMPLES" -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
find "$EXAMPLES" -name "ll_demo" -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Fertig. Alle Examples sind im Ausgangszustand."
|
||||||
|
echo "git status zeigt examples/ als clean (wenn kein PROTOKOLL.md verändert wurde)."
|
||||||
4
examples/rust-wordcount/Cargo.toml
Normal file
4
examples/rust-wordcount/Cargo.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
[package]
|
||||||
|
name = "wordcount"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
29
examples/rust-wordcount/PROTOKOLL.md
Normal file
29
examples/rust-wordcount/PROTOKOLL.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Demo-Protokoll: rust-wordcount
|
||||||
|
|
||||||
|
## Lauf 1
|
||||||
|
|
||||||
|
**Datum:**
|
||||||
|
**Befehl:**
|
||||||
|
```
|
||||||
|
/optimize "Ergänze --lines (Zeilenzählung) und --chars (Zeichenzählung) als CLI-Flags.
|
||||||
|
Ohne Flag: Standardausgabe wie bisher (Wörter).
|
||||||
|
Schreibe Tests für alle drei Modi." \
|
||||||
|
--test-cmd "cargo test"
|
||||||
|
```
|
||||||
|
**Startzeit:**
|
||||||
|
**Endzeit:**
|
||||||
|
**Dauer /optimize (min):**
|
||||||
|
**Runden:**
|
||||||
|
**Endergebnis /optimize:** PASS / PASS WITH CONCERNS / SHIP / NO-SHIP
|
||||||
|
|
||||||
|
**Befehl /version:**
|
||||||
|
```
|
||||||
|
/version
|
||||||
|
```
|
||||||
|
**Startzeit /version:**
|
||||||
|
**Endzeit /version:**
|
||||||
|
**Gewählter Bump:** patch / minor / major
|
||||||
|
**Gesetzter Tag:**
|
||||||
|
**Besonderheiten / Beobachtungen:**
|
||||||
|
|
||||||
|
---
|
||||||
50
examples/rust-wordcount/README.md
Normal file
50
examples/rust-wordcount/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Rust Word Counter
|
||||||
|
|
||||||
|
Liest stdin und gibt die Anzahl der Wörter aus.
|
||||||
|
Zeilen- und Zeichenzählung sowie CLI-Flags fehlen noch.
|
||||||
|
|
||||||
|
## Aktueller Stand
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main.rs count_words() — nur Wortzählung, kein Argument-Parsing
|
||||||
|
Cargo.toml Version 0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo 1: `/optimize` mit Cargo-Test-Integration
|
||||||
|
|
||||||
|
```
|
||||||
|
/optimize "Ergänze --lines (Zeilenzählung) und --chars (Zeichenzählung) als CLI-Flags.
|
||||||
|
Ohne Flag: Standardausgabe wie bisher (Wörter).
|
||||||
|
Schreibe Tests für alle drei Modi." \
|
||||||
|
--test-cmd "cargo test"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Was pi-coder hier zeigt:**
|
||||||
|
- Rust-Toolchain wird automatisch erkannt
|
||||||
|
- `cargo test`-Output geht an den Judge
|
||||||
|
- Mehrere Compile-Test-Fix-Zyklen möglich
|
||||||
|
|
||||||
|
## Demo 2: `/version` nach dem Feature
|
||||||
|
|
||||||
|
**Voraussetzung:** Das Verzeichnis muss ein git-Repo mit mindestens einem Commit sein.
|
||||||
|
Falls noch kein Repo existiert, vorher einmalig:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git init && git add -A && git commit -m "feat: initial wordcount"
|
||||||
|
git tag v0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
/version
|
||||||
|
```
|
||||||
|
|
||||||
|
Analysiert die Commits seit `v0.1.0`, erkennt `feat:`-Commits → schlägt `minor`-Bump vor
|
||||||
|
und setzt den Git-Tag `v0.2.0`.
|
||||||
|
|
||||||
|
## Manueller Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo test
|
||||||
|
echo "Hallo Welt" | cargo run
|
||||||
|
echo -e "Zeile 1\nZeile 2" | cargo run -- --lines
|
||||||
|
```
|
||||||
36
examples/rust-wordcount/src/main.rs
Normal file
36
examples/rust-wordcount/src/main.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
fn count_words(text: &str) -> usize {
|
||||||
|
text.split_whitespace().count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut input = String::new();
|
||||||
|
io::stdin().read_to_string(&mut input).unwrap();
|
||||||
|
println!("{} words", count_words(&input));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_input() {
|
||||||
|
assert_eq!(count_words(""), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_word() {
|
||||||
|
assert_eq!(count_words("hallo"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_words() {
|
||||||
|
assert_eq!(count_words("eins zwei drei"), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extra_whitespace() {
|
||||||
|
assert_eq!(count_words(" a b "), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue