Skip to content

Commit 182e034

Browse files
committed
Call teifion's algo when not enough noobs
More improvements
1 parent 2cd66d9 commit 182e034

File tree

5 files changed

+148
-21
lines changed

5 files changed

+148
-21
lines changed

lib/teiserver/battle/balance/cheeky_switcher_smart.ex

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ defmodule Teiserver.Battle.Balance.CheekySwitcherSmart do
2020
# Alias the types
2121
alias Teiserver.Battle.BalanceLib
2222
alias Teiserver.Battle.Balance.BalanceTypes, as: BT
23+
import Teiserver.Helper.NumberHelper, only: [format: 1]
2324

2425
# @type algorithm_state :: %{
2526
# teams: map,
@@ -158,7 +159,7 @@ defmodule Teiserver.Battle.Balance.CheekySwitcherSmart do
158159
|> Enum.map(fn {group, _} ->
159160
group.names
160161
|> Enum.with_index()
161-
|> Enum.map(fn {name, i} -> "#{name}[#{Enum.at(group.ratings, i)}]" end)
162+
|> Enum.map(fn {name, i} -> "#{name}[#{format(Enum.at(group.ratings, i))}]" end)
162163
end)
163164
|> List.flatten()
164165
|> Enum.join(",")
@@ -168,7 +169,7 @@ defmodule Teiserver.Battle.Balance.CheekySwitcherSmart do
168169
|> Enum.map(fn {group, _} ->
169170
group.names
170171
|> Enum.with_index()
171-
|> Enum.map(fn {name, i} -> "#{name}[#{Enum.at(group.ratings, i)}]" end)
172+
|> Enum.map(fn {name, i} -> "#{name}[#{format(Enum.at(group.ratings, i))}]" end)
172173
end)
173174
|> List.flatten()
174175
|> Enum.join(",")
@@ -429,11 +430,11 @@ defmodule Teiserver.Battle.Balance.CheekySwitcherSmart do
429430

430431
if next_group.count > 1 do
431432
[
432-
"Group picked #{names |> Enum.join(", ")} for team #{team_key}, adding #{group_rating} points for a new total of #{round(existing_team_rating + group_rating)}"
433+
"Group picked #{names |> Enum.join(", ")} for team #{team_key}, adding #{format(group_rating)} points for a new total of #{round(existing_team_rating + group_rating)}"
433434
]
434435
else
435436
[
436-
"Picked #{Enum.at(names, 0)} for team #{team_key}, adding #{group_rating} points for a new total of #{round(existing_team_rating + group_rating)}"
437+
"Picked #{Enum.at(names, 0)} for team #{team_key}, adding #{format(group_rating)} points for a new total of #{round(existing_team_rating + group_rating)}"
437438
]
438439
end
439440
end

lib/teiserver/battle/balance/split_one_chevs.ex

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ defmodule Teiserver.Battle.Balance.SplitOneChevs do
1818
"""
1919
alias Teiserver.Battle.Balance.SplitOneChevsTypes, as: ST
2020
alias Teiserver.Battle.Balance.BalanceTypes, as: BT
21+
import Teiserver.Helper.NumberHelper, only: [format: 1]
2122

2223
@splitter "---------------------------"
2324

@@ -26,10 +27,34 @@ defmodule Teiserver.Battle.Balance.SplitOneChevs do
2627
See split_one_chevs_internal_test.exs for sample input
2728
"""
2829
@spec perform([BT.expanded_group()], non_neg_integer(), list()) :: any()
29-
def perform(expanded_group, team_count, _opts \\ []) do
30-
members = flatten_members(expanded_group) |> sort_members()
31-
%{teams: teams, logs: logs} = assign_teams(members, team_count)
32-
standardise_result(teams, logs)
30+
def perform(expanded_group, team_count, opts \\ []) do
31+
if has_enough_noobs?(expanded_group) do
32+
members = flatten_members(expanded_group) |> sort_members()
33+
%{teams: teams, logs: logs} = assign_teams(members, team_count)
34+
standardise_result(teams, logs)
35+
else
36+
# Not enough noobs; so call another balancer
37+
result = Teiserver.Battle.Balance.LoserPicks.perform(expanded_group, team_count, opts)
38+
39+
new_logs =
40+
["Not enough noobs; calling another balancer.", @splitter, result.logs]
41+
|> List.flatten()
42+
43+
Map.put(result, :logs, new_logs)
44+
end
45+
end
46+
47+
@spec has_enough_noobs?([BT.expanded_group()]) :: bool()
48+
def has_enough_noobs?(expanded_group) do
49+
ranks =
50+
Enum.map(expanded_group, fn x ->
51+
Map.get(x, :ranks, [])
52+
end)
53+
|> List.flatten()
54+
55+
Enum.any?(ranks, fn x ->
56+
x < 2
57+
end)
3358
end
3459

3560
@doc """
@@ -73,16 +98,6 @@ defmodule Teiserver.Battle.Balance.SplitOneChevs do
7398
|> List.flatten()
7499
end
75100

76-
defp round_number(rating_value) when is_float(rating_value) do
77-
rating_value
78-
|> Decimal.from_float()
79-
|> Decimal.round(1)
80-
end
81-
82-
defp round_number(rating_value) when is_integer(rating_value) do
83-
rating_value
84-
end
85-
86101
@doc """
87102
Assigns teams using algorithm defined in moduledoc
88103
See split_one_chevs_internal_test.exs for sample input
@@ -104,7 +119,7 @@ defmodule Teiserver.Battle.Balance.SplitOneChevs do
104119
username = x.name
105120

