Skip to content

Commit

Permalink
Add preliminary competitor status response
Browse files Browse the repository at this point in the history
This factory password business is a mess!
  • Loading branch information
backspace committed Oct 20, 2024
1 parent 3d7e0da commit eb42942
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 16 deletions.
19 changes: 16 additions & 3 deletions registrations/lib/registrations/waydowntown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ defmodule Registrations.Waydowntown do

defp run_expired?(_), do: false

def get_run_progress(run) do
def get_run_progress(run, current_user_id) do
correct_submissions =
if run.specification.concept in ["orientation_memory", "cardinal_memory"] do
latest_submission = run.submissions |> Enum.sort_by(&{&1.inserted_at, &1.answer.order}, :desc) |> List.first()
Expand All @@ -426,13 +426,26 @@ defmodule Registrations.Waydowntown do

total_answers = length(run.specification.answers)

competitors = get_competitors_progress(run, current_user_id)

%{
correct_submissions: correct_submissions,
total_answers: total_answers,
complete: run.winner_submission_id != nil
complete: run.winner_submission_id != nil,
competitors: competitors
}
end

defp get_competitors_progress(run, current_user_id) do
run.participations
|> Enum.reject(&(&1.user_id == current_user_id))
|> Map.new(fn participation ->
user = Repo.get!(RegistrationsWeb.User, participation.user_id)
correct_submissions = Enum.count(run.submissions, &(&1.creator_id == user.id && &1.correct))
{user.email, %{correct_submissions: correct_submissions, total_answers: length(run.specification.answers)}}
end)
end

