Files
galaxy-game/internal/router/handler/command.go
T
2026-02-11 00:30:37 +02:00

113 lines
2.8 KiB
Go

package handler
import (
"encoding/json"
"fmt"
"net/http"
"github.com/go-playground/validator/v10"
"github.com/iliadenisov/galaxy/internal/controller"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/iliadenisov/galaxy/internal/model/rest"
)
func CommandHandler(c *gin.Context, executor CommandExecutor) {
var cmd rest.Command
if errorResponded(c, c.ShouldBindJSON(&cmd)) {
return
}
commands := make([]Command, 0)
for i := range cmd.Commands {
command, err := parseCommand(cmd.Actor, cmd.Commands[i])
if errorResponded(c, err) {
return
}
commands = append(commands, command)
}
if len(commands) == 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "no commands given"})
return
}
if errorResponded(c, executor.Execute(commands...)) {
return
}
c.Status(http.StatusNoContent)
}
func parseCommand(actor string, c json.RawMessage) (Command, error) {
meta := new(rest.CommandMeta)
if err := json.Unmarshal(c, meta); err != nil {
return nil, err
}
switch t := meta.Type; t {
case rest.CommandTypeRaceQuit:
return commandRaceQuit(actor)
case rest.CommandTypeRaceVote:
return commandRaceVote(actor, c)
case rest.CommandTypeRaceRelation:
return commandRaceRelation(actor, c)
case rest.CommandTypeShipClassCreate:
return commandShipClassCreate(actor, c)
default:
return nil, fmt.Errorf("unknown comman type: %s", t)
}
}
func commandRaceQuit(actor string) (Command, error) {
return func(c controller.Ctrl) error { return c.RaceQuit(actor) }, nil
}
func commandRaceVote(actor string, c json.RawMessage) (Command, error) {
if v, err := unmarshallCommand(c, new(rest.CommandRaceVote)); err != nil {
return nil, err
} else {
return func(c controller.Ctrl) error {
return c.RaceVote(actor, v.Acceptor)
}, nil
}
}
func commandRaceRelation(actor string, c json.RawMessage) (Command, error) {
if v, err := unmarshallCommand(c, new(rest.CommandRaceRelation)); err != nil {
return nil, err
} else {
return func(c controller.Ctrl) error {
return c.RaceRelation(actor, v.Acceptor, v.Relation)
}, nil
}
}
func commandShipClassCreate(actor string, c json.RawMessage) (Command, error) {
if v, err := unmarshallCommand(c, new(rest.CommandShipClassCreate)); err != nil {
return nil, err
} else {
return func(c controller.Ctrl) error {
return c.ShipClassCreate(actor, v.Name, v.Drive, int(v.Armament), v.Weapons, v.Shields, v.Cargo)
}, nil
}
}
func unmarshallCommand[T rest.DecodableCommand](c json.RawMessage, v *T) (*T, error) {
if err := json.Unmarshal(c, v); err != nil {
return nil, err
}
if err := validateCommand(v); err != nil {
return nil, err
}
return v, nil
}
func validateCommand(v any) error {
if ve, ok := binding.Validator.Engine().(*validator.Validate); ok {
if err := ve.Struct(v); err != nil {
return err
}
}
return nil
}