排名改变事件优化、增加排行榜清理前事件

This commit is contained in:
kercylan98 2023-05-30 15:52:49 +08:00
parent 4e75282d01
commit 4cf4e7a83e
2 changed files with 31 additions and 24 deletions

View File

@ -7,7 +7,7 @@ import (
"github.com/kercylan98/minotaur/utils/synchronization" "github.com/kercylan98/minotaur/utils/synchronization"
) )
// NewRankingList 创建一个排行榜 // NewRankingList 创建一个排名从0开始的排行榜
func NewRankingList[CompetitorID comparable, Score generic.Ordered](options ...RankingListOption[CompetitorID, Score]) *RankingList[CompetitorID, Score] { func NewRankingList[CompetitorID comparable, Score generic.Ordered](options ...RankingListOption[CompetitorID, Score]) *RankingList[CompetitorID, Score] {
rankingList := &RankingList[CompetitorID, Score]{ rankingList := &RankingList[CompetitorID, Score]{
rankCount: 100, rankCount: 100,
@ -25,7 +25,8 @@ type RankingList[CompetitorID comparable, Score generic.Ordered] struct {
competitors *synchronization.Map[CompetitorID, Score] competitors *synchronization.Map[CompetitorID, Score]
scores []*scoreItem[CompetitorID, Score] // CompetitorID, Score scores []*scoreItem[CompetitorID, Score] // CompetitorID, Score
rankChangeEventHandles []game.RankChangeEventHandle[CompetitorID, Score] rankChangeEventHandles []game.RankChangeEventHandle[CompetitorID, Score]
rankClearBeforeEventHandles []game.RankClearBeforeEventHandle[CompetitorID, Score]
} }
type scoreItem[CompetitorID comparable, Score generic.Ordered] struct { type scoreItem[CompetitorID comparable, Score generic.Ordered] struct {
@ -46,16 +47,9 @@ func (slf *RankingList[CompetitorID, Score]) Competitor(competitorId CompetitorI
slf.scores = append(slf.scores[0:rank], slf.scores[rank+1:]...) slf.scores = append(slf.scores[0:rank], slf.scores[rank+1:]...)
slf.competitors.Delete(competitorId) slf.competitors.Delete(competitorId)
if slf.Cmp(score, v) > 0 { if slf.Cmp(score, v) > 0 {
slf.competitor(competitorId, score, 0, rank-1) slf.competitor(competitorId, v, rank, score, 0, rank-1)
} else { } else {
slf.competitor(competitorId, score, rank, len(slf.scores)-1) slf.competitor(competitorId, v, rank, score, rank, len(slf.scores)-1)
}
if len(slf.rankChangeEventHandles) > 0 {
newRank, err := slf.GetRank(competitorId)
if err != nil {
panic(err)
}
slf.OnRankChangeEvent(competitorId, rank, newRank, v, score)
} }
} else { } else {
if slf.rankCount > 0 && len(slf.scores) >= slf.rankCount { if slf.rankCount > 0 && len(slf.scores) >= slf.rankCount {
@ -64,14 +58,7 @@ func (slf *RankingList[CompetitorID, Score]) Competitor(competitorId CompetitorI
return return
} }
} }
slf.competitor(competitorId, score, 0, len(slf.scores)-1) slf.competitor(competitorId, v, -1, score, 0, len(slf.scores)-1)
if len(slf.rankChangeEventHandles) > 0 {
newRank, err := slf.GetRank(competitorId)
if err != nil {
panic(err)
}
slf.OnRankChangeEvent(competitorId, newRank, newRank, score, score)
}
} }
} }
@ -93,8 +80,11 @@ func (slf *RankingList[CompetitorID, Score]) RemoveCompetitor(competitorId Compe
slf.competitors.Delete(competitorId) slf.competitors.Delete(competitorId)
return return
} }
oldScore := slf.scores[rank].Score
slf.OnRankChangeEvent(competitorId, rank, -1, oldScore, oldScore)
slf.scores = append(slf.scores[0:rank], slf.scores[rank+1:]...) slf.scores = append(slf.scores[0:rank], slf.scores[rank+1:]...)
slf.competitors.Delete(competitorId) slf.competitors.Delete(competitorId)
} }
func (slf *RankingList[CompetitorID, Score]) Size() int { func (slf *RankingList[CompetitorID, Score]) Size() int {
@ -178,6 +168,7 @@ func (slf *RankingList[CompetitorID, Score]) GetAllCompetitor() []CompetitorID {
} }
func (slf *RankingList[CompetitorID, Score]) Clear() { func (slf *RankingList[CompetitorID, Score]) Clear() {
slf.OnRankClearBeforeEvent()
slf.competitors.Clear() slf.competitors.Clear()
slf.scores = make([]*scoreItem[CompetitorID, Score], 0) slf.scores = make([]*scoreItem[CompetitorID, Score], 0)
} }
@ -198,7 +189,7 @@ func (slf *RankingList[CompetitorID, Score]) Cmp(s1, s2 Score) int {
} }
} }
func (slf *RankingList[CompetitorID, Score]) competitor(competitorId CompetitorID, score Score, low, high int) { func (slf *RankingList[CompetitorID, Score]) competitor(competitorId CompetitorID, oldScore Score, oldRank int, score Score, low, high int) {
for low <= high { for low <= high {
mid := (low + high) / 2 mid := (low + high) / 2
data := slf.scores[mid] data := slf.scores[mid]
@ -223,12 +214,12 @@ func (slf *RankingList[CompetitorID, Score]) competitor(competitorId CompetitorI
slf.scores = append(slf.scores, &scoreItem[CompetitorID, Score]{CompetitorId: competitorId, Score: score}) slf.scores = append(slf.scores, &scoreItem[CompetitorID, Score]{CompetitorId: competitorId, Score: score})
slf.competitors.Set(competitorId, score) slf.competitors.Set(competitorId, score)
slf.OnRankChangeEvent(competitorId, oldRank, len(slf.scores)-1, oldScore, score)
return return
} }
si := &scoreItem[CompetitorID, Score]{competitorId, score} si := &scoreItem[CompetitorID, Score]{competitorId, score}
//队首
if low == 0 { if low == 0 {
slf.scores = append([]*scoreItem[CompetitorID, Score]{si}, slf.scores...) slf.scores = append([]*scoreItem[CompetitorID, Score]{si}, slf.scores...)
} else { } else {
@ -236,12 +227,14 @@ func (slf *RankingList[CompetitorID, Score]) competitor(competitorId CompetitorI
slf.scores = append(slf.scores[0:low], tmp...) slf.scores = append(slf.scores[0:low], tmp...)
} }
slf.competitors.Set(competitorId, score) slf.competitors.Set(competitorId, score)
slf.OnRankChangeEvent(competitorId, oldRank, low, oldScore, score)
if slf.rankCount <= 0 || len(slf.scores) <= slf.rankCount { if slf.rankCount <= 0 || len(slf.scores) <= slf.rankCount {
return return
} }
count = len(slf.scores) - 1 count = len(slf.scores) - 1
si = slf.scores[count] si = slf.scores[count]
slf.OnRankChangeEvent(si.CompetitorId, count, -1, si.Score, si.Score)
slf.competitors.Delete(si.CompetitorId) slf.competitors.Delete(si.CompetitorId)
slf.scores = slf.scores[0:count] slf.scores = slf.scores[0:count]
} }
@ -281,6 +274,16 @@ func (slf *RankingList[CompetitorID, Score]) RegRankChangeEvent(handle game.Rank
func (slf *RankingList[CompetitorID, Score]) OnRankChangeEvent(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) { func (slf *RankingList[CompetitorID, Score]) OnRankChangeEvent(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) {
for _, handle := range slf.rankChangeEventHandles { for _, handle := range slf.rankChangeEventHandles {
handle(competitorId, oldRank, newRank, oldScore, newScore) handle(slf, competitorId, oldRank, newRank, oldScore, newScore)
}
}
func (slf *RankingList[CompetitorID, Score]) RegRankClearBeforeEvent(handle game.RankClearBeforeEventHandle[CompetitorID, Score]) {
slf.rankClearBeforeEventHandles = append(slf.rankClearBeforeEventHandles, handle)
}
func (slf *RankingList[CompetitorID, Score]) OnRankClearBeforeEvent() {
for _, handle := range slf.rankClearBeforeEventHandles {
handle(slf)
} }
} }

View File

@ -29,11 +29,15 @@ type RankingList[CompetitorID comparable, Score generic.Ordered] interface {
Clear() Clear()
// RegRankChangeEvent 排名改变时将立即执行注册的事件处理函数 // RegRankChangeEvent 排名改变时将立即执行注册的事件处理函数
// - 当竞争者为新加入时oldRank 和 oldScore 均与 newRank 和 newScore 相同 // - 排名为-1时表示未上榜
RegRankChangeEvent(handle RankChangeEventHandle[CompetitorID, Score]) RegRankChangeEvent(handle RankChangeEventHandle[CompetitorID, Score])
OnRankChangeEvent(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) OnRankChangeEvent(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score)
// RegRankClearBeforeEvent 在排行榜被清空前执行被注册的事件处理函数
RegRankClearBeforeEvent(handle RankClearBeforeEventHandle[CompetitorID, Score])
OnRankClearBeforeEvent()
} }
type ( type (
RankChangeEventHandle[CompetitorID comparable, Score generic.Ordered] func(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) RankChangeEventHandle[CompetitorID comparable, Score generic.Ordered] func(rankingList RankingList[CompetitorID, Score], competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score)
RankClearBeforeEventHandle[CompetitorID comparable, Score generic.Ordered] func(rankingList RankingList[CompetitorID, Score])
) )