Refactor: Mission Doktor v2.0 - Doktor-style menu system

- Restructured in crumbpages-doktor.sh style
- Main menu with mission categories (Basics, Advanced, Challenges)
- Added Doktor Tools: System Check, Werkzeug Check, Git Status
- Improved navigation and UX
- .gitignore updated to allow demo logs in repo
- Qdrant omitted (as requested)
- Linux first, cross-platform compatible
This commit is contained in:
Branko May Trinkwald
2025-12-21 14:10:22 +01:00
parent 2c53d4d85d
commit 49bf72c7e0
2 changed files with 277 additions and 157 deletions

6
.gitignore vendored
View File

@@ -19,12 +19,16 @@
.missionstage_log/
.bugsy_log/
# Individual log files
# Individual log files (but keep demo logs in missions/)
*.jsonl
*_log.json
*.log
mission_log_*.log
# But allow mission demo logs
!missions/**/*.log
!missions/**/demo_*.txt
# Environment variables (API keys!)
.env
.env.local

View File

@@ -1,184 +1,300 @@
#!/bin/bash
# ============================================================
# 🌲 Crumb Mission Selector - Lernpfade im Crumbforest
# ============================================================
# Inspiriert von CF_Zero_V1 dynamic_mission_selector.sh
# Metadata-driven, erweiterbar, bildungsfreundlich
# ============================================================
# 🌲 Crumbforest Mission Doktor v2.0
# Metadata-driven, erweiterbar, Bash 3.2+ kompatibel
# Inspiriert vom crumbpages-doktor.sh Konzept
set -euo pipefail
# === FARBEN ===
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# === KONFIGURATION ===
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MISSION_DIR="${SCRIPT_DIR}/missions"
DEFAULT_CATEGORY="basics"
# === FARBEN (optional, für bessere UX) ===
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# === DATENSTRUKTUREN ===
# Arrays für Missionen (Bash 3.2+ kompatibel)
MISSION_OPTIONS=()
MISSION_SCRIPTS=()
# ============================================================
# FUNKTIONEN
# HILFSFUNKTIONEN
# ============================================================
show_intro() {
clear
echo -e "${GREEN}"
cat << 'EOF'
🌟 Willkommen im Crumbforest Missionszentrum! 🌟
Hier kannst du auf Lern-Abenteuer gehen:
- 🦊 Fridolin zeigt dir die Pfade (Navigation)
- 🛠️ Balu hilft beim Bauen (Dateien & Ordner)
- 🐈🦉 Noko liest die Botschaften (Logs & Inhalte)
... und viele mehr! Wähle deine Mission:
function show_header() {
clear
echo -e "${GREEN}"
cat << 'EOF'
🌲 Crumbforest Mission Doktor 🌲
Willkommen im Waldlern-System!
Wähle deine Kategorie:
EOF
echo -e "${NC}"
sleep 1
echo -e "${NC}"
}
load_missions() {
local category="${1:-$DEFAULT_CATEGORY}"
local search_dir="${MISSION_DIR}/${category}"
if [[ ! -d "$search_dir" ]]; then
echo "⚠️ Kategorie '$category' nicht gefunden. Nutze Basis-Missionen."
search_dir="${MISSION_DIR}/basics"
fi
echo -e "${BLUE}🔍 Lade Missionen aus: ${search_dir}${NC}"
function load_missions_from_category() {
local category="$1"
local search_dir="${MISSION_DIR}/${category}"
# Alle .sh Dateien finden (Bash 3.2+ kompatibel)
MISSION_SCRIPTS=()
while IFS= read -r file; do
[[ -n "$file" ]] && MISSION_SCRIPTS+=("$file")
done < <(find "$search_dir" -maxdepth 1 -type f -name "*.sh" | sort)
if [[ ${#MISSION_SCRIPTS[@]} -eq 0 ]]; then
echo "❗ Keine Missionen gefunden!"
exit 1
fi
# Metadaten laden
for mission_file in "${MISSION_SCRIPTS[@]}"; do
local mission_name
mission_name="$(basename "$mission_file" .sh)"
local meta_file="${search_dir}/${mission_name}.meta.json"
if [[ -f "$meta_file" ]]; then
local icon title description enabled
icon=$(jq -r '.icon // "🛸"' "$meta_file" 2>/dev/null)
title=$(jq -r '.title // "Unknown"' "$meta_file" 2>/dev/null)
description=$(jq -r '.description // ""' "$meta_file" 2>/dev/null)
enabled=$(jq -r '.enabled // true' "$meta_file" 2>/dev/null)
# Ignoriere deaktivierte Missionen
[[ "$enabled" == "false" ]] && continue
MISSION_OPTIONS+=("${icon} ${title}")
else
# Fallback ohne Metadaten
MISSION_OPTIONS+=("🛸 ${mission_name}")
if [[ ! -d "$search_dir" ]]; then
echo -e "${RED}Kategorie '$category' nicht gefunden.${NC}"
return 1
fi
done
echo -e "${GREEN}${#MISSION_OPTIONS[@]} Missionen geladen.${NC}"
echo ""
}
show_mission_menu() {
# Beenden-Option hinzufügen
local exit_option="🚪 Zurück zum Terminal"
MISSION_OPTIONS+=("$exit_option")
while true; do
echo "🌲 Wähle deine Mission:"
echo "======================"
PS3="Gib die Zahl deiner Wahl ein: "
select opt in "${MISSION_OPTIONS[@]}"; do
local choice=$((REPLY - 1))
# Beenden gewählt
if [[ "$opt" == "$exit_option" ]]; then
echo "👋 Auf bald, kleiner Krümel!"
exit 0
fi
# Mission starten
if (( choice >= 0 && choice < ${#MISSION_OPTIONS[@]} - 1 )); then
local selected_script="${MISSION_SCRIPTS[$choice]}"
echo ""
echo -e "${YELLOW}▶️ Starte Mission: $(basename "$selected_script")${NC}"
echo ""
# Mission ausführen
bash "$selected_script"
# Nach Mission: Zurück zum Menü
echo ""
echo "✅ Mission abgeschlossen!"
read -p "Drücke Enter für das Hauptmenü..." -r
echo ""
break
else
echo "❗ Ungültige Eingabe. Bitte wähle eine Zahl zwischen 1 und ${#MISSION_OPTIONS[@]}."
fi
# Arrays für Missionen (Bash 3.2+ kompatibel)
MISSION_OPTIONS=()
MISSION_SCRIPTS=()
# Alle .sh Dateien finden
while IFS= read -r file; do
[[ -n "$file" ]] && MISSION_SCRIPTS+=("$file")
done < <(find "$search_dir" -maxdepth 1 -type f -name "*.sh" | sort)
if [[ ${#MISSION_SCRIPTS[@]} -eq 0 ]]; then
echo -e "${YELLOW}Keine Missionen in dieser Kategorie gefunden.${NC}"
return 1
fi
# Metadaten laden
for mission_file in "${MISSION_SCRIPTS[@]}"; do
local mission_name
mission_name="$(basename "$mission_file" .sh)"
local meta_file="${search_dir}/${mission_name}.meta.json"
if [[ -f "$meta_file" ]]; then
local icon title enabled
icon=$(jq -r '.icon // "🛸"' "$meta_file" 2>/dev/null)
title=$(jq -r '.title // "Unknown"' "$meta_file" 2>/dev/null)
enabled=$(jq -r '.enabled // true' "$meta_file" 2>/dev/null)
# Ignoriere deaktivierte Missionen
[[ "$enabled" == "false" ]] && continue
MISSION_OPTIONS+=("${icon} ${title}")
else
# Fallback ohne Metadaten
MISSION_OPTIONS+=("🛸 ${mission_name}")
fi
done
done
return 0
}
show_category_selector() {
echo "🗂️ Wähle eine Kategorie:"
echo "========================"
PS3="Kategorie wählen: "
categories=("📚 Basics" "🚀 Advanced" "🏆 Challenges" "🎯 Alle anzeigen")
select cat in "${categories[@]}"; do
case $REPLY in
1) load_missions "basics" ;;
2) load_missions "advanced" ;;
3) load_missions "challenges" ;;
4)
# Alle Kategorien durchsuchen
for dir in "$MISSION_DIR"/*; do
[[ -d "$dir" ]] && load_missions "$(basename "$dir")"
# ============================================================
# MISSION RUNNER
# ============================================================
function run_mission_menu() {
local category="$1"
local category_name="$2"
if ! load_missions_from_category "$category"; then
read -p "Drücke Enter..." -r
return
fi
while true; do
clear
echo -e "${BLUE}=== ${category_name} ===${NC}"
echo ""
# Beenden-Option hinzufügen
MISSION_OPTIONS+=("🚪 Zurück zum Hauptmenü")
PS3="Gib die Zahl deiner Wahl ein: "
select opt in "${MISSION_OPTIONS[@]}"; do
local choice=$((REPLY - 1))
# Beenden gewählt
if [[ "$opt" == "🚪 Zurück zum Hauptmenü" ]]; then
return
fi
# Mission starten
if (( choice >= 0 && choice < ${#MISSION_OPTIONS[@]} - 1 )); then
local selected_script="${MISSION_SCRIPTS[$choice]}"
echo ""
echo -e "${YELLOW}▶️ Starte Mission: $(basename "$selected_script")${NC}"
echo ""
# Mission ausführen
bash "$selected_script"
# Nach Mission: Zurück zum Menü
echo ""
echo -e "${GREEN}✅ Mission abgeschlossen!${NC}"
read -p "Drücke Enter für das Menü..." -r
break
else
echo -e "${RED}❗ Ungültige Eingabe.${NC}"
fi
done
;;
*)
echo "❗ Ungültige Auswahl"
continue
;;
esac
break
done
# Reload für nächste Iteration
if ! load_missions_from_category "$category"; then
return
fi
done
}
# ============================================================
# MAIN
# DOKTOR SYSTEM-CHECK
# ============================================================
main() {
show_intro
# Einfach - lade immer basics
load_missions "basics"
# Erweitert - Kategorie-Auswahl (uncomment für Kategorie-Menü)
# show_category_selector
show_mission_menu
function system_doktor() {
clear
echo -e "${BLUE}=== 🖥️ System Doktor ===${NC}"
echo ""
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo -e "${CYAN}🐧 Linux System${NC}"
hostnamectl 2>/dev/null || hostname
echo ""
uname -r
echo ""
free -h 2>/dev/null || echo "free: nicht verfügbar"
echo ""
df -h / 2>/dev/null
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo -e "${CYAN}🍏 macOS System${NC}"
hostname
echo ""
sw_vers 2>/dev/null
echo ""
echo "Memory:"
vm_stat | head -n 5
echo ""
echo "Disk:"
df -h /
else
echo -e "${YELLOW}Unbekanntes System: $OSTYPE${NC}"
fi
echo ""
echo -e "${GREEN}Bash Version: $BASH_VERSION${NC}"
echo ""
read -p "Drücke Enter..." -r
}
# Start!
main
# ============================================================
# TOOLS CHECK
# ============================================================
function tools_doktor() {
clear
echo -e "${BLUE}=== 🛠️ Werkzeug-Check ===${NC}"
echo ""
TOOLS="jq git curl python3 nano vim"
for tool in $TOOLS; do
if command -v "$tool" &> /dev/null; then
echo -e "${GREEN}$tool${NC} - $(command -v "$tool")"
else
echo -e "${RED}$tool${NC} - Nicht installiert"
fi
done
echo ""
echo -e "${CYAN}Mission System Requirements:${NC}"
# Check jq speziell (wichtig für Metadaten)
if command -v jq &> /dev/null; then
echo -e "${GREEN}✅ jq verfügbar${NC} - Mission Selector funktioniert"
else
echo -e "${RED}⚠️ jq fehlt${NC} - Bitte installieren: brew install jq (macOS) oder apt install jq (Linux)"
fi
echo ""
read -p "Drücke Enter..." -r
}
# ============================================================
# GIT DOKTOR
# ============================================================
function git_doktor() {
clear
echo -e "${BLUE}=== 🌲 Git Doktor ===${NC}"
echo ""
if [[ ! -d ".git" ]]; then
echo -e "${RED}❌ Kein Git Repository gefunden.${NC}"
read -p "Drücke Enter..." -r
return
fi
echo -e "${CYAN}Repository Status:${NC}"
echo ""
# Remote Info
echo -e "${YELLOW}Remote:${NC}"
git remote -v 2>/dev/null || echo "Keine Remotes"
echo ""
# Branch Info
echo -e "${YELLOW}Branch:${NC}"
git branch 2>/dev/null || echo "Keine Branches"
echo ""
# Status
echo -e "${YELLOW}Status:${NC}"
git status --short 2>/dev/null || git status
echo ""
# Letzter Commit
echo -e "${YELLOW}Letzter Commit:${NC}"
git log -1 --oneline 2>/dev/null || echo "Keine Commits"
echo ""
read -p "Drücke Enter..." -r
}
# ============================================================
# HAUPTMENÜ
# ============================================================
function main_menu() {
while true; do
show_header
echo "1) 📚 Basics - Einsteiger Missionen"
echo "2) 🚀 Advanced - Fortgeschrittene Missionen"
echo "3) 🏆 Challenges - Herausforderungen"
echo ""
echo "--- Doktor Tools ---"
echo "4) 🖥️ System Doktor"
echo "5) 🛠️ Werkzeug-Check"
echo "6) 🌲 Git Doktor"
echo ""
echo "7) 👋 Beenden"
echo ""
read -p "Auswahl [1-7]: " CHOICE
case $CHOICE in
1) run_mission_menu "basics" "📚 Basics - Einsteiger" ;;
2) run_mission_menu "advanced" "🚀 Advanced - Fortgeschrittene" ;;
3) run_mission_menu "challenges" "🏆 Challenges" ;;
4) system_doktor ;;
5) tools_doktor ;;
6) git_doktor ;;
7)
clear
echo -e "${GREEN}"
echo "👋 Auf bald im Crumbforest!"
echo -e "${NC}"
exit 0
;;
*)
echo -e "${RED}Bitte 1-7 wählen.${NC}"
sleep 1
;;
esac
done
}
# ============================================================
# START
# ============================================================
main_menu