qti 0.2.16 → 0.3.16

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: 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