qti 0.2.16 → 0.3.16

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f132d1d60f4543bdd51c0e802af142364ecec6dc
4
- data.tar.gz: 014a77115d5de11e5b30eafc1ffabfa75fbf433a
3
+ metadata.gz: 09a38606bbf7afefc7b808dd338055b24375193b
4
+ data.tar.gz: 1dcad5866f62bd26d1dd48ab3f3ab6646de5eddc
5
5
  SHA512:
6
- metadata.gz: 3c31189e0aec801f05c3f102e6a3702211ee389cf39f1c212140f4048ebf50f91943b2efcdd3f242aff519fd84e1385874a7ceee540b569d5562f5990bd96981
7
- data.tar.gz: e336ed0335bd67b47133a9fa0a48204d4f2ed7b181f0cc9af0958384ccdb9efb62f24947dedbd42ae61c8712e43cedbe735db121b62ab0bee10f5043f8aed316
6
+ metadata.gz: 952002458866f648ca5c473608a232e46fda37ae6e31cc273d48f25d4449eb4fc8f7f0d020069abb7f4593e72f1a71aaf706841aad90d48a761f0350c4477733
7
+ data.tar.gz: b38e9b92eda87771d2b8a9b4bcda1eb052540841b146bcc3c410bc2d67ca1b0ba9f38a2611f5caa579a269aaee55e00216f0b2e79151c38769554b369ed866da
data/README.md CHANGED
@@ -1,7 +1,3 @@
1
- ---
2
- content_id: "121077930"
3
- title: Qti
4
- ---
5
1
  # Qti Gem
6
2
 
7
3
  The Qti gem supports QTI 1.2 and 2.1. It currently supports the following interaction types:
@@ -19,8 +15,10 @@ $ bundle install qti
19
15
 
20
16
  ## Usage
21
17
 
22
- `require 'qti'`
23
- `@gem = Qti::Importer.new(path_of_quiz)`
18
+ ```rb
19
+ require 'qti'
20
+ @gem = Qti::Importer.new(path_of_quiz)
21
+ ```
24
22
 
25
23
  You can use the gem to access the manifest, the assessments, and the assessment items and use it in your own code!
26
24
 
@@ -53,7 +51,7 @@ Returns the version appropriate AssessmentItem model
53
51
  - `title`
54
52
  - `points_possible`
55
53
  - `rcardinality` (QTI 1.2)
56
- - ` interaction_model` (ie Choice Interaction)
54
+ - `interaction_model` (ie Choice Interaction)
57
55
  - `scoring_data_structs`
58
56
 
59
57
  ## Running Tests
@@ -62,7 +60,7 @@ You can run tests with code coverage using the following command:
62
60
 
63
61
  ## Development
64
62
 
65
- Want to contribute? Submit a pull request!
63
+ Want to contribute? Please submit a pull request!
66
64
 
67
65
  ## To Do
68
66
  - More interaction models!
data/lib/qti.rb CHANGED
@@ -54,9 +54,11 @@ require 'qti/models/base'
54
54
  require 'qti/v1/models/base'
55
55
  require 'qti/v1/models/interactions/base_interaction'
56
56
  require 'qti/v1/models/interactions/choice_interaction'
57
+
57
58
  require 'qti/v1/models/assessment'
58
59
  require 'qti/v1/models/assessment_item'
59
60
  require 'qti/v1/models/choices/logical_identifier_choice'
61
+ require 'qti/v1/models/choices/fill_blank_choice'
60
62
  require 'qti/v1/models/scoring_data'
61
63
 
62
64
  require 'qti/v2/models/base'
