canvas_cc 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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