Class: Exercise
- Inherits:
-
ApplicationRecord
show all
- Includes:
- Assistable, FriendlyName, ParentNavigation, Questionable, SiblingsNavigation, Submittable, WithAssignments, WithDescription, WithDiscussions, WithLanguage, WithLocale, WithName, WithNumber, WithRandomizations
- Defined in:
- app/models/exercise.rb
Constant Summary
collapse
- RANDOMIZED_FIELDS =
[:default_content, :description, :extra, :hint, :test]
Class Method Summary
collapse
Instance Method Summary
collapse
#navigable_name, #next_for, #restart
#leave, #navigable_name, #navigable_parent, #navigation_end?
#find_assignment_and_submit!, #submit!
#submit_question!
#assignment_for, #find_assignment_for, #has_messages_for?, #messages_for, #status_for
#friendly_name, #to_param
Methods included from Assistable
#assist_with, #assistant
#randomizer, #seed, #seed_with!
#discuss!, #try_solve_discussions
#description_teaser
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
.find_transparently!(params) ⇒ Object
201
202
203
|
# File 'app/models/exercise.rb', line 201
def self.find_transparently!(params)
Guide.find_transparently!(params).locate_exercise! params[:bibliotheca_id]
end
|
.locate!(slug_and_bibliotheca_id) ⇒ Object
205
206
207
208
|
# File 'app/models/exercise.rb', line 205
def self.locate!(slug_and_bibliotheca_id)
slug, bibliotheca_id = slug_and_bibliotheca_id
Guide.locate!(slug).locate_exercise! bibliotheca_id
end
|
Instance Method Details
#choice_index_for(value) ⇒ Object
110
111
112
|
# File 'app/models/exercise.rb', line 110
def choice_index_for(value)
choice_values.index(value)
end
|
#choice_values ⇒ Object
106
107
108
|
# File 'app/models/exercise.rb', line 106
def choice_values
self[:choice_values].presence || choices.map { |it| it.indifferent_get(:value) }
end
|
#console? ⇒ Boolean
36
37
38
|
# File 'app/models/exercise.rb', line 36
def console?
queriable?
end
|
#custom? ⇒ Boolean
171
172
173
|
# File 'app/models/exercise.rb', line 171
def custom?
false
end
|
#description_context ⇒ Object
159
160
161
|
# File 'app/models/exercise.rb', line 159
def description_context
Mumukit::ContentType::Markdown.to_html splitted_description.first
end
|
#description_task ⇒ Object
167
168
169
|
# File 'app/models/exercise.rb', line 167
def description_task
Mumukit::ContentType::Markdown.to_html splitted_description.drop(1).join("\n")
end
|
#ensure_type!(type) ⇒ Object
138
139
140
141
142
143
144
|
# File 'app/models/exercise.rb', line 138
def ensure_type!(type)
if self.type != type
reclassify! type
else
self
end
end
|
#files_for(current_content) ⇒ Object
194
195
196
197
198
199
|
# File 'app/models/exercise.rb', line 194
def files_for(current_content)
language
.directives_sections
.split_sections(current_content)
.map { |name, content| Mumuki::Domain::File.new name, content }
end
|
#friendly ⇒ Object
77
78
79
|
# File 'app/models/exercise.rb', line 77
def friendly
defaulting_name { "#{navigable_parent.friendly} - #{name}" }
end
|
#guide_done_for?(user) ⇒ Boolean
52
53
54
|
# File 'app/models/exercise.rb', line 52
def guide_done_for?(user)
guide.done_for?(user)
end
|
#import_from_resource_h!(number, resource_h) ⇒ Object
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
# File 'app/models/exercise.rb', line 89
def import_from_resource_h!(number, resource_h)
self.language = Language.for_name(resource_h.dig(:language, :name)) || guide.language
self.locale = guide.locale
reset!
attrs = whitelist_attributes(resource_h, except: [:type, :id])
attrs[:choices] = resource_h[:choices].to_a
attrs[:bibliotheca_id] = resource_h[:id]
attrs[:number] = number
attrs[:manual_evaluation] ||= false
attrs = attrs.except(:expectations) if type != 'Problem' || resource_h[:new_expectations]
assign_attributes(attrs)
save!
end
|
#inspection_keywords ⇒ Object
175
176
177
|
# File 'app/models/exercise.rb', line 175
def inspection_keywords
{}
end
|
#limited? ⇒ Boolean
190
191
192
|
# File 'app/models/exercise.rb', line 190
def limited?
navigable_parent.limited_for?(self)
end
|
#messages_path_for(user) ⇒ Object
151
152
153
|
# File 'app/models/exercise.rb', line 151
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
155
156
157
|
# File 'app/models/exercise.rb', line 155
def messages_url_for(user)
Mumukit::Platform.classroom_api.organic_url_for(Organization.current, messages_path_for(user))
end
|
#new_solution ⇒ Object
85
86
87
|
# File 'app/models/exercise.rb', line 85
def new_solution
Mumuki::Domain::Submission::Solution.new(content: default_content)
end
|
#pending_siblings_for(user) ⇒ Object
44
45
46
|
# File 'app/models/exercise.rb', line 44
def pending_siblings_for(user)
guide.pending_exercises(user)
end
|
#previous ⇒ Object
56
57
58
|
# File 'app/models/exercise.rb', line 56
def previous
sibling_at number.pred
end
|
#reclassify!(type) ⇒ Object
146
147
148
149
|
# File 'app/models/exercise.rb', line 146
def reclassify!(type)
update!(type: type)
Exercise.find(id)
end
|
#reset! ⇒ Object
129
130
131
132
133
134
135
136
|
# File 'app/models/exercise.rb', line 129
def reset!
self.name = nil
self.description = nil
self.corollary = nil
self.hint = nil
self. = nil
self.tag_list = []
end
|
65
66
67
|
# File 'app/models/exercise.rb', line 65
def search_tags
[language&.name, *tag_list].compact
end
|
#settings ⇒ Object
210
211
212
|
# File 'app/models/exercise.rb', line 210
def settings
guide.settings.deep_merge super
end
|
#sibling_at(index) ⇒ Object
60
61
62
63
|
# File 'app/models/exercise.rb', line 60
def sibling_at(index)
index = number + index unless index.positive?
guide.exercises.find_by(number: index)
end
|
#splitted_description ⇒ Object
163
164
165
|
# File 'app/models/exercise.rb', line 163
def splitted_description
description.split('> ')
end
|
#structural_parent ⇒ Object
48
49
50
|
# File 'app/models/exercise.rb', line 48
def structural_parent
guide
end
|
#submission_for(user) ⇒ Object
81
82
83
|
# File 'app/models/exercise.rb', line 81
def submission_for(user)
assignment_for(user).submission
end
|
#to_resource_h ⇒ Object
Keep this list up to date with Mumukit::Sync::Store::Github::Schema::Exercise
116
117
118
119
120
121
122
123
124
125
126
127
|
# File 'app/models/exercise.rb', line 116
def to_resource_h
language_resource_h = language.to_embedded_resource_h if language != guide.language
as_json(only: i(name layout editor corollary teacher_info manual_evaluation locale
choices assistance_rules randomizations tag_list goal
free_form_editor_source initial_state final_state))
.merge(id: bibliotheca_id, language: language_resource_h, type: type.underscore)
.merge(expectations: self[:expectations])
.merge(settings: self[:settings])
.merge(RANDOMIZED_FIELDS.map { |it| [it, self[it]] }.to_h)
.symbolize_keys
.compact
end
|
#transparent_id ⇒ Object
69
70
71
|
# File 'app/models/exercise.rb', line 69
def transparent_id
"#{guide.transparent_id}/#{bibliotheca_id}"
end
|
#transparent_params ⇒ Object
73
74
75
|
# File 'app/models/exercise.rb', line 73
def transparent_params
guide.transparent_params.merge(bibliotheca_id: bibliotheca_id)
end
|
#try_submit_solution!(user, solution = {}) ⇒ Object
Submits the user solution only if the corresponding assignment has attemps left
181
182
183
184
185
186
187
188
|
# File 'app/models/exercise.rb', line 181
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
40
41
42
|
# File 'app/models/exercise.rb', line 40
def used_in?(organization=Organization.current)
guide.usage_in_organization(organization).present?
end
|