qti 2.31.0 → 2.32.0

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
  SHA256:
3
- metadata.gz: a08fc96f6a77de2160651785437e8ae12448f4b727daddccd06128715c51e5a8
4
- data.tar.gz: 8893790e36626b9f29c743d6f48c313b8c77f9294117686dadaec8c085755751
3
+ metadata.gz: 6e8fff7e4ff119789cc3fe6191731a48d6bcbf96939e2dec388284ab3701fd66
4
+ data.tar.gz: b0fd5f24cc43d4fb62c67a25320b03e7be63e95fa0a2fca78c840942ee8be44a
5
5
  SHA512:
6
- metadata.gz: df3ce562a0617d78c4f34d12d4682743dfb06d409283d6e88a01fb46278d8f815a8820082717da308521c01ba836bf26a98ec7ab73973080ac17ec7fd8ebaa49
7
- data.tar.gz: d3fe2fd6a969a72af91ebd5942a3d715075ed9439fefb157a2d791ac7923779fee38a980fdf1624cd3a83efb53cb092b86672c04f4a8b6628931908b217caaa9
6
+ metadata.gz: 7d42f847359a65a74f030d45fdebc0de54fda395f8962f92ac98c37acb83a381c305e902d94c9d01a3f216403b73f8fb413f8cb079c273821a5c630b7045f780
7
+ data.tar.gz: c6ce3d5b3dc05f7315ef8011b0766d54d197b9fce52618bfe1809e959d853b363c2906e835299c289bede21816883f622c5b0b40c40b5ef48a06d7b90cf3936b
@@ -3,6 +3,13 @@ module Qti
3
3
  module Models
4
4
  module Interactions
5
5
  class BaseFillBlankInteraction < BaseInteraction
6
+ # A per-answer comment is carried by a respcondition of the same shape
7
+ # as a scoring one, so only the conditions that award points can be
8
+ # read as correct answers.
9
+ SCORING_VAREQUAL_XPATH =
10
+ './/xmlns:resprocessing/xmlns:respcondition[xmlns:setvar]' \
11
+ '/xmlns:conditionvar/xmlns:varequal'.freeze
12
+
6
13
  def canvas_stem_items(item_prompt)
7
14
  item_prompt = sanitize_attributes(item_prompt)
8
15
  item_prompt.split(CANVAS_BLANK_REGEX).map.with_index do |stem_item, index|
@@ -112,7 +119,7 @@ module Qti
112
119
  def correct_answers
113
120
  correct_answers = {}
114
121
 
115
- node.xpath('.//xmlns:varequal').each do |correct_answer|
122
+ node.xpath(SCORING_VAREQUAL_XPATH).each do |correct_answer|
116
123
  correct_answers[correct_answer.attributes['respident']&.value] = correct_answer.text
117
124
  end
118
125
 
@@ -120,7 +127,7 @@ module Qti
120
127
  end
121
128
 
122
129
  def correct_choice_id(blank)
123
- node.xpath('.//xmlns:resprocessing/xmlns:respcondition/xmlns:conditionvar/xmlns:varequal')
130
+ node.xpath(SCORING_VAREQUAL_XPATH)
124
131
  .find { |varequal| varequal.attribute('respident').value == blank[:id] }&.text
125
132
  end
126
133
 
data/lib/qti/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Qti
2
- VERSION = '2.31.0'.freeze
2
+ VERSION = '2.32.0'.freeze
3
3
  end
@@ -74,12 +74,6 @@
74
74
  </conditionvar>
75
75
  <displayfeedback feedbacktype="Response" linkrefid="general_fb"/>
76
76
  </respcondition>
77
- <respcondition continue="Yes">
78
- <conditionvar>
79
- <varequal respident="response_color1">6548</varequal>
80
- </conditionvar>
81
- <displayfeedback feedbacktype="Response" linkrefid="6548_fb"/>
82
- </respcondition>
83
77
  <respcondition continue="Yes">
84
78
  <conditionvar>
85
79
  <varequal respident="response_color1">5550</varequal>
@@ -88,9 +82,9 @@
88
82
  </respcondition>
89
83
  <respcondition continue="Yes">
90
84
  <conditionvar>
91
- <varequal respident="response_color2">6951</varequal>
85
+ <varequal respident="response_color1">6548</varequal>
92
86
  </conditionvar>
93
- <displayfeedback feedbacktype="Response" linkrefid="6951_fb"/>
87
+ <displayfeedback feedbacktype="Response" linkrefid="6548_fb"/>
94
88
  </respcondition>
