package main import ( "net/http" "os" "time" "github.com/gin-gonic/gin" "git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/server" ) // adminRoomPlayer ist eine vereinfachte Spieler-Ansicht für das Admin-Panel type adminRoomPlayer struct { Name string `json:"name"` Score int `json:"score"` IsAlive bool `json:"is_alive"` IsSpectator bool `json:"is_spectator"` X float64 `json:"x"` HasDoubleJump bool `json:"has_double_jump"` HasGodMode bool `json:"has_godmode"` } // adminRoom ist eine vereinfachte Raum-Ansicht für das Admin-Panel type adminRoom struct { ID string `json:"id"` Status string `json:"status"` PlayerCount int `json:"player_count"` AliveCount int `json:"alive_count"` ScrollX float64 `json:"scroll_x"` CurrentSpeed float64 `json:"current_speed"` DifficultyFactor float64 `json:"difficulty_factor"` ElapsedSeconds int `json:"elapsed_seconds"` HostID string `json:"host_id"` Players []adminRoomPlayer `json:"players"` } // RegisterAdminRoutes registriert alle Admin-Routen mit BasicAuth func RegisterAdminRoutes(r *gin.Engine) { user := os.Getenv("ADMIN_USER") if user == "" { user = "admin" } password := os.Getenv("ADMIN_PASSWORD") if password == "" { password = "changeme" } admin := r.Group("/admin", gin.BasicAuth(gin.Accounts{user: password})) // Admin Panel HTML admin.GET("", func(c *gin.Context) { c.Header("Cache-Control", "no-store") http.ServeFile(c.Writer, c.Request, "./cmd/client/web/admin.html") }) // --- API: Leaderboard --- admin.GET("/api/leaderboard", func(c *gin.Context) { if server.GlobalLeaderboard == nil { c.JSON(503, gin.H{"error": "Leaderboard nicht verfügbar"}) return } entries := server.GlobalLeaderboard.GetAll() c.JSON(200, entries) }) admin.DELETE("/api/leaderboard/:key", func(c *gin.Context) { key := c.Param("key") if key == "" { c.JSON(400, gin.H{"error": "Kein Key angegeben"}) return } if server.GlobalLeaderboard == nil { c.JSON(503, gin.H{"error": "Leaderboard nicht verfügbar"}) return } if err := server.GlobalLeaderboard.DeleteEntry(key); err != nil { c.JSON(500, gin.H{"error": err.Error()}) return } c.JSON(200, gin.H{"ok": true, "deleted": key}) }) // --- API: Rooms --- admin.GET("/api/rooms", func(c *gin.Context) { mu.RLock() defer mu.RUnlock() result := make([]adminRoom, 0, len(rooms)) for _, room := range rooms { room.Mutex.RLock() elapsed := 0 if room.Status == "RUNNING" || room.Status == "GAMEOVER" { elapsed = int(time.Since(room.GameStartTime).Seconds()) } players := make([]adminRoomPlayer, 0, len(room.Players)) aliveCount := 0 for _, p := range room.Players { if p.IsAlive && !p.IsSpectator { aliveCount++ } players = append(players, adminRoomPlayer{ Name: p.Name, Score: p.Score, IsAlive: p.IsAlive, IsSpectator: p.IsSpectator, X: p.X, HasDoubleJump: p.HasDoubleJump, HasGodMode: p.HasGodMode, }) } result = append(result, adminRoom{ ID: room.ID, Status: room.Status, PlayerCount: len(room.Players), AliveCount: aliveCount, ScrollX: room.GlobalScrollX, CurrentSpeed: room.CurrentSpeed, DifficultyFactor: room.DifficultyFactor, ElapsedSeconds: elapsed, HostID: room.HostID, Players: players, }) room.Mutex.RUnlock() } c.JSON(200, result) }) }