Lerne Zauber
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package gsmaster
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// DifficultyData enthält Skills und Trainingskosten für eine Schwierigkeitsstufe
|
||||
type DifficultyData struct {
|
||||
@@ -15,7 +17,8 @@ type LearningCostsTable2 struct {
|
||||
EPPerTE map[string]map[string]int
|
||||
|
||||
// EP-Kosten für 1 Lerneinheit (LE) für Zauber pro Charakterklasse und Zauberschule
|
||||
SpellEPPerLE map[string]map[string]int
|
||||
SpellEPPerLE map[string]map[string]int
|
||||
SpellLEPerLevel map[int]int
|
||||
|
||||
// LE-Kosten für Fertigkeiten basierend auf Schwierigkeit
|
||||
BaseLearnCost map[string]map[string]int
|
||||
@@ -282,6 +285,9 @@ var learningCostsData = &LearningCostsTable2{
|
||||
"Lied": 30,
|
||||
},
|
||||
},
|
||||
// Lernen von Zaubern
|
||||
// LE pro Stufe des Zaubers
|
||||
SpellLEPerLevel: map[int]int{1: 1, 2: 1, 3: 2, 4: 3, 5: 5, 6: 10, 7: 15, 8: 20, 9: 30, 10: 40, 11: 60, 12: 90},
|
||||
|
||||
// TE-Kosten für Verbesserungen basierend auf Kategorie, Schwierigkeit und aktuellem Wert
|
||||
ImprovementCost: map[string]map[string]DifficultyData{
|
||||
@@ -518,6 +524,28 @@ func contains(slice []string, item string) bool {
|
||||
|
||||
//### End of Helper functions ###
|
||||
|
||||
// GetSpellInfo returns the school and level of a spell from the database
|
||||
func GetSpellInfo(spellName string) (string, int, error) {
|
||||
// Create a Spell instance to search in the database
|
||||
var spell Spell
|
||||
|
||||
// Search for the spell in the database
|
||||
err := spell.First(spellName)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("spell '%s' not found in database: %w", spellName, err)
|
||||
}
|
||||
|
||||
return spell.Category, spell.Stufe, nil
|
||||
}
|
||||
|
||||
// GetSpecialization returns the specialization school for a character (placeholder)
|
||||
// This should be implemented to get the actual specialization from character data
|
||||
func GetSpecialization(characterID string) string {
|
||||
// TODO: Implement actual character specialization lookup
|
||||
// For now, return a default specialization
|
||||
return "Beherrschen"
|
||||
}
|
||||
|
||||
// findBestCategoryForSkillImprovement findet die Kategorie mit den niedrigsten EP-Kosten für eine Fertigkeit
|
||||
func findBestCategoryForSkillImprovement(skillName, characterClass string, level int) (string, string, error) {
|
||||
classKey := characterClass
|
||||
@@ -713,6 +741,43 @@ func CalcSkillImproveCost(costResult *SkillCostResultNew, currentLevel int, rewa
|
||||
func CalcSpellLernCost(costResult *SkillCostResultNew, reward *string) error {
|
||||
// Für Zauber verwenden wir eine ähnliche Logik wie für Skills
|
||||
// TODO: Implementiere spezifische Zauber-Kostenlogik wenn verfügbar
|
||||
// Für jetzt verwenden wir die gleiche Logik wie für Skills
|
||||
return CalcSkillLernCost(costResult, reward)
|
||||
classKey := costResult.CharacterClass
|
||||
spellCategory, spellLevel, err := GetSpellInfo(costResult.SkillName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get spell info: %w", err)
|
||||
}
|
||||
SpellEPPerLE, ok := learningCostsData.SpellEPPerLE[classKey][spellCategory]
|
||||
if !ok {
|
||||
return fmt.Errorf("EP-Kosten für Zauber '%s' und Klasse '%s' nicht gefunden", costResult.SkillName, classKey)
|
||||
}
|
||||
if classKey == "Ma" {
|
||||
spezialgebiet := GetSpecialization(costResult.CharacterID)
|
||||
if spellCategory == spezialgebiet {
|
||||
SpellEPPerLE = 30 // Spezialgebiet für Magier
|
||||
}
|
||||
}
|
||||
|
||||
trainCost := learningCostsData.SpellLEPerLevel[spellLevel] // LE pro Stufe des Zaubers
|
||||
if costResult.PPUsed > 0 {
|
||||
trainCost -= costResult.PPUsed // Wenn PP verwendet werden, setze die Kosten auf die PP
|
||||
}
|
||||
costResult.EP = trainCost * SpellEPPerLE // EP-Kosten für das Lernen des Zaubers
|
||||
costResult.GoldCost = trainCost * 100 // Beispiel: 200 Gold pro LE
|
||||
costResult.Category = spellCategory
|
||||
costResult.Difficulty = fmt.Sprintf("Stufe %d", spellLevel) // Zauber haben keine Schwierigkeit, sondern eine Stufe
|
||||
if reward != nil && *reward == "spruchrolle" {
|
||||
costResult.GoldCost = 20 // 20 Gold für Jeden Versuch
|
||||
costResult.EP = costResult.EP / 3 // 1/3 EP-Kosten bei Erfolg
|
||||
} else {
|
||||
|
||||
if reward != nil && *reward == "halveep" {
|
||||
costResult.EP = costResult.EP / 2 // Halbiere die EP-Kosten für diese Belohnung
|
||||
}
|
||||
if reward != nil && *reward == "halveepnoGold" {
|
||||
costResult.EP = costResult.EP / 2 // Halbiere die EP-Kosten für diese Belohnung
|
||||
costResult.GoldCost = 0 // Keine Goldkosten für diese Belohnung
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package gsmaster
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Helper function to create string pointers
|
||||
func stringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// TestGetSkillCategory tests the GetSkillCategory function
|
||||
func TestGetSkillCategory(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -606,11 +612,6 @@ func TestCalcSkillLernCostWithRewards(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to create string pointers
|
||||
func stringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// TestCalcSpellLernCostWithRewards tests the reward logic in CalcSpellLernCost
|
||||
/*
|
||||
func TestCalcSpellLernCostWithRewards(t *testing.T) {
|
||||
@@ -735,3 +736,215 @@ func TestCalcSkillImproveCostWithRewards(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetSpellInfo tests the GetSpellInfo function
|
||||
func TestGetSpellInfo(t *testing.T) {
|
||||
|
||||
// Initialize test database with migration (but no test data since we don't have the preparedTestDB file)
|
||||
database.SetupTestDB(true, false) // Use in-memory SQLite, no test data loading
|
||||
defer database.ResetTestDB()
|
||||
MigrateStructure()
|
||||
|
||||
// Create minimal test spell data for our test
|
||||
testSpells := []Spell{
|
||||
{
|
||||
LookupList: LookupList{
|
||||
GameSystem: "midgard",
|
||||
Name: "Schlummer",
|
||||
Beschreibung: "Test spell for GetSpellInfo",
|
||||
Quelle: "Test",
|
||||
},
|
||||
Stufe: 1,
|
||||
Category: "Beherrschen",
|
||||
},
|
||||
{
|
||||
LookupList: LookupList{
|
||||
GameSystem: "midgard",
|
||||
Name: "Erkennen von Krankheit",
|
||||
Beschreibung: "Test spell for GetSpellInfo",
|
||||
Quelle: "Test",
|
||||
},
|
||||
Stufe: 2,
|
||||
Category: "Dweomerzauber",
|
||||
},
|
||||
{
|
||||
LookupList: LookupList{
|
||||
GameSystem: "midgard",
|
||||
Name: "Das Loblied",
|
||||
Beschreibung: "Test spell for GetSpellInfo",
|
||||
Quelle: "Test",
|
||||
},
|
||||
Stufe: 3,
|
||||
Category: "Zauberlied",
|
||||
},
|
||||
}
|
||||
|
||||
// Insert test data directly
|
||||
for _, spell := range testSpells {
|
||||
if err := database.DB.Create(&spell).Error; err != nil {
|
||||
t.Fatalf("Failed to create test spell: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
spellName string
|
||||
expectedSchool string
|
||||
expectedLevel int
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
spellName: "Schlummer",
|
||||
expectedSchool: "Beherrschen",
|
||||
expectedLevel: 1,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
spellName: "Erkennen von Krankheit",
|
||||
expectedSchool: "Dweomerzauber",
|
||||
expectedLevel: 2,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
spellName: "Das Loblied",
|
||||
expectedSchool: "Zauberlied",
|
||||
expectedLevel: 3,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
spellName: "Unknown Spell",
|
||||
expectedSchool: "", // Should error for unknown spell
|
||||
expectedLevel: 0, // Should error for unknown spell
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.spellName, func(t *testing.T) {
|
||||
school, level, err := GetSpellInfo(tt.spellName)
|
||||
|
||||
if tt.expectError {
|
||||
if err == nil {
|
||||
t.Errorf("Expected error for unknown spell, but got none")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get spell info: %v", err)
|
||||
}
|
||||
|
||||
if school != tt.expectedSchool {
|
||||
t.Errorf("Expected school %s, got %s", tt.expectedSchool, school)
|
||||
}
|
||||
|
||||
if level != tt.expectedLevel {
|
||||
t.Errorf("Expected level %d, got %d", tt.expectedLevel, level)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestCalcSpellLernCostWithRewards tests the reward logic in CalcSpellLernCost
|
||||
func TestCalcSpellLernCostWithRewards(t *testing.T) {
|
||||
// Initialize test database with migration (but no test data since we don't have the preparedTestDB file)
|
||||
database.SetupTestDB(true, false) // Use in-memory SQLite, no test data loading
|
||||
defer database.ResetTestDB()
|
||||
MigrateStructure()
|
||||
|
||||
// Create minimal test spell data for our test
|
||||
testSpells := []Spell{
|
||||
{
|
||||
LookupList: LookupList{
|
||||
GameSystem: "midgard",
|
||||
Name: "Schlummer",
|
||||
Beschreibung: "Test spell for GetSpellInfo",
|
||||
Quelle: "Test",
|
||||
},
|
||||
Stufe: 1,
|
||||
Category: "Beherrschen",
|
||||
},
|
||||
{
|
||||
LookupList: LookupList{
|
||||
GameSystem: "midgard",
|
||||
Name: "Erkennen von Krankheit",
|
||||
Beschreibung: "Test spell for GetSpellInfo",
|
||||
Quelle: "Test",
|
||||
},
|
||||
Stufe: 2,
|
||||
Category: "Dweomer",
|
||||
},
|
||||
{
|
||||
LookupList: LookupList{
|
||||
GameSystem: "midgard",
|
||||
Name: "Das Loblied",
|
||||
Beschreibung: "Test spell for GetSpellInfo",
|
||||
Quelle: "Test",
|
||||
},
|
||||
Stufe: 3,
|
||||
Category: "Zauberlied",
|
||||
},
|
||||
}
|
||||
// Insert test data directly
|
||||
for _, spell := range testSpells {
|
||||
if err := database.DB.Create(&spell).Error; err != nil {
|
||||
t.Fatalf("Failed to create test spell: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
spellName string
|
||||
characterClass string
|
||||
reward *string
|
||||
expectedEP int
|
||||
expectedGold int
|
||||
}{
|
||||
{
|
||||
name: "Simple spell for Magier without but specialized",
|
||||
spellName: "Schlummer",
|
||||
characterClass: "Ma",
|
||||
reward: nil,
|
||||
expectedEP: 30, // Ma has 60 EP/LE for Beherrschen, Furcht is level 1 = 1 LE, so 1*60=60
|
||||
expectedGold: 100, // 1 LE * 100 Gold per LE
|
||||
},
|
||||
{
|
||||
name: "Spell with spruchrolle no reward",
|
||||
spellName: "Erkennen von Krankheit",
|
||||
characterClass: "Ma",
|
||||
reward: nil,
|
||||
expectedEP: 120, // 60/3 for spruchrolle
|
||||
expectedGold: 100, // Fixed 20 Gold for spruchrolle
|
||||
},
|
||||
{
|
||||
name: "Spell with spruchrolle reward",
|
||||
spellName: "Erkennen von Krankheit",
|
||||
characterClass: "Ma",
|
||||
reward: stringPtr("spruchrolle"),
|
||||
expectedEP: 40, // 60/3 for spruchrolle
|
||||
expectedGold: 20, // Fixed 20 Gold for spruchrolle
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
costResult := &SkillCostResultNew{
|
||||
CharacterClass: tt.characterClass,
|
||||
SkillName: tt.spellName,
|
||||
CharacterID: "test-character",
|
||||
}
|
||||
|
||||
err := CalcSpellLernCost(costResult, tt.reward)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to calculate spell costs: %v", err)
|
||||
}
|
||||
|
||||
if costResult.EP != tt.expectedEP {
|
||||
t.Errorf("Expected EP %d, got %d", tt.expectedEP, costResult.EP)
|
||||
}
|
||||
|
||||
if costResult.GoldCost != tt.expectedGold {
|
||||
t.Errorf("Expected gold cost %d, got %d", tt.expectedGold, costResult.GoldCost)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package integration_test
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"bamort/gsmaster"
|
||||
_ "bamort/maintenance" // Import for init() function that sets up test data callbacks
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestGetSpellInfoIntegration tests the GetSpellInfo function with full database integration
|
||||
func TestGetSpellInfoIntegration(t *testing.T) {
|
||||
// The maintenance package init() already sets up:
|
||||
// database.SetTestDataLoader(LoadPredefinedTestDataFromFile)
|
||||
// database.SetMigrationCallback(migrateAllStructures)
|
||||
|
||||
// Initialize test database with test data loading
|
||||
database.SetupTestDB(true, true) // Use in-memory SQLite with test data
|
||||
defer database.ResetTestDB()
|
||||
|
||||
// Test with real spell names that should exist in the prepared test database
|
||||
// If the prepared test database doesn't exist, these tests will fail gracefully
|
||||
tests := []struct {
|
||||
spellName string
|
||||
expectedSchool string
|
||||
expectedLevel int
|
||||
expectError bool
|
||||
description string
|
||||
}{
|
||||
{
|
||||
spellName: "Licht",
|
||||
expectedSchool: "Erschaffen", // Common light spell in Midgard
|
||||
expectedLevel: 1,
|
||||
expectError: false,
|
||||
description: "Basic light spell should exist in prepared database",
|
||||
},
|
||||
{
|
||||
spellName: "Erkennen von Krankheit",
|
||||
expectedSchool: "Erkennen",
|
||||
expectedLevel: 2,
|
||||
expectError: false,
|
||||
description: "Common diagnostic spell should exist in prepared database",
|
||||
},
|
||||
{
|
||||
spellName: "Furcht",
|
||||
expectedSchool: "Beherrschen",
|
||||
expectedLevel: 1,
|
||||
expectError: false,
|
||||
description: "Fear spell should exist in prepared database",
|
||||
},
|
||||
{
|
||||
spellName: "Unknown Spell That Should Not Exist",
|
||||
expectedSchool: "", // Should error for unknown spell
|
||||
expectedLevel: 0, // Should error for unknown spell
|
||||
expectError: true,
|
||||
description: "Non-existent spell should return error",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.spellName, func(t *testing.T) {
|
||||
school, level, err := gsmaster.GetSpellInfo(tt.spellName)
|
||||
|
||||
if tt.expectError {
|
||||
if err == nil {
|
||||
t.Errorf("Expected error for %s, but got none. %s", tt.spellName, tt.description)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// If we get an error for a spell we expect to exist, it might mean
|
||||
// the prepared test database doesn't exist or doesn't contain this spell
|
||||
t.Logf("Warning: Failed to get spell info for %s: %v. %s", tt.spellName, err, tt.description)
|
||||
t.Logf("This might indicate that the prepared test database is missing or incomplete.")
|
||||
t.Skip("Skipping test due to missing prepared test data")
|
||||
return
|
||||
}
|
||||
|
||||
if school != tt.expectedSchool {
|
||||
t.Errorf("Expected school %s, got %s for spell %s", tt.expectedSchool, school, tt.spellName)
|
||||
}
|
||||
|
||||
if level != tt.expectedLevel {
|
||||
t.Errorf("Expected level %d, got %d for spell %s", tt.expectedLevel, level, tt.spellName)
|
||||
}
|
||||
|
||||
t.Logf("✅ Successfully found spell %s: school=%s, level=%d", tt.spellName, school, level)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user