From ed8ee4a542228278376d5592a18775fa8b5bd6d6 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Thu, 27 Jul 2023 16:31:56 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20RankingList=20=E6=9B=B4=E5=90=8D?= =?UTF-8?q?=E4=B8=BA=20List=EF=BC=8C=E5=B9=B6=E4=B8=94=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E8=87=B3=20ranking=20=E5=8C=85=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/builtin/ranking_list_errors.go | 9 --- game/builtin/ranking_list_options.go | 24 ------- game/builtin/ranking_list_test.go | 1 - .../ranking_list.go => ranking/list.go} | 63 ++++++++++--------- game/ranking/list_errors.go | 9 +++ game/ranking/list_events.go | 37 +++++++++++ .../list_example_test.go} | 20 +++--- game/ranking/list_options.go | 24 +++++++ game/ranking_list.go | 41 ------------ 9 files changed, 112 insertions(+), 116 deletions(-) delete mode 100644 game/builtin/ranking_list_errors.go delete mode 100644 game/builtin/ranking_list_options.go delete mode 100644 game/builtin/ranking_list_test.go rename game/{builtin/ranking_list.go => ranking/list.go} (72%) create mode 100644 game/ranking/list_errors.go create mode 100644 game/ranking/list_events.go rename game/{builtin/ranking_list_example_test.go => ranking/list_example_test.go} (69%) create mode 100644 game/ranking/list_options.go delete mode 100644 game/ranking_list.go diff --git a/game/builtin/ranking_list_errors.go b/game/builtin/ranking_list_errors.go deleted file mode 100644 index 3508086..0000000 --- a/game/builtin/ranking_list_errors.go +++ /dev/null @@ -1,9 +0,0 @@ -package builtin - -import "errors" - -var ( - ErrRankingListNotExistCompetitor = errors.New("ranking list not exist competitor") - ErrRankingListIndexErr = errors.New("ranking list index error") - ErrRankingListNonexistentRanking = errors.New("nonexistent ranking") -) diff --git a/game/builtin/ranking_list_options.go b/game/builtin/ranking_list_options.go deleted file mode 100644 index 1b5e857..0000000 --- a/game/builtin/ranking_list_options.go +++ /dev/null @@ -1,24 +0,0 @@ -package builtin - -import "github.com/kercylan98/minotaur/utils/generic" - -type RankingListOption[CompetitorID comparable, Score generic.Ordered] func(list *RankingList[CompetitorID, Score]) - -// WithRankingListCount 通过限制排行榜竞争者数量来创建排行榜 -// - 默认情况下允许100位竞争者 -func WithRankingListCount[CompetitorID comparable, Score generic.Ordered](rankCount int) RankingListOption[CompetitorID, Score] { - return func(list *RankingList[CompetitorID, Score]) { - if rankCount <= 0 { - rankCount = 1 - } - list.rankCount = rankCount - } -} - -// WithRankingListASC 通过升序的方式创建排行榜 -// - 默认情况下为降序 -func WithRankingListASC[CompetitorID comparable, Score generic.Ordered]() RankingListOption[CompetitorID, Score] { - return func(list *RankingList[CompetitorID, Score]) { - list.asc = true - } -} diff --git a/game/builtin/ranking_list_test.go b/game/builtin/ranking_list_test.go deleted file mode 100644 index cf7e36a..0000000 --- a/game/builtin/ranking_list_test.go +++ /dev/null @@ -1 +0,0 @@ -package builtin_test diff --git a/game/builtin/ranking_list.go b/game/ranking/list.go similarity index 72% rename from game/builtin/ranking_list.go rename to game/ranking/list.go index e366883..3ca31e6 100644 --- a/game/builtin/ranking_list.go +++ b/game/ranking/list.go @@ -1,15 +1,15 @@ -package builtin +package ranking import ( "encoding/json" - "github.com/kercylan98/minotaur/game" "github.com/kercylan98/minotaur/utils/concurrent" "github.com/kercylan98/minotaur/utils/generic" ) -// NewRankingList 创建一个排名从0开始的排行榜 -func NewRankingList[CompetitorID comparable, Score generic.Ordered](options ...RankingListOption[CompetitorID, Score]) *RankingList[CompetitorID, Score] { - rankingList := &RankingList[CompetitorID, Score]{ +// NewList 创建一个排名从0开始的排行榜 +func NewList[CompetitorID comparable, Score generic.Ordered](options ...ListOption[CompetitorID, Score]) *List[CompetitorID, Score] { + rankingList := &List[CompetitorID, Score]{ + event: new(event[CompetitorID, Score]), rankCount: 100, competitors: concurrent.NewBalanceMap[CompetitorID, Score](), } @@ -19,14 +19,15 @@ func NewRankingList[CompetitorID comparable, Score generic.Ordered](options ...R return rankingList } -type RankingList[CompetitorID comparable, Score generic.Ordered] struct { +type List[CompetitorID comparable, Score generic.Ordered] struct { + *event[CompetitorID, Score] asc bool rankCount int competitors *concurrent.BalanceMap[CompetitorID, Score] scores []*scoreItem[CompetitorID, Score] // CompetitorID, Score - rankChangeEventHandles []game.RankChangeEventHandle[CompetitorID, Score] - rankClearBeforeEventHandles []game.RankClearBeforeEventHandle[CompetitorID, Score] + rankChangeEventHandles []RankChangeEventHandle[CompetitorID, Score] + rankClearBeforeEventHandles []RankClearBeforeEventHandle[CompetitorID, Score] } type scoreItem[CompetitorID comparable, Score generic.Ordered] struct { @@ -36,7 +37,7 @@ type scoreItem[CompetitorID comparable, Score generic.Ordered] struct { // Competitor 声明排行榜竞争者 // - 如果竞争者存在的情况下,会更新已有成绩,否则新增竞争者 -func (slf *RankingList[CompetitorID, Score]) Competitor(competitorId CompetitorID, score Score) { +func (slf *List[CompetitorID, Score]) Competitor(competitorId CompetitorID, score Score) { v, exist := slf.competitors.GetExist(competitorId) if exist { if slf.Cmp(v, score) == 0 { @@ -65,7 +66,7 @@ func (slf *RankingList[CompetitorID, Score]) Competitor(competitorId CompetitorI } // RemoveCompetitor 删除特定竞争者 -func (slf *RankingList[CompetitorID, Score]) RemoveCompetitor(competitorId CompetitorID) { +func (slf *List[CompetitorID, Score]) RemoveCompetitor(competitorId CompetitorID) { if !slf.competitors.Exist(competitorId) { return } @@ -82,16 +83,16 @@ func (slf *RankingList[CompetitorID, Score]) RemoveCompetitor(competitorId Compe } // Size 获取竞争者数量 -func (slf *RankingList[CompetitorID, Score]) Size() int { +func (slf *List[CompetitorID, Score]) Size() int { return slf.competitors.Size() } // GetRank 获取竞争者排名 // - 排名从 0 开始 -func (slf *RankingList[CompetitorID, Score]) GetRank(competitorId CompetitorID) (int, error) { +func (slf *List[CompetitorID, Score]) GetRank(competitorId CompetitorID) (int, error) { competitorScore, exist := slf.competitors.GetExist(competitorId) if !exist { - return 0, ErrRankingListNotExistCompetitor + return 0, ErrListNotExistCompetitor } low, high := 0, len(slf.scores)-1 @@ -120,25 +121,25 @@ func (slf *RankingList[CompetitorID, Score]) GetRank(competitorId CompetitorID) low = mid + 1 } } - return 0, ErrRankingListIndexErr + return 0, ErrListIndexErr } // GetCompetitor 获取特定排名的竞争者 -func (slf *RankingList[CompetitorID, Score]) GetCompetitor(rank int) (competitorId CompetitorID, err error) { +func (slf *List[CompetitorID, Score]) GetCompetitor(rank int) (competitorId CompetitorID, err error) { if rank < 0 || rank >= len(slf.scores) { - return competitorId, ErrRankingListNonexistentRanking + return competitorId, ErrListNonexistentRanking } return slf.scores[rank].CompetitorId, nil } // GetCompetitorWithRange 获取第start名到第end名竞争者 -func (slf *RankingList[CompetitorID, Score]) GetCompetitorWithRange(start, end int) ([]CompetitorID, error) { +func (slf *List[CompetitorID, Score]) GetCompetitorWithRange(start, end int) ([]CompetitorID, error) { if start < 1 || end < start { - return nil, ErrRankingListNonexistentRanking + return nil, ErrListNonexistentRanking } total := len(slf.scores) if start > total { - return nil, ErrRankingListNonexistentRanking + return nil, ErrListNonexistentRanking } if end > total { end = total @@ -151,17 +152,17 @@ func (slf *RankingList[CompetitorID, Score]) GetCompetitorWithRange(start, end i } // GetScore 获取竞争者成绩 -func (slf *RankingList[CompetitorID, Score]) GetScore(competitorId CompetitorID) (score Score, err error) { +func (slf *List[CompetitorID, Score]) GetScore(competitorId CompetitorID) (score Score, err error) { data, ok := slf.competitors.GetExist(competitorId) if !ok { - return score, ErrRankingListNotExistCompetitor + return score, ErrListNotExistCompetitor } return data, nil } // GetAllCompetitor 获取所有竞争者ID // - 结果为名次有序的 -func (slf *RankingList[CompetitorID, Score]) GetAllCompetitor() []CompetitorID { +func (slf *List[CompetitorID, Score]) GetAllCompetitor() []CompetitorID { var result []CompetitorID for _, data := range slf.scores { result = append(result, data.CompetitorId) @@ -170,13 +171,13 @@ func (slf *RankingList[CompetitorID, Score]) GetAllCompetitor() []CompetitorID { } // Clear 清空排行榜 -func (slf *RankingList[CompetitorID, Score]) Clear() { +func (slf *List[CompetitorID, Score]) Clear() { slf.OnRankClearBeforeEvent() slf.competitors.Clear() slf.scores = make([]*scoreItem[CompetitorID, Score], 0) } -func (slf *RankingList[CompetitorID, Score]) Cmp(s1, s2 Score) int { +func (slf *List[CompetitorID, Score]) Cmp(s1, s2 Score) int { var result int if s1 > s2 { result = 1 @@ -192,7 +193,7 @@ func (slf *RankingList[CompetitorID, Score]) Cmp(s1, s2 Score) int { } } -func (slf *RankingList[CompetitorID, Score]) competitor(competitorId CompetitorID, oldScore Score, oldRank int, score Score, low, high int) { +func (slf *List[CompetitorID, Score]) competitor(competitorId CompetitorID, oldScore Score, oldRank int, score Score, low, high int) { for low <= high { mid := (low + high) / 2 data := slf.scores[mid] @@ -242,7 +243,7 @@ func (slf *RankingList[CompetitorID, Score]) competitor(competitorId CompetitorI slf.scores = slf.scores[0:count] } -func (slf *RankingList[CompetitorID, Score]) UnmarshalJSON(bytes []byte) error { +func (slf *List[CompetitorID, Score]) UnmarshalJSON(bytes []byte) error { var t struct { Competitors *concurrent.BalanceMap[CompetitorID, Score] `json:"competitors,omitempty"` Scores []*scoreItem[CompetitorID, Score] `json:"scores,omitempty"` @@ -258,7 +259,7 @@ func (slf *RankingList[CompetitorID, Score]) UnmarshalJSON(bytes []byte) error { return nil } -func (slf *RankingList[CompetitorID, Score]) MarshalJSON() ([]byte, error) { +func (slf *List[CompetitorID, Score]) MarshalJSON() ([]byte, error) { var t struct { Competitors *concurrent.BalanceMap[CompetitorID, Score] `json:"competitors,omitempty"` Scores []*scoreItem[CompetitorID, Score] `json:"scores,omitempty"` @@ -271,21 +272,21 @@ func (slf *RankingList[CompetitorID, Score]) MarshalJSON() ([]byte, error) { return json.Marshal(&t) } -func (slf *RankingList[CompetitorID, Score]) RegRankChangeEvent(handle game.RankChangeEventHandle[CompetitorID, Score]) { +func (slf *List[CompetitorID, Score]) RegRankChangeEvent(handle RankChangeEventHandle[CompetitorID, Score]) { slf.rankChangeEventHandles = append(slf.rankChangeEventHandles, handle) } -func (slf *RankingList[CompetitorID, Score]) OnRankChangeEvent(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) { +func (slf *List[CompetitorID, Score]) OnRankChangeEvent(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) { for _, handle := range slf.rankChangeEventHandles { handle(slf, competitorId, oldRank, newRank, oldScore, newScore) } } -func (slf *RankingList[CompetitorID, Score]) RegRankClearBeforeEvent(handle game.RankClearBeforeEventHandle[CompetitorID, Score]) { +func (slf *List[CompetitorID, Score]) RegRankClearBeforeEvent(handle RankClearBeforeEventHandle[CompetitorID, Score]) { slf.rankClearBeforeEventHandles = append(slf.rankClearBeforeEventHandles, handle) } -func (slf *RankingList[CompetitorID, Score]) OnRankClearBeforeEvent() { +func (slf *List[CompetitorID, Score]) OnRankClearBeforeEvent() { for _, handle := range slf.rankClearBeforeEventHandles { handle(slf) } diff --git a/game/ranking/list_errors.go b/game/ranking/list_errors.go new file mode 100644 index 0000000..b4db00c --- /dev/null +++ b/game/ranking/list_errors.go @@ -0,0 +1,9 @@ +package ranking + +import "errors" + +var ( + ErrListNotExistCompetitor = errors.New("ranking list not exist competitor") + ErrListIndexErr = errors.New("ranking list index error") + ErrListNonexistentRanking = errors.New("nonexistent ranking") +) diff --git a/game/ranking/list_events.go b/game/ranking/list_events.go new file mode 100644 index 0000000..6e6b925 --- /dev/null +++ b/game/ranking/list_events.go @@ -0,0 +1,37 @@ +package ranking + +import "github.com/kercylan98/minotaur/utils/generic" + +type ( + RankChangeEventHandle[CompetitorID comparable, Score generic.Ordered] func(list *List[CompetitorID, Score], competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) + RankClearBeforeEventHandle[CompetitorID comparable, Score generic.Ordered] func(list *List[CompetitorID, Score]) +) + +type event[CompetitorID comparable, Score generic.Ordered] struct { + rankChangeEventHandles []RankChangeEventHandle[CompetitorID, Score] + rankClearBeforeEventHandles []RankClearBeforeEventHandle[CompetitorID, Score] +} + +// RegRankChangeEventHandle 注册排行榜变更事件 +func (slf *event[CompetitorID, Score]) RegRankChangeEventHandle(handle RankChangeEventHandle[CompetitorID, Score]) { + slf.rankChangeEventHandles = append(slf.rankChangeEventHandles, handle) +} + +// OnRankChangeEvent 触发排行榜变更事件 +func (slf *event[CompetitorID, Score]) OnRankChangeEvent(list *List[CompetitorID, Score], competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) { + for _, handle := range slf.rankChangeEventHandles { + handle(list, competitorId, oldRank, newRank, oldScore, newScore) + } +} + +// RegRankClearBeforeEventHandle 注册排行榜清空前事件 +func (slf *event[CompetitorID, Score]) RegRankClearBeforeEventHandle(handle RankClearBeforeEventHandle[CompetitorID, Score]) { + slf.rankClearBeforeEventHandles = append(slf.rankClearBeforeEventHandles, handle) +} + +// OnRankClearBeforeEvent 触发排行榜清空前事件 +func (slf *event[CompetitorID, Score]) OnRankClearBeforeEvent(list *List[CompetitorID, Score]) { + for _, handle := range slf.rankClearBeforeEventHandles { + handle(list) + } +} diff --git a/game/builtin/ranking_list_example_test.go b/game/ranking/list_example_test.go similarity index 69% rename from game/builtin/ranking_list_example_test.go rename to game/ranking/list_example_test.go index 2dd4ece..6d28b2e 100644 --- a/game/builtin/ranking_list_example_test.go +++ b/game/ranking/list_example_test.go @@ -1,20 +1,20 @@ -package builtin_test +package ranking_test import ( "fmt" - "github.com/kercylan98/minotaur/game/builtin" + "github.com/kercylan98/minotaur/game/ranking" ) -func ExampleNewRankingList() { - ranklingList := builtin.NewRankingList[string, int](builtin.WithRankingListCount[string, int](10)) +func ExampleNewList() { + ranklingList := ranking.NewList[string, int](ranking.WithListCount[string, int](10)) fmt.Println(ranklingList != nil) // Output: // true } -func ExampleRankingList_Competitor() { - ranklingList := builtin.NewRankingList[string, int](builtin.WithRankingListCount[string, int](10)) +func ExampleList_Competitor() { + ranklingList := ranking.NewList[string, int](ranking.WithListCount[string, int](10)) scores := []int{6131, 132, 5133, 134, 135, 136, 137, 138, 139, 140, 222, 333, 444, 555, 666} for i := 1; i <= 15; i++ { @@ -38,8 +38,8 @@ func ExampleRankingList_Competitor() { // 9 competitor_ 8 } -func ExampleRankingList_RemoveCompetitor() { - ranklingList := builtin.NewRankingList[string, int](builtin.WithRankingListCount[string, int](10)) +func ExampleList_RemoveCompetitor() { + ranklingList := ranking.NewList[string, int](ranking.WithListCount[string, int](10)) scores := []int{6131, 132, 5133, 134, 135, 136, 137, 138, 139, 140, 222, 333, 444, 555, 666} for i := 1; i <= 15; i++ { @@ -62,8 +62,8 @@ func ExampleRankingList_RemoveCompetitor() { // 8 competitor_ 8 } -func ExampleRankingList_GetRank() { - ranklingList := builtin.NewRankingList[string, int](builtin.WithRankingListCount[string, int](10)) +func ExampleList_GetRank() { + ranklingList := ranking.NewList[string, int](ranking.WithListCount[string, int](10)) scores := []int{6131, 132, 5133, 134, 135, 136, 137, 138, 139, 140, 222, 333, 444, 555, 666} for i := 1; i <= 15; i++ { diff --git a/game/ranking/list_options.go b/game/ranking/list_options.go new file mode 100644 index 0000000..979ef10 --- /dev/null +++ b/game/ranking/list_options.go @@ -0,0 +1,24 @@ +package ranking + +import "github.com/kercylan98/minotaur/utils/generic" + +type ListOption[CompetitorID comparable, Score generic.Ordered] func(list *List[CompetitorID, Score]) + +// WithListCount 通过限制排行榜竞争者数量来创建排行榜 +// - 默认情况下允许100位竞争者 +func WithListCount[CompetitorID comparable, Score generic.Ordered](rankCount int) ListOption[CompetitorID, Score] { + return func(list *List[CompetitorID, Score]) { + if rankCount <= 0 { + rankCount = 1 + } + list.rankCount = rankCount + } +} + +// WithListASC 通过升序的方式创建排行榜 +// - 默认情况下为降序 +func WithListASC[CompetitorID comparable, Score generic.Ordered]() ListOption[CompetitorID, Score] { + return func(list *List[CompetitorID, Score]) { + list.asc = true + } +} diff --git a/game/ranking_list.go b/game/ranking_list.go deleted file mode 100644 index b20479e..0000000 --- a/game/ranking_list.go +++ /dev/null @@ -1,41 +0,0 @@ -package game - -import "github.com/kercylan98/minotaur/utils/generic" - -// RankingList 排行榜 -type RankingList[CompetitorID comparable, Score generic.Ordered] interface { - // Competitor 声明排行榜竞争者 - // - 如果竞争者存在的情况下,会更新已有成绩,否则新增竞争者 - Competitor(competitorId CompetitorID, score Score) - // RemoveCompetitor 删除特定竞争者 - RemoveCompetitor(competitorId CompetitorID) - // Size 获取竞争者数量 - Size() int - // GetRank 获取竞争者排名 - // - 排名从 0 开始 - GetRank(competitorId CompetitorID) (int, error) - // GetCompetitor 获取特定排名的竞争者 - GetCompetitor(rank int) (CompetitorID, error) - // GetCompetitorWithRange 获取第start名到第end名竞争者 - GetCompetitorWithRange(start, end int) ([]CompetitorID, error) - // GetScore 获取竞争者成绩 - GetScore(competitorId CompetitorID) (Score, error) - // GetAllCompetitor 获取所有竞争者ID - // - 结果为名次有序的 - GetAllCompetitor() []CompetitorID - // Clear 清空排行榜 - Clear() - - // RegRankChangeEvent 排名改变时将立即执行注册的事件处理函数 - // - 排名为-1时表示未上榜 - RegRankChangeEvent(handle RankChangeEventHandle[CompetitorID, Score]) - OnRankChangeEvent(competitorId CompetitorID, oldRank, newRank int, oldScore, newScore Score) - // RegRankClearBeforeEvent 在排行榜被清空前执行被注册的事件处理函数 - RegRankClearBeforeEvent(handle RankClearBeforeEventHandle[CompetitorID, Score]) - OnRankClearBeforeEvent() -} - -type ( - 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]) -)