Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sorting for grading #1107

Merged
merged 29 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f6efd14
handled backend sorting
thortol Apr 8, 2024
7ba8681
fixed sorting by inserted_at
thortol Apr 8, 2024
5e9d582
removed unused code
thortol Apr 8, 2024
d258d80
changed inner_join to left_join
thortol Apr 8, 2024
91c9713
added new tests
thortol Apr 8, 2024
702092b
fixed formatting
thortol Apr 8, 2024
fb70883
reformatted code
thortol Apr 8, 2024
6dc40de
added more test
thortol Apr 8, 2024
c32bc42
added more tests
thortol Apr 9, 2024
b311ee5
Merge branch 'master' into add-sorting-for-grading
RichDom2185 Apr 14, 2024
eefb1a4
updated grading sorter for progressStatus
thortol Apr 14, 2024
7bb5ad6
Merge branch 'master' into add-sorting-for-grading
InfinityTwo Apr 15, 2024
82e7833
fixed test
thortol Apr 15, 2024
853aa2a
fixed sorting by group bug and made sorting work regardless of upper …
thortol Apr 15, 2024
fc87f68
fixed formatting
thortol Apr 15, 2024
06154b6
fixed bug where xp was not sorted properly
thortol Apr 16, 2024
0412aee
fixed sorting by grading bug
thortol Apr 16, 2024
c624803
fixed test
thortol Apr 16, 2024
eb61277
Merge branch 'master' into add-sorting-for-grading
RichDom2185 May 5, 2024
8feda64
Merge branch 'master' into add-sorting-for-grading
thortol May 9, 2024
021ef57
Merge branch 'master' into add-sorting-for-grading
lhw-1 May 15, 2024
2506570
Merge branch 'master' into add-sorting-for-grading
RichDom2185 May 19, 2024
b1c1061
Merge branch 'master' into add-sorting-for-grading
thortol May 21, 2024
50682b6
Merge branch 'master' into add-sorting-for-grading
lhw-1 Aug 6, 2024
4b268fb
Merge branch 'master' into add-sorting-for-grading
RichDom2185 Aug 11, 2024
8c884bf
Merge branch 'master' into add-sorting-for-grading
RichDom2185 Aug 19, 2024
415cdc0
Prefer piping
RichDom2185 Aug 19, 2024
a4e4858
Reduce nesting
RichDom2185 Aug 19, 2024
842cef1
Revert "Prefer piping"
RichDom2185 Aug 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 130 additions & 3 deletions lib/cadet/assessments/assessments.ex
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@
raw_answer,
force_submit
) do
with {:ok, team} <- find_team(question.assessment.id, cr_id),

Check warning on line 919 in lib/cadet/assessments/assessments.ex

View workflow job for this annotation

GitHub Actions / Run CI

variable "team" is unused (if the variable is not meant to be used, prefix it with an underscore)
{:ok, submission} <- find_or_create_submission(cr, question.assessment),
{:status, true} <- {:status, force_submit or submission.status != :submitted},
{:ok, _answer} <- insert_or_update_answer(submission, question, raw_answer, cr_id) do
Expand Down Expand Up @@ -1906,7 +1906,9 @@
"group" => "false",
"isFullyGraded" => "false",
"pageSize" => "10",
"offset" => "0"
"offset" => "0",
"sortBy" => "",
"sortDirection" => ""
}
) do
submission_answers_query =
Expand All @@ -1927,7 +1929,9 @@
on: q.assessment_id == a.id,
select: %{
assessment_id: q.assessment_id,
question_count: count(q.id)
question_count: count(q.id),
title: max(a.title),
config_id: max(a.config_id)
}
)

Expand All @@ -1939,12 +1943,23 @@
left_join: asst in subquery(question_answers_query),
on: asst.assessment_id == s.assessment_id,
as: :asst,
left_join: user in User,
on: user.id == s.student_id,
as: :user,
left_join: cr in CourseRegistration,
on: user.id == cr.user_id,
as: :cr,
left_join: group in Group,
on: cr.group_id == group.id,
as: :group,
inner_join: config in AssessmentConfig,
on: asst.config_id == config.id,
as: :config,
where: ^build_user_filter(params),
where: s.assessment_id in subquery(build_assessment_filter(params, course_id)),
where: s.assessment_id in subquery(build_assessment_config_filter(params)),
where: ^build_submission_filter(params),
where: ^build_course_registration_filter(params, grader),
order_by: [desc: s.inserted_at],
limit: ^elem(Integer.parse(Map.get(params, "pageSize", "10")), 0),
offset: ^elem(Integer.parse(Map.get(params, "offset", "0")), 0),
select: %{
Expand All @@ -1964,6 +1979,10 @@
}
)

