Files
mixmaker/backend/internal/domain/balancer_test.go
lemintare 1239fcee08
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / compose (push) Has been cancelled
Initialize project with basic structure, including Docker configuration, backend and frontend setup, environment configuration, and essential files for development.
2026-07-19 00:17:31 +03:00

98 lines
2.5 KiB
Go

package domain
import (
"fmt"
"reflect"
"testing"
)
func TestBalanceProducesDeterministicFullTeamsAndReserve(t *testing.T) {
var players []Player
for i := 0; i < 23; i++ {
players = append(players, Player{
ID: fmt.Sprintf("p%02d", i),
Ratings: Ratings{
Tank: 5 + i%36,
Damage: 5 + (i*3)%36,
Support: 5 + (i*7)%36,
},
})
}
first, err := Balance("event", players)
if err != nil {
t.Fatal(err)
}
second, _ := Balance("event", players)
if !reflect.DeepEqual(first, second) {
t.Fatal("balancer output is not deterministic")
}
if len(first) != 3 {
t.Fatalf("got %d candidates", len(first))
}
for _, candidate := range first {
if len(candidate.Teams) != 4 || len(candidate.Reserve) != 3 {
t.Fatalf("unexpected allocation: %d teams, %d reserve", len(candidate.Teams), len(candidate.Reserve))
}
for _, team := range candidate.Teams {
counts := map[Role]int{}
for _, slot := range team.Slots {
counts[slot.Role]++
}
if counts[Tank] != 1 || counts[Damage] != 2 || counts[Support] != 2 {
t.Fatalf("invalid composition: %#v", counts)
}
}
}
}
func TestBalanceKeepsOddNumberOfFullTeams(t *testing.T) {
players := make([]Player, 15)
for i := range players {
players[i] = Player{
ID: fmt.Sprintf("p%02d", i),
Ratings: Ratings{Tank: 10 + i, Damage: 15 + i%20, Support: 8 + (i*3)%30},
}
}
candidates, err := Balance("event", players)
if err != nil {
t.Fatal(err)
}
for _, candidate := range candidates {
if len(candidate.Teams) != 3 || len(candidate.Reserve) != 0 {
t.Fatalf("expected three full teams, got %d teams and %d reserve", len(candidate.Teams), len(candidate.Reserve))
}
}
}
func TestBalanceUsesSoftRoleAndTeammatePreferences(t *testing.T) {
players := make([]Player, 10)
for i := range players {
players[i] = Player{
ID: fmt.Sprintf("p%02d", i),
Ratings: Ratings{Tank: 20, Damage: 20, Support: 20},
}
}
players[0].PreferredRoles = []Role{Support}
players[0].PreferredPlayerIDs = []string{"p01"}
candidates, err := Balance("event", players)
if err != nil {
t.Fatal(err)
}
best := candidates[0]
var teamForP0, teamForP1 int = -1, -1
var roleForP0 Role
for teamIndex, team := range best.Teams {
for _, slot := range team.Slots {
switch slot.PlayerID {
case "p00":
teamForP0, roleForP0 = teamIndex, slot.Role
case "p01":
teamForP1 = teamIndex
}
}
}
if teamForP0 != teamForP1 || roleForP0 != Support {
t.Fatalf("preferences were not reflected in best candidate: role=%s teams=%d/%d", roleForP0, teamForP0, teamForP1)
}
}