canvas_cc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/canvas_cc.gemspec +37 -0
  8. data/lib/canvas_cc/canvas/assessment.rb +124 -0
  9. data/lib/canvas_cc/canvas/assignment.rb +98 -0
  10. data/lib/canvas_cc/canvas/converter.rb +30 -0
  11. data/lib/canvas_cc/canvas/course.rb +143 -0
  12. data/lib/canvas_cc/canvas/discussion_topic.rb +64 -0
  13. data/lib/canvas_cc/canvas/label.rb +8 -0
  14. data/lib/canvas_cc/canvas/question.rb +492 -0
  15. data/lib/canvas_cc/canvas/question_bank.rb +57 -0
  16. data/lib/canvas_cc/canvas/question_group.rb +35 -0
  17. data/lib/canvas_cc/canvas/resource.rb +16 -0
  18. data/lib/canvas_cc/canvas/templates/assignment.html.erb +9 -0
  19. data/lib/canvas_cc/canvas/templates/syllabus.html.erb +9 -0
  20. data/lib/canvas_cc/canvas/templates/wiki_content.html.erb +10 -0
  21. data/lib/canvas_cc/canvas/web_content.rb +15 -0
  22. data/lib/canvas_cc/canvas/web_link.rb +16 -0
  23. data/lib/canvas_cc/canvas/wiki.rb +26 -0
  24. data/lib/canvas_cc/canvas_cc/assessment_writer.rb +82 -0
  25. data/lib/canvas_cc/canvas_cc/assignment_group_writer.rb +48 -0
  26. data/lib/canvas_cc/canvas_cc/assignment_writer.rb +68 -0
  27. data/lib/canvas_cc/canvas_cc/calculated_question_writer.rb +72 -0
  28. data/lib/canvas_cc/canvas_cc/canvas_export_writer.rb +18 -0
  29. data/lib/canvas_cc/canvas_cc/cartridge_creator.rb +60 -0
  30. data/lib/canvas_cc/canvas_cc/course_setting_writer.rb +35 -0
  31. data/lib/canvas_cc/canvas_cc/discussion_writer.rb +52 -0
  32. data/lib/canvas_cc/canvas_cc/essay_question_writer.rb +19 -0
  33. data/lib/canvas_cc/canvas_cc/file_meta_writer.rb +38 -0
  34. data/lib/canvas_cc/canvas_cc/ims_manifest_generator.rb +123 -0
  35. data/lib/canvas_cc/canvas_cc/matching_question_writer.rb +43 -0
  36. data/lib/canvas_cc/canvas_cc/models/answer.rb +12 -0
  37. data/lib/canvas_cc/canvas_cc/models/assessment.rb +102 -0
  38. data/lib/canvas_cc/canvas_cc/models/assignment.rb +30 -0
  39. data/lib/canvas_cc/canvas_cc/models/assignment_group.rb +9 -0
  40. data/lib/canvas_cc/canvas_cc/models/calculated_question.rb +19 -0
  41. data/lib/canvas_cc/canvas_cc/models/canvas_file.rb +22 -0
  42. data/lib/canvas_cc/canvas_cc/models/canvas_module.rb +10 -0
  43. data/lib/canvas_cc/canvas_cc/models/course.rb +53 -0
  44. data/lib/canvas_cc/canvas_cc/models/discussion.rb +36 -0
  45. data/lib/canvas_cc/canvas_cc/models/discussion_topic.rb +5 -0
  46. data/lib/canvas_cc/canvas_cc/models/matching_question.rb +7 -0
  47. data/lib/canvas_cc/canvas_cc/models/module_item.rb +16 -0
  48. data/lib/canvas_cc/canvas_cc/models/multiple_dropdowns_question.rb +7 -0
  49. data/lib/canvas_cc/canvas_cc/models/numerical_question.rb +7 -0
  50. data/lib/canvas_cc/canvas_cc/models/page.rb +41 -0
  51. data/lib/canvas_cc/canvas_cc/models/question.rb +37 -0
  52. data/lib/canvas_cc/canvas_cc/models/question_bank.rb +42 -0
  53. data/lib/canvas_cc/canvas_cc/models/question_group.rb +10 -0
  54. data/lib/canvas_cc/canvas_cc/models/resource.rb +23 -0
  55. data/lib/canvas_cc/canvas_cc/models/web_content.rb +7 -0
  56. data/lib/canvas_cc/canvas_cc/models/web_link.rb +7 -0
  57. data/lib/canvas_cc/canvas_cc/models/workflow_state.rb +6 -0
  58. data/lib/canvas_cc/canvas_cc/module_meta_writer.rb +52 -0
  59. data/lib/canvas_cc/canvas_cc/multiple_answers_question_writer.rb +41 -0
  60. data/lib/canvas_cc/canvas_cc/multiple_blanks_question_writer.rb +51 -0
  61. data/lib/canvas_cc/canvas_cc/multiple_choice_question_writer.rb +48 -0
  62. data/lib/canvas_cc/canvas_cc/multiple_dropdowns_question_writer.rb +30 -0
  63. data/lib/canvas_cc/canvas_cc/numerical_question_writer.rb +40 -0
  64. data/lib/canvas_cc/canvas_cc/page_writer.rb +38 -0
  65. data/lib/canvas_cc/canvas_cc/question_bank_writer.rb +44 -0
  66. data/lib/canvas_cc/canvas_cc/question_group_writer.rb +23 -0
  67. data/lib/canvas_cc/canvas_cc/question_writer.rb +129 -0
  68. data/lib/canvas_cc/canvas_cc/short_answer_question_writer.rb +42 -0
  69. data/lib/canvas_cc/canvas_cc/text_only_question_writer.rb +19 -0
  70. data/lib/canvas_cc/canvas_cc/true_false_question_writer.rb +38 -0
  71. data/lib/canvas_cc/cc/assessment.rb +25 -0
  72. data/lib/canvas_cc/cc/assignment.rb +61 -0
  73. data/lib/canvas_cc/cc/cc_helper.rb +285 -0
  74. data/lib/canvas_cc/cc/converter.rb +137 -0
  75. data/lib/canvas_cc/cc/course.rb +16 -0
  76. data/lib/canvas_cc/cc/discussion_topic.rb +53 -0
  77. data/lib/canvas_cc/cc/label.rb +6 -0
  78. data/lib/canvas_cc/cc/question.rb +23 -0
  79. data/lib/canvas_cc/cc/resource.rb +30 -0
  80. data/lib/canvas_cc/cc/templates/assignment.html.erb +13 -0
  81. data/lib/canvas_cc/cc/templates/syllabus.html.erb +9 -0
  82. data/lib/canvas_cc/cc/templates/wiki_content.html.erb +10 -0
  83. data/lib/canvas_cc/cc/web_content.rb +48 -0
  84. data/lib/canvas_cc/cc/web_link.rb +75 -0
  85. data/lib/canvas_cc/cc/wiki.rb +73 -0
  86. data/lib/canvas_cc/version.rb +3 -0
  87. data/lib/canvas_cc.rb +94 -0
  88. data/spec/moodle2cc/canvas_cc/assessment_writer_spec.rb +95 -0
  89. data/spec/moodle2cc/canvas_cc/assignment_group_writer_spec.rb +51 -0
  90. data/spec/moodle2cc/canvas_cc/assignment_writer_spec.rb +74 -0
  91. data/spec/moodle2cc/canvas_cc/calculated_question_writer_spec.rb +88 -0
  92. data/spec/moodle2cc/canvas_cc/canvas_export_writer_spec.rb +26 -0
  93. data/spec/moodle2cc/canvas_cc/cartridge_creator_spec.rb +50 -0
  94. data/spec/moodle2cc/canvas_cc/course_setting_writer_spec.rb +47 -0
  95. data/spec/moodle2cc/canvas_cc/discussion_writer_spec.rb +38 -0
  96. data/spec/moodle2cc/canvas_cc/essay_question_writer_spec.rb +31 -0
  97. data/spec/moodle2cc/canvas_cc/file_meta_writer_spec.rb +57 -0
  98. data/spec/moodle2cc/canvas_cc/ims_manifest_generator_spec.rb +141 -0
  99. data/spec/moodle2cc/canvas_cc/matching_question_writer_spec.rb +51 -0
  100. data/spec/moodle2cc/canvas_cc/models/assessment_spec.rb +131 -0
  101. data/spec/moodle2cc/canvas_cc/models/assignment_group_spec.rb +9 -0
  102. data/spec/moodle2cc/canvas_cc/models/assignment_spec.rb +45 -0
  103. data/spec/moodle2cc/canvas_cc/models/calculated_question_spec.rb +25 -0
  104. data/spec/moodle2cc/canvas_cc/models/canvas_file_spec.rb +23 -0
  105. data/spec/moodle2cc/canvas_cc/models/canvas_module_spec.rb +16 -0
  106. data/spec/moodle2cc/canvas_cc/models/course_spec.rb +43 -0
  107. data/spec/moodle2cc/canvas_cc/models/discussion_spec.rb +47 -0
  108. data/spec/moodle2cc/canvas_cc/models/discussion_topic_spec.rb +7 -0
  109. data/spec/moodle2cc/canvas_cc/models/module_item_spec.rb +15 -0
  110. data/spec/moodle2cc/canvas_cc/models/page_spec.rb +34 -0
  111. data/spec/moodle2cc/canvas_cc/models/question_spec.rb +8 -0
  112. data/spec/moodle2cc/canvas_cc/models/resource_spec.rb +17 -0
  113. data/spec/moodle2cc/canvas_cc/models/web_content_spec.rb +7 -0
  114. data/spec/moodle2cc/canvas_cc/models/web_link_spec.rb +9 -0
  115. data/spec/moodle2cc/canvas_cc/module_meta_writer_spec.rb +118 -0
  116. data/spec/moodle2cc/canvas_cc/multiple_answers_question_writer_spec.rb +50 -0
  117. data/spec/moodle2cc/canvas_cc/multiple_blanks_question_writer_spec.rb +77 -0
  118. data/spec/moodle2cc/canvas_cc/multiple_choice_question_writer_spec.rb +69 -0
  119. data/spec/moodle2cc/canvas_cc/multiple_dropdowns_question_writer_spec.rb +46 -0
  120. data/spec/moodle2cc/canvas_cc/numerical_question_writer_spec.rb +69 -0
  121. data/spec/moodle2cc/canvas_cc/page_writer_spec.rb +29 -0
  122. data/spec/moodle2cc/canvas_cc/question_bank_writer_spec.rb +43 -0
  123. data/spec/moodle2cc/canvas_cc/question_writer_spec.rb +129 -0
  124. data/spec/moodle2cc/canvas_cc/short_answer_question_writer_spec.rb +50 -0
  125. data/spec/moodle2cc/canvas_cc/text_only_question_writer_spec.rb +23 -0
  126. data/spec/moodle2cc/canvas_cc/true_false_question_writer_spec.rb +62 -0
  127. data/spec/spec_helper.rb +12 -0
  128. data/spec/support/shared_examples_for_models.rb +26 -0
  129. data/test/acceptance/migrator_test.rb +24 -0
  130. data/test/fixtures/cc.imscc +0 -0
  131. data/test/fixtures/common_cartridge/ims_manifest_simple.xml +45 -0
  132. data/test/fixtures/common_cartridge/schema/cccv1p0.xsd +563 -0
  133. data/test/fixtures/common_cartridge/schema/ccv1p1_imsccauth_v1p1.xsd +203 -0
  134. data/test/fixtures/common_cartridge/schema/ccv1p1_imscp_v1p2_v1p0.xsd +827 -0
  135. data/test/fixtures/common_cartridge/schema/ccv1p1_lommanifest_v1p0.xsd +822 -0
  136. data/test/fixtures/common_cartridge/schema/ccv1p1_lomresource_v1p0.xsd +273 -0
  137. data/test/fixtures/common_cartridge/schema/xml.xsd +286 -0
  138. data/test/test_helper.rb +71 -0
  139. data/test/test_question_helper.rb +122 -0
  140. data/test/test_wiki_helper.rb +21 -0
  141. data/test/unit/canvas/assessment_test.rb +261 -0
  142. data/test/unit/canvas/assignment_test.rb +220 -0
  143. data/test/unit/canvas/converter_test.rb +171 -0
  144. data/test/unit/canvas/course_test.rb +176 -0
  145. data/test/unit/canvas/discussion_topic_test.rb +129 -0
  146. data/test/unit/canvas/label_test.rb +32 -0
  147. data/test/unit/canvas/question_bank_test.rb +92 -0
  148. data/test/unit/canvas/question_group_test.rb +90 -0
  149. data/test/unit/canvas/question_test.rb +876 -0
  150. data/test/unit/canvas/web_content_test.rb +46 -0
  151. data/test/unit/canvas/web_link_test.rb +48 -0
  152. data/test/unit/canvas/wiki_test.rb +74 -0
  153. data/test/unit/cc/assessment_test.rb +48 -0
  154. data/test/unit/cc/assignment_test.rb +72 -0
  155. data/test/unit/cc/cc_helper_test.rb +19 -0
  156. data/test/unit/cc/converter_test.rb +173 -0
  157. data/test/unit/cc/course_test.rb +36 -0
  158. data/test/unit/cc/discussion_topic_test.rb +83 -0
  159. data/test/unit/cc/label_test.rb +29 -0
  160. data/test/unit/cc/question_test.rb +54 -0
  161. data/test/unit/cc/web_content_test.rb +76 -0
  162. data/test/unit/cc/web_link_test.rb +159 -0
  163. data/test/unit/cc/wiki_test.rb +139 -0
  164. data/test/unit/logger_test.rb +33 -0
  165. data/test/unit/migrator_test.rb +67 -0
  166. data/test/unit/resource_factory_test.rb +216 -0
  167. metadata +499 -0