query =
sort_submission(query, Map.get(params, "sortBy", ""), Map.get(params, "sortDirection", ""))

query = from([s, ans, asst, user, cr, group] in query, order_by: [desc: s.inserted_at])
submissions = Repo.all(query)

count_query =
Expand All @@ -1987,6 +2006,114 @@
{:ok, %{count: count, data: generate_grading_summary_view_model(submissions, course_id)}}
end

# Given a query from submissions_by_grader_for_index,
# sorts it by the relevant field and direction
# sort_by is a string of either "", "assessmentName", "assessmentType", "studentName",
# "studentUsername", "groupName", "progressStatus", "xp"
# sort_direction is a string of either "", "sort-asc", "sort-desc"
defp sort_submission(query, sort_by, sort_direction) do
cond do
sort_direction == "sort-asc" ->
sort_submission_asc(query, sort_by)

sort_direction == "sort-desc" ->
sort_submission_desc(query, sort_by)

true ->
query
end
end

defp sort_submission_asc(query, sort_by) do
cond do
sort_by == "assessmentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", asst.title)
)

sort_by == "assessmentType" ->
from([s, ans, asst, user, cr, group, config] in query, order_by: asst.config_id)

sort_by == "studentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", user.name)
)

sort_by == "studentUsername" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", user.username)
)

sort_by == "groupName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", group.name)
)

sort_by == "progressStatus" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [
asc: config.is_manually_graded,
asc: s.status,
asc: ans.graded_count - asst.question_count,
asc: s.is_grading_published
]
)

sort_by == "xp" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: ans.xp + ans.xp_adjustment
)

true ->
query
end
end

defp sort_submission_desc(query, sort_by) do
cond do
sort_by == "assessmentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", asst.title)]
)

sort_by == "assessmentType" ->
from([s, ans, asst, user, cr, group, config] in query, order_by: [desc: asst.config_id])

sort_by == "studentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", user.name)]
)

sort_by == "studentUsername" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", user.username)]
)

sort_by == "groupName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", group.name)]
)

sort_by == "progressStatus" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [
desc: config.is_manually_graded,
desc: s.status,
desc: ans.graded_count - asst.question_count,
desc: s.is_grading_published
]
)

sort_by == "xp" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: ans.xp + ans.xp_adjustment]
)

true ->
query
end
end

defp build_assessment_filter(params, course_id) do
assessments_filters =
Enum.reduce(params, dynamic(true), fn
Expand Down Expand Up @@ -2554,7 +2681,7 @@

def has_last_modified_answer?(
question = %Question{},
cr = %CourseRegistration{id: cr_id},

Check warning on line 2684 in lib/cadet/assessments/assessments.ex

View workflow job for this annotation

GitHub Actions / Run CI

variable "cr_id" is unused (if the variable is not meant to be used, prefix it with an underscore)
last_modified_at,
force_submit
) do
Expand Down
182 changes: 182 additions & 0 deletions test/cadet/assessments/assessments_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2815,6 +2815,188 @@ defmodule Cadet.AssessmentsTest do
assert Enum.find(assessments_from_res, fn a -> a.id == s.assessment_id end) != nil
end)
end

test "sorting by assessment title ascending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentName",
"sortDirection" => "sort-asc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_title =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_title,
fn x, y ->
assert x.title >= y.title
y
end
)
end

test "sorting by assessment title descending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentName",
"sortDirection" => "sort-desc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_title =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_title,
fn x, y ->
assert x.title <= y.title
y
end
)
end

test "sorting by assessment type ascending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentType",
"sortDirection" => "sort-asc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_assessments_type =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_assessments_type,
fn x, y ->
assert x.config_id >= y.config_id
y
end
)
end

test "sorting by assessment type descending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentType",
"sortDirection" => "sort-desc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_assessments_type =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_assessments_type,
fn x, y ->
assert x.config_id <= y.config_id
y
end
)
end

test "sorting by xp ascending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "xp",
"sortDirection" => "sort-asc"
})

submissions_from_res = res[:data][:submissions]

Enum.reduce(
submissions_from_res,
fn x, y ->
assert x.xp >= y.xp
y
end
)
end

test "sorting by xp descending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "xp",
"sortDirection" => "sort-desc"
})

submissions_from_res = res[:data][:submissions]

Enum.reduce(
submissions_from_res,
fn x, y ->
assert x.xp <= y.xp
y
end
)
end
end

describe "is_fully_autograded? function" do
Expand Down
Loading