Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-waydowntown-full-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
api-level: 24
arch: x86_64
profile: Nexus 6
script: flutter test integration_test/token_refresh_test.dart integration_test/string_collector_test.dart integration_test/fill_in_the_blank_test.dart integration_test/team_game_test.dart --flavor local --dart-define=API_BASE_URL=http://10.0.2.2:4001 --timeout none --file-reporter json:test-results.json
script: flutter test integration_test/token_refresh_test.dart integration_test/string_collector_test.dart integration_test/fill_in_the_blank_test.dart integration_test/team_game_test.dart integration_test/edit_specification_test.dart --flavor local --dart-define=API_BASE_URL=http://10.0.2.2:4001 --timeout none --file-reporter json:test-results.json

- name: Publish test results
uses: EnricoMi/publish-unit-test-result-action@v2
Expand Down
41 changes: 39 additions & 2 deletions registrations/lib/registrations/waydowntown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ defmodule Registrations.Waydowntown do
answers = generate_answers(concept_data)

with {:ok, specification} <-
create_specification(%{
insert_specification(%{
concept: concept_key,
task_description: concept_data["instructions"]
}),
Expand Down Expand Up @@ -268,7 +268,7 @@ defmodule Registrations.Waydowntown do
end
end

defp create_specification(attrs) do
defp insert_specification(attrs) do
%Specification{}
|> Specification.changeset(attrs)
|> Repo.insert()
Expand Down Expand Up @@ -348,8 +348,45 @@ defmodule Registrations.Waydowntown do
|> Repo.preload(answers: [:reveals, :region], region: [parent: [parent: [:parent]]])
end

def get_answer!(id), do: Repo.get!(Answer, id) |> Repo.preload(:specification)

def create_answer(attrs) do
%Answer{}
|> Answer.changeset(attrs)
|> Repo.insert()
end

def update_answer(%Answer{} = answer, attrs) do
answer
|> Answer.changeset(attrs)
|> Repo.update()
end

def delete_answer(%Answer{} = answer) do
Repo.delete(answer)
end

def get_next_answer_order(specification_id) do
query = from(a in Answer, where: a.specification_id == ^specification_id, select: max(a.order))

case Repo.one(query) do
nil -> 1
max_order -> max_order + 1
end
end

def get_specification!(id), do: Repo.get!(Specification, id)

def create_specification(attrs) do
%Specification{}
|> Specification.changeset(attrs)
|> Repo.insert()
|> case do
{:ok, spec} -> {:ok, Repo.preload(spec, answers: [:reveals, :region], region: [parent: [parent: [:parent]]])}
error -> error
end
end

def update_specification(%Specification{} = specification, attrs) do
specification
|> Specification.changeset(attrs)
Expand Down
40 changes: 35 additions & 5 deletions registrations/lib/registrations/waydowntown/answer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,42 @@ defmodule Registrations.Waydowntown.Answer do
timestamps()
end

@ordered_concepts ~w(orientation_memory cardinal_memory)

@doc false
def changeset(answer, attrs) do
answer
|> cast(attrs, [:answer, :order, :specification_id, :region_id])
|> validate_required([:answer, :order, :specification_id])
|> assoc_constraint(:specification)
|> assoc_constraint(:region)
changeset =
answer
|> cast(attrs, [:answer, :order, :specification_id, :region_id, :label, :hint])
|> validate_required([:answer, :specification_id])
|> assoc_constraint(:specification)
|> assoc_constraint(:region)

if requires_order?(answer, changeset) do
validate_required(changeset, [:order])
else
changeset
end
end

defp requires_order?(answer, changeset) do
concept =
cond do
answer.specification && answer.specification.__struct__ != Ecto.Association.NotLoaded ->
answer.specification.concept

true ->
spec_id = get_field(changeset, :specification_id)

if spec_id do
Registrations.Repo.get(Registrations.Waydowntown.Specification, spec_id)
|> case do
nil -> nil
spec -> spec.concept
end
end
end

concept in @ordered_concepts
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
defmodule RegistrationsWeb.AnswerController do
use RegistrationsWeb, :controller

alias Registrations.Waydowntown
alias Registrations.Waydowntown.Answer
alias RegistrationsWeb.Owner.AnswerView

action_fallback(RegistrationsWeb.FallbackController)

def create(conn, %{"specification_id" => specification_id} = params) do
user = Pow.Plug.current_user(conn)
specification = Waydowntown.get_specification!(specification_id)

if specification.creator_id == user.id do
order = Waydowntown.get_next_answer_order(specification_id)
params = Map.put(params, "order", order)

with {:ok, %Answer{} = answer} <- Waydowntown.create_answer(params) do
answer = Waydowntown.get_answer!(answer.id)

conn
|> put_status(:created)
|> put_view(AnswerView)
|> render("show.json", %{data: answer, conn: conn})
end
else
conn
|> put_status(:unauthorized)
|> json(%{errors: [%{detail: "Unauthorized"}]})
end
end

def update(conn, %{"id" => id} = params) do
user = Pow.Plug.current_user(conn)
answer = Waydowntown.get_answer!(id)

if answer.specification.creator_id == user.id do
with {:ok, %Answer{} = updated_answer} <- Waydowntown.update_answer(answer, params) do
conn
|> put_view(AnswerView)
|> render("show.json", %{data: updated_answer, conn: conn})
end
else
conn
|> put_status(:unauthorized)
|> json(%{errors: [%{detail: "Unauthorized"}]})
end
end

def delete(conn, %{"id" => id}) do
user = Pow.Plug.current_user(conn)
answer = Waydowntown.get_answer!(id)

if answer.specification.creator_id == user.id do
with {:ok, %Answer{}} <- Waydowntown.delete_answer(answer) do
send_resp(conn, :no_content, "")
end
else
conn
|> put_status(:unauthorized)
|> json(%{errors: [%{detail: "Unauthorized"}]})
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,35 @@ defmodule RegistrationsWeb.SpecificationController do
|> render("index.json", %{data: specifications, conn: conn, params: params})
end

def create(conn, params) do
user = Pow.Plug.current_user(conn)

attrs = Map.put(params, "creator_id", user.id)

case Waydowntown.create_specification(attrs) do
{:ok, specification} ->
conn
|> put_status(:created)
|> put_view(SpecificationView)
|> render("show.json", data: specification, conn: conn, params: params)

{:error, changeset} ->
errors = Ecto.Changeset.traverse_errors(changeset, &RegistrationsWeb.ErrorHelpers.translate_error/1)

conn
|> put_status(:unprocessable_entity)
|> json(%{
errors:
Enum.map(errors, fn {field, message} ->
%{
detail: "#{message}",
source: %{pointer: "/data/attributes/#{field}"}
}
end)
})
end
end

def update(conn, %{"id" => id} = params) do
user = Pow.Plug.current_user(conn)
specification = Waydowntown.get_specification!(id)
Expand Down
28 changes: 16 additions & 12 deletions registrations/lib/registrations_web/controllers/test_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ defmodule RegistrationsWeb.TestController do
# Optionally create game data based on concept parameter
case params["game"] do
"fill_in_the_blank" ->
game_data = create_fill_in_the_blank_game()
game_data = create_fill_in_the_blank_game(user)
Map.merge(base_response, game_data)

"string_collector" ->
game_data = create_string_collector_game()
game_data = create_string_collector_game(user)
Map.merge(base_response, game_data)

"orientation_memory" ->
game_data = create_orientation_memory_game()
game_data = create_orientation_memory_game(user)
Map.merge(base_response, game_data)

"string_collector_team" ->
game_data = create_string_collector_team_game()
game_data = create_string_collector_team_game(user)
Map.merge(base_response, game_data)

_ ->
Expand All @@ -57,15 +57,16 @@ defmodule RegistrationsWeb.TestController do
|> json(response)
end

defp create_fill_in_the_blank_game do
defp create_fill_in_the_blank_game(user) do
region = Repo.insert!(%Region{name: "Test Region"})

specification =
Repo.insert!(%Specification{
concept: "fill_in_the_blank",
task_description: "What is the answer to this test?",
region: region,
duration: 300
duration: 300,
creator_id: user.id
})

# Insert answer separately (has_many relationship)
Expand All @@ -83,7 +84,7 @@ defmodule RegistrationsWeb.TestController do
}
end

defp create_string_collector_game do
defp create_string_collector_game(user) do
region = Repo.insert!(%Region{name: "Test Region"})

specification =
Expand All @@ -92,7 +93,8 @@ defmodule RegistrationsWeb.TestController do
task_description: "Find all the hidden words",
start_description: "Look around for words",
region: region,
duration: 300
duration: 300,
creator_id: user.id
})

