280 lines
7.4 KiB
Go

package achievements
import (
"fmt"
"maps"
"time"
)
// PlayerList manages achievements for a specific player
type PlayerList struct {
achievements map[uint32]*Achievement
}
// PlayerUpdateList manages achievement updates/progress for a specific player
type PlayerUpdateList struct {
updates map[uint32]*Update
}
// NewPlayerList creates a new player achievement list
func NewPlayerList() *PlayerList {
return &PlayerList{
achievements: make(map[uint32]*Achievement),
}
}
// NewPlayerUpdateList creates a new player achievement update list
func NewPlayerUpdateList() *PlayerUpdateList {
return &PlayerUpdateList{
updates: make(map[uint32]*Update),
}
}
// AddAchievement adds an achievement to the player's list
// Returns false if achievement with same ID already exists
func (p *PlayerList) AddAchievement(achievement *Achievement) bool {
if achievement == nil {
return false
}
if _, exists := p.achievements[achievement.ID]; exists {
return false
}
p.achievements[achievement.ID] = achievement
return true
}
// GetAchievement retrieves an achievement by ID
// Returns nil if not found
func (p *PlayerList) GetAchievement(id uint32) *Achievement {
return p.achievements[id]
}
// GetAllAchievements returns all player achievements
func (p *PlayerList) GetAllAchievements() map[uint32]*Achievement {
result := make(map[uint32]*Achievement, len(p.achievements))
maps.Copy(result, p.achievements)
return result
}
// RemoveAchievement removes an achievement from the player's list
// Returns true if achievement was found and removed
func (p *PlayerList) RemoveAchievement(id uint32) bool {
if _, exists := p.achievements[id]; !exists {
return false
}
delete(p.achievements, id)
return true
}
// HasAchievement checks if player has a specific achievement
func (p *PlayerList) HasAchievement(id uint32) bool {
_, exists := p.achievements[id]
return exists
}
// Clear removes all achievements from the player's list
func (p *PlayerList) Clear() {
p.achievements = make(map[uint32]*Achievement)
}
// Size returns the number of achievements in the player's list
func (p *PlayerList) Size() int {
return len(p.achievements)
}
// GetAchievementsByCategory returns player achievements filtered by category
func (p *PlayerList) GetAchievementsByCategory(category string) []*Achievement {
var result []*Achievement
for _, achievement := range p.achievements {
if achievement.Category == category {
result = append(result, achievement)
}
}
return result
}
// AddUpdate adds an achievement update to the player's list
// Returns false if update with same ID already exists
func (p *PlayerUpdateList) AddUpdate(update *Update) bool {
if update == nil {
return false
}
if _, exists := p.updates[update.ID]; exists {
return false
}
p.updates[update.ID] = update
return true
}
// GetUpdate retrieves an achievement update by ID
// Returns nil if not found
func (p *PlayerUpdateList) GetUpdate(id uint32) *Update {
return p.updates[id]
}
// GetAllUpdates returns all player achievement updates
func (p *PlayerUpdateList) GetAllUpdates() map[uint32]*Update {
result := make(map[uint32]*Update, len(p.updates))
maps.Copy(result, p.updates)
return result
}
// UpdateProgress updates or creates achievement progress
func (p *PlayerUpdateList) UpdateProgress(achievementID uint32, itemUpdate uint32) {
update := p.updates[achievementID]
if update == nil {
update = NewUpdate()
update.ID = achievementID
p.updates[achievementID] = update
}
// Add or update the progress item
found := false
for i := range update.UpdateItems {
if update.UpdateItems[i].AchievementID == achievementID {
update.UpdateItems[i].ItemUpdate = itemUpdate
found = true
break
}
}
if !found {
update.AddUpdateItem(UpdateItem{
AchievementID: achievementID,
ItemUpdate: itemUpdate,
})
}
}
// CompleteAchievement marks an achievement as completed
func (p *PlayerUpdateList) CompleteAchievement(achievementID uint32) {
update := p.updates[achievementID]
if update == nil {
update = NewUpdate()
update.ID = achievementID
p.updates[achievementID] = update
}
update.CompletedDate = time.Now()
}
// IsCompleted checks if an achievement is completed
func (p *PlayerUpdateList) IsCompleted(achievementID uint32) bool {
update := p.updates[achievementID]
return update != nil && !update.CompletedDate.IsZero()
}
// GetCompletedDate returns the completion date for an achievement
// Returns zero time if not completed
func (p *PlayerUpdateList) GetCompletedDate(achievementID uint32) time.Time {
update := p.updates[achievementID]
if update == nil {
return time.Time{}
}
return update.CompletedDate
}
// GetProgress returns the current progress for an achievement
// Returns 0 if no progress found
func (p *PlayerUpdateList) GetProgress(achievementID uint32) uint32 {
update := p.updates[achievementID]
if update == nil || len(update.UpdateItems) == 0 {
return 0
}
// Return the first matching update item's progress
for _, item := range update.UpdateItems {
if item.AchievementID == achievementID {
return item.ItemUpdate
}
}
return 0
}
// RemoveUpdate removes an achievement update from the player's list
// Returns true if update was found and removed
func (p *PlayerUpdateList) RemoveUpdate(id uint32) bool {
if _, exists := p.updates[id]; !exists {
return false
}
delete(p.updates, id)
return true
}
// Clear removes all updates from the player's list
func (p *PlayerUpdateList) Clear() {
p.updates = make(map[uint32]*Update)
}
// Size returns the number of updates in the player's list
func (p *PlayerUpdateList) Size() int {
return len(p.updates)
}
// GetCompletedAchievements returns all completed achievement IDs
func (p *PlayerUpdateList) GetCompletedAchievements() []uint32 {
var completed []uint32
for id, update := range p.updates {
if !update.CompletedDate.IsZero() {
completed = append(completed, id)
}
}
return completed
}
// GetInProgressAchievements returns all in-progress achievement IDs
func (p *PlayerUpdateList) GetInProgressAchievements() []uint32 {
var inProgress []uint32
for id, update := range p.updates {
if update.CompletedDate.IsZero() && len(update.UpdateItems) > 0 {
inProgress = append(inProgress, id)
}
}
return inProgress
}
// PlayerManager combines achievement list and update list for a player
type PlayerManager struct {
Achievements *PlayerList
Updates *PlayerUpdateList
}
// NewPlayerManager creates a new player manager
func NewPlayerManager() *PlayerManager {
return &PlayerManager{
Achievements: NewPlayerList(),
Updates: NewPlayerUpdateList(),
}
}
// CheckRequirements validates if player meets achievement requirements
// This is a basic implementation - extend as needed for specific game logic
func (pm *PlayerManager) CheckRequirements(achievement *Achievement) (bool, error) {
if achievement == nil {
return false, fmt.Errorf("achievement cannot be nil")
}
// Basic implementation - check if we have progress >= required quantity
progress := pm.Updates.GetProgress(achievement.ID)
return progress >= achievement.QtyRequired, nil
}
// GetCompletionStatus returns completion percentage for an achievement
func (pm *PlayerManager) GetCompletionStatus(achievement *Achievement) float64 {
if achievement == nil || achievement.QtyRequired == 0 {
return 0.0
}
progress := pm.Updates.GetProgress(achievement.ID)
if progress >= achievement.QtyRequired {
return 100.0
}
return (float64(progress) / float64(achievement.QtyRequired)) * 100.0
}