From fca9336c307dba60860d6e3cad08c2159414814b Mon Sep 17 00:00:00 2001 From: David Zhang Date: Wed, 28 Aug 2024 15:32:19 +0800 Subject: [PATCH] feat: add qualification/elimination win rate --- internal/converter/converter.go | 10 +++-- internal/entity/game.go | 7 ++++ internal/entity/player.go | 13 ++++--- internal/operator/double_player_rank.go | 49 +++++++++++++++++-------- internal/operator/single_player_rank.go | 35 ++++++++++++------ 5 files changed, 76 insertions(+), 38 deletions(-) diff --git a/internal/converter/converter.go b/internal/converter/converter.go index a93f1bf..0bfec8b 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -86,7 +86,7 @@ func (c *Converter) convertGames( rec := &c.record // preliminary rounds for _, r := range t.Rounds { - games, err := c.convertPlayToGame(r.Name, r.Plays, teams, players) + games, err := c.convertPlayToGame(r.Name, entity.GameTypeQualification, r.Plays, teams, players) if err != nil { return err } @@ -95,20 +95,20 @@ func (c *Converter) convertGames( for _, ko := range t.KnockOffs { for _, level := range ko.Levels { - games, err := c.convertPlayToGame(level.Name, level.Plays, teams, players) + games, err := c.convertPlayToGame(level.Name, entity.GameTypeElimination, level.Plays, teams, players) if err != nil { return err } rec.WinnerBracket = append(rec.WinnerBracket, games...) } for _, level := range ko.LeftLevels { - games, err := c.convertPlayToGame(level.Name, level.Plays, teams, players) + games, err := c.convertPlayToGame(level.Name, entity.GameTypeElimination, level.Plays, teams, players) if err != nil { return err } rec.LoserBracket = append(rec.LoserBracket, games...) } - games, err := c.convertPlayToGame(ko.Third.Name, ko.Third.Plays, teams, players) + games, err := c.convertPlayToGame(ko.Third.Name, entity.GameTypeElimination, ko.Third.Plays, teams, players) if err != nil { return err } @@ -300,6 +300,7 @@ func (Converter) validPlay(p model.Play) bool { func (c Converter) convertPlayToGame( name string, + gameType int, plays []model.Play, teams map[string]model.Team, players map[string]model.Player) ([]entity.Game, error) { @@ -324,6 +325,7 @@ func (c Converter) convertPlayToGame( } else { continue } + game.GameType = gameType game.TimeStart = p.TimeStart game.TimeEnd = p.TimeEnd game.TimePlayed = (p.TimeEnd - p.TimeStart) / 1000 diff --git a/internal/entity/game.go b/internal/entity/game.go index 091e900..0ede6d9 100644 --- a/internal/entity/game.go +++ b/internal/entity/game.go @@ -5,6 +5,7 @@ type Game struct { Team1 []string Team2 []string + GameType int // 1: qualification, 2: elimination TimeStart int TimeEnd int TimePlayed int @@ -16,6 +17,12 @@ type Game struct { Sets []Set } +// Game types +const ( + GameTypeQualification = iota + 1 + GameTypeElimination +) + // Set is stat for single set type Set struct { Point1 int diff --git a/internal/entity/player.go b/internal/entity/player.go index e000116..f986b27 100644 --- a/internal/entity/player.go +++ b/internal/entity/player.go @@ -26,12 +26,13 @@ type Player struct { ATSAPoints int `yaml:"-"` // ATSA points ITSFPoints int `yaml:"-"` // ITSF points // minor statistical data - HomeWin int `yaml:"-"` - HomeLoss int `yaml:"-"` - HomeWinRate float64 `yaml:"-"` - AwayWin int `yaml:"-"` - AwayLoss int `yaml:"-"` - AwayWinRate float64 `yaml:"-"` + QualificationWin int `yaml:"-"` + QualificationDraw int `yaml:"-"` + QualificationLoss int `yaml:"-"` + QualificationWinRate float64 `yaml:"-"` + EliminationWin int `yaml:"-"` + EliminationLoss int `yaml:"-"` + EliminationWinRate float64 `yaml:"-"` // data not implemented right now TimePlayed int `yaml:"-"` LongestGameTime int `yaml:"-"` diff --git a/internal/operator/double_player_rank.go b/internal/operator/double_player_rank.go index 279114b..525da78 100644 --- a/internal/operator/double_player_rank.go +++ b/internal/operator/double_player_rank.go @@ -58,25 +58,44 @@ func (o *DoublePlayerRank) Output() { t1p2Data.Win++ t2p1Data.Loss++ t2p2Data.Loss++ - t1p1Data.HomeWin++ - t1p2Data.HomeWin++ - t2p1Data.AwayLoss++ - t2p2Data.AwayLoss++ + if g.GameType == entity.GameTypeQualification { + t1p1Data.QualificationWin++ + t1p2Data.QualificationWin++ + t2p1Data.QualificationLoss++ + t2p2Data.QualificationLoss++ + } else if g.GameType == entity.GameTypeElimination { + t1p1Data.EliminationWin++ + t1p2Data.EliminationWin++ + t2p1Data.EliminationLoss++ + t2p2Data.EliminationLoss++ + } } else if g.Point2 > g.Point1 { t1p1Data.Loss++ t1p2Data.Loss++ t2p1Data.Win++ t2p2Data.Win++ - t1p1Data.HomeLoss++ - t1p2Data.HomeLoss++ - t2p1Data.AwayWin++ - t2p2Data.AwayWin++ + if g.GameType == entity.GameTypeQualification { + t1p1Data.QualificationLoss++ + t1p2Data.QualificationLoss++ + t2p1Data.QualificationWin++ + t2p2Data.QualificationWin++ + } else if g.GameType == entity.GameTypeElimination { + t1p1Data.EliminationLoss++ + t1p2Data.EliminationLoss++ + t2p1Data.EliminationWin++ + t2p2Data.EliminationWin++ + } } else { - // basically not approachable t1p1Data.Draw++ t1p2Data.Draw++ t2p1Data.Draw++ t2p2Data.Draw++ + if g.GameType == entity.GameTypeElimination { + t1p1Data.QualificationDraw++ + t1p2Data.QualificationDraw++ + t2p1Data.QualificationDraw++ + t2p2Data.QualificationDraw++ + } } // }}} // {{{ ELO @@ -174,12 +193,8 @@ func (o *DoublePlayerRank) Output() { for _, d := range data { if d.GamesPlayed != 0 { d.WinRate = float64(d.Win) / float64(d.GamesPlayed) * 100.0 - if d.HomeWin+d.HomeLoss > 0 { - d.HomeWinRate = float64(d.HomeWin) / float64(d.HomeWin+d.HomeLoss) * 100.0 - } - if d.AwayWin+d.AwayLoss > 0 { - d.AwayWinRate = float64(d.AwayWin) / float64(d.AwayWin+d.AwayLoss) * 100.0 - } + d.QualificationWinRate = float64(d.QualificationWin) / float64(d.QualificationWin+d.QualificationDraw+d.QualificationLoss) * 100.0 + d.EliminationWinRate = float64(d.EliminationWin) / float64(d.EliminationWin+d.EliminationLoss) * 100.0 sliceData = append(sliceData, d) } } @@ -228,7 +243,7 @@ func (o *DoublePlayerRank) Output() { sliceData = sliceData[len(sliceData)-o.options.Tail:] } - header := []string{"#", "Name", "Events", "Games", "Win", "Loss", "Draw", "WR%", "ELO", "KRP", "ATSA", "ITSF"} + header := []string{"#", "Name", "Events", "Games", "Win", "Loss", "Draw", "WR%", "QWR%", "ELR%", "ELO", "KRP", "ATSA", "ITSF"} table := [][]string{} index := 1 for _, d := range sliceData { @@ -244,6 +259,8 @@ func (o *DoublePlayerRank) Output() { fmt.Sprintf("%d", d.Loss), fmt.Sprintf("%d", d.Draw), fmt.Sprintf("%.0f%%", d.WinRate), + fmt.Sprintf("%.0f%%", d.QualificationWinRate), + fmt.Sprintf("%.0f%%", d.EliminationWinRate), fmt.Sprintf("%.0f", d.EloRating), fmt.Sprintf("%d", d.KickerPoints), fmt.Sprintf("%d", d.ATSAPoints), diff --git a/internal/operator/single_player_rank.go b/internal/operator/single_player_rank.go index 51700c6..ae4e8e7 100644 --- a/internal/operator/single_player_rank.go +++ b/internal/operator/single_player_rank.go @@ -50,17 +50,30 @@ func (o *SinglePlayerRank) Output() { if g.Point1 > g.Point2 { p1Data.Win++ p2Data.Loss++ - p1Data.HomeWin++ - p2Data.AwayLoss++ + if g.GameType == entity.GameTypeQualification { + p1Data.QualificationWin++ + p2Data.QualificationLoss++ + } else if g.GameType == entity.GameTypeElimination { + p1Data.EliminationWin++ + p2Data.EliminationLoss++ + } } else if g.Point2 > g.Point1 { p1Data.Loss++ p2Data.Win++ - p1Data.HomeLoss++ - p2Data.AwayWin++ + if g.GameType == entity.GameTypeQualification { + p1Data.QualificationLoss++ + p2Data.QualificationWin++ + } else if g.GameType == entity.GameTypeElimination { + p1Data.EliminationLoss++ + p2Data.EliminationWin++ + } } else { - // basically not approachable p1Data.Draw++ p2Data.Draw++ + if g.GameType == entity.GameTypeElimination { + p1Data.QualificationDraw++ + p2Data.QualificationDraw++ + } } // }}} // {{{ ELO @@ -136,12 +149,8 @@ func (o *SinglePlayerRank) Output() { for _, d := range data { if d.GamesPlayed != 0 { d.WinRate = float64(d.Win) / float64(d.GamesPlayed) * 100.0 - if d.HomeWin+d.HomeLoss > 0 { - d.HomeWinRate = float64(d.HomeWin) / float64(d.HomeWin+d.HomeLoss) * 100.0 - } - if d.AwayWin+d.AwayLoss > 0 { - d.AwayWinRate = float64(d.AwayWin) / float64(d.AwayWin+d.AwayLoss) * 100.0 - } + d.QualificationWinRate = float64(d.QualificationWin) / float64(d.QualificationWin+d.QualificationDraw+d.QualificationLoss) * 100.0 + d.EliminationWinRate = float64(d.EliminationWin) / float64(d.EliminationWin+d.EliminationLoss) * 100.0 sliceData = append(sliceData, d) } } @@ -190,7 +199,7 @@ func (o *SinglePlayerRank) Output() { sliceData = sliceData[len(sliceData)-o.options.Tail:] } - header := []string{"#", "Name", "Events", "Games", "Win", "Loss", "Draw", "WR%", "ELO", "KRP", "ATSA", "ITSF"} + header := []string{"#", "Name", "Events", "Games", "Win", "Loss", "Draw", "WR%", "QWR%", "EWR%", "ELO", "KRP", "ATSA", "ITSF"} table := [][]string{} index := 1 for _, d := range sliceData { @@ -206,6 +215,8 @@ func (o *SinglePlayerRank) Output() { fmt.Sprintf("%d", d.Loss), fmt.Sprintf("%d", d.Draw), fmt.Sprintf("%.0f%%", d.WinRate), + fmt.Sprintf("%.0f%%", d.QualificationWinRate), + fmt.Sprintf("%.0f%%", d.EliminationWinRate), fmt.Sprintf("%.0f", d.EloRating), fmt.Sprintf("%d", d.KickerPoints), fmt.Sprintf("%d", d.ATSAPoints),