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 +4 -4
- data/lib/qti/models/base.rb +1 -1
- data/lib/qti/models/manifest.rb +6 -6
- data/lib/qti/v1/models/interactions.rb +3 -3
- data/lib/qti/v1/models/interactions/base_fill_blank_interaction.rb +49 -0
- data/lib/qti/v1/models/interactions/base_interaction.rb +1 -1
- data/lib/qti/v1/models/interactions/canvas_multiple_dropdown.rb +84 -0
- data/lib/qti/v1/models/interactions/fill_blank_interaction.rb +21 -53
- data/lib/qti/v1/models/interactions/formula_interaction.rb +5 -7
- data/lib/qti/v1/models/interactions/upload_interaction.rb +34 -0
- data/lib/qti/version.rb +1 -1
- data/spec/fixtures/items_1.2/canvas_multiple_dropdown.xml +167 -0
- data/spec/fixtures/items_1.2/canvas_multiple_dropdowns.xml +167 -0
- data/spec/fixtures/items_1.2/upload.xml +34 -0
- data/spec/gemfiles/nokogiri-1.8.gemfile.lock +4 -4
- data/spec/lib/qti/v1/models/interactions/canvas_multiple_dropdown_spec.rb +106 -0
- data/spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb +6 -6
- data/spec/lib/qti/v1/models/interactions/formula_interaction_spec.rb +14 -10
- data/spec/lib/qti/v1/models/interactions/upload_interaction_spec.rb +32 -0
- data/spec/lib/qti/v1/models/numerics/precision_spec.rb +4 -8
- data/spec/lib/qti/v2/models/assessment_item_spec.rb +2 -0
- data/spec/lib/qti/v2/models/assessment_test_spec.rb +2 -0
- data/spec/lib/qti/v2/models/non_assessment_test_spec.rb +0 -2
- data/spec/lib/qti/v2/models/stimulus_item_spec.rb +4 -0
- metadata +15 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8a20f28fe6f8aeded9fd3282dccc970983a3234
|
4
|
+
data.tar.gz: 054ff6d10ef0da8fbde0e8b583ed40eb9f49b2e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0ba4fa3e613ee9bcf93afd69f02ce855688f1849e5613cfd224a706cc6f556b99fac43048b2cf6769bd66dcee03a9cf8db31615edae3a3d8c0c51b82d4b982b
|
7
|
+
data.tar.gz: 5df6efce6e7f3d33b1934752075c251bd9c43aafce275ada3c5f177cf858f2e587bff5223aef40b0d29d03ecc1872262453cac2b90f45d098314b2fed6db7124
|
data/lib/qti/models/base.rb
CHANGED
@@ -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.
|
77
|
+
text = node.text.tr("\u00a0", ' ')
|
78
78
|
latex_string = " \\(#{text}\\) "
|
79
79
|
node.replace(latex_string)
|
80
80
|
end
|
data/lib/qti/models/manifest.rb
CHANGED
@@ -10,8 +10,8 @@ module Qti
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def qti_1_href
|
13
|
-
test_path = xmlns_resource(
|
14
|
-
xmlns_resource(
|
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(
|
23
|
-
xmlns_resource(
|
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(
|
33
|
-
xmlns_resource_count(
|
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
|
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 |
|
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 ==
|
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 <
|
6
|
-
CANVAS_REGEX = /(\[.+?\])
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
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
|
120
|
-
case: value_node
|
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
|
-
|
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
|
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
@@ -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"><div><p>Roses are [color1], violets are [color2].</p></div></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"><p>Roses come in many colors, violets probably do too.</p>
|
118
|
+
<p>Never the less, the correct answers were <strong>red</strong> and <strong>blue</strong>.</p></mattext>
|
119
|
+
</material>
|
120
|
+
</flow_mat>
|
121
|
+
</itemfeedback>
|
122
|
+
<itemfeedback ident="correct_fb">
|
123
|
+
<flow_mat>
|
124
|
+
<material>
|
125
|
+
<mattext texttype="text/html"><p>Completing the poem, is left to you.</p></mattext>
|
126
|
+
</material>
|
127
|
+
</flow_mat>
|
128
|
+
</itemfeedback>
|
129
|
+
<itemfeedback ident="general_incorrect_fb">
|
130
|
+
<flow_mat>
|
131
|
+
<material>
|
132
|
+
<mattext texttype="text/html"><p>Those aren't colors, you meant <strong>red</strong> and <strong>blue</strong>.</p></mattext>
|
133
|
+
</material>
|
134
|
+
</flow_mat>
|
135
|
+
</itemfeedback>
|
136
|
+
<itemfeedback ident="6548_fb">
|
137
|
+
<flow_mat>
|
138
|
+
<material>
|
139
|
+
<mattext texttype="text/html"><p>Yes! <strong>Red</strong>.</p></mattext>
|
140
|
+
</material>
|
141
|
+
</flow_mat>
|
142
|
+
</itemfeedback>
|
143
|
+
<itemfeedback ident="5550_fb">
|
144
|
+
<flow_mat>
|
145
|
+
<material>
|
146
|
+
<mattext texttype="text/html"><p>I'm pretty sure you meant <strong>red.</strong></p></mattext>
|
147
|
+
</material>
|
148
|
+
</flow_mat>
|
149
|
+
</itemfeedback>
|
150
|
+
<itemfeedback ident="6951_fb">
|
151
|
+
<flow_mat>
|
152
|
+
<material>
|
153
|
+
<mattext texttype="text/html"><p>Yes, <strong>blue</strong>!</p></mattext>
|
154
|
+
</material>
|
155
|
+
</flow_mat>
|
156
|
+
</itemfeedback>
|
157
|
+
<itemfeedback ident="4500_fb">
|
158
|
+
<flow_mat>
|
159
|
+
<material>
|
160
|
+
<mattext texttype="text/html"><p>Did you also chose plaid? You wanted to <strong>blue</strong>.</p></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"><div><p>Roses are [color1], violets are [color2].</p></div></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"><p>Roses come in many colors, violets probably do too.</p>
|
118
|
+
<p>Never the less, the correct answers were <strong>red</strong> and <strong>blue</strong>.</p></mattext>
|
119
|
+
</material>
|
120
|
+
</flow_mat>
|
121
|
+
</itemfeedback>
|
122
|
+
<itemfeedback ident="correct_fb">
|
123
|
+
<flow_mat>
|
124
|
+
<material>
|
125
|
+
<mattext texttype="text/html"><p>Completing the poem, is left to you.</p></mattext>
|
126
|
+
</material>
|
127
|
+
</flow_mat>
|
128
|
+
</itemfeedback>
|
129
|
+
<itemfeedback ident="general_incorrect_fb">
|
130
|
+
<flow_mat>
|
131
|
+
<material>
|
132
|
+
<mattext texttype="text/html"><p>Those aren't colors, you meant <strong>red</strong> and <strong>blue</strong>.</p></mattext>
|
133
|
+
</material>
|
134
|
+
</flow_mat>
|
135
|
+
</itemfeedback>
|
136
|
+
<itemfeedback ident="6548_fb">
|
137
|
+
<flow_mat>
|
138
|
+
<material>
|
139
|
+
<mattext texttype="text/html"><p>Yes! <strong>Red</strong>.</p></mattext>
|
140
|
+
</material>
|
141
|
+
</flow_mat>
|
142
|
+
</itemfeedback>
|
143
|
+
<itemfeedback ident="5550_fb">
|
144
|
+
<flow_mat>
|
145
|
+
<material>
|
146
|
+
<mattext texttype="text/html"><p>I'm pretty sure you meant <strong>red.</strong></p></mattext>
|
147
|
+
</material>
|
148
|
+
</flow_mat>
|
149
|
+
</itemfeedback>
|
150
|
+
<itemfeedback ident="6951_fb">
|
151
|
+
<flow_mat>
|
152
|
+
<material>
|
153
|
+
<mattext texttype="text/html"><p>Yes, <strong>blue</strong>!</p></mattext>
|
154
|
+
</material>
|
155
|
+
</flow_mat>
|
156
|
+
</itemfeedback>
|
157
|
+
<itemfeedback ident="4500_fb">
|
158
|
+
<flow_mat>
|
159
|
+
<material>
|
160
|
+
<mattext texttype="text/html"><p>Did you also chose plaid? You wanted to <strong>blue</strong>.</p></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
|
-
|
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
|
-
{:
|
52
|
-
{:
|
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:
|
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) { [
|
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)
|
71
|
-
|
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)
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
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
|
@@ -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.
|
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-
|
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
|