qti 0.9.12 → 0.9.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ecb7ff4bd1d4f7dc9238fb727d9d6d111a8534ee
4
- data.tar.gz: e63c12313dc8ced9fb35262dedce19d670f0ed7b
3
+ metadata.gz: a8a20f28fe6f8aeded9fd3282dccc970983a3234
4
+ data.tar.gz: 054ff6d10ef0da8fbde0e8b583ed40eb9f49b2e6
5
5
  SHA512:
6
- metadata.gz: 808c41b55051f1a7b4501a18385a5e56c9d06019899f5eeb77c333129e61f3ae1247862ee7676d77a38e7d052004433eab6657e541533a31f049cf6a568d05d3
7
- data.tar.gz: 9432df6fdde51711156dc520027ec524ac890028876ff1c6661a334a78c662031400a965f94760daf4de8dc44caf65373d792e9dc7487a741f5087934509184d
6
+ metadata.gz: f0ba4fa3e613ee9bcf93afd69f02ce855688f1849e5613cfd224a706cc6f556b99fac43048b2cf6769bd66dcee03a9cf8db31615edae3a3d8c0c51b82d4b982b
7
+ data.tar.gz: 5df6efce6e7f3d33b1934752075c251bd9c43aafce275ada3c5f177cf858f2e587bff5223aef40b0d29d03ecc1872262453cac2b90f45d098314b2fed6db7124
@@ -74,7 +74,7 @@ module Qti
74
74
  nodes.each do |node|
75
75
  # convert all #160 space to regular #32 whitespace
76
76
  # latex parser won't work for #160 space
77
- text = node.text.gsub(/\u00a0/, ' ')
77
+ text = node.text.tr("\u00a0", ' ')
78
78
  latex_string = " \\(#{text}\\) "
79
79
  node.replace(latex_string)
80
80
  end
@@ -10,8 +10,8 @@ module Qti
10
10
  end
11
11
 
12
12
  def qti_1_href
13
- test_path = xmlns_resource("[@type='imsqti_xmlv1p2']/@href") ||
14
- xmlns_resource("[@type='imsqti_xmlv1p2']/xmlns:file/@href")
13
+ test_path = xmlns_resource('[@type="imsqti_xmlv1p2"]/@href') ||
14
+ xmlns_resource('[@type="imsqti_xmlv1p2"]/xmlns:file/@href')
15
15
  return unless test_path
