package handler import ( "net/http" "galaxy/model/order" "galaxy/model/rest" "galaxy/game/internal/repo" "github.com/gin-gonic/gin" ) func PutOrderHandler(c *gin.Context, executor CommandExecutor) { var cmd rest.Command if errorResponse(c, c.ShouldBindJSON(&cmd)) { return } // An empty `cmd` array is a valid PUT: the client clears its // local order draft and expects the server to mirror that // state. The engine stores the empty batch so the next GET // returns the same empty list with the new `updatedAt`. commands := make([]order.DecodableCommand, len(cmd.Commands)) for i := range cmd.Commands { command, err := repo.ParseOrder(cmd.Commands[i], validateCommand) if errorResponse(c, err) { return } commands[i] = command } result, err := executor.ValidateOrder(cmd.Actor, commands...) if errorResponse(c, err) { return } c.JSON(http.StatusAccepted, result) } type orderParam struct { Player string `form:"player" binding:"required,notblank"` Turn int `form:"turn" binding:"gte=0"` } func GetOrderHandler(c *gin.Context, executor CommandExecutor) { p := &orderParam{} // ShouldBindQuery surfaces both validator failures and strconv parse // errors; both are client-side faults, so 400 is the correct mapping. if err := c.ShouldBindQuery(p); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } o, ok, err := executor.FetchOrder(p.Player, uint(p.Turn)) if errorResponse(c, err) { return } if !ok { // no order has been previously stored by the player for this turn c.Status(http.StatusNoContent) return } c.JSON(http.StatusOK, o) }