Skip to content

Commit

Permalink
Add captain diff penalty to respect avoids
Browse files Browse the repository at this point in the history
Fix new player in parties
  • Loading branch information
jauggy committed Oct 19, 2024
1 parent 3cd4a75 commit b38382a
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 30 deletions.
62 changes: 38 additions & 24 deletions lib/teiserver/battle/balance/brute_force_avoid.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ defmodule Teiserver.Battle.Balance.BruteForceAvoid do
@max_team_diff_importance 10000
@party_importance 1000
@avoid_importance 10
@captain_diff_importance 1

def get_best_combo(players, avoids, parties) do
potential_teams = potential_teams(length(players))
Expand All @@ -34,27 +35,13 @@ defmodule Teiserver.Battle.Balance.BruteForceAvoid do
players_with_index = Enum.with_index(players)

# Go through every possibility and get the combination with the lowest score
result =
Enum.map(combos, fn x ->
team = get_players_from_indexes(x, players_with_index)
result = score_combo(team, players, avoids, parties)
Map.put(result, :first_team, team)
end)
|> Enum.min_by(fn z ->
z.score
end)

first_team = result.first_team

second_team =
players
|> Enum.filter(fn x ->
!Enum.any?(first_team, fn y ->
y.id == x.id
end)
end)

Map.put(result, :second_team, second_team)
Enum.map(combos, fn x ->
team = get_players_from_indexes(x, players_with_index)
score_combo(team, players, avoids, parties)
end)
|> Enum.min_by(fn z ->
z.score
end)
end

@spec potential_teams(integer()) :: any()
Expand All @@ -71,11 +58,34 @@ defmodule Teiserver.Battle.Balance.BruteForceAvoid do
max(total_lobby_rating / num_teams * percentage_of_team, @max_team_diff_abs)
end

@spec score_combo([BF.player()], [BF.player()], [[number()]], [[number()]]) :: any()
@spec get_second_team([BF.player()], [BF.player()]) :: [BF.player()]
def get_second_team(first_team, all_players) do
all_players
|> Enum.filter(fn player -> !Enum.any?(first_team, fn x -> x.id == player.id end) end)
end

@spec get_captain_rating([BF.player()]) :: any()
def get_captain_rating(team) do
if(length(team) > 0) do
captain = Enum.max_by(team, fn player -> player.rating end, &>=/2)
captain.rating
else
0
end
end

@spec score_combo([BF.player()], [BF.player()], [[number()]], [[number()]]) :: BF.combo_result()
def score_combo(first_team, all_players, avoids, parties) do
second_team = get_second_team(first_team, all_players)
first_team_rating = get_team_rating(first_team)

both_team_rating = get_team_rating(all_players)
rating_diff_penalty = abs(both_team_rating - first_team_rating * 2)

captain_diff_penalty =
abs(get_captain_rating(first_team) - get_captain_rating(second_team)) *
@captain_diff_importance

num_teams = 2

max_team_diff_penalty =
Expand All @@ -100,13 +110,17 @@ defmodule Teiserver.Battle.Balance.BruteForceAvoid do
end

score =
rating_diff_penalty + broken_avoid_penalty + broken_party_penalty + max_team_diff_penalty
rating_diff_penalty + broken_avoid_penalty + broken_party_penalty + max_team_diff_penalty +
captain_diff_penalty

%{
score: score,
rating_diff_penalty: rating_diff_penalty,
broken_avoid_penalty: broken_avoid_penalty,
broken_party_penalty: broken_party_penalty
broken_party_penalty: broken_party_penalty,
captain_diff_penalty: captain_diff_penalty,
second_team: second_team,
first_team: first_team
}
end

Expand Down
1 change: 1 addition & 0 deletions lib/teiserver/battle/balance/brute_force_avoid_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ defmodule Teiserver.Battle.Balance.BruteForceAvoidTypes do
broken_avoid_penalty: number(),
broken_party_penalty: number(),
rating_diff_penalty: number(),
captain_diff_penalty: number(),
score: number(),
first_team: [player()],
second_team: [player()]
Expand Down
9 changes: 5 additions & 4 deletions lib/teiserver/battle/balance/respect_avoids.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ defmodule Teiserver.Battle.Balance.RespectAvoids do
players = flatten_members(expanded_group)
parties = get_parties(expanded_group)

