Files

303 lines
11 KiB
Go
Raw Permalink Normal View History

2025-08-08 06:39:46 +02:00
package models
import (
"bamort/database"
2025-08-08 22:37:55 +02:00
"bamort/user"
2025-08-08 06:39:46 +02:00
"encoding/json"
"time"
"gorm.io/gorm"
)
// CharacterCreationSession speichert den Fortschritt der Charakter-Erstellung
type CharacterCreationSession struct {
2025-08-10 22:26:07 +02:00
ID string `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
2025-08-26 21:39:19 +02:00
User user.User `json:"user" gorm:"foreignKey:UserID;references:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
2025-08-10 22:26:07 +02:00
Name string `json:"name"`
2025-08-13 23:47:27 +02:00
Geschlecht string `json:"geschlecht"`
2025-08-10 22:26:07 +02:00
Rasse string `json:"rasse"`
Typ string `json:"typ"`
Herkunft string `json:"herkunft"`
2025-08-13 23:47:27 +02:00
Stand string `json:"stand"`
2025-08-10 22:26:07 +02:00
Glaube string `json:"glaube"`
Attributes AttributesData `json:"attributes" gorm:"type:text;serializer:json"`
DerivedValues DerivedValuesData `json:"derived_values" gorm:"type:text;serializer:json"`
Skills CharacterCreationSkills `json:"skills" gorm:"type:text;serializer:json"`
Spells CharacterCreationSpells `json:"spells" gorm:"type:text;serializer:json"`
SkillPoints SkillPointsData `json:"skill_points" gorm:"type:text;serializer:json"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ExpiresAt time.Time `json:"expires_at"`
CurrentStep int `json:"current_step"` // 1=Basic, 2=Attributes, 3=Derived, 4=Skills
2025-08-08 06:39:46 +02:00
}
// AttributesData speichert die Grundwerte
type AttributesData struct {
ST int `json:"st"` // Stärke
GS int `json:"gs"` // Geschicklichkeit
GW int `json:"gw"` // Gewandtheit
KO int `json:"ko"` // Konstitution
IN int `json:"in"` // Intelligenz
ZT int `json:"zt"` // Zaubertalent
AU int `json:"au"` // Ausstrahlung
}
// DerivedValuesData speichert die abgeleiteten Werte
type DerivedValuesData struct {
2025-08-13 23:47:27 +02:00
PA int `json:"pa"` // Persönliche Ausstrahlung
WK int `json:"wk"` // Willenskraft
LPMax int `json:"lp_max"` // Lebenspunkte Maximum
APMax int `json:"ap_max"` // Abenteuerpunkte Maximum
BMax int `json:"b_max"` // Belastung Maximum
ResistenzKoerper int `json:"resistenz_koerper"` // Resistenz Körper
ResistenzGeist int `json:"resistenz_geist"` // Resistenz Geist
ResistenzBonusKoerper int `json:"resistenz_bonus_koerper"` // Resistenz Bonus Körper
ResistenzBonusGeist int `json:"resistenz_bonus_geist"` // Resistenz Bonus Geist
Abwehr int `json:"abwehr"` // Abwehr
AbwehrBonus int `json:"abwehr_bonus"` // Abwehr Bonus
AusdauerBonus int `json:"ausdauer_bonus"` // Ausdauer Bonus
AngriffsBonus int `json:"angriffs_bonus"` // Angriffs Bonus
Zaubern int `json:"zaubern"` // Zaubern
ZauberBonus int `json:"zauber_bonus"` // Zauber Bonus
Raufen int `json:"raufen"` // Raufen
SchadensBonus int `json:"schadens_bonus"` // Schadens Bonus
SG int `json:"sg"` // Schicksalsgunst
GG int `json:"gg"` // Göttliche Gnade
GP int `json:"gp"` // Glückspunkte
2025-08-08 06:39:46 +02:00
}
// SkillPointsData speichert die verbleibenden Lernpunkte pro Kategorie
type SkillPointsData map[string]int
// CharacterCreationSkill repräsentiert eine ausgewählte Fertigkeit
type CharacterCreationSkill struct {
Name string `json:"name"`
Level int `json:"level"`
Category string `json:"category"`
Cost int `json:"cost"`
}
// CharacterCreationSpell repräsentiert einen ausgewählten Zauber
type CharacterCreationSpell struct {
Name string `json:"name"`
Cost int `json:"cost"`
}
2025-08-10 22:26:07 +02:00
// Slice types for GORM JSON handling
type CharacterCreationSkills []CharacterCreationSkill
type CharacterCreationSpells []CharacterCreationSpell
// ClassCategoryLearningPoints stores the learning points distribution for a character class
type ClassCategoryLearningPoints struct {
ID uint `gorm:"primaryKey" json:"id"`
CharacterClassID uint `gorm:"uniqueIndex:idx_class_category;not null" json:"character_class_id"`
SkillCategoryID uint `gorm:"uniqueIndex:idx_class_category;not null" json:"skill_category_id"`
Points int `gorm:"not null;default:0" json:"points"`
CharacterClass CharacterClass `gorm:"foreignKey:CharacterClassID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"character_class"`
SkillCategory SkillCategory `gorm:"foreignKey:SkillCategoryID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"skill_category"`
}
// ClassSpellPoints stores the spell learning points for a character class
type ClassSpellPoints struct {
ID uint `gorm:"primaryKey" json:"id"`
CharacterClassID uint `gorm:"uniqueIndex;not null" json:"character_class_id"`
SpellPoints int `gorm:"not null;default:0" json:"spell_points"` // Zauberlerneinheiten
CharacterClass CharacterClass `gorm:"foreignKey:CharacterClassID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"character_class"`
}
// ClassTypicalSkill stores typical skills for a character class with bonuses
type ClassTypicalSkill struct {
ID uint `gorm:"primaryKey" json:"id"`
CharacterClassID uint `gorm:"not null;index" json:"character_class_id"`
SkillID uint `gorm:"not null;index" json:"skill_id"`
Bonus int `gorm:"not null;default:0" json:"bonus"`
Attribute string `gorm:"size:10" json:"attribute,omitempty"` // z.B. "Gs", "In", "St"
Notes string `json:"notes,omitempty"` // Zusätzliche Notizen
CharacterClass CharacterClass `gorm:"foreignKey:CharacterClassID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"character_class"`
Skill Skill `gorm:"foreignKey:SkillID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"skill"`
}
// ClassTypicalSpell stores typical spells for a character class
type ClassTypicalSpell struct {
ID uint `gorm:"primaryKey" json:"id"`
CharacterClassID uint `gorm:"not null;index" json:"character_class_id"`
SpellID uint `gorm:"not null;index" json:"spell_id"`
Notes string `json:"notes,omitempty"` // z.B. "beliebig außer Dweomer"
CharacterClass CharacterClass `gorm:"foreignKey:CharacterClassID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"character_class"`
Spell Spell `gorm:"foreignKey:SpellID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"spell"`
}
// TableName specifies the table name for ClassLearningPoints
func (ClassCategoryLearningPoints) TableName() string {
//class_learning_points
return "gsm_cc_class_category_points"
}
// TableName specifies the table name for ClassSpellPoints
func (ClassSpellPoints) TableName() string {
//class_spell_points
return "gsm_cc_class_spell_points"
}
// TableName specifies the table name for ClassTypicalSkill
func (ClassTypicalSkill) TableName() string {
//class_typical_skills
return "gsm_cc_class_typical_skills"
}
// TableName specifies the table name for ClassTypicalSpell
func (ClassTypicalSpell) TableName() string {
//class_typical_spells
return "gsm_cc_class_typical_spells"
}
2025-08-10 22:26:07 +02:00
// JSON scanning methods for Skills slice
func (s *CharacterCreationSkills) Scan(value interface{}) error {
if value == nil {
*s = make([]CharacterCreationSkill, 0)
return nil
}
bytes, ok := value.([]byte)
if !ok {
*s = make([]CharacterCreationSkill, 0)
return nil
}
return json.Unmarshal(bytes, s)
}
func (s CharacterCreationSkills) Value() (interface{}, error) {
if len(s) == 0 {
return "[]", nil
}
return json.Marshal(s)
}
// JSON scanning methods for Spells slice
func (sp *CharacterCreationSpells) Scan(value interface{}) error {
if value == nil {
*sp = make([]CharacterCreationSpell, 0)
return nil
}
bytes, ok := value.([]byte)
if !ok {
*sp = make([]CharacterCreationSpell, 0)
return nil
}
return json.Unmarshal(bytes, sp)
}
func (sp CharacterCreationSpells) Value() (interface{}, error) {
if len(sp) == 0 {
return "[]", nil
}
return json.Marshal(sp)
}
2025-08-10 06:53:03 +02:00
func (object *CharacterCreationSession) TableName() string {
dbPrefix := "char"
return dbPrefix + "_" + "char_creation_session"
}
2025-08-08 06:39:46 +02:00
// Scanning methods for JSON fields in GORM
func (a *AttributesData) Scan(value interface{}) error {
if value == nil {
return nil
}
bytes, ok := value.([]byte)
if !ok {
return nil
}
return json.Unmarshal(bytes, a)
}
func (a AttributesData) Value() (interface{}, error) {
return json.Marshal(a)
}
func (d *DerivedValuesData) Scan(value interface{}) error {
if value == nil {
return nil
}
bytes, ok := value.([]byte)
if !ok {
return nil
}
return json.Unmarshal(bytes, d)
}
func (d DerivedValuesData) Value() (interface{}, error) {
return json.Marshal(d)
}
func (s *SkillPointsData) Scan(value interface{}) error {
if value == nil {
return nil
}
bytes, ok := value.([]byte)
if !ok {
return nil
}
return json.Unmarshal(bytes, s)
}
func (s SkillPointsData) Value() (interface{}, error) {
return json.Marshal(s)
}
// Cleanup expired sessions
func CleanupExpiredSessions(db *gorm.DB) error {
return db.Where("expires_at < ?", time.Now()).Delete(&CharacterCreationSession{}).Error
}
// Find sessions by user ID
func GetUserSessions(db *gorm.DB, userID uint) ([]CharacterCreationSession, error) {
var sessions []CharacterCreationSession
err := db.Where("user_id = ? AND expires_at > ?", userID, time.Now()).Find(&sessions).Error
return sessions, err
}
// GetLearningPointsForClass retrieves all learning points for a character class
func GetLearningPointsForClass(classID uint) ([]ClassCategoryLearningPoints, error) {
var points []ClassCategoryLearningPoints
err := database.DB.Preload("SkillCategory").Where("character_class_id = ?", classID).Find(&points).Error
return points, err
}
// GetSpellPointsForClass retrieves spell points for a character class
func GetSpellPointsForClass(classID uint) (*ClassSpellPoints, error) {
var points ClassSpellPoints
err := database.DB.Where("character_class_id = ?", classID).First(&points).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return &ClassSpellPoints{SpellPoints: 0}, nil
}
return nil, err
}
return &points, nil
}
// GetTypicalSkillsForClass retrieves typical skills for a character class
func GetTypicalSkillsForClass(classID uint) ([]ClassTypicalSkill, error) {
var skills []ClassTypicalSkill
err := database.DB.Preload("Skill").Where("character_class_id = ?", classID).Find(&skills).Error
return skills, err
}
// GetTypicalSpellsForClass retrieves typical spells for a character class
func GetTypicalSpellsForClass(classID uint) ([]ClassTypicalSpell, error) {
var spells []ClassTypicalSpell
err := database.DB.Preload("Spell").Where("character_class_id = ?", classID).Find(&spells).Error
return spells, err
}