refactor: executors and routers
* refactor: executors and routers
This commit is contained in:
@@ -1,47 +1,69 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/iliadenisov/galaxy/internal/controller"
|
||||
"github.com/iliadenisov/galaxy/internal/game"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/iliadenisov/galaxy/internal/model/rest"
|
||||
)
|
||||
|
||||
type CommandExecutor func(controller.Configurer, rest.Command) error
|
||||
|
||||
var (
|
||||
ErrCommandNotProcessed = errors.New("command was not processed by executor")
|
||||
)
|
||||
|
||||
func CommandHandler(c *gin.Context, configurer controller.Configurer, executor CommandExecutor) {
|
||||
func CommandHandler(c *gin.Context, executor CommandExecutor) {
|
||||
var cmd rest.Command
|
||||
if err := c.ShouldBindJSON(&cmd); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
if errorResponded(c, c.ShouldBindJSON(&cmd)) {
|
||||
return
|
||||
}
|
||||
err := executor(configurer, cmd)
|
||||
switch {
|
||||
case err == nil:
|
||||
c.Status(http.StatusOK)
|
||||
case errors.Is(err, ErrCommandNotProcessed):
|
||||
c.Status(http.StatusInternalServerError) // TODO: add error text?
|
||||
|
||||
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.CommandTypeVote:
|
||||
return giveVotes(actor, c)
|
||||
case rest.CommandTypeRelation:
|
||||
return updateRelation(actor, c)
|
||||
default:
|
||||
// TODO: separate invalid input and game state errors
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return nil, fmt.Errorf("unknown comman type: %s", t)
|
||||
}
|
||||
}
|
||||
|
||||
func ExecuteCommand(config controller.Configurer, cmd rest.Command) error {
|
||||
switch {
|
||||
case cmd.DeclareWar != nil:
|
||||
return game.DeclareWar(config, cmd.Race, cmd.DeclareWar.Opponent)
|
||||
case cmd.DeclarePeace != nil:
|
||||
return game.DeclarePeace(config, cmd.Race, cmd.DeclareWar.Opponent)
|
||||
default:
|
||||
return ErrCommandNotProcessed
|
||||
func giveVotes(actor string, c json.RawMessage) (Command, error) {
|
||||
var v rest.CommandVote
|
||||
if err := json.Unmarshal(c, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func(c controller.Ctrl) error { return c.GiveVotes(actor, v.Recipient) }, nil
|
||||
}
|
||||
|
||||
func updateRelation(actor string, c json.RawMessage) (Command, error) {
|
||||
var v rest.CommandUpdateRelation
|
||||
if err := json.Unmarshal(c, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func(c controller.Ctrl) error { return c.UpdateRelation(actor, v.Opponent, v.Relation) }, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user