95
89
  <respcondition continue="Yes">
96
90
  <conditionvar>
@@ -98,6 +92,12 @@
98
92
  </conditionvar>
99
93
  <displayfeedback feedbacktype="Response" linkrefid="4500_fb"/>
100
94
  </respcondition>
95
+ <respcondition continue="Yes">
96
+ <conditionvar>
97
+ <varequal respident="response_color2">6951</varequal>
98
+ </conditionvar>
99
+ <displayfeedback feedbacktype="Response" linkrefid="6951_fb"/>
100
+ </respcondition>
101
101
  <respcondition>
102
102
  <conditionvar>
103
103
  <varequal respident="response_color1">6548</varequal>
@@ -0,0 +1,156 @@
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
+ <item ident="267f458a6d7d3f8aad007d415587ec4f" title="NQ Multiple Dropdowns Answer Feedback">
4
+ <itemmetadata>
5
+ <qtimetadata>
6
+ <qtimetadatafield>
7
+ <fieldlabel>question_type</fieldlabel>
8
+ <fieldentry>fill_in_multiple_blanks_question</fieldentry>
9
+ </qtimetadatafield>
10
+ <qtimetadatafield>
11
+ <fieldlabel>points_possible</fieldlabel>
12
+ <fieldentry>1.0</fieldentry>
13
+ </qtimetadatafield>
14
+ <qtimetadatafield>
15
+ <fieldlabel>original_answer_ids</fieldlabel>
16
+ <fieldentry>["7c011c63-8e76-42eb-86ab-531cd03f98a4", "087e23e8-e032-43b2-958b-3eae421c3e49", "f1046a5d-c476-450f-98bb-33997446d0b0", "18cebc2e-c102-4b51-ac52-72412ecf4619", "ac8c8556-2eb3-45ac-8994-9a04eff74614", "625d984e-d1c3-45f1-bcab-f3f8a847d1f0"]</fieldentry>
17
+ </qtimetadatafield>
18
+ <qtimetadatafield>
19
+ <fieldlabel>assessment_question_identifierref</fieldlabel>
20
+ <fieldentry>cd0dd757adb72497669129244b26ae71</fieldentry>
21
+ </qtimetadatafield>
22
+ </qtimetadata>
23
+ </itemmetadata>
24
+ <presentation>
25
+ <material>
26
+ <mattext texttype="text/html">&lt;div&gt;&lt;p&gt;&lt;span&gt;Roses are [68857282-90bc-4881-83b0-e811ab0502a6], violets are [6702826b-84db-422a-bdd5-f14e759fcb5e] mega [4fc61c7b-83f8-4eba-ae21-747fb76f6ae9]&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;</mattext>
27
+ </material>
28
+ <response_lid ident="response_68857282-90bc-4881-83b0-e811ab0502a6">
29
+ <material>
30
+ <mattext>aaa1</mattext>
31
+ </material>
32
+ <render_choice>
33
+ <response_label scoring_algorithm="Equivalence" answer_type="dropdown" ident="7c011c63-8e76-42eb-86ab-531cd03f98a4" position="1">
34
+ <material>
35
+ <mattext texttype="text/plain">aaa1</mattext>
36
+ </material>
37
+ </response_label>
38
+ <response_label scoring_algorithm="Equivalence" answer_type="dropdown" ident="087e23e8-e032-43b2-958b-3eae421c3e49" position="2">
39
+ <material>
40
+ <mattext texttype="text/plain">bbb1</mattext>
41
+ </material>
42
+ </response_label>
43
+ </render_choice>
44
+ </response_lid>
45
+ <response_lid ident="response_6702826b-84db-422a-bdd5-f14e759fcb5e">
46
+ <material>
47
+ <mattext>aaa2</mattext>
48
+ </material>
49
+ <render_choice>
50
+ <response_label scoring_algorithm="Equivalence" answer_type="dropdown" ident="f1046a5d-c476-450f-98bb-33997446d0b0" position="1">
51
+ <material>
52
+ <mattext texttype="text/plain">aaa2</mattext>
53
+ </material>
54
+ </response_label>
55
+ <response_label scoring_algorithm="Equivalence" answer_type="dropdown" ident="18cebc2e-c102-4b51-ac52-72412ecf4619" position="2">
56
+ <material>
57
+ <mattext texttype="text/plain">bbb2</mattext>
58
+ </material>
59
+ </response_label>
60
+ </render_choice>
61
+ </response_lid>
62
+ <response_lid ident="response_4fc61c7b-83f8-4eba-ae21-747fb76f6ae9">
63
+ <material>
64
+ <mattext>aaa3</mattext>
65
+ </material>
66
+ <render_choice>
67
+ <response_label scoring_algorithm="Equivalence" answer_type="dropdown" ident="ac8c8556-2eb3-45ac-8994-9a04eff74614" position="1">
68
+ <material>
69
+ <mattext texttype="text/plain">aaa3</mattext>
70
+ </material>
71
+ </response_label>
72
+ <response_label scoring_algorithm="Equivalence" answer_type="dropdown" ident="625d984e-d1c3-45f1-bcab-f3f8a847d1f0" position="2">
73
+ <material>
74
+ <mattext texttype="text/plain">bbb3</mattext>
75
+ </material>
76
+ </response_label>
77
+ </render_choice>
78
+ </response_lid>
79
+ </presentation>
80
+ <resprocessing>
81
+ <outcomes>
82
+ <decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
83
+ </outcomes>
84
+ <respcondition>
85
+ <conditionvar>
86
+ <varequal respident="response_68857282-90bc-4881-83b0-e811ab0502a6">7c011c63-8e76-42eb-86ab-531cd03f98a4</varequal>
87
+ </conditionvar>
88
+ <setvar action="Add" varname="SCORE">33.33</setvar>
89
+ </respcondition>
90
+ <respcondition>
91
+ <conditionvar>
92
+ <varequal respident="response_6702826b-84db-422a-bdd5-f14e759fcb5e">f1046a5d-c476-450f-98bb-33997446d0b0</varequal>
93
+ </conditionvar>
94
+ <setvar action="Add" varname="SCORE">33.33</setvar>
95
+ </respcondition>
96
+ <respcondition>
97
+ <conditionvar>
98
+ <varequal respident="response_4fc61c7b-83f8-4eba-ae21-747fb76f6ae9">ac8c8556-2eb3-45ac-8994-9a04eff74614</varequal>
99
+ </conditionvar>
100
+ <setvar action="Add" varname="SCORE">33.33</setvar>
101
+ </respcondition>
102
+ <respcondition continue="Yes">
103
+ <conditionvar>
104
+ <varequal respident="response_6702826b-84db-422a-bdd5-f14e759fcb5e">f1046a5d-c476-450f-98bb-33997446d0b0</varequal>
105
+ </conditionvar>
106
+ <displayfeedback feedbacktype="Response" linkrefid="f1046a5d-c476-450f-98bb-33997446d0b0_fb"/>
107
+ </respcondition>
108
+ <respcondition continue="Yes">
109
+ <conditionvar>
110
+ <varequal respident="response_4fc61c7b-83f8-4eba-ae21-747fb76f6ae9">ac8c8556-2eb3-45ac-8994-9a04eff74614</varequal>
111
+ </conditionvar>
112
+ <displayfeedback feedbacktype="Response" linkrefid="ac8c8556-2eb3-45ac-8994-9a04eff74614_fb"/>
113
+ </respcondition>
114
+ <respcondition continue="Yes">
115
+ <conditionvar>
116
+ <varequal respident="response_6702826b-84db-422a-bdd5-f14e759fcb5e">18cebc2e-c102-4b51-ac52-72412ecf4619</varequal>
117
+ </conditionvar>
118
+ <displayfeedback feedbacktype="Response" linkrefid="18cebc2e-c102-4b51-ac52-72412ecf4619_fb"/>
119
+ </respcondition>
120
+ <respcondition continue="Yes">
121
+ <conditionvar>
122
+ <varequal respident="response_4fc61c7b-83f8-4eba-ae21-747fb76f6ae9">625d984e-d1c3-45f1-bcab-f3f8a847d1f0</varequal>
123
+ </conditionvar>
124
+ <displayfeedback feedbacktype="Response" linkrefid="625d984e-d1c3-45f1-bcab-f3f8a847d1f0_fb"/>
125
+ </respcondition>
126
+ </resprocessing>
127
+ <itemfeedback ident="f1046a5d-c476-450f-98bb-33997446d0b0_fb">
128
+ <flow_mat>
129
+ <material>
130
+ <mattext texttype="text/html">&lt;p&gt;feedback for aaa2&lt;/p&gt;</mattext>
131
+ </material>
132
+ </flow_mat>
133
+ </itemfeedback>
134
+ <itemfeedback ident="ac8c8556-2eb3-45ac-8994-9a04eff74614_fb">
135
+ <flow_mat>
136
+ <material>
137
+ <mattext texttype="text/html">&lt;p&gt;feedback for blank3 aaa&lt;/p&gt;</mattext>
138
+ </material>
139
+ </flow_mat>
140
+ </itemfeedback>
141
+ <itemfeedback ident="18cebc2e-c102-4b51-ac52-72412ecf4619_fb">
142
+ <flow_mat>
143
+ <material>
144
+ <mattext texttype="text/html">&lt;p&gt;feedback for bbb2&lt;/p&gt;</mattext>
145
+ </material>
146
+ </flow_mat>
147
+ </itemfeedback>
148
+ <itemfeedback ident="625d984e-d1c3-45f1-bcab-f3f8a847d1f0_fb">
149
+ <flow_mat>
150
+ <material>
151
+ <mattext texttype="text/html">&lt;p&gt;feedback for blank3 bbb&lt;/p&gt;</mattext>
152
+ </material>
153
+ </flow_mat>
154
+ </itemfeedback>
155
+ </item>
156
+ </questestinterop>
@@ -59,6 +59,33 @@ describe Qti::V1::Models::Interactions::BaseFillBlankInteraction do
59
59
  end
