Skip to content

Improve seeding feature for grading related tables #1067

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

Merged
merged 43 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
29246b0
feat: implement paginated submissions query function
GabrielCWT Jan 28, 2024
a60e39f
feat: implement /grading route accepting pagination query parameters
GabrielCWT Jan 28, 2024
29057e7
fix: fix paginated submissions with group filter
GabrielCWT Jan 30, 2024
c662fbc
refactor: change page to offset for pagination
GabrielCWT Jan 31, 2024
6adbf8c
feat: Update admin grading controller to take variable amount of params
GabrielCWT Feb 9, 2024
3b621af
refactor: Refactor code from using raw sql to using ecto query
GabrielCWT Feb 11, 2024
fc55c55
feat: Implement filtering by mission name
GabrielCWT Feb 11, 2024
610ffbf
feat: Implement filtering by progress for submission
GabrielCWT Feb 11, 2024
7de9882
refactor: show all and show only grader's groups now use ecto query
GabrielCWT Feb 11, 2024
c9ba93e
feat: Implement filter by group id
GabrielCWT Feb 11, 2024
451cea8
fix: Fix limit and offset default for missing query param
GabrielCWT Feb 11, 2024
940e282
refactor: Rename group filter to course registration filter
GabrielCWT Feb 11, 2024
2f5c910
feat: Implement filter by name
GabrielCWT Feb 11, 2024
ca768aa
feat: Implement filter by assessment type
GabrielCWT Feb 11, 2024
9ff4108
Implement filter by is_manually_graded
GabrielCWT Feb 12, 2024
8afcc22
feat: Include total count of submissions in response
GabrielCWT Feb 13, 2024
c7dc2ca
refactor: Use one join query for assessment config queries
GabrielCWT Feb 14, 2024
2e9b1ea
refactor: Use one join query for user queries
GabrielCWT Feb 14, 2024
70b7f59
refactor: Move queries for assessment and assessment config to builder
GabrielCWT Feb 15, 2024
f5f651d
fix: Update admin_grading_controller test to account for change in re…
GabrielCWT Feb 15, 2024
37c7a4e
refactor: Rename function
GabrielCWT Feb 15, 2024
b7ea15b
docs: Include a description of the function
GabrielCWT Feb 15, 2024
0fd3e65
refactor: Format code
GabrielCWT Feb 15, 2024
bac36b4
Merge branch 'master' into gabriel/pagination
GabrielCWT Feb 15, 2024
00e48f2
fix: Update filter by groupID to groupName
GabrielCWT Feb 17, 2024
80e2f5e
feat: Assessment title filter using LIKE
GabrielCWT Feb 18, 2024
b1a249c
fix: Change Notification/Email tests to use the new response
GabrielCWT Feb 18, 2024
82b2a10
refactor: Remove old code for submissions query
GabrielCWT Feb 18, 2024
22b05f9
feat: Implement new seed for populating DB
GabrielCWT Feb 19, 2024
013893e
refactor: Make only 3 types of assessments (Mission, Path, Quest)
GabrielCWT Feb 19, 2024
5dede85
refactor: Rename assessments to contain 's'
GabrielCWT Feb 19, 2024
8c52005
fix: Fix bug where admin_cr was not being assigned the return value
GabrielCWT Feb 19, 2024
d3f69ba
refactor: Format code
GabrielCWT Feb 19, 2024
6eb9c52
refactor: Update code to be in actual seed file
GabrielCWT Feb 20, 2024
7b016b6
Format code
GabrielCWT Feb 21, 2024
bd5b93c
fix: Fix bug where xp generated was more than max_xp
GabrielCWT Feb 21, 2024
edfc332
refactor: Add number of questions variable
GabrielCWT Feb 21, 2024
ffe70f9
Merge branch 'master' into feat/seeding
GabrielCWT Feb 24, 2024
715cc48
refactor: Remove old comment
GabrielCWT Feb 24, 2024
697b8de
feat: Update seed to populate a staff course & group
GabrielCWT Feb 24, 2024
6fc2a65
Merge branch 'master' into feat/seeding
RichDom2185 Mar 4, 2024
5046bd7
Merge branch 'master' into feat/seeding
RichDom2185 Mar 13, 2024
ca24523
Merge branch 'master' into feat/seeding
RichDom2185 Mar 21, 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
2 changes: 0 additions & 2 deletions lib/cadet/assessments/assessments.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1338,8 +1338,6 @@ defmodule Cadet.Assessments do
else it is {:error, {:forbidden, "Forbidden."}}
"""

# We bypass Ecto here and use a raw query to generate JSON directly from
# PostgreSQL, because doing it in Elixir/Erlang is too inefficient.
@spec submissions_by_grader_for_index(CourseRegistration.t()) ::
{:ok,
%{
Expand Down
275 changes: 167 additions & 108 deletions priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,127 +9,186 @@
#
# We recommend using the bang functions (`insert!`, `update!`
# and so on) as they will fail if something goes wrong.
use Cadet, [:context, :display]

import Cadet.Factory
import Cadet.Factory
import Ecto.Query

alias Cadet.Assessments.SubmissionStatus

alias Cadet.Accounts.{
User,
CourseRegistration
}

# insert default source version
# Cadet.Repo.insert!(%Cadet.Settings.Sublanguage{chapter: 1, variant: "default"})

if Cadet.Env.env() == :dev do
number_of_students = 10
number_of_assessments = 5
number_of_questions = 3

# Course
course1 = insert(:course)
course2 = insert(:course, %{course_name: "Algorithm", course_short_name: "CS2040S"})
# Users
avenger1 = insert(:user, %{name: "avenger", latest_viewed_course: course1})
admin1 = insert(:user, %{name: "admin", latest_viewed_course: course1})

studenta1admin2 = insert(:user, %{name: "student a", latest_viewed_course: course1})

studentb1 = insert(:user, %{latest_viewed_course: course1})
studentc1 = insert(:user, %{latest_viewed_course: course1})
# CourseRegistration and Group
avenger1_cr = insert(:course_registration, %{user: avenger1, course: course1, role: :staff})
_admin1_cr = insert(:course_registration, %{user: admin1, course: course1, role: :admin})
group = insert(:group, %{leader: avenger1_cr})

student1a_cr =
insert(:course_registration, %{
user: studenta1admin2,
course: course1,
role: :student,
group: group
})

student1b_cr =
insert(:course_registration, %{user: studentb1, course: course1, role: :student, group: group})

student1c_cr =
insert(:course_registration, %{user: studentc1, course: course1, role: :student, group: group})

students = [student1a_cr, student1b_cr, student1c_cr]

_admin2cr =
insert(:course_registration, %{user: studenta1admin2, course: course2, role: :admin})

# Assessments
for i <- 1..5 do
config = insert(:assessment_config, %{type: "Mission#{i}", order: i, course: course1})
assessment = insert(:assessment, %{is_published: true, config: config, course: course1})

config2 = insert(:assessment_config, %{type: "Homework#{i}", order: i, course: course2})
_assessment2 = insert(:assessment, %{is_published: true, config: config2, course: course2})

programming_questions =
insert_list(3, :programming_question, %{
assessment: assessment,
max_xp: 1_000
})

mcq_questions =
insert_list(3, :mcq_question, %{
assessment: assessment,
max_xp: 500
})

submissions =
students
|> Enum.take(2)
|> Enum.map(
&insert(:submission, %{
assessment: assessment,
student: &1,
status: Enum.random(SubmissionStatus.__enum_map__())
})
)

# Programming Answers
for submission <- submissions,
question <- programming_questions do
insert(:answer, %{
xp: Enum.random(0..1_000),
question: question,
submission: submission,
answer: build(:programming_answer)
})
admin_course =
insert(:course, %{course_name: "Mock Admin Course", course_short_name: "CS0000S"})

# Admin, Staff and Group
admin_cr =
from(cr in CourseRegistration,
where: cr.user_id in subquery(from(u in User, where: u.name == ^"admin", select: u.id)),
select: cr
)
|> Repo.one()

admin_cr =
if admin_cr == nil do
admin =
insert(:user, %{name: "Test Admin", username: "admin", latest_viewed_course: admin_course})

insert(:course_registration, %{user: admin, course: admin_course, role: :admin})
else
admin_cr
end

# MCQ Answers
for submission <- submissions,
question <- mcq_questions do
insert(:answer, %{
xp: Enum.random(0..500),
question: question,
submission: submission,
answer: build(:mcq_answer)
})
avenger_course =
insert(:course, %{course_name: "Mock Avenger Course", course_short_name: "CS1111S"})

avenger_cr =
from(cr in CourseRegistration,
where: cr.user_id in subquery(from(u in User, where: u.name == ^"staff", select: u.id)),
select: cr
)
|> Repo.one()

avenger_cr =
if avenger_cr == nil do
avenger =
insert(:user, %{
name: "Test Staff",
username: "staff",
latest_viewed_course: avenger_course
})

insert(:course_registration, %{user: avenger, course: avenger_course, role: :staff})
else
avenger_cr
end

# # Notifications
# for submission <- submissions do
# case submission.status do
# :submitted ->
# insert(:notification, %{
# type: :submitted,
# read: false,
# user_id: avenger.id,
# submission_id: submission.id,
# assessment_id: assessment.id
# })

# _ ->
# nil
# end
# end

# for student <- students do
# insert(:notification, %{
# type: :new,
# user_id: student.id,
# assessment_id: assessment.id
# })
# end
end
admin_group = insert(:group, %{name: "MockAdminGroup", leader: admin_cr})
avenger_group = insert(:group, %{name: "MockAvengerGroup", leader: avenger_cr})

groups_and_courses = [{admin_group, admin_course}, {avenger_group, avenger_course}]
# Users

Enum.each(groups_and_courses, fn {group, course} ->
students =
for i <- 1..number_of_students do
student = insert(:user, %{latest_viewed_course: course})

student_cr =
insert(:course_registration, %{
user: student,
course: course,
role: :student,
group: group
})

student_cr
end

# Assessments and Submissions
valid_assessment_types = [{1, "Missions"}, {2, "Paths"}, {3, "Quests"}]

assessment_configs =
Enum.map(valid_assessment_types, fn {order, type} ->
insert(:assessment_config, %{type: type, order: order, course: course})
end)

for i <- 1..number_of_assessments do
assessment =
insert(:assessment, %{
is_published: true,
config: Enum.random(assessment_configs),
course: course
})

questions =
case assessment.config.type do
"Missions" ->
insert_list(number_of_questions, :programming_question, %{
assessment: assessment,
max_xp: 1_000
})

"Paths" ->
insert_list(number_of_questions, :mcq_question, %{assessment: assessment, max_xp: 500})

"Quests" ->
insert_list(number_of_questions, :programming_question, %{
assessment: assessment,
max_xp: 1_000
})
end

submissions =
students
|> Enum.map(
&insert(:submission, %{
assessment: assessment,
student: &1,
status: Enum.random(SubmissionStatus.__enum_map__())
})
)

for submission <- submissions,
question <- questions do
case question.type do
:programming ->
insert(:answer, %{
xp: Enum.random(0..1_000),
question: question,
submission: submission,
answer: build(:programming_answer)
})

:mcq ->
insert(:answer, %{
xp: Enum.random(0..500),
question: question,
submission: submission,
answer: build(:mcq_answer)
})
end
end

# # Notifications
# for submission <- submissions do
# case submission.status do
# :submitted ->
# insert(:notification, %{
# type: :submitted,
# read: false,
# user_id: avenger.id,
# submission_id: submission.id,
# assessment_id: assessment.id
# })

# _ ->
# nil
# end
# end

# for student <- students do
# insert(:notification, %{
# type: :new,
# user_id: student.id,
# assessment_id: assessment.id
# })
# end
end
end)

# goal_0 =
# insert(:goal, %{
Expand Down