qti 2.17.0 → 2.18.1

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: 8ecae7fca00b12644bc2942b43f7fe47c6b959823c6b4b3a92e70193529b064f
4
- data.tar.gz: b9c35c2873033a84e0b673b58e4859d434de0ea0052a4891b38e448de034759d
3
+ metadata.gz: 336700103b4d3c146a3a14e388d0cc03b568aa7561401ffabede5cab0881559d
4
+ data.tar.gz: 29a3213732a5377ba14d133c06a5e545c3f16c25e1e19200d9f4dd98e1b98792
5
5
  SHA512:
6
- metadata.gz: c7ec25c08693f1b467121f8d528859c99ff58d57ad9eb55d44fb31871210a6d04f0184517db425ce62509ab3ea00700ea6203e1d4ae3323de4b4eaad3577f0a1
7
- data.tar.gz: aa5a807baa86a4554c52a83c0d2c16c7421c82ef1bb5a4c680cfc1e2f4cb9c5bbcea79936d1bc02984fb0bb74d6c4b6d44a8d1bdc0b8d7f4272f49fc27249018
6
+ metadata.gz: e31d581b78da6e468e3a8c5d188310585981b42c2a581f66d9938861c2fcdc701f86d8cbc99c13f3eaf6977e191237deb9904d50bd83159e6b780ffd89005846
7
+ data.tar.gz: 3ad4b4496777d9df2ef092ae2a9c9cbd7d19808c4939bbfdd63fdc1710faa85aeee2296c2209c8642fd15d9bf9ae417f5618f4858e13e4296075aaac65631c35
@@ -84,6 +84,27 @@ module Qti
84
84
  end
85
85
  end
86
86
 
87
+ def calculator_type
88
+ @calculator_type ||= begin
89
+ if calculator_type_metadata?
90
+ calculator_type_metadata_label = qti_metadata_children.children.find do |node|
91
+ node.text == 'calculator_type'
92
+ end
93
+ calculator_type_metadata_label.next.text
94
+ end
95
+ end
96
+ end
97
+
98
+ def calculator_type_metadata?
99
+ if @doc.at_xpath('.//xmlns:qtimetadata').present?
100
+ qti_metadata_children.children.find do |node|
101
+ node.text == 'calculator_type'
102
+ end.present?
103
+ else
104
+ false
105
+ end
106
+ end
107
+
87
108
  def decvar_maxvalue
88
109
  @doc.at_xpath('.//xmlns:decvar/@maxvalue')&.value&.to_i ||
89
110
  @doc.at_xpath('.//xmlns:decvar/@defaultval')&.value&.to_i || 0
@@ -40,6 +40,16 @@ module Qti
40
40
  @node.at_xpath('.//xmlns:render_choice/@shuffle')&.value.try(:downcase) == 'yes'
41
41
  end
42
42
 
43
+ def locked_choices
44
+ return [] unless shuffled?
45
+
46
+ @node.xpath('.//xmlns:response_label').filter_map.with_index do |answer_node, index|
47
+ is_locked = answer_node.attributes['lock']&.value&.downcase == 'yes'
48
+
49
+ is_locked ? index : nil
50
+ end
51
+ end
52
+
43
53
  def scoring_data_structs
44
54
  raise NotImplementedError
45
55
  end
data/lib/qti/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Qti
2
- VERSION = '2.17.0'.freeze
2
+ VERSION = '2.18.1'.freeze
3
3
  end
@@ -21,7 +21,7 @@
21
21
  </material>
22
22
  <response_lid ident="QUE_1004_RL" rcardinality="Single" rtiming="No">
23
23
  <render_choice shuffle="Yes">
24
- <response_label ident="QUE_1005_A1">
24
+ <response_label ident="QUE_1005_A1" lock="Yes">
25
25
  <material>
26
26
  <mattext texttype="text/html"><![CDATA[True]]></mattext>
27
27
  </material>
