233c9ebc2a
feat: order commands result save/load
161 lines
6.0 KiB
Go
161 lines
6.0 KiB
Go
package controller
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
e "github.com/iliadenisov/galaxy/internal/error"
|
|
"github.com/iliadenisov/galaxy/internal/model/order"
|
|
)
|
|
|
|
func (c *Controller) ValidateOrder(actor string, commands ...order.DecodableCommand) (err error) {
|
|
for i := range commands {
|
|
if _, ok := commands[i].(order.CommandRaceQuit); ok && i != len(commands)-1 {
|
|
err = e.NewQuitCommandFollowedByCommandError()
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = errors.Join(err, c.applyCommand(actor, commands[i]))
|
|
}
|
|
return
|
|
}
|
|
|
|
func (c *Controller) applyCommand(actor string, cmd order.DecodableCommand) (err error) {
|
|
var m *order.CommandMeta
|
|
if v, ok := order.AsCommand[*order.CommandRaceQuit](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.RaceQuit(actor)
|
|
} else if v, ok := order.AsCommand[*order.CommandRaceVote](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.RaceVote(actor, v.Acceptor)
|
|
} else if v, ok := order.AsCommand[*order.CommandRaceRelation](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.RaceRelation(actor, v.Acceptor, v.Relation)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipClassCreate](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipClassCreate(actor, v.Name, v.Drive, int(v.Armament), v.Weapons, v.Shields, v.Cargo)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipClassMerge](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipClassMerge(actor, v.Name, v.Target)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipClassRemove](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipClassRemove(actor, v.Name)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupLoad](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupLoad(actor, uuid.MustParse(v.ID), v.Cargo, v.Quantity)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupUnload](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupUnload(actor, uuid.MustParse(v.ID), v.Quantity)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupSend](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupSend(actor, uuid.MustParse(v.ID), uint(v.Destination))
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupUpgrade](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupUpgrade(actor, uuid.MustParse(v.ID), v.Tech, v.Level)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupMerge](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupMerge(actor)
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupBreak](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupBreak(actor, uuid.MustParse(v.ID), uuid.MustParse(v.NewID), uint(v.Quantity))
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupDismantle](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupDismantle(actor, uuid.MustParse(v.ID))
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupTransfer](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupTransfer(actor, v.Acceptor, uuid.MustParse(v.ID))
|
|
} else if v, ok := order.AsCommand[*order.CommandShipGroupJoinFleet](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ShipGroupJoinFleet(actor, v.Name, uuid.MustParse(v.ID))
|
|
} else if v, ok := order.AsCommand[*order.CommandFleetMerge](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.FleetMerge(actor, v.Name, v.Target)
|
|
} else if v, ok := order.AsCommand[*order.CommandFleetSend](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.FleetSend(actor, v.Name, uint(v.Destination))
|
|
} else if v, ok := order.AsCommand[*order.CommandScienceCreate](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ScienceCreate(actor, v.Name, v.Drive, v.Weapons, v.Shields, v.Cargo)
|
|
} else if v, ok := order.AsCommand[*order.CommandScienceRemove](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.ScienceRemove(actor, v.Name)
|
|
} else if v, ok := order.AsCommand[*order.CommandPlanetRename](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.PlanetRename(actor, v.Number, v.Name)
|
|
} else if v, ok := order.AsCommand[*order.CommandPlanetProduce](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.PlanetProduce(actor, v.Number, v.Production, v.Subject)
|
|
} else if v, ok := order.AsCommand[*order.CommandPlanetRouteSet](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.PlanetRouteSet(actor, v.LoadType, uint(v.Origin), uint(v.Destination))
|
|
} else if v, ok := order.AsCommand[*order.CommandPlanetRouteRemove](cmd); ok {
|
|
m = &v.CommandMeta
|
|
err = c.PlanetRouteRemove(actor, v.LoadType, uint(v.Origin))
|
|
} else {
|
|
return e.NewUnrecognizedCommandError(cmd.CommandType().String())
|
|
}
|
|
|
|
if ge, ok := errors.AsType[*e.GenericError](err); ok {
|
|
m.Result(ge.Code)
|
|
} else if err != nil {
|
|
panic(fmt.Errorf("error applying command has unknown origin: %w", err))
|
|
} else {
|
|
m.Result(0)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// TODO: test commands ordering
|
|
func (c *Controller) applyOrders(t uint) error {
|
|
raceOrder := make(map[int][]order.DecodableCommand)
|
|
unloadGroups := make([]uuid.UUID, 0)
|
|
unloadQuantities := make([]float64, 0)
|
|
for ri := range c.Cache.listRaceActingIdx() {
|
|
o, ok, err := c.Repo.LoadOrder(t, c.Cache.g.Race[ri].ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !ok {
|
|
continue
|
|
}
|
|
raceOrder[ri] = o.Commands
|
|
for i := range o.Commands {
|
|
if o.Commands[i].CommandType() == order.CommandTypeShipGroupUnload {
|
|
unloadCommand := o.Commands[i].(order.CommandShipGroupUnload)
|
|
unloadGroups = append(unloadGroups, uuid.MustParse(unloadCommand.ID))
|
|
unloadQuantities = append(unloadQuantities, unloadCommand.Quantity)
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := c.Cache.shipGroupUnloadColonistChallenge(unloadGroups, unloadQuantities); err != nil {
|
|
return err
|
|
}
|
|
|
|
for ri := range raceOrder {
|
|
for _, cmd := range raceOrder[ri] {
|
|
if cmd.CommandType() == order.CommandTypeShipGroupUnload {
|
|
// group unload commands execution should be failed at this point,
|
|
// otherwise produce no-errors
|
|
if v, ok := order.AsCommand[*order.CommandShipGroupUnload](cmd); ok {
|
|
v.Result(0)
|
|
}
|
|
continue
|
|
}
|
|
// any command might fail due to challenged planets colonization
|
|
_ = c.applyCommand(c.Cache.g.Race[ri].Name, cmd)
|
|
}
|
|
}
|
|
|
|
for ri := range c.Cache.listRaceActingIdx() {
|
|
if err := c.Repo.SaveOrder(t, c.Cache.g.Race[ri].ID, &order.Order{Commands: raceOrder[ri]}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|