From 5697d0ad57576989c7408e04c289bcfdfe9f17fd Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Wed, 11 Feb 2026 09:46:24 +0200 Subject: [PATCH] refactor: duplicate identifier error --- internal/controller/fleet.go | 2 +- internal/controller/science.go | 2 +- internal/controller/science_test.go | 2 +- internal/controller/ship_class.go | 2 +- internal/controller/ship_class_test.go | 4 ++-- internal/controller/ship_group.go | 5 +++++ internal/controller/ship_group_test.go | 3 +++ internal/error/generic.go | 6 +++--- internal/error/input.go | 4 ++-- 9 files changed, 19 insertions(+), 11 deletions(-) diff --git a/internal/controller/fleet.go b/internal/controller/fleet.go index f4b571b..6163811 100644 --- a/internal/controller/fleet.go +++ b/internal/controller/fleet.go @@ -189,7 +189,7 @@ func (c *Cache) createFleet(ri int, name string) (int, error) { return 0, e.NewEntityTypeNameValidationError("%q", n) } if _, ok := c.fleetIndex(ri, n); ok { - return 0, e.NewEntityTypeNameDuplicateError("fleet %q", n) + return 0, e.NewEntityDuplicateIdentifierError("fleet %q", n) } fleets := slices.Clone(c.g.Fleets) fleets = append(fleets, game.Fleet{ diff --git a/internal/controller/science.go b/internal/controller/science.go index 013f53c..6e5d232 100644 --- a/internal/controller/science.go +++ b/internal/controller/science.go @@ -17,7 +17,7 @@ func (c *Cache) ScienceCreate(ri int, name string, drive, weapons, shileds, carg return e.NewEntityTypeNameValidationError("%q", n) } if sc := slices.IndexFunc(c.g.Race[ri].Sciences, func(s game.Science) bool { return s.Name == n }); sc >= 0 { - return e.NewEntityTypeNameDuplicateError("science %q", c.g.Race[ri].Sciences[sc].Name) + return e.NewEntityDuplicateIdentifierError("science %q", c.g.Race[ri].Sciences[sc].Name) } if drive < 0 { diff --git a/internal/controller/science_test.go b/internal/controller/science_test.go index 249b256..565995d 100644 --- a/internal/controller/science_test.go +++ b/internal/controller/science_test.go @@ -37,7 +37,7 @@ func TestScienceCreate(t *testing.T) { e.GenericErrorText(e.ErrInputEntityTypeNameInvalid)) assert.ErrorContains(t, g.ScienceCreate(Race_0.Name, first, 0.4, 0, 0.6, 0), - e.GenericErrorText(e.ErrInputEntityTypeNameDuplicate)) + e.GenericErrorText(e.ErrInputNewEntityDuplicateIdentifier)) assert.ErrorContains(t, g.ScienceCreate(Race_0.Name, second, -0.1, 0, 1.1, 0), e.GenericErrorText(e.ErrInputDriveValue)) diff --git a/internal/controller/ship_class.go b/internal/controller/ship_class.go index 0e595e3..a4af175 100644 --- a/internal/controller/ship_class.go +++ b/internal/controller/ship_class.go @@ -21,7 +21,7 @@ func (c *Cache) ShipClassCreate(ri int, typeName string, drive float64, ammo int return e.NewEntityTypeNameValidationError("%q", n) } if st := slices.IndexFunc(c.g.Race[ri].ShipTypes, func(st game.ShipType) bool { return st.Name == typeName }); st >= 0 { - return e.NewEntityTypeNameDuplicateError("ship type %q", c.g.Race[ri].ShipTypes[st].Name) + return e.NewEntityDuplicateIdentifierError("ship class %q", c.g.Race[ri].ShipTypes[st].Name) } c.g.Race[ri].ShipTypes = append(c.g.Race[ri].ShipTypes, game.ShipType{ ID: uuid.New(), diff --git a/internal/controller/ship_class_test.go b/internal/controller/ship_class_test.go index 07d4bad..15fcf06 100644 --- a/internal/controller/ship_class_test.go +++ b/internal/controller/ship_class_test.go @@ -24,7 +24,7 @@ func TestShipClassCreate(t *testing.T) { assert.ErrorContains(t, g.ShipClassCreate(Race_0.Name, Race_0_Gunship, 1, 0, 0, 0, 0), - e.GenericErrorText(e.ErrInputEntityTypeNameDuplicate)) + e.GenericErrorText(e.ErrInputNewEntityDuplicateIdentifier)) assert.ErrorContains(t, g.ShipClassCreate(UnknownRace, "Drone", 1, 0, 0, 0, 0), e.GenericErrorText(e.ErrInputUnknownRace)) @@ -80,7 +80,7 @@ func TestCreateShipTypeValidation(t *testing.T) { err := g.ShipClassCreate(race, tc.name+strconv.Itoa(i), tc.d, tc.a, tc.w, tc.s, tc.c) assert.NoError(t, err) err = g.ShipClassCreate(race, tc.name+strconv.Itoa(i), tc.d, tc.a, tc.w, tc.s, tc.c) - assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputEntityTypeNameDuplicate)) + assert.ErrorContains(t, err, e.GenericErrorText(e.ErrInputNewEntityDuplicateIdentifier)) } else { err := g.ShipClassCreate(race, tc.name, tc.d, tc.a, tc.w, tc.s, tc.c) assert.ErrorContains(t, err, tc.err) diff --git a/internal/controller/ship_group.go b/internal/controller/ship_group.go index da2ced6..10a1d35 100644 --- a/internal/controller/ship_group.go +++ b/internal/controller/ship_group.go @@ -383,6 +383,11 @@ func (c *Cache) ShipGroupBreak(ri int, groupID, newID uuid.UUID, quantity uint) if !ok { return e.NewEntityNotExistsError("group %s", groupID) } + for sgi := range c.g.ShipGroups { + if c.g.ShipGroups[sgi].ID == newID { + return e.NewEntityDuplicateIdentifierError("group %s", newID) + } + } if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit { return e.NewShipsBusyError() diff --git a/internal/controller/ship_group_test.go b/internal/controller/ship_group_test.go index 3db8d1b..0526a6f 100644 --- a/internal/controller/ship_group_test.go +++ b/internal/controller/ship_group_test.go @@ -116,6 +116,9 @@ func TestShipGroupBreak(t *testing.T) { assert.ErrorContains(t, g.ShipGroupBreak(Race_0.Name, uuid.New(), uuid.New(), 1), e.GenericErrorText(e.ErrInputEntityNotExists)) + assert.ErrorContains(t, + g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, c.ShipGroup(0).ID, 1), + e.GenericErrorText(e.ErrInputNewEntityDuplicateIdentifier)) assert.ErrorContains(t, g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, uuid.New(), 17), e.GenericErrorText(e.ErrBeakGroupNumberNotEnough)) diff --git a/internal/error/generic.go b/internal/error/generic.go index 8d01302..262d0e5 100644 --- a/internal/error/generic.go +++ b/internal/error/generic.go @@ -35,7 +35,7 @@ const ( ErrInputUnknownRelation ErrInputSameRace ErrInputEntityTypeNameInvalid - ErrInputEntityTypeNameDuplicate + ErrInputNewEntityDuplicateIdentifier ErrInputEntityTypeNameEquality ErrInputEntityNotExists ErrInputEntityNotOwned @@ -83,8 +83,8 @@ func GenericErrorText(code int) string { return "Race name must be different from your own" case ErrInputEntityTypeNameInvalid: return "Name has invalid length or symbols" - case ErrInputEntityTypeNameDuplicate: - return "Name already exists" + case ErrInputNewEntityDuplicateIdentifier: + return "Entity already exists" case ErrInputEntityTypeNameEquality: return "Names should differ" case ErrInputEntityNotExists: diff --git a/internal/error/input.go b/internal/error/input.go index f4a638a..6a0957d 100644 --- a/internal/error/input.go +++ b/internal/error/input.go @@ -16,8 +16,8 @@ func NewEntityTypeNameValidationError(arg ...any) error { return newGenericError(ErrInputEntityTypeNameInvalid, arg...) } -func NewEntityTypeNameDuplicateError(arg ...any) error { - return newGenericError(ErrInputEntityTypeNameDuplicate, arg...) +func NewEntityDuplicateIdentifierError(arg ...any) error { + return newGenericError(ErrInputNewEntityDuplicateIdentifier, arg...) } func NewEntityTypeNameEqualityError(arg ...any) error {