Skip to content

Commit

Permalink
Handle matchmaking/list message
Browse files Browse the repository at this point in the history
  • Loading branch information
geekingfrog committed Sep 1, 2024
1 parent 9806b25 commit 2df1a99
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 2 deletions.
6 changes: 4 additions & 2 deletions lib/teiserver/matchmaking/queue_server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ defmodule Teiserver.Matchmaking.QueueServer do
@type queue :: %{
name: String.t(),
team_size: pos_integer(),
team_count: pos_integer()
team_count: pos_integer(),
ranked: boolean()
}

@type state :: %{
Expand Down Expand Up @@ -80,7 +81,8 @@ defmodule Teiserver.Matchmaking.QueueServer do
queue: %{
name: attrs.name,
team_size: attrs.team_size,
team_count: attrs.team_count
team_count: attrs.team_count,
ranked: true
},
settings: Map.merge(default_settings(), Map.get(attrs, :settings, %{})),
members: Map.get(attrs, :members, [])
Expand Down
20 changes: 20 additions & 0 deletions lib/teiserver/player/tachyon_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ defmodule Teiserver.Player.TachyonHandler do
Player specific code to handle tachyon logins and actions
"""

alias Teiserver.Tachyon.Schema
alias Teiserver.Tachyon.Handler
alias Teiserver.Data.Types, as: T
alias Teiserver.Player
alias Teiserver.Matchmaking

@behaviour Handler

Expand Down Expand Up @@ -51,6 +53,24 @@ defmodule Teiserver.Player.TachyonHandler do
term(),
state()
) :: WebSock.handle_result()
def handle_command("matchmaking/list" = cmd_id, "request", message_id, _message, state) do
queues =
Matchmaking.list_queues()
|> Enum.map(fn {qid, queue} ->
%{
id: qid,
name: queue.name,
numOfTeams: queue.team_count,
teamSize: queue.team_size,
ranked: queue.ranked
}
end)

resp = Schema.response(cmd_id, message_id, %{playlists: queues}) |> Jason.encode!()

{:reply, :ok, {:text, resp}, state}
end

def handle_command(command_id, _message_type, message_id, _message, state) do
resp =
Schema.error_response(command_id, message_id, :command_unimplemented)
Expand Down
17 changes: 17 additions & 0 deletions priv/tachyon/schema/matchmaking/list/request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$id": "https://schema.beyondallreason.dev/tachyon/matchmaking/list/request.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MatchmakingListRequest",
"tachyon": {
"source": "user",
"target": "server",
"scopes": ["tachyon.lobby"]
},
"type": "object",
"properties": {
"type": { "const": "request" },
"messageId": { "type": "string" },
"commandId": { "const": "matchmaking/list" }
},
"required": ["type", "messageId", "commandId"]
}
49 changes: 49 additions & 0 deletions test/support/tachyon.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,55 @@ defmodule Teiserver.Support.Tachyon do
"ws://#{conf[:url][:host]}:#{conf[:http][:port]}/tachyon"
end

# TODO tachyon_mvp: add a json validation here to make sure the request
# sent there is conforming
def request(command_id, data \\ nil) do
req = %{
type: :request,
commandId: command_id,
messageId: UUID.uuid4()
}

if is_nil(data) do
req
else
Map.put(req, :data, data)
end
end

# TODO tachyon_mvp: create a version of this function that also check the
# the response against the expected json schema
def recv_response(client) do
case WSC.recv(client) do
{:ok, {:text, resp}} -> {:ok, Jason.decode!(resp)}
other -> other
end
end

@doc """
high level function to get the list of matchmaking queues
"""
def list_queues!(client) do
req = request("matchmaking/list")
:ok = WSC.send_message(client, {:text, req |> Jason.encode!()})
{:ok, resp} = recv_response(client)

message_id = req.messageId

# This checks the server replies with the correct message_id
# it only needs to be done once in the test suite so might as well put
# put it here since this is the first request implemented
# This could (should?) be moved elsewhere later
%{
"type" => "response",
"messageId" => ^message_id,
"commandId" => "matchmaking/list",
"status" => "success"
} = resp

resp
end

@doc """
Run the given function `f` until `pred` returns true on its result.
Waits `wait` ms between each tries. Raise an error if `pred` returns false
Expand Down
31 changes: 31 additions & 0 deletions test/teiserver_web/tachyon/matchmaking_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Teiserver.Matchmaking.MatchmakingTest do
use TeiserverWeb.ConnCase
alias Teiserver.Support.Tachyon
alias WebsocketSyncClient, as: WSC

# redefinition because ExUnit < 1.15 doesn't support passing setup
# definition as {Tachyon, :setup_client}
defp setup_client(_context), do: Tachyon.setup_client()

describe "list" do
setup :setup_client

test "works", %{client: client} do
resp = Tachyon.list_queues!(client)

# convert into a set since the order must not impact test result
expected_playlists =
MapSet.new([
%{
"id" => "1v1",
"name" => "Duel",
"numOfTeams" => 2,
"teamSize" => 1,
"ranked" => true
}
])

assert MapSet.new(resp["data"]["playlists"]) == expected_playlists
end
end
end

0 comments on commit 2df1a99

Please sign in to comment.