eq2go/internal/groups/master.go

213 lines
5.7 KiB
Go

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
}