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 +4 -4
- data/README.md +6 -8
- data/lib/qti.rb +2 -0
- data/lib/qti/v1/models/choices/fill_blank_choice.rb +27 -0
- data/lib/qti/v1/models/interactions/fill_blank_interaction.rb +77 -0
- data/lib/qti/v1/models/interactions/string_interaction.rb +8 -2
- data/lib/qti/v1/models/scoring_data.rb +5 -1
- data/lib/qti/v2/models/choices/gap_match_choice.rb +0 -0
- data/lib/qti/v2/models/interactions/gap_match_interaction.rb +34 -0
- data/spec/fixtures/items_1.2/choice.xml +209 -0
- data/spec/fixtures/items_1.2/essay.xml +25 -0
- data/spec/fixtures/items_1.2/fib.xml +46 -0
- data/spec/fixtures/items_1.2/fib_str.xml +46 -0
- data/spec/fixtures/test_qti_1.2/quiz.xml +46 -0
- data/spec/lib/qti/v1/models/choices/fill_blank_choice_spec.rb +23 -0
- data/spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb +1 -1
- data/spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb +64 -0
- data/spec/lib/qti/v1/models/interactions/string_interaction_spec.rb +17 -0
- data/spec/lib/qti_spec.rb +2 -2
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 09a38606bbf7afefc7b808dd338055b24375193b
|
4
|
+
data.tar.gz: 1dcad5866f62bd26d1dd48ab3f3ab6646de5eddc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
23
|
-
|
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
|
-
- `
|
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?
|
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
|
-
|
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
|
File without changes
|
@@ -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, '
|
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
|
data/spec/lib/qti_spec.rb
CHANGED
@@ -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
|
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.
|
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-
|
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
|