package fightlogs import ( "fmt" "strings" "time" "dk/internal/database" ) // FightLog represents a single action in a fight type FightLog struct { ID int FightID int Type int Data int Name string Created int64 } // Action type constants const ( ActionAttackHit = 1 ActionAttackMiss = 2 ActionSpellHeal = 3 ActionSpellHurt = 4 ActionRunSuccess = 5 ActionRunFail = 6 ActionGeneric = 7 ActionMonsterAttack = 8 ActionMonsterMiss = 9 ActionMonsterSpell = 10 ActionMonsterDeath = 11 ) // New creates a new FightLog with sensible defaults func New(fightID int) *FightLog { return &FightLog{ FightID: fightID, Type: ActionGeneric, Data: 0, Name: "", Created: time.Now().Unix(), } } // Validate checks if fight log has valid values func (fl *FightLog) Validate() error { if fl.FightID <= 0 { return fmt.Errorf("fight log FightID must be positive") } if fl.Created <= 0 { return fmt.Errorf("fight log Created timestamp must be positive") } return nil } // CRUD operations func (fl *FightLog) Delete() error { return database.Exec("DELETE FROM fight_logs WHERE id = %d", fl.ID) } func (fl *FightLog) Insert() error { id, err := database.Insert("fight_logs", fl, "ID") if err != nil { return err } fl.ID = int(id) return nil } // Query functions func Find(id int) (*FightLog, error) { var log FightLog err := database.Get(&log, "SELECT * FROM fight_logs WHERE id = %d", id) if err != nil { return nil, fmt.Errorf("fight log with ID %d not found", id) } return &log, nil } func ByFightID(fightID int) ([]*FightLog, error) { var logs []*FightLog err := database.Select(&logs, "SELECT * FROM fight_logs WHERE fight_id = %d ORDER BY created ASC, id ASC", fightID) return logs, err } func DeleteByFightID(fightID int) error { return database.Exec("DELETE FROM fight_logs WHERE fight_id = %d", fightID) } // Helper functions for adding different types of actions func AddAction(fightID int, action string) error { log := &FightLog{ FightID: fightID, Type: ActionGeneric, Name: action, Created: time.Now().Unix(), } return log.Insert() } func AddAttackHit(fightID, damage int) error { log := &FightLog{ FightID: fightID, Type: ActionAttackHit, Data: damage, Created: time.Now().Unix(), } return log.Insert() } func AddAttackMiss(fightID int) error { log := &FightLog{ FightID: fightID, Type: ActionAttackMiss, Created: time.Now().Unix(), } return log.Insert() } func AddSpellHeal(fightID int, spellName string, healAmount int) error { log := &FightLog{ FightID: fightID, Type: ActionSpellHeal, Data: healAmount, Name: spellName, Created: time.Now().Unix(), } return log.Insert() } func AddSpellHurt(fightID int, spellName string, damage int) error { log := &FightLog{ FightID: fightID, Type: ActionSpellHurt, Data: damage, Name: spellName, Created: time.Now().Unix(), } return log.Insert() } func AddRunSuccess(fightID int) error { log := &FightLog{ FightID: fightID, Type: ActionRunSuccess, Created: time.Now().Unix(), } return log.Insert() } func AddRunFail(fightID int) error { log := &FightLog{ FightID: fightID, Type: ActionRunFail, Created: time.Now().Unix(), } return log.Insert() } func AddMonsterAttack(fightID int, monsterName string, damage int) error { log := &FightLog{ FightID: fightID, Type: ActionMonsterAttack, Data: damage, Name: monsterName, Created: time.Now().Unix(), } return log.Insert() } func AddMonsterMiss(fightID int, monsterName string) error { log := &FightLog{ FightID: fightID, Type: ActionMonsterMiss, Name: monsterName, Created: time.Now().Unix(), } return log.Insert() } func AddMonsterSpell(fightID int, monsterName, spellName string, damage int) error { log := &FightLog{ FightID: fightID, Type: ActionMonsterSpell, Data: damage, Name: monsterName + "|" + spellName, Created: time.Now().Unix(), } return log.Insert() } func AddMonsterDeath(fightID int, monsterName string) error { log := &FightLog{ FightID: fightID, Type: ActionMonsterDeath, Name: monsterName, Created: time.Now().Unix(), } return log.Insert() } // Convert logs to human-readable strings func GetActions(fightID int) ([]string, error) { logs, err := ByFightID(fightID) if err != nil { return nil, err } result := make([]string, len(logs)) for i, log := range logs { result[i] = log.ToString() } return result, nil } func GetLastAction(fightID int) (string, error) { var log FightLog err := database.Get(&log, "SELECT * FROM fight_logs WHERE fight_id = %d ORDER BY created DESC, id DESC LIMIT 1", fightID) if err != nil { return "", nil // No logs found } return log.ToString(), nil } // Helper methods func (fl *FightLog) CreatedTime() time.Time { return time.Unix(fl.Created, 0) } func (fl *FightLog) ToString() string { switch fl.Type { case ActionAttackHit: return fmt.Sprintf("You attacked for %d damage!", fl.Data) case ActionAttackMiss: return "You missed your attack!" case ActionSpellHeal: return fmt.Sprintf("You cast %s and healed %d HP!", fl.Name, fl.Data) case ActionSpellHurt: return fmt.Sprintf("You cast %s and dealt %d damage!", fl.Name, fl.Data) case ActionRunSuccess: return "You successfully ran away!" case ActionRunFail: return "You failed to run away!" case ActionGeneric: return fl.Name case ActionMonsterAttack: return fmt.Sprintf("%s attacks for %d damage!", fl.Name, fl.Data) case ActionMonsterMiss: return fmt.Sprintf("%s missed its attack!", fl.Name) case ActionMonsterSpell: parts := strings.Split(fl.Name, "|") if len(parts) == 2 { return fmt.Sprintf("%s casts %s for %d damage!", parts[0], parts[1], fl.Data) } return fmt.Sprintf("%s casts a spell for %d damage!", fl.Name, fl.Data) case ActionMonsterDeath: return fmt.Sprintf("%s has been defeated!", fl.Name) default: return "Unknown action" } }