16
16
  Qti::V1::Models::Assessment.from_path!(
17
17
  remap_href_path(test_path), @package_root
@@ -19,8 +19,8 @@ module Qti
19
19
  end
20
20
 
21
21
  def qti_2_x_href
22
- test_path = xmlns_resource("[@type='imsqti_test_xmlv2p1']/@href") ||
23
- xmlns_resource("[@type='imsqti_test_xmlv2p2']/@href")
22
+ test_path = xmlns_resource('[@type="imsqti_test_xmlv2p1"]/@href') ||
23
+ xmlns_resource('[@type="imsqti_test_xmlv2p2"]/@href')
24
24
  return unless test_path
25
25
  Qti::V2::Models::AssessmentTest.from_path!(
26
26
  remap_href_path(test_path), @package_root
@@ -29,8 +29,8 @@ module Qti
29
29
 
30
30
  def qti_2_non_assessment_href
31
31
  Qti::V2::Models::NonAssessmentTest.from_path!(@path, @package_root) if
32
- xmlns_resource_count("[@type='imsqti_item_xmlv2p1']/@href") > 0 ||
33
- xmlns_resource_count("[@type='imsqti_item_xmlv2p2']/@href") > 0
32
+ xmlns_resource_count('[@type="imsqti_item_xmlv2p1"]/@href').positive? ||
33
+ xmlns_resource_count('[@type="imsqti_item_xmlv2p2"]/@href').positive?
34
34
  end
35
35
 
36
36
  def unknown_type
@@ -1,4 +1,4 @@
1
- require "active_support/core_ext/hash/except"
1
+ require 'active_support/core_ext/hash/except'
2
2
  # Populate the subclasses
3
3
  Dir["#{__dir__}/interactions/*.rb"].each { |f| load f }
4
4
 
@@ -8,8 +8,8 @@ module Qti
8
8
  module Interactions
9
9
  # This one finds the correct parsing model based on the provided xml node
10
10
  def self.interaction_model(node, parent)
11
- ordered_classes = [ FormulaInteraction, NumericInteraction ]
12
- ordered_classes.each do | interaction_class |
11
+ ordered_classes = [CanvasMultipleDropdownInteraction, FormulaInteraction, NumericInteraction]
12
+ ordered_classes.each do |interaction_class|
13
13
  match = interaction_class.matches(node, parent)
14
14
  return match if match
15
15
  end
@@ -0,0 +1,49 @@
1
+ module Qti
2
+ module V1
3
+ module Models
4
+ module Interactions
5
+ class BaseFillBlankInteraction < BaseInteraction
6
+ CANVAS_REGEX = /(\[.+?\])/
7
+
8
+ def canvas_stem_items(item_prompt)
9
+ item_prompt.split(CANVAS_REGEX).map.with_index do |stem_item, index|
10
+ if stem_item.match CANVAS_REGEX
11
+ stem_blank(index, canvas_blank_id(stem_item))
12
+ else
13
+ stem_text(index, stem_item)
14
+ end
15
+ end
16
+ end
17
+
18
+ def stem_blank(index, value)
19
+ {
20
+ id: "stem_#{index}",
21
+ position: index + 1,
22
+ type: 'blank',
23
+ blank_id: value
24
+ }
25
+ end
26
+
27
+ def stem_text(index, value)
28
+ {
29
+ id: "stem_#{index}",
30
+ position: index + 1,
31
+ type: 'text',
32
+ value: value
33
+ }
34
+ end
35
+
36
+ def canvas_blank_id(stem_item)
37
+ blank_id = nil
38
+ node.xpath('.//xmlns:response_lid').children.map do |response_lid_node|
39
+ if stem_item.include?(response_lid_node.text)
40
+ blank_id = response_lid_node.parent.attributes['ident']&.value
41
+ end
42
+ end
43
+ blank_id
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -12,7 +12,7 @@ module Qti
12
12
  def self.canvas_multiple_fib?(node)
13
13
  matches = node.xpath('.//xmlns:response_lid')
14
14
  return false if matches.count <= 1
15
- node.at_xpath('.//xmlns:fieldentry').text == "fill_in_multiple_blanks_question"
15
+ node.at_xpath('.//xmlns:fieldentry').text == 'fill_in_multiple_blanks_question'
16
16
  end
17
17
 
18
18
  def initialize(node, parent)
@@ -0,0 +1,84 @@
1
+ module Qti
2
+ module V1
3
+ module Models
4
+ module Interactions
5
+ class CanvasMultipleDropdownInteraction < BaseFillBlankInteraction
6
+ # This will know if a class matches
7
+ def self.matches(node, parent)
8
+ field_entry = node.xpath('.//xmlns:fieldentry')[0]
9
+ return false unless field_entry&.text == 'multiple_dropdowns_question'
10
+ new(node, parent)
11
+ end
12
+
13
+ def stem_items
14
+ canvas_stem_items(node.at_xpath('.//xmlns:presentation/xmlns:material/xmlns:mattext').text)
15
+ end
16
+
17
+ def blanks
18
+ @blanks = node.xpath('.//xmlns:response_lid').map do |resp|
19
+ index = 0
20
+ {
21
+ id: resp[:ident],
22
+ choices:
23
+ resp.xpath('.//xmlns:response_label').map do |bnode|
24
+ blank_choice(bnode, index += 1)
25
+ end
26
+ }
27
+ end
28
+ end
29
+
30
+ def scoring_data_structs
31
+ answers.map do |answer|
32
+ ScoringData.new(
33
+ {
34
+ id: answer[:entry_id],
35
+ position: position_for_entry(answer[:entry_id]),
36
+ item_body: answer[:blank_text]
37
+ },
38
+ rcardinality,
39
+ id: answer[:value]
40
+ )
41
+ end
42
+ end
43
+
44
+ def text_for_entry(entry_id)
45
+ blanks
46
+ @blank_choices[entry_id][:item_body]
47
+ end
48
+
49
+ def position_for_entry(entry_id)
50
+ blanks
51
+ @blank_choices[entry_id][:position]
52
+ end
53
+
54
+ def answers
55
+ @node.xpath('.//xmlns:respcondition/xmlns:setvar[@varname="SCORE"]').map do |points|
56
+ entry = points.at_xpath('preceding-sibling::xmlns:conditionvar/xmlns:varequal')
57
+ {
58
+ value: entry[:respident],
59
+ entry_id: entry.text,
60
+ blank_text: text_for_entry(entry.text),
61
+ action: points[:action],
62
+ point_value: points.text
63
+ }
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def blank_choice(bnode, index)
70
+ bnode_id = bnode[:ident]
71
+ choice = {
72
+ id: bnode_id,
73
+ position: index + 1,
74
+ item_body: bnode.at_xpath('.//xmlns:mattext').text
75
+ }
76
+ @blank_choices ||= {}
77
+ @blank_choices[bnode_id] = choice
78
+ choice
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -2,19 +2,19 @@ module Qti
2
2
  module V1
3
3
  module Models
4
4
  module Interactions
5
- class FillBlankInteraction < BaseInteraction
6
- CANVAS_REGEX = /(\[.+?\])/.freeze
5
+ class FillBlankInteraction < BaseFillBlankInteraction
6
+ CANVAS_REGEX = /(\[.+?\])/
7
7
 
8
8
  # This will know if a class matches
9
9
  def self.matches(node, parent)
10
10
  return false if node.at_xpath('.//xmlns:other').present?
11
11
  match = if BaseInteraction.canvas_multiple_fib?(node)
12
- node.at_xpath('.//xmlns:response_lid')
13
- else
14
- node.at_xpath('.//xmlns:render_fib')
15
- end
12
+ node.at_xpath('.//xmlns:response_lid')
13
+ else
14
+ node.at_xpath('.//xmlns:render_fib')
15
+ end
16
16
  return false if match.blank? ||
17
- match.attributes['fibtype']&.value == 'Decimal'
17
+ match.attributes['fibtype']&.value == 'Decimal'
18
18
  new(node, parent)
19
19
  end
20
20
 
@@ -24,59 +24,19 @@ module Qti
24
24
 
25
25
  def stem_items
26
26
  if canvas_multiple_fib?
27
- canvas_stem_items
27
+ canvas_stem_items(node.at_xpath('.//xmlns:mattext').text)
28
28
  else
29
29
  qti_stem_items
30
30
  end
31
31
  end
32
32
 
33
- def canvas_stem_items
34
- @response_lid_nodes = node.xpath('.//xmlns:response_lid')
35
- item_prompt = node.at_xpath('.//xmlns:mattext').text
36
- item_prompt_words = item_prompt.split(CANVAS_REGEX)
37
- item_prompt_words.map.with_index do |stem_item, index|
38
- if stem_item.match CANVAS_REGEX
39
- @response_lid_nodes.children.map do |response_lid_node|
40
- if stem_item.include?(response_lid_node.text)
41
- @blank_id = response_lid_node.parent.attributes['ident']&.value
42
- end
43
- end
44
-
45
- {
46
- id: "stem_#{index}",
47
- position: index + 1,
48
- type: 'blank',
49
- blank_id: @blank_id
50
- }
51
- else
52
- {
53
- id: "stem_#{index}",
54
- position: index + 1,
55
- type: 'text',
56
- value: stem_item
57
- }
58
- end
59
- end
60
- end
61
-
62
-
63
33
  def qti_stem_items
64
34
  stem_item_nodes = node.xpath('.//xmlns:presentation').children
65
35
  stem_item_nodes.map.with_index do |stem_item, index|
66
36
  if stem_item.xpath('./xmlns:render_fib').present?
67
- {
68
- id: "stem_#{index}",
69
- position: index + 1,
70
- type: 'blank',
71
- blank_id: stem_item.attributes['ident'].value
72
- }
37
+ stem_blank(index, stem_item.attributes['ident'].value)
73
38
  else
74
- {
75
- id: "stem_#{index}",
76
- position: index + 1,
77
- type: 'text',
78
- value: stem_item.children.text
79
- }
39
+ stem_text(index, stem_item.children.text)
80
40
  end
81
41
  end
82
42
  end
@@ -116,9 +76,9 @@ module Qti
116
76
  ScoringData.new(
117
77
  value_node.content,
118
78
  rcardinality,
119
- id: value_node.attributes['respident']&.value || value_node.attributes['ident']&.value,
120
- case: value_node.attributes['case']&.value || 'no',
121
- parent_identifier: value_node.parent.parent.attributes['ident']&.value,
79
+ id: scoring_data_id(value_node),
80
+ case: scoring_data_case(value_node),
81
+ parent_identifier: value_node.parent.parent.attributes['ident']&.value
122
82
  )
123
83
  end
124
84
  end
@@ -137,6 +97,14 @@ module Qti
137
97
  @node.xpath('.//xmlns:varequal')
138
98
  end
139
99
  end
100
+
101
+ def scoring_data_id(node)
102
+ node.attributes['respident']&.value || node.attributes['ident']&.value
103
+ end
104
+
105
+ def scoring_data_case(node)
106
+ node.attributes['case']&.value || 'no'
107
+ end
140
108
  end
141
109
  end
142
110
  end
@@ -15,7 +15,7 @@ module Qti
15
15
  ScoringData.new(
16
16
  answer[:output],
17
17
  rcardinality,
18
- {id: answer[:id]}
18
+ id: answer[:id]
19
19
  )
20
20
  end
21
21
  end
@@ -46,10 +46,10 @@ module Qti
46
46
  end
47
47
 
48
48
  def margin_of_error
49
- if answer_tolerance.ends_with? "%"
50
- return {margin: answer_tolerance[0..-2], margin_type:'percent'}
49
+ if answer_tolerance.ends_with? '%'
50
+ return { margin: answer_tolerance[0..-2], margin_type: 'percent' }
51
51
  end
52
- {margin: answer_tolerance, margin_type:'absolute'}
52
+ { margin: answer_tolerance, margin_type: 'absolute' }
53
53
  end
54
54
 
55
55
  def formula_decimal_places
@@ -57,9 +57,7 @@ module Qti
57
57
  end
58
58
 
59
59
  def formulas
60
- node.xpath('.//xmlns:formula').map do |fnode|
61
- fnode.text
62
- end
60
+ node.xpath('.//xmlns:formula').map(&:text)
63
61
  end
64
62
 
65
63
  private
@@ -0,0 +1,34 @@
1
+ module Qti
2
+ module V1
3
+ module Models
4
+ module Interactions
5
+ class UploadInteraction < BaseInteraction
6
+ # This will know if a class matches
7
+ def self.matches(node, parent)
8
+ meta_node = node.at_xpath(
9
+ './/xmlns:qtimetadatafield[./xmlns:fieldlabel/text()="question_type"]'
10
+ )
11
+ return false unless meta_node.present?
12
+ type_node = meta_node.at_xpath('.//xmlns:fieldentry')
13
+ return false unless type_node&.text() == 'file_upload_question'
14
+ new(node, parent)
15
+ end
16
+
17
+ def item_body
18
+ @item_body ||= begin
19
+ node = @node.dup
20
+ presentation = node.at_xpath('.//xmlns:presentation')
21
+ mattext = presentation.at_xpath('.//xmlns:mattext')
22
+ inner_content = return_inner_content!(mattext)
23
+ sanitize_content!(inner_content)
24
+ end
25
+ end
26
+
27
+ def scoring_data_structs
28
+ { value: '' }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/qti/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Qti
2
- VERSION = '0.9.12'.freeze
2
+ VERSION = '0.9.13'.freeze
3
3
  end
@@ -0,0 +1,167 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <questestinterop xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd">
3
+ <assessment ident="ie797010092a6c1798006e216ba4c9c90" title="Multiple Drop Down">
4
+ <qtimetadata>
5
+ <qtimetadatafield>
6
+ <fieldlabel>cc_maxattempts</fieldlabel>
7
+ <fieldentry>1</fieldentry>
8
+ </qtimetadatafield>
9
+ </qtimetadata>
10
+ <section ident="root_section">
11
+ <item ident="id9d8b63d85a03f2987646622805b61cf" title="Question">
12
+ <itemmetadata>
13
+ <qtimetadata>
14
+ <qtimetadatafield>
15
+ <fieldlabel>question_type</fieldlabel>
16
+ <fieldentry>multiple_dropdowns_question</fieldentry>
17
+ </qtimetadatafield>
18
+ <qtimetadatafield>
19
+ <fieldlabel>points_possible</fieldlabel>
20
+ <fieldentry>1.0</fieldentry>
21
+ </qtimetadatafield>
22
+ <qtimetadatafield>
23
+ <fieldlabel>assessment_question_identifierref</fieldlabel>
24
+ <fieldentry>i7ad7f9841cc58f0a1392816b78aaa878</fieldentry>
25
+ </qtimetadatafield>
26
+ </qtimetadata>
27
+ </itemmetadata>
28
+ <presentation>
29
+ <material>
30
+ <mattext texttype="text/html">&lt;div&gt;&lt;p&gt;Roses are [color1], violets are [color2].&lt;/p&gt;&lt;/div&gt;</mattext>
31
+ </material>
32
+ <response_lid ident="response_color1">
33
+ <material>
34
+ <mattext>color1</mattext>
35
+ </material>
36
+ <render_choice>
37
+ <response_label ident="6548">
38
+ <material>
39
+ <mattext texttype="text/plain">red</mattext>
40
+ </material>
41
+ </response_label>
42
+ <response_label ident="5550">
43
+ <material>
44
+ <mattext texttype="text/plain">plaid</mattext>
45
+ </material>
46
+ </response_label>
47
+ </render_choice>
48
+ </response_lid>
49
+ <response_lid ident="response_color2">
50
+ <material>
51
+ <mattext>color2</mattext>
52
+ </material>
53
+ <render_choice>
54
+ <response_label ident="6951">
55
+ <material>
56
+ <mattext texttype="text/plain">blue</mattext>
57
+ </material>
58
+ </response_label>
59
+ <response_label ident="4500">
60
+ <material>
61
+ <mattext texttype="text/plain">paisely</mattext>
62
+ </material>
63
+ </response_label>
64
+ </render_choice>
65
+ </response_lid>
66
+ </presentation>
67
+ <resprocessing>
68
+ <outcomes>
69
+ <decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
70
+ </outcomes>
71
+ <respcondition continue="Yes">
72
+ <conditionvar>
73
+ <other/>
74
+ </conditionvar>
75
+ <displayfeedback feedbacktype="Response" linkrefid="general_fb"/>
76
+ </respcondition>
77
+ <respcondition continue="Yes">
78
+ <conditionvar>
79
+ <varequal respident="response_color1">6548</varequal>
80
+ </conditionvar>
81
+ <displayfeedback feedbacktype="Response" linkrefid="6548_fb"/>
82
+ </respcondition>
83
+ <respcondition continue="Yes">
84
+ <conditionvar>
85
+ <varequal respident="response_color1">5550</varequal>
86
+ </conditionvar>
87
+ <displayfeedback feedbacktype="Response" linkrefid="5550_fb"/>
88
+ </respcondition>
89
+ <respcondition continue="Yes">
90
+ <conditionvar>
91
+ <varequal respident="response_color2">6951</varequal>
92
+ </conditionvar>
93
+ <displayfeedback feedbacktype="Response" linkrefid="6951_fb"/>
94
+ </respcondition>
95
+ <respcondition continue="Yes">
96
+ <conditionvar>
97
+ <varequal respident="response_color2">4500</varequal>
98
+ </conditionvar>
99
+ <displayfeedback feedbacktype="Response" linkrefid="4500_fb"/>
100
+ </respcondition>
101
+ <respcondition>
102
+ <conditionvar>
103
+ <varequal respident="response_color1">6548</varequal>
104
+ </conditionvar>
105
+ <setvar varname="SCORE" action="Add">50.00</setvar>
106
+ </respcondition>
107
+ <respcondition>
108
+ <conditionvar>
109
+ <varequal respident="response_color2">6951</varequal>
110
+ </conditionvar>
111
+ <setvar varname="SCORE" action="Add">50.00</setvar>
112
+ </respcondition>
113
+ </resprocessing>
114
+ <itemfeedback ident="general_fb">
115
+ <flow_mat>
116
+ <material>
117
+ <mattext texttype="text/html">&lt;p&gt;Roses come in many colors, violets probably do too.&lt;/p&gt;
118
+ &lt;p&gt;Never the less, the correct answers were &lt;strong&gt;red&lt;/strong&gt; and &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
119
+ </material>
120
+ </flow_mat>
121
+ </itemfeedback>
122
+ <itemfeedback ident="correct_fb">
123
+ <flow_mat>
124
+ <material>
125
+ <mattext texttype="text/html">&lt;p&gt;Completing the poem, is left to you.&lt;/p&gt;</mattext>
126
+ </material>
127
+ </flow_mat>
128
+ </itemfeedback>
129
+ <itemfeedback ident="general_incorrect_fb">
130
+ <flow_mat>
131
+ <material>
132
+ <mattext texttype="text/html">&lt;p&gt;Those aren't colors, you meant &lt;strong&gt;red&lt;/strong&gt; and &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
133
+ </material>
134
+ </flow_mat>
135
+ </itemfeedback>
136
+ <itemfeedback ident="6548_fb">
137
+ <flow_mat>
138
+ <material>
139
+ <mattext texttype="text/html">&lt;p&gt;Yes! &lt;strong&gt;Red&lt;/strong&gt;.&lt;/p&gt;</mattext>
140
+ </material>
141
+ </flow_mat>
142
+ </itemfeedback>
143
+ <itemfeedback ident="5550_fb">
144
+ <flow_mat>
145
+ <material>
146
+ <mattext texttype="text/html">&lt;p&gt;I'm pretty sure you meant &lt;strong&gt;red.&lt;/strong&gt;&lt;/p&gt;</mattext>
147
+ </material>
148
+ </flow_mat>
149
+ </itemfeedback>
150
+ <itemfeedback ident="6951_fb">
151
+ <flow_mat>
152
+ <material>
153
+ <mattext texttype="text/html">&lt;p&gt;Yes, &lt;strong&gt;blue&lt;/strong&gt;!&lt;/p&gt;</mattext>
154
+ </material>
155
+ </flow_mat>
156
+ </itemfeedback>
157
+ <itemfeedback ident="4500_fb">
158
+ <flow_mat>
159
+ <material>
160
+ <mattext texttype="text/html">&lt;p&gt;Did you also chose plaid? You wanted to &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
161
+ </material>
162
+ </flow_mat>
163
+ </itemfeedback>
164
+ </item>
165
+ </section>
166
+ </assessment>
167
+ </questestinterop>
@@ -0,0 +1,167 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <questestinterop xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd">
3
+ <assessment ident="ie797010092a6c1798006e216ba4c9c90" title="Multiple Drop Down">
4
+ <qtimetadata>
5
+ <qtimetadatafield>
6
+ <fieldlabel>cc_maxattempts</fieldlabel>
7
+ <fieldentry>1</fieldentry>
8
+ </qtimetadatafield>
9
+ </qtimetadata>
10
+ <section ident="root_section">
11
+ <item ident="id9d8b63d85a03f2987646622805b61cf" title="Question">
12
+ <itemmetadata>
13
+ <qtimetadata>
14
+ <qtimetadatafield>
15
+ <fieldlabel>question_type</fieldlabel>
16
+ <fieldentry>multiple_dropdowns_question</fieldentry>
17
+ </qtimetadatafield>
18
+ <qtimetadatafield>
19
+ <fieldlabel>points_possible</fieldlabel>
20
+ <fieldentry>1.0</fieldentry>
21
+ </qtimetadatafield>
22
+ <qtimetadatafield>
23
+ <fieldlabel>assessment_question_identifierref</fieldlabel>
24
+ <fieldentry>i7ad7f9841cc58f0a1392816b78aaa878</fieldentry>
25
+ </qtimetadatafield>
26
+ </qtimetadata>
27
+ </itemmetadata>
28
+ <presentation>
29
+ <material>
30
+ <mattext texttype="text/html">&lt;div&gt;&lt;p&gt;Roses are [color1], violets are [color2].&lt;/p&gt;&lt;/div&gt;</mattext>
31
+ </material>
32
+ <response_lid ident="response_color1">
33
+ <material>
34
+ <mattext>color1</mattext>
35
+ </material>
36
+ <render_choice>
37
+ <response_label ident="6548">
38
+ <material>
39
+ <mattext texttype="text/plain">red</mattext>
40
+ </material>
41
+ </response_label>
42
+ <response_label ident="5550">
43
+ <material>
44
+ <mattext texttype="text/plain">plaid</mattext>
45
+ </material>
46
+ </response_label>
47
+ </render_choice>
48
+ </response_lid>
49
+ <response_lid ident="response_color2">
50
+ <material>
51
+ <mattext>color2</mattext>
52
+ </material>
53
+ <render_choice>
54
+ <response_label ident="6951">
55
+ <material>
56
+ <mattext texttype="text/plain">blue</mattext>
57
+ </material>
58
+ </response_label>
59
+ <response_label ident="4500">
60
+ <material>
61
+ <mattext texttype="text/plain">paisely</mattext>
62
+ </material>
63
+ </response_label>
64
+ </render_choice>
65
+ </response_lid>
66
+ </presentation>
67
+ <resprocessing>
68
+ <outcomes>
69
+ <decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
70
+ </outcomes>
71
+ <respcondition continue="Yes">
72
+ <conditionvar>
73
+ <other/>
74
+ </conditionvar>
75
+ <displayfeedback feedbacktype="Response" linkrefid="general_fb"/>
76
+ </respcondition>
77
+ <respcondition continue="Yes">
78
+ <conditionvar>
79
+ <varequal respident="response_color1">6548</varequal>
80
+ </conditionvar>
81
+ <displayfeedback feedbacktype="Response" linkrefid="6548_fb"/>
82
+ </respcondition>
83
+ <respcondition continue="Yes">
84
+ <conditionvar>
85
+ <varequal respident="response_color1">5550</varequal>
86
+ </conditionvar>
87
+ <displayfeedback feedbacktype="Response" linkrefid="5550_fb"/>
88
+ </respcondition>
89
+ <respcondition continue="Yes">
90
+ <conditionvar>
91
+ <varequal respident="response_color2">6951</varequal>
92
+ </conditionvar>
93
+ <displayfeedback feedbacktype="Response" linkrefid="6951_fb"/>
94
+ </respcondition>
95
+ <respcondition continue="Yes">
96
+ <conditionvar>
97
+ <varequal respident="response_color2">4500</varequal>
98
+ </conditionvar>
99
+ <displayfeedback feedbacktype="Response" linkrefid="4500_fb"/>
100
+ </respcondition>
101
+ <respcondition>
102
+ <conditionvar>
103
+ <varequal respident="response_color1">6548</varequal>
104
+ </conditionvar>
105
+ <setvar varname="SCORE" action="Add">50.00</setvar>
106
+ </respcondition>
107
+ <respcondition>
108
+ <conditionvar>
109
+ <varequal respident="response_color2">6951</varequal>
110
+ </conditionvar>
111
+ <setvar varname="SCORE" action="Add">50.00</setvar>
112
+ </respcondition>
113
+ </resprocessing>
114
+ <itemfeedback ident="general_fb">
115
+ <flow_mat>
116
+ <material>
117
+ <mattext texttype="text/html">&lt;p&gt;Roses come in many colors, violets probably do too.&lt;/p&gt;
118
+ &lt;p&gt;Never the less, the correct answers were &lt;strong&gt;red&lt;/strong&gt; and &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
119
+ </material>
120
+ </flow_mat>
121
+ </itemfeedback>
122
+ <itemfeedback ident="correct_fb">
123
+ <flow_mat>
124
+ <material>
125
+ <mattext texttype="text/html">&lt;p&gt;Completing the poem, is left to you.&lt;/p&gt;</mattext>
126
+ </material>
127
+ </flow_mat>
128
+ </itemfeedback>
129
+ <itemfeedback ident="general_incorrect_fb">
130
+ <flow_mat>
131
+ <material>
132
+ <mattext texttype="text/html">&lt;p&gt;Those aren't colors, you meant &lt;strong&gt;red&lt;/strong&gt; and &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
133
+ </material>
134
+ </flow_mat>
135
+ </itemfeedback>
136
+ <itemfeedback ident="6548_fb">
137
+ <flow_mat>
138
+ <material>
139
+ <mattext texttype="text/html">&lt;p&gt;Yes! &lt;strong&gt;Red&lt;/strong&gt;.&lt;/p&gt;</mattext>
140
+ </material>
141
+ </flow_mat>
142
+ </itemfeedback>
143
+ <itemfeedback ident="5550_fb">
144
+ <flow_mat>
145
+ <material>
146
+ <mattext texttype="text/html">&lt;p&gt;I'm pretty sure you meant &lt;strong&gt;red.&lt;/strong&gt;&lt;/p&gt;</mattext>
147
+ </material>
148
+ </flow_mat>
149
+ </itemfeedback>
150
+ <itemfeedback ident="6951_fb">
151
+ <flow_mat>
152
+ <material>
153
+ <mattext texttype="text/html">&lt;p&gt;Yes, &lt;strong&gt;blue&lt;/strong&gt;!&lt;/p&gt;</mattext>
154
+ </material>
155
+ </flow_mat>
156
+ </itemfeedback>
157
+ <itemfeedback ident="4500_fb">
158
+ <flow_mat>
159
+ <material>
160
+ <mattext texttype="text/html">&lt;p&gt;Did you also chose plaid? You wanted to &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
161
+ </material>
162
+ </flow_mat>
163
+ </itemfeedback>
164
+ </item>
165
+ </section>
166
+ </assessment>
167
+ </questestinterop>
@@ -0,0 +1,34 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <questestinterop xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd">
3
+ <qtimetadata>
4
+ <qtimetadatafield>
5
+ <fieldlabel>cc_maxattempts</fieldlabel>
6
+ <fieldentry>1</fieldentry>
7
+ </qtimetadatafield>
8
+ </qtimetadata>
9
+ <section ident="root_section">
10
+ <item ident="i53d46f6a4edbfcefd662489e9f2a970a" title="Question">
11
+ <itemmetadata>
12
+ <qtimetadata>
13
+ <qtimetadatafield>
14
+ <fieldlabel>question_type</fieldlabel>
15
+ <fieldentry>file_upload_question</fieldentry>
16
+ </qtimetadatafield>
17
+ <qtimetadatafield>
18
+ <fieldlabel>points_possible</fieldlabel>
19
+ <fieldentry>1.0</fieldentry>
20
+ </qtimetadatafield>
21
+ <qtimetadatafield>
22
+ <fieldlabel>assessment_question_identifierref</fieldlabel>
23
+ <fieldentry>i2b5557c31dcad5441b956ebb83d06915</fieldentry>
24
+ </qtimetadatafield>
25
+ </qtimetadata>
26
+ </itemmetadata>
27
+ <presentation>
28
+ <material>
29
+ <mattext texttype="text/html">Upload a file that is a CSV</mattext>
30
+ </material>
31
+ </presentation>
32
+ </item>
33
+ </section>
34
+ </questestinterop>
@@ -1,7 +1,10 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- qti (0.9.12)
4
+ mathml2latex (0.1.2)
5
+ activesupport (>= 4.2.9, < 5.2)
6
+ nokogiri (>= 1.6.8)
7
+ qti (0.9.13)
5
8
  actionview (>= 4.2.0)
6
9
  activesupport (>= 4.2.9, < 5.2)
7
10
  dry-struct (~> 0.2.1)
@@ -67,9 +70,6 @@ GEM
67
70
  loofah (2.2.2)
68
71
  crass (~> 1.0.2)
69
72
  nokogiri (>= 1.5.9)
70
- mathml2latex (0.1.1)
71
- activesupport (>= 4.2.9, < 5.2)
72
- nokogiri (~> 1.8)
73
73
  method_source (0.9.0)
74
74
  mini_portile2 (2.3.0)
75
75
  minitest (5.11.3)
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+
3
+ describe Qti::V1::Models::Interactions::CanvasMultipleDropdownInteraction do
4
+ let(:fixtures_path) { File.join('spec', 'fixtures', 'items_1.2') }
5
+ let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
6
+ let(:assessment_item_refs) { test_object.assessment_items }
7
+ let(:loaded_class) { described_class.new(assessment_item_refs.first, test_object) }
8
+
9
+ shared_examples_for 'shuffled?' do
10
+ it 'returns shuffle setting' do
11
+ expect(loaded_class.shuffled?).to eq shuffle_value
12
+ end
13
+ end
14
+
15
+ shared_examples_for 'blanks' do
16
+ it 'returns the blanks' do
17
+ expect(loaded_class.blanks).to eq(expected_blanks)
18
+ end
19
+ end
20
+
21
+ shared_examples_for 'answers' do
22
+ it 'returns the answers' do
23
+ expect(loaded_class.answers.count).to eq answer_count
24
+ expect(loaded_class.answers).to eq(expected_answers)
25
+ end
26
+ end
27
+
28
+ shared_examples_for 'stem_items' do
29
+ it 'returns the stem_items' do
30
+ expect(loaded_class.stem_items).to eq(expected_stem_items)
31
+ end
32
+ end
33
+
34
+ shared_examples_for 'scoring_data_structs' do
35
+ it 'returns the scoring_data_structs' do
36
+ expect(loaded_class.scoring_data_structs.map(&:id)).to eq(scoring_data_ids)
37
+ expect(loaded_class.scoring_data_structs.map(&:values)).to eq(scoring_data_values)
38
+ end
39
+ end
40
+
41
+ context 'canvas_multiple_dropdowns.xml' do
42
+ let(:file_path) { File.join(fixtures_path, 'canvas_multiple_dropdowns.xml') }
43
+ let(:shuffle_value) { false }
44
+ let(:answer_count) { 2 }
45
+ let(:scoring_data_ids) { %w[response_color1 response_color2] }
46
+ let(:scoring_data_values) do
47
+ [
48
+ { id: '6548', position: 2, item_body: 'red' },
49
+ { id: '6951', position: 2, item_body: 'blue' }
50
+ ]
51
+ end
52
+ let(:expected_blanks) do
53
+ [
54
+ {
55
+ id: 'response_color1',
56
+ choices:
57
+ [
58
+ { id: '6548', position: 2, item_body: 'red' },
59
+ { id: '5550', position: 3, item_body: 'plaid' }
60
+ ]
61
+ },
62
+ {
63
+ id: 'response_color2',
64
+ choices:
65
+ [
66
+ { id: '6951', position: 2, item_body: 'blue' },
67
+ { id: '4500', position: 3, item_body: 'paisely' }
68
+ ]
69
+ }
70
+ ]
71
+ end
72
+ let(:expected_stem_items) do
73
+ [
74
+ { id: 'stem_0', position: 1, type: 'text', value: '<div><p>Roses are ' },
75
+ { id: 'stem_1', position: 2, type: 'blank', blank_id: 'response_color1' },
76
+ { id: 'stem_2', position: 3, type: 'text', value: ', violets are ' },
77
+ { id: 'stem_3', position: 4, type: 'blank', blank_id: 'response_color2' },
78
+ { id: 'stem_4', position: 5, type: 'text', value: '.</p></div>' }
79
+ ]
80
+ end
81
+ let('expected_answers') do
82
+ [
83
+ {
84
+ value: 'response_color1',
85
+ entry_id: '6548',
86
+ blank_text: 'red',
87
+ action: 'Add',
88
+ point_value: '50.00'
89
+ },
90
+ {
91
+ value: 'response_color2',
92
+ entry_id: '6951',
93
+ blank_text: 'blue',
94
+ action: 'Add',
95
+ point_value: '50.00'
96
+ }
97
+ ]
98
+ end
99
+
100
+ include_examples 'shuffled?'
101
+ include_examples 'answers'
102
+ include_examples 'blanks'
103
+ include_examples 'stem_items'
104
+ include_examples 'scoring_data_structs'
105
+ end
106
+ end
@@ -45,11 +45,11 @@ describe Qti::V1::Models::Interactions::FillBlankInteraction do
45
45
  let(:scoring_data_values) { %w[Illinois illinois] }
46
46
  let(:scoring_data_case) { %w[no no] }
47
47
  let(:answer_count) { 2 }
48
- let(:expected_blanks) {[{ id: 'response1' }]}
48
+ let(:expected_blanks) { [{ id: 'response1' }] }
49
49
  let(:expected_stem_items) do
50
50
  [
51
- {:id=>"stem_0", :position=>1, :type=>"text", :value=>"<div><p>Chicago is in what state?</p></div>"},
52
- {:id=>"stem_1", :position=>2, :type=>"blank", :blank_id=>"response1"}
51
+ { id: 'stem_0', position: 1, type: 'text', value: '<div><p>Chicago is in what state?</p></div>' },
52
+ { id: 'stem_1', position: 2, type: 'blank', blank_id: 'response1' }
53
53
  ]
54
54
  end
55
55
 
@@ -70,14 +70,14 @@ describe Qti::V1::Models::Interactions::FillBlankInteraction do
70
70
  let(:scoring_data_values) { %w[red Red blue Blue] }
71
71
  let(:scoring_data_case) { %w[no no no no] }
72
72
  let(:answer_count) { 4 }
73
- let(:expected_blanks) {[{id: '9799'}, {id: '5231'}, {id: '5939'}, {id: '6364'}]}
73
+ let(:expected_blanks) { [{ id: '9799' }, { id: '5231' }, { id: '5939' }, { id: '6364' }] }
74
74
  let(:expected_stem_items) do
75
75
  [
76
76
  { id: 'stem_0', position: 1, type: 'text', value: '<div><p><span>Roses are ' },
77
77
  { id: 'stem_1', position: 2, type: 'blank', blank_id: 'response_color1' },
78
78
  { id: 'stem_2', position: 3, type: 'text', value: ', violets are ' },
79
79
  { id: 'stem_3', position: 4, type: 'blank', blank_id: 'response_color2' },
80
- { id: "stem_4", position: 5, type: "text", value: "</span></p></div>"}
80
+ { id: 'stem_4', position: 5, type: 'text', value: '</span></p></div>' }
81
81
  ]
82
82
  end
83
83
 
@@ -99,7 +99,7 @@ describe Qti::V1::Models::Interactions::FillBlankInteraction do
99
99
  let(:scoring_data_values) { %w[Winter Summer York] }
100
100
  let(:scoring_data_case) { %w[Yes Yes Yes] }
101
101
  let(:answer_count) { 3 }
102
- let(:expected_blanks) {[{ id: 'FIB01' }, { id: 'FIB02' }, { id: 'FIB03' }]}
102
+ let(:expected_blanks) { [{ id: 'FIB01' }, { id: 'FIB02' }, { id: 'FIB03' }] }
103
103
  let(:expected_stem_items) do
104
104
  [
105
105
  { id: 'stem_0', position: 1, type: 'text', value: 'Fill-in-the blanks in this text from Richard III: ' },
@@ -45,9 +45,9 @@ describe Qti::V1::Models::Interactions::FormulaInteraction do
45
45
  let(:formula_decimal_places) { '0' }
46
46
  let(:formula_formulas) { ['x'] }
47
47
 
48
- let(:item_title) {'<div><p>What number is [x]</p></div>'}
48
+ let(:item_title) { '<div><p>What number is [x]</p></div>' }
49
49
 
50
- let(:variables) { [ { name: 'x', min: '1.0', max: '10.0', precision: '0' } ] }
50
+ let(:variables) { [{ name: 'x', min: '1.0', max: '10.0', precision: '0' }] }
51
51
 
52
52
  include_examples 'scoring_data_structs'
53
53
  include_examples 'reading_formulas'
@@ -65,10 +65,12 @@ describe Qti::V1::Models::Interactions::FormulaInteraction do
65
65
  let(:formula_decimal_places) { '0' }
66
66
  let(:formula_formulas) { ['x+y'] }
67
67
 
68
- let(:item_title) {'<div><p>[x] + [y]</p></div>'}
68
+ let(:item_title) { '<div><p>[x] + [y]</p></div>' }
69
69
 
70
- let(:variables) { [ { name: 'x', min: '1.0', max: '10.0', precision: '0' },
71
- { name: 'y', min: '1.0', max: '10.0', precision: '0' } ] }
70
+ let(:variables) do
71
+ [{ name: 'x', min: '1.0', max: '10.0', precision: '0' },
72
+ { name: 'y', min: '1.0', max: '10.0', precision: '0' }]
73
+ end
72
74
 
73
75
  include_examples 'scoring_data_structs'
74
76
  include_examples 'answer_tolerance'
@@ -86,12 +88,14 @@ describe Qti::V1::Models::Interactions::FormulaInteraction do
86
88
  let(:formula_decimal_places) { '2' }
87
89
  let(:formula_formulas) { ['x=n*x', 'y=m*y', 'x+y'] }
88
90
 
89
- let(:item_title) {'<div><p>[n][x] + [m][y]</p></div>'}
91
+ let(:item_title) { '<div><p>[n][x] + [m][y]</p></div>' }
90
92
 
91
- let(:variables) { [ { name: 'y', min: '1.0', max: '10.0', precision: '2' },
92
- { name: 'x', min: '1.0', max: '10.0', precision: '2' },
93
- { name: 'n', min: '1.0', max: '10.0', precision: '2' },
94
- { name: 'm', min: '1.0', max: '10.0', precision: '2' } ] }
93
+ let(:variables) do
94
+ [{ name: 'y', min: '1.0', max: '10.0', precision: '2' },
95
+ { name: 'x', min: '1.0', max: '10.0', precision: '2' },
96
+ { name: 'n', min: '1.0', max: '10.0', precision: '2' },
97
+ { name: 'm', min: '1.0', max: '10.0', precision: '2' }]
98
+ end
95
99
 
96
100
  include_examples 'scoring_data_structs'
97
101
  include_examples 'answer_tolerance'
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Qti::V1::Models::Interactions::UploadInteraction do
4
+ let(:fixtures_path) { File.join('spec', 'fixtures', 'items_1.2') }
5
+ let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
6
+ let(:assessment_item_refs) { test_object.assessment_items }
7
+ let(:loaded_class) { described_class.new(assessment_item_refs.first, test_object) }
8
+
9
+ context 'upload.xml' do
10
+ let(:file_path) { File.join(fixtures_path, 'upload.xml') }
11
+ let(:cardinality) { 'Single' }
12
+
13
+ it 'returns loads the correct cardinality' do
14
+ expect(loaded_class.send(:rcardinality)).to eq(cardinality)
15
+ end
16
+
17
+ context '#item_body' do
18
+ let(:loaded_class) { described_class.new(assessment_item_refs.first, test_object) }
19
+ it 'returns right title' do
20
+ expect(loaded_class.item_body).to eq 'Upload a file that is a CSV'
21
+ end
22
+ end
23
+
24
+ describe '#scoring_data_structs' do
25
+ it 'grabs scoring data value for matching questions' do
26
+ expect(loaded_class.scoring_data_structs).to eq(
27
+ value: ''
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
@@ -71,18 +71,14 @@ describe Qti::V1::Models::Numerics::Precision do
71
71
 
72
72
  context '#significant_digits' do
73
73
  it 'returns correct number for leading zeros' do
74
- expect(described_class.significant_digits('0.0000123')).
75
- to eq(3)
74
+ expect(described_class.significant_digits('0.0000123')).to eq(3)
76
75
  end
77
76
  it 'returns correct number for trailing zeros' do
78
- expect(described_class.significant_digits('0.0000123000')).
79
- to eq(3)
77
+ expect(described_class.significant_digits('0.0000123000')).to eq(3)
80
78
  end
81
79
  it 'returns correct number for zeros in the middle' do
82
- expect(described_class.significant_digits('0.000012003')).
83
- to eq(5)
84
- expect(described_class.significant_digits('15.000012003')).
85
- to eq(11)
80
+ expect(described_class.significant_digits('0.000012003')).to eq(5)
81
+ expect(described_class.significant_digits('15.000012003')).to eq(11)
86
82
  end
87
83
  end
88
84
  end
@@ -86,7 +86,9 @@ describe Qti::V2::Models::AssessmentItem do
86
86
 
87
87
  # it 'removes the passage from the item_body' do
88
88
  # item = test_object.create_assessment_item(item_ref)
89
+ # rubocop:disable AsciiComments
89
90
  # expect(item.item_body).not_to include '¡El equipo de hockey te necesita!'
91
+ # rubocop:enable AsciiComments
90
92
  # end
91
93
  # end
92
94
  end
@@ -86,7 +86,9 @@ describe Qti::V2::Models::AssessmentTest do
86
86
  # 'passages', '0cfd5cf7-2c91-4b35-a57a-9f5d1709f68f.html'
87
87
  # )
88
88
  # stimulus = loaded_class.create_stimulus(stimulus_path)
89
+ # rubocop:disable AsciiComments
89
90
  # expect(stimulus.title).to eq '¡El equipo de hockey te necesita!'
91
+ # rubocop:enable AsciiComments
90
92
  # end
91
93
  # end
92
94
  end
@@ -2,8 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  fixtures_path = File.join('spec', 'fixtures')
4
4
 
5
-
6
-
7
5
  describe Qti::V2::Models::NonAssessmentTest do
8
6
  shared_examples_for 'loading_a_non-assessment' do
9
7
  it 'loads an Non-AssessmentTest XML file' do
@@ -13,13 +13,17 @@
13
13
  # end
14
14
 
15
15
  # it 'has the title' do
16
+ # rubocop:disable AsciiComments
16
17
  # expect(loaded_class.title).to eq '¡El equipo de hockey te necesita!'
18
+ # rubocop:enable AsciiComments
17
19
  # end
18
20
 
19
21
  # it 'has sanitized item_body' do
20
22
  # expect(loaded_class.body).to include '<div'
21
23
  # expect(loaded_class.body).to include 'Listen to the audio passage.'
24
+ # rubocop:disable AsciiComments
22
25
  # expect(loaded_class.body).to include '¡'
26
+ # rubocop:enable AsciiComments
23
27
  # end
24
28
 
25
29
  # it 'has the identifier used to identify it in manifest file' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qti
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.12
4
+ version: 0.9.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hannah Bottalla
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-04-04 00:00:00.000000000 Z
12
+ date: 2018-04-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -296,7 +296,9 @@ files:
296
296
  - lib/qti/v1/models/choices/fill_blank_choice.rb
297
297
  - lib/qti/v1/models/choices/logical_identifier_choice.rb
298
298
  - lib/qti/v1/models/interactions.rb
299
+ - lib/qti/v1/models/interactions/base_fill_blank_interaction.rb
299
300
  - lib/qti/v1/models/interactions/base_interaction.rb
301
+ - lib/qti/v1/models/interactions/canvas_multiple_dropdown.rb
300
302
  - lib/qti/v1/models/interactions/choice_interaction.rb
301
303
  - lib/qti/v1/models/interactions/fill_blank_interaction.rb
302
304
  - lib/qti/v1/models/interactions/formula_interaction.rb
@@ -304,6 +306,7 @@ files:
304
306
  - lib/qti/v1/models/interactions/numeric_interaction.rb
305
307
  - lib/qti/v1/models/interactions/ordering_interaction.rb
306
308
  - lib/qti/v1/models/interactions/string_interaction.rb
309
+ - lib/qti/v1/models/interactions/upload_interaction.rb
307
310
  - lib/qti/v1/models/numerics/exact_match.rb
308
311
  - lib/qti/v1/models/numerics/margin_error.rb
309
312
  - lib/qti/v1/models/numerics/precision.rb
@@ -333,6 +336,8 @@ files:
333
336
  - lib/qti/v2/models/scoring_data.rb
334
337
  - lib/qti/v2/models/stimulus_item.rb
335
338
  - lib/qti/version.rb
339
+ - spec/fixtures/items_1.2/canvas_multiple_dropdown.xml
340
+ - spec/fixtures/items_1.2/canvas_multiple_dropdowns.xml
336
341
  - spec/fixtures/items_1.2/canvas_multiple_fib.xml
337
342
  - spec/fixtures/items_1.2/choice.xml
338
343
  - spec/fixtures/items_1.2/essay.xml
@@ -352,6 +357,7 @@ files:
352
357
  - spec/fixtures/items_1.2/ordering.xml
353
358
  - spec/fixtures/items_1.2/single_fib.xml
354
359
  - spec/fixtures/items_1.2/true_false.xml
360
+ - spec/fixtures/items_1.2/upload.xml
355
361
  - spec/fixtures/items_2.1/Example02-feedbackInline.xml
356
362
  - spec/fixtures/items_2.1/categorization.xml
357
363
  - spec/fixtures/items_2.1/choice.xml
@@ -570,6 +576,7 @@ files:
570
576
  - spec/lib/qti/v1/models/choices/fill_blank_choice_spec.rb
571
577
  - spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
572
578
  - spec/lib/qti/v1/models/interactions/base_interaction_spec.rb
579
+ - spec/lib/qti/v1/models/interactions/canvas_multiple_dropdown_spec.rb
573
580
  - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
574
581
  - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
575
582
  - spec/lib/qti/v1/models/interactions/formula_interaction_spec.rb
@@ -577,6 +584,7 @@ files:
577
584
  - spec/lib/qti/v1/models/interactions/numeric_interaction_spec.rb
578
585
  - spec/lib/qti/v1/models/interactions/ordering_interaction_spec.rb
579
586
  - spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
587
+ - spec/lib/qti/v1/models/interactions/upload_interaction_spec.rb
580
588
  - spec/lib/qti/v1/models/numerics/exact_match_spec.rb
581
589
  - spec/lib/qti/v1/models/numerics/margin_error_spec.rb
582
590
  - spec/lib/qti/v1/models/numerics/precision_spec.rb
@@ -626,6 +634,8 @@ signing_key:
626
634
  specification_version: 4
627
635
  summary: QTI 1.2 and 2.1 import and export models
628
636
  test_files:
637
+ - spec/fixtures/items_1.2/canvas_multiple_dropdown.xml
638
+ - spec/fixtures/items_1.2/canvas_multiple_dropdowns.xml
629
639
  - spec/fixtures/items_1.2/canvas_multiple_fib.xml
630
640
  - spec/fixtures/items_1.2/choice.xml
631
641
  - spec/fixtures/items_1.2/essay.xml
@@ -645,6 +655,7 @@ test_files:
645
655
  - spec/fixtures/items_1.2/ordering.xml
646
656
  - spec/fixtures/items_1.2/single_fib.xml
647
657
  - spec/fixtures/items_1.2/true_false.xml
658
+ - spec/fixtures/items_1.2/upload.xml
648
659
  - spec/fixtures/items_2.1/Example02-feedbackInline.xml
649
660
  - spec/fixtures/items_2.1/categorization.xml
650
661
  - spec/fixtures/items_2.1/choice.xml
@@ -863,6 +874,7 @@ test_files:
863
874
  - spec/lib/qti/v1/models/choices/fill_blank_choice_spec.rb
864
875
  - spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
865
876
  - spec/lib/qti/v1/models/interactions/base_interaction_spec.rb
877
+ - spec/lib/qti/v1/models/interactions/canvas_multiple_dropdown_spec.rb
866
878
  - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
867
879
  - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
868
880
  - spec/lib/qti/v1/models/interactions/formula_interaction_spec.rb
@@ -870,6 +882,7 @@ test_files:
870
882
  - spec/lib/qti/v1/models/interactions/numeric_interaction_spec.rb
871
883
  - spec/lib/qti/v1/models/interactions/ordering_interaction_spec.rb
872
884
  - spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
885
+ - spec/lib/qti/v1/models/interactions/upload_interaction_spec.rb
873
886
  - spec/lib/qti/v1/models/numerics/exact_match_spec.rb
874
887
  - spec/lib/qti/v1/models/numerics/margin_error_spec.rb
875
888
  - spec/lib/qti/v1/models/numerics/precision_spec.rb