@@ -0,0 +1,90 @@
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
+ <itemmetadata>
7
+ <qtimetadata>
8
+ <qtimetadatafield>
9
+ <fieldlabel>question_type</fieldlabel>
10
+ <fieldentry>true_false_question</fieldentry>
11
+ </qtimetadatafield>
12
+ <qtimetadatafield>
13
+ <fieldlabel>assessment_question_identifierref</fieldlabel>
14
+ <fieldentry>iff205c7405d3b36bdca9b75b51198932</fieldentry>
15
+ </qtimetadatafield>
16
+ <qtimetadatafield>
17
+ <fieldlabel>calculator_type</fieldlabel>
18
+ <fieldentry>basic</fieldentry>
19
+ </qtimetadatafield>
20
+ </qtimetadata>
21
+ </itemmetadata>
22
+ <presentation>
23
+ <material>
24
+ <mattext texttype="text/html"><![CDATA[If I get a 3, I must have done something wrong. <img data-equation-content="sample equation" script="alert('bad')" align="bottom" alt="image.png" src="org0/images/image.png" border="0"/> <img script="alert('bad')" align="bottom" alt="image.png" src="org0/images/image.png" border="0"/>]]></mattext>
25
+ </material>
26
+ <response_lid ident="QUE_1004_RL" rcardinality="Single" rtiming="No">
27
+ <render_choice shuffle="Yes">
28
+ <response_label ident="QUE_1005_A1">
29
+ <material>
30
+ <mattext texttype="text/html"><![CDATA[True]]></mattext>
31
+ </material>
32
+ </response_label>
33
+ <response_label ident="QUE_1006_A2">
34
+ <material>
35
+ <mattext texttype="text/html"><![CDATA[False]]></mattext>
36
+ </material>
37
+ </response_label>
38
+ </render_choice>
39
+ </response_lid>
40
+ </presentation>
41
+ <resprocessing>
42
+ <outcomes>
43
+ <decvar vartype="Decimal" defaultval="0" varname="que_score"/>
44
+ </outcomes>
45
+ <respcondition>
46
+ <conditionvar>
47
+ <varequal respident="QUE_1004_RL">QUE_1005_A1</varequal>
48
+ </conditionvar>
49
+ <setvar varname="que_score" action="Add">0</setvar>
50
+ </respcondition>
51
+ <respcondition>
52
+ <conditionvar>
53
+ <varequal respident="QUE_1004_RL">QUE_1006_A2</varequal>
54
+ </conditionvar>
55
+ <setvar varname="que_score" action="Set">10.00</setvar>
56
+ <displayfeedback feedbacktype="Response" linkrefid="fb_QUE_1006_A2"/>
57
+ </respcondition>
58
+ </resprocessing>
59
+ <itemfeedback ident="general_fb">
60
+ <flow_mat>
61
+ <material>
62
+ <mattext texttype="text/html">&lt;p&gt;Neutral&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
63
+ </material>
64
+ </flow_mat>
65
+ </itemfeedback>
66
+ <itemfeedback ident="correct_fb">
67
+ <flow_mat>
68
+ <material>
69
+ <mattext texttype="text/html">&lt;p&gt;Correct&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
70
+ </material>
71
+ </flow_mat>
72
+ </itemfeedback>
73
+ <itemfeedback ident="general_incorrect_fb">
74
+ <flow_mat>
75
+ <material>
76
+ <mattext texttype="text/html">&lt;p&gt;Incorrect&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
77
+ </material>
78
+ </flow_mat>
79
+ </itemfeedback>
80
+ <itemfeedback ident="fb_QUE_1006_A2">
81
+ <flow_mat>
82
+ <material>
83
+ <mattext texttype="text/html">&lt;p&gt;Answer was Correct&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
84
+ </material>
85
+ </flow_mat>
86
+ </itemfeedback>
87
+ </item>
88
+ </section>
89
+ </assessment>
90
+ </questestinterop>
@@ -115,6 +115,26 @@ describe Qti::V1::Models::AssessmentItem do
115
115
  end
116
116
  end
117
117
 
118
+ describe '#calculator_type' do
119
+ let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
120
+ let(:assessment_item_refs) { test_object.assessment_items }
121
+ let(:loaded_class) { described_class.new(assessment_item_refs) }
122
+
123
+ context 'when it does not contain calculator_type metadata' do
124
+ let(:file_path) { File.join('spec', 'fixtures', 'items_1.2', 'true_false.xml') }
125
+ it 'returns nil' do
126
+ expect(loaded_class.calculator_type).to be_nil
127
+ end
128
+ end
129
+
130
+ context 'when it contains calculator_type metadata' do
131
+ let(:file_path) { File.join('spec', 'fixtures', 'items_1.2', 'true_false_with_calculator.xml') }
132
+ it 'returns the calculator_type value' do
133
+ expect(loaded_class.calculator_type).to eq 'basic'
134
+ end
135
+ end
136
+ end
137
+
118
138
  describe '#scoring_data_structs' do