noobs = get_noobs(players) |> sort_noobs()
noobs = get_solo_noobs(players) |> sort_noobs()
experienced_players = get_experienced_players(players, noobs)
experienced_player_ids = experienced_players |> Enum.map(fn x -> x.id end)
players_in_parties_count = parties |> List.flatten() |> Enum.count()
Expand Down Expand Up @@ -297,6 +297,7 @@ defmodule Teiserver.Battle.Balance.RespectAvoids do
"Team rating diff penalty: #{format(combo_result.rating_diff_penalty)}",
"Broken party penalty: #{combo_result.broken_party_penalty}",
"Broken avoid penalty: #{combo_result.broken_avoid_penalty}",
"Captain rating diff penalty: #{format(combo_result.captain_diff_penalty)}",
"Score: #{format(combo_result.score)} (lower is better)",
@splitter,
"Draft remaining players (ordered from best to worst).",
Expand Down Expand Up @@ -514,10 +515,10 @@ defmodule Teiserver.Battle.Balance.RespectAvoids do
end

# Noobs have high uncertainty and chev 1,2,3
@spec get_noobs([RA.player()]) :: any()
def get_noobs(players) do
@spec get_solo_noobs([RA.player()]) :: any()
def get_solo_noobs(players) do
Enum.filter(players, fn player ->
is_newish_player?(player.rank, player.uncertainty)
is_newish_player?(player.rank, player.uncertainty) && !player.in_party?
end)
end

Expand Down
83 changes: 83 additions & 0 deletions test/teiserver/battle/brute_force_avoid_internal_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
defmodule Teiserver.Battle.BruteForceAvoidInternalTest do
@moduledoc """
Can run all balance tests via
mix test --only balance_test
"""
use ExUnit.Case
@moduletag :balance_test
alias Teiserver.Battle.Balance.BruteForceAvoid

test "can get second team" do
players = [
%{name: "kyutoryu", rating: 12.25, id: 1},
%{name: "fbots1998", rating: 13.98, id: 2},
%{name: "Dixinormus", rating: 18.28, id: 3},
%{name: "HungDaddy", rating: 2.8, id: 4},
%{name: "SLOPPYGAGGER", rating: 8.89, id: 5},
%{name: "jauggy", rating: 20.49, id: 6},
%{name: "reddragon2010", rating: 18.4, id: 7},
%{name: "Aposis", rating: 20.42, id: 8},
%{name: "MaTThiuS_82", rating: 8.26, id: 9},
%{name: "Noody", rating: 17.64, id: 10},
%{name: "[DTG]BamBin0", rating: 20.06, id: 11},
%{name: "barmalev", rating: 3.58, id: 12}
]

first_team = [
%{name: "kyutoryu", rating: 12.25, id: 1},
%{name: "fbots1998", rating: 13.98, id: 2},
%{name: "Dixinormus", rating: 18.28, id: 3},
%{name: "HungDaddy", rating: 2.8, id: 4},
%{name: "SLOPPYGAGGER", rating: 8.89, id: 5},
%{name: "jauggy", rating: 20.49, id: 6}
]

result = BruteForceAvoid.get_second_team(first_team, players)

assert result == [
%{id: 7, name: "reddragon2010", rating: 18.4},
%{id: 8, name: "Aposis", rating: 20.42},
%{id: 9, name: "MaTThiuS_82", rating: 8.26},
%{id: 10, name: "Noody", rating: 17.64},
%{id: 11, name: "[DTG]BamBin0", rating: 20.06},
%{id: 12, name: "barmalev", rating: 3.58}
]
end

test "can get second team - side cases" do
players = []

first_team = []

result = BruteForceAvoid.get_second_team(first_team, players)

assert result == []

players = [%{id: 7, name: "reddragon2010", rating: 18.4}]

first_team = [%{id: 7, name: "reddragon2010", rating: 18.4}]

result = BruteForceAvoid.get_second_team(first_team, players)

assert result == []
end

test "can get captain rating" do
first_team = [
%{name: "kyutoryu", rating: 12.25, id: 1},
%{name: "fbots1998", rating: 13.98, id: 2},
%{name: "Dixinormus", rating: 18.28, id: 3},
%{name: "HungDaddy", rating: 2.8, id: 4},
%{name: "SLOPPYGAGGER", rating: 8.89, id: 5},
%{name: "jauggy", rating: 20.49, id: 6}
]

result = BruteForceAvoid.get_captain_rating(first_team)

assert result == 20.49

result = BruteForceAvoid.get_captain_rating([])

assert result == 0
end
end
Loading

0 comments on commit b38382a

Please sign in to comment.