defp check_submission_correctness(
%Run{specification: %Specification{concept: concept, answers: [%Answer{answer: correct_answer}]}},
submission_text,
Expand Down Expand Up @@ -551,6 +564,6 @@ defmodule Registrations.Waydowntown do
end

defp submission_preloads do
[:answer, run: [specification: [:answers], submissions: [:answer]]]
[:answer, run: [:participations, specification: [:answers], submissions: [:answer]]]
end
end
19 changes: 12 additions & 7 deletions registrations/lib/registrations_web/views/run_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule RegistrationsWeb.RunView do
alias Registrations.Waydowntown

def fields do
[:complete, :correct_submissions, :total_answers, :task_description, :started_at]
[:complete, :correct_submissions, :total_answers, :task_description, :started_at, :competitors]
end

def hidden(run) do
Expand All @@ -28,16 +28,21 @@ defmodule RegistrationsWeb.RunView do
run.specification.task_description
end

def complete(run, _conn) do
Waydowntown.get_run_progress(run).complete
def complete(run, conn) do
Waydowntown.get_run_progress(run, conn.assigns.current_user.id).complete
end

def correct_submissions(run, _conn) do
Waydowntown.get_run_progress(run).correct_submissions
@spec correct_submissions(any(), any()) :: any()
def correct_submissions(run, conn) do
Waydowntown.get_run_progress(run, conn.assigns.current_user.id).correct_submissions
end

def total_answers(run, _conn) do
Waydowntown.get_run_progress(run).total_answers
def total_answers(run, conn) do
Waydowntown.get_run_progress(run, conn.assigns.current_user.id).total_answers
end

def competitors(run, conn) do
Waydowntown.get_run_progress(run, conn.assigns.current_user.id).competitors
end

def relationships do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ defmodule RegistrationsWeb.SubmissionControllerTest do

alias Registrations.Waydowntown
alias Registrations.Waydowntown.Answer
alias Registrations.Waydowntown.Participation
alias Registrations.Waydowntown.Region
alias Registrations.Waydowntown.Run
alias Registrations.Waydowntown.Specification
alias Registrations.Waydowntown.Submission

defp setup_conn(conn) do
defp setup_conn(conn, user \\ nil) do
conn
|> put_req_header("accept", "application/vnd.api+json")
|> put_req_header("content-type", "application/vnd.api+json")
|> put_req_header("authorization", setup_user_and_get_token())
|> put_req_header("authorization", setup_user_and_get_token(user))
end

describe "create submission" do
Expand Down Expand Up @@ -1046,9 +1047,145 @@ defmodule RegistrationsWeb.SubmissionControllerTest do
end
end

defp setup_user_and_get_token do
describe "create submissions for run with multiple participants" do
setup do
region = Repo.insert!(%Region{name: "Test Region"})

specification =
Repo.insert!(%Specification{
concept: "orientation_memory",
answers: [
%Answer{order: 1, answer: "left"},
%Answer{order: 2, answer: "up"},
%Answer{order: 3, answer: "right"}
],
region: region
})

run = Repo.insert!(%Run{specification: specification, started_at: DateTime.utc_now()})

current_user = insert(:octavia, admin: true)
other_user1 = insert(:user, email: "[email protected]")
other_user2 = insert(:user, email: "[email protected]")

Repo.insert!(%Participation{user_id: current_user.id, run_id: run.id})
Repo.insert!(%Participation{user_id: other_user1.id, run_id: run.id})
Repo.insert!(%Participation{user_id: other_user2.id, run_id: run.id})

%{
run: run,
specification: specification,
region: region,
current_user: current_user,
other_user1: other_user1,
other_user2: other_user2
}
end

test "creates submissions and completes the run with current user winning", %{
conn: conn,
run: run,
specification: specification,
current_user: current_user
} do
[answer_1, answer_2, answer_3] = specification.answers

# Current user submits correct answers
Enum.each([answer_1, answer_2, answer_3], fn answer ->
conn =
conn
|> setup_conn()
|> post(Routes.submission_path(conn, :create), %{
"data" => %{
"type" => "submissions",
"attributes" => %{"submission" => answer.answer},
"relationships" => %{
"run" => %{"data" => %{"type" => "runs", "id" => run.id}},
"answer" => %{"data" => %{"type" => "answers", "id" => answer.id}}
}
}
})

assert %{"id" => id} = json_response(conn, 201)["data"]
submission = Waydowntown.get_submission!(id)
assert submission.correct

included_run = Enum.find(json_response(conn, 201)["included"], &(&1["type"] == "runs"))
assert included_run["attributes"]["correct_submissions"] == answer.order
assert included_run["attributes"]["total_answers"] == 3

if answer.order == 3 do
assert included_run["attributes"]["complete"]

assert included_run["attributes"]["competitors"] == %{
"[email protected]" => %{"correct_submissions" => 0, "total_answers" => 3},
"[email protected]" => %{"correct_submissions" => 0, "total_answers" => 3}
}
else
refute included_run["attributes"]["complete"]
end
end)

run = Waydowntown.get_run!(run.id)
assert run.winner_submission_id != nil
winning_submission = Waydowntown.get_submission!(run.winner_submission_id)
assert winning_submission.creator_id == current_user.id
end

test "creates submissions with another user winning", %{
conn: conn,
run: run,
specification: specification,
other_user1: other_user1
} do
[answer_1, answer_2, answer_3] = specification.answers

# user1 submits correct answers
Enum.each([answer_1, answer_2, answer_3], fn answer ->
conn =
conn
|> setup_conn(other_user1)
|> post(Routes.submission_path(conn, :create), %{
"data" => %{
"type" => "submissions",
"attributes" => %{"submission" => answer.answer},
"relationships" => %{
"run" => %{"data" => %{"type" => "runs", "id" => run.id}},
"answer" => %{"data" => %{"type" => "answers", "id" => answer.id}}
}
}
})

assert %{"id" => id} = json_response(conn, 201)["data"]
submission = Waydowntown.get_submission!(id)
assert submission.correct

included_run = Enum.find(json_response(conn, 201)["included"], &(&1["type"] == "runs"))
assert included_run["attributes"]["correct_submissions"] == answer.order
assert included_run["attributes"]["total_answers"] == 3

if answer.order == 3 do
assert included_run["attributes"]["complete"]

assert included_run["attributes"]["competitors"] == %{
"[email protected]" => %{"correct_submissions" => 0, "total_answers" => 3},
"[email protected]" => %{"correct_submissions" => 0, "total_answers" => 3}
}
else
refute included_run["attributes"]["complete"]
end
end)

run = Waydowntown.get_run!(run.id)
assert run.winner_submission_id != nil
winning_submission = Waydowntown.get_submission!(run.winner_submission_id)
assert winning_submission.creator_id == other_user1.id
end
end

defp setup_user_and_get_token(user \\ nil) do
user =
Registrations.Repo.get_by(RegistrationsWeb.User, email: "[email protected]") ||
user || Registrations.Repo.get_by(RegistrationsWeb.User, email: "[email protected]") ||
insert(:octavia, admin: true)

authed_conn = build_conn()
Expand Down
7 changes: 5 additions & 2 deletions registrations/test/support/factory.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ defmodule Registrations.Factory do
@moduledoc false
use ExMachina.Ecto, repo: Registrations.Repo

alias Pow.Ecto.Schema.Password

def user_factory do
%RegistrationsWeb.User{
email: sequence(:email, &"jh#{&1}@example.com")
email: sequence(:email, &"jh#{&1}@example.com"),
password_hash: Password.pbkdf2_hash("Xenogenesis")
}
end

Expand All @@ -22,7 +25,7 @@ defmodule Registrations.Factory do
user_factory(),
%{
email: "[email protected]",
password_hash: Pow.Ecto.Schema.Password.pbkdf2_hash("Xenogenesis")
password_hash: Password.pbkdf2_hash("Xenogenesis")
}
)
end
Expand Down

0 comments on commit eb42942

Please sign in to comment.