2025-07-29 07:30:51 +02:00
|
|
|
package gsmaster
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bamort/database"
|
|
|
|
|
"bamort/models"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// EnhanceLearningDataWithExistingTables ergänzt die neuen Lernkosten-Tabellen mit Daten aus den bereits vorhandenen Tabellen
|
|
|
|
|
func EnhanceLearningDataWithExistingTables() error {
|
|
|
|
|
log.Println("Starting enhancement of learning data with existing tables...")
|
|
|
|
|
|
|
|
|
|
// 1. Fertigkeiten aus der bestehenden Skill-Tabelle in SkillCategoryDifficulty einbinden
|
|
|
|
|
if err := linkExistingSkillsToCategories(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to link existing skills to categories: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. Zauber aus der bestehenden Spell-Tabelle mit Zauberschulen verknüpfen
|
|
|
|
|
if err := linkExistingSpellsToSchools(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to link existing spells to schools: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. Charaktere aus der bestehenden Character-Tabelle mit Charakterklassen verknüpfen
|
|
|
|
|
if err := linkExistingCharactersToClasses(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to link existing characters to classes: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. Fehlende Fertigkeiten aus der bestehenden Tabelle zu den Kategorien hinzufügen
|
|
|
|
|
if err := addMissingSkillsToCategories(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to add missing skills to categories: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. Verknüpfe bestehende Fertigkeiten und Zauber mit Standardquellen
|
|
|
|
|
if err := linkExistingItemsToDefaultSources(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to link existing items to default sources: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Println("Enhancement completed successfully!")
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// linkExistingSkillsToCategories verknüpft vorhandene Fertigkeiten mit Kategorien und Schwierigkeiten
|
|
|
|
|
func linkExistingSkillsToCategories() error {
|
|
|
|
|
var skills []models.Skill
|
|
|
|
|
if err := database.DB.Find(&skills).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to fetch existing skills: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, skill := range skills {
|
|
|
|
|
// Prüfe ob bereits Verknüpfungen für diese Fertigkeit existieren
|
|
|
|
|
var existingLinks []models.SkillCategoryDifficulty
|
|
|
|
|
if err := database.DB.Where("skill_id = ?", skill.ID).Find(&existingLinks).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to check existing links for skill %s: %w", skill.Name, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wenn bereits Verknüpfungen existieren, überspringe
|
|
|
|
|
if len(existingLinks) > 0 {
|
|
|
|
|
log.Printf("Skill %s already has category links, skipping", skill.Name)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Suche nach der Fertigkeit in den lerningCostsData
|
|
|
|
|
category, difficulty := findSkillInLearningData(skill.Name)
|
|
|
|
|
if category == "" {
|
|
|
|
|
log.Printf("Warning: Skill %s not found in learning data, using default category", skill.Name)
|
|
|
|
|
// Verwende eine Standard-Kategorie basierend auf der bestehenden Category
|
|
|
|
|
if skill.Category != "" {
|
|
|
|
|
category = skill.Category
|
|
|
|
|
difficulty = skill.Difficulty
|
|
|
|
|
if difficulty == "" {
|
|
|
|
|
difficulty = "normal"
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
category = "Unbekannt"
|
|
|
|
|
difficulty = "normal"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Erstelle Verknüpfung
|
|
|
|
|
if err := createSkillCategoryLink(skill.ID, skill.Name, category, difficulty); err != nil {
|
|
|
|
|
log.Printf("Warning: Failed to create category link for skill %s: %v", skill.Name, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// linkExistingSpellsToSchools verknüpft vorhandene Zauber mit Zauberschulen
|
|
|
|
|
func linkExistingSpellsToSchools() error {
|
|
|
|
|
var spells []models.Spell
|
|
|
|
|
if err := database.DB.Find(&spells).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to fetch existing spells: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, spell := range spells {
|
|
|
|
|
// Prüfe ob die Zauberschule existiert
|
|
|
|
|
if spell.Category == "" {
|
|
|
|
|
log.Printf("Warning: Spell %s has no category, skipping", spell.Name)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var spellSchool models.SpellSchool
|
|
|
|
|
if err := spellSchool.FirstByName(spell.Category); err != nil {
|
|
|
|
|
// Zauberschule existiert nicht, erstelle sie
|
|
|
|
|
newSchool := models.SpellSchool{
|
2026-01-29 09:14:33 +01:00
|
|
|
Name: spell.Category,
|
|
|
|
|
GameSystemId: 1,
|
2025-07-29 07:30:51 +02:00
|
|
|
}
|
|
|
|
|
if err := newSchool.Create(); err != nil {
|
|
|
|
|
log.Printf("Warning: Failed to create spell school %s for spell %s: %v", spell.Category, spell.Name, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
log.Printf("Created new spell school: %s", spell.Category)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Printf("Spell %s linked to school %s", spell.Name, spell.Category)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// linkExistingCharactersToClasses verknüpft vorhandene Charaktere mit Charakterklassen
|
|
|
|
|
func linkExistingCharactersToClasses() error {
|
|
|
|
|
var characters []models.Char
|
|
|
|
|
if err := database.DB.Find(&characters).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to fetch existing characters: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lade alle verfügbaren Charakterklassen aus der Datenbank
|
|
|
|
|
var characterClasses []models.CharacterClass
|
|
|
|
|
if err := database.DB.Find(&characterClasses).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to fetch character classes from database: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Erstelle Mapping-Maps für beide Richtungen (Code->Klasse und Name->Klasse)
|
|
|
|
|
codeToClass := make(map[string]models.CharacterClass)
|
|
|
|
|
nameToClass := make(map[string]models.CharacterClass)
|
|
|
|
|
|
|
|
|
|
for _, class := range characterClasses {
|
|
|
|
|
codeToClass[class.Code] = class
|
|
|
|
|
nameToClass[class.Name] = class
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, character := range characters {
|
|
|
|
|
var characterClass models.CharacterClass
|
|
|
|
|
var found bool
|
|
|
|
|
|
|
|
|
|
// Versuche zuerst über Code zu finden (falls character.Typ bereits ein Code ist)
|
|
|
|
|
if class, exists := codeToClass[character.Typ]; exists {
|
|
|
|
|
characterClass = class
|
|
|
|
|
found = true
|
|
|
|
|
} else if class, exists := nameToClass[character.Typ]; exists {
|
|
|
|
|
// Wenn nicht über Code gefunden, versuche über vollständigen Namen
|
|
|
|
|
characterClass = class
|
|
|
|
|
found = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
|
log.Printf("Warning: Character class '%s' not found in database for character %s", character.Typ, character.Name)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Printf("Character %s linked to class %s (%s)", character.Name, characterClass.Code, characterClass.Name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// addMissingSkillsToCategories fügt Fertigkeiten hinzu, die in der Datenbank existieren aber nicht in den Lernkosten-Daten
|
|
|
|
|
func addMissingSkillsToCategories() error {
|
|
|
|
|
var skills []models.Skill
|
|
|
|
|
if err := database.DB.Find(&skills).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to fetch skills: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, skill := range skills {
|
|
|
|
|
// Prüfe ob bereits Kategorien-Verknüpfungen existieren
|
|
|
|
|
var count int64
|
|
|
|
|
if err := database.DB.Model(&models.SkillCategoryDifficulty{}).Where("skill_id = ?", skill.ID).Count(&count).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to count category links for skill %s: %w", skill.Name, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if count == 0 {
|
|
|
|
|
// Keine Kategorien-Verknüpfung gefunden, erstelle eine Standard-Verknüpfung
|
|
|
|
|
category := "Unbekannt"
|
|
|
|
|
difficulty := "normal"
|
|
|
|
|
|
|
|
|
|
// Verwende bestehende Kategorie falls vorhanden
|
|
|
|
|
if skill.Category != "" {
|
|
|
|
|
category = skill.Category
|
|
|
|
|
}
|
|
|
|
|
if skill.Difficulty != "" {
|
|
|
|
|
difficulty = skill.Difficulty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := createSkillCategoryLink(skill.ID, skill.Name, category, difficulty); err != nil {
|
|
|
|
|
log.Printf("Warning: Failed to create default category link for skill %s: %v", skill.Name, err)
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("Created default category link for skill %s: %s - %s", skill.Name, category, difficulty)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hilfsfunktionen
|
|
|
|
|
|
|
|
|
|
// findSkillInLearningData sucht eine Fertigkeit in den learningCostsData und gibt Kategorie und Schwierigkeit zurück
|
|
|
|
|
func findSkillInLearningData(skillName string) (string, string) {
|
|
|
|
|
for categoryName, difficulties := range learningCostsData.ImprovementCost {
|
|
|
|
|
for difficultyName, data := range difficulties {
|
|
|
|
|
for _, skill := range data.Skills {
|
|
|
|
|
if skill == skillName {
|
|
|
|
|
return categoryName, difficultyName
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "", ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// createSkillCategoryLink erstellt eine Verknüpfung zwischen Fertigkeit, Kategorie und Schwierigkeit
|
|
|
|
|
func createSkillCategoryLink(skillID uint, skillName, categoryName, difficultyName string) error {
|
|
|
|
|
// Hole oder erstelle die Kategorie
|
|
|
|
|
var skillCategory models.SkillCategory
|
2026-01-29 09:14:33 +01:00
|
|
|
gs := GetGameSystem(0, "midgard")
|
2025-07-29 07:30:51 +02:00
|
|
|
if err := skillCategory.FirstByName(categoryName); err != nil {
|
|
|
|
|
// Kategorie existiert nicht, erstelle sie
|
|
|
|
|
skillCategory = models.SkillCategory{
|
2026-01-29 09:14:33 +01:00
|
|
|
Name: categoryName,
|
|
|
|
|
GameSystemId: gs.ID,
|
2025-07-29 07:30:51 +02:00
|
|
|
}
|
|
|
|
|
if err := skillCategory.Create(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to create skill category %s: %w", categoryName, err)
|
|
|
|
|
}
|
|
|
|
|
log.Printf("Created new skill category: %s", categoryName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hole oder erstelle die Schwierigkeit
|
|
|
|
|
var skillDifficulty models.SkillDifficulty
|
|
|
|
|
if err := skillDifficulty.FirstByName(difficultyName); err != nil {
|
|
|
|
|
// Schwierigkeit existiert nicht, erstelle sie
|
|
|
|
|
skillDifficulty = models.SkillDifficulty{
|
2026-01-29 09:14:33 +01:00
|
|
|
Name: difficultyName,
|
|
|
|
|
GameSystemId: gs.ID,
|
2025-07-29 07:30:51 +02:00
|
|
|
}
|
|
|
|
|
if err := skillDifficulty.Create(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to create skill difficulty %s: %w", difficultyName, err)
|
|
|
|
|
}
|
|
|
|
|
log.Printf("Created new skill difficulty: %s", difficultyName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bestimme LearnCost basierend auf den learningCostsData
|
|
|
|
|
learnCost := 2 // Standard-Wert
|
|
|
|
|
if categoryData, exists := learningCostsData.ImprovementCost[categoryName]; exists {
|
|
|
|
|
if difficultyData, exists := categoryData[difficultyName]; exists {
|
|
|
|
|
learnCost = difficultyData.LearnCost
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Erstelle die Verknüpfung
|
|
|
|
|
categoryDifficulty := models.SkillCategoryDifficulty{
|
|
|
|
|
SkillID: skillID,
|
|
|
|
|
SkillCategoryID: skillCategory.ID,
|
|
|
|
|
SkillDifficultyID: skillDifficulty.ID,
|
|
|
|
|
LearnCost: learnCost,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := categoryDifficulty.Create(); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to create skill category difficulty link: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Printf("Created skill category link: %s - %s - %s (Learn: %d LE)", skillName, categoryName, difficultyName, learnCost)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CreateLearningCostsTables erstellt alle neuen Tabellen für das Lernkosten-System
|
|
|
|
|
func CreateLearningCostsTables() error {
|
|
|
|
|
log.Println("Creating learning costs tables...")
|
|
|
|
|
|
|
|
|
|
// Liste aller neuen Modelle
|
|
|
|
|
models := []interface{}{
|
|
|
|
|
&models.Source{},
|
|
|
|
|
&models.CharacterClass{},
|
|
|
|
|
&models.SkillCategory{},
|
|
|
|
|
&models.SkillDifficulty{},
|
|
|
|
|
&models.SpellSchool{},
|
|
|
|
|
&models.ClassCategoryEPCost{},
|
|
|
|
|
&models.ClassSpellSchoolEPCost{},
|
|
|
|
|
&models.SpellLevelLECost{},
|
|
|
|
|
&models.SkillCategoryDifficulty{},
|
2026-02-01 13:33:04 +01:00
|
|
|
&models.SkillImprovementCost{},
|
2025-07-29 07:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Erstelle oder migriere alle Tabellen
|
|
|
|
|
for _, model := range models {
|
|
|
|
|
if err := database.DB.AutoMigrate(model); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to migrate table for model %T: %w", model, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Println("Learning costs tables created successfully!")
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// linkExistingItemsToDefaultSources verknüpft bestehende Fertigkeiten und Zauber mit Standardquellen
|
|
|
|
|
func linkExistingItemsToDefaultSources() error {
|
|
|
|
|
// Hole die Standardquellen
|
|
|
|
|
var kodSource models.Source
|
|
|
|
|
if err := kodSource.FirstByCode("KOD"); err != nil {
|
|
|
|
|
return fmt.Errorf("KOD source not found: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var arkSource models.Source
|
|
|
|
|
if err := arkSource.FirstByCode("ARK"); err != nil {
|
|
|
|
|
return fmt.Errorf("ARK source not found: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verknüpfe Fertigkeiten mit KOD (falls noch keine Quelle zugeordnet)
|
|
|
|
|
var skills []models.Skill
|
|
|
|
|
if err := database.DB.Where("source_id IS NULL OR source_id = 0").Find(&skills).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to fetch skills without source: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, skill := range skills {
|
|
|
|
|
if err := database.DB.Model(&skill).Update("source_id", kodSource.ID).Error; err != nil {
|
|
|
|
|
log.Printf("Warning: Failed to update source for skill %s: %v", skill.Name, err)
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("Linked skill %s to source KOD", skill.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verknüpfe Zauber mit ARK (falls noch keine Quelle zugeordnet)
|
|
|
|
|
var spells []models.Spell
|
|
|
|
|
if err := database.DB.Where("source_id IS NULL OR source_id = 0").Find(&spells).Error; err != nil {
|
|
|
|
|
return fmt.Errorf("failed to fetch spells without source: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, spell := range spells {
|
|
|
|
|
if err := database.DB.Model(&spell).Update("source_id", arkSource.ID).Error; err != nil {
|
|
|
|
|
log.Printf("Warning: Failed to update source for spell %s: %v", spell.Name, err)
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("Linked spell %s to source ARK", spell.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|