package game import ( "slices" "github.com/google/uuid" e "github.com/iliadenisov/galaxy/internal/error" ) type Science struct { ID uuid.UUID `json:"id"` ScienceReport } type ScienceReportForeign struct { RaceName string ScienceReport } type ScienceReport struct { Name string `json:"name"` Drive float64 `json:"drive"` Weapons float64 `json:"weapons"` Shields float64 `json:"shields"` Cargo float64 `json:"cargo"` } func (g Game) Sciences(raceName string) ([]Science, error) { ri, err := g.raceIndex(raceName) if err != nil { return nil, err } return g.sciencesInternal(ri), nil } func (g Game) sciencesInternal(ri int) []Science { return g.Race[ri].Sciences } func (g Game) DeleteScience(raceName, typeName string) error { ri, err := g.raceIndex(raceName) if err != nil { return err } return g.deleteScienceInternal(ri, typeName) } func (g Game) deleteScienceInternal(ri int, name string) error { sc := slices.IndexFunc(g.Race[ri].Sciences, func(s Science) bool { return s.Name == name }) if sc < 0 { return e.NewEntityNotExistsError("science %w", name) } if pl := slices.IndexFunc(g.Map.Planet, func(p Planet) bool { return p.Production.Type == ResearchScience && p.Production.SubjectID != nil && *p.Production.SubjectID == g.Race[ri].Sciences[sc].ID }); pl >= 0 { return e.NewDeleteSciencePlanetProductionError(g.Map.Planet[pl].Name) } g.Race[ri].Sciences = append(g.Race[ri].Sciences[:sc], g.Race[ri].Sciences[sc+1:]...) return nil } func (g Game) CreateScience(raceName, typeName string, d, w, s, c float64) error { ri, err := g.raceIndex(raceName) if err != nil { return err } return g.createScienceInternal(ri, typeName, d, w, s, c) } func (g Game) createScienceInternal(ri int, name string, d, w, s, c float64) error { n, ok := validateTypeName(name) if !ok { return e.NewEntityTypeNameValidationError("%q", n) } if sc := slices.IndexFunc(g.Race[ri].Sciences, func(s Science) bool { return s.Name == n }); sc >= 0 { return e.NewEntityTypeNameDuplicateError("science %w", g.Race[ri].Sciences[sc].Name) } if d < 0 { return e.NewDriveValueError(d) } if w < 0 { return e.NewWeaponsValueError(w) } if s < 0 { return e.NewShieldsValueError(s) } if c < 0 { return e.NewCargoValueError(c) } sum := d + w + s + c if sum != 1 { return e.NewScienceSumValuesError("D=%f W=%f S=%f C=%f sum=%f", d, w, s, c, sum) } g.Race[ri].Sciences = append(g.Race[ri].Sciences, Science{ ID: uuid.New(), ScienceReport: ScienceReport{ Name: n, Drive: d, Weapons: w, Shields: s, Cargo: c, }, }) return nil }