Skip to content

Commit abd8d0b

Browse files
committed
feat: add round win limit handling in ScoreService and ScoreRepository
1 parent 26243b1 commit abd8d0b

3 files changed

Lines changed: 76 additions & 10 deletions

File tree

internal/model/score.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type Match struct {
3838
RosterAwayID int `gorm:"column:away_team_id"`
3939
RosterHomeID int `gorm:"column:home_team_id"`
4040
WinLimit int `gorm:"column:win_limit"`
41+
RoundWinLimit int `gorm:"column:round_win_limit"`
4142
}
4243

4344
// TableName overrides the table name for Match

internal/repository/score_repository.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,49 @@ func (r *ScoreRepository) UpdateMatchStatus(matchID, status int) error {
8080

8181
return nil
8282
}
83+
84+
// HasTeamReachedRoundWinLimit checks whether either team reached the configured round win limit
85+
func (r *ScoreRepository) HasTeamReachedRoundWinLimit(matchID int) (bool, error) {
86+
var match model.Match
87+
matchQuery := r.db.Select("round_win_limit", "home_team_id", "away_team_id").Where("id = ?", matchID).First(&match)
88+
if matchQuery.Error != nil {
89+
return false, fmt.Errorf("failed to fetch match info: %w", matchQuery.Error)
90+
}
91+
92+
validWinners := make(map[int]struct{})
93+
if match.RosterHomeID != 0 {
94+
validWinners[match.RosterHomeID] = struct{}{}
95+
}
96+
if match.RosterAwayID != 0 {
97+
validWinners[match.RosterAwayID] = struct{}{}
98+
}
99+
100+
if match.RoundWinLimit <= 0 || len(validWinners) == 0 {
101+
return false, nil
102+
}
103+
104+
var rounds []model.MatchRound
105+
roundsQuery := r.db.Select("winner_id").Where("match_id = ?", matchID).Find(&rounds)
106+
if roundsQuery.Error != nil {
107+
return false, fmt.Errorf("failed to fetch match rounds: %w", roundsQuery.Error)
108+
}
109+
110+
wins := make(map[int]int)
111+
for _, round := range rounds {
112+
if round.WinnerID == nil {
113+
continue
114+
}
115+
116+
winnerID := *round.WinnerID
117+
if _, ok := validWinners[winnerID]; !ok {
118+
continue
119+
}
120+
121+
wins[winnerID]++
122+
if wins[winnerID] >= match.RoundWinLimit {
123+
return true, nil
124+
}
125+
}
126+
127+
return false, nil
128+
}

internal/service/score_service.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,44 @@ func (s *ScoreService) ProcessScoreData(scoreData *model.ScoreData) error {
5252
// Continue processing even if this check fails
5353
}
5454

55-
// If all rounds are done, update match status to completed (status 3)
56-
if allDone {
57-
err = s.repo.UpdateMatchStatus(scoreData.MatchID, 3)
58-
if err != nil {
59-
logger.Log.Error("Failed to update match status", zap.Error(err))
60-
return fmt.Errorf("error updating match status: %w", err)
55+
shouldComplete := allDone
56+
completionReason := "all rounds completed"
57+
if !shouldComplete {
58+
reachedLimit, checkErr := s.repo.HasTeamReachedRoundWinLimit(scoreData.MatchID)
59+
if checkErr != nil {
60+
logger.Log.Error("Failed to determine if round win limit was reached", zap.Error(checkErr))
61+
} else if reachedLimit {
62+
shouldComplete = true
63+
completionReason = "round win limit reached"
6164
}
65+
}
6266

63-
// Update scores again after marking match as complete
64-
if err := s.updateScores(scoreData.MatchID); err != nil {
65-
logger.Log.Error("Failed to update scores via external API after completion", zap.Error(err))
66-
return fmt.Errorf("error updating scores: %w", err)
67+
if shouldComplete {
68+
logger.Log.Info("Marking match as completed", zap.Int("matchID", scoreData.MatchID), zap.String("reason", completionReason))
69+
if err := s.completeMatch(scoreData.MatchID); err != nil {
70+
return err
6771
}
6872
}
6973

7074
logger.Log.Info("Successfully processed score data", zap.Int("matchID", scoreData.MatchID), zap.Int("roundID", scoreData.RoundID))
7175
return nil
7276
}
7377

78+
// completeMatch finalizes a match by setting its status and notifying the league site
79+
func (s *ScoreService) completeMatch(matchID int) error {
80+
if err := s.repo.UpdateMatchStatus(matchID, 3); err != nil {
81+
logger.Log.Error("Failed to update match status", zap.Error(err), zap.Int("matchID", matchID))
82+
return fmt.Errorf("error updating match status: %w", err)
83+
}
84+
85+
if err := s.updateScores(matchID); err != nil {
86+
logger.Log.Error("Failed to update scores via external API after completion", zap.Error(err), zap.Int("matchID", matchID))
87+
return fmt.Errorf("error updating scores: %w", err)
88+
}
89+
90+
return nil
91+
}
92+
7493
// updateScores calls the external API to update scores
7594
func (s *ScoreService) updateScores(matchID int) error {
7695
updateScoresURL := fmt.Sprintf("https://udl.tf/leagues/matches/%d/update_scores", matchID)

0 commit comments

Comments
 (0)