package groups import ( "fmt" "eq2emu/internal/common" ) // MasterList manages all groups using generic MasterList pattern type MasterList struct { *common.MasterList[int32, *Group] } // NewMasterList creates a new master list for groups func NewMasterList() *MasterList { return &MasterList{ MasterList: common.NewMasterList[int32, *Group](), } } // AddGroup adds a group to the master list func (ml *MasterList) AddGroup(group *Group) bool { return ml.MasterList.Add(group) } // GetGroup retrieves a group by ID func (ml *MasterList) GetGroup(groupID int32) *Group { return ml.MasterList.Get(groupID) } // RemoveGroup removes a group by ID func (ml *MasterList) RemoveGroup(groupID int32) bool { return ml.MasterList.Remove(groupID) } // GetAllGroups returns all groups func (ml *MasterList) GetAllGroups() []*Group { return ml.MasterList.GetAllSlice() } // GetGroupsByFilter returns groups matching the filter function func (ml *MasterList) GetGroupsByFilter(filter func(*Group) bool) []*Group { return ml.MasterList.Filter(filter) } // GetActiveGroups returns all non-disbanded groups func (ml *MasterList) GetActiveGroups() []*Group { return ml.GetGroupsByFilter(func(group *Group) bool { return !group.IsDisbanded() }) } // GetGroupsByZone returns groups with members in the specified zone func (ml *MasterList) GetGroupsByZone(zoneID int32) []*Group { return ml.GetGroupsByFilter(func(group *Group) bool { members := group.GetMembers() for _, member := range members { if member.ZoneID == zoneID { return true } } return false }) } // GetGroupsBySize returns groups of the specified size func (ml *MasterList) GetGroupsBySize(size int32) []*Group { return ml.GetGroupsByFilter(func(group *Group) bool { return group.GetSize() == size }) } // GetRaidGroups returns all groups that are part of raids func (ml *MasterList) GetRaidGroups() []*Group { return ml.GetGroupsByFilter(func(group *Group) bool { return group.IsGroupRaid() }) } // GetSoloGroups returns all groups with only one member func (ml *MasterList) GetSoloGroups() []*Group { return ml.GetGroupsBySize(1) } // GetFullGroups returns all groups at maximum capacity func (ml *MasterList) GetFullGroups() []*Group { return ml.GetGroupsBySize(MAX_GROUP_SIZE) } // GetGroupsByLeader returns groups led by entities with the specified name func (ml *MasterList) GetGroupsByLeader(leaderName string) []*Group { return ml.GetGroupsByFilter(func(group *Group) bool { return group.GetLeaderName() == leaderName }) } // GetGroupsByMember returns groups containing a member with the specified name func (ml *MasterList) GetGroupsByMember(memberName string) []*Group { return ml.GetGroupsByFilter(func(group *Group) bool { members := group.GetMembers() for _, member := range members { if member.Name == memberName { return true } } return false }) } // GetGroupStatistics returns statistics about the groups in the master list func (ml *MasterList) GetGroupStatistics() *GroupMasterListStats { allGroups := ml.GetAllGroups() activeGroups := ml.GetActiveGroups() raidGroups := ml.GetRaidGroups() var totalMembers int32 var totalRaidMembers int32 for _, group := range activeGroups { totalMembers += group.GetSize() if group.IsGroupRaid() { totalRaidMembers += group.GetSize() } } var averageGroupSize float64 if len(activeGroups) > 0 { averageGroupSize = float64(totalMembers) / float64(len(activeGroups)) } return &GroupMasterListStats{ TotalGroups: int32(len(allGroups)), ActiveGroups: int32(len(activeGroups)), RaidGroups: int32(len(raidGroups)), TotalMembers: totalMembers, TotalRaidMembers: totalRaidMembers, AverageGroupSize: averageGroupSize, SoloGroups: int32(len(ml.GetSoloGroups())), FullGroups: int32(len(ml.GetFullGroups())), } } // GroupMasterListStats holds statistics about the groups master list type GroupMasterListStats struct { TotalGroups int32 `json:"total_groups"` ActiveGroups int32 `json:"active_groups"` RaidGroups int32 `json:"raid_groups"` TotalMembers int32 `json:"total_members"` TotalRaidMembers int32 `json:"total_raid_members"` AverageGroupSize float64 `json:"average_group_size"` SoloGroups int32 `json:"solo_groups"` FullGroups int32 `json:"full_groups"` } // Cleanup removes disbanded groups from the master list func (ml *MasterList) Cleanup() int32 { disbandedGroups := ml.GetGroupsByFilter(func(group *Group) bool { return group.IsDisbanded() }) removed := int32(0) for _, group := range disbandedGroups { if ml.RemoveGroup(group.GetID()) { removed++ } } return removed } // ValidateAll validates all groups in the master list func (ml *MasterList) ValidateAll() []error { var errors []error allGroups := ml.GetAllGroups() for _, group := range allGroups { // Check for basic validity if group.GetID() <= 0 { errors = append(errors, fmt.Errorf("group %d has invalid ID", group.GetID())) } if group.GetSize() == 0 && !group.IsDisbanded() { errors = append(errors, fmt.Errorf("group %d is empty but not disbanded", group.GetID())) } if group.GetSize() > MAX_GROUP_SIZE { errors = append(errors, fmt.Errorf("group %d exceeds maximum size (%d > %d)", group.GetID(), group.GetSize(), MAX_GROUP_SIZE)) } // Check for leader members := group.GetMembers() hasLeader := false leaderCount := 0 for _, member := range members { if member.Leader { hasLeader = true leaderCount++ } } if !hasLeader && !group.IsDisbanded() { errors = append(errors, fmt.Errorf("group %d has no leader", group.GetID())) } if leaderCount > 1 { errors = append(errors, fmt.Errorf("group %d has multiple leaders (%d)", group.GetID(), leaderCount)) } } return errors }