refactor: group uuid instead of index
This commit is contained in:
@@ -69,14 +69,14 @@ func (c *Cache) cacheShipsAndGroups() {
|
|||||||
} else {
|
} else {
|
||||||
c.cacheShipClassByShipGroupIndex = make(map[int]*game.ShipType)
|
c.cacheShipClassByShipGroupIndex = make(map[int]*game.ShipType)
|
||||||
}
|
}
|
||||||
for groupIndex := range c.g.ShipGroups {
|
for sgi := range c.g.ShipGroups {
|
||||||
ri := c.RaceIndex(c.g.ShipGroups[groupIndex].OwnerID)
|
ri := c.RaceIndex(c.g.ShipGroups[sgi].OwnerID)
|
||||||
c.cacheRaceIndexByShipGroupIndex[groupIndex] = ri
|
c.cacheRaceIndexByShipGroupIndex[sgi] = ri
|
||||||
sti, ok := ShipClassIndex(c.g, ri, c.g.ShipGroups[groupIndex].TypeID)
|
sci, ok := ShipClassIndex(c.g, ri, c.g.ShipGroups[sgi].TypeID)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("CollectPlanetGroups: ship class not found for race=%q group=%v", c.g.Race[ri].Name, c.g.ShipGroups[groupIndex].Index))
|
panic(fmt.Sprintf("CollectPlanetGroups: ship class not found for race=%q group=%v", c.g.Race[ri].Name, c.g.ShipGroups[sgi].ID))
|
||||||
}
|
}
|
||||||
c.cacheShipClassByShipGroupIndex[groupIndex] = &c.g.Race[ri].ShipTypes[sti]
|
c.cacheShipClassByShipGroupIndex[sgi] = &c.g.Race[ri].ShipTypes[sci]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func (c *Controller) ShipClassRemove(actor, typeName string) error {
|
|||||||
return c.Cache.shipClassRemove(ri, typeName)
|
return c.Cache.shipClassRemove(ri, typeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupLoad(actor string, groupIndex uint, cargoType string, ships uint, quantity float64) error {
|
func (c *Controller) ShipGroupLoad(actor string, groupID uuid.UUID, cargoType string, ships uint, quantity float64) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -87,31 +87,31 @@ func (c *Controller) ShipGroupLoad(actor string, groupIndex uint, cargoType stri
|
|||||||
if !ok {
|
if !ok {
|
||||||
return e.NewCargoTypeInvalidError(cargoType)
|
return e.NewCargoTypeInvalidError(cargoType)
|
||||||
}
|
}
|
||||||
return c.Cache.shipGroupLoad(ri, groupIndex, ct, ships, quantity)
|
return c.Cache.shipGroupLoad(ri, groupID, ct, ships, quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupUnload(actor string, groupIndex uint, ships uint, quantity float64) error {
|
func (c *Controller) ShipGroupUnload(actor string, groupID uuid.UUID, ships uint, quantity float64) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.Cache.shipGroupUnload(ri, groupIndex, ships, quantity)
|
return c.Cache.shipGroupUnload(ri, groupID, ships, quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupSend(actor string, groupIndex, planetNumber, quantity uint) error {
|
func (c *Controller) ShipGroupSend(actor string, groupID uuid.UUID, planetNumber, quantity uint) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.Cache.shipGroupSend(ri, groupIndex, planetNumber, quantity)
|
return c.Cache.shipGroupSend(ri, groupID, planetNumber, quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupUpgrade(actor string, groupIndex uint, techInput string, limitShips uint, limitLevel float64) error {
|
func (c *Controller) ShipGroupUpgrade(actor string, groupID uuid.UUID, techInput string, limitShips uint, limitLevel float64) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.Cache.shipGroupUpgrade(ri, groupIndex, techInput, limitShips, limitLevel)
|
return c.Cache.shipGroupUpgrade(ri, groupID, techInput, limitShips, limitLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupMerge(actor string) error {
|
func (c *Controller) ShipGroupMerge(actor string) error {
|
||||||
@@ -123,23 +123,23 @@ func (c *Controller) ShipGroupMerge(actor string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupBreak(actor string, groupIndex, quantity uint) error {
|
func (c *Controller) ShipGroupBreak(actor string, groupID uuid.UUID, quantity uint) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.Cache.ShipGroupBreak(ri, groupIndex, quantity)
|
return c.Cache.ShipGroupBreak(ri, groupID, quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupDismantle(actor string, groupIndex, quantity uint) error {
|
func (c *Controller) ShipGroupDismantle(actor string, groupID uuid.UUID, quantity uint) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.Cache.shipGroupDismantle(ri, groupIndex, quantity)
|
return c.Cache.shipGroupDismantle(ri, groupID, quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupTransfer(actor, acceptor string, groupIndex, quantity uint) error {
|
func (c *Controller) ShipGroupTransfer(actor, acceptor string, groupID uuid.UUID, quantity uint) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -148,15 +148,15 @@ func (c *Controller) ShipGroupTransfer(actor, acceptor string, groupIndex, quant
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.Cache.shipGroupTransfer(ri, riAccept, groupIndex, quantity)
|
return c.Cache.shipGroupTransfer(ri, riAccept, groupID, quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShipGroupJoinFleet(actor, fleetName string, group, count uint) error {
|
func (c *Controller) ShipGroupJoinFleet(actor, fleetName string, groupID uuid.UUID, count uint) error {
|
||||||
ri, err := c.Cache.validActor(actor)
|
ri, err := c.Cache.validActor(actor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.Cache.ShipGroupJoinFleet(ri, fleetName, group, count)
|
return c.Cache.ShipGroupJoinFleet(ri, fleetName, groupID, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) FleetMerge(actor, fleetSourceName, fleetTargetName string) error {
|
func (c *Controller) FleetMerge(actor, fleetSourceName, fleetTargetName string) error {
|
||||||
|
|||||||
@@ -51,15 +51,15 @@ type Ctrl interface {
|
|||||||
ShipClassCreate(actor, typeName string, drive float64, ammo int, weapons, shileds, cargo float64) error
|
ShipClassCreate(actor, typeName string, drive float64, ammo int, weapons, shileds, cargo float64) error
|
||||||
ShipClassMerge(actor, name, targetName string) error
|
ShipClassMerge(actor, name, targetName string) error
|
||||||
ShipClassRemove(actor, typeName string) error
|
ShipClassRemove(actor, typeName string) error
|
||||||
ShipGroupLoad(actor string, groupIndex uint, cargoType string, ships uint, quantity float64) error
|
ShipGroupLoad(actor string, groupID uuid.UUID, cargoType string, ships uint, quantity float64) error
|
||||||
ShipGroupUnload(actor string, groupIndex uint, ships uint, quantity float64) error
|
ShipGroupUnload(actor string, groupID uuid.UUID, ships uint, quantity float64) error
|
||||||
ShipGroupSend(actor string, groupIndex, planetNumber, quantity uint) error
|
ShipGroupSend(actor string, groupID uuid.UUID, planetNumber, quantity uint) error
|
||||||
ShipGroupUpgrade(actor string, groupIndex uint, techInput string, limitShips uint, limitLevel float64) error
|
ShipGroupUpgrade(actor string, groupID uuid.UUID, techInput string, limitShips uint, limitLevel float64) error
|
||||||
ShipGroupBreak(actor string, groupIndex, quantity uint) error
|
ShipGroupBreak(actor string, groupID uuid.UUID, quantity uint) error
|
||||||
ShipGroupMerge(actor string) error
|
ShipGroupMerge(actor string) error
|
||||||
ShipGroupDismantle(actor string, groupIndex, quantity uint) error
|
ShipGroupDismantle(actor string, groupID uuid.UUID, quantity uint) error
|
||||||
ShipGroupTransfer(actor, acceptor string, groupIndex, quantity uint) error
|
ShipGroupTransfer(actor, acceptor string, groupID uuid.UUID, quantity uint) error
|
||||||
ShipGroupJoinFleet(actor, fleetName string, group, count uint) error
|
ShipGroupJoinFleet(actor, fleetName string, groupID uuid.UUID, count uint) error
|
||||||
FleetMerge(actor, fleetSourceName, fleetTargetName string) error
|
FleetMerge(actor, fleetSourceName, fleetTargetName string) error
|
||||||
FleetSend(actor, fleetName string, planetNumber uint) error
|
FleetSend(actor, fleetName string, planetNumber uint) error
|
||||||
ScienceCreate(actor, typeName string, drive, weapons, shields, cargo float64) error
|
ScienceCreate(actor, typeName string, drive, weapons, shields, cargo float64) error
|
||||||
|
|||||||
@@ -1,13 +1,32 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"iter"
|
"iter"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (c *Cache) CreateShips(ri int, shipTypeName string, planetNumber uint, quantity int) error {
|
||||||
|
class, _, ok := c.ShipClass(ri, shipTypeName)
|
||||||
|
if !ok {
|
||||||
|
return e.NewEntityNotExistsError("ship class q", shipTypeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
p, ok := c.Planet(planetNumber)
|
||||||
|
if !ok {
|
||||||
|
return e.NewEntityNotExistsError("planet #%d", planetNumber)
|
||||||
|
}
|
||||||
|
if !p.OwnedBy(c.g.Race[ri].ID) {
|
||||||
|
return e.NewEntityNotOwnedError("planet #%d", planetNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.createShipsUnsafe(ri, class.ID, p.Number, uint(quantity))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cache) AddRace(n string) (int, uuid.UUID) {
|
func (c *Cache) AddRace(n string) (int, uuid.UUID) {
|
||||||
id := uuid.New()
|
id := uuid.New()
|
||||||
r := &game.Race{
|
r := &game.Race{
|
||||||
@@ -57,15 +76,6 @@ func (c *Cache) MustFleetID(ri int, name string) uuid.UUID {
|
|||||||
panic("fleet not found")
|
panic("fleet not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) MustShipGroup(ri int, index uint) *game.ShipGroup {
|
|
||||||
for sg := range c.listShipGroups(ri) {
|
|
||||||
if sg.Index == index {
|
|
||||||
return sg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("race i=%d have no group i=%d", ri, index))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cache) MustShipClass(ri int, name string) *game.ShipType {
|
func (c *Cache) MustShipClass(ri int, name string) *game.ShipType {
|
||||||
st, _, ok := c.ShipClass(ri, name)
|
st, _, ok := c.ShipClass(ri, name)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -130,8 +130,6 @@ func newGame() *game.Game {
|
|||||||
|
|
||||||
func newCache() (*controller.Cache, *controller.Controller) {
|
func newCache() (*controller.Cache, *controller.Controller) {
|
||||||
ctl := controller.NewGameController(newGame())
|
ctl := controller.NewGameController(newGame())
|
||||||
// g := newGame()
|
|
||||||
// c := controller.NewCache(g)
|
|
||||||
c := ctl.Cache
|
c := ctl.Cache
|
||||||
assertNoError(c.ShipClassCreate(Race_0_idx, Race_0_Gunship, 60, 3, 30, 100, 0))
|
assertNoError(c.ShipClassCreate(Race_0_idx, Race_0_Gunship, 60, 3, 30, 100, 0))
|
||||||
assertNoError(c.ShipClassCreate(Race_0_idx, Race_0_Freighter, 8, 0, 0, 2, 10))
|
assertNoError(c.ShipClassCreate(Race_0_idx, Race_0_Freighter, 8, 0, 0, 2, 10))
|
||||||
@@ -141,9 +139,6 @@ func newCache() (*controller.Cache, *controller.Controller) {
|
|||||||
assertNoError(c.ShipClassCreate(Race_1_idx, Race_1_Freighter, 8, 0, 0, 2, 10))
|
assertNoError(c.ShipClassCreate(Race_1_idx, Race_1_Freighter, 8, 0, 0, 2, 10))
|
||||||
assertNoError(c.ShipClassCreate(Race_1_idx, ShipType_Cruiser, 15, 2, 15, 15, 0)) // same name - different type (why.)
|
assertNoError(c.ShipClassCreate(Race_1_idx, ShipType_Cruiser, 15, 2, 15, 15, 0)) // same name - different type (why.)
|
||||||
|
|
||||||
// ctl := controller.NewRepoController(nil)
|
|
||||||
// ctl.Cache = c
|
|
||||||
|
|
||||||
return c, ctl
|
return c, ctl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ func (c *Cache) FleetState(fleetID uuid.UUID) FleetState {
|
|||||||
InSpace: func() (game.InSpace, bool) { return game.InSpace{}, false },
|
InSpace: func() (game.InSpace, bool) { return game.InSpace{}, false },
|
||||||
AtPlanet: func() (uint, bool) { return 0, false },
|
AtPlanet: func() (uint, bool) { return 0, false },
|
||||||
}
|
}
|
||||||
for sg := range c.FleetGroups(ri, fi) {
|
for sgi := range c.FleetGroupIdx(ri, fi) {
|
||||||
|
sg := c.ShipGroup(sgi)
|
||||||
if fs.State == fleetStateNil {
|
if fs.State == fleetStateNil {
|
||||||
fs.State = sg.State()
|
fs.State = sg.State()
|
||||||
fs.Destination = sg.Destination
|
fs.Destination = sg.Destination
|
||||||
@@ -100,15 +101,15 @@ func (c *Cache) FleetSpeedAndMass(fi int) (float64, float64) {
|
|||||||
return speed, mass
|
return speed, mass
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) ShipGroupJoinFleet(ri int, fleetName string, groupIndex, quantity uint) (err error) {
|
func (c *Cache) ShipGroupJoinFleet(ri int, fleetName string, groupID uuid.UUID, quantity uint) (err error) {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
name, ok := util.ValidateTypeName(fleetName)
|
name, ok := util.ValidateTypeName(fleetName)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityTypeNameValidationError("%q", name)
|
return e.NewEntityTypeNameValidationError("%q", name)
|
||||||
}
|
}
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
return e.NewEntityNotExistsError("group %s", groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
||||||
@@ -139,7 +140,7 @@ func (c *Cache) ShipGroupJoinFleet(ri int, fleetName string, groupIndex, quantit
|
|||||||
}
|
}
|
||||||
|
|
||||||
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
|
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
|
||||||
nsgi, err := c.breakGroupSafe(ri, groupIndex, quantity)
|
nsgi, err := c.breakGroupSafe(ri, groupID, quantity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -268,13 +269,14 @@ func (c *Cache) MustFleetIndex(ID uuid.UUID) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) FleetGroups(ri, fi int) iter.Seq[*game.ShipGroup] {
|
func (c *Cache) FleetGroupIdx(ri, fi int) iter.Seq[int] {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
c.validateFleetIndex(fi)
|
c.validateFleetIndex(fi)
|
||||||
return func(yield func(*game.ShipGroup) bool) {
|
return func(yield func(int) bool) {
|
||||||
for sg := range c.listShipGroups(ri) {
|
for sgi := range c.listShipGroupIdx(ri) {
|
||||||
|
sg := c.ShipGroup(sgi)
|
||||||
if sg.FleetID != nil && *sg.FleetID == c.g.Fleets[fi].ID {
|
if sg.FleetID != nil && *sg.FleetID == c.g.Fleets[fi].ID {
|
||||||
if !yield(sg) {
|
if !yield(sgi) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ func (c *Cache) FleetSend(ri, fi int, planetNumber uint) error {
|
|||||||
return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
|
return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
|
||||||
}
|
}
|
||||||
|
|
||||||
for sg := range c.FleetGroups(ri, fi) {
|
for sgi := range c.FleetGroupIdx(ri, fi) {
|
||||||
st := c.MustShipType(ri, sg.TypeID)
|
st := c.MustShipType(ri, c.ShipGroup(sgi).TypeID)
|
||||||
if st.DriveBlockMass() == 0 {
|
if st.DriveBlockMass() == 0 {
|
||||||
return e.NewSendShipHasNoDrivesError("Class=%s", st.Name)
|
return e.NewSendShipHasNoDrivesError("Class=%s", st.Name)
|
||||||
}
|
}
|
||||||
@@ -48,15 +48,15 @@ func (c *Cache) FleetSend(ri, fi int, planetNumber uint) error {
|
|||||||
func (c *Cache) LaunchFleet(ri, fi int, destination uint) {
|
func (c *Cache) LaunchFleet(ri, fi int, destination uint) {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
c.validateFleetIndex(fi)
|
c.validateFleetIndex(fi)
|
||||||
for sg := range c.FleetGroups(ri, fi) {
|
for sgi := range c.FleetGroupIdx(ri, fi) {
|
||||||
c.LaunchShips(sg, destination)
|
c.LaunchShips(sgi, destination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) UnsendFleet(ri, fi int) {
|
func (c *Cache) UnsendFleet(ri, fi int) {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
c.validateFleetIndex(fi)
|
c.validateFleetIndex(fi)
|
||||||
for sg := range c.FleetGroups(ri, fi) {
|
for sgi := range c.FleetGroupIdx(ri, fi) {
|
||||||
c.UnsendShips(sg)
|
c.UnsendShips(sgi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,22 +29,22 @@ func TestFleetSend(t *testing.T) {
|
|||||||
fleetUnmovable := "R0_Fleet_unmovable"
|
fleetUnmovable := "R0_Fleet_unmovable"
|
||||||
fleetUnmovable2 := "R0_Fleet_unmovable2"
|
fleetUnmovable2 := "R0_Fleet_unmovable2"
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, 1, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, c.ShipGroup(0).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
|
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, 3, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, c.ShipGroup(2).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
|
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetInSpace, 2, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetInSpace, c.ShipGroup(1).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 2)
|
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 2)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, 3, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, c.ShipGroup(2).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 3)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable2, 4, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable2, c.ShipGroup(3).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 4)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, 4, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, c.ShipGroup(3).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 3)
|
||||||
|
|
||||||
// group #2 - in_space
|
// group #2 - in_space
|
||||||
@@ -75,14 +75,14 @@ func TestFleetSend(t *testing.T) {
|
|||||||
assert.NoError(t, g.FleetSend(Race_0.Name, fleetSending, 2))
|
assert.NoError(t, g.FleetSend(Race_0.Name, fleetSending, 2))
|
||||||
fleetState := c.FleetState(c.MustFleetID(Race_0_idx, fleetSending))
|
fleetState := c.FleetState(c.MustFleetID(Race_0_idx, fleetSending))
|
||||||
assert.Equal(t, game.StateLaunched, fleetState.State)
|
assert.Equal(t, game.StateLaunched, fleetState.State)
|
||||||
for sg := range c.FleetGroups(Race_0_idx, c.MustFleetIndex(c.MustFleetID(Race_0_idx, fleetSending))) {
|
for sgi := range c.FleetGroupIdx(Race_0_idx, c.MustFleetIndex(c.MustFleetID(Race_0_idx, fleetSending))) {
|
||||||
assert.Equal(t, game.StateLaunched, sg.State())
|
assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.NoError(t, g.FleetSend(Race_0.Name, fleetSending, 0))
|
assert.NoError(t, g.FleetSend(Race_0.Name, fleetSending, 0))
|
||||||
fleetState = c.FleetState(c.MustFleetID(Race_0_idx, fleetSending))
|
fleetState = c.FleetState(c.MustFleetID(Race_0_idx, fleetSending))
|
||||||
assert.Equal(t, game.StateInOrbit, fleetState.State)
|
assert.Equal(t, game.StateInOrbit, fleetState.State)
|
||||||
for sg := range c.FleetGroups(Race_0_idx, c.MustFleetIndex(c.MustFleetID(Race_0_idx, fleetSending))) {
|
for sgi := range c.FleetGroupIdx(Race_0_idx, c.MustFleetIndex(c.MustFleetID(Race_0_idx, fleetSending))) {
|
||||||
assert.Equal(t, game.StateInOrbit, sg.State())
|
assert.Equal(t, game.StateInOrbit, c.ShipGroup(sgi).State())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/internal/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -12,7 +13,7 @@ import (
|
|||||||
|
|
||||||
func TestShipGroupJoinFleet(t *testing.T) {
|
func TestShipGroupJoinFleet(t *testing.T) {
|
||||||
c, g := newCache()
|
c, g := newCache()
|
||||||
var groupIndex uint = 1
|
groupIndex := uuid.Nil
|
||||||
|
|
||||||
fleetOne := "R0_Fleet_one"
|
fleetOne := "R0_Fleet_one"
|
||||||
fleetTwo := "R0_Fleet_two"
|
fleetTwo := "R0_Fleet_two"
|
||||||
@@ -27,6 +28,7 @@ func TestShipGroupJoinFleet(t *testing.T) {
|
|||||||
|
|
||||||
// creating ShipGroup
|
// creating ShipGroup
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5))
|
||||||
|
groupIndex = c.ShipGroup(0).ID
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupJoinFleet(UnknownRace, fleetOne, groupIndex, 0),
|
g.ShipGroupJoinFleet(UnknownRace, fleetOne, groupIndex, 0),
|
||||||
@@ -57,7 +59,7 @@ func TestShipGroupJoinFleet(t *testing.T) {
|
|||||||
|
|
||||||
// create another ShipGroup
|
// create another ShipGroup
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 3))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 3))
|
||||||
groupIndex = 2
|
groupIndex = c.ShipGroup(1).ID
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTwo, groupIndex, 2))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTwo, groupIndex, 2))
|
||||||
fleets = slices.Collect(c.ListFleets(Race_0_idx))
|
fleets = slices.Collect(c.ListFleets(Race_0_idx))
|
||||||
groups = slices.Collect(c.RaceShipGroups(Race_0_idx))
|
groups = slices.Collect(c.RaceShipGroups(Race_0_idx))
|
||||||
@@ -72,14 +74,12 @@ func TestShipGroupJoinFleet(t *testing.T) {
|
|||||||
assert.NotNil(t, groups[gi].FleetID)
|
assert.NotNil(t, groups[gi].FleetID)
|
||||||
assert.Equal(t, fleets[1].ID, *groups[gi].FleetID)
|
assert.Equal(t, fleets[1].ID, *groups[gi].FleetID)
|
||||||
assert.Equal(t, uint(2), groups[gi].Number)
|
assert.Equal(t, uint(2), groups[gi].Number)
|
||||||
assert.Equal(t, uint(3), groups[gi].Index)
|
|
||||||
|
|
||||||
gi = 1
|
gi = 1
|
||||||
assert.Nil(t, groups[gi].FleetID)
|
assert.Nil(t, groups[gi].FleetID)
|
||||||
assert.Equal(t, uint(1), groups[gi].Number)
|
assert.Equal(t, uint(1), groups[gi].Number)
|
||||||
assert.Equal(t, uint(2), groups[gi].Index)
|
|
||||||
|
|
||||||
groupIndex = groups[gi].Index
|
groupIndex = groups[gi].ID
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOne, groupIndex, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOne, groupIndex, 0))
|
||||||
fleets = slices.Collect(c.ListFleets(Race_0_idx))
|
fleets = slices.Collect(c.ListFleets(Race_0_idx))
|
||||||
assert.Len(t, fleets, 2)
|
assert.Len(t, fleets, 2)
|
||||||
@@ -94,7 +94,7 @@ func TestShipGroupJoinFleet(t *testing.T) {
|
|||||||
gi = 3
|
gi = 3
|
||||||
c.ShipGroup(gi).StateInSpace = &InSpace
|
c.ShipGroup(gi).StateInSpace = &InSpace
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).Index, 0),
|
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).ID, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
c.ShipGroup(gi).StateInSpace = nil
|
c.ShipGroup(gi).StateInSpace = nil
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ func TestShipGroupJoinFleet(t *testing.T) {
|
|||||||
c.ShipGroup(0).StateInSpace = &InSpace
|
c.ShipGroup(0).StateInSpace = &InSpace
|
||||||
c.ShipGroup(1).StateInSpace = c.ShipGroup(0).StateInSpace
|
c.ShipGroup(1).StateInSpace = c.ShipGroup(0).StateInSpace
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).Index, 0),
|
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).ID, 0),
|
||||||
e.GenericErrorText(e.ErrShipsNotOnSamePlanet))
|
e.GenericErrorText(e.ErrShipsNotOnSamePlanet))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,21 +133,21 @@ func TestFleetMerge(t *testing.T) {
|
|||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupJoinFleet(UnknownRace, fleetSourceOne, 1, 0),
|
g.ShipGroupJoinFleet(UnknownRace, fleetSourceOne, c.ShipGroup(0).ID, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupJoinFleet(Race_Extinct.Name, fleetSourceOne, 1, 0),
|
g.ShipGroupJoinFleet(Race_Extinct.Name, fleetSourceOne, c.ShipGroup(0).ID, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSourceOne, 1, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSourceOne, c.ShipGroup(0).ID, 0))
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.FleetMerge(Race_0.Name, fleetSourceOne, fleetTargetTwo),
|
g.FleetMerge(Race_0.Name, fleetSourceOne, fleetTargetTwo),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTargetTwo, 3, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTargetTwo, c.ShipGroup(2).ID, 0))
|
||||||
assert.NoError(t, g.FleetMerge(Race_0.Name, fleetSourceOne, fleetTargetTwo))
|
assert.NoError(t, g.FleetMerge(Race_0.Name, fleetSourceOne, fleetTargetTwo))
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOnPlanet2, 2, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOnPlanet2, c.ShipGroup(1).ID, 0))
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.FleetMerge(Race_0.Name, fleetOnPlanet2, fleetTargetTwo),
|
g.FleetMerge(Race_0.Name, fleetOnPlanet2, fleetTargetTwo),
|
||||||
@@ -168,12 +168,12 @@ func TestFleetSpeedAndMass(t *testing.T) {
|
|||||||
m := c.ShipGroup(0).FullMass(c.MustShipClass(Race_0_idx, Race_0_Gunship))
|
m := c.ShipGroup(0).FullMass(c.MustShipClass(Race_0_idx, Race_0_Gunship))
|
||||||
|
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5)) // 2
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5)) // 2
|
||||||
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, 2, "MAT", 10., 0))
|
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(1).ID, "MAT", 10., 0))
|
||||||
|
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7)) // 3
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7)) // 3
|
||||||
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, 3, "CAP", 10., 0))
|
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(2).ID, "CAP", 10., 0))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, 1, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(0).ID, 0))
|
||||||
fleetIndex := 0
|
fleetIndex := 0
|
||||||
speed, mass = c.FleetSpeedAndMass(fleetIndex)
|
speed, mass = c.FleetSpeedAndMass(fleetIndex)
|
||||||
assert.Equal(t, s, speed)
|
assert.Equal(t, s, speed)
|
||||||
@@ -182,7 +182,7 @@ func TestFleetSpeedAndMass(t *testing.T) {
|
|||||||
s = math.Min(s, c.ShipGroup(1).Speed(c.MustShipClass(Race_0_idx, Race_0_Freighter)))
|
s = math.Min(s, c.ShipGroup(1).Speed(c.MustShipClass(Race_0_idx, Race_0_Freighter)))
|
||||||
m += c.ShipGroup(1).FullMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
m += c.ShipGroup(1).FullMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, 2, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(1).ID, 0))
|
||||||
speed, mass = c.FleetSpeedAndMass(fleetIndex)
|
speed, mass = c.FleetSpeedAndMass(fleetIndex)
|
||||||
assert.Equal(t, s, speed)
|
assert.Equal(t, s, speed)
|
||||||
assert.Equal(t, m, mass)
|
assert.Equal(t, m, mass)
|
||||||
@@ -190,7 +190,7 @@ func TestFleetSpeedAndMass(t *testing.T) {
|
|||||||
s = math.Min(s, c.ShipGroup(2).Speed(c.MustShipClass(Race_0_idx, Race_0_Freighter)))
|
s = math.Min(s, c.ShipGroup(2).Speed(c.MustShipClass(Race_0_idx, Race_0_Freighter)))
|
||||||
m += c.ShipGroup(2).FullMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
m += c.ShipGroup(2).FullMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, 3, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(2).ID, 0))
|
||||||
speed, mass = c.FleetSpeedAndMass(fleetIndex)
|
speed, mass = c.FleetSpeedAndMass(fleetIndex)
|
||||||
assert.Equal(t, s, speed)
|
assert.Equal(t, s, speed)
|
||||||
assert.Equal(t, m, mass)
|
assert.Equal(t, m, mass)
|
||||||
|
|||||||
@@ -191,8 +191,8 @@ func TestProduceShips(t *testing.T) {
|
|||||||
c.MustPlanet(R0_Planet_2_num).Population = 100
|
c.MustPlanet(R0_Planet_2_num).Population = 100
|
||||||
c.MustPlanet(R0_Planet_2_num).Industry = 100
|
c.MustPlanet(R0_Planet_2_num).Industry = 100
|
||||||
c.RaceTechLevel(Race_0_idx, game.TechDrive, 1.5)
|
c.RaceTechLevel(Race_0_idx, game.TechDrive, 1.5)
|
||||||
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, 2, "Drive", 0, 0))
|
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(1).ID, "Drive", 0, 0))
|
||||||
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, 1, "Drive", 0, 0))
|
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "Drive", 0, 0))
|
||||||
assert.Equal(t, game.StateUpgrade, c.ShipGroup(0).State())
|
assert.Equal(t, game.StateUpgrade, c.ShipGroup(0).State())
|
||||||
assert.Equal(t, game.StateUpgrade, c.ShipGroup(1).State())
|
assert.Equal(t, game.StateUpgrade, c.ShipGroup(1).State())
|
||||||
|
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ func (c *Cache) ReportLocalGroup(ri int, rep *mr.Report) {
|
|||||||
sliceIndexValidate(&rep.LocalGroup, i)
|
sliceIndexValidate(&rep.LocalGroup, i)
|
||||||
st := c.MustShipType(ri, sg.TypeID)
|
st := c.MustShipType(ri, sg.TypeID)
|
||||||
c.otherGroup(&rep.LocalGroup[i].OtherGroup, sg, st)
|
c.otherGroup(&rep.LocalGroup[i].OtherGroup, sg, st)
|
||||||
rep.LocalGroup[i].Index = sg.Index
|
rep.LocalGroup[i].ID = sg.ID
|
||||||
rep.LocalGroup[i].State = sg.State().String()
|
rep.LocalGroup[i].State = sg.State().String()
|
||||||
if sg.FleetID != nil {
|
if sg.FleetID != nil {
|
||||||
rep.LocalGroup[i].Fleet = &c.g.Fleets[c.MustFleetIndex(*sg.FleetID)].Name
|
rep.LocalGroup[i].Fleet = &c.g.Fleets[c.MustFleetIndex(*sg.FleetID)].Name
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ func (c *Cache) SendRoutedGroups() {
|
|||||||
sortGroups := func(g []int) {
|
sortGroups := func(g []int) {
|
||||||
// sort groups by largest CargoCapacity
|
// sort groups by largest CargoCapacity
|
||||||
slices.SortFunc(g, func(l, r int) int {
|
slices.SortFunc(g, func(l, r int) int {
|
||||||
return cmp.Or(cmp.Compare(c.ShipGroup(r).CargoCapacity(c.ShipGroupShipClass(r)),
|
return cmp.Or(
|
||||||
c.ShipGroup(l).CargoCapacity(c.ShipGroupShipClass(l))),
|
cmp.Compare(c.ShipGroup(r).CargoCapacity(c.ShipGroupShipClass(r)), c.ShipGroup(l).CargoCapacity(c.ShipGroupShipClass(l))),
|
||||||
cmp.Compare(l, r))
|
cmp.Compare(l, r))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ func (c *Cache) SendRoutedGroups() {
|
|||||||
ct = game.CargoMaterial
|
ct = game.CargoMaterial
|
||||||
default:
|
default:
|
||||||
for _, sgi := range groups {
|
for _, sgi := range groups {
|
||||||
c.LaunchShips(c.ShipGroup(sgi), dest)
|
c.LaunchShips(sgi, dest)
|
||||||
}
|
}
|
||||||
groups = reorderGroups(groups)
|
groups = reorderGroups(groups)
|
||||||
continue
|
continue
|
||||||
@@ -131,6 +131,7 @@ func (c *Cache) SendRoutedGroups() {
|
|||||||
toLoad = sgCapacity
|
toLoad = sgCapacity
|
||||||
} else if maxShips := uint(math.Ceil(toLoad / (sgCapacity / float64(ships)))); maxShips < ships {
|
} else if maxShips := uint(math.Ceil(toLoad / (sgCapacity / float64(ships)))); maxShips < ships {
|
||||||
newGroupIdx := c.breakGroupUnsafe(c.RaceIndex(sg.OwnerID), sgi, maxShips)
|
newGroupIdx := c.breakGroupUnsafe(c.RaceIndex(sg.OwnerID), sgi, maxShips)
|
||||||
|
sgi = newGroupIdx
|
||||||
sg = c.ShipGroup(newGroupIdx)
|
sg = c.ShipGroup(newGroupIdx)
|
||||||
}
|
}
|
||||||
// decrease planet resource
|
// decrease planet resource
|
||||||
@@ -138,7 +139,7 @@ func (c *Cache) SendRoutedGroups() {
|
|||||||
// load group
|
// load group
|
||||||
sg.Load = sg.Load.Add(toLoad)
|
sg.Load = sg.Load.Add(toLoad)
|
||||||
sg.CargoType = &ct
|
sg.CargoType = &ct
|
||||||
c.LaunchShips(sg, dest)
|
c.LaunchShips(sgi, dest)
|
||||||
groups = reorderGroups(groups)
|
groups = reorderGroups(groups)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,11 +118,11 @@ func TestListRoutedSendGroupIds(t *testing.T) {
|
|||||||
|
|
||||||
// Foreign group -> idx 1
|
// Foreign group -> idx 1
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||||
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, 5, 0))
|
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(4).ID, 0))
|
||||||
|
|
||||||
// 5: idx = 4 / Part of the Fleet
|
// 5: idx = 4 / Part of the Fleet
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", 5, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(5).ID, 0))
|
||||||
|
|
||||||
planet_0_groups := slices.Collect(c.ListRoutedSendGroupIds(0))
|
planet_0_groups := slices.Collect(c.ListRoutedSendGroupIds(0))
|
||||||
assert.Len(t, planet_0_groups, 1)
|
assert.Len(t, planet_0_groups, 1)
|
||||||
@@ -150,9 +150,11 @@ func TestEnrouteGroups_SplitGroup(t *testing.T) {
|
|||||||
c.SendRoutedGroups()
|
c.SendRoutedGroups()
|
||||||
|
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
|
||||||
|
|
||||||
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
|
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
|
||||||
assert.Equal(t, uint(1), c.ShipGroup(0).Number)
|
assert.Equal(t, uint(1), c.ShipGroup(0).Number)
|
||||||
assert.Equal(t, 0., c.ShipGroup(0).Load.F())
|
assert.Equal(t, 0., c.ShipGroup(0).Load.F())
|
||||||
|
|
||||||
assert.Equal(t, game.StateLaunched, c.ShipGroup(1).State())
|
assert.Equal(t, game.StateLaunched, c.ShipGroup(1).State())
|
||||||
assert.Equal(t, uint(4), c.ShipGroup(1).Number)
|
assert.Equal(t, uint(4), c.ShipGroup(1).Number)
|
||||||
assert.Equal(t, 65., c.ShipGroup(1).Load.F())
|
assert.Equal(t, 65., c.ShipGroup(1).Load.F())
|
||||||
@@ -281,7 +283,7 @@ func TestListRoutedUnloadShipGroupIds(t *testing.T) {
|
|||||||
|
|
||||||
// 5: idx = 4 / Part of the Fleet
|
// 5: idx = 4 / Part of the Fleet
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", 5, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(4).ID, 0))
|
||||||
|
|
||||||
assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))
|
assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))
|
||||||
for _, rt := range game.RouteTypeSet {
|
for _, rt := range game.RouteTypeSet {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ func (c *Cache) shipClassRemove(ri int, name string) error {
|
|||||||
|
|
||||||
for sg := range c.listShipGroups(ri) {
|
for sg := range c.listShipGroups(ri) {
|
||||||
if sg.TypeID == st.ID {
|
if sg.TypeID == st.ID {
|
||||||
return e.NewDeleteShipTypeExistingGroupError("group: %v", sg.Index)
|
return e.NewDeleteShipTypeExistingGroupError("group: %s", sg.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.g.Race[ri].ShipTypes = append(c.g.Race[ri].ShipTypes[:i], c.g.Race[ri].ShipTypes[i+1:]...)
|
c.g.Race[ri].ShipTypes = append(c.g.Race[ri].ShipTypes[:i], c.g.Race[ri].ShipTypes[i+1:]...)
|
||||||
|
|||||||
@@ -10,43 +10,8 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/internal/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/iliadenisov/galaxy/internal/number"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Cache) CreateShips(ri int, shipTypeName string, planetNumber uint, quantity int) error {
|
|
||||||
class, _, ok := c.ShipClass(ri, shipTypeName)
|
|
||||||
if !ok {
|
|
||||||
return e.NewEntityNotExistsError("ship class q", shipTypeName)
|
|
||||||
}
|
|
||||||
|
|
||||||
p, ok := c.Planet(planetNumber)
|
|
||||||
if !ok {
|
|
||||||
return e.NewEntityNotExistsError("planet #%d", planetNumber)
|
|
||||||
}
|
|
||||||
if !p.OwnedBy(c.g.Race[ri].ID) {
|
|
||||||
return e.NewEntityNotOwnedError("planet #%d", planetNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.createShipsUnsafe(ri, class.ID, p.Number, uint(quantity))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cache) createShipsUnsafe(ri int, classID uuid.UUID, planet uint, quantity uint) {
|
|
||||||
c.appendShipGroup(ri, &game.ShipGroup{
|
|
||||||
OwnerID: c.g.Race[ri].ID,
|
|
||||||
TypeID: classID,
|
|
||||||
Destination: planet,
|
|
||||||
Number: uint(quantity),
|
|
||||||
Tech: map[game.Tech]game.Float{
|
|
||||||
game.TechDrive: game.F(c.g.Race[ri].TechLevel(game.TechDrive)),
|
|
||||||
game.TechWeapons: game.F(c.g.Race[ri].TechLevel(game.TechWeapons)),
|
|
||||||
game.TechShields: game.F(c.g.Race[ri].TechLevel(game.TechShields)),
|
|
||||||
game.TechCargo: game.F(c.g.Race[ri].TechLevel(game.TechCargo)),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShipGroup is a proxy func, nothing to cache
|
// ShipGroup is a proxy func, nothing to cache
|
||||||
func (c *Cache) ShipGroup(groupIndex int) *game.ShipGroup {
|
func (c *Cache) ShipGroup(groupIndex int) *game.ShipGroup {
|
||||||
c.validateShipGroupIndex(groupIndex)
|
c.validateShipGroupIndex(groupIndex)
|
||||||
@@ -77,16 +42,6 @@ func (c *Cache) ShipGroupsIndex() iter.Seq[int] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) ShipGroupMaxIndex(ri int) uint {
|
|
||||||
var max uint = 0
|
|
||||||
for i := range c.g.ShipGroups {
|
|
||||||
if r := c.ShipGroupOwnerRaceIndex(i); r == ri && c.ShipGroup(i).Index > max {
|
|
||||||
max = c.ShipGroup(i).Index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cache) ShipGroupOwnerRaceIndex(groupIndex int) int {
|
func (c *Cache) ShipGroupOwnerRaceIndex(groupIndex int) int {
|
||||||
c.validateShipGroupIndex(groupIndex)
|
c.validateShipGroupIndex(groupIndex)
|
||||||
if len(c.cacheRaceIndexByShipGroupIndex) == 0 {
|
if len(c.cacheRaceIndexByShipGroupIndex) == 0 {
|
||||||
@@ -167,7 +122,7 @@ func (c *Cache) shipGroupMerge(ri int) {
|
|||||||
for i := 0; i < len(raceGroups)-1; i++ {
|
for i := 0; i < len(raceGroups)-1; i++ {
|
||||||
for j := len(raceGroups) - 1; j > i; j-- {
|
for j := len(raceGroups) - 1; j > i; j-- {
|
||||||
if raceGroups[i].Equal(raceGroups[j]) {
|
if raceGroups[i].Equal(raceGroups[j]) {
|
||||||
raceGroups[i].Index = number.Max(raceGroups[i].Index, raceGroups[j].Index)
|
raceGroups[i].ID = raceGroups[j].ID
|
||||||
raceGroups[i].Number += raceGroups[j].Number
|
raceGroups[i].Number += raceGroups[j].Number
|
||||||
raceGroups = append(raceGroups[:j], raceGroups[j+1:]...)
|
raceGroups = append(raceGroups[:j], raceGroups[j+1:]...)
|
||||||
}
|
}
|
||||||
@@ -195,7 +150,7 @@ func (c *Cache) shipGroupMerge(ri int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) shipGroupDismantle(ri int, groupIndex, quantity uint) error {
|
func (c *Cache) shipGroupDismantle(ri int, groupIndex uuid.UUID, quantity uint) error {
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
||||||
@@ -253,13 +208,13 @@ func (c *Cache) shipGroupDismantle(ri int, groupIndex, quantity uint) error {
|
|||||||
// Корабль может нести только один тип груза одновременно.
|
// Корабль может нести только один тип груза одновременно.
|
||||||
// Возможные типы груза - это колонисты, сырье и промышленность.
|
// Возможные типы груза - это колонисты, сырье и промышленность.
|
||||||
// Груз может быть доставлен на борт корабля с Вашей или не занятой планеты, на которой он имеется.
|
// Груз может быть доставлен на борт корабля с Вашей или не занятой планеты, на которой он имеется.
|
||||||
func (c *Cache) shipGroupLoad(ri int, groupIndex uint, ct game.CargoType, ships uint, quantity float64) error {
|
func (c *Cache) shipGroupLoad(ri int, groupID uuid.UUID, ct game.CargoType, ships uint, quantity float64) error {
|
||||||
if ships == 0 && quantity > 0 {
|
if ships == 0 && quantity > 0 {
|
||||||
return e.NewCargoQuantityWithoutGroupBreakError()
|
return e.NewCargoQuantityWithoutGroupBreakError()
|
||||||
}
|
}
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
return e.NewEntityNotExistsError("group %s", groupID)
|
||||||
}
|
}
|
||||||
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
||||||
return e.NewShipsBusyError("state: %s", state)
|
return e.NewShipsBusyError("state: %s", state)
|
||||||
@@ -281,7 +236,7 @@ func (c *Cache) shipGroupLoad(ri int, groupIndex uint, ct game.CargoType, ships
|
|||||||
return e.NewCargoLoadNotEqualError("cargo: %v", *c.ShipGroup(sgi).CargoType)
|
return e.NewCargoLoadNotEqualError("cargo: %v", *c.ShipGroup(sgi).CargoType)
|
||||||
}
|
}
|
||||||
if ships > 0 && ships < c.ShipGroup(sgi).Number {
|
if ships > 0 && ships < c.ShipGroup(sgi).Number {
|
||||||
nsgi, err := c.breakGroupSafe(ri, groupIndex, ships)
|
nsgi, err := c.breakGroupSafe(ri, groupID, ships)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -323,14 +278,14 @@ func (c *Cache) shipGroupLoad(ri int, groupIndex uint, ct game.CargoType, ships
|
|||||||
|
|
||||||
// Промышленность и Сырье могут быть выгружены на любой планете.
|
// Промышленность и Сырье могут быть выгружены на любой планете.
|
||||||
// Колонисты могут быть высажены только на планеты, принадлежащие Вам или на необитаемые планеты.
|
// Колонисты могут быть высажены только на планеты, принадлежащие Вам или на необитаемые планеты.
|
||||||
func (c *Cache) shipGroupUnload(ri int, groupIndex uint, ships uint, quantity float64) error {
|
func (c *Cache) shipGroupUnload(ri int, groupID uuid.UUID, ships uint, quantity float64) error {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
if ships == 0 && quantity > 0 {
|
if ships == 0 && quantity > 0 {
|
||||||
return e.NewCargoQuantityWithoutGroupBreakError()
|
return e.NewCargoQuantityWithoutGroupBreakError()
|
||||||
}
|
}
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
return e.NewEntityNotExistsError("group %s", groupID)
|
||||||
}
|
}
|
||||||
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
||||||
return e.NewShipsBusyError("state: %s", state)
|
return e.NewShipsBusyError("state: %s", state)
|
||||||
@@ -350,7 +305,7 @@ func (c *Cache) shipGroupUnload(ri int, groupIndex uint, ships uint, quantity fl
|
|||||||
return e.NewEntityNotOwnedError("planet #%d unload %v", p.Number, ct)
|
return e.NewEntityNotOwnedError("planet #%d unload %v", p.Number, ct)
|
||||||
}
|
}
|
||||||
if ships > 0 && ships < c.ShipGroup(sgi).Number {
|
if ships > 0 && ships < c.ShipGroup(sgi).Number {
|
||||||
nsgi, err := c.breakGroupSafe(ri, groupIndex, ships)
|
nsgi, err := c.breakGroupSafe(ri, groupID, ships)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -405,13 +360,13 @@ func (c *Cache) unsafeUnloadCargo(sgi int, q float64) {
|
|||||||
p.UnpackCapital()
|
p.UnpackCapital()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (err error) {
|
func (c *Cache) shipGroupTransfer(ri, riAccept int, groupID uuid.UUID, quantity uint) (err error) {
|
||||||
if ri == riAccept {
|
if ri == riAccept {
|
||||||
return e.NewSameRaceError(c.g.Race[riAccept].Name)
|
return e.NewSameRaceError(c.g.Race[riAccept].Name)
|
||||||
}
|
}
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
return e.NewEntityNotExistsError("group %s", groupID)
|
||||||
}
|
}
|
||||||
sg := c.ShipGroup(sgi)
|
sg := c.ShipGroup(sgi)
|
||||||
state := sg.State()
|
state := sg.State()
|
||||||
@@ -444,6 +399,7 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
newGroup := *(sg)
|
newGroup := *(sg)
|
||||||
|
newGroup.ID = uuid.New()
|
||||||
newGroup.TypeID = c.g.Race[riAccept].ShipTypes[stAcc].ID
|
newGroup.TypeID = c.g.Race[riAccept].ShipTypes[stAcc].ID
|
||||||
newGroup.Tech = maps.Clone(sg.Tech)
|
newGroup.Tech = maps.Clone(sg.Tech)
|
||||||
if state == game.StateLaunched {
|
if state == game.StateLaunched {
|
||||||
@@ -451,6 +407,7 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if quantity == 0 || quantity == sg.Number {
|
if quantity == 0 || quantity == sg.Number {
|
||||||
|
// FIXME: remove fleet & invalidate cache?
|
||||||
c.unsafeDeleteShipGroup(sgi)
|
c.unsafeDeleteShipGroup(sgi)
|
||||||
} else {
|
} else {
|
||||||
newGroup.Number = quantity
|
newGroup.Number = quantity
|
||||||
@@ -462,17 +419,11 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) ShipGroupBreak(ri int, groupIndex, quantity uint) error {
|
func (c *Cache) ShipGroupBreak(ri int, groupID uuid.UUID, quantity uint) error {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
sgi := -1
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
for i := range c.ShipGroupsIndex() {
|
if !ok {
|
||||||
if c.ShipGroupOwnerRaceIndex(i) == ri && c.ShipGroup(i).Index == groupIndex {
|
return e.NewEntityNotExistsError("group %s", groupID)
|
||||||
sgi = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sgi < 0 {
|
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
||||||
@@ -486,7 +437,7 @@ func (c *Cache) ShipGroupBreak(ri int, groupIndex, quantity uint) error {
|
|||||||
if quantity == 0 || quantity == c.ShipGroup(sgi).Number {
|
if quantity == 0 || quantity == c.ShipGroup(sgi).Number {
|
||||||
c.internalShipGroupJoinFleet(sgi, nil)
|
c.internalShipGroupJoinFleet(sgi, nil)
|
||||||
} else {
|
} else {
|
||||||
if _, err := c.breakGroupSafe(ri, groupIndex, quantity); err != nil {
|
if _, err := c.breakGroupSafe(ri, groupID, quantity); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,14 +445,14 @@ func (c *Cache) ShipGroupBreak(ri int, groupIndex, quantity uint) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) breakGroupSafe(ri int, groupIndex uint, newGroupShips uint) (int, error) {
|
func (c *Cache) breakGroupSafe(ri int, groupID uuid.UUID, newGroupShips uint) (int, error) {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return -1, e.NewEntityNotExistsError("group #%d", groupIndex)
|
return -1, e.NewEntityNotExistsError("group %s", groupID)
|
||||||
}
|
}
|
||||||
if c.ShipGroup(sgi).Number < newGroupShips {
|
if c.ShipGroup(sgi).Number < newGroupShips {
|
||||||
return -1, e.NewBreakGroupIllegalNumberError("group #%d ships: %d -> %d", c.ShipGroup(sgi).Index, c.ShipGroup(sgi).Number, newGroupShips)
|
return -1, e.NewBreakGroupIllegalNumberError("group=%s ships: %d -> %d", c.ShipGroup(sgi).ID, c.ShipGroup(sgi).Number, newGroupShips)
|
||||||
}
|
}
|
||||||
return c.breakGroupUnsafe(ri, sgi, newGroupShips), nil
|
return c.breakGroupUnsafe(ri, sgi, newGroupShips), nil
|
||||||
}
|
}
|
||||||
@@ -519,39 +470,39 @@ func (c *Cache) breakGroupUnsafe(ri, sgi int, newGroupShips uint) int {
|
|||||||
|
|
||||||
// Internal funcs
|
// Internal funcs
|
||||||
|
|
||||||
func (c *Cache) appendShipGroup(ri int, sg *game.ShipGroup) int {
|
func (c *Cache) raceShipGroupIndex(ri int, id uuid.UUID) (int, bool) {
|
||||||
c.validateRaceIndex(ri)
|
|
||||||
sg.Index = c.ShipGroupMaxIndex(ri) + 1
|
|
||||||
sg.OwnerID = c.g.Race[ri].ID
|
|
||||||
sg.FleetID = nil
|
|
||||||
c.g.ShipGroups = append(c.g.ShipGroups, *sg)
|
|
||||||
i := len(c.g.ShipGroups) - 1
|
|
||||||
c.invalidateShipGroupCache()
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cache) raceShipGroupIndex(ri int, index uint) (int, bool) {
|
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
for i := range c.ShipGroupsIndex() {
|
for i := range c.ShipGroupsIndex() {
|
||||||
if c.ShipGroupOwnerRaceIndex(i) == ri && c.ShipGroup(i).Index == index {
|
if c.ShipGroupOwnerRaceIndex(i) == ri && c.ShipGroup(i).ID == id {
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1, false
|
return -1, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cache) listShipGroupIdx(ri int) iter.Seq[int] {
|
||||||
|
c.validateRaceIndex(ri)
|
||||||
|
return func(yield func(int) bool) {
|
||||||
|
for i := range c.g.ShipGroups {
|
||||||
|
if ri == c.ShipGroupOwnerRaceIndex(i) {
|
||||||
|
if !yield(i) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cache) listShipGroups(ri int) iter.Seq[*game.ShipGroup] {
|
func (c *Cache) listShipGroups(ri int) iter.Seq[*game.ShipGroup] {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
return func(yield func(*game.ShipGroup) bool) {
|
return func(yield func(*game.ShipGroup) bool) {
|
||||||
for i := range c.g.ShipGroups {
|
for sgi := range c.listShipGroupIdx(ri) {
|
||||||
if ri == c.ShipGroupOwnerRaceIndex(i) {
|
if !yield(c.ShipGroup(sgi)) {
|
||||||
if !yield(&c.g.ShipGroups[i]) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cache) shipGroupsInUpgrade(planetNumber uint) iter.Seq[*game.ShipGroup] {
|
func (c *Cache) shipGroupsInUpgrade(planetNumber uint) iter.Seq[*game.ShipGroup] {
|
||||||
return func(yield func(*game.ShipGroup) bool) {
|
return func(yield func(*game.ShipGroup) bool) {
|
||||||
@@ -584,3 +535,29 @@ func (c *Cache) validateShipGroupIndex(i int) {
|
|||||||
panic(fmt.Sprintf("group index out of range: %d >= %d", i, len(c.g.ShipGroups)))
|
panic(fmt.Sprintf("group index out of range: %d >= %d", i, len(c.g.ShipGroups)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cache) createShipsUnsafe(ri int, classID uuid.UUID, planet uint, quantity uint) {
|
||||||
|
c.appendShipGroup(ri, &game.ShipGroup{
|
||||||
|
OwnerID: c.g.Race[ri].ID,
|
||||||
|
TypeID: classID,
|
||||||
|
Destination: planet,
|
||||||
|
Number: uint(quantity),
|
||||||
|
Tech: map[game.Tech]game.Float{
|
||||||
|
game.TechDrive: game.F(c.g.Race[ri].TechLevel(game.TechDrive)),
|
||||||
|
game.TechWeapons: game.F(c.g.Race[ri].TechLevel(game.TechWeapons)),
|
||||||
|
game.TechShields: game.F(c.g.Race[ri].TechLevel(game.TechShields)),
|
||||||
|
game.TechCargo: game.F(c.g.Race[ri].TechLevel(game.TechCargo)),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) appendShipGroup(ri int, sg *game.ShipGroup) int {
|
||||||
|
c.validateRaceIndex(ri)
|
||||||
|
sg.ID = uuid.New()
|
||||||
|
sg.OwnerID = c.g.Race[ri].ID
|
||||||
|
sg.FleetID = nil
|
||||||
|
c.g.ShipGroups = append(c.g.ShipGroups, *sg)
|
||||||
|
i := len(c.g.ShipGroups) - 1
|
||||||
|
c.invalidateShipGroupCache()
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ func TestListMoveableGroupIds(t *testing.T) {
|
|||||||
// 3: idx = 2 / [v] In-Fleet group
|
// 3: idx = 2 / [v] In-Fleet group
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", 2, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(1).ID, 0))
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", 3, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(2).ID, 0))
|
||||||
|
|
||||||
// 4: idx = 3 / [v] In_Space
|
// 4: idx = 3 / [v] In_Space
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7))
|
||||||
@@ -34,7 +34,7 @@ func TestListMoveableGroupIds(t *testing.T) {
|
|||||||
|
|
||||||
// 6: idx = 5 / [v] Just launched group
|
// 6: idx = 5 / [v] Just launched group
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||||
assert.NoError(t, g.ShipGroupSend(Race_0.Name, 6, R0_Planet_2_num, 0))
|
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(5).ID, R0_Planet_2_num, 0))
|
||||||
|
|
||||||
movableGroups := slices.Collect(c.ListMoveableGroupIds())
|
movableGroups := slices.Collect(c.ListMoveableGroupIds())
|
||||||
assert.Len(t, movableGroups, 5)
|
assert.Len(t, movableGroups, 5)
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/internal/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
"github.com/iliadenisov/galaxy/internal/util"
|
"github.com/iliadenisov/galaxy/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Cache) shipGroupSend(ri int, groupIndex, planetNumber, quantity uint) error {
|
func (c *Cache) shipGroupSend(ri int, groupID uuid.UUID, planetNumber, quantity uint) error {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
|
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
return e.NewEntityNotExistsError("group %s", groupID)
|
||||||
}
|
}
|
||||||
st := c.ShipGroupShipClass(sgi)
|
st := c.ShipGroupShipClass(sgi)
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ func (c *Cache) shipGroupSend(ri int, groupIndex, planetNumber, quantity uint) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
|
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
|
||||||
nsgi, err := c.breakGroupSafe(ri, groupIndex, quantity)
|
nsgi, err := c.breakGroupSafe(ri, groupID, quantity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -50,22 +51,20 @@ func (c *Cache) shipGroupSend(ri int, groupIndex, planetNumber, quantity uint) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if p1.Number == p2.Number {
|
if p1.Number == p2.Number {
|
||||||
c.UnsendShips(c.ShipGroup(sgi))
|
c.UnsendShips(sgi)
|
||||||
c.shipGroupMerge(ri)
|
c.shipGroupMerge(ri)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.LaunchShips(c.ShipGroup(sgi), planetNumber)
|
c.LaunchShips(sgi, planetNumber)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) LaunchShips(sg *game.ShipGroup, destination uint) *game.ShipGroup {
|
func (c *Cache) LaunchShips(sgi int, destination uint) *game.ShipGroup {
|
||||||
for i := range c.ShipGroupsIndex() {
|
sg := c.ShipGroup(sgi)
|
||||||
if c.ShipGroup(i).OwnerID == sg.OwnerID && c.ShipGroup(i).Index == sg.Index {
|
|
||||||
state := c.ShipGroup(i).State()
|
|
||||||
var p *game.Planet
|
var p *game.Planet
|
||||||
switch state {
|
switch sg.State() {
|
||||||
case game.StateInOrbit:
|
case game.StateInOrbit:
|
||||||
p = c.MustPlanet(sg.Destination)
|
p = c.MustPlanet(sg.Destination)
|
||||||
case game.StateLaunched:
|
case game.StateLaunched:
|
||||||
@@ -73,25 +72,17 @@ func (c *Cache) LaunchShips(sg *game.ShipGroup, destination uint) *game.ShipGrou
|
|||||||
default:
|
default:
|
||||||
panic("state invalid")
|
panic("state invalid")
|
||||||
}
|
}
|
||||||
c.g.ShipGroups[i] = LaunchShips(*sg, destination, p.X.F(), p.Y.F())
|
c.g.ShipGroups[sgi] = LaunchShips(*sg, destination, p.X.F(), p.Y.F())
|
||||||
return &c.g.ShipGroups[i]
|
return &c.g.ShipGroups[sgi]
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("ship group not found")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) UnsendShips(sg *game.ShipGroup) *game.ShipGroup {
|
func (c *Cache) UnsendShips(sgi int) *game.ShipGroup {
|
||||||
for i := range c.ShipGroupsIndex() {
|
sg := c.ShipGroup(sgi)
|
||||||
if c.ShipGroup(i).OwnerID == sg.OwnerID && c.ShipGroup(i).Index == sg.Index {
|
if sg.State() != game.StateLaunched {
|
||||||
state := c.ShipGroup(i).State()
|
|
||||||
if state != game.StateLaunched {
|
|
||||||
panic("state invalid")
|
panic("state invalid")
|
||||||
}
|
}
|
||||||
c.g.ShipGroups[i] = UnsendShips(*sg)
|
c.g.ShipGroups[sgi] = UnsendShips(*sg)
|
||||||
return &c.g.ShipGroups[i]
|
return &c.g.ShipGroups[sgi]
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("ship group not found")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func LaunchShips(sg game.ShipGroup, destination uint, originX, originY float64) game.ShipGroup {
|
func LaunchShips(sg game.ShipGroup, destination uint, originX, originY float64) game.ShipGroup {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/internal/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
@@ -23,31 +24,31 @@ func TestShipGroupSend(t *testing.T) {
|
|||||||
assert.NoError(t, c.CreateShips(Race_0_idx, "Fortress", R0_Planet_0_num, 1))
|
assert.NoError(t, c.CreateShips(Race_0_idx, "Fortress", R0_Planet_0_num, 1))
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(UnknownRace, 1, 2, 0),
|
g.ShipGroupSend(UnknownRace, c.ShipGroup(0).ID, 2, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(Race_Extinct.Name, 1, 2, 0),
|
g.ShipGroupSend(Race_Extinct.Name, c.ShipGroup(0).ID, 2, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(Race_0.Name, 555, 2, 0),
|
g.ShipGroupSend(Race_0.Name, uuid.New(), 2, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(Race_0.Name, 1, 222, 0),
|
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 222, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(Race_0.Name, 2, 1, 0),
|
g.ShipGroupSend(Race_0.Name, c.ShipGroup(1).ID, 1, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(Race_0.Name, 3, 2, 0),
|
g.ShipGroupSend(Race_0.Name, c.ShipGroup(2).ID, 2, 0),
|
||||||
e.GenericErrorText(e.ErrSendShipHasNoDrives))
|
e.GenericErrorText(e.ErrSendShipHasNoDrives))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(Race_0.Name, 1, 2, 100),
|
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 2, 100),
|
||||||
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupSend(Race_0.Name, 1, 3, 0),
|
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 3, 0),
|
||||||
e.GenericErrorText(e.ErrSendUnreachableDestination))
|
e.GenericErrorText(e.ErrSendUnreachableDestination))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupSend(Race_0.Name, 1, R0_Planet_2_num, 3)) // send 3 of 10
|
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, R0_Planet_2_num, 3)) // send 3 of 10
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, uint(7), c.ShipGroup(0).Number)
|
assert.Equal(t, uint(7), c.ShipGroup(0).Number)
|
||||||
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
|
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
|
||||||
@@ -57,23 +58,25 @@ func TestShipGroupSend(t *testing.T) {
|
|||||||
assert.Nil(t, c.ShipGroup(3).StateInSpace.X)
|
assert.Nil(t, c.ShipGroup(3).StateInSpace.X)
|
||||||
assert.Nil(t, c.ShipGroup(3).StateInSpace.Y)
|
assert.Nil(t, c.ShipGroup(3).StateInSpace.Y)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupSend(Race_0.Name, 4, R0_Planet_0_num, 2)) // un-send 2 of 3
|
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(3).ID, R0_Planet_0_num, 2)) // un-send 2 of 3
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, uint(9), c.MustShipGroup(Race_0_idx, 1).Number)
|
|
||||||
assert.Equal(t, game.StateInOrbit, c.MustShipGroup(Race_0_idx, 1).State())
|
|
||||||
assert.Equal(t, uint(1), c.MustShipGroup(Race_0_idx, 4).Number)
|
|
||||||
assert.Equal(t, game.StateLaunched, c.MustShipGroup(Race_0_idx, 4).State())
|
|
||||||
assert.NotNil(t, c.MustShipGroup(Race_0_idx, 4).StateInSpace)
|
|
||||||
assert.Nil(t, c.MustShipGroup(Race_0_idx, 4).StateInSpace.X)
|
|
||||||
assert.Nil(t, c.MustShipGroup(Race_0_idx, 4).StateInSpace.Y)
|
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupSend(Race_0.Name, 4, R0_Planet_0_num, 0)) // un-send the rest 1
|
assert.Equal(t, uint(9), c.ShipGroup(0).Number)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
|
||||||
assert.Equal(t, uint(10), c.MustShipGroup(Race_0_idx, 1).Number)
|
|
||||||
assert.Equal(t, game.StateInOrbit, c.MustShipGroup(Race_0_idx, 1).State())
|
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupSend(Race_0.Name, 1, R0_Planet_2_num, 0))
|
assert.Equal(t, uint(1), c.ShipGroup(3).Number)
|
||||||
|
assert.Equal(t, game.StateLaunched, c.ShipGroup(3).State())
|
||||||
|
assert.NotNil(t, c.ShipGroup(3).StateInSpace)
|
||||||
|
assert.Nil(t, c.ShipGroup(3).StateInSpace.X)
|
||||||
|
assert.Nil(t, c.ShipGroup(3).StateInSpace.Y)
|
||||||
|
|
||||||
|
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(3).ID, R0_Planet_0_num, 0)) // un-send the rest 1
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
||||||
assert.Equal(t, uint(10), c.MustShipGroup(Race_0_idx, 1).Number)
|
assert.Equal(t, uint(10), c.ShipGroup(0).Number)
|
||||||
assert.Equal(t, game.StateLaunched, c.MustShipGroup(Race_0_idx, 1).State())
|
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
|
||||||
|
|
||||||
|
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, R0_Planet_2_num, 0))
|
||||||
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
||||||
|
assert.Equal(t, uint(10), c.ShipGroup(0).Number)
|
||||||
|
assert.Equal(t, game.StateLaunched, c.ShipGroup(0).State())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,16 +82,16 @@ func TestShipGroupMerge(t *testing.T) {
|
|||||||
switch {
|
switch {
|
||||||
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Freighter) && sg.TechLevel(game.TechDrive) == 1.1:
|
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Freighter) && sg.TechLevel(game.TechDrive) == 1.1:
|
||||||
assert.Equal(t, uint(7), sg.Number)
|
assert.Equal(t, uint(7), sg.Number)
|
||||||
assert.Equal(t, uint(1), sg.Index)
|
// assert.Equal(t, uint(1), sg.Index)
|
||||||
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Freighter) && sg.TechLevel(game.TechDrive) == 1.5:
|
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Freighter) && sg.TechLevel(game.TechDrive) == 1.5:
|
||||||
assert.Equal(t, uint(11), sg.Number)
|
assert.Equal(t, uint(11), sg.Number)
|
||||||
assert.Equal(t, uint(4), sg.Index)
|
// assert.Equal(t, uint(4), sg.Index)
|
||||||
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Gunship) && sg.TechLevel(game.TechDrive) == 1.1:
|
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Gunship) && sg.TechLevel(game.TechDrive) == 1.1:
|
||||||
assert.Equal(t, uint(2), sg.Number)
|
assert.Equal(t, uint(2), sg.Number)
|
||||||
assert.Equal(t, uint(2), sg.Index)
|
// assert.Equal(t, uint(2), sg.Index)
|
||||||
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Gunship) && sg.TechLevel(game.TechDrive) == 1.5:
|
case sg.TypeID == shipTypeID(Race_0_idx, Race_0_Gunship) && sg.TechLevel(game.TechDrive) == 1.5:
|
||||||
assert.Equal(t, uint(13), sg.Number)
|
assert.Equal(t, uint(13), sg.Number)
|
||||||
assert.Equal(t, uint(3), sg.Index)
|
// assert.Equal(t, uint(3), sg.Index)
|
||||||
default:
|
default:
|
||||||
t.Error("not all ship groups covered")
|
t.Error("not all ship groups covered")
|
||||||
}
|
}
|
||||||
@@ -105,48 +105,48 @@ func TestShipGroupBreak(t *testing.T) {
|
|||||||
c.ShipGroup(1).StateInSpace = &InSpace
|
c.ShipGroup(1).StateInSpace = &InSpace
|
||||||
|
|
||||||
fleet := "R0_Fleet"
|
fleet := "R0_Fleet"
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, 1, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(0).ID, 0))
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupBreak(UnknownRace, 1, 0),
|
g.ShipGroupBreak(UnknownRace, c.ShipGroup(0).ID, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupBreak(Race_Extinct.Name, 1, 0),
|
g.ShipGroupBreak(Race_Extinct.Name, c.ShipGroup(0).ID, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupBreak(Race_0.Name, 555, 0),
|
g.ShipGroupBreak(Race_0.Name, uuid.New(), 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupBreak(Race_0.Name, 1, 17),
|
g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, 17),
|
||||||
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupBreak(Race_0.Name, 2, 0),
|
g.ShipGroupBreak(Race_0.Name, c.ShipGroup(1).ID, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
|
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
|
||||||
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
|
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
|
||||||
|
|
||||||
// group #1 -> group #3 (5 new, 8 left)
|
// group #1 -> group #3 (5 new, 8 left)
|
||||||
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, 1, 5)) // group #3 (2)
|
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, c.ShipGroup(0).ID, 5)) // group #3 (2)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
||||||
assert.Equal(t, uint(8), c.ShipGroup(0).Number)
|
assert.Equal(t, uint(8), c.ShipGroup(0).Number)
|
||||||
assert.NotNil(t, c.ShipGroup(0).FleetID)
|
assert.NotNil(t, c.ShipGroup(0).FleetID)
|
||||||
assert.Equal(t, uint(5), c.ShipGroup(2).Number)
|
assert.Equal(t, uint(5), c.ShipGroup(2).Number)
|
||||||
assert.Equal(t, uint(3), c.ShipGroup(2).Index)
|
// assert.Equal(t, uint(3), c.ShipGroup(2).Index)
|
||||||
assert.Nil(t, c.ShipGroup(2).FleetID)
|
assert.Nil(t, c.ShipGroup(2).FleetID)
|
||||||
assert.Nil(t, c.ShipGroup(2).CargoType)
|
assert.Nil(t, c.ShipGroup(2).CargoType)
|
||||||
|
|
||||||
// group #1 -> group #4 (2 new, 6 left)
|
// group #1 -> group #4 (2 new, 6 left)
|
||||||
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
|
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
|
||||||
c.ShipGroup(0).Load = 32.8 // 8 ships
|
c.ShipGroup(0).Load = 32.8 // 8 ships
|
||||||
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, 1, 2)) // group #4 (3)
|
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, c.ShipGroup(0).ID, 2)) // group #4 (3)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, uint(6), c.ShipGroup(0).Number)
|
assert.Equal(t, uint(6), c.ShipGroup(0).Number)
|
||||||
assert.NotNil(t, c.ShipGroup(0).FleetID)
|
assert.NotNil(t, c.ShipGroup(0).FleetID)
|
||||||
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
|
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
|
||||||
assert.Equal(t, uint(4), c.ShipGroup(3).Index)
|
// assert.Equal(t, uint(4), c.ShipGroup(3).Index)
|
||||||
assert.Nil(t, c.ShipGroup(3).FleetID)
|
assert.Nil(t, c.ShipGroup(3).FleetID)
|
||||||
assert.NoError(t, c.ShipGroupJoinFleet(Race_0_idx, fleet, 4, 0))
|
assert.NoError(t, c.ShipGroupJoinFleet(Race_0_idx, fleet, c.ShipGroup(3).ID, 0))
|
||||||
assert.NotNil(t, c.ShipGroup(3).FleetID)
|
assert.NotNil(t, c.ShipGroup(3).FleetID)
|
||||||
|
|
||||||
assert.Equal(t, game.CargoColonist.Ref(), c.ShipGroup(0).CargoType)
|
assert.Equal(t, game.CargoColonist.Ref(), c.ShipGroup(0).CargoType)
|
||||||
@@ -155,13 +155,13 @@ func TestShipGroupBreak(t *testing.T) {
|
|||||||
assert.Equal(t, 8.2, number.Fixed3(c.ShipGroup(3).Load.F()))
|
assert.Equal(t, 8.2, number.Fixed3(c.ShipGroup(3).Load.F()))
|
||||||
|
|
||||||
// group #1 -> MAX 6 off the fleet
|
// group #1 -> MAX 6 off the fleet
|
||||||
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, 1, 6)) // group #1 (0)
|
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, 6)) // group #1 (0)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, uint(6), c.ShipGroup(0).Number)
|
assert.Equal(t, uint(6), c.ShipGroup(0).Number)
|
||||||
assert.Nil(t, c.ShipGroup(0).FleetID)
|
assert.Nil(t, c.ShipGroup(0).FleetID)
|
||||||
|
|
||||||
// group #4 -> ALL off the fleet
|
// group #4 -> ALL off the fleet
|
||||||
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, 4, 0)) // group #1 (0)
|
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, c.ShipGroup(3).ID, 0)) // group #1 (0)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
|
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
|
||||||
assert.Nil(t, c.ShipGroup(3).FleetID)
|
assert.Nil(t, c.ShipGroup(3).FleetID)
|
||||||
@@ -170,10 +170,10 @@ func TestShipGroupBreak(t *testing.T) {
|
|||||||
func TestShipGroupTransfer(t *testing.T) {
|
func TestShipGroupTransfer(t *testing.T) {
|
||||||
c, g := newCache()
|
c, g := newCache()
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, ShipType_Cruiser, R0_Planet_0_num, 11)) // group #1 (0)
|
assert.NoError(t, c.CreateShips(Race_0_idx, ShipType_Cruiser, R0_Planet_0_num, 11)) // group #1 (0)
|
||||||
assert.NoError(t, c.CreateShips(Race_1_idx, ShipType_Cruiser, R1_Planet_1_num, 23)) // group #1 (1)
|
assert.NoError(t, c.CreateShips(Race_1_idx, ShipType_Cruiser, R1_Planet_1_num, 23)) // group #2 (1)
|
||||||
|
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 17)) // group #2 (2) - In_Space
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 17)) // group #3 (2) - In_Space
|
||||||
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "R0_Fleet", 2, 0))
|
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "R0_Fleet", c.ShipGroup(2).ID, 0))
|
||||||
assert.NotNil(t, c.ShipGroup(2).FleetID)
|
assert.NotNil(t, c.ShipGroup(2).FleetID)
|
||||||
c.ShipGroup(2).StateInSpace = &InSpace
|
c.ShipGroup(2).StateInSpace = &InSpace
|
||||||
c.ShipGroup(2).CargoType = game.CargoMaterial.Ref()
|
c.ShipGroup(2).CargoType = game.CargoMaterial.Ref()
|
||||||
@@ -183,31 +183,31 @@ func TestShipGroupTransfer(t *testing.T) {
|
|||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 1)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 1)
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(UnknownRace, Race_1.Name, 2, 0),
|
g.ShipGroupTransfer(UnknownRace, Race_1.Name, c.ShipGroup(1).ID, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_0.Name, UnknownRace, 2, 0),
|
g.ShipGroupTransfer(Race_0.Name, UnknownRace, c.ShipGroup(1).ID, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_0.Name, Race_Extinct.Name, 2, 0),
|
g.ShipGroupTransfer(Race_0.Name, Race_Extinct.Name, c.ShipGroup(1).ID, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_Extinct.Name, Race_1.Name, 2, 0),
|
g.ShipGroupTransfer(Race_Extinct.Name, Race_1.Name, c.ShipGroup(1).ID, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_0.Name, Race_0.Name, 2, 0),
|
g.ShipGroupTransfer(Race_0.Name, Race_0.Name, c.ShipGroup(1).ID, 0),
|
||||||
e.GenericErrorText(e.ErrInputSameRace))
|
e.GenericErrorText(e.ErrInputSameRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, 555, 0),
|
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, uuid.New(), 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, 2, 18),
|
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(2).ID, 18),
|
||||||
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, 1, 0),
|
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(0).ID, 0),
|
||||||
e.GenericErrorText(e.ErrGiveawayGroupShipsTypeNotEqual))
|
e.GenericErrorText(e.ErrGiveawayGroupShipsTypeNotEqual))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, 2, 11)) // group #2 (3)
|
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(2).ID, 11)) // group #2 (3)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 2)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 2)
|
||||||
|
|
||||||
@@ -233,24 +233,24 @@ func TestShipGroupTransfer(t *testing.T) {
|
|||||||
assert.Equal(t, c.ShipGroup(3).Number, uint(11))
|
assert.Equal(t, c.ShipGroup(3).Number, uint(11))
|
||||||
assert.Nil(t, c.ShipGroup(3).FleetID)
|
assert.Nil(t, c.ShipGroup(3).FleetID)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupTransfer(Race_1.Name, Race_0.Name, 2, 11))
|
assert.NoError(t, g.ShipGroupTransfer(Race_1.Name, Race_0.Name, c.ShipGroup(3).ID, 11))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 1)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 1)
|
||||||
|
|
||||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 1))
|
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 1))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, game.StateInOrbit, c.ShipGroup(4).State())
|
assert.Equal(t, game.StateInOrbit, c.ShipGroup(4).State())
|
||||||
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(4).Index, R0_Planet_2_num, 0))
|
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(4).ID, R0_Planet_2_num, 0))
|
||||||
assert.Equal(t, game.StateLaunched, c.ShipGroup(4).State())
|
assert.Equal(t, game.StateLaunched, c.ShipGroup(4).State())
|
||||||
assert.Equal(t, c.ShipGroup(4).OwnerID, Race_0_ID)
|
assert.Equal(t, c.ShipGroup(4).OwnerID, Race_0_ID)
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(4).Index, 0))
|
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(4).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 2)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 2)
|
||||||
assert.Equal(t, game.StateTransfer, c.ShipGroup(4).State())
|
assert.Equal(t, game.StateTransfer, c.ShipGroup(4).State())
|
||||||
assert.Equal(t, c.ShipGroup(4).OwnerID, Race_1_ID)
|
assert.Equal(t, c.ShipGroup(4).OwnerID, Race_1_ID)
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupTransfer(Race_1.Name, Race_0.Name, c.ShipGroup(4).Index, 0),
|
g.ShipGroupTransfer(Race_1.Name, Race_0.Name, c.ShipGroup(4).ID, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,49 +280,49 @@ func TestShipGroupLoad(t *testing.T) {
|
|||||||
|
|
||||||
// tests
|
// tests
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(UnknownRace, 1, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(UnknownRace, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_Extinct.Name, 1, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_Extinct.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 1, "GOLD", 0, 0),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, "GOLD", 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputCargoTypeInvalid))
|
e.GenericErrorText(e.ErrInputCargoTypeInvalid))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 555, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_0.Name, uuid.New(), game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 3, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(2).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 5, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(4).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotOwned))
|
e.GenericErrorText(e.ErrInputEntityNotOwned))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 2, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(1).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputNoCargoBay))
|
e.GenericErrorText(e.ErrInputNoCargoBay))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 4, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(3).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputCargoLoadNotEqual))
|
e.GenericErrorText(e.ErrInputCargoLoadNotEqual))
|
||||||
|
|
||||||
// initial planet is empty
|
// initial planet is empty
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputCargoLoadNotEnough))
|
e.GenericErrorText(e.ErrInputCargoLoadNotEnough))
|
||||||
// add cargo to planet
|
// add cargo to planet
|
||||||
c.PutMaterial(R0_Planet_0_num, 100)
|
c.PutMaterial(R0_Planet_0_num, 100)
|
||||||
// not enough on the planet
|
// not enough on the planet
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 11, 101),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 11, 101),
|
||||||
e.GenericErrorText(e.ErrInputCargoLoadNotEnough))
|
e.GenericErrorText(e.ErrInputCargoLoadNotEnough))
|
||||||
// quantity > ships
|
// quantity > ships
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 0, 1),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 1),
|
||||||
e.GenericErrorText(e.ErrInputCargoQuantityWithoutGroupBreak))
|
e.GenericErrorText(e.ErrInputCargoQuantityWithoutGroupBreak))
|
||||||
|
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 5)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 5)
|
||||||
|
|
||||||
// break group and load maximum
|
// break group and load maximum
|
||||||
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 2, 0))
|
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 2, 0))
|
||||||
assert.Equal(t, 58.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
assert.Equal(t, 58.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 6)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 6)
|
||||||
assert.Nil(t, c.ShipGroup(0).CargoType)
|
assert.Nil(t, c.ShipGroup(0).CargoType)
|
||||||
@@ -333,7 +333,7 @@ func TestShipGroupLoad(t *testing.T) {
|
|||||||
assert.Equal(t, 42.0, c.ShipGroup(5).Load.F())
|
assert.Equal(t, 42.0, c.ShipGroup(5).Load.F())
|
||||||
|
|
||||||
// break group and load limited
|
// break group and load limited
|
||||||
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 2, 18))
|
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 2, 18))
|
||||||
assert.Equal(t, 40.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
assert.Equal(t, 40.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
||||||
assert.Nil(t, c.ShipGroup(0).CargoType)
|
assert.Nil(t, c.ShipGroup(0).CargoType)
|
||||||
@@ -346,7 +346,7 @@ func TestShipGroupLoad(t *testing.T) {
|
|||||||
// add cargo to planet
|
// add cargo to planet
|
||||||
c.PutMaterial(R0_Planet_0_num, 100)
|
c.PutMaterial(R0_Planet_0_num, 100)
|
||||||
// loading all available cargo
|
// loading all available cargo
|
||||||
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 0, 0))
|
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
||||||
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
||||||
assert.Equal(t, 100.0, c.ShipGroup(0).Load.F()) // free: 131.0
|
assert.Equal(t, 100.0, c.ShipGroup(0).Load.F()) // free: 131.0
|
||||||
@@ -354,14 +354,14 @@ func TestShipGroupLoad(t *testing.T) {
|
|||||||
|
|
||||||
// add cargo to planet
|
// add cargo to planet
|
||||||
c.PutMaterial(R0_Planet_0_num, 200)
|
c.PutMaterial(R0_Planet_0_num, 200)
|
||||||
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 11, 31))
|
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 11, 31))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
||||||
assert.Equal(t, 169.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
assert.Equal(t, 169.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
||||||
assert.Equal(t, 131.0, c.ShipGroup(0).Load.F()) // free: 100.0
|
assert.Equal(t, 131.0, c.ShipGroup(0).Load.F()) // free: 100.0
|
||||||
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
|
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
|
||||||
|
|
||||||
// load to maximum cargo space left
|
// load to maximum cargo space left
|
||||||
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 11, 0))
|
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 11, 0))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
||||||
assert.Equal(t, 153.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
assert.Equal(t, 153.0, c.MustPlanet(R0_Planet_0_num).Material.F())
|
||||||
assert.Equal(t, 147.0, c.ShipGroup(0).Load.F()) // free: 0.0
|
assert.Equal(t, 147.0, c.ShipGroup(0).Load.F()) // free: 0.0
|
||||||
@@ -369,7 +369,7 @@ func TestShipGroupLoad(t *testing.T) {
|
|||||||
|
|
||||||
// ship group is full
|
// ship group is full
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupLoad(Race_0.Name, 1, game.CargoMaterial.String(), 0, 0),
|
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputCargoLoadNoSpaceLeft))
|
e.GenericErrorText(e.ErrInputCargoLoadNoSpaceLeft))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
||||||
}
|
}
|
||||||
@@ -408,39 +408,39 @@ func TestShipGroupUnload(t *testing.T) {
|
|||||||
|
|
||||||
// tests
|
// tests
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(UnknownRace, 1, 0, 0),
|
g.ShipGroupUnload(UnknownRace, c.ShipGroup(0).ID, 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_Extinct.Name, 1, 0, 0),
|
g.ShipGroupUnload(Race_Extinct.Name, c.ShipGroup(0).ID, 0, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_0.Name, 555, 0, 0),
|
g.ShipGroupUnload(Race_0.Name, uuid.New(), 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_0.Name, 3, 0, 0),
|
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(2).ID, 0, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_0.Name, 2, 0, 0),
|
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(1).ID, 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputNoCargoBay))
|
e.GenericErrorText(e.ErrInputNoCargoBay))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_0.Name, 1, 0, 0),
|
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputCargoUnloadEmpty))
|
e.GenericErrorText(e.ErrInputCargoUnloadEmpty))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_0.Name, 5, 0, 0),
|
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(4).ID, 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotOwned))
|
e.GenericErrorText(e.ErrInputEntityNotOwned))
|
||||||
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
|
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
|
||||||
c.ShipGroup(0).Load = 100
|
c.ShipGroup(0).Load = 100
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_0.Name, 1, 11, 101),
|
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 11, 101),
|
||||||
e.GenericErrorText(e.ErrInputCargoUnoadNotEnough))
|
e.GenericErrorText(e.ErrInputCargoUnoadNotEnough))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUnload(Race_0.Name, 1, 0, 1),
|
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0, 1),
|
||||||
e.GenericErrorText(e.ErrInputCargoQuantityWithoutGroupBreak))
|
e.GenericErrorText(e.ErrInputCargoQuantityWithoutGroupBreak))
|
||||||
|
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 6)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 6)
|
||||||
|
|
||||||
// unload MAT on foreign planet / break group
|
// unload MAT on foreign planet / break group
|
||||||
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, 6, 3, 0))
|
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(5).ID, 3, 0))
|
||||||
assert.Equal(t, 27.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.F()))
|
assert.Equal(t, 27.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.F()))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
|
||||||
assert.Equal(t, uint(3), c.ShipGroup(6).Number)
|
assert.Equal(t, uint(3), c.ShipGroup(6).Number)
|
||||||
@@ -452,7 +452,7 @@ func TestShipGroupUnload(t *testing.T) {
|
|||||||
assert.Equal(t, 72.727, number.Fixed3(c.ShipGroup(5).Load.F()))
|
assert.Equal(t, 72.727, number.Fixed3(c.ShipGroup(5).Load.F()))
|
||||||
|
|
||||||
// unload MAT on foreign planet / break group / limited MAT
|
// unload MAT on foreign planet / break group / limited MAT
|
||||||
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, 6, 3, 20.0))
|
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(5).ID, 3, 20.0))
|
||||||
assert.Equal(t, 47.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.F()))
|
assert.Equal(t, 47.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.F()))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 8)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 8)
|
||||||
assert.Equal(t, uint(3), c.ShipGroup(7).Number)
|
assert.Equal(t, uint(3), c.ShipGroup(7).Number)
|
||||||
@@ -463,7 +463,7 @@ func TestShipGroupUnload(t *testing.T) {
|
|||||||
assert.Equal(t, 45.455, number.Fixed3(c.ShipGroup(5).Load.F()))
|
assert.Equal(t, 45.455, number.Fixed3(c.ShipGroup(5).Load.F()))
|
||||||
|
|
||||||
// unload ALL
|
// unload ALL
|
||||||
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, 1, 0, 0))
|
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0, 0))
|
||||||
assert.Equal(t, 100.0, number.Fixed3(c.MustPlanet(R0_Planet_0_num).Colonists.F()))
|
assert.Equal(t, 100.0, number.Fixed3(c.MustPlanet(R0_Planet_0_num).Colonists.F()))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 8)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 8)
|
||||||
assert.Equal(t, uint(10), c.ShipGroup(0).Number)
|
assert.Equal(t, uint(10), c.ShipGroup(0).Number)
|
||||||
@@ -502,26 +502,26 @@ func TestShipGroupDismantle(t *testing.T) {
|
|||||||
|
|
||||||
// tests
|
// tests
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupDismantle(UnknownRace, 1, 0),
|
g.ShipGroupDismantle(UnknownRace, c.ShipGroup(0).ID, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupDismantle(Race_Extinct.Name, 1, 0),
|
g.ShipGroupDismantle(Race_Extinct.Name, c.ShipGroup(0).ID, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupDismantle(Race_0.Name, 555, 0),
|
g.ShipGroupDismantle(Race_0.Name, uuid.New(), 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupDismantle(Race_0.Name, 2, 0),
|
g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(1).ID, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupDismantle(Race_0.Name, 3, 12),
|
g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(2).ID, 12),
|
||||||
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
|
||||||
|
|
||||||
groupEmptyMass := c.ShipGroup(4).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
groupEmptyMass := c.ShipGroup(4).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
||||||
planetMAT := c.MustPlanet(R1_Planet_1_num).Material.F()
|
planetMAT := c.MustPlanet(R1_Planet_1_num).Material.F()
|
||||||
planetCOL := c.MustPlanet(R1_Planet_1_num).Colonists.F()
|
planetCOL := c.MustPlanet(R1_Planet_1_num).Colonists.F()
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, 5, 0))
|
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(4).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, planetMAT+groupEmptyMass, c.MustPlanet(R1_Planet_1_num).Material.F())
|
assert.Equal(t, planetMAT+groupEmptyMass, c.MustPlanet(R1_Planet_1_num).Material.F())
|
||||||
assert.Equal(t, planetCOL, c.MustPlanet(R1_Planet_1_num).Colonists.F())
|
assert.Equal(t, planetCOL, c.MustPlanet(R1_Planet_1_num).Colonists.F())
|
||||||
@@ -529,7 +529,7 @@ func TestShipGroupDismantle(t *testing.T) {
|
|||||||
groupEmptyMass = c.ShipGroup(3).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
groupEmptyMass = c.ShipGroup(3).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
|
||||||
groupLoadMAT := c.ShipGroup(3).Load.F()
|
groupLoadMAT := c.ShipGroup(3).Load.F()
|
||||||
planetMAT = c.MustPlanet(R1_Planet_1_num).Material.F()
|
planetMAT = c.MustPlanet(R1_Planet_1_num).Material.F()
|
||||||
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, 4, 0))
|
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(3).ID, 0))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
||||||
assert.Equal(t, planetMAT+groupEmptyMass+groupLoadMAT, c.MustPlanet(R1_Planet_1_num).Material.F())
|
assert.Equal(t, planetMAT+groupEmptyMass+groupLoadMAT, c.MustPlanet(R1_Planet_1_num).Material.F())
|
||||||
|
|
||||||
@@ -547,7 +547,7 @@ func TestShipGroupDismantle(t *testing.T) {
|
|||||||
freePOPLeft := c.MustPlanet(R0_Planet_0_num).Size.F() - c.MustPlanet(R0_Planet_0_num).Population.F()
|
freePOPLeft := c.MustPlanet(R0_Planet_0_num).Size.F() - c.MustPlanet(R0_Planet_0_num).Population.F()
|
||||||
expectAddedCOL := (expectPOPIncrease - freePOPLeft) / 8
|
expectAddedCOL := (expectPOPIncrease - freePOPLeft) / 8
|
||||||
expectAddedPOP := freePOPLeft
|
expectAddedPOP := freePOPLeft
|
||||||
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, 3, quantity))
|
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(2).ID, quantity))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
|
||||||
assert.Equal(t, planetCOL+expectAddedCOL, c.MustPlanet(R0_Planet_0_num).Colonists.F())
|
assert.Equal(t, planetCOL+expectAddedCOL, c.MustPlanet(R0_Planet_0_num).Colonists.F())
|
||||||
assert.Equal(t, planetPOP+expectAddedPOP, c.MustPlanet(R0_Planet_0_num).Population.F())
|
assert.Equal(t, planetPOP+expectAddedPOP, c.MustPlanet(R0_Planet_0_num).Population.F())
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
e "github.com/iliadenisov/galaxy/internal/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Cache) shipGroupUpgrade(ri int, groupIndex uint, techInput string, limitShips uint, limitLevel float64) error {
|
func (c *Cache) shipGroupUpgrade(ri int, groupID uuid.UUID, techInput string, limitShips uint, limitLevel float64) error {
|
||||||
c.validateRaceIndex(ri)
|
c.validateRaceIndex(ri)
|
||||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
return e.NewEntityNotExistsError("group %s", groupID)
|
||||||
}
|
}
|
||||||
st := c.ShipGroupShipClass(sgi)
|
st := c.ShipGroupShipClass(sgi)
|
||||||
sg := c.ShipGroup(sgi)
|
sg := c.ShipGroup(sgi)
|
||||||
@@ -24,7 +25,7 @@ func (c *Cache) shipGroupUpgrade(ri int, groupIndex uint, techInput string, limi
|
|||||||
|
|
||||||
p := c.MustPlanet(sg.Destination)
|
p := c.MustPlanet(sg.Destination)
|
||||||
if p.Owned() && !p.OwnedBy(c.g.Race[ri].ID) {
|
if p.Owned() && !p.OwnedBy(c.g.Race[ri].ID) {
|
||||||
return e.NewEntityNotOwnedError("planet #%d for upgrade group #%d", p.Number, groupIndex)
|
return e.NewEntityNotOwnedError("planet #%d for upgrade group %s", p.Number, groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
upgradeValidTech := map[string]game.Tech{
|
upgradeValidTech := map[string]game.Tech{
|
||||||
@@ -117,7 +118,7 @@ func (c *Cache) shipGroupUpgrade(ri int, groupIndex uint, techInput string, limi
|
|||||||
|
|
||||||
// break group if needed
|
// break group if needed
|
||||||
if maxUpgradableShips < sg.Number {
|
if maxUpgradableShips < sg.Number {
|
||||||
nsgi, err := c.breakGroupSafe(ri, groupIndex, maxUpgradableShips)
|
nsgi, err := c.breakGroupSafe(ri, groupID, maxUpgradableShips)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/iliadenisov/galaxy/internal/controller"
|
"github.com/iliadenisov/galaxy/internal/controller"
|
||||||
e "github.com/iliadenisov/galaxy/internal/error"
|
e "github.com/iliadenisov/galaxy/internal/error"
|
||||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||||
@@ -125,43 +126,43 @@ func TestShipGroupUpgrade(t *testing.T) {
|
|||||||
c.ShipGroup(2).Destination = R1_Planet_1_num
|
c.ShipGroup(2).Destination = R1_Planet_1_num
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(UnknownRace, 1, "DRIVE", 0, 0),
|
g.ShipGroupUpgrade(UnknownRace, c.ShipGroup(0).ID, "DRIVE", 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputUnknownRace))
|
e.GenericErrorText(e.ErrInputUnknownRace))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_Extinct.Name, 1, "DRIVE", 0, 0),
|
g.ShipGroupUpgrade(Race_Extinct.Name, c.ShipGroup(0).ID, "DRIVE", 0, 0),
|
||||||
e.GenericErrorText(e.ErrRaceExinct))
|
e.GenericErrorText(e.ErrRaceExinct))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 555, "DRIVE", 0, 0),
|
g.ShipGroupUpgrade(Race_0.Name, uuid.New(), "DRIVE", 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotExists))
|
e.GenericErrorText(e.ErrInputEntityNotExists))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 2, "DRIVE", 0, 0),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(1).ID, "DRIVE", 0, 0),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 3, "DRIVE", 0, 0),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(2).ID, "DRIVE", 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputEntityNotOwned))
|
e.GenericErrorText(e.ErrInputEntityNotOwned))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 1, "GUN", 0, 0),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "GUN", 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputTechUnknown))
|
e.GenericErrorText(e.ErrInputTechUnknown))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 1, "CARGO", 0, 0),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "CARGO", 0, 0),
|
||||||
e.GenericErrorText(e.ErrInputUpgradeShipTechNotUsed))
|
e.GenericErrorText(e.ErrInputUpgradeShipTechNotUsed))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 1, "ALL", 0, 2.0),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "ALL", 0, 2.0),
|
||||||
e.GenericErrorText(e.ErrInputUpgradeParameterNotAllowed))
|
e.GenericErrorText(e.ErrInputUpgradeParameterNotAllowed))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 1, "DRIVE", 0, 2.0),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 0, 2.0),
|
||||||
e.GenericErrorText(e.ErrInputUpgradeTechLevelInsufficient))
|
e.GenericErrorText(e.ErrInputUpgradeTechLevelInsufficient))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 1, "DRIVE", 0, 1.1),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 0, 1.1),
|
||||||
e.GenericErrorText(e.ErrInputUpgradeShipsAlreadyUpToDate))
|
e.GenericErrorText(e.ErrInputUpgradeShipsAlreadyUpToDate))
|
||||||
|
|
||||||
c.RaceTechLevel(Race_0_idx, game.TechDrive, 10.0)
|
c.RaceTechLevel(Race_0_idx, game.TechDrive, 10.0)
|
||||||
assert.Equal(t, 10.0, c.Race(Race_0_idx).TechLevel(game.TechDrive))
|
assert.Equal(t, 10.0, c.Race(Race_0_idx).TechLevel(game.TechDrive))
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 1, "DRIVE", 0, 10.0),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 0, 10.0),
|
||||||
e.GenericErrorText(e.ErrUpgradeInsufficientResources))
|
e.GenericErrorText(e.ErrUpgradeInsufficientResources))
|
||||||
|
|
||||||
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, 1, "DRIVE", 2, 1.2))
|
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 2, 1.2))
|
||||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
|
||||||
assert.Equal(t, uint(8), c.ShipGroup(0).Number)
|
assert.Equal(t, uint(8), c.ShipGroup(0).Number)
|
||||||
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
|
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
|
||||||
@@ -169,6 +170,6 @@ func TestShipGroupUpgrade(t *testing.T) {
|
|||||||
assert.Equal(t, game.StateUpgrade, c.ShipGroup(3).State())
|
assert.Equal(t, game.StateUpgrade, c.ShipGroup(3).State())
|
||||||
|
|
||||||
assert.ErrorContains(t,
|
assert.ErrorContains(t,
|
||||||
g.ShipGroupUpgrade(Race_0.Name, 4, "DRIVE", 1, 1.3),
|
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(3).ID, "DRIVE", 1, 1.3),
|
||||||
e.GenericErrorText(e.ErrShipsBusy))
|
e.GenericErrorText(e.ErrShipsBusy))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,10 +105,10 @@ func (t Tech) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ShipGroup struct {
|
type ShipGroup struct {
|
||||||
Index uint `json:"index"` // FIXME: use UUID for Group Index (ordered)
|
ID uuid.UUID `json:"id"`
|
||||||
OwnerID uuid.UUID `json:"ownerId"` // Race link
|
OwnerID uuid.UUID `json:"ownerId"` // Race reference
|
||||||
TypeID uuid.UUID `json:"typeId"` // ShipType link
|
TypeID uuid.UUID `json:"typeId"` // ShipType reference
|
||||||
FleetID *uuid.UUID `json:"fleetId,omitempty"` // Fleet link
|
FleetID *uuid.UUID `json:"fleetId,omitempty"` // Fleet reference
|
||||||
Number uint `json:"number"` // Number (quantity) ships of specific ShipType
|
Number uint `json:"number"` // Number (quantity) ships of specific ShipType
|
||||||
CargoType *CargoType `json:"loadType,omitempty"` //
|
CargoType *CargoType `json:"loadType,omitempty"` //
|
||||||
Load Float `json:"load"` // Cargo loaded - "Масса груза"
|
Load Float `json:"load"` // Cargo loaded - "Масса груза"
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ func TestShipGroupEqual(t *testing.T) {
|
|||||||
mat := game.CargoMaterial
|
mat := game.CargoMaterial
|
||||||
cap := game.CargoCapital
|
cap := game.CargoCapital
|
||||||
left := &game.ShipGroup{
|
left := &game.ShipGroup{
|
||||||
Index: 1,
|
ID: uuid.New(),
|
||||||
Number: 1,
|
Number: 1,
|
||||||
|
|
||||||
OwnerID: uuid.New(),
|
OwnerID: uuid.New(),
|
||||||
@@ -241,7 +241,7 @@ func TestShipGroupEqual(t *testing.T) {
|
|||||||
// non-essential properties
|
// non-essential properties
|
||||||
right = *left
|
right = *left
|
||||||
|
|
||||||
left.Index = 2
|
left.ID = uuid.New()
|
||||||
assert.True(t, left.Equal(right))
|
assert.True(t, left.Equal(right))
|
||||||
|
|
||||||
// dirty hack to equalize loads
|
// dirty hack to equalize loads
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package report
|
package report
|
||||||
|
|
||||||
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
type ShipClass struct {
|
type ShipClass struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Drive Float `json:"drive"`
|
Drive Float `json:"drive"`
|
||||||
@@ -34,7 +36,7 @@ type IncomingGroup struct {
|
|||||||
|
|
||||||
type LocalGroup struct {
|
type LocalGroup struct {
|
||||||
OtherGroup
|
OtherGroup
|
||||||
Index uint `json:"index"`
|
ID uuid.UUID `json:"id"`
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
Fleet *string `json:"fleet"`
|
Fleet *string `json:"fleet"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package number
|
package number
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmp"
|
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,10 +20,3 @@ func fixed(num float64, precision int) float64 {
|
|||||||
func round(num float64) int {
|
func round(num float64) int {
|
||||||
return int(num + math.Copysign(0.5, num))
|
return int(num + math.Copysign(0.5, num))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Max[T cmp.Ordered](x, y T) T {
|
|
||||||
if cmp.Compare(x, y) == 1 {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -31,10 +31,3 @@ func TestFixed(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMax(t *testing.T) {
|
|
||||||
assert.Equal(t, 10., Max(9., 10.))
|
|
||||||
assert.Equal(t, 11., Max(11., 10.))
|
|
||||||
assert.Equal(t, 0, Max(-1, 0))
|
|
||||||
assert.Equal(t, 1, Max(1, 0))
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user