Class: Assignment

Inherits:
Progress show all
Includes:
Contextualization, Gamified, WithMessages
Defined in:
app/models/assignment.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Gamified

#award_experience_points!, #net_experience

Methods included from WithMessages

#build_message, #has_messages?, #pending_messages?, #receive_answer!, #send_question!

Methods included from Contextualization

#affable_expectation_results, #affable_test_results, #affable_tips, #expectation_results_visible?, #failed_expectation_results, #feedback_html, #first_test_result, #first_test_result_html, #humanized_expectation_results, #iconize, #queries_with_results, #result_html, #results_body_hidden?, #sanitized_affable_test_results, #single_visible_test_result?, #single_visual_result?, #single_visual_result_html, #test_result_html, #visible_expectation_results

Methods inherited from Progress

#_copy_to!, #delete_duplicates_in!, #dirty_parent_by_submission!, #guide_indicator?, #has_duplicates_in?, #parent, #transfer_to!

Methods inherited from ApplicationRecord

aggregate_of, all_except, defaults, #delete, #destroy!, numbered, organic_on, resource_fields, #save, #save_and_notify!, #save_and_notify_changes!, serialize_symbolized_hash_array, teaser_on, #update_and_notify!, update_or_create!, whitelist_attributes

Class Method Details

.build_for(user, exercise, organization) ⇒ Object



266
267
268
# File 'app/models/assignment.rb', line 266

def self.build_for(user, exercise, organization)
  Assignment.new submitter: user, exercise: exercise, organization: organization
end

.evaluate_manually!(teacher_evaluation) ⇒ Object



126
127
128
# File 'app/models/assignment.rb', line 126

def self.evaluate_manually!(teacher_evaluation)
  Assignment.find_by(submission_id: teacher_evaluation[:submission_id])&.evaluate_manually! teacher_evaluation
end

Instance Method Details

#attempts_leftObject



230
231
232
# File 'app/models/assignment.rb', line 230

def attempts_left
  navigable_parent.attempts_left_for(self)
end

#attempts_left?Boolean

Tells whether the submitter of this assignment can keep on sending submissions which is true for non limited or for assignments that have not reached their submissions limit

Returns:

  • (Boolean)


238
239
240
# File 'app/models/assignment.rb', line 238

def attempts_left?
  !limited? || attempts_left > 0
end

#completed_before_last_save?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'app/models/assignment.rb', line 73

def completed_before_last_save?
  status_before_last_save.completed?
end

#completion_changed?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'app/models/assignment.rb', line 69

def completion_changed?
  completed_before_last_save? != completed?
end

#content=(content) ⇒ Object



130
131
132
133
134
# File 'app/models/assignment.rb', line 130

def content=(content)
  if exercise.solvable?
    self.solution = exercise.single_choice? ? exercise.choice_index_for(content) : content
  end
end

#current_contentObject



242
243
244
# File 'app/models/assignment.rb', line 242

def current_content
  solution || default_content
end

#current_content_at(index) ⇒ Object



246
247
248
# File 'app/models/assignment.rb', line 246

def current_content_at(index)
  exercise.sibling_at(index).assignment_for(submitter).current_content
end

#current_notification_contextsObject



110
111
112
# File 'app/models/assignment.rb', line 110

def current_notification_contexts
  [Organization.current, submitter.current_immersive_context_at(exercise)].uniq
end

#default_contentObject



250
251
252
# File 'app/models/assignment.rb', line 250

def default_content
  @default_content ||= language.interpolate_references_for(self, exercise.default_content)
end

#errored!(message) ⇒ Object



178
179
180
# File 'app/models/assignment.rb', line 178

def errored!(message)
  update! result: message, submission_status: :errored
end

#evaluate_manually!(teacher_evaluation) ⇒ Object



77
78
79
# File 'app/models/assignment.rb', line 77

def evaluate_manually!(teacher_evaluation)
  update! status: teacher_evaluation[:status], manual_evaluation_comment: teacher_evaluation[:manual_evaluation]
end

#extensionObject



99
100
101
# File 'app/models/assignment.rb', line 99

def extension
  exercise.language.extension
end

#extraObject



140
141
142
# File 'app/models/assignment.rb', line 140

def extra
  exercise.extra && language.interpolate_references_for(self, exercise.extra)
end

#extra_previewObject



144
145
146
# File 'app/models/assignment.rb', line 144

def extra_preview
  Mumukit::ContentType::Markdown.highlighted_code(language.name, extra)
end

#filesObject



254
255
256
# File 'app/models/assignment.rb', line 254

def files
  exercise.files_for(current_content)
end

#increment_attempts!Object



226
227
228
# File 'app/models/assignment.rb', line 226

def increment_attempts!
  self.attempts_count += 1 if should_retry?
end

#manual_evaluation_pending!Object



158
159
160
# File 'app/models/assignment.rb', line 158

def manual_evaluation_pending!
  update! submission_status: :manual_evaluation_pending