119
139
  it 'grabs the rcardinality and scoring data value' do
120
140
  struct = loaded_class.send(:scoring_data_structs)
@@ -10,6 +10,12 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
10
10
  end
11
11
  end
12
12
 
13
+ shared_examples_for 'locked_choices' do
14
+ it 'returns locked choices setting' do
15
+ expect(loaded_class.locked_choices).to eq locked_choices_value
16
+ end
17
+ end
18
+
13
19
  shared_examples_for 'answers' do
14
20
  it 'returns the answers' do
15
21
  expect(loaded_class.answers.count).to eq answer_choices_count
@@ -27,10 +33,12 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
27
33
  context 'multiple_choice.xml' do
28
34
  let(:file_path) { File.join(fixtures_path, 'multiple_choice.xml') }
29
35
  let(:shuffle_value) { false }
36
+ let(:locked_choices_value) { [] }
30
37
  let(:answer_choices_count) { 5 }
31
38
  let(:meta_type) { nil }
32
39
 
33
40
  include_examples 'shuffled?'
41
+ include_examples 'locked_choices'
34
42
  include_examples 'answers'
35
43
  include_examples 'meta_type'
36
44
  end
@@ -38,10 +46,12 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
38
46
  context 'true_false.xml' do
39
47
  let(:file_path) { File.join(fixtures_path, 'true_false.xml') }
40
48
  let(:shuffle_value) { true }
49
+ let(:locked_choices_value) { [0] }
41
50
  let(:answer_choices_count) { 2 }
42
51
  let(:meta_type) { 'true_false_question' }
43
52
 
44
53
  include_examples 'shuffled?'
54
+ include_examples 'locked_choices'
45
55
  include_examples 'answers'
46
56
  include_examples 'meta_type'
47
57
  end
@@ -49,17 +59,21 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
49
59
  context 'multiple_answer.xml' do
50
60
  let(:file_path) { File.join(fixtures_path, 'multiple_answer.xml') }
51
61
  let(:shuffle_value) { false }
62
+ let(:locked_choices_value) { [] }
52
63
 
53
64
  include_examples 'shuffled?'
65
+ include_examples 'locked_choices'
54
66
  end
55
67
 
56
68
  context 'multiple_answer_canvas.xml' do
57
69
  let(:file_path) { File.join(fixtures_path, 'multiple_answer_canvas.xml') }
58
70
  let(:shuffle_value) { false }
71
+ let(:locked_choices_value) { [] }
59
72
  let(:answer_choices_count) { 4 }
60
73
  let(:meta_type) { 'multiple_answers_question' }
61
74
 
62
75
  include_examples 'shuffled?'
76
+ include_examples 'locked_choices'
63
77
  include_examples 'meta_type'
64
78
  end
65
79
 
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.17.0
4
+ version: 2.18.1
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: 2023-07-10 00:00:00.000000000 Z
15
+ date: 2023-07-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: actionview
@@ -428,6 +428,7 @@ files:
428
428
  - spec/fixtures/items_1.2/stimulus_with_child_item.xml
429
429
  - spec/fixtures/items_1.2/text.no.question.xml
430
430
  - spec/fixtures/items_1.2/true_false.xml
431
+ - spec/fixtures/items_1.2/true_false_with_calculator.xml
431
432
  - spec/fixtures/items_1.2/upload.xml
432
433
  - spec/fixtures/items_2.1/Example02-feedbackInline.xml
433
434
  - spec/fixtures/items_2.1/categorization.xml
@@ -795,6 +796,7 @@ test_files:
795
796
  - spec/fixtures/items_1.2/stimulus_with_child_item.xml
796
797
  - spec/fixtures/items_1.2/text.no.question.xml
797
798
  - spec/fixtures/items_1.2/true_false.xml
799
+ - spec/fixtures/items_1.2/true_false_with_calculator.xml
798
800
  - spec/fixtures/items_1.2/upload.xml
799
801
  - spec/fixtures/items_2.1/Example02-feedbackInline.xml
800
802
  - spec/fixtures/items_2.1/categorization.xml