60
60
 
61
61
  include_examples 'canvas_fib_responses'
62
+
63
+ # The item comments a wrong choice before the correct one, and canvas emits
64
+ # those comments ahead of the scoring conditions.
65
+ it 'names each blank after its correct choice, not a commented one' do
66
+ expect(loaded_class.blank_value('response_color1')).to eq('red')
67
+ expect(loaded_class.blank_value('response_color2')).to eq('blue')
68
+ end
69
+ end
70
+
71
+ context 'nq_multiple_dropdowns_answer_feedback.xml' do
72
+ let(:file_path) { File.join(fixtures_path, 'nq_multiple_dropdowns_answer_feedback.xml') }
73
+
74
+ # The item comments a wrong choice in the second and third blank after the
75
+ # correct one, and new quizzes emits those comments after the scoring
76
+ # conditions.
77
+ it 'maps each blank to its correct choice, not to a commented one' do
78
+ expect(loaded_class.correct_answer_map).to eq(
79
+ 'response_68857282-90bc-4881-83b0-e811ab0502a6' => '7c011c63-8e76-42eb-86ab-531cd03f98a4',
80
+ 'response_6702826b-84db-422a-bdd5-f14e759fcb5e' => 'f1046a5d-c476-450f-98bb-33997446d0b0',
81
+ 'response_4fc61c7b-83f8-4eba-ae21-747fb76f6ae9' => 'ac8c8556-2eb3-45ac-8994-9a04eff74614'
82
+ )
83
+ end
84
+
85
+ it 'names each blank after its correct choice' do
86
+ expect(loaded_class.blank_value('response_6702826b-84db-422a-bdd5-f14e759fcb5e')).to eq('aaa2')
87
+ expect(loaded_class.blank_value('response_4fc61c7b-83f8-4eba-ae21-747fb76f6ae9')).to eq('aaa3')
88
+ end
62
89
  end
