diff --git a/backend/character/creation_rules.go b/backend/character/creation_rules.go new file mode 100644 index 0000000..38019c1 --- /dev/null +++ b/backend/character/creation_rules.go @@ -0,0 +1,117 @@ +package character + +import "fmt" + +// SpecialAbility repräsentiert eine besondere Fähigkeit mit Name und Modifier +type SpecialAbility struct { + Name string `json:"name"` + Modifier int `json:"modifier"` + Special string `json:"special,omitempty"` // Für spezielle Fälle wie Berserkergang +} + +// GetSpecialAbilityByRoll gibt die besondere Fähigkeit basierend auf einem W100-Wurf zurück +// W% Besondere Fähigkeit +// 01-05: Sehen–2 +// 06-10: Hören–2 +// 11-15: Riechen–2 +// 16-20: Sechster Sinn+2 +// 21-30: Sehen+2 +// 31-40: Hören+2 +// 41-50: Riechen+2 +// 51-55: Nachtsicht+2 +// 56-60: Gute Reflexe+9 +// 61-65: Richtungssinn+12 +// 66-70: Robustheit+9 +// 71-75: Schmerzunempfindlichkeit+9 +// 76-80: Trinken+12 +// 81-85: Wachgabe+6 +// 86-90: Wahrnehmung+8 +// 91-95: Einprägen+4 +// 96-99: Berserkergang+(18–Wk/5) +// 100: freie Wahl und zweiter Wurf +func GetSpecialAbilityByRoll(roll int) (*SpecialAbility, error) { + if roll < 1 || roll > 100 { + return nil, fmt.Errorf("ungültiger Würfelwurf: %d (muss zwischen 1 und 100 liegen)", roll) + } + + switch { + case roll >= 1 && roll <= 5: + return &SpecialAbility{Name: "Sehen", Modifier: -2}, nil + case roll >= 6 && roll <= 10: + return &SpecialAbility{Name: "Hören", Modifier: -2}, nil + case roll >= 11 && roll <= 15: + return &SpecialAbility{Name: "Riechen", Modifier: -2}, nil + case roll >= 16 && roll <= 20: + return &SpecialAbility{Name: "Sechster Sinn", Modifier: 2}, nil + case roll >= 21 && roll <= 30: + return &SpecialAbility{Name: "Sehen", Modifier: 2}, nil + case roll >= 31 && roll <= 40: + return &SpecialAbility{Name: "Hören", Modifier: 2}, nil + case roll >= 41 && roll <= 50: + return &SpecialAbility{Name: "Riechen", Modifier: 2}, nil + case roll >= 51 && roll <= 55: + return &SpecialAbility{Name: "Nachtsicht", Modifier: 2}, nil + case roll >= 56 && roll <= 60: + return &SpecialAbility{Name: "Gute Reflexe", Modifier: 9}, nil + case roll >= 61 && roll <= 65: + return &SpecialAbility{Name: "Richtungssinn", Modifier: 12}, nil + case roll >= 66 && roll <= 70: + return &SpecialAbility{Name: "Robustheit", Modifier: 9}, nil + case roll >= 71 && roll <= 75: + return &SpecialAbility{Name: "Schmerzunempfindlichkeit", Modifier: 9}, nil + case roll >= 76 && roll <= 80: + return &SpecialAbility{Name: "Trinken", Modifier: 12}, nil + case roll >= 81 && roll <= 85: + return &SpecialAbility{Name: "Wachgabe", Modifier: 6}, nil + case roll >= 86 && roll <= 90: + return &SpecialAbility{Name: "Wahrnehmung", Modifier: 8}, nil + case roll >= 91 && roll <= 95: + return &SpecialAbility{Name: "Einprägen", Modifier: 4}, nil + case roll >= 96 && roll <= 99: + return &SpecialAbility{ + Name: "Berserkergang", + Modifier: 0, + Special: "+(18–Wk/5)", + }, nil + case roll == 100: + return &SpecialAbility{ + Name: "Freie Wahl", + Modifier: 0, + Special: "freie Wahl und zweiter Wurf", + }, nil + default: + return nil, fmt.Errorf("unerwarteter Würfelwurf: %d", roll) + } +} + +// GetAllSpecialAbilities gibt alle möglichen besonderen Fähigkeiten mit ihren Wahrscheinlichkeiten zurück +func GetAllSpecialAbilities() []struct { + RangeStart int `json:"range_start"` + RangeEnd int `json:"range_end"` + Ability *SpecialAbility `json:"ability"` +} { + return []struct { + RangeStart int `json:"range_start"` + RangeEnd int `json:"range_end"` + Ability *SpecialAbility `json:"ability"` + }{ + {1, 5, &SpecialAbility{Name: "Sehen", Modifier: -2}}, + {6, 10, &SpecialAbility{Name: "Hören", Modifier: -2}}, + {11, 15, &SpecialAbility{Name: "Riechen", Modifier: -2}}, + {16, 20, &SpecialAbility{Name: "Sechster Sinn", Modifier: 2}}, + {21, 30, &SpecialAbility{Name: "Sehen", Modifier: 2}}, + {31, 40, &SpecialAbility{Name: "Hören", Modifier: 2}}, + {41, 50, &SpecialAbility{Name: "Riechen", Modifier: 2}}, + {51, 55, &SpecialAbility{Name: "Nachtsicht", Modifier: 2}}, + {56, 60, &SpecialAbility{Name: "Gute Reflexe", Modifier: 9}}, + {61, 65, &SpecialAbility{Name: "Richtungssinn", Modifier: 12}}, + {66, 70, &SpecialAbility{Name: "Robustheit", Modifier: 9}}, + {71, 75, &SpecialAbility{Name: "Schmerzunempfindlichkeit", Modifier: 9}}, + {76, 80, &SpecialAbility{Name: "Trinken", Modifier: 12}}, + {81, 85, &SpecialAbility{Name: "Wachgabe", Modifier: 6}}, + {86, 90, &SpecialAbility{Name: "Wahrnehmung", Modifier: 8}}, + {91, 95, &SpecialAbility{Name: "Einprägen", Modifier: 4}}, + {96, 99, &SpecialAbility{Name: "Berserkergang", Modifier: 0, Special: "+(18–Wk/5)"}}, + {100, 100, &SpecialAbility{Name: "Freie Wahl", Modifier: 0, Special: "freie Wahl und zweiter Wurf"}}, + } +} diff --git a/backend/character/creation_rules_test.go b/backend/character/creation_rules_test.go new file mode 100644 index 0000000..e105e36 --- /dev/null +++ b/backend/character/creation_rules_test.go @@ -0,0 +1,74 @@ +package character + +import ( + "testing" +) + +func TestGetSpecialAbilityByRoll(t *testing.T) { + testCases := []struct { + roll int + expected string + modifier int + }{ + {1, "Sehen", -2}, + {5, "Sehen", -2}, + {6, "Hören", -2}, + {16, "Sechster Sinn", 2}, + {25, "Sehen", 2}, + {55, "Nachtsicht", 2}, + {60, "Gute Reflexe", 9}, + {65, "Richtungssinn", 12}, + {70, "Robustheit", 9}, + {75, "Schmerzunempfindlichkeit", 9}, + {80, "Trinken", 12}, + {85, "Wachgabe", 6}, + {90, "Wahrnehmung", 8}, + {95, "Einprägen", 4}, + {96, "Berserkergang", 0}, + {99, "Berserkergang", 0}, + {100, "Freie Wahl", 0}, + } + + for _, tc := range testCases { + ability, err := GetSpecialAbilityByRoll(tc.roll) + if err != nil { + t.Errorf("Unerwarteter Fehler für Wurf %d: %v", tc.roll, err) + continue + } + if ability.Name != tc.expected { + t.Errorf("Für Wurf %d: erwartet '%s', erhalten '%s'", tc.roll, tc.expected, ability.Name) + } + if ability.Modifier != tc.modifier { + t.Errorf("Für Wurf %d: erwarteter Modifier %d, erhalten %d", tc.roll, tc.modifier, ability.Modifier) + } + } +} + +func TestGetSpecialAbilityByRollInvalidInput(t *testing.T) { + invalidRolls := []int{0, -1, 101, 1000} + + for _, roll := range invalidRolls { + _, err := GetSpecialAbilityByRoll(roll) + if err == nil { + t.Errorf("Erwartete Fehler für ungültigen Wurf %d, aber keinen erhalten", roll) + } + } +} + +func TestGetAllSpecialAbilities(t *testing.T) { + abilities := GetAllSpecialAbilities() + + if len(abilities) != 18 { + t.Errorf("Erwartete 18 besondere Fähigkeiten, erhalten %d", len(abilities)) + } + + // Teste, dass alle Bereiche lückenlos von 1-100 abgedeckt sind + for i, ability := range abilities { + if i == 0 && ability.RangeStart != 1 { + t.Errorf("Erster Bereich sollte bei 1 starten, startet bei %d", ability.RangeStart) + } + if i == len(abilities)-1 && ability.RangeEnd != 100 { + t.Errorf("Letzter Bereich sollte bei 100 enden, endet bei %d", ability.RangeEnd) + } + } +} diff --git a/backend/models/database.go b/backend/models/database.go index 2446c93..4ce999f 100644 --- a/backend/models/database.go +++ b/backend/models/database.go @@ -79,7 +79,6 @@ func characterMigrateStructure(db ...*gorm.DB) error { err := targetDB.AutoMigrate( &Char{}, - &CharacterCreationSession{}, &Eigenschaft{}, &Lp{}, &Ap{}, @@ -88,6 +87,7 @@ func characterMigrateStructure(db ...*gorm.DB) error { &Erfahrungsschatz{}, &Bennies{}, &Vermoegen{}, + &CharacterCreationSession{}, ) if err != nil { return err diff --git a/backend/models/model_character.go b/backend/models/model_character.go index 7bfe931..159e69a 100644 --- a/backend/models/model_character.go +++ b/backend/models/model_character.go @@ -75,7 +75,7 @@ type Vermoegen struct { type Char struct { BamortBase - UserID uint `gorm:"index;not null" json:"user_id"` + UserID uint `gorm:"index;not null;default:1" json:"user_id"` User user.User `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"user"` Rasse string `json:"rasse"` Typ string `json:"typ"` diff --git a/backend/models/model_character_creation.go b/backend/models/model_character_creation.go index 91733ac..69f72fd 100644 --- a/backend/models/model_character_creation.go +++ b/backend/models/model_character_creation.go @@ -69,6 +69,11 @@ type CharacterCreationSpell struct { Cost int `json:"cost"` } +func (object *CharacterCreationSession) TableName() string { + dbPrefix := "char" + return dbPrefix + "_" + "char_creation_session" +} + // Scanning methods for JSON fields in GORM func (a *AttributesData) Scan(value interface{}) error { if value == nil {