chore: refactor structure

This commit is contained in:
Ilia Denisov
2025-11-21 21:40:15 +03:00
parent 126f381b04
commit 269de2184c
72 changed files with 512 additions and 393 deletions
+128
View File
@@ -0,0 +1,128 @@
package game
import (
"slices"
"github.com/google/uuid"
e "github.com/iliadenisov/galaxy/internal/error"
)
type PlanetProduction string
const (
ProductionNone PlanetProduction = "-"
ProductionMaterial PlanetProduction = "MAT" // Сырьё
ProductionCapital PlanetProduction = "CAP" // Промышленность
ResearchDrive PlanetProduction = "DRIVE"
ResearchWeapons PlanetProduction = "WEAPONS"
ResearchShields PlanetProduction = "SHIELDS"
ResearchCargo PlanetProduction = "CARGO"
ResearchScience PlanetProduction = "SCIENCE"
ProductionShip PlanetProduction = "SHIP"
)
type ProductionType struct {
Production PlanetProduction `json:"type"`
SubjectID *uuid.UUID `json:"subjectId"`
Progress *float64 `json:"progress"`
}
func (p PlanetProduction) AsType(subject uuid.UUID) ProductionType {
switch p {
case ResearchScience, ProductionShip:
return ProductionType{Production: p, SubjectID: &subject}
default:
return ProductionType{Production: p, SubjectID: nil}
}
}
func (g Game) PlanetProduction(raceName string, planetNumber int, prodType, subject string) error {
ri, err := g.raceIndex(raceName)
if err != nil {
return err
}
var prod PlanetProduction
switch PlanetProduction(prodType) {
case ProductionMaterial:
prod = ProductionMaterial
case ProductionCapital:
prod = ProductionCapital
case ResearchDrive:
prod = ResearchDrive
case ResearchWeapons:
prod = ResearchWeapons
case ResearchShields:
prod = ResearchShields
case ResearchCargo:
prod = ResearchCargo
case ResearchScience:
prod = ResearchScience
case ProductionShip:
prod = ProductionShip
default:
return e.NewProductionInvalidError(prodType)
}
return g.planetProductionInternal(ri, planetNumber, prod, subject)
}
func (g Game) planetProductionInternal(ri int, number int, prod PlanetProduction, subj string) error {
if number < 0 {
return e.NewPlanetNumberError(number)
}
i := slices.IndexFunc(g.Map.Planet, func(p Planet) bool { return p.Number == uint(number) })
if i < 0 {
return e.NewEntityNotExistsError("planet #%d", number)
}
if g.Map.Planet[i].Owner != g.Race[ri].ID {
return e.NewEntityNotOwnedError("planet %#d", number)
}
g.Map.Planet[i].Production.Progress = nil
var subjectID *uuid.UUID
if (prod == ResearchScience || prod == ProductionShip) && subj == "" {
return e.NewEntityTypeNameValidationError("%s=%q", prod, subj)
}
if prod == ResearchScience {
i := slices.IndexFunc(g.Race[ri].Sciences, func(s Science) bool { return s.Name == subj })
if i < 0 {
return e.NewEntityNotExistsError("science %w", subj)
}
subjectID = &g.Race[ri].Sciences[i].ID
}
if prod == ProductionShip {
i := slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.Name == subj })
if i < 0 {
return e.NewEntityNotExistsError("ship type %w", subj)
}
if g.Map.Planet[i].Production.Production == ProductionShip &&
g.Map.Planet[i].Production.SubjectID != nil &&
*g.Map.Planet[i].Production.SubjectID == g.Race[ri].ShipTypes[i].ID {
// Planet already produces this ship type, keeping progress intact
return nil
}
subjectID = &g.Race[ri].ShipTypes[i].ID
var progress float64 = 0.
g.Map.Planet[i].Production.Progress = &progress
}
if g.Map.Planet[i].Production.Production == ProductionShip {
if g.Map.Planet[i].Production.SubjectID == nil {
return e.NewGameStateError("planet #%d produces ship but SubjectID is empty", g.Map.Planet[i].Number)
}
s := *g.Map.Planet[i].Production.SubjectID
if g.Map.Planet[i].Production.Progress == nil {
return e.NewGameStateError("planet #%d produces ship but Progress is empty", g.Map.Planet[i].Number)
}
progress := *g.Map.Planet[i].Production.Progress
i := slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.ID == s })
if i < 0 {
return e.NewGameStateError("planet #%d produces ship but ShipType was not found for race %s", g.Map.Planet[i].Number, g.Race[ri].Name)
}
mat, _ := g.Race[ri].ShipTypes[i].ProductionCost()
extra := mat * progress
g.Map.Planet[i].Material += extra
}
g.Map.Planet[i].Production.Production = prod
g.Map.Planet[i].Production.SubjectID = subjectID
return nil
}