Add event management features to API, including event cancellation, deletion, registration closure, and workflow balance generation. Introduce new roster management endpoints and enhance participant handling with avoided player preferences. Update database schema and service logic to support these changes.
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / compose (push) Has been cancelled

This commit is contained in:
2026-07-19 02:10:02 +03:00
parent 59c0bdb345
commit 4b889fb8a0
30 changed files with 2766 additions and 149 deletions

View File

@@ -107,10 +107,11 @@ func buildCandidate(eventID string, players []Player, variant int, roleOrder []R
}
optimizeCandidate(c.Teams, players)
c.Score = balanceScore(c.Teams, players)
preferredRoles, preferredTeammates := preferenceStats(c.Teams, players)
preferredRoles, preferredTeammates, avoidedTeammates := preferenceStats(c.Teams, players)
c.Explanation = []string{
fmt.Sprintf("%d preferred role assignments satisfied", preferredRoles),
fmt.Sprintf("%d preferred teammate choices satisfied", preferredTeammates),
fmt.Sprintf("%d avoided teammate choices satisfied", avoidedTeammates),
}
return c
}
@@ -146,6 +147,7 @@ func balanceScore(teams []Team, players []Player) int {
}
}
preferredTeammatePenalty := 0
avoidedTeammatePenalty := 0
for _, player := range players {
teamIndex, active := teamByPlayer[player.ID]
if !active {
@@ -156,8 +158,13 @@ func balanceScore(teams []Team, players []Player) int {
preferredTeammatePenalty += 8
}
}
for _, avoidedID := range player.AvoidedPlayerIDs {
if avoidedTeam, avoidedActive := teamByPlayer[avoidedID]; avoidedActive && avoidedTeam == teamIndex {
avoidedTeammatePenalty += 14
}
}
}
score := (maxTotal-minTotal)*3 + weakRolePenalty + preferredRolePenalty + preferredTeammatePenalty
score := (maxTotal-minTotal)*3 + weakRolePenalty + preferredRolePenalty + preferredTeammatePenalty + avoidedTeammatePenalty
for _, totals := range roleTotals {
minimum, maximum := math.MaxInt, 0
for _, total := range totals {
@@ -198,7 +205,7 @@ func optimizeCandidate(teams []Team, players []Player) {
}
}
func preferenceStats(teams []Team, players []Player) (int, int) {
func preferenceStats(teams []Team, players []Player) (int, int, int) {
playerByID := make(map[string]Player, len(players))
teamByPlayer := make(map[string]int)
roleByPlayer := make(map[string]Role)
@@ -211,7 +218,7 @@ func preferenceStats(teams []Team, players []Player) (int, int) {
roleByPlayer[slot.PlayerID] = slot.Role
}
}
roleMatches, teammateMatches := 0, 0
roleMatches, teammateMatches, avoidedMatches := 0, 0, 0
for playerID, teamIndex := range teamByPlayer {
player := playerByID[playerID]
if len(player.PreferredRoles) > 0 && slices.Contains(player.PreferredRoles, roleByPlayer[playerID]) {
@@ -222,8 +229,13 @@ func preferenceStats(teams []Team, players []Player) (int, int) {
teammateMatches++
}
}
for _, avoidedID := range player.AvoidedPlayerIDs {
if avoidedTeam, ok := teamByPlayer[avoidedID]; ok && avoidedTeam != teamIndex {
avoidedMatches++
}
}
}
return roleMatches, teammateMatches
return roleMatches, teammateMatches, avoidedMatches
}
func candidateSignature(candidate BalanceCandidate) string {