end

#notify!Object



103
104
105
106
107
108
# File 'app/models/assignment.rb', line 103

def notify!
  unless Organization.silenced?
    update_misplaced!(current_notification_contexts.size > 1)
    Mumukit::Nuntius.notify! 'submissions', to_resource_h
  end
end

#notify_to_accessible_organizations!Object



114
115
116
117
# File 'app/models/assignment.rb', line 114

def notify_to_accessible_organizations!
  warn "Don't use notify_to_accessible_organizations!. Use notify_to_student_granted_organizations! instead"
  notify_to_student_granted_organizations!
end

#notify_to_student_granted_organizations!Object



119
120
121
122
123
124
# File 'app/models/assignment.rb', line 119

def notify_to_student_granted_organizations!
  submitter.student_granted_organizations.each do |organization|
    organization.switch!
    notify!
  end
end

#passed!Object



162
163
164
# File 'app/models/assignment.rb', line 162

def passed!
  update! submission_status: :passed
end

#persist_submission!(submission) ⇒ Object



89
90
91
92
93
94
95
96
97
# File 'app/models/assignment.rb', line 89

def persist_submission!(submission)
  transaction do
    messages.destroy_all if submission_id.present?
    update! submission_id: submission.id
    update! submitted_at: DateTime.current
    update_submissions_count!
    update_last_submission!
  end
end

#recontextualize!(new_organization = Organization.current) ⇒ Object



57
58
59
60
61
62
63
# File 'app/models/assignment.rb', line 57

def recontextualize!(new_organization = Organization.current)
  if organization != new_organization
    dirty_parent_by_submission! if organization.present? && exercise.used_in?(organization)
    self.organization = new_organization
    self.parent_id = nil
  end
end

#run_tests!(params) ⇒ Object



187
188
189
# File 'app/models/assignment.rb', line 187

def run_tests!(params)
  exercise.run_tests! params.merge(extra: extra, test: test, settings: settings)
end

#run_update!Object



148
149
150
151
152
153
154
155
156
# File 'app/models/assignment.rb', line 148

def run_update!
  running!
  begin
    update! yield
  rescue => e
    errored! e.message
    raise e
  end
end

#running!Object



170
171
172
173
174
175
176
# File 'app/models/assignment.rb', line 170

def running!
  update! submission_status: :running,
          result: nil,
          test_results: nil,
          expectation_results: [],
          manual_evaluation_comment: nil
end

#set_current_organization!Object

TODO: Momentary as some assignments may not have an associated organization



53
54
55
# File 'app/models/assignment.rb', line 53

def set_current_organization!
  self.organization = Organization.current
end

#set_default_top_submission_statusObject



65
66
67
# File 'app/models/assignment.rb', line 65

def set_default_top_submission_status
  self.top_submission_status ||= 0
end

#skipped!Object



166
167
168
# File 'app/models/assignment.rb', line 166

def skipped!
  update! submission_status: :skipped
end

#testObject



136
137
138
# File 'app/models/assignment.rb', line 136

def test
  exercise.test && language.interpolate_references_for(self, exercise.test)
end

#tipsObject



222
223
224
# File 'app/models/assignment.rb', line 222

def tips
  @tips ||= exercise.assist_with(self)
end

#to_resource_hObject



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'app/models/assignment.rb', line 191

def to_resource_h
  excluded_fields = i(created_at exercise_id id organization_id parent_id solution submission_id
                       submission_status  submitter_id top_submission_status updated_at misplaced)

  as_json(except: excluded_fields,
            include: {
              guide: {
                only: [:slug, :name],
                include: {
                  lesson: {only: [:number]},
                  language: {only: [:name]}},
              },
              exercise: {only: [:name, :number]},
              submitter: {only: [:email, :social_id, :uid], methods: [:name, :profile_picture]}}).
    deep_merge(
      'organization' => Organization.current.name,
      'sid' => submission_id,
      'created_at' =>  || updated_at,
      'content' => solution,
      'status' => submission_status,
      'exercise' => {
        'eid' => exercise.bibliotheca_id
      },
      'guide' => {'parent' => {
        'type' => navigable_parent.class.to_s,
        'name' => navigable_parent.name,
        'position' => navigable_parent.try(:number),
        'chapter' => guide.chapter.as_json(only: [:id], methods: [:name])
      }})
end

#update_misplaced!(value) ⇒ Object



262
263
264
# File 'app/models/assignment.rb', line 262

def update_misplaced!(value)
  update! misplaced: value if value != misplaced?
end

#update_top_submission!Object



258
259
260
# File 'app/models/assignment.rb', line 258

def update_top_submission!
  self.top_submission_status = submission_status unless submission_status.improved_by?(top_submission_status)
end

#visible_statusObject



81
82
83
84
85
86
87
# File 'app/models/assignment.rb', line 81

def visible_status
  if results_hidden? && !pending?
    :manual_evaluation_pending.to_submission_status
  else
    super
  end
end