Skip to content

Commit

Permalink
Add Team Assessments (#968)
Browse files Browse the repository at this point in the history
* Update assessment schema and add max_team_size as a required field

* Update assessment schema and add max_team_size as a required field

* Add max team size to assessment controller payload

* Update mix.exs

* Create migrations for team assessments

* Add Team Formation Models

* Fix line endings

* Fix line endings

* Establish connection with Frontend

* Generate seeds for team and team_member

* Fix line endings

* Add API call to retrieve team formation students

* Add Validation for Create Team

* Update response for Create and Delete Team API

* Add Update Teams API call

* Modify helper function

* Update seeds

* Modify TeamMember migration

* Update AlterSubmissionsTable migration

* Add API to retrieve TeamFormationOverview for students

* Add Delete Team

* Refactor SQL chunk to fetch both Team and Individual submissions

* Add retrieve Team Submission

* Add create empty submission for Team submission

* Add cascade delete answer when Team is deleted

* Update XOR validation in Submission

* Remove bulk_upload API call and doc

* Add retrieve of team submission answers

* Add unsubmit for team submission

* Add retrieval of team submissions for grading

* Add handle team submission notifications

* Remove io inspect statement

* Remove io inspect statement

* Revert seeds

* Revert seeds

* Revert seeds

* Add last_modified_at field for Answer

* Add Save-Safe

* Add documentation for models

* Minor refactoring of Teams

* Add Swagger Documentation for AdminTeamsController

* Write Function Documentation for Teams

* Add documentation and minor refactoring

* Minor changes to existing tests

* Cascade delete notification for submission

* Update error message for team creation

* Update assessments Team retrieval

* Add cascading delete for notifications

* Fix Team Delete Bug

* Fix save answer bug when no team

* Raise exception when mass team imports violates constraints

* remove test file

* Fix bug of importing duplicate students through excel

* Refactor default max team size to 1

* Check size of the team before insertion

* Fix format

* Fix unsubmit handle notifications bug

* Fix end of line issue

* Fix end of line issue

* Fix end of line issue

* Raise exception when some of the students in mass team import are not enrolled in the course

* Update docs

* Fix Submission Grading Bug

* Update docs

* Fix team deletion bug when there is a submitted assessment

* Send proper error msg to frontend when delete team fails

* Resolve merge conflict from upstream

* Merge conflict

* Retrieve Team Submission Details

* Fix failed test cases

* Add test cases

* Team Member Factory

* add team tests

* Modify Submission Factory to include Team Submission

* Write test for Team Members

* Increase COV for Notification Test

* Prepend unused variable with underscore

* Answer View Test

* Team View Test

* Update Admin Teams Controller

* Admin Teams Controller Test

* Clean up test cases

* Improve test coverage for teams

* Improve test coverage for team controller

* Improve submission test coverage

* Remove unrecheable code

* Empty Guardian Test

* Answer Controller Test

* Notification Test

* improve test coverage for assessments

* Improve test coverage for assessments

* Clean up test cases

* Update Swagger Documentation

* Modify AddMaxTeamSizeToAssessments migration file

* Remove unused variable in notification test

* Fix format

* Fix credo errors

* Fix casing (code quality)
* Fix other miscellaneous code quality issues
* Revert credo dependency version update
* Fix credo configuration

* Fix failing tests

* Remove unused variables

* Fix failing tests

* Remove IO.inspect

* Fix dialyzer CI

* Run mix format

* Fix format

* Simplify code

* Group multiple aliases together
* Remove unnecesary newlines
* Reorder/revert/reformat unnecessary changes to simplify diff

* Revert file permission changes

* Remove commented code

* Revert status code changes

* Fix tests following status code change revert

* Remove redundant conversion

* Add comment to notifications

* Add validation for max team size

* Update assessment changeset testcase

* Abstract out find teams

* Remove repeated code

* Abstraction of XOR logic

* Fix format

* Fix failing tests

* Run format

* Fix format

* Redate migrations

To ensure proper ordering

* Fix format post-merge

* Remove typo

* Revert dependency downgrades

* Revert incorrect merge conflict resolution

* Fix tests

* Update status code for not found

* Fix test for not found status code

---------

Co-authored-by: Lu Yiting <[email protected]>
Co-authored-by: LuYiting0913 <[email protected]>
Co-authored-by: Richard Dominick <[email protected]>
Co-authored-by: Chen Yanyu <[email protected]>
  • Loading branch information
5 people authored Mar 26, 2024
1 parent bba4b1a commit 5bf61d9
Show file tree
Hide file tree
Showing 51 changed files with 3,113 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .credo.exs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
{Credo.Check.Readability.SpaceAfterCommas},
{Credo.Check.Refactor.DoubleBooleanNegation},
{Credo.Check.Refactor.CondStatements},
{Credo.Check.Refactor.CyclomaticComplexity},
{Credo.Check.Refactor.CyclomaticComplexity, max_complexity: 10},
{Credo.Check.Refactor.FunctionArity},
{Credo.Check.Refactor.LongQuoteBlocks},
{Credo.Check.Refactor.MatchInCondition},
Expand Down
2 changes: 1 addition & 1 deletion .iex.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Ecto.Query
alias Cadet.Repo
alias Cadet.Accounts.User
alias Cadet.Accounts.{User, Team, TeamMember}
alias Cadet.Assessments.{Answer, Assessment, Question, Submission}
alias Cadet.Courses.Group
76 changes: 64 additions & 12 deletions lib/cadet/accounts/notifications.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Cadet.Accounts.Notifications do
import Ecto.Query

alias Cadet.Repo
alias Cadet.Accounts.{Notification, CourseRegistration, CourseRegistration}
alias Cadet.Accounts.{Notification, CourseRegistration, CourseRegistration, Team, TeamMember}
alias Cadet.Assessments.Submission
alias Ecto.Multi

Expand Down Expand Up @@ -169,17 +169,47 @@ defmodule Cadet.Accounts.Notifications do
@spec write_notification_when_graded(integer(), any()) ::
{:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
def write_notification_when_graded(submission_id, type) when type in [:graded, :autograded] do
submission =
Submission
|> Repo.get_by(id: submission_id)
case Repo.get(Submission, submission_id) do
nil ->
{:error, %Ecto.Changeset{}}

write(%{
type: type,
read: false,
role: :student,
course_reg_id: submission.student_id,
assessment_id: submission.assessment_id
})
submission ->
case submission.student_id do
nil ->
team = Repo.get(Team, submission.team_id)

query =
from(t in Team,
join: tm in TeamMember,
on: t.id == tm.team_id,
join: cr in CourseRegistration,
on: tm.student_id == cr.id,
where: t.id == ^team.id,
select: cr.id
)

team_members = Repo.all(query)

Enum.each(team_members, fn tm_id ->
write(%{
type: type,
read: false,
role: :student,
course_reg_id: tm_id,
assessment_id: submission.assessment_id
})
end)

student_id ->
write(%{
type: type,
read: false,
role: :student,
course_reg_id: student_id,
assessment_id: submission.assessment_id
})
end
end
end

@doc """
Expand Down Expand Up @@ -223,7 +253,29 @@ defmodule Cadet.Accounts.Notifications do
@spec write_notification_when_student_submits(Submission.t()) ::
{:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
def write_notification_when_student_submits(submission = %Submission{}) do
avenger_id = get_avenger_id_of(submission.student_id)
id =
case submission.student_id do
nil ->
team_id = submission.team_id

team =
Repo.one(
from(t in Team,
where: t.id == ^team_id,
preload: [:team_members]
)
)

# Does not matter if team members have different Avengers
# Just require one of them to be notified of the submission
s_id = team.team_members |> hd() |> Map.get(:student_id)
s_id

_ ->
submission.student_id
end

avenger_id = get_avenger_id_of(id)

if is_nil(avenger_id) do
{:ok, nil}
Expand Down
45 changes: 45 additions & 0 deletions lib/cadet/accounts/team.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule Cadet.Accounts.Team do
@moduledoc """
This module defines the Ecto schema and changeset for teams in the Cadet.Accounts context.
Teams represent groups of students collaborating on an assessment within a course.
"""

use Cadet, :model

alias Cadet.Accounts.TeamMember
alias Cadet.Assessments.{Assessment, Submission}

@doc """
Ecto schema definition for teams.
This schema represents a group of students collaborating on a specific assessment within a course.
Fields:
- `assessment`: A reference to the assessment associated with the team.
- `submission`: A reference to the team's submission for the assessment.
- `team_members`: A list of team members associated with the team.
"""
schema "teams" do
belongs_to(:assessment, Assessment)
has_one(:submission, Submission, on_delete: :delete_all)
has_many(:team_members, TeamMember, on_delete: :delete_all)

timestamps()
end

@required_fields ~w(assessment_id)a

@doc """
Builds an Ecto changeset for a team.
This function is used to create or update a team record based on the provided attributes.
Args:
- `team`: The existing team struct.
- `attrs`: The attributes to be cast and validated for the changeset.
Returns:
A changeset struct with cast and validated attributes.
"""
def changeset(team, attrs) do
team
|> cast(attrs, @required_fields)
|> validate_required(@required_fields)
|> foreign_key_constraint(:assessment_id)
end
end
45 changes: 45 additions & 0 deletions lib/cadet/accounts/team_member.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule Cadet.Accounts.TeamMember do
@moduledoc """
This module defines the Ecto schema and changeset for team members in the Cadet.Accounts context.
Team members represent the association between a student and a team within a course.
"""

use Ecto.Schema

import Ecto.Changeset

alias Cadet.Accounts.{CourseRegistration, Team}

@doc """
Ecto schema definition for team members.
This schema represents the relationship between a student and a team within a course.
Fields:
- `student`: A reference to the student's course registration.
- `team`: A reference to the team associated with the student.
"""
schema "team_members" do
belongs_to(:student, CourseRegistration)
belongs_to(:team, Team)

timestamps()
end

@required_fields ~w(student_id team_id)a

@doc """
Builds an Ecto changeset for a team member.
This function is used to create or update a team member record based on the provided attributes.
Args:
- `team_member`: The existing team member struct.
- `attrs`: The attributes to be cast and validated for the changeset.
Returns:
A changeset struct with cast and validated attributes.
"""
def changeset(team_member, attrs) do
team_member
|> cast(attrs, @required_fields)
|> validate_required(@required_fields)
|> foreign_key_constraint(:team_id)
|> foreign_key_constraint(:student_id)
end
end
Loading

0 comments on commit 5bf61d9

Please sign in to comment.