package controller import ( "fmt" "slices" "github.com/google/uuid" "github.com/iliadenisov/galaxy/internal/model/game" ) type Cache struct { g *game.Game cacheRaceIndexByID map[uuid.UUID]int cacheFleetIndexByID map[uuid.UUID]int cacheRaceIndexByShipGroupIndex map[int]int cacheShipClassByShipGroupIndex map[int]*game.ShipType cachePlanetByPlanetNumber map[uint]*game.Planet cacheRelation map[int]map[int]game.Relation } func NewCache(g *game.Game) *Cache { if g == nil { panic("NewCache: nil Game passed") } c := &Cache{ g: g, } return c } func (c *Cache) ShipGroupShipClass(groupIndex int) *game.ShipType { if len(c.cacheShipClassByShipGroupIndex) == 0 { c.cacheShipsAndGroups() } c.validateShipGroupIndex(groupIndex) if v, ok := c.cacheShipClassByShipGroupIndex[groupIndex]; ok { return v } else { panic(fmt.Sprintf("ShipClassByShipGroupIndex: group not found by index=%v", groupIndex)) } } func (c *Cache) RaceIndex(ID uuid.UUID) int { if c.cacheRaceIndexByID == nil { c.cacheRaceIndexByID = make(map[uuid.UUID]int) for i := range c.g.Race { c.cacheRaceIndexByID[c.g.Race[i].ID] = i } } if v, ok := c.cacheRaceIndexByID[ID]; ok { return v } else { panic(fmt.Sprintf("RaceIndex: race not found by ID=%v", ID)) } } func (c *Cache) cacheShipsAndGroups() { if c.cacheRaceIndexByShipGroupIndex != nil { clear(c.cacheRaceIndexByShipGroupIndex) } else { c.cacheRaceIndexByShipGroupIndex = make(map[int]int) } if c.cacheShipClassByShipGroupIndex != nil { clear(c.cacheShipClassByShipGroupIndex) } else { c.cacheShipClassByShipGroupIndex = make(map[int]*game.ShipType) } for groupIndex := range c.g.ShipGroups { ri := c.RaceIndex(c.g.ShipGroups[groupIndex].OwnerID) c.cacheRaceIndexByShipGroupIndex[groupIndex] = ri sti, ok := ShipClassIndex(c.g, ri, c.g.ShipGroups[groupIndex].TypeID) 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)) } c.cacheShipClassByShipGroupIndex[groupIndex] = &c.g.Race[ri].ShipTypes[sti] } } func (c *Cache) invalidateShipGroupCache() { clear(c.cacheRaceIndexByShipGroupIndex) clear(c.cacheShipClassByShipGroupIndex) } func (c *Cache) invalidateFleetCache() { clear(c.cacheFleetIndexByID) } // Helpers func ShipClassIndex(g *game.Game, ri int, classID uuid.UUID) (int, bool) { if len(g.Race) < ri+1 { panic(fmt.Sprintf("ShipClass: game race index %d invalid: len=%d", ri, len(g.Race))) } sti := slices.IndexFunc(g.Race[ri].ShipTypes, func(st game.ShipType) bool { return st.ID == classID }) return sti, sti >= 0 }