@@ -0,0 +1,27 @@
1
+ require 'qti/v1/models/base'
2
+
3
+ module Qti
4
+ module V1
5
+ module Models
6
+ module Choices
7
+ class FillBlankChoice < Qti::V1::Models::Base
8
+ def initialize(node)
9
+ @node = node
10
+ end
11
+
12
+ def identifier
13
+ @identifier ||= @node.attributes['respident']&.value ||
14
+ @node.attributes['ident']&.value
15
+ end
16
+
17
+ def item_body
18
+ @item_body ||= begin
19
+ node = @node.dup
20
+ node.content.squish
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,77 @@
1
+ module Qti
2
+ module V1
3
+ module Models
4
+ module Interactions
5
+ class FillBlankInteraction < BaseInteraction
6
+ # This will know if a class matches
7
+ def self.matches(node)
8
+ return false if node.xpath('.//xmlns:other').present?
9
+ matches = node.xpath('.//xmlns:render_fib')
10
+ return false if matches.empty?
11
+ new(node)
12
+ end
13
+
14
+ def initialize(node)
15
+ @node = node
16
+ end
17
+
18
+ def stem_items
19
+ stem_item_nodes = node.xpath('.//xmlns:presentation').children
20
+ stem_item_nodes.map.with_index do |stem_item, index|
21
+ if stem_item.xpath('./xmlns:render_fib').present?
22
+ {
23
+ id: "stem_#{index}",
24
+ position: index + 1,
25
+ type: 'blank',
26
+ blank_id: stem_item.attributes['ident'].value
27
+ }
28
+ else
29
+ {
30
+ id: "stem_#{index}",
31
+ position: index + 1,
32
+ type: 'text',
33
+ value: stem_item.children.text
34
+ }
35
+ end
36
+ end
37
+ end
38
+
39
+ def blanks
40
+ node.xpath('.//xmlns:response_str').map do |blank|
41
+ { id: blank.attributes['ident'].value }
42
+ end
43
+ end
44
+
45
+ def answers
46
+ @answers ||= answer_nodes.map do |node|
47
+ V1::Models::Choices::FillBlankChoice.new(node)
48
+ end
49
+ end
50
+
51
+ def scoring_data_structs
52
+ answer_nodes.map { |value_node| ScoringData.new(
53
+ value_node.content,
54
+ rcardinality,
55
+ {
56
+ id: value_node.attributes['respident']&.value,
57
+ case: value_node.attributes['case']&.value
58
+ }
59
+ )
60
+ }
61
+ end
62
+
63
+ private
64
+
65
+ def rcardinality
66
+ @rcardinality ||= @node.at_xpath('.//xmlns:response_str/@rcardinality')&.value ||
67
+ @node.at_xpath('.//xmlns:response_num/@rcardinality')&.value
68
+ end
69
+
70
+ def answer_nodes
71
+ @node.xpath('.//xmlns:varequal')
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -3,10 +3,10 @@ module Qti
3
3
  module Models
4
4
  module Interactions
5
5
  class StringInteraction < BaseInteraction
6
- @node_name = 'response_str'.freeze
7
6
  # This will know if a class matches
8
7
  def self.matches(node)
9
- matches = node.children.children.select { |n| n.name == @node_name }
8
+ return false unless node.xpath('.//xmlns:other').present?
9
+ matches = node.xpath('.//xmlns:render_fib')
10
10
  return false if matches.empty?
11
11
  new(matches.first)
12
12
  end
@@ -14,6 +14,12 @@ module Qti
14
14
  def initialize(node)
15
15
  @node = node
16
16
  end
17
+
18
+ private
19
+
20
+ def rcardinality
21
+ @rcardinality ||= @node.at_xpath('.//xmlns:response_str/@rcardinality').value
22
+ end
17
23
  end
18
24
  end
19
25
  end
@@ -1,7 +1,11 @@
1
1
  module Qti
2
2
  module V1
3
3
  module Models
4
- ScoringData = Struct.new(:values, :rcardinality)
4
+ ScoringData = Struct.new(:values, :rcardinality, :id, :case) do
5
+ def initialize(values, rcardinality, options={})
6
+ super(values, rcardinality, options[:id], options[:case])
7
+ end
8
+ end
5
9
  end
6
10
  end
7
11
  end
