Skip to content

Commit 5975023

Browse files
authored
Improve seeding feature for grading related tables (#1067)
* feat: implement paginated submissions query function * feat: implement /grading route accepting pagination query parameters * fix: fix paginated submissions with group filter * Changed group_filter query to work with the new paginated query * refactor: change page to offset for pagination * feat: Update admin grading controller to take variable amount of params * refactor: Refactor code from using raw sql to using ecto query * feat: Implement filtering by mission name * feat: Implement filtering by progress for submission * refactor: show all and show only grader's groups now use ecto query * feat: Implement filter by group id * fix: Fix limit and offset default for missing query param * refactor: Rename group filter to course registration filter * feat: Implement filter by name * feat: Implement filter by assessment type * Implement filter by is_manually_graded * feat: Include total count of submissions in response * refactor: Use one join query for assessment config queries * refactor: Use one join query for user queries * refactor: Move queries for assessment and assessment config to builder * fix: Update admin_grading_controller test to account for change in response * refactor: Rename function * docs: Include a description of the function * refactor: Format code * fix: Update filter by groupID to groupName * feat: Assessment title filter using LIKE * fix: Change Notification/Email tests to use the new response * refactor: Remove old code for submissions query * feat: Implement new seed for populating DB * refactor: Make only 3 types of assessments (Mission, Path, Quest) * refactor: Rename assessments to contain 's' * fix: Fix bug where admin_cr was not being assigned the return value * refactor: Format code * refactor: Update code to be in actual seed file * Format code * fix: Fix bug where xp generated was more than max_xp * refactor: Add number of questions variable * refactor: Remove old comment * feat: Update seed to populate a staff course & group
1 parent 8208743 commit 5975023

File tree

2 files changed

+167
-110
lines changed

2 files changed

+167
-110
lines changed

lib/cadet/assessments/assessments.ex

-2
Original file line numberDiff line numberDiff line change
@@ -1338,8 +1338,6 @@ defmodule Cadet.Assessments do
13381338
else it is {:error, {:forbidden, "Forbidden."}}
13391339
"""
13401340

1341-
# We bypass Ecto here and use a raw query to generate JSON directly from
1342-
# PostgreSQL, because doing it in Elixir/Erlang is too inefficient.
13431341
@spec submissions_by_grader_for_index(CourseRegistration.t()) ::
13441342
{:ok,
13451343
%{

priv/repo/seeds.exs

+167-108
Original file line numberDiff line numberDiff line change
@@ -9,127 +9,186 @@
99
#
1010
# We recommend using the bang functions (`insert!`, `update!`
1111
# and so on) as they will fail if something goes wrong.
12+
use Cadet, [:context, :display]
13+
14+
import Cadet.Factory
1215
import Cadet.Factory
16+
import Ecto.Query
1317

1418
alias Cadet.Assessments.SubmissionStatus
1519

20+
alias Cadet.Accounts.{
21+
User,
22+
CourseRegistration
23+
}
24+
1625
# insert default source version
1726
# Cadet.Repo.insert!(%Cadet.Settings.Sublanguage{chapter: 1, variant: "default"})
1827

1928
if Cadet.Env.env() == :dev do
29+
number_of_students = 10
30+
number_of_assessments = 5
31+
number_of_questions = 3
32+
2033
# Course
21-
course1 = insert(:course)
22-
course2 = insert(:course, %{course_name: "Algorithm", course_short_name: "CS2040S"})
23-
# Users
24-
avenger1 = insert(:user, %{name: "avenger", latest_viewed_course: course1})
25-
admin1 = insert(:user, %{name: "admin", latest_viewed_course: course1})
26-
27-
studenta1admin2 = insert(:user, %{name: "student a", latest_viewed_course: course1})
28-
29-
studentb1 = insert(:user, %{latest_viewed_course: course1})
30-
studentc1 = insert(:user, %{latest_viewed_course: course1})
31-
# CourseRegistration and Group
32-
avenger1_cr = insert(:course_registration, %{user: avenger1, course: course1, role: :staff})
33-
_admin1_cr = insert(:course_registration, %{user: admin1, course: course1, role: :admin})
34-
group = insert(:group, %{leader: avenger1_cr})
35-
36-
student1a_cr =
37-
insert(:course_registration, %{
38-
user: studenta1admin2,
39-
course: course1,
40-
role: :student,
41-
group: group
42-
})
43-
44-
student1b_cr =
45-
insert(:course_registration, %{user: studentb1, course: course1, role: :student, group: group})
46-
47-
student1c_cr =
48-
insert(:course_registration, %{user: studentc1, course: course1, role: :student, group: group})
49-
50-
students = [student1a_cr, student1b_cr, student1c_cr]
51-
52-
_admin2cr =
53-
insert(:course_registration, %{user: studenta1admin2, course: course2, role: :admin})
54-
55-
# Assessments
56-
for i <- 1..5 do
57-
config = insert(:assessment_config, %{type: "Mission#{i}", order: i, course: course1})
58-
assessment = insert(:assessment, %{is_published: true, config: config, course: course1})
59-
60-
config2 = insert(:assessment_config, %{type: "Homework#{i}", order: i, course: course2})
61-
_assessment2 = insert(:assessment, %{is_published: true, config: config2, course: course2})
62-
63-
programming_questions =
64-
insert_list(3, :programming_question, %{
65-
assessment: assessment,
66-
max_xp: 1_000
67-
})
68-
69-
mcq_questions =
70-
insert_list(3, :mcq_question, %{
71-
assessment: assessment,
72-
max_xp: 500
73-
})
74-
75-
submissions =
76-
students
77-
|> Enum.take(2)
78-
|> Enum.map(
79-
&insert(:submission, %{
80-
assessment: assessment,
81-
student: &1,
82-
status: Enum.random(SubmissionStatus.__enum_map__())
83-
})
84-
)
85-
86-
# Programming Answers
87-
for submission <- submissions,
88-
question <- programming_questions do
89-
insert(:answer, %{
90-
xp: Enum.random(0..1_000),
91-
question: question,
92-
submission: submission,
93-
answer: build(:programming_answer)
94-
})
34+
admin_course =
35+
insert(:course, %{course_name: "Mock Admin Course", course_short_name: "CS0000S"})
36+
37+
# Admin, Staff and Group
38+
admin_cr =
39+
from(cr in CourseRegistration,
40+
where: cr.user_id in subquery(from(u in User, where: u.name == ^"admin", select: u.id)),
41+
select: cr
42+
)
43+
|> Repo.one()
44+
45+
admin_cr =
46+
if admin_cr == nil do
47+
admin =
48+
insert(:user, %{name: "Test Admin", username: "admin", latest_viewed_course: admin_course})
49+
50+
insert(:course_registration, %{user: admin, course: admin_course, role: :admin})
51+
else
52+
admin_cr
9553
end
9654

97-
# MCQ Answers
98-
for submission <- submissions,
99-
question <- mcq_questions do
100-
insert(:answer, %{
101-
xp: Enum.random(0..500),
102-
question: question,
103-
submission: submission,
104-
answer: build(:mcq_answer)
105-
})
55+
avenger_course =
56+
insert(:course, %{course_name: "Mock Avenger Course", course_short_name: "CS1111S"})
57+
58+
avenger_cr =
59+
from(cr in CourseRegistration,
60+
where: cr.user_id in subquery(from(u in User, where: u.name == ^"staff", select: u.id)),
61+
select: cr
62+
)
63+
|> Repo.one()
64+
65+
avenger_cr =
66+
if avenger_cr == nil do
67+
avenger =
68+
insert(:user, %{
69+
name: "Test Staff",
70+
username: "staff",
71+
latest_viewed_course: avenger_course
72+
})
73+
74+
insert(:course_registration, %{user: avenger, course: avenger_course, role: :staff})
75+
else
76+
avenger_cr
10677
end
10778

108-
# # Notifications
109-
# for submission <- submissions do
110-
# case submission.status do
111-
# :submitted ->
112-
# insert(:notification, %{
113-
# type: :submitted,
114-
# read: false,
115-
# user_id: avenger.id,
116-
# submission_id: submission.id,
117-
# assessment_id: assessment.id
118-
# })
119-
120-
# _ ->
121-
# nil
122-
# end
123-
# end
124-
125-
# for student <- students do
126-
# insert(:notification, %{
127-
# type: :new,
128-
# user_id: student.id,
129-
# assessment_id: assessment.id
130-
# })
131-
# end
132-
end
79+
admin_group = insert(:group, %{name: "MockAdminGroup", leader: admin_cr})
80+
avenger_group = insert(:group, %{name: "MockAvengerGroup", leader: avenger_cr})
81+
82+
groups_and_courses = [{admin_group, admin_course}, {avenger_group, avenger_course}]
83+
# Users
84+
85+
Enum.each(groups_and_courses, fn {group, course} ->
86+
students =
87+
for i <- 1..number_of_students do
88+
student = insert(:user, %{latest_viewed_course: course})
89+
90+
student_cr =
91+
insert(:course_registration, %{
92+
user: student,
93+
course: course,
94+
role: :student,
95+
group: group
96+
})
97+
98+
student_cr
99+
end
100+
101+
# Assessments and Submissions
102+
valid_assessment_types = [{1, "Missions"}, {2, "Paths"}, {3, "Quests"}]
103+
104+
assessment_configs =
105+
Enum.map(valid_assessment_types, fn {order, type} ->
106+
insert(:assessment_config, %{type: type, order: order, course: course})
107+
end)
108+
109+
for i <- 1..number_of_assessments do
110+
assessment =
111+
insert(:assessment, %{
112+
is_published: true,
113+
config: Enum.random(assessment_configs),
114+
course: course
115+
})
116+
117+
questions =
118+
case assessment.config.type do
119+
"Missions" ->
120+
insert_list(number_of_questions, :programming_question, %{
121+
assessment: assessment,
122+
max_xp: 1_000
123+
})
124+
125+
"Paths" ->
126+
insert_list(number_of_questions, :mcq_question, %{assessment: assessment, max_xp: 500})
127+
128+
"Quests" ->
129+
insert_list(number_of_questions, :programming_question, %{
130+
assessment: assessment,
131+
max_xp: 1_000
132+
})
133+
end
134+
135+
submissions =
136+
students
137+
|> Enum.map(
138+
&insert(:submission, %{
139+
assessment: assessment,
140+
student: &1,
141+
status: Enum.random(SubmissionStatus.__enum_map__())
142+
})
143+
)
144+
145+
for submission <- submissions,
146+
question <- questions do
147+
case question.type do
148+
:programming ->
149+
insert(:answer, %{
150+
xp: Enum.random(0..1_000),
151+
question: question,
152+
submission: submission,
153+
answer: build(:programming_answer)
154+
})
155+
156+
:mcq ->
157+
insert(:answer, %{
158+
xp: Enum.random(0..500),
159+
question: question,
160+
submission: submission,
161+
answer: build(:mcq_answer)
162+
})
163+
end
164+
end
165+
166+
# # Notifications
167+
# for submission <- submissions do
168+
# case submission.status do
169+
# :submitted ->
170+
# insert(:notification, %{
171+
# type: :submitted,
172+
# read: false,
173+
# user_id: avenger.id,
174+
# submission_id: submission.id,
175+
# assessment_id: assessment.id
176+
# })
177+
178+
# _ ->
179+
# nil
180+
# end
181+
# end
182+
183+
# for student <- students do
184+
# insert(:notification, %{
185+
# type: :new,
186+
# user_id: student.id,
187+
# assessment_id: assessment.id
188+
# })
189+
# end
190+
end
191+
end)
133192

134193
# goal_0 =
135194
# insert(:goal, %{

0 commit comments

Comments
 (0)