Skip to content

Commit

Permalink
WIP: Make re-queue work for parties
Browse files Browse the repository at this point in the history
  • Loading branch information
Askaholic committed Dec 2, 2023
1 parent 378ba27 commit 02e1939
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 35 deletions.
86 changes: 54 additions & 32 deletions server/ladder_service/ladder_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,20 +339,27 @@ def start_search(
on_matched=on_matched
)

for player in players:
self._add_search_to_queue(search, queue)

def _add_search_to_queue(
self,
search: Search,
queue: MatchmakerQueue,
):
for player in search.players:
player.state = PlayerState.SEARCHING_LADDER

self.write_rating_progress(player, queue.rating_type)

player.write_message({
"command": "search_info",
"queue_name": queue_name,
"queue_name": queue.name,
"state": "start"
})

self._searches[player][queue_name] = search
self._searches[player][queue.name] = search

self._logger.info("%s started searching for %s", search, queue_name)
self._logger.info("%s started searching for %s", search, queue.name)

asyncio.create_task(queue.search(search))

Expand Down Expand Up @@ -418,26 +425,28 @@ def _clear_search(
return search

def write_rating_progress(self, player: Player, rating_type: str) -> None:
if player not in self._informed_players:
self._informed_players.add(player)
_, deviation = player.ratings[rating_type]
if player in self._informed_players:
return

if deviation > 490:
player.write_message({
"command": "notice",
"style": "info",
"text": (
"<i>Welcome to the matchmaker</i><br><br><b>The "
"matchmaking system needs to calibrate your skill level; "
"your first few games may be more imbalanced as the "
"system attempts to learn your capability as a player."
"</b><br><b>"
"Afterwards, you'll be more reliably matched up with "
"people of your skill level: so don't worry if your "
"first few games are uneven. This will improve as you "
"play!</b>"
)
})
self._informed_players.add(player)
_, deviation = player.ratings[rating_type]

if deviation > 490:
player.write_message({
"command": "notice",
"style": "info",
"text": (
"<i>Welcome to the matchmaker</i><br><br><b>The "
"matchmaking system needs to calibrate your skill level; "
"your first few games may be more imbalanced as the "
"system attempts to learn your capability as a player."
"</b><br><b>"
"Afterwards, you'll be more reliably matched up with "
"people of your skill level: so don't worry if your "
"first few games are uneven. This will improve as you "
"play!</b>"
)
})

def on_match_found(
self,
Expand Down Expand Up @@ -504,16 +513,29 @@ async def confirm_match(
player.state = PlayerState.IDLE
player.write_message(msg)

# Return any player that accepted the match back to the queue
# TODO: make this work with parties
# Return any search that fully accepted the match back to the queue
for search in (s1, s2):
for player in search.players:
if player in unready_players:
self.cancel_search(player)
else:
search.unmatch()
player.state = PlayerState.SEARCHING_LADDER
asyncio.create_task(queue.search(search))
search_players = search.players
search_unready_players = [
player
for player in unready_players
if player in search_players
]
if not search_unready_players:
search.unmatch()
self._add_search_to_queue(search, queue)
self._logger.debug(
"%s auto requeued after failed match",
search
)
else:
for player in search_players:
player.write_message({
"command": "match_notice",
"unready_players": [
p.id for p in search_unready_players
]
})

self.violation_service.register_violations(unready_players)

Expand Down
3 changes: 2 additions & 1 deletion tests/integration_tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,14 @@ async def queue_temp_players_for_matchmaking(
tmp_user,
num_players,
queue_name,
player_name=None,
):
"""
Queue an arbitrary number of players for matchmaking in a particular queue
by setting up temp users.
"""
users = await asyncio.gather(*[
tmp_user(queue_name)
tmp_user(player_name or queue_name)
for _ in range(num_players)
])
responses = await asyncio.gather(*[
Expand Down
61 changes: 59 additions & 2 deletions tests/integration_tests/test_matchmaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,57 @@ async def test_game_matchmaking_close_fa_and_requeue(lobby_server):
await read_until_command(proto1, "match_found", timeout=5)


@fast_forward(130)
async def test_game_matchmaking_no_accept_offer_auto_requeue(
lobby_server,
tmp_user,
):
proto1, proto2 = await queue_temp_players_for_matchmaking(
lobby_server,
tmp_user,
num_players=2,
queue_name="ladder1v1",
player_name="Player",
)

await read_until_command(proto1, "match_found", timeout=30)
await read_until_command(proto2, "match_found", timeout=5)

# Only player 1 accepts the match
await read_until_command(proto1, "match_info", timeout=5)
await read_until_command(proto2, "match_info", timeout=5)
await proto1.send_message({"command": "match_ready"})
await read_until_command(proto1, "match_cancelled", timeout=120)

# Player 1 is automatically re-added to the queue, but player 2 is not
await read_until_command(proto1, "search_info", state="start", timeout=5)
msg = await read_until_command(proto1, "matchmaker_info", timeout=5)
queue_message = next(
queue
for queue in msg["queues"]
if queue["queue_name"] == "ladder1v1"
)
assert queue_message["num_players"] == 1

# A third player joins the queue and is matched with player 1
proto3, = await queue_temp_players_for_matchmaking(
lobby_server,
tmp_user,
num_players=1,
queue_name="ladder1v1",
player_name="Player",
)

await asyncio.gather(*[
read_until_match(proto)
for proto in (proto1, proto3)
])
await asyncio.gather(
client_response(proto1),
client_response(proto3)
)


@pytest.mark.flaky
@fast_forward(200)
async def test_anti_map_repetition(lobby_server):
Expand Down Expand Up @@ -567,7 +618,9 @@ async def read_update_msg():
msg = await read_until_command(proto, "matchmaker_info")

queue_message = next(
q for q in msg["queues"] if q["queue_name"] == "ladder1v1"
queue
for queue in msg["queues"]
if queue["queue_name"] == "ladder1v1"
)
if queue_message["num_players"] == 0:
continue
Expand All @@ -586,7 +639,11 @@ async def read_update_msg():
# Update message because we left the queue
msg = await read_until_command(proto, "matchmaker_info")

queue_message = next(q for q in msg["queues"] if q["queue_name"] == "ladder1v1")
queue_message = next(
queue
for queue in msg["queues"]
if queue["queue_name"] == "ladder1v1"
)
assert queue_message["num_players"] == 0


Expand Down

0 comments on commit 02e1939

Please sign in to comment.