From 2da51017652557ea5c79fd15feb34fe9d12e1c67 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:39:19 +0800 Subject: [PATCH 01/35] rename hasTokenCounter to hasVotingFeature under assessmentConfig --- lib/cadet/courses/assessment_config.ex | 4 ++-- lib/cadet_web/admin_views/admin_courses_view.ex | 2 +- lib/cadet_web/views/user_view.ex | 2 +- ...17_rename_has_token_counter_to_has_voting_features.exs | 7 +++++++ .../admin_controllers/admin_courses_controller_test.exs | 8 ++++---- test/cadet_web/controllers/user_controller_test.exs | 6 +++--- 6 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs diff --git a/lib/cadet/courses/assessment_config.ex b/lib/cadet/courses/assessment_config.ex index ec2455b69..ee15a9631 100644 --- a/lib/cadet/courses/assessment_config.ex +++ b/lib/cadet/courses/assessment_config.ex @@ -12,7 +12,7 @@ defmodule Cadet.Courses.AssessmentConfig do field(:type, :string) field(:show_grading_summary, :boolean, default: true) field(:is_manually_graded, :boolean, default: true) - field(:has_token_counter, :boolean, default: false) + field(:has_voting_features, :boolean, default: false) # used by frontend to determine display styles field(:early_submission_xp, :integer, default: 0) field(:hours_before_early_xp_decay, :integer, default: 0) @@ -24,7 +24,7 @@ defmodule Cadet.Courses.AssessmentConfig do @required_fields ~w(course_id)a @optional_fields ~w(order type early_submission_xp - hours_before_early_xp_decay show_grading_summary is_manually_graded has_token_counter)a + hours_before_early_xp_decay show_grading_summary is_manually_graded has_voting_features)a def changeset(assessment_config, params) do assessment_config diff --git a/lib/cadet_web/admin_views/admin_courses_view.ex b/lib/cadet_web/admin_views/admin_courses_view.ex index 4ce97f3c0..f561fa815 100644 --- a/lib/cadet_web/admin_views/admin_courses_view.ex +++ b/lib/cadet_web/admin_views/admin_courses_view.ex @@ -12,7 +12,7 @@ defmodule CadetWeb.AdminCoursesView do displayInDashboard: :show_grading_summary, isManuallyGraded: :is_manually_graded, earlySubmissionXp: :early_submission_xp, - hasTokenCounter: :has_token_counter, + hasVotingFeatures: :has_voting_features, hoursBeforeEarlyXpDecay: :hours_before_early_xp_decay }) end diff --git a/lib/cadet_web/views/user_view.ex b/lib/cadet_web/views/user_view.ex index 35de6c92b..c153e841b 100644 --- a/lib/cadet_web/views/user_view.ex +++ b/lib/cadet_web/views/user_view.ex @@ -125,7 +125,7 @@ defmodule CadetWeb.UserView do type: :type, displayInDashboard: :show_grading_summary, isManuallyGraded: :is_manually_graded, - hasTokenCounter: :has_token_counter, + hasVotingFeatures: :has_voting_features, earlySubmissionXp: :early_submission_xp, hoursBeforeEarlyXpDecay: :hours_before_early_xp_decay }) diff --git a/priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs b/priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs new file mode 100644 index 000000000..61f689930 --- /dev/null +++ b/priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs @@ -0,0 +1,7 @@ +defmodule Cadet.Repo.Migrations.RenameHasTokenCounterToHasVotingFeatures do + use Ecto.Migration + + def change do + rename(table(:assessment_configs), :has_token_counter, to: :has_voting_features) + end +end diff --git a/test/cadet_web/admin_controllers/admin_courses_controller_test.exs b/test/cadet_web/admin_controllers/admin_courses_controller_test.exs index 492d4f8a0..c29ddbb02 100644 --- a/test/cadet_web/admin_controllers/admin_courses_controller_test.exs +++ b/test/cadet_web/admin_controllers/admin_courses_controller_test.exs @@ -158,7 +158,7 @@ defmodule CadetWeb.AdminCoursesControllerTest do order: 2, type: "Mission2", course: course, - has_token_counter: true + has_voting_features: true }) resp = @@ -174,7 +174,7 @@ defmodule CadetWeb.AdminCoursesControllerTest do "isManuallyGraded" => true, "type" => "Mission1", "assessmentConfigId" => config1.id, - "hasTokenCounter" => false + "hasVotingFeatures" => false }, %{ "earlySubmissionXp" => 200, @@ -183,7 +183,7 @@ defmodule CadetWeb.AdminCoursesControllerTest do "isManuallyGraded" => false, "type" => "Mission2", "assessmentConfigId" => config2.id, - "hasTokenCounter" => true + "hasVotingFeatures" => true }, %{ "earlySubmissionXp" => 200, @@ -192,7 +192,7 @@ defmodule CadetWeb.AdminCoursesControllerTest do "isManuallyGraded" => true, "type" => "Mission3", "assessmentConfigId" => config3.id, - "hasTokenCounter" => false + "hasVotingFeatures" => false } ] diff --git a/test/cadet_web/controllers/user_controller_test.exs b/test/cadet_web/controllers/user_controller_test.exs index c16a9b1fc..09bfffb88 100644 --- a/test/cadet_web/controllers/user_controller_test.exs +++ b/test/cadet_web/controllers/user_controller_test.exs @@ -123,7 +123,7 @@ defmodule CadetWeb.UserControllerTest do "assessmentConfigId" => config1.id, "earlySubmissionXp" => 200, "hoursBeforeEarlyXpDecay" => 48, - "hasTokenCounter" => false + "hasVotingFeatures" => false }, %{ "type" => "test type 2", @@ -132,7 +132,7 @@ defmodule CadetWeb.UserControllerTest do "assessmentConfigId" => config2.id, "earlySubmissionXp" => 200, "hoursBeforeEarlyXpDecay" => 48, - "hasTokenCounter" => false + "hasVotingFeatures" => false }, %{ "type" => "test type 3", @@ -141,7 +141,7 @@ defmodule CadetWeb.UserControllerTest do "assessmentConfigId" => config3.id, "earlySubmissionXp" => 200, "hoursBeforeEarlyXpDecay" => 48, - "hasTokenCounter" => false + "hasVotingFeatures" => false } ] } From fe7854cf94ff3077f6825e2019a8d8f6818c83ac Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 01:11:43 +0800 Subject: [PATCH 02/35] Added hasVotingFeatures to assessment config --- lib/cadet/courses/assessment_config.ex | 3 ++- ...oting_features_toggle_to_assessment_config.exs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 priv/repo/migrations/20240321141522_add_has_voting_features_toggle_to_assessment_config.exs diff --git a/lib/cadet/courses/assessment_config.ex b/lib/cadet/courses/assessment_config.ex index ee15a9631..a9ea941ed 100644 --- a/lib/cadet/courses/assessment_config.ex +++ b/lib/cadet/courses/assessment_config.ex @@ -12,6 +12,7 @@ defmodule Cadet.Courses.AssessmentConfig do field(:type, :string) field(:show_grading_summary, :boolean, default: true) field(:is_manually_graded, :boolean, default: true) + field(:has_token_counter, :boolean, default: false) field(:has_voting_features, :boolean, default: false) # used by frontend to determine display styles field(:early_submission_xp, :integer, default: 0) @@ -24,7 +25,7 @@ defmodule Cadet.Courses.AssessmentConfig do @required_fields ~w(course_id)a @optional_fields ~w(order type early_submission_xp - hours_before_early_xp_decay show_grading_summary is_manually_graded has_voting_features)a + hours_before_early_xp_decay show_grading_summary is_manually_graded has_voting_features has_token_counter)a def changeset(assessment_config, params) do assessment_config diff --git a/priv/repo/migrations/20240321141522_add_has_voting_features_toggle_to_assessment_config.exs b/priv/repo/migrations/20240321141522_add_has_voting_features_toggle_to_assessment_config.exs new file mode 100644 index 000000000..4fe02d730 --- /dev/null +++ b/priv/repo/migrations/20240321141522_add_has_voting_features_toggle_to_assessment_config.exs @@ -0,0 +1,15 @@ +defmodule Cadet.Repo.Migrations.AddHasVotingFeaturesToggleToAssessmentConfig do + use Ecto.Migration + + def up do + alter table(:assessment_configs) do + add(:has_voting_features, :boolean, null: false, default: false) + end + end + + def down do + alter table(:assessment_configs) do + remove(:has_voting_features) + end + end +end From d2bfd924e9be49074143cfccce32c8b3b9e455f4 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 01:13:03 +0800 Subject: [PATCH 03/35] Added hasVotingFeature to assessmentConfig --- ...717_rename_has_token_counter_to_has_voting_features.exs | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs diff --git a/priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs b/priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs deleted file mode 100644 index 61f689930..000000000 --- a/priv/repo/migrations/20240320151717_rename_has_token_counter_to_has_voting_features.exs +++ /dev/null @@ -1,7 +0,0 @@ -defmodule Cadet.Repo.Migrations.RenameHasTokenCounterToHasVotingFeatures do - use Ecto.Migration - - def change do - rename(table(:assessment_configs), :has_token_counter, to: :has_voting_features) - end -end From cb18e73d13d37184931b9e7e680d464f94588476 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 01:13:55 +0800 Subject: [PATCH 04/35] Added hasTokenCounter and hasVotingFeatures to assessments --- lib/cadet/assessments/assessment.ex | 6 ++++-- ...d_has_token_counter_toggle_to_assessment.exs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 priv/repo/migrations/20240320154407_add_has_token_counter_toggle_to_assessment.exs diff --git a/lib/cadet/assessments/assessment.ex b/lib/cadet/assessments/assessment.ex index 77d0ef513..715ded37e 100644 --- a/lib/cadet/assessments/assessment.ex +++ b/lib/cadet/assessments/assessment.ex @@ -32,6 +32,8 @@ defmodule Cadet.Assessments.Assessment do field(:story, :string) field(:reading, :string) field(:password, :string, default: nil) + field(:has_token_counter, :boolean, default: :false) + field(:has_voting_features, :boolean, default: :false) belongs_to(:config, AssessmentConfig) belongs_to(:course, Course) @@ -40,9 +42,9 @@ defmodule Cadet.Assessments.Assessment do timestamps() end - @required_fields ~w(title open_at close_at number course_id config_id)a + @required_fields ~w(title open_at close_at number course_id config_id )a @optional_fields ~w(reading summary_short summary_long - is_published story cover_picture access password)a + is_published story cover_picture access password has_token_counter has_voting_features)a @optional_file_fields ~w(mission_pdf)a def changeset(assessment, params) do diff --git a/priv/repo/migrations/20240320154407_add_has_token_counter_toggle_to_assessment.exs b/priv/repo/migrations/20240320154407_add_has_token_counter_toggle_to_assessment.exs new file mode 100644 index 000000000..6bb8daaed --- /dev/null +++ b/priv/repo/migrations/20240320154407_add_has_token_counter_toggle_to_assessment.exs @@ -0,0 +1,17 @@ +defmodule Cadet.Repo.Migrations.AddHasTokenCounterToggleToAssessment do + use Ecto.Migration + + def up do + alter table(:assessments) do + add(:has_token_counter, :boolean, null: false, default: false) + add(:has_voting_features, :boolean, null: false, default: false) + end + end + + def down do + alter table(:assessments) do + remove(:has_token_counter) + remove(:has_voting_features) + end + end +end From 6012b112e949c9e1bb08c8664d388d18ff284256 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 01:15:06 +0800 Subject: [PATCH 05/35] hasTokenCounter and hasVotingFeatures to be updated to ones in assessment config when uploaded --- lib/cadet/jobs/xml_parser.ex | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/cadet/jobs/xml_parser.ex b/lib/cadet/jobs/xml_parser.ex index fb1742571..36399aa85 100644 --- a/lib/cadet/jobs/xml_parser.ex +++ b/lib/cadet/jobs/xml_parser.ex @@ -5,8 +5,11 @@ defmodule Cadet.Updater.XMLParser do use Cadet, [:display] + import Ecto.Query import SweetXml + alias Cadet.Repo + alias Cadet.Courses.AssessmentConfig alias Cadet.Assessments require Logger @@ -80,6 +83,11 @@ defmodule Cadet.Updater.XMLParser do close_at = Timex.shift(open_at, days: 7) + assessmentConfig = + AssessmentConfig + |> where(id: ^assessment_config_id) + |> Repo.one() + assessment_params = xml |> xpath( @@ -99,6 +107,8 @@ defmodule Cadet.Updater.XMLParser do |> Map.put(:close_at, close_at) |> Map.put(:course_id, course_id) |> Map.put(:config_id, assessment_config_id) + |> Map.put(:has_token_counter, assessmentConfig.has_token_counter) + |> Map.put(:has_voting_features, assessmentConfig.has_voting_features) |> (&if(&1.access === "public", do: Map.put(&1, :password, nil), else: &1 From ade5541da0b0a8003c72278242dfc3a22f9659d3 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 01:16:21 +0800 Subject: [PATCH 06/35] Added hasTokenCounter and hasVotingFeatures to be shown when assessment is requested --- lib/cadet_web/admin_views/admin_assessments_view.ex | 5 ++++- lib/cadet_web/admin_views/admin_courses_view.ex | 1 + lib/cadet_web/views/assessments_view.ex | 5 ++++- lib/cadet_web/views/user_view.ex | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/cadet_web/admin_views/admin_assessments_view.ex b/lib/cadet_web/admin_views/admin_assessments_view.ex index 4b1274d5d..9566be027 100644 --- a/lib/cadet_web/admin_views/admin_assessments_view.ex +++ b/lib/cadet_web/admin_views/admin_assessments_view.ex @@ -27,7 +27,9 @@ defmodule CadetWeb.AdminAssessmentsView do private: &password_protected?(&1.password), isPublished: :is_published, questionCount: :question_count, - gradedCount: &(&1.graded_count || 0) + gradedCount: &(&1.graded_count || 0), + hasVotingFeatures: :has_voting_features, + hasTokenCounter: :has_token_counter }) end @@ -43,6 +45,7 @@ defmodule CadetWeb.AdminAssessmentsView do number: :number, reading: :reading, longSummary: :summary_long, + hasTokenCounter: :has_token_counter, missionPDF: &Cadet.Assessments.Upload.url({&1.mission_pdf, &1}), questions: &Enum.map(&1.questions, fn question -> diff --git a/lib/cadet_web/admin_views/admin_courses_view.ex b/lib/cadet_web/admin_views/admin_courses_view.ex index f561fa815..2804eb664 100644 --- a/lib/cadet_web/admin_views/admin_courses_view.ex +++ b/lib/cadet_web/admin_views/admin_courses_view.ex @@ -13,6 +13,7 @@ defmodule CadetWeb.AdminCoursesView do isManuallyGraded: :is_manually_graded, earlySubmissionXp: :early_submission_xp, hasVotingFeatures: :has_voting_features, + hasTokenCounter: :has_token_counter, hoursBeforeEarlyXpDecay: :hours_before_early_xp_decay }) end diff --git a/lib/cadet_web/views/assessments_view.ex b/lib/cadet_web/views/assessments_view.ex index 20aad951f..d712f1cfd 100644 --- a/lib/cadet_web/views/assessments_view.ex +++ b/lib/cadet_web/views/assessments_view.ex @@ -28,7 +28,9 @@ defmodule CadetWeb.AssessmentsView do private: &password_protected?(&1.password), isPublished: :is_published, questionCount: :question_count, - gradedCount: &(&1.graded_count || 0) + gradedCount: &(&1.graded_count || 0), + hasVotingFeatures: :has_voting_features, + hasTokenCounter: :has_token_counter }) end @@ -44,6 +46,7 @@ defmodule CadetWeb.AssessmentsView do number: :number, reading: :reading, longSummary: :summary_long, + hasTokenCounter: :has_token_counter, missionPDF: &Cadet.Assessments.Upload.url({&1.mission_pdf, &1}), questions: &Enum.map(&1.questions, fn question -> diff --git a/lib/cadet_web/views/user_view.ex b/lib/cadet_web/views/user_view.ex index c153e841b..84b5b5392 100644 --- a/lib/cadet_web/views/user_view.ex +++ b/lib/cadet_web/views/user_view.ex @@ -126,6 +126,7 @@ defmodule CadetWeb.UserView do displayInDashboard: :show_grading_summary, isManuallyGraded: :is_manually_graded, hasVotingFeatures: :has_voting_features, + hasTokenCounter: :has_token_counter, earlySubmissionXp: :early_submission_xp, hoursBeforeEarlyXpDecay: :hours_before_early_xp_decay }) From 284da0622a14c9e6544a6861c8547f0855a98f1e Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 01:17:00 +0800 Subject: [PATCH 07/35] Added hasTokenCounter into swaggers --- lib/cadet_web/controllers/assessments_controller.ex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/cadet_web/controllers/assessments_controller.ex b/lib/cadet_web/controllers/assessments_controller.ex index 5fb0659ec..bc053afe4 100644 --- a/lib/cadet_web/controllers/assessments_controller.ex +++ b/lib/cadet_web/controllers/assessments_controller.ex @@ -174,6 +174,8 @@ defmodule CadetWeb.AssessmentsController do required: true ) + hasTokenCounter(:boolean, "Does the assessment have Token Counter enabled?") + maxXp( :integer, "The maximum XP for this assessment", @@ -214,6 +216,7 @@ defmodule CadetWeb.AssessmentsController do story(:string, "The story that should be shown for this assessment") reading(:string, "The reading for this assessment") longSummary(:string, "Long summary", required: true) + hasTokenCounter(:boolean, "Does the assessment have Token Counter enabled?") missionPDF(:string, "The URL to the assessment pdf") questions(Schema.ref(:Questions), "The list of questions for this assessment") From 96d1dc7bba428d927d02b34e34d4fb03303ebfb4 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 01:17:23 +0800 Subject: [PATCH 08/35] Changed test cases to include hasVotingFeatures and hasTokenCounter --- .../admin_assessments_controller_test.exs | 8 ++++++-- .../admin_courses_controller_test.exs | 12 ++++++++---- .../controllers/assessments_controller_test.exs | 11 +++++++++-- test/cadet_web/controllers/user_controller_test.exs | 9 ++++++--- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs index f1411ada3..fe693f206 100644 --- a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs +++ b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs @@ -89,7 +89,9 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do "isPublished" => &1.is_published, "gradedCount" => 0, "questionCount" => 9, - "xp" => (800 + 500 + 100) * 3 + "xp" => (800 + 500 + 100) * 3, + "hasVotingFeatures" => &1.has_voting_features, + "hasTokenCounter" => &1.has_token_counter } ) @@ -135,7 +137,9 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do "isPublished" => &1.is_published, "gradedCount" => 0, "questionCount" => 9, - "xp" => 0 + "xp" => 0, + "hasVotingFeatures" => &1.has_voting_features, + "hasTokenCounter" => &1.has_token_counter } ) diff --git a/test/cadet_web/admin_controllers/admin_courses_controller_test.exs b/test/cadet_web/admin_controllers/admin_courses_controller_test.exs index c29ddbb02..c9a3096c2 100644 --- a/test/cadet_web/admin_controllers/admin_courses_controller_test.exs +++ b/test/cadet_web/admin_controllers/admin_courses_controller_test.exs @@ -158,7 +158,8 @@ defmodule CadetWeb.AdminCoursesControllerTest do order: 2, type: "Mission2", course: course, - has_voting_features: true + has_voting_features: true, + has_token_counter: true }) resp = @@ -174,7 +175,8 @@ defmodule CadetWeb.AdminCoursesControllerTest do "isManuallyGraded" => true, "type" => "Mission1", "assessmentConfigId" => config1.id, - "hasVotingFeatures" => false + "hasVotingFeatures" => false, + "hasTokenCounter" => false }, %{ "earlySubmissionXp" => 200, @@ -183,7 +185,8 @@ defmodule CadetWeb.AdminCoursesControllerTest do "isManuallyGraded" => false, "type" => "Mission2", "assessmentConfigId" => config2.id, - "hasVotingFeatures" => true + "hasVotingFeatures" => true, + "hasTokenCounter" => true }, %{ "earlySubmissionXp" => 200, @@ -192,7 +195,8 @@ defmodule CadetWeb.AdminCoursesControllerTest do "isManuallyGraded" => true, "type" => "Mission3", "assessmentConfigId" => config3.id, - "hasVotingFeatures" => false + "hasVotingFeatures" => false, + "hasTokenCounter" => false } ] diff --git a/test/cadet_web/controllers/assessments_controller_test.exs b/test/cadet_web/controllers/assessments_controller_test.exs index f9251d09b..1e2c5a49c 100644 --- a/test/cadet_web/controllers/assessments_controller_test.exs +++ b/test/cadet_web/controllers/assessments_controller_test.exs @@ -78,7 +78,9 @@ defmodule CadetWeb.AssessmentsControllerTest do "private" => false, "isPublished" => &1.is_published, "gradedCount" => 0, - "questionCount" => 9 + "questionCount" => 9, + "hasVotingFeatures" => &1.has_voting_features, + "hasTokenCounter" => &1.has_token_counter } ) @@ -161,7 +163,9 @@ defmodule CadetWeb.AssessmentsControllerTest do "private" => false, "isPublished" => &1.is_published, "gradedCount" => 0, - "questionCount" => 9 + "questionCount" => 9, + "hasVotingFeatures" => &1.has_voting_features, + "hasTokenCounter" => &1.has_token_counter } ) @@ -271,6 +275,8 @@ defmodule CadetWeb.AssessmentsControllerTest do "private" => false, "gradedCount" => 0, "questionCount" => 9, + "hasVotingFeatures" => &1.has_voting_features, + "hasTokenCounter" => &1.has_token_counter, "isPublished" => if &1.config.type == hd(configs).type do false @@ -305,6 +311,7 @@ defmodule CadetWeb.AssessmentsControllerTest do "number" => assessment.number, "reading" => assessment.reading, "longSummary" => assessment.summary_long, + "hasTokenCounter" => assessment.has_token_counter, "missionPDF" => Cadet.Assessments.Upload.url({assessment.mission_pdf, assessment}) } diff --git a/test/cadet_web/controllers/user_controller_test.exs b/test/cadet_web/controllers/user_controller_test.exs index 09bfffb88..1b6465af5 100644 --- a/test/cadet_web/controllers/user_controller_test.exs +++ b/test/cadet_web/controllers/user_controller_test.exs @@ -123,7 +123,8 @@ defmodule CadetWeb.UserControllerTest do "assessmentConfigId" => config1.id, "earlySubmissionXp" => 200, "hoursBeforeEarlyXpDecay" => 48, - "hasVotingFeatures" => false + "hasVotingFeatures" => false, + "hasTokenCounter" => false }, %{ "type" => "test type 2", @@ -132,7 +133,8 @@ defmodule CadetWeb.UserControllerTest do "assessmentConfigId" => config2.id, "earlySubmissionXp" => 200, "hoursBeforeEarlyXpDecay" => 48, - "hasVotingFeatures" => false + "hasVotingFeatures" => false, + "hasTokenCounter" => false }, %{ "type" => "test type 3", @@ -141,7 +143,8 @@ defmodule CadetWeb.UserControllerTest do "assessmentConfigId" => config3.id, "earlySubmissionXp" => 200, "hoursBeforeEarlyXpDecay" => 48, - "hasVotingFeatures" => false + "hasVotingFeatures" => false, + "hasTokenCounter" => false } ] } From 96879304cdda1fd08f928ab67862decc707af7c4 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:07:34 +0800 Subject: [PATCH 09/35] Added a way to change hasTokenCounter and hasVotingFeatures from the frontEnd --- .../admin_controllers/admin_assessments_controller.ex | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 4a5076b33..68e8f2483 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -82,6 +82,8 @@ defmodule CadetWeb.AdminAssessmentsController do open_at = params |> Map.get("openAt") close_at = params |> Map.get("closeAt") is_published = params |> Map.get("isPublished") + has_token_counter = params |> Map.get("hasTokenCounter") + has_voting_features = params |> Map.get("hasVotingFeatures") updated_assessment = if is_nil(is_published) do @@ -90,6 +92,15 @@ defmodule CadetWeb.AdminAssessmentsController do %{:is_published => is_published} end + updated_assessment = + if is_nil(has_token_counter) do + updated_assessment + else + updated_assessment + |> Map.put(:has_token_counter, has_token_counter) + |> Map.put(:has_voting_features, has_voting_features) + end + with {:ok, assessment} <- check_dates(open_at, close_at, updated_assessment), {:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment) do text(conn, "OK") From 0bc248606e1c3ca9eebc9e7db23197bf02040a18 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:07:41 +0800 Subject: [PATCH 10/35] fixed format --- lib/cadet/assessments/assessment.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cadet/assessments/assessment.ex b/lib/cadet/assessments/assessment.ex index 715ded37e..4e692ed7d 100644 --- a/lib/cadet/assessments/assessment.ex +++ b/lib/cadet/assessments/assessment.ex @@ -32,8 +32,8 @@ defmodule Cadet.Assessments.Assessment do field(:story, :string) field(:reading, :string) field(:password, :string, default: nil) - field(:has_token_counter, :boolean, default: :false) - field(:has_voting_features, :boolean, default: :false) + field(:has_token_counter, :boolean, default: false) + field(:has_voting_features, :boolean, default: false) belongs_to(:config, AssessmentConfig) belongs_to(:course, Course) From 394cb5201f98f4e47b8cf9ee65c9d76de78358e8 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 21:59:47 +0800 Subject: [PATCH 11/35] fixed format --- lib/cadet/jobs/xml_parser.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cadet/jobs/xml_parser.ex b/lib/cadet/jobs/xml_parser.ex index 36399aa85..18392311d 100644 --- a/lib/cadet/jobs/xml_parser.ex +++ b/lib/cadet/jobs/xml_parser.ex @@ -83,7 +83,7 @@ defmodule Cadet.Updater.XMLParser do close_at = Timex.shift(open_at, days: 7) - assessmentConfig = + assessment_config = AssessmentConfig |> where(id: ^assessment_config_id) |> Repo.one() @@ -107,8 +107,8 @@ defmodule Cadet.Updater.XMLParser do |> Map.put(:close_at, close_at) |> Map.put(:course_id, course_id) |> Map.put(:config_id, assessment_config_id) - |> Map.put(:has_token_counter, assessmentConfig.has_token_counter) - |> Map.put(:has_voting_features, assessmentConfig.has_voting_features) + |> Map.put(:has_token_counter, assessment_config.has_token_counter) + |> Map.put(:has_voting_features, assessment_config.has_voting_features) |> (&if(&1.access === "public", do: Map.put(&1, :password, nil), else: &1 From 49ac07db1d5d17a03791ee851c9108162da5512c Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 22 Mar 2024 22:04:54 +0800 Subject: [PATCH 12/35] fixed alias format --- lib/cadet/jobs/xml_parser.ex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/cadet/jobs/xml_parser.ex b/lib/cadet/jobs/xml_parser.ex index 18392311d..09640b565 100644 --- a/lib/cadet/jobs/xml_parser.ex +++ b/lib/cadet/jobs/xml_parser.ex @@ -8,9 +8,7 @@ defmodule Cadet.Updater.XMLParser do import Ecto.Query import SweetXml - alias Cadet.Repo - alias Cadet.Courses.AssessmentConfig - alias Cadet.Assessments + alias Cadet.{Repo, Courses.AssessmentConfig, Assessments} require Logger From 74dfaed4263c6cc06af9cfd147434fa229900b61 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sun, 24 Mar 2024 22:46:16 +0800 Subject: [PATCH 13/35] added new function to delete voteSubmissions and call InsertVoting --- lib/cadet/assessments/assessments.ex | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index 871b0fc7c..c2590abec 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -516,6 +516,45 @@ defmodule Cadet.Assessments do Question.changeset(%Question{}, params_with_assessment_id) end + def update_voting(assessment_id, publish_voting) do + if publish_voting do + Submission + |> where(assessment_id: ^assessment_id) + |> delete_submission_assocation(assessment_id) + + Question + |> where(assessment_id: ^assessment_id) + |> Repo.all() + |> Enum.each(fn q -> + delete_submission_votes_association(q) + end) + + voting_assigned_question_ids = + SubmissionVotes + |> select([v], v.question_id) + |> Repo.all() + + unpublished_voting_questions = + Question + |> where(type: :voting) + |> where([q], q.id not in ^voting_assigned_question_ids) + |> where(assessment_id: ^assessment_id) + |> join(:inner, [q], asst in assoc(q, :assessment)) + |> select([q, asst], %{course_id: asst.course_id, question: q.question, id: q.id}) + |> Repo.all() + + for q <- unpublished_voting_questions do + insert_voting(q.course_id, q.question["contest_number"], q.id) + end + + {:ok, nil} + else + + {:ok, "no change to voting"} + end + + end + def update_final_contest_entries do # 1435 = 1 day - 5 minutes if Log.log_execution("update_final_contest_entries", Duration.from_minutes(1435)) do From 41c61a3a79dd9b4fc85521787ad1710102d92c35 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sun, 24 Mar 2024 22:46:46 +0800 Subject: [PATCH 14/35] Added ability to reassign voting --- .../admin_controllers/admin_assessments_controller.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 68e8f2483..bd0c61948 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -84,6 +84,7 @@ defmodule CadetWeb.AdminAssessmentsController do is_published = params |> Map.get("isPublished") has_token_counter = params |> Map.get("hasTokenCounter") has_voting_features = params |> Map.get("hasVotingFeatures") + reassign_voting = params |> Map.get("reassignEntriesForVoting") updated_assessment = if is_nil(is_published) do @@ -102,7 +103,8 @@ defmodule CadetWeb.AdminAssessmentsController do end with {:ok, assessment} <- check_dates(open_at, close_at, updated_assessment), - {:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment) do + {:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment), + {:ok, _nil} <- Assessments.update_voting(assessment_id, reassign_voting) do text(conn, "OK") else {:error, {status, message}} -> From 88f36533555ca06aa04b9093a52f982e6d55d182 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sun, 24 Mar 2024 23:26:54 +0800 Subject: [PATCH 15/35] rename update_voting to reassign_voting for clarity --- lib/cadet/assessments/assessments.ex | 4 ++-- .../admin_controllers/admin_assessments_controller.ex | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index c2590abec..783718775 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -516,8 +516,8 @@ defmodule Cadet.Assessments do Question.changeset(%Question{}, params_with_assessment_id) end - def update_voting(assessment_id, publish_voting) do - if publish_voting do + def reassign_voting(assessment_id, is_reassigning_voting) do + if is_reassigning_voting do Submission |> where(assessment_id: ^assessment_id) |> delete_submission_assocation(assessment_id) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index bd0c61948..4f1f12717 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -84,7 +84,7 @@ defmodule CadetWeb.AdminAssessmentsController do is_published = params |> Map.get("isPublished") has_token_counter = params |> Map.get("hasTokenCounter") has_voting_features = params |> Map.get("hasVotingFeatures") - reassign_voting = params |> Map.get("reassignEntriesForVoting") + is_reassigning_voting = params |> Map.get("reassignEntriesForVoting") updated_assessment = if is_nil(is_published) do @@ -104,7 +104,7 @@ defmodule CadetWeb.AdminAssessmentsController do with {:ok, assessment} <- check_dates(open_at, close_at, updated_assessment), {:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment), - {:ok, _nil} <- Assessments.update_voting(assessment_id, reassign_voting) do + {:ok, _nil} <- Assessments.reassign_voting(assessment_id, is_reassigning_voting) do text(conn, "OK") else {:error, {status, message}} -> From 48205a8918def171ce9d46e61269e486bba608dc Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sun, 24 Mar 2024 23:33:16 +0800 Subject: [PATCH 16/35] added test case for reassign_voting --- test/cadet/assessments/assessments_test.exs | 72 +++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 7894ed5de..8d376dd8c 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -268,6 +268,78 @@ defmodule Cadet.AssessmentsTest do assert SubmissionVotes |> where(question_id: ^question.id) |> Repo.all() |> length() == 0 end + test "function that reassign voting after voting is assigned" do + course = insert(:course) + config = insert(:assessment_config) + # contest assessment that has closed + closed_contest_assessment = + insert(:assessment, + is_published: true, + open_at: Timex.shift(Timex.now(), days: -5), + close_at: Timex.shift(Timex.now(), hours: -1), + course: course, + config: config + ) + + contest_question = insert(:programming_question, assessment: closed_contest_assessment) + voting_assessment = insert(:assessment, %{course: course}) + + question = + insert(:voting_question, %{ + assessment: voting_assessment, + question: + build(:voting_question_content, contest_number: closed_contest_assessment.number) + }) + + students = + insert_list(6, :course_registration, %{ + role: :student, + course: course + }) + + Enum.map(students, fn student -> + submission = + insert(:submission, + student: student, + assessment: contest_question.assessment, + status: "submitted" + ) + + insert(:answer, + answer: %{code: "return 2;"}, + submission: submission, + question: contest_question + ) + end) + + unattempted_student = insert(:course_registration, %{role: :student, course: course}) + + # unattempted submission will automatically be submitted after the assessment closes. + unattempted_submission = + insert(:submission, + student: unattempted_student, + assessment: contest_question.assessment, + status: "submitted" + ) + + insert(:answer, + answer: %{ + code: "// question was left blank by student" + }, + submission: unattempted_submission, + question: contest_question + ) + + Assessments.insert_voting(course.id, contest_question.assessment.number, question.id) + Assessments.reassign_voting(voting_assessment.id, true) + + + # students with own contest submissions will vote for 5 entries + # students without own contest submissin will vote for 6 entries + assert SubmissionVotes |> where(question_id: ^question.id) |> Repo.all() |> length() == + 6 * 5 + 6 + end + test "function that checks for closed contests and releases entries into voting pool" do course = insert(:course) config = insert(:assessment_config) From f93efca646c1c70e248a089c0fb45f01dc2b2252 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:37:48 +0800 Subject: [PATCH 17/35] rename reassignEntriesForVoting to assignEntriesForVoting --- lib/cadet_web/admin_controllers/admin_assessments_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 4f1f12717..75c8fca21 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -84,7 +84,7 @@ defmodule CadetWeb.AdminAssessmentsController do is_published = params |> Map.get("isPublished") has_token_counter = params |> Map.get("hasTokenCounter") has_voting_features = params |> Map.get("hasVotingFeatures") - is_reassigning_voting = params |> Map.get("reassignEntriesForVoting") + is_reassigning_voting = params |> Map.get("assignEntriesForVoting") updated_assessment = if is_nil(is_published) do From 6ee9e467cae855d9ba189766c5e806e0ea1202f5 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Tue, 26 Mar 2024 20:36:52 +0800 Subject: [PATCH 18/35] added isVotingPublished to AssessmentOverview and changed testCases to match --- .../admin_views/admin_assessments_view.ex | 19 +++++++++++++++- lib/cadet_web/views/assessments_view.ex | 19 +++++++++++++++- .../admin_assessments_controller_test.exs | 21 +++++++++++++++--- .../assessments_controller_test.exs | 22 ++++++++++++++++--- 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/lib/cadet_web/admin_views/admin_assessments_view.ex b/lib/cadet_web/admin_views/admin_assessments_view.ex index 9566be027..849cc5847 100644 --- a/lib/cadet_web/admin_views/admin_assessments_view.ex +++ b/lib/cadet_web/admin_views/admin_assessments_view.ex @@ -2,6 +2,9 @@ defmodule CadetWeb.AdminAssessmentsView do use CadetWeb, :view use Timex import CadetWeb.AssessmentsHelpers + import Ecto.Query + alias Cadet.Assessments.{Question, SubmissionVotes} + alias Cadet.Repo def render("index.json", %{assessments: assessments}) do render_many(assessments, CadetWeb.AdminAssessmentsView, "overview.json", as: :assessment) @@ -29,7 +32,8 @@ defmodule CadetWeb.AdminAssessmentsView do questionCount: :question_count, gradedCount: &(&1.graded_count || 0), hasVotingFeatures: :has_voting_features, - hasTokenCounter: :has_token_counter + hasTokenCounter: :has_token_counter, + isVotingPublished: &is_voting_assigned(&1.id) }) end @@ -63,4 +67,17 @@ defmodule CadetWeb.AdminAssessmentsView do defp password_protected?(nil), do: false defp password_protected?(_), do: true + + defp is_voting_assigned(assessment_id) do + voting_assigned_question_ids = + SubmissionVotes + |> select([v], v.question_id) + |> Repo.all() + + Question + |> where(type: :voting) + |> where(assessment_id: ^assessment_id) + |> where([q], q.id in ^voting_assigned_question_ids) + |> Repo.exists?() + end end diff --git a/lib/cadet_web/views/assessments_view.ex b/lib/cadet_web/views/assessments_view.ex index d712f1cfd..1a4f2af3a 100644 --- a/lib/cadet_web/views/assessments_view.ex +++ b/lib/cadet_web/views/assessments_view.ex @@ -1,6 +1,9 @@ defmodule CadetWeb.AssessmentsView do use CadetWeb, :view use Timex + import Ecto.Query + alias Cadet.Assessments.{Question, SubmissionVotes} + alias Cadet.Repo import CadetWeb.AssessmentsHelpers @@ -30,7 +33,8 @@ defmodule CadetWeb.AssessmentsView do questionCount: :question_count, gradedCount: &(&1.graded_count || 0), hasVotingFeatures: :has_voting_features, - hasTokenCounter: :has_token_counter + hasTokenCounter: :has_token_counter, + isVotingPublished: &is_voting_assigned(&1.id) }) end @@ -64,4 +68,17 @@ defmodule CadetWeb.AssessmentsView do defp password_protected?(nil), do: false defp password_protected?(_), do: true + + defp is_voting_assigned(assessment_id) do + voting_assigned_question_ids = + SubmissionVotes + |> select([v], v.question_id) + |> Repo.all() + + Question + |> where(type: :voting) + |> where(assessment_id: ^assessment_id) + |> where([q], q.id in ^voting_assigned_question_ids) + |> Repo.exists?() + end end diff --git a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs index fe693f206..910a8d4fe 100644 --- a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs +++ b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs @@ -7,7 +7,7 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do alias Cadet.Repo alias Cadet.Accounts.CourseRegistration - alias Cadet.Assessments.{Assessment, Submission} + alias Cadet.Assessments.{Assessment, Submission, SubmissionVotes, Question} alias Cadet.Test.XMLGenerator alias CadetWeb.AdminAssessmentsController @@ -91,7 +91,8 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do "questionCount" => 9, "xp" => (800 + 500 + 100) * 3, "hasVotingFeatures" => &1.has_voting_features, - "hasTokenCounter" => &1.has_token_counter + "hasTokenCounter" => &1.has_token_counter, + "isVotingPublished" => is_voting_published(&1) } ) @@ -139,7 +140,8 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do "questionCount" => 9, "xp" => 0, "hasVotingFeatures" => &1.has_voting_features, - "hasTokenCounter" => &1.has_token_counter + "hasTokenCounter" => &1.has_token_counter, + "isVotingPublished" => is_voting_published(&1) } ) @@ -692,4 +694,17 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do (submission && submission.status |> Atom.to_string()) || "not_attempted" end + + defp is_voting_published(assessment) do + voting_assigned_question_ids = + SubmissionVotes + |> select([v], v.question_id) + |> Repo.all() + + Question + |> where(type: :voting) + |> where(assessment_id: ^assessment.id) + |> where([q], q.id in ^voting_assigned_question_ids) + |> Repo.exists?() + end end diff --git a/test/cadet_web/controllers/assessments_controller_test.exs b/test/cadet_web/controllers/assessments_controller_test.exs index 1e2c5a49c..2f173937f 100644 --- a/test/cadet_web/controllers/assessments_controller_test.exs +++ b/test/cadet_web/controllers/assessments_controller_test.exs @@ -7,7 +7,7 @@ defmodule CadetWeb.AssessmentsControllerTest do alias Cadet.{Assessments, Repo} alias Cadet.Accounts.{Role, CourseRegistration} - alias Cadet.Assessments.{Assessment, Submission, SubmissionStatus} + alias Cadet.Assessments.{Assessment, Submission, SubmissionStatus, SubmissionVotes, Question} alias Cadet.Autograder.GradingJob alias CadetWeb.AssessmentsController @@ -80,7 +80,8 @@ defmodule CadetWeb.AssessmentsControllerTest do "gradedCount" => 0, "questionCount" => 9, "hasVotingFeatures" => &1.has_voting_features, - "hasTokenCounter" => &1.has_token_counter + "hasTokenCounter" => &1.has_token_counter, + "isVotingPublished" => is_voting_published(&1) } ) @@ -165,7 +166,8 @@ defmodule CadetWeb.AssessmentsControllerTest do "gradedCount" => 0, "questionCount" => 9, "hasVotingFeatures" => &1.has_voting_features, - "hasTokenCounter" => &1.has_token_counter + "hasTokenCounter" => &1.has_token_counter, + "isVotingPublished" => is_voting_published(&1) } ) @@ -277,6 +279,7 @@ defmodule CadetWeb.AssessmentsControllerTest do "questionCount" => 9, "hasVotingFeatures" => &1.has_voting_features, "hasTokenCounter" => &1.has_token_counter, + "isVotingPublished" => is_voting_published(&1), "isPublished" => if &1.config.type == hd(configs).type do false @@ -1579,4 +1582,17 @@ defmodule CadetWeb.AssessmentsControllerTest do (submission && submission.status |> Atom.to_string()) || "not_attempted" end + + defp is_voting_published(assessment) do + voting_assigned_question_ids = + SubmissionVotes + |> select([v], v.question_id) + |> Repo.all() + + Question + |> where(type: :voting) + |> where(assessment_id: ^assessment.id) + |> where([q], q.id in ^voting_assigned_question_ids) + |> Repo.exists?() + end end From f625fff8e833fa83bcf64be0fc1e04107764fe18 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Tue, 26 Mar 2024 20:37:10 +0800 Subject: [PATCH 19/35] fixed format --- lib/cadet/assessments/assessments.ex | 48 ++++++++++----------- test/cadet/assessments/assessments_test.exs | 1 - 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index 783718775..d9dfc6b69 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -518,41 +518,39 @@ defmodule Cadet.Assessments do def reassign_voting(assessment_id, is_reassigning_voting) do if is_reassigning_voting do - Submission - |> where(assessment_id: ^assessment_id) - |> delete_submission_assocation(assessment_id) + Submission + |> where(assessment_id: ^assessment_id) + |> delete_submission_assocation(assessment_id) + + Question + |> where(assessment_id: ^assessment_id) + |> Repo.all() + |> Enum.each(fn q -> + delete_submission_votes_association(q) + end) + + voting_assigned_question_ids = + SubmissionVotes + |> select([v], v.question_id) + |> Repo.all() + unpublished_voting_questions = Question + |> where(type: :voting) + |> where([q], q.id not in ^voting_assigned_question_ids) |> where(assessment_id: ^assessment_id) + |> join(:inner, [q], asst in assoc(q, :assessment)) + |> select([q, asst], %{course_id: asst.course_id, question: q.question, id: q.id}) |> Repo.all() - |> Enum.each(fn q -> - delete_submission_votes_association(q) - end) - - voting_assigned_question_ids = - SubmissionVotes - |> select([v], v.question_id) - |> Repo.all() - - unpublished_voting_questions = - Question - |> where(type: :voting) - |> where([q], q.id not in ^voting_assigned_question_ids) - |> where(assessment_id: ^assessment_id) - |> join(:inner, [q], asst in assoc(q, :assessment)) - |> select([q, asst], %{course_id: asst.course_id, question: q.question, id: q.id}) - |> Repo.all() - for q <- unpublished_voting_questions do - insert_voting(q.course_id, q.question["contest_number"], q.id) - end + for q <- unpublished_voting_questions do + insert_voting(q.course_id, q.question["contest_number"], q.id) + end {:ok, nil} else - {:ok, "no change to voting"} end - end def update_final_contest_entries do diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 8d376dd8c..446732e48 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -333,7 +333,6 @@ defmodule Cadet.AssessmentsTest do Assessments.insert_voting(course.id, contest_question.assessment.number, question.id) Assessments.reassign_voting(voting_assessment.id, true) - # students with own contest submissions will vote for 5 entries # students without own contest submissin will vote for 6 entries assert SubmissionVotes |> where(question_id: ^question.id) |> Repo.all() |> length() == From 7b03f687c40302577f0bec56a31491b01d800ed6 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:35:47 +0800 Subject: [PATCH 20/35] Moved is_voting_published to be a function in assessments --- lib/cadet/assessments/assessments.ex | 20 +++++++++++++++--- .../admin_assessments_controller_test.exs | 21 ++++--------------- .../assessments_controller_test.exs | 21 ++++--------------- 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index 2e2562593..e5bc16c04 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -556,10 +556,10 @@ defmodule Cadet.Assessments do end def reassign_voting(assessment_id, is_reassigning_voting) do - if is_reassigning_voting do + if is_voting_published(assessment_id) do Submission |> where(assessment_id: ^assessment_id) - |> delete_submission_assocation(assessment_id) + |> delete_submission_association(assessment_id) Question |> where(assessment_id: ^assessment_id) @@ -567,7 +567,8 @@ defmodule Cadet.Assessments do |> Enum.each(fn q -> delete_submission_votes_association(q) end) - + end + if is_reassigning_voting do voting_assigned_question_ids = SubmissionVotes |> select([v], v.question_id) @@ -592,6 +593,19 @@ defmodule Cadet.Assessments do end end + def is_voting_published(assessment_id) do + voting_assigned_question_ids = + SubmissionVotes + |> select([v], v.question_id) + |> Repo.all() + + Question + |> where(type: :voting) + |> where(assessment_id: ^assessment_id) + |> where([q], q.id in ^voting_assigned_question_ids) + |> Repo.exists?() + end + def update_final_contest_entries do # 1435 = 1 day - 5 minutes if Log.log_execution("update_final_contest_entries", Duration.from_minutes(1435)) do diff --git a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs index 622607a27..f1a3ff0c3 100644 --- a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs +++ b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs @@ -5,9 +5,9 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do import Ecto.Query import ExUnit.CaptureLog - alias Cadet.Repo + alias Cadet.{Assessments, Repo} alias Cadet.Accounts.CourseRegistration - alias Cadet.Assessments.{Assessment, Submission, SubmissionVotes, Question} + alias Cadet.Assessments.{Assessment, Submission} alias Cadet.Test.XMLGenerator alias CadetWeb.AdminAssessmentsController @@ -94,7 +94,7 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do "earlySubmissionXp" => &1.config.early_submission_xp, "hasVotingFeatures" => &1.has_voting_features, "hasTokenCounter" => &1.has_token_counter, - "isVotingPublished" => is_voting_published(&1) + "isVotingPublished" => Assessments.is_voting_published(&1.id) } ) @@ -145,7 +145,7 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do "earlySubmissionXp" => &1.config.early_submission_xp, "hasVotingFeatures" => &1.has_voting_features, "hasTokenCounter" => &1.has_token_counter, - "isVotingPublished" => is_voting_published(&1) + "isVotingPublished" => Assessments.is_voting_published(&1.id) } ) @@ -768,17 +768,4 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do (submission && submission.status |> Atom.to_string()) || "not_attempted" end - - defp is_voting_published(assessment) do - voting_assigned_question_ids = - SubmissionVotes - |> select([v], v.question_id) - |> Repo.all() - - Question - |> where(type: :voting) - |> where(assessment_id: ^assessment.id) - |> where([q], q.id in ^voting_assigned_question_ids) - |> Repo.exists?() - end end diff --git a/test/cadet_web/controllers/assessments_controller_test.exs b/test/cadet_web/controllers/assessments_controller_test.exs index a469d1421..83f52445e 100644 --- a/test/cadet_web/controllers/assessments_controller_test.exs +++ b/test/cadet_web/controllers/assessments_controller_test.exs @@ -7,7 +7,7 @@ defmodule CadetWeb.AssessmentsControllerTest do alias Cadet.{Assessments, Repo} alias Cadet.Accounts.{Role, CourseRegistration} - alias Cadet.Assessments.{Assessment, Submission, SubmissionStatus, SubmissionVotes, Question} + alias Cadet.Assessments.{Assessment, Submission, SubmissionStatus} alias Cadet.Autograder.GradingJob alias CadetWeb.AssessmentsController @@ -83,7 +83,7 @@ defmodule CadetWeb.AssessmentsControllerTest do "earlySubmissionXp" => &1.config.early_submission_xp, "hasVotingFeatures" => &1.has_voting_features, "hasTokenCounter" => &1.has_token_counter, - "isVotingPublished" => is_voting_published(&1) + "isVotingPublished" => Assessments.is_voting_published(&1.id) } ) @@ -171,7 +171,7 @@ defmodule CadetWeb.AssessmentsControllerTest do "earlySubmissionXp" => &1.config.early_submission_xp, "hasVotingFeatures" => &1.has_voting_features, "hasTokenCounter" => &1.has_token_counter, - "isVotingPublished" => is_voting_published(&1) + "isVotingPublished" => Assessments.is_voting_published(&1.id) } ) @@ -284,7 +284,7 @@ defmodule CadetWeb.AssessmentsControllerTest do "questionCount" => 9, "hasVotingFeatures" => &1.has_voting_features, "hasTokenCounter" => &1.has_token_counter, - "isVotingPublished" => is_voting_published(&1), + "isVotingPublished" => Assessments.is_voting_published(&1.id), "earlySubmissionXp" => &1.config.early_submission_xp, "isPublished" => if &1.config.type == hd(configs).type do @@ -1589,17 +1589,4 @@ defmodule CadetWeb.AssessmentsControllerTest do (submission && submission.status |> Atom.to_string()) || "not_attempted" end - - defp is_voting_published(assessment) do - voting_assigned_question_ids = - SubmissionVotes - |> select([v], v.question_id) - |> Repo.all() - - Question - |> where(type: :voting) - |> where(assessment_id: ^assessment.id) - |> where([q], q.id in ^voting_assigned_question_ids) - |> Repo.exists?() - end end From 2c8a3329cb67a9f82478d5095de34c8cf00b7dcf Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:36:20 +0800 Subject: [PATCH 21/35] Prevent deletions of submissions if voting has not been published --- .../admin_controllers/admin_assessments_controller.ex | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index e5b23a6e2..950c085c2 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -85,7 +85,7 @@ defmodule CadetWeb.AdminAssessmentsController do max_team_size = params |> Map.get("maxTeamSize") has_token_counter = params |> Map.get("hasTokenCounter") has_voting_features = params |> Map.get("hasVotingFeatures") - is_reassigning_voting = params |> Map.get("assignEntriesForVoting") + assign_entries_for_voting = params |> Map.get("assignEntriesForVoting") updated_assessment = if is_nil(is_published) do @@ -115,9 +115,16 @@ defmodule CadetWeb.AdminAssessmentsController do Map.put(updated_assessment, :has_voting_features, has_voting_features) end + reassign_voting = + if is_nil(assign_entries_for_voting) do + false + else + assign_entries_for_voting + end + with {:ok, assessment} <- check_dates(open_at, close_at, updated_assessment), {:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment), - {:ok, _nil} <- Assessments.reassign_voting(assessment_id, is_reassigning_voting) do + {:ok, _nil} <- Assessments.reassign_voting(assessment_id, reassign_voting) do text(conn, "OK") else {:error, {status, message}} -> From 2339b36e784773c8f4c8b15d1d01f34e26d248f8 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:40:44 +0800 Subject: [PATCH 22/35] fix format --- lib/cadet/assessments/assessments.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index e5bc16c04..f3c59d181 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -568,6 +568,7 @@ defmodule Cadet.Assessments do delete_submission_votes_association(q) end) end + if is_reassigning_voting do voting_assigned_question_ids = SubmissionVotes From 293af4b76ca04472f7f4655232d40ae4b0555c36 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:42:58 +0800 Subject: [PATCH 23/35] fix bug where submission is deleted regardless of reassigning_voting status --- lib/cadet/assessments/assessments.ex | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index f3c59d181..e46312090 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -556,20 +556,20 @@ defmodule Cadet.Assessments do end def reassign_voting(assessment_id, is_reassigning_voting) do - if is_voting_published(assessment_id) do - Submission - |> where(assessment_id: ^assessment_id) - |> delete_submission_association(assessment_id) + if is_reassigning_voting do + if is_voting_published(assessment_id) do + Submission + |> where(assessment_id: ^assessment_id) + |> delete_submission_association(assessment_id) - Question - |> where(assessment_id: ^assessment_id) - |> Repo.all() - |> Enum.each(fn q -> - delete_submission_votes_association(q) - end) - end + Question + |> where(assessment_id: ^assessment_id) + |> Repo.all() + |> Enum.each(fn q -> + delete_submission_votes_association(q) + end) + end - if is_reassigning_voting do voting_assigned_question_ids = SubmissionVotes |> select([v], v.question_id) From faec738a7df305c57633373f43f74a184f59a0dd Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 29 Mar 2024 23:14:01 +0800 Subject: [PATCH 24/35] changed label for better clarity --- lib/cadet/assessments/assessments.ex | 2 +- .../admin_controllers/admin_assessments_controller.ex | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index e46312090..414fde364 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -588,7 +588,7 @@ defmodule Cadet.Assessments do insert_voting(q.course_id, q.question["contest_number"], q.id) end - {:ok, nil} + {:ok, "voting assigned"} else {:ok, "no change to voting"} end diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 950c085c2..8c43a6be6 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -115,7 +115,7 @@ defmodule CadetWeb.AdminAssessmentsController do Map.put(updated_assessment, :has_voting_features, has_voting_features) end - reassign_voting = + is_assign_voting = if is_nil(assign_entries_for_voting) do false else @@ -124,7 +124,7 @@ defmodule CadetWeb.AdminAssessmentsController do with {:ok, assessment} <- check_dates(open_at, close_at, updated_assessment), {:ok, _nil} <- Assessments.update_assessment(assessment_id, assessment), - {:ok, _nil} <- Assessments.reassign_voting(assessment_id, reassign_voting) do + {:ok, _nil} <- Assessments.reassign_voting(assessment_id, is_assign_voting) do text(conn, "OK") else {:error, {status, message}} -> From b989c5ff3a61d2f09fa9ef26ef7ca70960f14d10 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:24:27 +0800 Subject: [PATCH 25/35] added new route/endpoint to get contest leaderboards --- .../admin_assessments_controller.ex | 24 +++++++++++++++++++ lib/cadet_web/router.ex | 2 ++ 2 files changed, 26 insertions(+) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 8c43a6be6..5ffae65c6 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -6,10 +6,12 @@ defmodule CadetWeb.AdminAssessmentsController do import Ecto.Query, only: [where: 2] import Cadet.Updater.XMLParser, only: [parse_xml: 4] + alias Cadet.Assessments.Question alias Cadet.{Assessments, Repo} alias Cadet.Assessments.Assessment alias Cadet.Accounts.CourseRegistration + def index(conn, %{"course_reg_id" => course_reg_id}) do course_reg = Repo.get(CourseRegistration, course_reg_id) {:ok, assessments} = Assessments.all_assessments(course_reg) @@ -134,6 +136,28 @@ defmodule CadetWeb.AdminAssessmentsController do end end + def get_score_learderboard(conn, %{"assessmentid" => assessment_id}) do + voting_questions = + Question + |> where(type: :voting) + |> where(assessment_id: ^assessment_id) + |> Repo.one() + result = Assessments.fetch_top_relative_score_answers(voting_questions.id, 10) + + render(conn, "leaderboard.json", leaderboard: result) + end + + def get_popular_learderboard(conn, %{"assessmentid" => assessment_id}) do + voting_questions = + Question + |> where(type: :voting) + |> where(assessment_id: ^assessment_id) + |> Repo.one() + result = Assessments.fetch_top_popular_score_answers(voting_questions.id, 10) + + render(conn, "leaderboard.json", leaderboard: result) + end + defp check_dates(open_at, close_at, assessment) do if is_nil(open_at) and is_nil(close_at) do {:ok, assessment} diff --git a/lib/cadet_web/router.ex b/lib/cadet_web/router.ex index 32e94eca2..98895b41f 100644 --- a/lib/cadet_web/router.ex +++ b/lib/cadet_web/router.ex @@ -117,6 +117,8 @@ defmodule CadetWeb.Router do post("/assessments", AdminAssessmentsController, :create) post("/assessments/:assessmentid", AdminAssessmentsController, :update) delete("/assessments/:assessmentid", AdminAssessmentsController, :delete) + get("/assessments/:assessmentid/popularVoteLeaderboard", AdminAssessmentsController, :get_popular_learderboard) + get("/assessments/:assessmentid/scoreLeaderboard", AdminAssessmentsController, :get_score_learderboard) get("/grading", AdminGradingController, :index) get("/grading/summary", AdminGradingController, :grading_summary) From 2fdc1093ed1aedf97925dd1d5e23784ddbf3fc06 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:24:46 +0800 Subject: [PATCH 26/35] Added new way to display leaderboard --- .../admin_views/admin_assessments_view.ex | 25 +++++++++++++++++++ lib/cadet_web/views/assessments_view.ex | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/lib/cadet_web/admin_views/admin_assessments_view.ex b/lib/cadet_web/admin_views/admin_assessments_view.ex index d08b758ae..767db762e 100644 --- a/lib/cadet_web/admin_views/admin_assessments_view.ex +++ b/lib/cadet_web/admin_views/admin_assessments_view.ex @@ -66,6 +66,31 @@ defmodule CadetWeb.AdminAssessmentsView do ) end + def render("leaderboard.json", %{leaderboard: leaderboard}) do + render_many(leaderboard, CadetWeb.AdminAssessmentsView, "answer.json", as: :answer) + end + + def render("answer.json", %{answer: answer}) do + IO.inspect(transform_map_for_view( + answer, + %{ + student_name: :student_name, + answer: & &1.answer["code"], + popular_score: :popular_score, + relative_score: :relative_score + } + )) + transform_map_for_view( + answer, + %{ + student_name: :student_name, + answer: & &1.answer["code"], + popular_score: :popular_score, + relative_score: :relative_score + } + ) + end + defp password_protected?(nil), do: false defp password_protected?(_), do: true diff --git a/lib/cadet_web/views/assessments_view.ex b/lib/cadet_web/views/assessments_view.ex index 67442faa5..77d912c08 100644 --- a/lib/cadet_web/views/assessments_view.ex +++ b/lib/cadet_web/views/assessments_view.ex @@ -67,6 +67,31 @@ defmodule CadetWeb.AssessmentsView do ) end + def render("leaderboard.json", %{leaderboard: leaderboard}) do + render_many(leaderboard, CadetWeb.AdminAssessmentsView, "answer.json", as: :answer) + end + + def render("answer.json", %{answer: answer}) do + IO.inspect(transform_map_for_view( + answer, + %{ + student_name: :student_name, + answer: & &1.answer["code"], + popular_score: :popular_score, + relative_score: :relative_score + } + )) + transform_map_for_view( + answer, + %{ + student_name: :student_name, + answer: & &1.answer["code"], + popular_score: :popular_score, + relative_score: :relative_score + } + ) + end + defp password_protected?(nil), do: false defp password_protected?(_), do: true From b2bc496dff4805ea2e666b492029aa9352df7a66 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:28:16 +0800 Subject: [PATCH 27/35] fixed format --- .../admin_assessments_controller.ex | 3 ++- .../admin_views/admin_assessments_view.ex | 9 --------- lib/cadet_web/router.ex | 14 ++++++++++++-- lib/cadet_web/views/assessments_view.ex | 9 --------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 5ffae65c6..953db652f 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -11,7 +11,6 @@ defmodule CadetWeb.AdminAssessmentsController do alias Cadet.Assessments.Assessment alias Cadet.Accounts.CourseRegistration - def index(conn, %{"course_reg_id" => course_reg_id}) do course_reg = Repo.get(CourseRegistration, course_reg_id) {:ok, assessments} = Assessments.all_assessments(course_reg) @@ -142,6 +141,7 @@ defmodule CadetWeb.AdminAssessmentsController do |> where(type: :voting) |> where(assessment_id: ^assessment_id) |> Repo.one() + result = Assessments.fetch_top_relative_score_answers(voting_questions.id, 10) render(conn, "leaderboard.json", leaderboard: result) @@ -153,6 +153,7 @@ defmodule CadetWeb.AdminAssessmentsController do |> where(type: :voting) |> where(assessment_id: ^assessment_id) |> Repo.one() + result = Assessments.fetch_top_popular_score_answers(voting_questions.id, 10) render(conn, "leaderboard.json", leaderboard: result) diff --git a/lib/cadet_web/admin_views/admin_assessments_view.ex b/lib/cadet_web/admin_views/admin_assessments_view.ex index 767db762e..155ced738 100644 --- a/lib/cadet_web/admin_views/admin_assessments_view.ex +++ b/lib/cadet_web/admin_views/admin_assessments_view.ex @@ -71,15 +71,6 @@ defmodule CadetWeb.AdminAssessmentsView do end def render("answer.json", %{answer: answer}) do - IO.inspect(transform_map_for_view( - answer, - %{ - student_name: :student_name, - answer: & &1.answer["code"], - popular_score: :popular_score, - relative_score: :relative_score - } - )) transform_map_for_view( answer, %{ diff --git a/lib/cadet_web/router.ex b/lib/cadet_web/router.ex index 98895b41f..b6a4c428d 100644 --- a/lib/cadet_web/router.ex +++ b/lib/cadet_web/router.ex @@ -117,8 +117,18 @@ defmodule CadetWeb.Router do post("/assessments", AdminAssessmentsController, :create) post("/assessments/:assessmentid", AdminAssessmentsController, :update) delete("/assessments/:assessmentid", AdminAssessmentsController, :delete) - get("/assessments/:assessmentid/popularVoteLeaderboard", AdminAssessmentsController, :get_popular_learderboard) - get("/assessments/:assessmentid/scoreLeaderboard", AdminAssessmentsController, :get_score_learderboard) + + get( + "/assessments/:assessmentid/popularVoteLeaderboard", + AdminAssessmentsController, + :get_popular_learderboard + ) + + get( + "/assessments/:assessmentid/scoreLeaderboard", + AdminAssessmentsController, + :get_score_learderboard + ) get("/grading", AdminGradingController, :index) get("/grading/summary", AdminGradingController, :grading_summary) diff --git a/lib/cadet_web/views/assessments_view.ex b/lib/cadet_web/views/assessments_view.ex index 77d912c08..93e46f675 100644 --- a/lib/cadet_web/views/assessments_view.ex +++ b/lib/cadet_web/views/assessments_view.ex @@ -72,15 +72,6 @@ defmodule CadetWeb.AssessmentsView do end def render("answer.json", %{answer: answer}) do - IO.inspect(transform_map_for_view( - answer, - %{ - student_name: :student_name, - answer: & &1.answer["code"], - popular_score: :popular_score, - relative_score: :relative_score - } - )) transform_map_for_view( answer, %{ From e1673f69cf90ba3f6f6d66cdf7fb4cd9883dfb96 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:30:37 +0800 Subject: [PATCH 28/35] fixed credo --- .../admin_controllers/admin_assessments_controller.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 953db652f..7ff4bce5f 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -6,9 +6,8 @@ defmodule CadetWeb.AdminAssessmentsController do import Ecto.Query, only: [where: 2] import Cadet.Updater.XMLParser, only: [parse_xml: 4] - alias Cadet.Assessments.Question + alias Cadet.Assessments.{Question, Assessment} alias Cadet.{Assessments, Repo} - alias Cadet.Assessments.Assessment alias Cadet.Accounts.CourseRegistration def index(conn, %{"course_reg_id" => course_reg_id}) do From 6cbc842a6b4a9ab70cd60a3128ade60375b97709 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sat, 6 Apr 2024 13:14:58 +0800 Subject: [PATCH 29/35] changed the building of leaderboard entries to be public --- lib/cadet_web/helpers/assessments_helpers.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cadet_web/helpers/assessments_helpers.ex b/lib/cadet_web/helpers/assessments_helpers.ex index 6a03dbff2..967df1131 100644 --- a/lib/cadet_web/helpers/assessments_helpers.ex +++ b/lib/cadet_web/helpers/assessments_helpers.ex @@ -102,7 +102,7 @@ defmodule CadetWeb.AssessmentsHelpers do }) end - defp build_contest_leaderboard_entry(leaderboard_ans) do + def build_contest_leaderboard_entry(leaderboard_ans) do Map.put( transform_map_for_view(leaderboard_ans, %{ submission_id: :submission_id, @@ -114,7 +114,7 @@ defmodule CadetWeb.AssessmentsHelpers do ) end - defp build_popular_leaderboard_entry(leaderboard_ans) do + def build_popular_leaderboard_entry(leaderboard_ans) do Map.put( transform_map_for_view(leaderboard_ans, %{ submission_id: :submission_id, From 8d84973ca0455e1ca14cbcbd3adc51dda991c233 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sat, 6 Apr 2024 13:15:29 +0800 Subject: [PATCH 30/35] used previously implemented functions to build the leaderboard results --- .../admin_assessments_controller.ex | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 7ff4bce5f..3f92fbe73 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -6,6 +6,7 @@ defmodule CadetWeb.AdminAssessmentsController do import Ecto.Query, only: [where: 2] import Cadet.Updater.XMLParser, only: [parse_xml: 4] + alias CadetWeb.AssessmentsHelpers alias Cadet.Assessments.{Question, Assessment} alias Cadet.{Assessments, Repo} alias Cadet.Accounts.CourseRegistration @@ -141,7 +142,12 @@ defmodule CadetWeb.AdminAssessmentsController do |> where(assessment_id: ^assessment_id) |> Repo.one() - result = Assessments.fetch_top_relative_score_answers(voting_questions.id, 10) + result = + voting_questions.id + |> Assessments.fetch_top_relative_score_answers(10) + |> Enum.map(fn entry -> + AssessmentsHelpers.build_contest_leaderboard_entry(entry) + end) render(conn, "leaderboard.json", leaderboard: result) end @@ -153,7 +159,12 @@ defmodule CadetWeb.AdminAssessmentsController do |> where(assessment_id: ^assessment_id) |> Repo.one() - result = Assessments.fetch_top_popular_score_answers(voting_questions.id, 10) + result = + voting_questions.id + |> Assessments.fetch_top_relative_score_answers(10) + |> Enum.map(fn entry -> + AssessmentsHelpers.build_contest_leaderboard_entry(entry) + end) render(conn, "leaderboard.json", leaderboard: result) end From 0cebe51393fe57dd823e01b8e2b3628f96964516 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sat, 6 Apr 2024 13:15:49 +0800 Subject: [PATCH 31/35] Change the reference of rendering for clarity --- lib/cadet_web/admin_views/admin_assessments_view.ex | 11 ++++++----- lib/cadet_web/views/assessments_view.ex | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/cadet_web/admin_views/admin_assessments_view.ex b/lib/cadet_web/admin_views/admin_assessments_view.ex index 155ced738..848ab727c 100644 --- a/lib/cadet_web/admin_views/admin_assessments_view.ex +++ b/lib/cadet_web/admin_views/admin_assessments_view.ex @@ -67,17 +67,18 @@ defmodule CadetWeb.AdminAssessmentsView do end def render("leaderboard.json", %{leaderboard: leaderboard}) do - render_many(leaderboard, CadetWeb.AdminAssessmentsView, "answer.json", as: :answer) + render_many(leaderboard, CadetWeb.AdminAssessmentsView, "contestEntries.json", + as: :contestEntries + ) end - def render("answer.json", %{answer: answer}) do + def render("contestEntries.json", %{contestEntries: contestEntries}) do transform_map_for_view( - answer, + contestEntries, %{ student_name: :student_name, answer: & &1.answer["code"], - popular_score: :popular_score, - relative_score: :relative_score + final_score: "final_score" } ) end diff --git a/lib/cadet_web/views/assessments_view.ex b/lib/cadet_web/views/assessments_view.ex index 93e46f675..c5828454e 100644 --- a/lib/cadet_web/views/assessments_view.ex +++ b/lib/cadet_web/views/assessments_view.ex @@ -68,17 +68,18 @@ defmodule CadetWeb.AssessmentsView do end def render("leaderboard.json", %{leaderboard: leaderboard}) do - render_many(leaderboard, CadetWeb.AdminAssessmentsView, "answer.json", as: :answer) + render_many(leaderboard, CadetWeb.AdminAssessmentsView, "contestEntries.json", + as: :contestEntries + ) end - def render("answer.json", %{answer: answer}) do + def render("contestEntries.json", %{contestEntries: contestEntries}) do transform_map_for_view( - answer, + contestEntries, %{ student_name: :student_name, answer: & &1.answer["code"], - popular_score: :popular_score, - relative_score: :relative_score + final_score: "final_score" } ) end From 5e3ad277beb6e893e8d3d5d4e08bb72691e730b1 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sat, 6 Apr 2024 13:41:06 +0800 Subject: [PATCH 32/35] Added new path to swaggers --- .../admin_assessments_controller.ex | 32 +++++++++++++++++++ .../controllers/assessments_controller.ex | 14 ++++++++ 2 files changed, 46 insertions(+) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index 3f92fbe73..e9976cac1 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -265,6 +265,38 @@ defmodule CadetWeb.AdminAssessmentsController do response(403, "Forbidden") end + swagger_path :get_popular_learderboard do + get("/courses/{course_id}/admin/assessments/:assessmentid/popularVoteLeaderboard") + + summary("get the top 10 contest entries based on popularity") + + security([%{JWT: []}]) + + parameters do + assessmentId(:path, :integer, "Assessment ID", required: true) + end + + response(200, "OK", Schema.array(:Leaderboard)) + response(401, "Unauthorised") + response(403, "Forbidden") + end + + swagger_path :get_score_learderboard do + get("/courses/{course_id}/admin/assessments/:assessmentid/scoreLeaderboard") + + summary("get the top 10 contest entries based on score") + + security([%{JWT: []}]) + + parameters do + assessmentId(:path, :integer, "Assessment ID", required: true) + end + + response(200, "OK", Schema.array(:Leaderboard)) + response(401, "Unauthorised") + response(403, "Forbidden") + end + def swagger_definitions do %{ # Schemas for payloads to modify data diff --git a/lib/cadet_web/controllers/assessments_controller.ex b/lib/cadet_web/controllers/assessments_controller.ex index ce42aae49..ec64f68c9 100644 --- a/lib/cadet_web/controllers/assessments_controller.ex +++ b/lib/cadet_web/controllers/assessments_controller.ex @@ -393,6 +393,20 @@ defmodule CadetWeb.AssessmentsController do type(:string) enum([:none, :processing, :success, :failed]) end, + Leaderboard: + swagger_schema do + description("A list of top entries for leaderboard") + type(:array) + items(Schema.ref(:ContestEntries)) + end, + ContestEntries: + swagger_schema do + properties do + student_name(:string, "Name of the student", required: true) + answer(:string, "The code that the student submitted", required: true) + final_score(:float, "The score that the student obtained", required: true) + end + end, # Schemas for payloads to modify data UnlockAssessmentPayload: From 21e91dd2f13954b172d6f43e480f5782c84e608b Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:29:50 +0800 Subject: [PATCH 33/35] fixed bug which caused wrong result being displayed --- lib/cadet/assessments/assessments.ex | 2 +- .../admin_assessments_controller.ex | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/cadet/assessments/assessments.ex b/lib/cadet/assessments/assessments.ex index 414fde364..28602b298 100644 --- a/lib/cadet/assessments/assessments.ex +++ b/lib/cadet/assessments/assessments.ex @@ -1239,7 +1239,7 @@ defmodule Cadet.Assessments do end # Finds the contest_question_id associated with the given voting_question id - defp fetch_associated_contest_question_id(course_id, voting_question) do + def fetch_associated_contest_question_id(course_id, voting_question) do contest_number = voting_question.question["contest_number"] if is_nil(contest_number) do diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index e9976cac1..dc818af22 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -135,15 +135,17 @@ defmodule CadetWeb.AdminAssessmentsController do end end - def get_score_learderboard(conn, %{"assessmentid" => assessment_id}) do + def get_score_learderboard(conn, %{"assessmentid" => assessment_id, "course_id" => course_id}) do voting_questions = Question |> where(type: :voting) |> where(assessment_id: ^assessment_id) |> Repo.one() + contest_id = Assessments.fetch_associated_contest_question_id(course_id, voting_questions) + result = - voting_questions.id + contest_id |> Assessments.fetch_top_relative_score_answers(10) |> Enum.map(fn entry -> AssessmentsHelpers.build_contest_leaderboard_entry(entry) @@ -152,20 +154,24 @@ defmodule CadetWeb.AdminAssessmentsController do render(conn, "leaderboard.json", leaderboard: result) end - def get_popular_learderboard(conn, %{"assessmentid" => assessment_id}) do + def get_popular_learderboard(conn, %{"assessmentid" => assessment_id, "course_id" => course_id}) do voting_questions = Question |> where(type: :voting) |> where(assessment_id: ^assessment_id) |> Repo.one() + contest_id = Assessments.fetch_associated_contest_question_id(course_id, voting_questions) + IO.inspect(contest_id) + result = - voting_questions.id - |> Assessments.fetch_top_relative_score_answers(10) + contest_id + |> Assessments.fetch_top_popular_score_answers(10) |> Enum.map(fn entry -> - AssessmentsHelpers.build_contest_leaderboard_entry(entry) + AssessmentsHelpers.build_popular_leaderboard_entry(entry) end) + IO.inspect(result) render(conn, "leaderboard.json", leaderboard: result) end From e986394e22353aa588d85205da7c125495f863f0 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:53:10 +0800 Subject: [PATCH 34/35] Added relevant test cases --- .../admin_assessments_controller.ex | 2 - .../admin_assessments_controller_test.exs | 166 ++++++++++++++++++ 2 files changed, 166 insertions(+), 2 deletions(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index dc818af22..e56e3ef33 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -162,7 +162,6 @@ defmodule CadetWeb.AdminAssessmentsController do |> Repo.one() contest_id = Assessments.fetch_associated_contest_question_id(course_id, voting_questions) - IO.inspect(contest_id) result = contest_id @@ -171,7 +170,6 @@ defmodule CadetWeb.AdminAssessmentsController do AssessmentsHelpers.build_popular_leaderboard_entry(entry) end) - IO.inspect(result) render(conn, "leaderboard.json", leaderboard: result) end diff --git a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs index f1a3ff0c3..0b0dc1483 100644 --- a/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs +++ b/test/cadet_web/admin_controllers/admin_assessments_controller_test.exs @@ -159,6 +159,166 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do end end + describe "GET /:assessment_id/popularVoteLeaderboard, unauthenticated" do + test "unauthorized", %{conn: conn, courses: %{course1: course1}} do + config = insert(:assessment_config, %{course: course1}) + assessment = insert(:assessment, %{course: course1, config: config}) + + conn + |> get(build_popular_leaderboard_url(course1.id, assessment.id)) + |> response(401) + end + end + + describe "GET /:assessment_id/popularVoteLeaderboard, student only" do + @tag authenticate: :student + test "Forbidden", %{conn: conn} do + test_cr = conn.assigns.test_cr + course = test_cr.course + config = insert(:assessment_config, %{course: course}) + assessment = insert(:assessment, %{course: course, config: config}) + + conn + |> get(build_popular_leaderboard_url(course.id, assessment.id)) + |> response(403) + end + end + + describe "GET /:assessment_id/popularVoteLeaderboard" do + @tag authenticate: :staff + test "successful", %{conn: conn} do + test_cr = conn.assigns.test_cr + course = test_cr.course + + config = insert(:assessment_config, %{course: course}) + contest_assessment = insert(:assessment, %{course: course, config: config}) + contest_students = insert_list(5, :course_registration, %{course: course, role: :student}) + contest_question = insert(:programming_question, %{assessment: contest_assessment}) + + contest_submissions = + contest_students + |> Enum.map(&insert(:submission, %{assessment: contest_assessment, student: &1})) + + contest_answer = + contest_submissions + |> Enum.map( + &insert(:answer, %{ + question: contest_question, + submission: &1, + popular_score: 10.0, + answer: build(:programming_answer) + }) + ) + + voting_assessment = insert(:assessment, %{course: course, config: config}) + + insert( + :voting_question, + %{ + question: build(:voting_question_content, contest_number: contest_assessment.number), + assessment: voting_assessment + } + ) + + expected = + contest_answer + |> Enum.map( + &%{ + "answer" => &1.answer.code, + "student_name" => &1.submission.student.user.name, + "final_score" => &1.popular_score + } + ) + + resp = + conn + |> get(build_popular_leaderboard_url(course.id, voting_assessment.id)) + |> json_response(200) + + assert expected == resp + end + end + + describe "GET /:assessment_id/scoreLeaderboard, unauthenticated" do + test "unauthorized", %{conn: conn, courses: %{course1: course1}} do + config = insert(:assessment_config, %{course: course1}) + assessment = insert(:assessment, %{course: course1, config: config}) + + conn + |> get(build_popular_leaderboard_url(course1.id, assessment.id)) + |> response(401) + end + end + + describe "GET /:assessment_id/scoreLeaderboard, student only" do + @tag authenticate: :student + test "Forbidden", %{conn: conn} do + test_cr = conn.assigns.test_cr + course = test_cr.course + config = insert(:assessment_config, %{course: course}) + assessment = insert(:assessment, %{course: course, config: config}) + + conn + |> get(build_popular_leaderboard_url(course.id, assessment.id)) + |> response(403) + end + end + + describe "GET /:assessment_id/scoreLeaderboard" do + @tag authenticate: :staff + test "successful", %{conn: conn} do + test_cr = conn.assigns.test_cr + course = test_cr.course + + config = insert(:assessment_config, %{course: course}) + contest_assessment = insert(:assessment, %{course: course, config: config}) + contest_students = insert_list(5, :course_registration, %{course: course, role: :student}) + contest_question = insert(:programming_question, %{assessment: contest_assessment}) + + contest_submissions = + contest_students + |> Enum.map(&insert(:submission, %{assessment: contest_assessment, student: &1})) + + contest_answer = + contest_submissions + |> Enum.map( + &insert(:answer, %{ + question: contest_question, + submission: &1, + relative_score: 10.0, + answer: build(:programming_answer) + }) + ) + + voting_assessment = insert(:assessment, %{course: course, config: config}) + + insert( + :voting_question, + %{ + question: build(:voting_question_content, contest_number: contest_assessment.number), + assessment: voting_assessment + } + ) + + expected = + contest_answer + |> Enum.map( + &%{ + "answer" => &1.answer.code, + "student_name" => &1.submission.student.user.name, + "final_score" => &1.relative_score + } + ) + + resp = + conn + |> get(build_score_leaderboard_url(course.id, voting_assessment.id)) + |> json_response(200) + + assert expected == resp + end + end + describe "POST /, unauthenticated" do test "unauthorized", %{ conn: conn, @@ -757,6 +917,12 @@ defmodule CadetWeb.AdminAssessmentsControllerTest do defp build_user_assessments_url(course_id, course_reg_id), do: "/v2/courses/#{course_id}/admin/users/#{course_reg_id}/assessments" + defp build_popular_leaderboard_url(course_id, assessment_id), + do: "#{build_url(course_id, assessment_id)}/popularVoteLeaderboard" + + defp build_score_leaderboard_url(course_id, assessment_id), + do: "#{build_url(course_id, assessment_id)}/scoreLeaderboard" + defp open_at_asc_comparator(x, y), do: Timex.before?(x.open_at, y.open_at) defp get_assessment_status(course_reg = %CourseRegistration{}, assessment = %Assessment{}) do From ec1c11abbd30b5c77d97157f6954ba5e7bdbd980 Mon Sep 17 00:00:00 2001 From: Xiang Yu <156517235+DesSnowy@users.noreply.github.com> Date: Sat, 6 Apr 2024 19:18:18 +0800 Subject: [PATCH 35/35] fixed minor typo and renaming --- .../admin_controllers/admin_assessments_controller.ex | 8 ++++---- lib/cadet_web/admin_views/admin_assessments_view.ex | 8 +++----- lib/cadet_web/router.ex | 4 ++-- lib/cadet_web/views/assessments_view.ex | 8 +++----- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex index d5836115d..d9a992267 100644 --- a/lib/cadet_web/admin_controllers/admin_assessments_controller.ex +++ b/lib/cadet_web/admin_controllers/admin_assessments_controller.ex @@ -135,7 +135,7 @@ defmodule CadetWeb.AdminAssessmentsController do end end - def get_score_learderboard(conn, %{"assessmentid" => assessment_id, "course_id" => course_id}) do + def get_score_leaderboard(conn, %{"assessmentid" => assessment_id, "course_id" => course_id}) do voting_questions = Question |> where(type: :voting) @@ -154,7 +154,7 @@ defmodule CadetWeb.AdminAssessmentsController do render(conn, "leaderboard.json", leaderboard: result) end - def get_popular_learderboard(conn, %{"assessmentid" => assessment_id, "course_id" => course_id}) do + def get_popular_leaderboard(conn, %{"assessmentid" => assessment_id, "course_id" => course_id}) do voting_questions = Question |> where(type: :voting) @@ -269,7 +269,7 @@ defmodule CadetWeb.AdminAssessmentsController do response(403, "Forbidden") end - swagger_path :get_popular_learderboard do + swagger_path :get_popular_leaderboard do get("/courses/{course_id}/admin/assessments/:assessmentid/popularVoteLeaderboard") summary("get the top 10 contest entries based on popularity") @@ -285,7 +285,7 @@ defmodule CadetWeb.AdminAssessmentsController do response(403, "Forbidden") end - swagger_path :get_score_learderboard do + swagger_path :get_score_leaderboard do get("/courses/{course_id}/admin/assessments/:assessmentid/scoreLeaderboard") summary("get the top 10 contest entries based on score") diff --git a/lib/cadet_web/admin_views/admin_assessments_view.ex b/lib/cadet_web/admin_views/admin_assessments_view.ex index 848ab727c..159c5b848 100644 --- a/lib/cadet_web/admin_views/admin_assessments_view.ex +++ b/lib/cadet_web/admin_views/admin_assessments_view.ex @@ -67,14 +67,12 @@ defmodule CadetWeb.AdminAssessmentsView do end def render("leaderboard.json", %{leaderboard: leaderboard}) do - render_many(leaderboard, CadetWeb.AdminAssessmentsView, "contestEntries.json", - as: :contestEntries - ) + render_many(leaderboard, CadetWeb.AdminAssessmentsView, "contestEntry.json", as: :contestEntry) end - def render("contestEntries.json", %{contestEntries: contestEntries}) do + def render("contestEntry.json", %{contestEntry: contestEntry}) do transform_map_for_view( - contestEntries, + contestEntry, %{ student_name: :student_name, answer: & &1.answer["code"], diff --git a/lib/cadet_web/router.ex b/lib/cadet_web/router.ex index b6a4c428d..896410583 100644 --- a/lib/cadet_web/router.ex +++ b/lib/cadet_web/router.ex @@ -121,13 +121,13 @@ defmodule CadetWeb.Router do get( "/assessments/:assessmentid/popularVoteLeaderboard", AdminAssessmentsController, - :get_popular_learderboard + :get_popular_leaderboard ) get( "/assessments/:assessmentid/scoreLeaderboard", AdminAssessmentsController, - :get_score_learderboard + :get_score_leaderboard ) get("/grading", AdminGradingController, :index) diff --git a/lib/cadet_web/views/assessments_view.ex b/lib/cadet_web/views/assessments_view.ex index c5828454e..d7da3ad5d 100644 --- a/lib/cadet_web/views/assessments_view.ex +++ b/lib/cadet_web/views/assessments_view.ex @@ -68,14 +68,12 @@ defmodule CadetWeb.AssessmentsView do end def render("leaderboard.json", %{leaderboard: leaderboard}) do - render_many(leaderboard, CadetWeb.AdminAssessmentsView, "contestEntries.json", - as: :contestEntries - ) + render_many(leaderboard, CadetWeb.AdminAssessmentsView, "contestEntry.json", as: :contestEntry) end - def render("contestEntries.json", %{contestEntries: contestEntries}) do + def render("contestEntry.json", %{contestEntry: contestEntry}) do transform_map_for_view( - contestEntries, + contestEntry, %{ student_name: :student_name, answer: & &1.answer["code"],