@@ -10,9 +10,10 @@ defmodule Cadet.Assessments do
1010 alias Timex.Duration
1111
1212 alias Cadet.Accounts.User
13- alias Cadet.Assessments . { Answer , Assessment , Question , Submission }
13+ alias Cadet.Assessments . { Answer , Assessment , Query , Question , Submission }
1414
1515 @ submit_answer_roles ~w( student) a
16+ @ grading_roles ~w( staff) a
1617
1718 def all_assessments ( ) do
1819 Repo . all ( Assessment )
@@ -89,7 +90,7 @@ defmodule Cadet.Assessments do
8990 end
9091
9192 def create_question_for_assessment ( params , assessment_id )
92- when is_binary ( assessment_id ) or is_number ( assessment_id ) do
93+ when is_ecto_id ( assessment_id ) do
9394 assessment = get_assessment ( assessment_id )
9495 create_question_for_assessment ( params , assessment )
9596 end
@@ -151,6 +152,95 @@ defmodule Cadet.Assessments do
151152 end
152153 end
153154
155+ @ spec all_submissions_by_grader ( User . t ( ) ) ::
156+ { :ok , [ Submission . t ( ) ] } | { :error , { :unauthorized , String . t ( ) } }
157+ def all_submissions_by_grader ( grader = % User { role: role } ) do
158+ if role in @ grading_roles do
159+ students = Cadet.Accounts.Query . students_of ( grader )
160+
161+ submissions =
162+ Submission
163+ |> join ( :inner , [ s ] , x in subquery ( Query . submissions_xp ( ) ) , s . id == x . submission_id )
164+ |> join ( :inner , [ s ] , st in subquery ( students ) , s . student_id == st . id )
165+ |> join (
166+ :inner ,
167+ [ s ] ,
168+ a in subquery ( Query . all_assessments_with_max_xp ( ) ) ,
169+ s . assessment_id == a . id
170+ )
171+ |> select ( [ s , x , st , a ] , % Submission { s | xp: x . xp , student: st , assessment: a } )
172+ |> Repo . all ( )
173+
174+ { :ok , submissions }
175+ else
176+ { :error , { :unauthorized , "User is not permitted to grade." } }
177+ end
178+ end
179+
180+ @ spec get_answers_in_submission ( integer ( ) | String . t ( ) , User . t ( ) ) ::
181+ { :ok , [ Answer . t ( ) ] } | { :error , { :unauthorized , String . t ( ) } }
182+ def get_answers_in_submission ( id , grader = % User { role: role } ) when is_ecto_id ( id ) do
183+ if role in @ grading_roles do
184+ students = Cadet.Accounts.Query . students_of ( grader )
185+
186+ answers =
187+ Answer
188+ |> where ( submission_id: ^ id )
189+ |> join ( :inner , [ a ] , s in Submission , a . submission_id == s . id )
190+ |> join ( :inner , [ a , s ] , t in subquery ( students ) , t . id == s . student_id )
191+ |> join ( :inner , [ a ] , q in assoc ( a , :question ) )
192+ |> preload ( [ a , ... , q ] , question: q )
193+ |> Repo . all ( )
194+
195+ { :ok , answers }
196+ else
197+ { :error , { :unauthorized , "User is not permitted to grade." } }
198+ end
199+ end
200+
201+ @ spec update_grading_info (
202+ % { submission_id: integer ( ) | String . t ( ) , question_id: integer ( ) | String . t ( ) } ,
203+ % { } ,
204+ User . t ( )
205+ ) ::
206+ { :ok , nil }
207+ | { :error , { :unauthorized | :bad_request | :internal_server_error , String . t ( ) } }
208+ def update_grading_info (
209+ % { submission_id: submission_id , question_id: question_id } ,
210+ attrs ,
211+ grader = % User { role: role }
212+ )
213+ when is_ecto_id ( submission_id ) and is_ecto_id ( question_id ) do
214+ if role in @ grading_roles do
215+ students = Cadet.Accounts.Query . students_of ( grader )
216+
217+ answer =
218+ Answer
219+ |> where ( [ a ] , a . submission_id == ^ submission_id and a . question_id == ^ question_id )
220+ |> join ( :inner , [ a ] , s in assoc ( a , :submission ) )
221+ |> join ( :inner , [ a , s ] , t in subquery ( students ) , t . id == s . student_id )
222+ |> Repo . one ( )
223+
224+ with { :answer_found? , true } <- { :answer_found? , is_map ( answer ) } ,
225+ { :valid , changeset = % Ecto.Changeset { valid?: true } } <-
226+ { :valid , Answer . grading_changeset ( answer , attrs ) } ,
227+ { :ok , _ } <- Repo . update ( changeset ) do
228+ { :ok , nil }
229+ else
230+ { :answer_found? , false } ->
231+ { :error , { :bad_request , "Answer not found or user not permitted to grade." } }
232+
233+ { :valid , changeset } ->
234+ { :error , { :bad_request , full_error_messages ( changeset . errors ) } }
235+
236+ { :error , _ } ->
237+ { :error , { :internal_server_error , "Please try again later." } }
238+ end
239+ else
240+ { :error , { :unauthorized , "User is not permitted to grade." } }
241+ end
242+ end
243+
154244 defp find_submission ( user = % User { } , assessment = % Assessment { } ) do
155245 submission =
156246 Submission
@@ -211,25 +301,4 @@ defmodule Cadet.Assessments do
211301 % { code: raw_answer }
212302 end
213303 end
214-
215- # TODO: Decide what to do with these methods
216- # def create_multiple_choice_question(json_attr) when is_binary(json_attr) do
217- # %MCQQuestion{}
218- # |> MCQQuestion.changeset(%{raw_mcqquestion: json_attr})
219- # end
220-
221- # def create_multiple_choice_question(attr = %{}) do
222- # %MCQQuestion{}
223- # |> MCQQuestion.changeset(attr)
224- # end
225-
226- # def create_programming_question(json_attr) when is_binary(json_attr) do
227- # %ProgrammingQuestion{}
228- # |> ProgrammingQuestion.changeset(%{raw_programmingquestion: json_attr})
229- # end
230-
231- # def create_programming_question(attr = %{}) do
232- # %ProgrammingQuestion{}
233- # |> ProgrammingQuestion.changeset(attr)
234- # end
235304end
0 commit comments