Files
90CNServer/server/internal/modules/dnf/companion/team_test.go
T

96 lines
3.3 KiB
Go

package companion
import (
"reflect"
"testing"
)
func TestMatchTeamKeepsManualSelectionAndFillsByLevelAndJob(t *testing.T) {
candidates := []TeamCandidate{
{CharacterID: "1", Level: 90, Job: "0", Slot: 0},
{CharacterID: "2", Level: 90, Job: "12", Slot: 1},
{CharacterID: "3", Level: 90, Job: "3", Slot: 2},
{CharacterID: "4", Level: 90, Job: "0", Slot: 3},
{CharacterID: "5", Level: 21, Job: "2", Slot: 4},
}
match := MatchTeam("1", []string{"4"}, candidates, 3)
if want := []string{"4", "2", "3"}; !reflect.DeepEqual(match.Selected, want) {
t.Fatalf("selected=%v want=%v", match.Selected, want)
}
}
func TestMatchTeamSkipsOwnerOnlineDeletedLowLevelAndInvalid(t *testing.T) {
candidates := []TeamCandidate{
{CharacterID: "1", Level: 90, Job: "0", Slot: 0}, // owner
{CharacterID: "2", Level: 90, Job: "0", Slot: 1, Online: true}, // online
{CharacterID: "3", Level: 90, Job: "0", Slot: 2, Deleted: true},
{CharacterID: "4", Level: 0, Job: "0", Slot: 3},
{CharacterID: "5", Level: 90, Job: "x", Slot: 4},
{CharacterID: "0", Level: 90, Job: "0", Slot: 5},
{CharacterID: "6", Level: 90, Job: "1", Slot: 6},
}
match := MatchTeam("1", []string{"2", "3", "4", "5", "0", "99"}, candidates, 3)
if want := []string{"6"}; !reflect.DeepEqual(match.Selected, want) {
t.Fatalf("selected=%v want=%v", match.Selected, want)
}
assertSkip(t, match, "2") // online
assertSkip(t, match, "3") // deleted
assertSkip(t, match, "4") // low level
assertSkip(t, match, "5") // unsupported job
assertSkip(t, match, "99") // missing
}
func TestMatchTeamCapsAtThreeAndIsDeterministic(t *testing.T) {
candidates := []TeamCandidate{
{CharacterID: "9", Level: 90, Job: "0", Slot: 9},
{CharacterID: "7", Level: 90, Job: "2", Slot: 7},
{CharacterID: "8", Level: 90, Job: "4", Slot: 8},
{CharacterID: "6", Level: 90, Job: "1", Slot: 6},
}
first := MatchTeam("1", nil, candidates, 99)
if len(first.Selected) != TeamMaxCompanions {
t.Fatalf("selected=%v want %d entries", first.Selected, TeamMaxCompanions)
}
// Slot order wins inside the same-levelled, different-job set.
if want := []string{"6", "7", "8"}; !reflect.DeepEqual(first.Selected, want) {
t.Fatalf("selected=%v want=%v", first.Selected, want)
}
for i := 0; i < 20; i++ {
again := MatchTeam("1", nil, candidates, 99)
if !reflect.DeepEqual(again.Selected, first.Selected) {
t.Fatalf("iteration %d selected=%v want=%v", i, again.Selected, first.Selected)
}
}
}
func TestMatchTeamEmptyRosterReturnsNoSelection(t *testing.T) {
match := MatchTeam("1", []string{"2"}, nil, 3)
if len(match.Selected) != 0 {
t.Fatalf("selected=%v want empty", match.Selected)
}
assertSkip(t, match, "2")
}
func TestDefaultTeamAIProfileIsAggressiveAndJobScoped(t *testing.T) {
profile := DefaultTeamAIProfile(12)
if profile.Behavior != "aggressive" {
t.Fatalf("behavior=%q want aggressive", profile.Behavior)
}
if profile.ClassID != 12 {
t.Fatalf("class id=%d want 12", profile.ClassID)
}
if err := profile.Validate(); err != nil {
t.Fatalf("default team profile is invalid: %v", err)
}
}
func assertSkip(t *testing.T, match TeamMatch, id string) {
t.Helper()
for _, skipped := range match.Skipped {
if skipped.CharacterID == id {
return
}
}
t.Fatalf("candidate %s was not recorded as skipped: %+v", id, match.Skipped)
}