Skip to content

Commit 556f7ad

Browse files
Manually assign entries for voting (#1097)
* rename hasTokenCounter to hasVotingFeature under assessmentConfig * Added hasVotingFeatures to assessment config * Added hasVotingFeature to assessmentConfig * Added hasTokenCounter and hasVotingFeatures to assessments * hasTokenCounter and hasVotingFeatures to be updated to ones in assessment config when uploaded * Added hasTokenCounter and hasVotingFeatures to be shown when assessment is requested * Added hasTokenCounter into swaggers * Changed test cases to include hasVotingFeatures and hasTokenCounter * Added a way to change hasTokenCounter and hasVotingFeatures from the frontEnd * fixed format * fixed format * fixed alias format * added new function to delete voteSubmissions and call InsertVoting * Added ability to reassign voting * rename update_voting to reassign_voting for clarity * added test case for reassign_voting * rename reassignEntriesForVoting to assignEntriesForVoting * added isVotingPublished to AssessmentOverview and changed testCases to match * fixed format * Moved is_voting_published to be a function in assessments * Prevent deletions of submissions if voting has not been published * fix format * fix bug where submission is deleted regardless of reassigning_voting status * changed label for better clarity * Rename value for clarity and consistency --------- Co-authored-by: Richard Dominick <[email protected]>
1 parent 59fe997 commit 556f7ad

File tree

7 files changed

+179
-8
lines changed

7 files changed

+179
-8
lines changed

lib/cadet/assessments/assessments.ex

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,58 @@ defmodule Cadet.Assessments do
555555
Question.changeset(%Question{}, params_with_assessment_id)
556556
end
557557

558+
def reassign_voting(assessment_id, is_reassigning_voting) do
559+
if is_reassigning_voting do
560+
if is_voting_published(assessment_id) do
561+
Submission
562+
|> where(assessment_id: ^assessment_id)
563+
|> delete_submission_association(assessment_id)
564+
565+
Question
566+
|> where(assessment_id: ^assessment_id)
567+
|> Repo.all()
568+
|> Enum.each(fn q ->
569+
delete_submission_votes_association(q)
570+
end)
571+
end
572+
573+
voting_assigned_question_ids =
574+
SubmissionVotes
575+
|> select([v], v.question_id)
576+
|> Repo.all()
577+
578+
unpublished_voting_questions =
579+
Question
580+
|> where(type: :voting)
581+
|> where([q], q.id not in ^voting_assigned_question_ids)
582+
|> where(assessment_id: ^assessment_id)
583+
|> join(:inner, [q], asst in assoc(q, :assessment))
584+
|> select([q, asst], %{course_id: asst.course_id, question: q.question, id: q.id})
585+
|> Repo.all()
586+
587+
for q <- unpublished_voting_questions do
588+
insert_voting(q.course_id, q.question["contest_number"], q.id)
589+
end
590+
591+
{:ok, "voting assigned"}
592+
else
593+
{:ok, "no change to voting"}
594+
end
595+
end
596+
597+
def is_voting_published(assessment_id) do
598+
voting_assigned_question_ids =
599+
SubmissionVotes
600+
|> select([v], v.question_id)
601+
|> Repo.all()
602+
603+
Question
604+
|> where(type: :voting)
605+
|> where(assessment_id: ^assessment_id)
606+
|> where([q], q.id in ^voting_assigned_question_ids)
607+
|> Repo.exists?()
608+
end
609+
558610
def update_final_contest_entries do
559611
# 1435 = 1 day - 5 minutes
560612
if Log.log_execution("update_final_contest_entries", Duration.from_minutes(1435)) do

lib/cadet_web/admin_controllers/admin_assessments_controller.ex

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ defmodule CadetWeb.AdminAssessmentsController do
8585
max_team_size = params |> Map.get("maxTeamSize")
8686
has_token_counter = params |> Map.get("hasTokenCounter")
8787
has_voting_features = params |> Map.get("hasVotingFeatures")
88+
assign_entries_for_voting = params |> Map.get("assignEntriesForVoting")
8889

8990
updated_assessment =
9091
if is_nil(is_published) do
@@ -114,8 +115,16 @@ defmodule CadetWeb.AdminAssessmentsController do
114115
Map.put(updated_assessment, :has_voting_features, has_voting_features)
115116
end
116117

118+
is_reassigning_voting =
119+
if is_nil(assign_entries_for_voting) do
120+
false
121+
else
122+
assign_entries_for_voting
123+
end
124+
117125
with {:ok, assessment} <- check_dates(open_at, close_at, updated_assessment),
118-
{:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment) do
126+
{:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment),
127+
{:ok, _nil} <- Assessments.reassign_voting(assessment_id, is_reassigning_voting) do
119128
text(conn, "OK")
120129
else
121130
{:error, {status, message}} ->

lib/cadet_web/admin_views/admin_assessments_view.ex

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ defmodule CadetWeb.AdminAssessmentsView do
22
use CadetWeb, :view
33
use Timex
44
import CadetWeb.AssessmentsHelpers
5+
import Ecto.Query
6+
alias Cadet.Assessments.{Question, SubmissionVotes}
7+
alias Cadet.Repo
58

69
def render("index.json", %{assessments: assessments}) do
710
render_many(assessments, CadetWeb.AdminAssessmentsView, "overview.json", as: :assessment)
@@ -31,7 +34,8 @@ defmodule CadetWeb.AdminAssessmentsView do
3134
earlySubmissionXp: & &1.config.early_submission_xp,
3235
maxTeamSize: :max_team_size,
3336
hasVotingFeatures: :has_voting_features,
34-
hasTokenCounter: :has_token_counter
37+
hasTokenCounter: :has_token_counter,
38+
isVotingPublished: &is_voting_assigned(&1.id)
3539
})
3640
end
3741

