package skills import ( "fmt" "sync" ) // Manager provides high-level management of the skills system type Manager struct { masterSkillList *MasterSkillList mutex sync.RWMutex // Statistics totalSkillUps int64 skillUpsByType map[int32]int64 // Skill type -> count skillUpsBySkill map[int32]int64 // Skill ID -> count playersWithSkills int64 } // NewManager creates a new skills manager func NewManager() *Manager { return &Manager{ masterSkillList: NewMasterSkillList(), skillUpsByType: make(map[int32]int64), skillUpsBySkill: make(map[int32]int64), } } // Initialize loads skills data (placeholder for database loading) func (m *Manager) Initialize() error { // TODO: Load skills from database when database system is integrated // This would typically load all skills from a skills table return nil } // GetMasterSkillList returns the master skill list func (m *Manager) GetMasterSkillList() *MasterSkillList { return m.masterSkillList } // AddSkillToMaster adds a skill to the master list func (m *Manager) AddSkillToMaster(skill *Skill) { m.masterSkillList.AddSkill(skill) } // GetSkill returns a skill from the master list by ID func (m *Manager) GetSkill(skillID int32) *Skill { return m.masterSkillList.GetSkill(skillID) } // GetSkillByName returns a skill from the master list by name func (m *Manager) GetSkillByName(skillName string) *Skill { return m.masterSkillList.GetSkillByName(skillName) } // CreatePlayerSkillList creates a new player skill list func (m *Manager) CreatePlayerSkillList() *PlayerSkillList { m.mutex.Lock() m.playersWithSkills++ m.mutex.Unlock() return NewPlayerSkillList() } // RecordSkillUp records a skill increase for statistics func (m *Manager) RecordSkillUp(skillID int32, skillType int32) { m.mutex.Lock() defer m.mutex.Unlock() m.totalSkillUps++ m.skillUpsByType[skillType]++ m.skillUpsBySkill[skillID]++ } // GetStatistics returns skill system statistics func (m *Manager) GetStatistics() map[string]any { m.mutex.RLock() defer m.mutex.RUnlock() stats := make(map[string]any) stats["total_skill_ups"] = m.totalSkillUps stats["players_with_skills"] = m.playersWithSkills stats["total_skills_in_master"] = m.masterSkillList.GetSkillCount() // Copy skill type statistics typeStats := make(map[int32]int64) for skillType, count := range m.skillUpsByType { typeStats[skillType] = count } stats["skill_ups_by_type"] = typeStats // Copy individual skill statistics skillStats := make(map[int32]int64) for skillID, count := range m.skillUpsBySkill { skillStats[skillID] = count } stats["skill_ups_by_skill"] = skillStats return stats } // ResetStatistics resets all statistics func (m *Manager) ResetStatistics() { m.mutex.Lock() defer m.mutex.Unlock() m.totalSkillUps = 0 m.playersWithSkills = 0 m.skillUpsByType = make(map[int32]int64) m.skillUpsBySkill = make(map[int32]int64) } // GetSkillsByType returns all skills of a specific type func (m *Manager) GetSkillsByType(skillType int32) []*Skill { return m.masterSkillList.GetSkillsByType(skillType) } // GetSkillTypeCount returns the number of skills of a specific type func (m *Manager) GetSkillTypeCount(skillType int32) int { skills := m.GetSkillsByType(skillType) return len(skills) } // GetSkillUpCount returns the total number of skill ups for a skill func (m *Manager) GetSkillUpCount(skillID int32) int64 { m.mutex.RLock() defer m.mutex.RUnlock() return m.skillUpsBySkill[skillID] } // GetSkillTypeUpCount returns the total number of skill ups for a skill type func (m *Manager) GetSkillTypeUpCount(skillType int32) int64 { m.mutex.RLock() defer m.mutex.RUnlock() return m.skillUpsByType[skillType] } // ValidateSkillData validates that all skills in the master list are properly configured func (m *Manager) ValidateSkillData() []string { skills := m.masterSkillList.GetAllSkills() issues := make([]string, 0) if len(skills) == 0 { issues = append(issues, "No skills configured in master list") return issues } for skillID, skill := range skills { if skill == nil { issues = append(issues, fmt.Sprintf("Skill ID %d is nil", skillID)) continue } if skill.SkillID != skillID { issues = append(issues, fmt.Sprintf("Skill %d has mismatched ID: %d", skillID, skill.SkillID)) } if skill.Name.Data == "" { issues = append(issues, fmt.Sprintf("Skill %d has empty name", skillID)) } if skill.SkillType == 0 { issues = append(issues, fmt.Sprintf("Skill %d (%s) has no skill type", skillID, skill.Name.Data)) } if skill.MaxVal < 0 { issues = append(issues, fmt.Sprintf("Skill %d (%s) has negative max value: %d", skillID, skill.Name.Data, skill.MaxVal)) } if skill.CurrentVal < 0 { issues = append(issues, fmt.Sprintf("Skill %d (%s) has negative current value: %d", skillID, skill.Name.Data, skill.CurrentVal)) } if skill.CurrentVal > skill.MaxVal { issues = append(issues, fmt.Sprintf("Skill %d (%s) has current value (%d) greater than max value (%d)", skillID, skill.Name.Data, skill.CurrentVal, skill.MaxVal)) } } return issues } // ProcessCommand handles skill-related commands func (m *Manager) ProcessCommand(command string, args []string) (string, error) { switch command { case "stats": return m.handleStatsCommand(args) case "validate": return m.handleValidateCommand(args) case "list": return m.handleListCommand(args) case "info": return m.handleInfoCommand(args) default: return "", fmt.Errorf("unknown skills command: %s", command) } } // handleStatsCommand shows skill system statistics func (m *Manager) handleStatsCommand(args []string) (string, error) { stats := m.GetStatistics() result := "Skills System Statistics:\n" result += fmt.Sprintf("Total Skills in Master List: %d\n", stats["total_skills_in_master"]) result += fmt.Sprintf("Players with Skills: %d\n", stats["players_with_skills"]) result += fmt.Sprintf("Total Skill Ups: %d\n", stats["total_skill_ups"]) return result, nil } // handleValidateCommand validates skill data func (m *Manager) handleValidateCommand(args []string) (string, error) { issues := m.ValidateSkillData() if len(issues) == 0 { return "All skill data is valid.", nil } result := fmt.Sprintf("Found %d issues with skill data:\n", len(issues)) for i, issue := range issues { result += fmt.Sprintf("%d. %s\n", i+1, issue) } return result, nil } // handleListCommand lists skills func (m *Manager) handleListCommand(args []string) (string, error) { skills := m.masterSkillList.GetAllSkills() if len(skills) == 0 { return "No skills configured.", nil } result := fmt.Sprintf("Skills (%d):\n", len(skills)) count := 0 for _, skill := range skills { if count >= 20 { // Limit output result += "... (and more)\n" break } result += fmt.Sprintf(" %d: %s (Type: %d)\n", skill.SkillID, skill.Name.Data, skill.SkillType) count++ } return result, nil } // handleInfoCommand shows information about a specific skill func (m *Manager) handleInfoCommand(args []string) (string, error) { if len(args) == 0 { return "", fmt.Errorf("skill name or ID required") } skillName := args[0] skill := m.GetSkillByName(skillName) if skill == nil { return fmt.Sprintf("Skill '%s' not found.", skillName), nil } result := fmt.Sprintf("Skill Information:\n") result += fmt.Sprintf("ID: %d\n", skill.SkillID) result += fmt.Sprintf("Name: %s\n", skill.Name.Data) result += fmt.Sprintf("Short Name: %s\n", skill.ShortName.Data) result += fmt.Sprintf("Type: %d\n", skill.SkillType) result += fmt.Sprintf("Description: %s\n", skill.Description.Data) result += fmt.Sprintf("Max Value: %d\n", skill.MaxVal) result += fmt.Sprintf("Current Value: %d\n", skill.CurrentVal) result += fmt.Sprintf("Active: %t\n", skill.ActiveSkill) upCount := m.GetSkillUpCount(skill.SkillID) result += fmt.Sprintf("Total Skill Ups Recorded: %d\n", upCount) return result, nil } // Shutdown gracefully shuts down the manager func (m *Manager) Shutdown() { // Nothing to clean up currently, but placeholder for future cleanup }