@@ -0,0 +1,34 @@
1
+ module Qti
2
+ module V2
3
+ module Models
4
+ module Interactions
5
+ class GapMatchInteraction < Qti::V2::Models::Base
6
+ NODE_NAME = 'gapMatchInteraction'.freeze
7
+ # This will know if a class matches
8
+ def self.matches(node)
9
+ matches = node.children.filter(INTERACTION_ELEMENTS_CSS).select { |n| n.name == NODE_NAME }
10
+ return false if matches.empty?
11
+
12
+ raise Qti::UnsupportedSchema if matches.size > 1
13
+ new(matches.first)
14
+ end
15
+
16
+ def initialize(node)
17
+ @node = node
18
+ end
19
+
20
+ def gap_max_count
21
+ @node.attributes['gapMax']&.value&.to_i
22
+ end
23
+
24
+ def gap_min_count
25
+ @node.attributes['gapMin']&.value&.to_i
26
+ end
27
+
28
+ def gap_choice
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,209 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
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 title="1.2 Import Quiz" ident="A1001">
4
+ <section title="Main" ident="S1002">
5
+ <item title="Grading - specific - 3 pt score" ident="QUE_1003">
6
+ <presentation>
7
+ <material>
8
+ <mattext texttype="text/html"><![CDATA[If I get a 3, I must have done something wrong. <img align="bottom" alt="image.png" src="org0/images/image.png" border="0"/>]]></mattext>
9
+ </material>
10
+ <response_lid ident="QUE_1004_RL" rcardinality="Single" rtiming="No">
11
+ <render_choice shuffle="Yes">
12
+ <response_label ident="QUE_1005_A1">
13
+ <material>
14
+ <mattext texttype="text/html"><![CDATA[True]]></mattext>
15
+ </material>
16
+ </response_label>
17
+ <response_label ident="QUE_1006_A2">
18
+ <material>
19
+ <mattext texttype="text/html"><![CDATA[False]]></mattext>
20
+ </material>
21
+ </response_label>
22
+ </render_choice>
23
+ </response_lid>
24
+ </presentation>
25
+ <resprocessing>
26
+ <outcomes>
27
+ <decvar vartype="Decimal" defaultval="0" varname="que_score"/>
28
+ </outcomes>
29
+ <respcondition>
30
+ <conditionvar>
31
+ <varequal respident="QUE_1004_RL">QUE_1005_A1</varequal>
32
+ </conditionvar>
33
+ <setvar varname="que_score" action="Add">0</setvar>
34
+ </respcondition>
35
+ <respcondition>
36
+ <conditionvar>
37
+ <varequal respident="QUE_1004_RL">QUE_1006_A2</varequal>
38
+ </conditionvar>
39
+ <setvar varname="que_score" action="Set">10.00</setvar>
40
+ </respcondition>
41
+ </resprocessing>
42
+ </item>
43
+ <item title="How much time each week?" ident="QUE_1007">
44
+ <presentation>
45
+ <material>
46
+ <mattext texttype="text/html"><![CDATA[How much time should you spend working on your online course each week in order to earn credit? <img align="bottom" alt="image.png" src="$IMS_CC_FILE_BASE$org1/images/image.png" border="0"/>]]></mattext>
47
+ </material>
48
+ <response_lid ident="QUE_1008_RL" rcardinality="Single" rtiming="No">
49
+ <render_choice>
50
+ <response_label ident="QUE_1009_A1">
51
+ <material>
52
+ <mattext texttype="text/html"><![CDATA[However long it takes]]></mattext>
53
+ </material>
54
+ </response_label>
55
+ <response_label ident="QUE_1010_A2">
56
+ <material>
57
+ <mattext texttype="text/html"><![CDATA[30 - 90 minutes]]></mattext>
58
+ </material>
59
+ </response_label>
60
+ <response_label ident="QUE_1011_A3">
61
+ <material>
62
+ <mattext texttype="text/html"><![CDATA[1 - 2 hours]]></mattext>
63
+ </material>
64
+ </response_label>
65
+ <response_label ident="QUE_1012_A4">
66
+ <material>
67
+ <mattext texttype="text/html"><![CDATA[At least 3 hours]]></mattext>
68
+ </material>
69
+ </response_label>
70
+ <response_label ident="QUE_1013_A5">
71
+ <material>
72
+ <mattext texttype="text/html"><![CDATA[6 or more hours]]></mattext>
73
+ </material>
74
+ </response_label>
75
+ </render_choice>
76
+ </response_lid>
77
+ </presentation>
78
+ <resprocessing>
79
+ <outcomes>
80
+ <decvar vartype="Decimal" maxvalue="10" defaultval="0" varname="que_score"/>
81
+ </outcomes>
82
+ <respcondition>
83
+ <conditionvar>
84
+ <varequal respident="QUE_1008_RL">QUE_1009_A1</varequal>
85
+ </conditionvar>
86
+ <setvar varname="que_score" action="Add">0</setvar>
87
+ </respcondition>
88
+ <respcondition>
89
+ <conditionvar>
90
+ <varequal respident="QUE_1008_RL">QUE_1010_A2</varequal>
91
+ </conditionvar>
92
+ <setvar varname="que_score" action="Add">0</setvar>
93
+ </respcondition>
94
+ <respcondition>
95
+ <conditionvar>
96
+ <varequal respident="QUE_1008_RL">QUE_1011_A3</varequal>
97
+ </conditionvar>
98
+ <setvar varname="que_score" action="Add">0</setvar>
99
+ </respcondition>
100
+ <respcondition>
101
+ <conditionvar>
102
+ <varequal respident="QUE_1008_RL">QUE_1012_A4</varequal>
103
+ </conditionvar>
104
+ <setvar varname="que_score" action="Set">10.00</setvar>
105
+ </respcondition>
106
+ <respcondition>
107
+ <conditionvar>
108
+ <varequal respident="QUE_1008_RL">QUE_1013_A5</varequal>
109
+ </conditionvar>
110
+ <setvar varname="que_score" action="Add">0</setvar>
111
+ </respcondition>
112
+ </resprocessing>
113
+ </item>
114
+ <item title="Discussion - content." ident="QUE_1022">
115
+ <presentation>
116
+ <material>
117
+ <mattext texttype="text/html"><![CDATA[A good discussion posting includes which of the following (select all that apply):]]></mattext>
118
+ </material>
119
+ <response_lid ident="QUE_1023_RL" rcardinality="Multiple" rtiming="No">
120
+ <render_choice>
121
+ <response_label ident="QUE_1024_A1">
122
+ <material>
123
+ <mattext texttype="text/html"><![CDATA[Poses a question or invites additional comment from others]]></mattext>
124
+ </material>
125
+ </response_label>
126
+ <response_label ident="QUE_1025_A2">
127
+ <material>
128
+ <mattext texttype="text/html"><![CDATA[Attacks another's post to generate controversy]]></mattext>
129
+ </material>
130
+ </response_label>
131
+ <response_label ident="QUE_1026_A3">
132
+ <material>
133
+ <mattext texttype="text/html"><![CDATA[Expresses an opinion which may be controversial so that others can agree or disagree]]></mattext>
134
+ </material>
135
+ </response_label>
136
+ <response_label ident="QUE_1027_A4">
137
+ <material>
138
+ <mattext texttype="text/html"><![CDATA[Adds information, ideas or suggestions that expand everyone's thinking about the topic]]></mattext>
139
+ </material>
140
+ </response_label>
141
+ <response_label ident="QUE_1028_A5">
142
+ <material>
143
+ <mattext texttype="text/html"><![CDATA[Reiterates the consensus or restates the ideas of others without adding independent thought]]></mattext>
144
+ </material>
145
+ </response_label>
146
+ <response_label ident="QUE_1029_A6">
147
+ <material>
148
+ <mattext texttype="text/html"><![CDATA[Provides non-specific praise for fellow learners like "good job" or "I loved your idea"]]></mattext>
149
+ </material>
150
+ </response_label>
151
+ <response_label ident="QUE_1030_A7">
152
+ <material>
153
+ <mattext texttype="text/html"><![CDATA[Responds positively to a person's comment and includes their name or quote from the original posting that supports your expanded idea]]></mattext>
154
+ </material>
155
+ </response_label>
156
+ </render_choice>
157
+ </response_lid>
158
+ </presentation>
159
+ <resprocessing>
160
+ <outcomes>
161
+ <decvar vartype="Decimal" defaultval="0" varname="que_score" maxvalue="10.00" minvalue="0"/>
162
+ </outcomes>
163
+ <respcondition>
164
+ <conditionvar>
165
+ <varequal respident="QUE_1023_RL">QUE_1024_A1</varequal>
166
+ </conditionvar>
167
+ <setvar varname="que_score" action="Add">25.00</setvar>
168
+ </respcondition>
169
+ <respcondition>
170
+ <conditionvar>
171
+ <varequal respident="QUE_1023_RL">QUE_1025_A2</varequal>
172
+ </conditionvar>
173
+ <setvar varname="que_score" action="Add">-10.00</setvar>
174
+ </respcondition>
175
+ <respcondition>
176
+ <conditionvar>
177
+ <varequal respident="QUE_1023_RL">QUE_1026_A3</varequal>
178
+ </conditionvar>
179
+ <setvar varname="que_score" action="Add">25.00</setvar>
180
+ </respcondition>
181
+ <respcondition>
182
+ <conditionvar>
183
+ <varequal respident="QUE_1023_RL">QUE_1027_A4</varequal>
184
+ </conditionvar>
185
+ <setvar varname="que_score" action="Add">25.00</setvar>
186
+ </respcondition>
187
+ <respcondition>
188
+ <conditionvar>
189
+ <varequal respident="QUE_1023_RL">QUE_1028_A5</varequal>
190
+ </conditionvar>
191
+ <setvar varname="que_score" action="Add">-10.00</setvar>
192
+ </respcondition>
193
+ <respcondition>
194
+ <conditionvar>
195
+ <varequal respident="QUE_1023_RL">QUE_1029_A6</varequal>
196
+ </conditionvar>
197
+ <setvar varname="que_score" action="Add">-10.00</setvar>
198
+ </respcondition>
199
+ <respcondition>
200
+ <conditionvar>
201
+ <varequal respident="QUE_1023_RL">QUE_1030_A7</varequal>
202
+ </conditionvar>
203
+ <setvar varname="que_score" action="Add">25.00</setvar>
204
+ </respcondition>
205
+ </resprocessing>
206
+ </item>
207
+ </section>
208
+ </assessment>
209
+ </questestinterop>
@@ -0,0 +1,25 @@
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
+ <item ident="if15fb877c2cde9a14437aa7429360ac6" title="First Essay">
4
+ <presentation>
5
+ <material>
6
+ <mattext texttype="text/html">Here is an essay question</mattext>
7
+ </material>
8
+ <response_str ident="response1" rcardinality="Single">
9
+ <render_fib>
10
+ <response_label ident="answer1" rshuffle="No"/>
11
+ </render_fib>
12
+ </response_str>
13
+ </presentation>
14
+ <resprocessing>
15
+ <outcomes>
16
+ <decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
17
+ </outcomes>
18
+ <respcondition continue="No">
19
+ <conditionvar>
20
+ <other/>
21
+ </conditionvar>
22
+ </respcondition>
23
+ </resprocessing>
24
+ </item>
25
+ </questestinterop>
@@ -0,0 +1,46 @@
1
+ <?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
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
+ <item title = "Standard FIB string Item" ident = "FIB_STR">
4
+ <presentation label = "BasicExample013b">
5
+ <material>
6
+ <mattext>Fill-in-the blanks in this text from Richard III: </mattext>
7
+ </material>
8
+ <material>
9
+ <mattext>Now is the </mattext>
10
+ </material>
11
+ <response_str ident = "FIB01" rcardinality = "Single" rtiming = "No">
12
+ <render_fib fibtype = "String" prompt = "Dashline" maxchars = "6">
13
+ <response_label ident = "A"/>
14
+ </render_fib>
15
+ </response_str>
16
+ <material>
17
+ <mattext> of our discontent made glorious </mattext>
18
+ </material>
19
+ <response_str ident = "FIB02" rcardinality = "Single" rtiming = "No">
20
+ <render_fib fibtype = "String" prompt = "Dashline" maxchars = "6">
21
+ <response_label ident = "A"/>
22
+ </render_fib>
23
+ </response_str>
24
+ <material>
25
+ <mattext> by these sons of </mattext>
26
+ </material>
27
+ <response_str ident = "FIB03" rcardinality = "Single" rtiming = "No">
28
+ <render_fib fibtype = "String" prompt = "Dashline" maxchars = "4">
29
+ <response_label ident = "A"/>
30
+ </render_fib>
31
+ </response_str>
32
+ </presentation>
33
+ <resprocessing>
34
+ <outcomes>
35
+ <decvar varname = "FIBSCORE1" vartype = "Integer" defaultval = "0"/>
36
+ </outcomes>
37
+ <respcondition>
38
+ <conditionvar>
39
+ <varequal respident = "FIB01" case = "Yes">Winter</varequal>
40
+ <varequal respident = "FIB02" case = "Yes">Summer</varequal>
41
+ <varequal respident = "FIB03" case = "Yes">York</varequal>
42
+ </conditionvar>
43
+ <setvar action = "Add" varname = "FIBSCORE1">3</setvar>
44
+ </respcondition>
45
+ </item>
46
+ </questestinterop>
@@ -0,0 +1,46 @@
1
+ <?xml version = "1.0" encoding = "UTF-8" standalone = "no"?>
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
+ <item title = "Standard FIB string Item" ident = "FIB_STR">
4
+ <presentation label = "BasicExample013b">
5
+ <material>
6
+ <mattext>Fill-in-the blanks in this text from Richard III: </mattext>
7
+ </material>
8
+ <material>
9
+ <mattext>Now is the </mattext>
10
+ </material>
11
+ <response_str ident = "FIB01" rcardinality = "Single" rtiming = "No">
12
+ <render_fib fibtype = "String" prompt = "Dashline" maxchars = "6">
13
+ <response_label ident = "A"/>
14
+ </render_fib>
15
+ </response_str>
16
+ <material>
17
+ <mattext> of our discontent made glorious </mattext>
18
+ </material>
19
+ <response_str ident = "FIB02" rcardinality = "Single" rtiming = "No">
20
+ <render_fib fibtype = "String" prompt = "Dashline" maxchars = "6">
21
+ <response_label ident = "A"/>
22
+ </render_fib>
23
+ </response_str>
24
+ <material>
25
+ <mattext> by these sons of </mattext>
26
+ </material>
27
+ <response_str ident = "FIB03" rcardinality = "Single" rtiming = "No">
28
+ <render_fib fibtype = "String" prompt = "Dashline" maxchars = "4">
29
+ <response_label ident = "A"/>
30
+ </render_fib>
31
+ </response_str>
32
+ </presentation>
33
+ <resprocessing>
34
+ <outcomes>
35
+ <decvar varname = "FIBSCORE1" vartype = "Integer" defaultval = "0"/>
36
+ </outcomes>
37
+ <respcondition>
38
+ <conditionvar>
39
+ <varequal respident = "FIB01" case = "Yes">Winter</varequal>
40
+ <varequal respident = "FIB02" case = "Yes">Summer</varequal>
41
+ <varequal respident = "FIB03" case = "Yes">York</varequal>
42
+ </conditionvar>
43
+ <setvar action = "Add" varname = "FIBSCORE1">3</setvar>
44
+ </respcondition>
45
+ </item>
46
+ </questestinterop>
@@ -204,6 +204,52 @@
204
204
  </respcondition>
205
205
  </resprocessing>
206
206
  </item>
207
+ <item ident="i25e12fe33ac9d91ff208923796f83d0a" title="Question">
208
+ <presentation>
209
+ <material>
210
+ <mattext texttype="text/html">First color of the rainbow?</mattext>
211
+ </material>
212
+ <response_str ident="response1" rcardinality="Single">
213
+ <render_fib>
214
+ <response_label ident="answer1" rshuffle="No"/>
215
+ </render_fib>
216
+ </response_str>
217
+ </presentation>
218
+ <resprocessing>
219
+ <outcomes>
220
+ <decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
221
+ </outcomes>
222
+ <respcondition continue="No">
223
+ <conditionvar>
224
+ <varequal respident="response1">Red</varequal>
225
+ </conditionvar>
226
+ <setvar action="Set" varname="SCORE">100</setvar>
227
+ </respcondition>
228
+ </resprocessing>
229
+ </item>
230
+ <item ident="i8c4f92444b901b000087b00d84c3e36c" title="FIB Numeric (Decimal)">
231
+ <presentation>
232
+ <material>
233
+ <mattext texttype="text/html">Give the value of PI to three decimal places and round up.</mattext>
234
+ </material>
235
+ <response_num ident="response1" rcardinality="Single">
236
+ <render_fib>
237
+ <response_label ident="answer1" rshuffle="No"/>
238
+ </render_fib>
239
+ </response_num>
240
+ </presentation>
241
+ <resprocessing>
242
+ <outcomes>
243
+ <decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
244
+ </outcomes>
245
+ <respcondition continue="No">
246
+ <conditionvar>
247
+ <varequal respident="response1">3.142</varequal>
248
+ </conditionvar>
249
+ <setvar action="Set" varname="SCORE">100</setvar>
250
+ </respcondition>
251
+ </resprocessing>
252
+ </item>
207
253
  </section>
208
254
  </assessment>
209
255
  </questestinterop>
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Qti::V1::Models::Choices::FillBlankChoice do
4
+ context 'fib.xml' do
5
+ let(:fixtures_path) { File.join('spec', 'fixtures') }
6
+ let(:file_path) { File.join(fixtures_path, 'items_1.2', 'fib.xml') }
7
+ let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
8
+ let(:nodes) { test_object.assessment_items }
9
+ let(:choices) { nodes.map { |node| described_class.new(node) } }
10
+
11
+ it 'returns the right identifier' do
12
+ expect(choices.map(&:identifier)).to eq %w(FIB_STR)
13
+ end
14
+
15
+ it 'returns the item body text' do
16
+ expect(choices.map(&:item_body).map(&:empty?).any?).to eq false
17
+ end
18
+
19
+ it 'removes inline feedback elements from item_body' do
20
+ expect(choices.map(&:item_body).map { |text| text.include? 'correct' }.any?).to eq false
21
+ end
22
+ end
23
+ end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Qti::V1::Models::Choices::LogicalIdentifierChoice do
4
4
  context 'quiz.xml' do
5
5
  let(:fixtures_path) { File.join('spec', 'fixtures') }
6
- let(:file_path) { File.join(fixtures_path, 'test_qti_1.2', 'quiz.xml') }
6
+ let(:file_path) { File.join(fixtures_path, 'items_1.2', 'choice.xml') }
7
7
  let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
8
8
  let(:nodes) { test_object.assessment_items }
9
9
  let(:choices) { nodes.map { |node| described_class.new(node) } }
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Qti::V1::Models::Interactions::FillBlankInteraction 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) }
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 [{ id: "FIB01" }, { id: "FIB02" }, { id: "FIB03" }]
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.first).to be_an_instance_of(Qti::V1::Models::Choices::FillBlankChoice)
25
+ end
26
+ end
27
+
28
+ shared_examples_for 'scoring_data_structs' do
29
+ it 'returns the scoring_data_structs' do
30
+ expect(loaded_class.scoring_data_structs.map(&:id)).to eq(scoring_data_ids)
31
+ expect(loaded_class.scoring_data_structs.map(&:values)).to eq(scoring_data_values)
32
+ expect(loaded_class.scoring_data_structs.map(&:case)).to eq(scoring_data_case)
33
+ end
34
+ end
35
+
36
+ shared_examples_for 'stem_items' do
37
+ it 'returns the stem_items' do
38
+ expect(loaded_class.stem_items).to eq(expected_stem_items)
39
+ end
40
+ end
41
+
42
+ context 'fib_str.xml' do
43
+ let(:file_path) { File.join(fixtures_path, 'fib_str.xml') }
44
+ let(:shuffle_value) { false }
45
+ let(:scoring_data_ids) { %w(FIB01 FIB02 FIB03) }
46
+ let(:scoring_data_values) { %w(Winter Summer York) }
47
+ let(:scoring_data_case) { %w(Yes Yes Yes) }
48
+ let(:answer_count) { 3 }
49
+ let(:expected_stem_items) {[
50
+ { id: "stem_0", position: 1, type: "text", value: "Fill-in-the blanks in this text from Richard III: " },
51
+ { id: "stem_1", position: 2, type: "text", value: "Now is the " },
52
+ { id: "stem_2", position: 3, type: "blank", blank_id: "FIB01" },
53
+ { id: "stem_3", position: 4, type: "text", value: " of our discontent made glorious " },
54
+ { id: "stem_4", position: 5, type: "blank", blank_id: "FIB02" },
55
+ { id: "stem_5", position: 6, type: "text", value: " by these sons of " },
56
+ { id: "stem_6", position: 7, type: "blank", blank_id: "FIB03" }
57
+ ]}
58
+
59
+ include_examples 'shuffled?'
60
+ include_examples 'answers'
61
+ include_examples 'scoring_data_structs'
62
+ include_examples 'stem_items'
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Qti::V1::Models::Interactions::StringInteraction 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) }
8
+
9
+ context 'essay.xml' do
10
+ let(:file_path) { File.join(fixtures_path, 'essay.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
+ end
17
+ end
@@ -30,9 +30,9 @@ describe Qti::Importer do
30
30
  it 'create items with correct scoring structs' do
31
31
  assessment = importer.test_object
32
32
  assessment_items = importer.assessment_item_refs.map{ |ref| importer.create_assessment_item(ref) }
33
- expect(assessment_items.count).to eq 3
33
+ expect(assessment_items.count).to eq 5
34
34
  answer_arity = assessment_items.map{|item| item.scoring_data_structs.count }
35
- expect(answer_arity).to eq [1, 1, 4]
35
+ expect(answer_arity).to eq [1, 1, 4, 1, 1]
36
36
  end
37
37
  end
38
38
  end
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.2.16
4
+ version: 0.3.16
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: 2017-04-25 00:00:00.000000000 Z
12
+ date: 2017-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -205,10 +205,12 @@ files:
205
205
  - lib/qti/v1/models/assessment.rb
206
206
  - lib/qti/v1/models/assessment_item.rb
207
207
  - lib/qti/v1/models/base.rb
208
+ - lib/qti/v1/models/choices/fill_blank_choice.rb
208
209
  - lib/qti/v1/models/choices/logical_identifier_choice.rb
209
210
  - lib/qti/v1/models/interactions.rb
210
211
  - lib/qti/v1/models/interactions/base_interaction.rb
211
212
  - lib/qti/v1/models/interactions/choice_interaction.rb
213
+ - lib/qti/v1/models/interactions/fill_blank_interaction.rb
212
214
  - lib/qti/v1/models/interactions/match_interaction.rb
213
215
  - lib/qti/v1/models/interactions/ordering_interaction.rb
214
216
  - lib/qti/v1/models/interactions/string_interaction.rb
@@ -216,14 +218,20 @@ files:
216
218
  - lib/qti/v2/models/assessment_item.rb
217
219
  - lib/qti/v2/models/assessment_test.rb
218
220
  - lib/qti/v2/models/base.rb
221
+ - lib/qti/v2/models/choices/gap_match_choice.rb
219
222
  - lib/qti/v2/models/choices/simple_associable_choice.rb
220
223
  - lib/qti/v2/models/choices/simple_choice.rb
221
224
  - lib/qti/v2/models/interactions.rb
222
225
  - lib/qti/v2/models/interactions/base_interaction.rb
223
226
  - lib/qti/v2/models/interactions/choice_interaction.rb
224
227
  - lib/qti/v2/models/interactions/extended_text_interaction.rb
228
+ - lib/qti/v2/models/interactions/gap_match_interaction.rb
225
229
  - lib/qti/v2/models/interactions/match_interaction.rb
226
230
  - lib/qti/v2/models/scoring_data.rb
231
+ - spec/fixtures/items_1.2/choice.xml
232
+ - spec/fixtures/items_1.2/essay.xml
233
+ - spec/fixtures/items_1.2/fib.xml
234
+ - spec/fixtures/items_1.2/fib_str.xml
227
235
  - spec/fixtures/items_1.2/matching.xml
228
236
  - spec/fixtures/items_1.2/multiple_answer.xml
229
237
  - spec/fixtures/items_1.2/multiple_choice.xml
@@ -409,8 +417,11 @@ files:
409
417
  - spec/lib/qti/models/manifest_spec.rb
410
418
  - spec/lib/qti/v1/models/assessment_item_spec.rb
411
419
  - spec/lib/qti/v1/models/assessment_spec.rb
420
+ - spec/lib/qti/v1/models/choices/fill_blank_choice_spec.rb
412
421
  - spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
413
422
  - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
423
+ - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
424
+ - spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
414
425
  - spec/lib/qti/v2/models/assessment_item_spec.rb
415
426
  - spec/lib/qti/v2/models/assessment_test_spec.rb
416
427
  - spec/lib/qti/v2/models/choices/simple_choice_spec.rb
@@ -444,6 +455,10 @@ signing_key:
444
455
  specification_version: 4
445
456
  summary: QTI 1.2 and 2.1 import and export models
446
457
  test_files:
458
+ - spec/fixtures/items_1.2/choice.xml
459
+ - spec/fixtures/items_1.2/essay.xml
460
+ - spec/fixtures/items_1.2/fib.xml
461
+ - spec/fixtures/items_1.2/fib_str.xml
447
462
  - spec/fixtures/items_1.2/matching.xml
448
463
  - spec/fixtures/items_1.2/multiple_answer.xml
449
464
  - spec/fixtures/items_1.2/multiple_choice.xml
@@ -629,8 +644,11 @@ test_files:
629
644
  - spec/lib/qti/models/manifest_spec.rb
630
645
  - spec/lib/qti/v1/models/assessment_item_spec.rb
631
646
  - spec/lib/qti/v1/models/assessment_spec.rb
647
+ - spec/lib/qti/v1/models/choices/fill_blank_choice_spec.rb
632
648
  - spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
633
649
  - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
650
+ - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
651
+ - spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
634
652
  - spec/lib/qti/v2/models/assessment_item_spec.rb
635
653
  - spec/lib/qti/v2/models/assessment_test_spec.rb
636
654
  - spec/lib/qti/v2/models/choices/simple_choice_spec.rb