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?, #single_visible_test_result?, #single_visual_result?, #single_visual_result_html, #test_result_html, #visible_expectation_results

Methods inherited from Progress

#dirty_parent_by_submission!, #parent

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, #update_and_notify!, update_or_create!, whitelist_attributes

Class Method Details

.evaluate_manually!(teacher_evaluation) ⇒ Object



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

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



209
210
211
# File 'app/models/assignment.rb', line 209

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)


217
218
219
# File 'app/models/assignment.rb', line 217

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

#completed_before_last_save?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'app/models/assignment.rb', line 63

def completed_before_last_save?
  status_before_last_save.completed?
end

#completion_changed?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'app/models/assignment.rb', line 59

def completion_changed?
  completed_before_last_save? != completed?
end

#content=(content) ⇒ Object



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

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

#current_contentObject



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

def current_content
  solution || default_content
end

#current_content_at(index) ⇒ Object



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

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

#default_contentObject



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

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

#errored!(message) ⇒ Object



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

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

#evaluate_manually!(teacher_evaluation) ⇒ Object



67
68
69
# File 'app/models/assignment.rb', line 67

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

#extensionObject



89
90
91
# File 'app/models/assignment.rb', line 89

def extension
  exercise.language.extension
end

#extraObject



123
124
125
# File 'app/models/assignment.rb', line 123

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

#extra_previewObject



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

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

#filesObject



233
234
235
# File 'app/models/assignment.rb', line 233

def files
  exercise.files_for(current_content)
end

#increment_attempts!Object



205
206
207
# File 'app/models/assignment.rb', line 205

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

#notify!Object



93
94
95
# File 'app/models/assignment.rb', line 93

def notify!
  Mumukit::Nuntius.notify! 'submissions', to_resource_h unless Organization.silenced?
end

#notify_to_accessible_organizations!Object



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

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



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

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

#passed!Object



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

def passed!
  update! submission_status: :passed
end

#persist_submission!(submission) ⇒ Object



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

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

#run_tests!(params) ⇒ Object



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

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

#run_update!Object



131
132
133
134
135
136
137
138
139
# File 'app/models/assignment.rb', line 131

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

#running!Object



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

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



51
52
53
# File 'app/models/assignment.rb', line 51

def set_current_organization!
  self.organization = Organization.current
end

#set_default_top_submission_statusObject



55
56
57
# File 'app/models/assignment.rb', line 55

def set_default_top_submission_status
  self.top_submission_status ||= 0
end

#skipped!Object



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

def skipped!
  update! submission_status: :skipped
end

#testObject



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

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

#tipsObject



201
202
203
# File 'app/models/assignment.rb', line 201

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

#to_resource_hObject



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'app/models/assignment.rb', line 170

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

  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_top_submission!Object



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

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

#visible_statusObject



71
72
73
74
75
76
77
# File 'app/models/assignment.rb', line 71

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