106121
new_log =
107-
"#{username} (#{round_number(x.rating)}, σ: #{round_number(x.uncertainty)}, Chev: #{x.rank + 1}) picked for Team #{picking_team.team_id}"
122+
"#{username} (#{format(x.rating)}, σ: #{format(x.uncertainty)}, Chev: #{x.rank + 1}) picked for Team #{picking_team.team_id}"
108123

109124
%{
110125
teams: [update_picking_team | get_non_picking_teams(acc.teams, picking_team)],

lib/teiserver/helpers/number_helper.ex

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,20 @@ defmodule Teiserver.Helper.NumberHelper do
120120
def percent(v, dp) do
121121
round(v * 100, dp)
122122
end
123+
124+
@doc """
125+
Use this function for printing floats with only one decimal place.
126+
Integers will be returned without modification.
127+
If you need to always print the same amount of decimals no matter if float or integer,
128+
then use the round function also defined in this module.
129+
"""
130+
def format(rating_value) when is_float(rating_value) do
131+
rating_value
132+
|> Decimal.from_float()
133+
|> Decimal.round(1)
134+
end
135+
136+
def format(rating_value) when is_integer(rating_value) do
137+
rating_value
138+
end
123139
end

test/teiserver/battle/split_one_chevs_internal_test.exs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,76 @@ defmodule Teiserver.Battle.SplitOneChevsInternalTest do
108108
%{members: [], team_id: 3}
109109
]
110110
end
111+
112+
test "has enough noobs" do
113+
expanded_group = [
114+
%{
115+
count: 2,
116+
members: ["Pro1", "Noob1"],
117+
group_rating: 13,
118+
ratings: [8, 5],
119+
ranks: [1, 0],
120+
names: ["Pro1", "Noob1"],
121+
uncertainties: [0, 1]
122+
},
123+
%{
124+
count: 1,
125+
members: ["Noob2"],
126+
group_rating: 6,
127+
ratings: [6],
128+
ranks: [0],
129+
names: ["Noob2"],
130+
uncertainties: [2]
131+
},
132+
%{
133+
count: 1,
134+
members: ["Noob3"],
135+
group_rating: 7,
136+
ratings: [17],
137+
ranks: [0],
138+
names: ["Noob3"],
139+
uncertainties: [3]
140+
}
141+
]
142+
143+
result = SplitOneChevs.has_enough_noobs?(expanded_group)
144+
145+
assert result
146+
end
147+
148+
test "not have enough noobs" do
149+
expanded_group = [
150+
%{
151+
count: 2,
152+
members: ["B", "A"],
153+
group_rating: 13,
154+
ratings: [8, 5],
155+
ranks: [2, 2],
156+
names: ["B", "A"],
157+
uncertainties: [0, 1]
158+
},
159+
%{
160+
count: 1,
161+
members: ["C"],
162+
group_rating: 6,
163+
ratings: [6],
164+
ranks: [2],
165+
names: ["C"],
166+
uncertainties: [2]
167+
},
168+
%{
169+
count: 1,
170+
members: ["D"],
171+
group_rating: 7,
172+
ratings: [17],
173+
ranks: [2],
174+
names: ["D"],
175+
uncertainties: [3]
176+
}
177+
]
178+
179+
result = SplitOneChevs.has_enough_noobs?(expanded_group)
180+
181+
refute result
182+
end
111183
end

test/teiserver/battle/split_one_chevs_test.exs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ defmodule Teiserver.Battle.SplitOneChevsTest do
6464
algorithm: @split_algo
6565
)
6666

67-
assert result.team_players == %{1 => [1, 5], 2 => [2, 6], 3 => [3, 4]}
67+
assert result.team_players == %{1 => [5, 2], 2 => [6, 1], 3 => [4, 3]}
6868
end
6969

7070
test "split one chevs simple group" do
@@ -83,7 +83,7 @@ defmodule Teiserver.Battle.SplitOneChevsTest do
8383
algorithm: @split_algo
8484
)
8585

86-
assert result.team_players == %{1 => [4, 1], 2 => [2, 3]}
86+
assert result.team_players == %{1 => [1, 4], 2 => [2, 3]}
8787
end
8888

8989
test "logs FFA" do
@@ -135,4 +135,27 @@ defmodule Teiserver.Battle.SplitOneChevsTest do
135135
"Noob2 (8, σ: 8, Chev: 1) picked for Team 1"
136136
]
137137
end
138+
139+
test "calls another balancer when no noobs" do
140+
result =
141+
BalanceLib.create_balance(
142+
[
143+
%{"A" => %{rating: 5, rank: 2}},
144+
%{"B" => %{rating: 6, rank: 2}},
145+
%{"C" => %{rating: 7, rank: 2, uncertainty: 7.9}},
146+
%{"D" => %{rating: 8, rank: 2, uncertainty: 8}}
147+
],
148+
2,
149+
algorithm: @split_algo
150+
)
151+
152+
assert result.logs == [
153+
"Not enough noobs; calling another balancer.",
154+
"---------------------------",
155+
"Picked D for team 1, adding 8.0 points for new total of 8.0",
156+
"Picked C for team 2, adding 7.0 points for new total of 7.0",
157+
"Picked B for team 2, adding 6.0 points for new total of 13.0",
158+
"Picked A for team 1, adding 5.0 points for new total of 13.0"
159+
]
160+
end
138161
end

0 commit comments

Comments
 (0)