262 lines
5.8 KiB
Go
262 lines
5.8 KiB
Go
package fights
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"dk/internal/database"
|
|
)
|
|
|
|
// Fight represents a fight, past or present
|
|
type Fight struct {
|
|
ID int
|
|
UserID int
|
|
MonsterID int
|
|
MonsterHP int
|
|
MonsterMaxHP int
|
|
MonsterSleep int
|
|
MonsterImmune int
|
|
UberDamage int
|
|
UberDefense int
|
|
FirstStrike bool
|
|
Turn int
|
|
RanAway bool
|
|
Victory bool
|
|
Won bool
|
|
RewardGold int
|
|
RewardExp int
|
|
Created int64
|
|
Updated int64
|
|
}
|
|
|
|
// New creates a new Fight with sensible defaults
|
|
func New(userID, monsterID int) *Fight {
|
|
now := time.Now().Unix()
|
|
return &Fight{
|
|
UserID: userID,
|
|
MonsterID: monsterID,
|
|
MonsterHP: 0,
|
|
MonsterMaxHP: 0,
|
|
MonsterSleep: 0,
|
|
MonsterImmune: 0,
|
|
UberDamage: 0,
|
|
UberDefense: 0,
|
|
FirstStrike: false,
|
|
Turn: 0,
|
|
RanAway: false,
|
|
Victory: false,
|
|
Won: false,
|
|
RewardGold: 0,
|
|
RewardExp: 0,
|
|
Created: now,
|
|
Updated: now,
|
|
}
|
|
}
|
|
|
|
// Validate checks if fight has valid values
|
|
func (f *Fight) Validate() error {
|
|
if f.UserID <= 0 {
|
|
return fmt.Errorf("fight UserID must be positive")
|
|
}
|
|
if f.MonsterID <= 0 {
|
|
return fmt.Errorf("fight MonsterID must be positive")
|
|
}
|
|
if f.Turn < 0 {
|
|
return fmt.Errorf("fight Turn cannot be negative")
|
|
}
|
|
if f.MonsterHP < 0 {
|
|
return fmt.Errorf("fight MonsterHP cannot be negative")
|
|
}
|
|
if f.Created <= 0 {
|
|
return fmt.Errorf("fight Created timestamp must be positive")
|
|
}
|
|
if f.Updated <= 0 {
|
|
return fmt.Errorf("fight Updated timestamp must be positive")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CRUD operations
|
|
func (f *Fight) Delete() error {
|
|
return database.Exec("DELETE FROM fights WHERE id = %d", f.ID)
|
|
}
|
|
|
|
func (f *Fight) Insert() error {
|
|
f.Updated = time.Now().Unix()
|
|
id, err := database.Insert("fights", f, "ID")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
f.ID = int(id)
|
|
return nil
|
|
}
|
|
|
|
func (f *Fight) Update() error {
|
|
f.Updated = time.Now().Unix()
|
|
return database.Update("fights", map[string]any{
|
|
"user_id": f.UserID,
|
|
"monster_id": f.MonsterID,
|
|
"monster_hp": f.MonsterHP,
|
|
"monster_max_hp": f.MonsterMaxHP,
|
|
"monster_sleep": f.MonsterSleep,
|
|
"monster_immune": f.MonsterImmune,
|
|
"uber_damage": f.UberDamage,
|
|
"uber_defense": f.UberDefense,
|
|
"first_strike": f.FirstStrike,
|
|
"turn": f.Turn,
|
|
"ran_away": f.RanAway,
|
|
"victory": f.Victory,
|
|
"won": f.Won,
|
|
"reward_gold": f.RewardGold,
|
|
"reward_exp": f.RewardExp,
|
|
"created": f.Created,
|
|
"updated": f.Updated,
|
|
}, "id", f.ID)
|
|
}
|
|
|
|
// Query functions
|
|
func Find(id int) (*Fight, error) {
|
|
var fight Fight
|
|
err := database.Get(&fight, "SELECT * FROM fights WHERE id = %d", id)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fight with ID %d not found", id)
|
|
}
|
|
return &fight, nil
|
|
}
|
|
|
|
func All() ([]*Fight, error) {
|
|
var fights []*Fight
|
|
err := database.Select(&fights, "SELECT * FROM fights ORDER BY created DESC, id DESC")
|
|
return fights, err
|
|
}
|
|
|
|
func ByUserID(userID int) ([]*Fight, error) {
|
|
var fights []*Fight
|
|
err := database.Select(&fights, "SELECT * FROM fights WHERE user_id = %d ORDER BY created DESC, id DESC", userID)
|
|
return fights, err
|
|
}
|
|
|
|
func ByMonsterID(monsterID int) ([]*Fight, error) {
|
|
var fights []*Fight
|
|
err := database.Select(&fights, "SELECT * FROM fights WHERE monster_id = %d ORDER BY created DESC, id DESC", monsterID)
|
|
return fights, err
|
|
}
|
|
|
|
func ActiveByUserID(userID int) ([]*Fight, error) {
|
|
var fights []*Fight
|
|
err := database.Select(&fights, "SELECT * FROM fights WHERE user_id = %d AND ran_away = 0 AND victory = 0 ORDER BY created DESC, id DESC", userID)
|
|
return fights, err
|
|
}
|
|
|
|
func Active() ([]*Fight, error) {
|
|
var fights []*Fight
|
|
err := database.Select(&fights, "SELECT * FROM fights WHERE ran_away = 0 AND victory = 0 ORDER BY created DESC, id DESC")
|
|
return fights, err
|
|
}
|
|
|
|
func Recent(within time.Duration) ([]*Fight, error) {
|
|
cutoff := time.Now().Add(-within).Unix()
|
|
var fights []*Fight
|
|
err := database.Select(&fights, "SELECT * FROM fights WHERE created >= %d ORDER BY created DESC, id DESC", cutoff)
|
|
return fights, err
|
|
}
|
|
|
|
// Helper methods
|
|
func (f *Fight) CreatedTime() time.Time {
|
|
return time.Unix(f.Created, 0)
|
|
}
|
|
|
|
func (f *Fight) UpdatedTime() time.Time {
|
|
return time.Unix(f.Updated, 0)
|
|
}
|
|
|
|
func (f *Fight) IsActive() bool {
|
|
return !f.RanAway && !f.Victory
|
|
}
|
|
|
|
func (f *Fight) IsComplete() bool {
|
|
return f.RanAway || f.Victory
|
|
}
|
|
|
|
func (f *Fight) GetStatus() string {
|
|
if f.Won {
|
|
return "Won"
|
|
}
|
|
if f.Victory && !f.Won {
|
|
return "Lost"
|
|
}
|
|
if f.RanAway {
|
|
return "Ran Away"
|
|
}
|
|
return "Active"
|
|
}
|
|
|
|
func (f *Fight) GetMonsterHealthPercent() float64 {
|
|
if f.MonsterMaxHP <= 0 {
|
|
return 0.0
|
|
}
|
|
return float64(f.MonsterHP) / float64(f.MonsterMaxHP) * 100.0
|
|
}
|
|
|
|
func (f *Fight) IsMonsterSleeping() bool {
|
|
return f.MonsterSleep > 0
|
|
}
|
|
|
|
func (f *Fight) IsMonsterImmune() bool {
|
|
return f.MonsterImmune > 0
|
|
}
|
|
|
|
func (f *Fight) HasUberBonus() bool {
|
|
return f.UberDamage > 0 || f.UberDefense > 0
|
|
}
|
|
|
|
func (f *Fight) GetDuration() time.Duration {
|
|
return time.Unix(f.Updated, 0).Sub(time.Unix(f.Created, 0))
|
|
}
|
|
|
|
func (f *Fight) EndFight(victory bool) {
|
|
f.Victory = victory
|
|
f.RanAway = !victory
|
|
f.Updated = time.Now().Unix()
|
|
}
|
|
|
|
func (f *Fight) WinFight(goldReward, expReward int) {
|
|
f.Victory = true
|
|
f.Won = true
|
|
f.RanAway = false
|
|
f.RewardGold = goldReward
|
|
f.RewardExp = expReward
|
|
f.Updated = time.Now().Unix()
|
|
}
|
|
|
|
func (f *Fight) LoseFight() {
|
|
f.Victory = true
|
|
f.Won = false
|
|
f.RanAway = false
|
|
f.Updated = time.Now().Unix()
|
|
}
|
|
|
|
func (f *Fight) RunAway() {
|
|
f.RanAway = true
|
|
f.Victory = false
|
|
f.Updated = time.Now().Unix()
|
|
}
|
|
|
|
func (f *Fight) IncrementTurn() {
|
|
f.Turn++
|
|
f.Updated = time.Now().Unix()
|
|
}
|
|
|
|
func (f *Fight) SetMonsterHP(hp int) {
|
|
f.MonsterHP = hp
|
|
f.Updated = time.Now().Unix()
|
|
}
|
|
|
|
func (f *Fight) DamageMonster(damage int) {
|
|
f.MonsterHP -= damage
|
|
if f.MonsterHP < 0 {
|
|
f.MonsterHP = 0
|
|
}
|
|
f.Updated = time.Now().Unix()
|
|
}
|