@@ -65,4 +69,17 @@ defmodule CadetWeb.AdminAssessmentsView do
6569
defp password_protected?(nil), do: false
6670

6771
defp password_protected?(_), do: true
72+
73+
defp is_voting_assigned(assessment_id) do
74+
voting_assigned_question_ids =
75+
SubmissionVotes
76+
|> select([v], v.question_id)
77+
|> Repo.all()
78+
79+
Question
80+
|> where(type: :voting)
81+
|> where(assessment_id: ^assessment_id)
82+
|> where([q], q.id in ^voting_assigned_question_ids)
83+
|> Repo.exists?()
84+
end
6885
end

lib/cadet_web/views/assessments_view.ex

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
defmodule CadetWeb.AssessmentsView do
22
use CadetWeb, :view
33
use Timex
4+
import Ecto.Query
5+
alias Cadet.Assessments.{Question, SubmissionVotes}
6+
alias Cadet.Repo
47

58
import CadetWeb.AssessmentsHelpers
69

@@ -32,7 +35,8 @@ defmodule CadetWeb.AssessmentsView do
3235
earlySubmissionXp: & &1.config.early_submission_xp,
3336
maxTeamSize: :max_team_size,
3437
hasVotingFeatures: :has_voting_features,
35-
hasTokenCounter: :has_token_counter
38+
hasTokenCounter: :has_token_counter,
39+
isVotingPublished: &is_voting_assigned(&1.id)
3640
})
3741
end
3842

@@ -66,4 +70,17 @@ defmodule CadetWeb.AssessmentsView do
6670
defp password_protected?(nil), do: false
6771

6872
defp password_protected?(_), do: true
73+
74+
defp is_voting_assigned(assessment_id) do
75+
voting_assigned_question_ids =
76+
SubmissionVotes
77+
|> select([v], v.question_id)
78+
|> Repo.all()
79+
80+
Question
81+
|> where(type: :voting)
82+
|> where(assessment_id: ^assessment_id)
83+
|> where([q], q.id in ^voting_assigned_question_ids)
84+
|> Repo.exists?()
85+
end
6986
end

test/cadet/assessments/assessments_test.exs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,77 @@ defmodule Cadet.AssessmentsTest do
558558
assert SubmissionVotes |> where(question_id: ^question.id) |> Repo.all() |> length() == 0
559559
end
560560

