package handlers import ( "doudizhu-server/internal/game" "doudizhu-server/internal/models" "doudizhu-server/internal/ws" "encoding/json" "net/http" "strings" ) type Handler struct { GameMgr *game.GameManager Hub *ws.Hub } func NewHandler(gameMgr *game.GameManager, hub *ws.Hub) *Handler { return &Handler{GameMgr: gameMgr, Hub: hub} } func (h *Handler) CreateRoom(w http.ResponseWriter, r *http.Request) { var req models.CreateRoomRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { h.jsonError(w, http.StatusBadRequest, "invalid request") return } if req.PlayerName == "" { h.jsonError(w, http.StatusBadRequest, "player name required") return } if req.MaxPlayers < 2 || req.MaxPlayers > 10 { req.MaxPlayers = 4 } room, player := h.GameMgr.CreateRoom(req.PlayerName, req.MaxPlayers) h.jsonSuccess(w, map[string]string{"roomId": room.ID, "playerId": player.ID}) } func (h *Handler) JoinRoom(w http.ResponseWriter, r *http.Request) { roomID := strings.ToLower(extractRoomID(r.URL.Path)) if roomID == "" { h.jsonError(w, http.StatusBadRequest, "room id required") return } var req models.JoinRoomRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { h.jsonError(w, http.StatusBadRequest, "invalid request") return } if req.PlayerName == "" { h.jsonError(w, http.StatusBadRequest, "player name required") return } room, player, err := h.GameMgr.JoinRoom(roomID, req.PlayerName) if err != nil { h.jsonError(w, http.StatusBadRequest, err.Error()) return } h.jsonSuccess(w, map[string]string{"roomId": room.ID, "playerId": player.ID}) } func (h *Handler) WebSocket(w http.ResponseWriter, r *http.Request) { ws.ServeWs(h.Hub, w, r) } func (h *Handler) jsonSuccess(w http.ResponseWriter, data interface{}) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(models.ApiResponse{ Status: 200, Code: 0, Message: "success", Data: data, }) } func (h *Handler) jsonError(w http.ResponseWriter, status int, msg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) json.NewEncoder(w).Encode(models.ApiResponse{ Status: status, Code: 1, Message: msg, }) } func extractRoomID(path string) string { parts := strings.Split(strings.Trim(path, "/"), "/") for i, p := range parts { if p == "rooms" && i+1 < len(parts) && parts[i+1] != "join" { return parts[i+1] } } return "" }