@@ -0,0 +1,492 @@
1
+ module CanvasCc::Canvas
2
+ class Question < CanvasCc::CC::Question
3
+ META_ATTRIBUTES = [:question_type, :points_possible, :assessment_question_identifierref]
4
+ QUESTION_TYPE_MAP = {
5
+ 'calculated' => 'calculated_question',
6
+ 'description' => 'text_only_question',
7
+ 'essay' => 'essay_question',
8
+ 'match' => 'matching_question',
9
+ 'multianswer' => 'embedded_answers_question',
10
+ 'multichoice' => 'multiple_choice_question',
11
+ 'shortanswer' => 'short_answer_question',
12
+ 'numerical' => 'numerical_question',
13
+ 'truefalse' => 'true_false_question',
14
+ 'choice' => 'multiple_choice_question'
15
+ }
16
+ QUESTION_TYPE_ID_MAP = {
17
+ 1 => 'true_false_question', # yes/no question
18
+ 2 => 'essay_question', # text box question
19
+ 3 => 'essay_question', # essay box question
20
+ 4 => 'multiple_choice_question', # radio buttons question
21
+ 5 => 'multiple_answers_question', # check boxes question
22
+ 6 => 'multiple_choice_question', # dropdown box question
23
+ 8 => 'multiple_dropdowns_question', # rate 1..5 question
24
+ 9 => 'essay_question', # date question
25
+ 10 => 'numerical_question', # numeric question
26
+ 100 => 'text_only_question', # label question
27
+ }
28
+
29
+ attr_accessor :material, :general_feedback, :answer_tolerance,
30
+ :formulas, :formula_decimal_places, :vars, :var_sets, :matches, :answers,
31
+ :numericals, :length, *META_ATTRIBUTES
32
+
33
+ def initialize(question, assessment=nil)
34
+ super
35
+ @question_type = question.type ? QUESTION_TYPE_MAP[question.type] : QUESTION_TYPE_ID_MAP[question.type_id]
36
+ @points_possible = question.grade
37
+ @general_feedback = question.general_feedback
38
+ @length = question.length
39
+
40
+ @answers = []
41
+
42
+ unless question.answers.empty?
43
+ @answers = question.answers.map do |answer|
44
+ CanvasCc::OpenStruct.new(
45
+ :id => answer.id,
46
+ :text => answer.text,
47
+ :fraction => answer.fraction,
48
+ :feedback => answer.feedback
49
+ )
50
+ end
51
+ end
52
+
53
+ unless question.choices.nil? || question.choices.empty?
54
+ @answers = question.choices.map do |answer|
55
+ CanvasCc::OpenStruct.new(
56
+ :id => answer.id,
57
+ :text => answer.content
58
+ )
59
+ end
60
+ end
61
+
62
+ calculation = question.calculations.first unless question.calculations.nil?
63
+ if calculation
64
+ @answer_tolerance = calculation.tolerance
65
+ @formula_decimal_places = calculation.correct_answer_format == 1 ? calculation.correct_answer_length : 0
66
+ @formulas = question.answers.map { |a| a.text.gsub(/[\{\}\s]/, '') }
67
+ @vars = calculation.dataset_definitions.map do |ds_def|
68
+ name = ds_def.name
69
+ type, min, max, scale = ds_def.options.split(':')
70
+ {:name => name, :min => min, :max => max, :scale => scale}
71
+ end
72
+ @var_sets = []
73
+ calculation.dataset_definitions.each do |ds_def|
74
+ ds_def.dataset_items.sort_by(&:number).each_with_index do |ds_item, index|
75
+ var_set = @var_sets[index] || {}
76
+ vars = var_set[:vars] || {}
77
+ vars[ds_def.name] = ds_item.value
78
+ var_set[:vars] = vars
79
+ @var_sets[index] = var_set
80
+ end
81
+ end
82
+ @var_sets.map do |var_set|
83
+ answer = 0
84
+ var_set[:vars].each do |k, v|
85
+ answer += v
86
+ end
87
+ var_set[:answer] = answer
88
+ end
89
+ end
90
+
91
+ unless question.numericals.nil?
92
+ @numericals = question.numericals.map do |n|
93
+ CanvasCc::OpenStruct.new(
94
+ :answer => @answers.find { |a| a.id == n.answer_id },
95
+ :tolerance => n.tolerance
96
+ )
97
+ end
98
+ end
99
+
100
+ if !question.matches.nil? && question.matches.length > 0
101
+ answers = question.matches.inject({}) do |result, match|
102
+ result[match.code] = match.answer_text
103
+ result
104
+ end
105
+ @matches = question.matches.select do |match|
106
+ match.question_text && match.question_text.strip.length > 0
107
+ end.map do |match|
108
+ CanvasCc::OpenStruct.new(
109
+ :question => match.question_text,
110
+ :answers => answers,
111
+ :answer => match.code
112
+ )
113
+ end
114
+ end
115
+
116
+ material = question.text
117
+ material = question.content || '' if material.nil?
118
+ material = material.gsub(/\{(.*?)\}/, '[\1]')
119
+ material = material + image_html(question.image) unless question.image.nil? || question.image.strip == ''
120
+ material = RDiscount.new(material).to_html if question.format == 4 # markdown
121
+ material = convert_file_path_tokens(material)
122
+ if @answers
123
+ @answers.each do |answer|
124
+ answer.text = convert_file_path_tokens(answer.text) if answer.text
125
+ end
126
+ end
127
+ @material = material
128
+
129
+ if @question_type == 'multiple_dropdowns_question' && !@answers.empty? && @length
130
+ choices = @answers[0..(@length-1)]
131
+ if @length >= @answers.length || !choices.all?{|a| !!a.text.match(/^\d/)}
132
+ # the choices don't seem to be present, so construct them
133
+ choices = (1..@length).map do |i|
134
+ CanvasCc::OpenStruct.new(
135
+ :id => "#{i}",
136
+ :text => "#{i}"
137
+ )
138
+ end
139
+ @responses = @answers
140
+ else
141
+ @responses = @answers[@length..-1]
142
+ end
143
+ @answers = choices
144
+ @responses.each_with_index do |response, index|
145
+ @material << "\n#{response.text} [response#{index + 1}]"
146
+ end
147
+ end
148
+
149
+ if question.instance_id
150
+ @assessment_question_identifierref = create_key(question.id, "#{@identifier_prefix}question_")
151
+ end
152
+ end
153
+
154
+ def create_item_xml(section_node)
155
+ section_node.item(:title => @title, :ident => @identifier) do |item_node|
156
+ item_node.itemmetadata do |meta_node|
157
+ meta_node.qtimetadata do |qtime_node|
158
+ META_ATTRIBUTES.each do |attr|
159
+ value = send(attr).to_s
160
+ if value && value.length > 0
161
+ qtime_node.qtimetadatafield do |field_node|
162
+ field_node.fieldlabel attr.to_s
163
+ field_node.fieldentry value
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ item_node.presentation do |presentation_node|
171
+ presentation_node.material do |material_node|
172
+ material_node.mattext(@material, :texttype => 'text/html')
173
+ end
174
+ create_responses(presentation_node)
175
+ end
176
+
177
+ item_node.resprocessing do |processing_node|
178
+ processing_node.outcomes do |outcomes_node|
179
+ outcomes_node.decvar(:maxvalue => '100', :minvalue => '0', :varname => 'SCORE', :vartype => 'Decimal')
180
+ end
181
+ if @general_feedback
182
+ processing_node.respcondition(:continue => 'Yes') do |condition_node|
183
+ condition_node.conditionvar do |var_node|
184
+ var_node.other
185
+ end
186
+ condition_node.displayfeedback(:feedbacktype => 'Response', :linkrefid => 'general_fb')
187
+ end
188
+ end
189
+ create_response_conditions(processing_node)
190
+ end
191
+
192
+ create_feedback_nodes(item_node)
193
+ create_additional_nodes(item_node)
194
+ end
195
+ end
196
+
197
+ def create_responses(presentation_node)
198
+ case @question_type
199
+ when 'calculated_question'
200
+ presentation_node.response_str(:rcardinality => 'Single', :ident => 'response1') do |response_node|
201
+ response_node.render_fib(:fibtype => 'Decimal') do |render_node|
202
+ render_node.response_label(:ident => 'answer1')
203
+ end
204
+ end
205
+ when 'essay_question', 'short_answer_question', 'embedded_answers_question'
206
+ presentation_node.response_str(:rcardinality => 'Single', :ident => 'response1') do |response_node|
207
+ response_node.render_fib do |render_node|
208
+ render_node.response_label(:ident => 'answer1', :rshuffle => 'No')
209
+ end
210
+ end
211
+ when 'matching_question'
212
+ @matches.each do |match|
213
+ presentation_node.response_lid(:ident => "response_#{match.answer}") do |response_node|
214
+ response_node.material do |material_node|
215
+ material_node.mattext(match.question, :texttype => 'text/html')
216
+ end
217
+ response_node.render_choice do |choice_node|
218
+ match.answers.each do |ident, text|
219
+ choice_node.response_label(:ident => ident) do |label_node|
220
+ label_node.material do |material_node|
221
+ material_node.mattext text
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ when 'multiple_choice_question'
229
+ presentation_node.response_lid(:ident => 'response1', :rcardinality => 'Single') do |response_node|
230
+ response_node.render_choice do |choice_node|
231
+ @answers.each do |answer|
232
+ choice_node.response_label(:ident => answer.id) do |label_node|
233
+ label_node.material do |material_node|
234
+ material_node.mattext answer.text, :texttype => 'text/html'
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+ when 'multiple_answers_question'
241
+ presentation_node.response_lid(:ident => 'response1', :rcardinality => 'Multiple') do |response_node|
242
+ response_node.render_choice do |choice_node|
243
+ @answers.each do |answer|
244
+ choice_node.response_label(:ident => answer.id) do |label_node|
245
+ label_node.material do |material_node|
246
+ material_node.mattext answer.text, :texttype => 'text/html'
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+ when 'multiple_dropdowns_question'
253
+ @responses.each_with_index do |response, index|
254
+ response_id = index + 1
255
+ presentation_node.response_lid(:ident => "response_response#{response_id}") do |response_node|
256
+ response_node.material do |material_node|
257
+ material_node.mattext "response#{response_id}"
258
+ end
259
+ response_node.render_choice do |choice_node|
260
+ @answers.each do |answer|
261
+ choice_node.response_label(:ident => "#{response_id}#{answer.id}") do |label_node|
262
+ label_node.material do |material_node|
263
+ material_node.mattext answer.text, :texttype => 'text/html'
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end
270
+ when 'numerical_question'
271
+ presentation_node.response_str(:rcardinality => 'Single', :ident => 'response1') do |response_node|
272
+ response_node.render_fib(:fibtype => 'Decimal') do |render_fib_node|
273
+ render_fib_node.response_label(:ident => 'answer1')
274
+ end
275
+ end
276
+ when 'true_false_question'
277
+ presentation_node.response_lid(:rcardinality => 'Single', :ident => 'response1') do |response_node|
278
+ response_node.render_choice do |render_choice_node|
279
+ @answers.each do |answer|
280
+ render_choice_node.response_label(:ident => answer.id) do |response_label_node|
281
+ response_label_node.material do |material_node|
282
+ material_node.mattext(answer.text, :texttype => 'text/html')
283
+ end
284
+ end
285
+ end
286
+ end
287
+ end
288
+ end
289
+ end
290
+
291
+ def create_response_conditions(processing_node)
292
+ case @question_type
293
+ when 'calculated_question'
294
+ processing_node.respcondition(:title => 'correct') do |condition|
295
+ condition.conditionvar do |var_node|
296
+ var_node.other
297
+ end
298
+ condition.setvar('100', :varname => 'SCORE', :action => 'Set')
299
+ end
300
+ processing_node.respcondition(:title => 'incorrect') do |condition|
301
+ condition.conditionvar do |var_node|
302
+ var_node.other
303
+ end
304
+ condition.setvar('0', :varname => 'SCORE', :action => 'Set')
305
+ end
306
+ when 'essay_question', 'embedded_answers_question'
307
+ processing_node.respcondition(:continue => 'No') do |condition|
308
+ condition.conditionvar do |var_node|
309
+ var_node.other
310
+ end
311
+ end
312
+ when 'matching_question'
313
+ score = 100.0 / @matches.length.to_f
314
+ @matches.each do |match|
315
+ processing_node.respcondition do |condition_node|
316
+ condition_node.conditionvar do |var_node|
317
+ var_node.varequal match.answer, :respident => "response_#{match.answer}"
318
+ end
319
+ condition_node.setvar "%.2f" % score, :varname => 'SCORE', :action => 'Add'
320
+ end
321
+ end
322
+ when 'multiple_choice_question'
323
+ # Feeback
324
+ @answers.each do |answer|
325
+ next unless answer.feedback && answer.feedback.strip.length > 0
326
+ processing_node.respcondition(:continue => 'Yes') do |condition_node|
327
+ condition_node.conditionvar do |var_node|
328
+ var_node.varequal answer.id, :respident => 'response1'
329
+ end
330
+ condition_node.displayfeedback(:feedbacktype => 'Response', :linkrefid => "#{answer.id}_fb")
331
+ end
332
+ end
333
+
334
+ # Scores
335
+ @answers.each do |answer|
336
+ processing_node.respcondition(:continue => 'No') do |condition_node|
337
+ condition_node.conditionvar do |var_node|
338
+ var_node.varequal answer.id, :respident => 'response1'
339
+ end
340
+ condition_node.setvar(get_score(answer.fraction), :varname => 'SCORE', :action => 'Set')
341
+ end
342
+ end
343
+ when 'multiple_answers_question'
344
+ processing_node.respcondition(:continue => 'No') do |condition_node|
345
+ first = @answers.first
346
+ rest = @answers[1..-1]
347
+ condition_node.conditionvar do |var_node|
348
+ var_node.and do |and_node|
349
+ and_node.varequal first.id, :respident => 'response1'
350
+ rest.each do |answer|
351
+ and_node.not do |not_node|
352
+ not_node.varequal answer.id, :respident => 'response1'
353
+ end
354
+ end
355
+ end
356
+ end
357
+ condition_node.setvar('100', :varname => 'SCORE', :action => 'Set')
358
+ end
359
+ when 'multiple_dropdowns_question'
360
+ score = 100.0 / @responses.length.to_f
361
+ @responses.each_with_index do |response, index|
362
+ response_id = index + 1
363
+ processing_node.respcondition do |condition_node|
364
+ condition_node.conditionvar do |var_node|
365
+ var_node.varequal "#{response_id}#{@answers.first.id}", :respident => "response_response#{response_id}"
366
+ end
367
+ condition_node.setvar "%.2f" % score, :varname => 'SCORE', :action => 'Add'
368
+ end
369
+ end
370
+ when 'numerical_question'
371
+ @numericals.each do |numerical|
372
+ processing_node.respcondition(:continue => 'No') do |condition_node|
373
+ condition_node.conditionvar do |var_node|
374
+ var_node.or do |or_node|
375
+ or_node.varequal numerical.answer.text, :respident => 'response1'
376
+ or_node.and do |and_node|
377
+ and_node.vargte numerical.answer.text.to_f - numerical.tolerance.to_f, :respident => 'response1'
378
+ and_node.varlte numerical.answer.text.to_f + numerical.tolerance.to_f, :respident => 'response1'
379
+ end
380
+ end
381
+ end
382
+ condition_node.setvar(get_score(numerical.answer.fraction), :varname => "SCORE", :action => 'Set')
383
+ condition_node.displayfeedback(:feedbacktype => 'Response', :linkrefid => "#{numerical.answer.id}_fb") if numerical.answer.feedback && numerical.answer.feedback.strip.length > 0
384
+ end
385
+ end
386
+ when 'short_answer_question'
387
+ # Feedback
388
+ @answers.each do |answer|
389
+ next unless answer.feedback && answer.feedback.strip.length > 0
390
+ processing_node.respcondition(:continue => 'Yes') do |condition_node|
391
+ condition_node.conditionvar do |var_node|
392
+ var_node.varequal answer.text, :respident => 'response1'
393
+ end
394
+ condition_node.displayfeedback(:feedbacktype => 'Response', :linkrefid => "#{answer.id}_fb")
395
+ end
396
+ end
397
+
398
+ # Conditions
399
+ @answers.each do |answer|
400
+ processing_node.respcondition(:continue => 'No') do |condition_node|
401
+ condition_node.conditionvar do |var_node|
402
+ var_node.varequal answer.text, :respident => 'response1'
403
+ end
404
+ condition_node.setvar(get_score(answer.fraction), :varname => 'SCORE', :action => "Set")
405
+ end
406
+ end
407
+ when 'true_false_question'
408
+ @answers.each do |answer|
409
+ processing_node.respcondition(:continue => 'No') do |condition_node|
410
+ condition_node.conditionvar do |var_node|
411
+ var_node.varequal answer.id, :respident => 'response1'
412
+ end
413
+ condition_node.displayfeedback(:feedbacktype => 'Response', :linkrefid => "#{answer.id}_fb") if answer.feedback && answer.feedback.strip.length > 0
414
+ condition_node.setvar(get_score(answer.fraction), :varname => 'SCORE', :action => "Set")
415
+ end
416
+ end
417
+ end
418
+ end
419
+
420
+ def create_feedback_nodes(item_node)
421
+ # Feeback
422
+ if @general_feedback
423
+ item_node.itemfeedback(:ident => 'general_fb') do |fb_node|
424
+ fb_node.flow_mat do |flow_node|
425
+ flow_node.material do |material_node|
426
+ material_node.mattext(@general_feedback, :texttype => 'text/html')
427
+ end
428
+ end
429
+ end
430
+ end
431
+
432
+ case @question_type
433
+ when 'multiple_choice_question', 'numerical_question', 'short_answer_question', 'true_false_question'
434
+ @answers.each do |answer|
435
+ next unless answer.feedback && answer.feedback.strip.length > 0
436
+ item_node.itemfeedback(:ident => "#{answer.id}_fb") do |feedback_node|
437
+ feedback_node.flow_mat do |flow_node|
438
+ flow_node.material do |material_node|
439
+ material_node.mattext answer.feedback, :texttype => 'text/html'
440
+ end
441
+ end
442
+ end
443
+ end
444
+ end
445
+ end
446
+
447
+ def create_additional_nodes(item_node)
448
+ case @question_type
449
+ when 'calculated_question'
450
+ item_node.itemproc_extension do |extension_node|
451
+ extension_node.calculated do |calculated_node|
452
+ calculated_node.answer_tolerance @answer_tolerance
453
+ calculated_node.formulas(:decimal_places => @formula_decimal_places) do |formulas_node|
454
+ @formulas.each do |formula|
455
+ formulas_node.formula formula
456
+ end
457
+ end
458
+ calculated_node.vars do |vars_node|
459
+ @vars.each do |var|
460
+ vars_node.var(:name => var[:name], :scale => var[:scale]) do |var_node|
461
+ var_node.min var[:min]
462
+ var_node.max var[:max]
463
+ end
464
+ end
465
+ end
466
+ calculated_node.var_sets do |var_sets_node|
467
+ @var_sets.each do |var_set|
468
+ ident = var_set[:vars].sort.map { |k,v| v.to_s.split('.').join }.flatten.join
469
+ var_sets_node.var_set(:ident => ident) do |var_set_node|
470
+ var_set[:vars].each do |k, v|
471
+ var_set_node.var(v, :name => k)
472
+ end
473
+ var_set_node.answer var_set[:answer]
474
+ end
475
+ end
476
+ end
477
+ end
478
+ end
479
+ end
480
+ end
481
+
482
+ def get_score(fraction)
483
+ return 100 if fraction.nil?
484
+ (100 * fraction).to_i
485
+ end
486
+
487
+ def image_html(image)
488
+ image = image.strip
489
+ %{<p><img src="#{WEB_CONTENT_TOKEN}/#{image}" alt="#{image}"/></p>}
490
+ end
491
+ end
492
+ end
@@ -0,0 +1,57 @@
1
+ module CanvasCc::Canvas
2
+ class QuestionBank
3
+ include CanvasCc::CC::CCHelper
4
+ attr_accessor :id, :title, :questions, :identifier
5
+
6
+ def initialize(question_category)
7
+ @id = question_category.id
8
+ @title = question_category.name
9
+ @identifier = create_key(@id, 'objectbank_')
10
+ @question_category = question_category
11
+ @questions = @question_category.questions.reject { |q| q.type == 'random' }.map do |question|
12
+ Question.new question
13
+ end
14
+ end
15
+
16
+ def create_resource_node(resources_node)
17
+ href = File.join(ASSESSMENT_NON_CC_FOLDER, "#{identifier}.xml.qti")
18
+ resources_node.resource(
19
+ :href => href,
20
+ :type => LOR,
21
+ :identifier => identifier
22
+ ) do |resource_node|
23
+ resource_node.file(:href => href)
24
+ end
25
+ end
26
+
27
+ def create_files(export_dir)
28
+ create_qti_xml(export_dir)
29
+ end
30
+
31
+ def create_qti_xml(export_dir)
32
+ path = File.join(export_dir, ASSESSMENT_NON_CC_FOLDER, "#{identifier}.xml.qti")
33
+ FileUtils.mkdir_p(File.dirname(path))
34
+ File.open(path, 'w') do |file|
35
+ node = Builder::XmlMarkup.new(:target => file, :indent => 2)
36
+ node.instruct!
37
+ node.questestinterop(
38
+ 'xsi:schemaLocation' => "http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd",
39
+ 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
40
+ 'xmlns' => "http://www.imsglobal.org/xsd/ims_qtiasiv1p2"
41
+ ) do |root_node|
42
+ root_node.objectbank(:ident => identifier) do |objectbank_node|
43
+ objectbank_node.qtimetadata do |qtimetadata_node|
44
+ qtimetadata_node.qtimetadatafield do |qtimetadatafield_node|
45
+ qtimetadatafield_node.fieldlabel "bank_title"
46
+ qtimetadatafield_node.fieldentry @title
47
+ end
48
+ end
49
+ @questions.each do |question|
50
+ question.create_item_xml(objectbank_node) if question
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,35 @@
1
+ module CanvasCc::Canvas
2
+ class QuestionGroup
3
+ include CanvasCc::CC::CCHelper
4
+ attr_accessor :id, :title, :selection_number, :points_per_item,
5
+ :question_bank, :sourcebank_ref, :identifier
6
+
7
+ def initialize(params={})
8
+ @id = params[:id] || 1
9
+ @title = "Group #{@id}"
10
+ @selection_number = 1
11
+ @points_per_item = params[:points_per_item] || 1
12
+ @question_bank = params[:question_bank]
13
+ @sourcebank_ref = @question_bank.identifier if @question_bank
14
+ @identifier = create_key @id, 'question_group_'
15
+ end
16
+
17
+ def increment_selection_number
18
+ @selection_number += 1
19
+ end
20
+
21
+ def create_item_xml(root_node)
22
+ root_node.section(:title => @title, :ident => @identifier) do |section_node|
23
+ section_node.selection_ordering do |ordering_node|
24
+ ordering_node.selection do |selection_node|
25
+ selection_node.sourcebank_ref @sourcebank_ref
26
+ selection_node.selection_number @selection_number
27
+ selection_node.selection_extension do |extension_node|
28
+ extension_node.points_per_item @points_per_item
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ module CanvasCc::Canvas
2
+ module Resource
3
+ def create_module_meta_item_node(items_node, position)
4
+ items_node.item(:identifier => create_mod_key(@mod)) do |item_node|
5
+ item_node.title @title
6
+ item_node.position position
7
+ item_node.new_tab ''
8
+ item_node.indent @indent
9
+ create_module_meta_item_elements(item_node)
10
+ end
11
+ end
12
+
13
+ def create_module_meta_item_elements(item_node)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4
+ <title>Assignment: <%= title %></title>
5
+ </head>
6
+ <body>
7
+ <%= body %>
8
+ </body>
9
+ </html>
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4
+ <title>Syllabus</title>
5
+ </head>
6
+ <body>
7
+ <%= syllabus_body %>
8
+ </body>
9
+ </html>
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4
+ <title><%= title %></title>
5
+ <meta name="identifier" content="<%= identifier %>"/>
6
+ </head>
7
+ <body>
8
+ <%= body %>
9
+ </body>
10
+ </html>
@@ -0,0 +1,15 @@
1
+ module CanvasCc::Canvas
2
+ class WebContent < CanvasCc::CC::WebContent
3
+ include Resource
4
+
5
+ def initialize(mod)
6
+ super
7
+ @rel_path = File.join(WIKI_FOLDER, "#{file_slug(@title)}.html")
8
+ end
9
+
10
+ def create_module_meta_item_elements(item_node)
11
+ item_node.content_type 'WikiPage'
12
+ item_node.identifierref @identifier
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module CanvasCc::Canvas
2
+ class WebLink < CanvasCc::CC::WebLink
3
+ include Resource
4
+
5
+ def create_module_meta_item_elements(item_node)
6
+ item_node.identifierref @identifier
7
+
8
+ if @external_link
9
+ item_node.url @url
10
+ item_node.content_type 'ExternalUrl'
11
+ else
12
+ item_node.content_type 'Attachment'
13
+ end
14
+ end
15
+ end
16
+ end