# Insert answers separately (has_many relationship)
Expand All @@ -108,7 +110,7 @@ defmodule RegistrationsWeb.TestController do
}
end

defp create_orientation_memory_game do
defp create_orientation_memory_game(user) do
region = Repo.insert!(%Region{name: "Test Region"})

specification =
Expand All @@ -117,7 +119,8 @@ defmodule RegistrationsWeb.TestController do
task_description: "Remember the sequence of directions",
start_description: "Watch the pattern carefully",
region: region,
duration: 300
duration: 300,
creator_id: user.id
})

# Insert ordered answers (order field is required for orientation_memory)
Expand All @@ -133,7 +136,7 @@ defmodule RegistrationsWeb.TestController do
}
end

defp create_string_collector_team_game do
defp create_string_collector_team_game(user) do
region = Repo.insert!(%Region{name: "Test Region"})

specification =
Expand All @@ -142,7 +145,8 @@ defmodule RegistrationsWeb.TestController do
task_description: "Find all the hidden words",
start_description: "Look around for words",
region: region,
duration: 300
duration: 300,
creator_id: user.id
})

answer1 = Repo.insert!(%Answer{answer: "apple", specification_id: specification.id})
Expand Down
4 changes: 3 additions & 1 deletion registrations/lib/registrations_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ defmodule RegistrationsWeb.Router do
post "/start", RunController, :start, as: :start
end

resources("/specifications", SpecificationController, only: [:update])
resources("/answers", AnswerController, only: [:create, :update, :delete])

resources("/specifications", SpecificationController, only: [:create, :update])
get("/specifications/mine", SpecificationController, :mine, as: :my_specifications)

resources("/submissions", SubmissionController, only: [:create, :show])
Expand Down
Loading
Loading