Class: Exercise

Direct Known Subclasses

Challenge, Reading

Instance Method Summary collapse

Methods included from SiblingsNavigation

#navigable_name, #next_for, #restart

Methods included from ParentNavigation

#leave, #navigable_name, #navigable_parent, #navigation_end?

Methods included from Submittable

#find_assignment_and_submit!, #submit!

Methods included from Questionable

#submit_question!

Methods included from WithAssignments

#assignment_for, #find_assignment_for, #has_messages_for?, #messages_for, #status_for

Methods included from FriendlyName

#friendly_name, #to_param

Methods included from Assistable

#assist_with, #assistant

Methods included from WithRandomizations

#randomizer, #seed, #seed_with!

Methods included from WithDiscussions

#discuss!, #try_solve_discussions

Methods included from WithDescription

#description_teaser

Methods inherited from ApplicationRecord

aggregate_of, all_except, defaults, name_model_as, numbered, #save, #save_and_notify!, #save_and_notify_changes!, #update_and_notify!, update_or_create!, whitelist_attributes

Instance Method Details

#console?Boolean

Returns:

  • (Boolean)


27
28
29
# File 'app/models/exercise.rb', line 27

def console?
  queriable?
end

#custom?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'app/models/exercise.rb', line 138

def custom?
  false
end

#default_contentObject



146
147
148
# File 'app/models/exercise.rb', line 146

def default_content
  self[:default_content] || ''
end

#description_contextObject



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

def description_context
  Mumukit::ContentType::Markdown.to_html splitted_description.first
end

#description_taskObject



134
135
136
# File 'app/models/exercise.rb', line 134

def description_task
  Mumukit::ContentType::Markdown.to_html splitted_description.drop(1).join("\n")
end

#ensure_type!(type) ⇒ Object



105
106
107
108
109
110
111
# File 'app/models/exercise.rb', line 105

def ensure_type!(type)
  if self.type != type
    reclassify! type
  else
    self
  end
end

#friendlyObject



68
69
70
# File 'app/models/exercise.rb', line 68

def friendly
  defaulting_name { "#{navigable_parent.friendly} - #{name}" }
end

#guide_done_for?(user) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
# File 'app/models/exercise.rb', line 43

def guide_done_for?(user)
  guide.done_for?(user)
end

#import_from_json!(number, json) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'app/models/exercise.rb', line 80

def import_from_json!(number, json)
  self.language = Language.for_name(json['language']) || guide.language
  self.locale = guide.locale

  reset!

  attrs = whitelist_attributes(json, except: %w(type id))
  attrs['choices'] = json['choices'].map { |choice| choice['value'] } if json['choices'].present?
  attrs['bibliotheca_id'] = json['id']
  attrs['number'] = number
  attrs = attrs.except('expectations') if json['type'] != 'problem' || json['new_expectations']

  assign_attributes(attrs)
  save!
end

#inspection_keywordsObject



142
143
144
# File 'app/models/exercise.rb', line 142

def inspection_keywords
  {}
end

#messages_path_for(user) ⇒ Object



118
119
120
# File 'app/models/exercise.rb', line 118

def messages_path_for(user)
  "api/guides/#{guide.slug}/#{bibliotheca_id}/student/#{URI.escape user.uid}/messages?language=#{language}"
end

#messages_url_for(user) ⇒ Object



122
123
124
# File 'app/models/exercise.rb', line 122

def messages_url_for(user)
  Mumukit::Platform.classroom_api.organic_url_for(Organization.current, messages_path_for(user))
end

#new_solutionObject



76
77
78
# File 'app/models/exercise.rb', line 76

def new_solution
  Solution.new(content: default_content)
end

#pending_siblings_for(user) ⇒ Object



35
36
37
# File 'app/models/exercise.rb', line 35

def pending_siblings_for(user)
  guide.pending_exercises(user)
end

#previousObject



47
48
49
# File 'app/models/exercise.rb', line 47

def previous
  sibling_at number.pred
end

#reclassify!(type) ⇒ Object



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

def reclassify!(type)
  update!(type: Exercise.class_for(type).name)
  Exercise.find(id)
end

#reset!Object



96
97
98
99
100
101
102
103
# File 'app/models/exercise.rb', line 96

def reset!
  self.name = nil
  self.description = nil
  self.corollary = nil
  self.hint = nil
  self.extra = nil
  self.tag_list = []
end

#search_tagsObject



56
57
58
# File 'app/models/exercise.rb', line 56

def search_tags
  [language&.name, *tag_list].compact
end

#sibling_at(index) ⇒ Object



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

def sibling_at(index)
  index = number + index unless index.positive?
  guide.exercises.find_by(number: index)
end

#slugObject



60
61
62
# File 'app/models/exercise.rb', line 60

def slug
  "#{guide.slug}/#{bibliotheca_id}"
end

#slug_partsObject



64
65
66
# File 'app/models/exercise.rb', line 64

def slug_parts
  guide.slug_parts.merge(bibliotheca_id: bibliotheca_id)
end

#splitted_descriptionObject



130
131
132
# File 'app/models/exercise.rb', line 130

def splitted_description
  description.split('> ')
end

#structural_parentObject



39
40
41
# File 'app/models/exercise.rb', line 39

def structural_parent
  guide
end

#submission_for(user) ⇒ Object



72
73
74
# File 'app/models/exercise.rb', line 72

def submission_for(user)
  assignment_for(user).submission
end

#try_submit_solution!(user, solution = {}) ⇒ Object

Submits the user solution only if the corresponding assignment has attemps left



152
153
154
155
156
157
158
159
# File 'app/models/exercise.rb', line 152

def try_submit_solution!(user, solution={})
  assignment = assignment_for(user)
  if assignment.attempts_left?
    submit_solution!(user, solution)
  else
    assignment
  end
end

#used_in?(organization = Organization.current) ⇒ Boolean

Returns:

  • (Boolean)


31
32
33
# File 'app/models/exercise.rb', line 31

def used_in?(organization=Organization.current)
  guide.usage_in_organization(organization).present?
end