63
90
 
64
91
  context 'canvas_multiple_fib.xml' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qti
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.31.0
4
+ version: 2.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Diaz
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2026-09-08 00:00:00.000000000 Z
15
+ date: 2026-09-23 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: actionview
@@ -409,6 +409,7 @@ files:
409
409
  - spec/fixtures/items_1.2/multiple_answer.xml
410
410
  - spec/fixtures/items_1.2/multiple_answer_canvas.xml
411
411
  - spec/fixtures/items_1.2/multiple_choice.xml
412
+ - spec/fixtures/items_1.2/nq_multiple_dropdowns_answer_feedback.xml
412
413
  - spec/fixtures/items_1.2/nq_multiple_fib_answer_types.xml
413
414
  - spec/fixtures/items_1.2/nq_multiple_fib_case_sensitive.xml
414
415
  - spec/fixtures/items_1.2/nq_multiple_fib_scoring_algorithms.xml
@@ -795,6 +796,7 @@ test_files:
795
796
  - spec/fixtures/items_1.2/multiple_answer.xml
796
797
  - spec/fixtures/items_1.2/multiple_answer_canvas.xml
797
798
  - spec/fixtures/items_1.2/multiple_choice.xml
799
+ - spec/fixtures/items_1.2/nq_multiple_dropdowns_answer_feedback.xml
798
800
  - spec/fixtures/items_1.2/nq_multiple_fib_answer_types.xml
799
801
  - spec/fixtures/items_1.2/nq_multiple_fib_case_sensitive.xml
800
802
  - spec/fixtures/items_1.2/nq_multiple_fib_scoring_algorithms.xml