package spells import ( "dk/internal/store" "fmt" "strings" ) // Spell represents a spell in the game type Spell struct { ID int `json:"id"` Name string `json:"name"` MP int `json:"mp"` Attribute int `json:"attribute"` Type int `json:"type"` } func (s *Spell) Save() error { return GetStore().UpdateWithRebuild(s.ID, s) } func (s *Spell) Delete() error { GetStore().RemoveWithRebuild(s.ID) return nil } // Creates a new Spell with sensible defaults func New() *Spell { return &Spell{ Name: "", MP: 5, // Default MP cost Attribute: 10, // Default attribute value Type: TypeHealing, // Default to healing spell } } // Validate checks if spell has valid values func (s *Spell) Validate() error { if s.Name == "" { return fmt.Errorf("spell name cannot be empty") } if s.MP < 0 { return fmt.Errorf("spell MP cannot be negative") } if s.Attribute < 0 { return fmt.Errorf("spell Attribute cannot be negative") } if s.Type < TypeHealing || s.Type > TypeDefenseBoost { return fmt.Errorf("invalid spell type: %d", s.Type) } return nil } // SpellType constants for spell types const ( TypeHealing = 1 TypeHurt = 2 TypeSleep = 3 TypeAttackBoost = 4 TypeDefenseBoost = 5 ) // SpellStore with enhanced BaseStore type SpellStore struct { *store.BaseStore[Spell] } // Global store with singleton pattern var GetStore = store.NewSingleton(func() *SpellStore { ss := &SpellStore{BaseStore: store.NewBaseStore[Spell]()} // Register indices ss.RegisterIndex("byType", store.BuildIntGroupIndex(func(s *Spell) int { return s.Type })) ss.RegisterIndex("byName", store.BuildCaseInsensitiveLookupIndex(func(s *Spell) string { return s.Name })) ss.RegisterIndex("byMP", store.BuildIntGroupIndex(func(s *Spell) int { return s.MP })) ss.RegisterIndex("allByTypeMP", store.BuildSortedListIndex(func(a, b *Spell) bool { if a.Type != b.Type { return a.Type < b.Type } if a.MP != b.MP { return a.MP < b.MP } return a.ID < b.ID })) return ss }) // Enhanced CRUD operations func (ss *SpellStore) AddSpell(spell *Spell) error { return ss.AddWithRebuild(spell.ID, spell) } func (ss *SpellStore) RemoveSpell(id int) { ss.RemoveWithRebuild(id) } func (ss *SpellStore) UpdateSpell(spell *Spell) error { return ss.UpdateWithRebuild(spell.ID, spell) } // Data persistence func LoadData(dataPath string) error { ss := GetStore() return ss.BaseStore.LoadData(dataPath) } func SaveData(dataPath string) error { ss := GetStore() return ss.BaseStore.SaveData(dataPath) } // Query functions using enhanced store func Find(id int) (*Spell, error) { ss := GetStore() spell, exists := ss.Find(id) if !exists { return nil, fmt.Errorf("spell with ID %d not found", id) } return spell, nil } func All() ([]*Spell, error) { ss := GetStore() return ss.AllSorted("allByTypeMP"), nil } func ByType(spellType int) ([]*Spell, error) { ss := GetStore() return ss.GroupByIndex("byType", spellType), nil } func ByMaxMP(maxMP int) ([]*Spell, error) { ss := GetStore() return ss.FilterByIndex("allByTypeMP", func(s *Spell) bool { return s.MP <= maxMP }), nil } func ByTypeAndMaxMP(spellType, maxMP int) ([]*Spell, error) { ss := GetStore() return ss.FilterByIndex("allByTypeMP", func(s *Spell) bool { return s.Type == spellType && s.MP <= maxMP }), nil } func ByName(name string) (*Spell, error) { ss := GetStore() spell, exists := ss.LookupByIndex("byName", strings.ToLower(name)) if !exists { return nil, fmt.Errorf("spell with name '%s' not found", name) } return spell, nil } // Insert with ID assignment func (s *Spell) Insert() error { ss := GetStore() if s.ID == 0 { s.ID = ss.GetNextID() } return ss.AddSpell(s) } // Helper methods func (s *Spell) IsHealing() bool { return s.Type == TypeHealing } func (s *Spell) IsHurt() bool { return s.Type == TypeHurt } func (s *Spell) IsSleep() bool { return s.Type == TypeSleep } func (s *Spell) IsAttackBoost() bool { return s.Type == TypeAttackBoost } func (s *Spell) IsDefenseBoost() bool { return s.Type == TypeDefenseBoost } func (s *Spell) TypeName() string { switch s.Type { case TypeHealing: return "Healing" case TypeHurt: return "Hurt" case TypeSleep: return "Sleep" case TypeAttackBoost: return "Attack Boost" case TypeDefenseBoost: return "Defense Boost" default: return "Unknown" } } func (s *Spell) CanCast(availableMP int) bool { return availableMP >= s.MP } func (s *Spell) Efficiency() float64 { if s.MP == 0 { return 0 } return float64(s.Attribute) / float64(s.MP) } func (s *Spell) IsOffensive() bool { return s.Type == TypeHurt || s.Type == TypeSleep } func (s *Spell) IsSupport() bool { return s.Type == TypeHealing || s.Type == TypeAttackBoost || s.Type == TypeDefenseBoost }