561+
test "function that reassign voting after voting is assigned" do
562+
course = insert(:course)
563+
config = insert(:assessment_config)
564+
# contest assessment that has closed
565+
closed_contest_assessment =
566+
insert(:assessment,
567+
is_published: true,
568+
open_at: Timex.shift(Timex.now(), days: -5),
569+
close_at: Timex.shift(Timex.now(), hours: -1),
570+
course: course,
571+
config: config
572+
)
573+
574+
contest_question = insert(:programming_question, assessment: closed_contest_assessment)
575+
voting_assessment = insert(:assessment, %{course: course})
576+
577+
question =
578+
insert(:voting_question, %{
579+
assessment: voting_assessment,
580+
question:
581+
build(:voting_question_content, contest_number: closed_contest_assessment.number)
582+
})
583+
584+
students =
585+
insert_list(6, :course_registration, %{
586+
role: :student,
587+
course: course
588+
})
589+
590+
Enum.map(students, fn student ->
591+
submission =
592+
insert(:submission,
593+
student: student,
594+
assessment: contest_question.assessment,
595+
status: "submitted"
596+
)
597+
598+
insert(:answer,
599+
answer: %{code: "return 2;"},
600+
submission: submission,
601+
question: contest_question
602+
)
603+
end)
604+
605+
unattempted_student = insert(:course_registration, %{role: :student, course: course})
606+
607+
# unattempted submission will automatically be submitted after the assessment closes.
608+
unattempted_submission =
609+
insert(:submission,
610+
student: unattempted_student,
611+
assessment: contest_question.assessment,
612+
status: "submitted"
613+
)
614+
615+
insert(:answer,
616+
answer: %{
617+
code: "// question was left blank by student"
618+
},
619+
submission: unattempted_submission,
620+
question: contest_question
621+
)
622+
623+
Assessments.insert_voting(course.id, contest_question.assessment.number, question.id)
624+
Assessments.reassign_voting(voting_assessment.id, true)
625+
626+
# students with own contest submissions will vote for 5 entries
627+
# students without own contest submissin will vote for 6 entries
628+
assert SubmissionVotes |> where(question_id: ^question.id) |> Repo.all() |> length() ==
629+
6 * 5 + 6
630+
end
631+
561632
test "function that checks for closed contests and releases entries into voting pool" do
562633
course = insert(:course)
563634
config = insert(:assessment_config)

test/cadet_web/admin_controllers/admin_assessments_controller_test.exs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do
55
import Ecto.Query
66
import ExUnit.CaptureLog
77

8-
alias Cadet.Repo
8+
alias Cadet.{Assessments, Repo}
99
alias Cadet.Accounts.CourseRegistration
1010
alias Cadet.Assessments.{Assessment, Submission}
1111
alias Cadet.Test.XMLGenerator
@@ -93,7 +93,8 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do
9393
"xp" => (800 + 500 + 100) * 3,
9494
"earlySubmissionXp" => &1.config.early_submission_xp,
9595
"hasVotingFeatures" => &1.has_voting_features,
96-
"hasTokenCounter" => &1.has_token_counter
96+
"hasTokenCounter" => &1.has_token_counter,
97+
"isVotingPublished" => Assessments.is_voting_published(&1.id)
9798
}
9899
)
99100

@@ -143,7 +144,8 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do
143144
"xp" => 0,
144145
"earlySubmissionXp" => &1.config.early_submission_xp,
145146
"hasVotingFeatures" => &1.has_voting_features,
146-
"hasTokenCounter" => &1.has_token_counter
147+
"hasTokenCounter" => &1.has_token_counter,
148+
"isVotingPublished" => Assessments.is_voting_published(&1.id)
147149
}
148150
)
149151

test/cadet_web/controllers/assessments_controller_test.exs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ defmodule CadetWeb.AssessmentsControllerTest do
8282
"questionCount" => 9,
8383
"earlySubmissionXp" => &1.config.early_submission_xp,
8484
"hasVotingFeatures" => &1.has_voting_features,
85-
"hasTokenCounter" => &1.has_token_counter
85+
"hasTokenCounter" => &1.has_token_counter,
86+
"isVotingPublished" => Assessments.is_voting_published(&1.id)
8687
}
8788
)
8889

@@ -169,7 +170,8 @@ defmodule CadetWeb.AssessmentsControllerTest do
169170
"questionCount" => 9,
170171
"earlySubmissionXp" => &1.config.early_submission_xp,
171172
"hasVotingFeatures" => &1.has_voting_features,
172-
"hasTokenCounter" => &1.has_token_counter
173+
"hasTokenCounter" => &1.has_token_counter,
174+
"isVotingPublished" => Assessments.is_voting_published(&1.id)
173175
}
174176
)
175177

@@ -282,6 +284,7 @@ defmodule CadetWeb.AssessmentsControllerTest do
282284
"questionCount" => 9,
283285
"hasVotingFeatures" => &1.has_voting_features,
284286
"hasTokenCounter" => &1.has_token_counter,
287+
"isVotingPublished" => Assessments.is_voting_published(&1.id),
285288
"earlySubmissionXp" => &1.config.early_submission_xp,
286289
"isPublished" =>
287290
if &1.config.type == hd(configs).type do

0 commit comments

Comments
 (0)