qti 2.17.0 → 2.18.1

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