qti 0.4.16 → 0.5.16
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 +4 -4
- data/lib/qti.rb +0 -1
- data/lib/qti/v1/models/interactions/match_interaction.rb +0 -6
- data/lib/qti/v2/models/choices/simple_associable_choice.rb +7 -0
- data/lib/qti/v2/models/choices/simple_choice.rb +1 -0
- data/lib/qti/v2/models/interactions.rb +7 -3
- data/lib/qti/v2/models/interactions/categorization_interaction.rb +69 -0
- data/lib/qti/v2/models/interactions/match_interaction.rb +29 -32
- data/lib/qti/v2/models/interactions/match_item_tag_processors/associate_interaction_tag_processor.rb +75 -0
- data/lib/qti/v2/models/interactions/match_item_tag_processors/match_interaction_tag_processor.rb +67 -0
- data/lib/qti/v2/models/scoring_data.rb +3 -3
- data/spec/fixtures/items_2.1/categorization.xml +35 -0
- data/spec/fixtures/items_2.1/match.xml +19 -26
- data/spec/fixtures/items_2.1/match2.xml +119 -0
- data/spec/lib/qti/v1/models/interactions/match_interaction_spec.rb +44 -0
- data/spec/lib/qti/v2/models/assessment_item_spec.rb +0 -24
- data/spec/lib/qti/v2/models/choices/simple_associable_choice_spec.rb +21 -0
- data/spec/lib/qti/v2/models/interactions/categorization_interaction_spec.rb +23 -0
- data/spec/lib/qti/v2/models/interactions/match_interaction_spec.rb +71 -7
- data/spec/support/monkey_patches.rb +14 -0
- metadata +31 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4883be4fd0b3c4f0f662068c6b7d42e2cfee0645
|
4
|
+
data.tar.gz: 262e1f6ad0e5d3d80c844d30084bcb6eb461fcf0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: beddd3cfcec82686646a5635773414d32502f58ea993719afb175f4ca9adaeed7ee9f6a622016618497a0a6f474915a0ff205d80fd0984f610ce1093675270ba
|
7
|
+
data.tar.gz: 81bc3c599b5c15b0c1437d1abf2fe985676d1f9d2ec2e433f5be5d1cac458822a113eb1e5e6290d995315a05984cf541a89453e4a900597bd5fc5d799762184b
|
data/lib/qti.rb
CHANGED
@@ -62,7 +62,6 @@ require 'qti/v1/models/choices/fill_blank_choice'
|
|
62
62
|
require 'qti/v1/models/scoring_data'
|
63
63
|
|
64
64
|
require 'qti/v2/models/base'
|
65
|
-
require 'qti/v2/models/interactions/base_interaction'
|
66
65
|
require 'qti/v2/models/choices/simple_choice'
|
67
66
|
require 'qti/v2/models/choices/simple_associable_choice'
|
68
67
|
require 'qti/v2/models/choices/gap_match_choice'
|
@@ -3,18 +3,12 @@ module Qti
|
|
3
3
|
module Models
|
4
4
|
module Interactions
|
5
5
|
class MatchInteraction < BaseInteraction
|
6
|
-
attr_reader :node
|
7
|
-
|
8
6
|
def self.matches(node)
|
9
7
|
matches = node.xpath('.//xmlns:response_lid')
|
10
8
|
return false if matches.count <= 1
|
11
9
|
new(node)
|
12
10
|
end
|
13
11
|
|
14
|
-
def initialize(node)
|
15
|
-
@node = node
|
16
|
-
end
|
17
|
-
|
18
12
|
def answers
|
19
13
|
@answers ||= answer_nodes.map do |node|
|
20
14
|
V1::Models::Choices::LogicalIdentifierChoice.new(node)
|
@@ -5,6 +5,13 @@ module Qti
|
|
5
5
|
module Models
|
6
6
|
module Choices
|
7
7
|
class SimpleAssociableChoice < SimpleChoice
|
8
|
+
def match_max
|
9
|
+
@_match_max ||= @node.attributes['matchMax'].value || 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def match_min
|
13
|
+
@_match_min ||= @node.attributes['matchMin'].value || 0
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
10
17
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'qti/v2/models/interactions/base_interaction'
|
2
2
|
Dir["#{__dir__}/interactions/*.rb"].each { |f| load f }
|
3
3
|
|
4
4
|
module Qti
|
@@ -7,8 +7,6 @@ module Qti
|
|
7
7
|
module Interactions
|
8
8
|
# This one finds the correct parsing model based on the provided xml node
|
9
9
|
def self.interaction_model(node)
|
10
|
-
subclasses = constants.map { |c| const_get(c) }
|
11
|
-
|
12
10
|
# Check for matches
|
13
11
|
matches = subclasses.each_with_object([]) do |interaction_class, result|
|
14
12
|
match = interaction_class.matches(node)
|
@@ -19,6 +17,12 @@ module Qti
|
|
19
17
|
|
20
18
|
matches.first
|
21
19
|
end
|
20
|
+
|
21
|
+
def self.subclasses
|
22
|
+
constants.map { |c| const_get(c) }
|
23
|
+
.reject { |c| c.name =~ /Implementations|Base/ }
|
24
|
+
.select { |c| c.name =~ /^Qti::V2.*Interaction$/ }
|
25
|
+
end
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative 'match_interaction'
|
2
|
+
|
3
|
+
module Qti
|
4
|
+
module V2
|
5
|
+
module Models
|
6
|
+
module Interactions
|
7
|
+
class CategorizationInteraction < MatchInteraction
|
8
|
+
def self.matches(node)
|
9
|
+
if use_match_interaction_implementation?(node)
|
10
|
+
new(node, MatchItemTagProcesssors::MatchInteractionTagProcessor)
|
11
|
+
else
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.use_match_interaction_implementation?(node)
|
17
|
+
MatchItemTagProcesssors::MatchInteractionTagProcessor.match_interaction_tag?(node) &&
|
18
|
+
MatchItemTagProcesssors::MatchInteractionTagProcessor.number_of_questions_per_answer(node)
|
19
|
+
.any? { |n| n != 1 }
|
20
|
+
end
|
21
|
+
|
22
|
+
def scoring_data_structs
|
23
|
+
questions_categories_choices_hash.map do |category_choice, questions_choices|
|
24
|
+
ScoringData.new(category_choice.text, 'directedPair',
|
25
|
+
id: node_identifier(category_choice),
|
26
|
+
questions_ids: questions_choices.map { |q| node_identifier(q) })
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def questions_categories_choices_hash
|
33
|
+
category_choices.each_with_object({}) do |category_choice, hash|
|
34
|
+
hash[category_choice] = questions_for_category_choice(category_choice)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def questions_for_category_choice(choice)
|
39
|
+
choice_identifier = node_identifier(choice)
|
40
|
+
category_questions_ids = implementation.question_response_pairs
|
41
|
+
.select { |_, category_id| category_id == choice_identifier }
|
42
|
+
.map { |question_id, _| question_id }
|
43
|
+
question_choices.select { |q| category_questions_ids.include? node_identifier(q) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def category_choices
|
47
|
+
@_category_choices ||= implementation.choices.select { |c| categories_ids.include? node_identifier(c) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def question_choices
|
51
|
+
@_question_choices ||= implementation.choices.select { |c| questions_ids.include? node_identifier(c) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def categories_ids
|
55
|
+
@_categories_ids ||= implementation.question_response_pairs.map { |_, category_id| category_id }.uniq
|
56
|
+
end
|
57
|
+
|
58
|
+
def questions_ids
|
59
|
+
@_questions_ids ||= implementation.question_response_pairs.map { |question_id, _| question_id }.uniq
|
60
|
+
end
|
61
|
+
|
62
|
+
def node_identifier(node)
|
63
|
+
node.attributes['identifier'].value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,51 +1,48 @@
|
|
1
|
+
require_relative 'match_item_tag_processors/match_interaction_tag_processor'
|
2
|
+
require_relative 'match_item_tag_processors/associate_interaction_tag_processor'
|
3
|
+
|
1
4
|
module Qti
|
2
5
|
module V2
|
3
6
|
module Models
|
4
7
|
module Interactions
|
5
8
|
class MatchInteraction < BaseInteraction
|
6
|
-
|
7
|
-
matches = node.xpath('//xmlns:matchInteraction')
|
8
|
-
return false if matches.count != 1
|
9
|
-
new(node)
|
10
|
-
end
|
9
|
+
extend Forwardable
|
11
10
|
|
12
|
-
|
13
|
-
node.xpath('.//xmlns:correctResponse//xmlns:value')
|
14
|
-
.map { |value| value.content.split.first }
|
15
|
-
.map { |id| { id: id, question_body: choices_by_identifier[id].content } }
|
16
|
-
end
|
11
|
+
attr_reader :implementation
|
17
12
|
|
18
|
-
def
|
19
|
-
node
|
13
|
+
def initialize(node, implementation)
|
14
|
+
super(node)
|
15
|
+
@implementation = implementation.new(node)
|
20
16
|
end
|
21
17
|
|
22
|
-
|
23
|
-
answer_nodes.map { |node| Choices::SimpleAssociableChoice.new(node) }
|
24
|
-
end
|
18
|
+
def_delegators :@implementation, :answers, :questions, :shuffled?
|
25
19
|
|
26
20
|
def scoring_data_structs
|
27
|
-
|
28
|
-
value.content.split
|
29
|
-
end
|
30
|
-
question_response_id_mapping = Hash[question_response_pairs]
|
31
|
-
data = question_response_id_mapping.reduce({}) do |acc, pair|
|
32
|
-
question_id, answer_id = pair
|
33
|
-
acc.update question_id => choices_by_identifier[answer_id].content
|
34
|
-
end
|
35
|
-
[ScoringData.new(data, 'directedPair')]
|
21
|
+
implementation.scoring_data_structs
|
36
22
|
end
|
37
23
|
|
38
|
-
|
24
|
+
def self.matches(node)
|
25
|
+
implementation =
|
26
|
+
if use_associate_interaction_implementation?(node)
|
27
|
+
MatchItemTagProcesssors::AssociateInteractionTagProcessor
|
28
|
+
elsif use_match_interaction_implementation?(node)
|
29
|
+
MatchItemTagProcesssors::MatchInteractionTagProcessor
|
30
|
+
end
|
31
|
+
|
32
|
+
return false unless implementation.present?
|
33
|
+
new(node, implementation)
|
34
|
+
end
|
39
35
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
36
|
+
def self.use_associate_interaction_implementation?(node)
|
37
|
+
MatchItemTagProcesssors::AssociateInteractionTagProcessor.associate_interaction_tag?(node) &&
|
38
|
+
MatchItemTagProcesssors::AssociateInteractionTagProcessor.number_of_questions_per_answer(node)
|
39
|
+
.all? { |n| n == 1 }
|
45
40
|
end
|
46
41
|
|
47
|
-
def
|
48
|
-
|
42
|
+
def self.use_match_interaction_implementation?(node)
|
43
|
+
MatchItemTagProcesssors::MatchInteractionTagProcessor.match_interaction_tag?(node) &&
|
44
|
+
MatchItemTagProcesssors::MatchInteractionTagProcessor.number_of_questions_per_answer(node)
|
45
|
+
.all? { |n| n == 1 }
|
49
46
|
end
|
50
47
|
end
|
51
48
|
end
|
data/lib/qti/v2/models/interactions/match_item_tag_processors/associate_interaction_tag_processor.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Qti
|
2
|
+
module V2
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
module MatchItemTagProcesssors
|
6
|
+
class AssociateInteractionTagProcessor < Interactions::BaseInteraction
|
7
|
+
def self.associate_interaction_tag?(node)
|
8
|
+
node.xpath('.//xmlns:associateInteraction').count == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.number_of_questions_per_answer(node)
|
12
|
+
question_response_pairs = node.xpath('.//xmlns:correctResponse//xmlns:value').map do |value|
|
13
|
+
value.content.split
|
14
|
+
end
|
15
|
+
count = Hash.new { 0 }
|
16
|
+
question_response_pairs.reduce(count) do |acc, pair|
|
17
|
+
acc.update pair.last => acc[pair.last] + 1
|
18
|
+
end
|
19
|
+
count.values
|
20
|
+
end
|
21
|
+
|
22
|
+
def shuffled?
|
23
|
+
node.at_xpath('.//xmlns:associateInteraction').attributes['shuffle']&.value.try(:downcase) == 'true'
|
24
|
+
end
|
25
|
+
|
26
|
+
def questions
|
27
|
+
questions_ids.map { |id| { id: id, question_body: choices_by_identifier[id].content } }
|
28
|
+
end
|
29
|
+
|
30
|
+
def answers
|
31
|
+
answer_nodes.map { |node| Choices::SimpleAssociableChoice.new(node) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def scoring_data_structs
|
35
|
+
question_response_pairs.map do |question_id, answer_id|
|
36
|
+
content = choices_by_identifier[answer_id].content
|
37
|
+
ScoringData.new(content, 'Pair', id: answer_id, question_id: question_id)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def choices_by_identifier
|
44
|
+
@_choices_by_identifier ||= choices.reduce({}) do |acc, choice|
|
45
|
+
acc.update choice.attributes['identifier'].value => choice
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def answer_nodes
|
50
|
+
@_answer_nodes ||= choices.select { |c| answer_ids.include?(c.attributes['identifier'].value) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def questions_ids
|
54
|
+
@_questions_ids ||= question_response_pairs.map { |question_id, _| question_id }
|
55
|
+
end
|
56
|
+
|
57
|
+
def answer_ids
|
58
|
+
@_answer_ids ||= question_response_pairs.map { |_, answer_id| answer_id }
|
59
|
+
end
|
60
|
+
|
61
|
+
def choices
|
62
|
+
node.xpath('.//xmlns:simpleAssociableChoice')
|
63
|
+
end
|
64
|
+
|
65
|
+
def question_response_pairs
|
66
|
+
node.xpath('.//xmlns:correctResponse//xmlns:value').map do |value|
|
67
|
+
value.content.split
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/qti/v2/models/interactions/match_item_tag_processors/match_interaction_tag_processor.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Qti
|
2
|
+
module V2
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
module MatchItemTagProcesssors
|
6
|
+
class MatchInteractionTagProcessor < Interactions::BaseInteraction
|
7
|
+
def self.match_interaction_tag?(node)
|
8
|
+
node.xpath('//xmlns:matchInteraction').count == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.number_of_questions_per_answer(node)
|
12
|
+
correct_categories = node.xpath('.//xmlns:correctResponse//xmlns:value')
|
13
|
+
.map { |value| value.content.split.last }
|
14
|
+
|
15
|
+
correct_categories.each_with_object(Hash.new(0)) { |category_id, counts| counts[category_id] += 1 }.values
|
16
|
+
end
|
17
|
+
|
18
|
+
def questions
|
19
|
+
questions_ids.map { |id| { id: id, question_body: choices_by_identifier[id].content } }
|
20
|
+
end
|
21
|
+
|
22
|
+
def shuffled?
|
23
|
+
node.at_xpath('.//xmlns:matchInteraction').attributes['shuffle']&.value.try(:downcase) == 'true'
|
24
|
+
end
|
25
|
+
|
26
|
+
def answers
|
27
|
+
answer_nodes.map { |node| Choices::SimpleAssociableChoice.new(node) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def scoring_data_structs
|
31
|
+
question_response_pairs.map do |question_id, answer_id|
|
32
|
+
content = choices_by_identifier[answer_id].content
|
33
|
+
ScoringData.new(content, 'Pair', id: answer_id, question_id: question_id)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def choices
|
38
|
+
node.xpath('.//xmlns:simpleAssociableChoice')
|
39
|
+
end
|
40
|
+
|
41
|
+
def question_response_pairs
|
42
|
+
node.xpath('.//xmlns:correctResponse//xmlns:value').map do |value|
|
43
|
+
value.content.split
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def questions_ids
|
50
|
+
@_questions_ids ||= question_response_pairs.map { |question_id, _| question_id }
|
51
|
+
end
|
52
|
+
|
53
|
+
def choices_by_identifier
|
54
|
+
@choices_by_identifier ||= choices.reduce({}) do |acc, choice|
|
55
|
+
acc.update choice.attributes['identifier'].value => choice
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def answer_nodes
|
60
|
+
node.xpath('.//xmlns:matchInteraction//xmlns:simpleMatchSet[2]//xmlns:simpleAssociableChoice')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Qti
|
2
2
|
module V2
|
3
3
|
module Models
|
4
|
-
ScoringData = Struct.new(:values, :type, :id, :case) do
|
5
|
-
def initialize(values,
|
6
|
-
super(values,
|
4
|
+
ScoringData = Struct.new(:values, :type, :id, :case, :question_id, :questions_ids) do
|
5
|
+
def initialize(values, type, options={})
|
6
|
+
super(values, type, options[:id], options[:case], options[:question_id], options[:questions_ids])
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p2 http://www.imsglobal.org/xsd/qti/qtiv2p2/imsqti_v2p2.xsd" identifier="match" title="Characters and Plays" adaptive="false" timeDependent="false">
|
3
|
+
<responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="directedPair">
|
4
|
+
<correctResponse>
|
5
|
+
<value>C R</value>
|
6
|
+
<value>D M</value>
|
7
|
+
<value>L M</value>
|
8
|
+
<value>P T</value>
|
9
|
+
</correctResponse>
|
10
|
+
<mapping defaultValue="0">
|
11
|
+
<mapEntry mapKey="C R" mappedValue="1"/>
|
12
|
+
<mapEntry mapKey="D M" mappedValue="0.5"/>
|
13
|
+
<mapEntry mapKey="L M" mappedValue="0.5"/>
|
14
|
+
<mapEntry mapKey="P T" mappedValue="1"/>
|
15
|
+
</mapping>
|
16
|
+
</responseDeclaration>
|
17
|
+
<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"/>
|
18
|
+
<itemBody>
|
19
|
+
<matchInteraction responseIdentifier="RESPONSE" shuffle="true" maxAssociations="4">
|
20
|
+
<prompt>Match the following characters to the Shakespeare play they appeared in:</prompt>
|
21
|
+
<simpleMatchSet>
|
22
|
+
<simpleAssociableChoice identifier="C" matchMax="1">Capulet</simpleAssociableChoice>
|
23
|
+
<simpleAssociableChoice identifier="D" matchMax="1">Demetrius</simpleAssociableChoice>
|
24
|
+
<simpleAssociableChoice identifier="L" matchMax="1">Lysander</simpleAssociableChoice>
|
25
|
+
<simpleAssociableChoice identifier="P" matchMax="1">Prospero</simpleAssociableChoice>
|
26
|
+
</simpleMatchSet>
|
27
|
+
<simpleMatchSet>
|
28
|
+
<simpleAssociableChoice identifier="M" matchMax="4">A Midsummer-Night's Dream</simpleAssociableChoice>
|
29
|
+
<simpleAssociableChoice identifier="R" matchMax="4">Romeo and Juliet</simpleAssociableChoice>
|
30
|
+
<simpleAssociableChoice identifier="T" matchMax="4">The Tempest</simpleAssociableChoice>
|
31
|
+
</simpleMatchSet>
|
32
|
+
</matchInteraction>
|
33
|
+
</itemBody>
|
34
|
+
<responseProcessing template="http://www.imsglobal.org/question/qti_v2p2/rptemplates/map_response"/>
|
35
|
+
</assessmentItem>
|
@@ -1,35 +1,28 @@
|
|
1
|
-
<?xml version="1.0" encoding="
|
2
|
-
<assessmentItem xmlns="http://www.imsglobal.org/xsd/
|
3
|
-
<responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 http://www.imsglobal.org/xsd/qti/qtiv2p1/imsqti_v2p1p2.xsd" identifier="associate" title="Shakespearian Rivals" adaptive="false" timeDependent="false">
|
3
|
+
<responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="pair">
|
4
4
|
<correctResponse>
|
5
|
-
<value>
|
6
|
-
<value>
|
7
|
-
<value>L
|
8
|
-
<value>P T</value>
|
5
|
+
<value>A P</value>
|
6
|
+
<value>C M</value>
|
7
|
+
<value>D L</value>
|
9
8
|
</correctResponse>
|
10
9
|
<mapping defaultValue="0">
|
11
|
-
<mapEntry mapKey="
|
12
|
-
<mapEntry mapKey="
|
13
|
-
<mapEntry mapKey="L
|
14
|
-
<mapEntry mapKey="P T" mappedValue="1"/>
|
10
|
+
<mapEntry mapKey="A P" mappedValue="2"/>
|
11
|
+
<mapEntry mapKey="C M" mappedValue="1"/>
|
12
|
+
<mapEntry mapKey="D L" mappedValue="1"/>
|
15
13
|
</mapping>
|
16
14
|
</responseDeclaration>
|
17
15
|
<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"/>
|
18
16
|
<itemBody>
|
19
|
-
<
|
20
|
-
<prompt>
|
21
|
-
<
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
</
|
27
|
-
|
28
|
-
<simpleAssociableChoice identifier="M" matchMax="4">A Midsummer-Night's Dream</simpleAssociableChoice>
|
29
|
-
<simpleAssociableChoice identifier="R" matchMax="4">Romeo and Juliet</simpleAssociableChoice>
|
30
|
-
<simpleAssociableChoice identifier="T" matchMax="4">The Tempest</simpleAssociableChoice>
|
31
|
-
</simpleMatchSet>
|
32
|
-
</matchInteraction>
|
17
|
+
<associateInteraction responseIdentifier="RESPONSE" shuffle="true" maxAssociations="3">
|
18
|
+
<prompt>Hidden in this list of characters from famous Shakespeare plays are three pairs of rivals. Can you match each character to his adversary?</prompt>
|
19
|
+
<simpleAssociableChoice identifier="A" matchMax="1">Antonio</simpleAssociableChoice>
|
20
|
+
<simpleAssociableChoice identifier="C" matchMax="1">Capulet</simpleAssociableChoice>
|
21
|
+
<simpleAssociableChoice identifier="D" matchMax="1">Demetrius</simpleAssociableChoice>
|
22
|
+
<simpleAssociableChoice identifier="L" matchMax="1">Lysander</simpleAssociableChoice>
|
23
|
+
<simpleAssociableChoice identifier="M" matchMax="1">Montague</simpleAssociableChoice>
|
24
|
+
<simpleAssociableChoice identifier="P" matchMax="1">Prospero</simpleAssociableChoice>
|
25
|
+
</associateInteraction>
|
33
26
|
</itemBody>
|
34
|
-
<responseProcessing template="http://www.imsglobal.org/question/
|
27
|
+
<responseProcessing template="http://www.imsglobal.org/question/qti_v2p1/rptemplates/map_response"/>
|
35
28
|
</assessmentItem>
|
@@ -0,0 +1,119 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!--This file was created using: Onyx Editor, Version 3.4.3 (Full, licensed version), (c)2012 BPS Bildungsportal Sachsen GmbH-->
|
3
|
+
<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p2 http://www.imsglobal.org/xsd/qti/qtiv2p2/imsqti_v2p2.xsd" identifier="Matchsingle_143114773" title="match (single)" adaptive="false" timeDependent="false">
|
4
|
+
<responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="directedPair">
|
5
|
+
<correctResponse>
|
6
|
+
<value>Match28433682 Match2675678</value>
|
7
|
+
<value>Match7191791 Match9372581</value>
|
8
|
+
<value>Match20473010 Match22744006</value>
|
9
|
+
<value>Match6429655 Match17943221</value>
|
10
|
+
</correctResponse>
|
11
|
+
</responseDeclaration>
|
12
|
+
<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float">
|
13
|
+
<defaultValue>
|
14
|
+
<value>0.0</value>
|
15
|
+
</defaultValue>
|
16
|
+
</outcomeDeclaration>
|
17
|
+
<outcomeDeclaration identifier="MAXSCORE" cardinality="single" baseType="float">
|
18
|
+
<defaultValue>
|
19
|
+
<value>1.0</value>
|
20
|
+
</defaultValue>
|
21
|
+
</outcomeDeclaration>
|
22
|
+
<outcomeDeclaration identifier="FEEDBACKBASIC" cardinality="single" baseType="identifier">
|
23
|
+
<defaultValue>
|
24
|
+
<value>empty</value>
|
25
|
+
</defaultValue>
|
26
|
+
</outcomeDeclaration>
|
27
|
+
<outcomeDeclaration identifier="FEEDBACKMODAL" cardinality="multiple" baseType="identifier" view="testConstructor"/>
|
28
|
+
<itemBody>
|
29
|
+
<div>Der wichtigste, größte und einzig schiffbare Fluss des Bundeslandes Sachsens ist die
|
30
|
+
Elbe. Die verschiedene Quellflüsse der Elbe durchziehen die sächsischen Städte.
|
31
|
+
<br/>Ordne anhand des Flusslaufs die Quellflüsse den gegebenen Städten zu.</div>
|
32
|
+
<matchInteraction responseIdentifier="RESPONSE" shuffle="true" maxAssociations="0">
|
33
|
+
<simpleMatchSet>
|
34
|
+
<simpleAssociableChoice identifier="Match28433682" fixed="false" matchMin="1" matchMax="1">Weißeritz</simpleAssociableChoice>
|
35
|
+
<simpleAssociableChoice identifier="Match7191791" fixed="false" matchMin="1" matchMax="1">Mulde</simpleAssociableChoice>
|
36
|
+
<simpleAssociableChoice identifier="Match20473010" fixed="false" matchMin="1" matchMax="1">Saale</simpleAssociableChoice>
|
37
|
+
<simpleAssociableChoice identifier="Match6429655" fixed="false" matchMin="1" matchMax="1">Spree</simpleAssociableChoice>
|
38
|
+
</simpleMatchSet>
|
39
|
+
<simpleMatchSet>
|
40
|
+
<simpleAssociableChoice identifier="Match2675678" fixed="false" matchMin="1" matchMax="1">Dresden</simpleAssociableChoice>
|
41
|
+
<simpleAssociableChoice identifier="Match9372581" fixed="false" matchMin="1" matchMax="1">Leipzig</simpleAssociableChoice>
|
42
|
+
<simpleAssociableChoice identifier="Match22744006" fixed="false" matchMin="1" matchMax="1">Halle</simpleAssociableChoice>
|
43
|
+
<simpleAssociableChoice identifier="Match17943221" fixed="false" matchMin="1" matchMax="1">Bautzen</simpleAssociableChoice>
|
44
|
+
</simpleMatchSet>
|
45
|
+
</matchInteraction>
|
46
|
+
</itemBody>
|
47
|
+
<responseProcessing>
|
48
|
+
<responseCondition>
|
49
|
+
<responseIf>
|
50
|
+
<isNull>
|
51
|
+
<variable identifier="RESPONSE"/>
|
52
|
+
</isNull>
|
53
|
+
<setOutcomeValue identifier="FEEDBACKBASIC">
|
54
|
+
<baseValue baseType="identifier">empty</baseValue>
|
55
|
+
</setOutcomeValue>
|
56
|
+
</responseIf>
|
57
|
+
<responseElseIf>
|
58
|
+
<match>
|
59
|
+
<variable identifier="RESPONSE"/>
|
60
|
+
<correct identifier="RESPONSE"/>
|
61
|
+
</match>
|
62
|
+
<setOutcomeValue identifier="SCORE">
|
63
|
+
<sum>
|
64
|
+
<variable identifier="SCORE"/>
|
65
|
+
<variable identifier="MAXSCORE"/>
|
66
|
+
</sum>
|
67
|
+
</setOutcomeValue>
|
68
|
+
<setOutcomeValue identifier="FEEDBACKBASIC">
|
69
|
+
<baseValue baseType="identifier">correct</baseValue>
|
70
|
+
</setOutcomeValue>
|
71
|
+
</responseElseIf>
|
72
|
+
<responseElse>
|
73
|
+
<setOutcomeValue identifier="FEEDBACKBASIC">
|
74
|
+
<baseValue baseType="identifier">incorrect</baseValue>
|
75
|
+
</setOutcomeValue>
|
76
|
+
</responseElse>
|
77
|
+
</responseCondition>
|
78
|
+
<responseCondition>
|
79
|
+
<responseIf>
|
80
|
+
<and>
|
81
|
+
<match>
|
82
|
+
<baseValue baseType="identifier">correct</baseValue>
|
83
|
+
<variable identifier="FEEDBACKBASIC"/>
|
84
|
+
</match>
|
85
|
+
</and>
|
86
|
+
<setOutcomeValue identifier="FEEDBACKMODAL">
|
87
|
+
<multiple>
|
88
|
+
<variable identifier="FEEDBACKMODAL"/>
|
89
|
+
<baseValue baseType="identifier">FEEDBACK_27448254</baseValue>
|
90
|
+
</multiple>
|
91
|
+
</setOutcomeValue>
|
92
|
+
</responseIf>
|
93
|
+
</responseCondition>
|
94
|
+
<responseCondition>
|
95
|
+
<responseIf>
|
96
|
+
<and>
|
97
|
+
<match>
|
98
|
+
<baseValue baseType="identifier">incorrect</baseValue>
|
99
|
+
<variable identifier="FEEDBACKBASIC"/>
|
100
|
+
</match>
|
101
|
+
</and>
|
102
|
+
<setOutcomeValue identifier="FEEDBACKMODAL">
|
103
|
+
<multiple>
|
104
|
+
<variable identifier="FEEDBACKMODAL"/>
|
105
|
+
<baseValue baseType="identifier">FEEDBACK_16479834</baseValue>
|
106
|
+
</multiple>
|
107
|
+
</setOutcomeValue>
|
108
|
+
</responseIf>
|
109
|
+
</responseCondition>
|
110
|
+
</responseProcessing>
|
111
|
+
<modalFeedback identifier="FEEDBACK_27448254" outcomeIdentifier="FEEDBACKMODAL" showHide="show" title="Richtig!">Die Elbe durchzieht den Freistaat von Südosten nach Nordwesten. Wichtige
|
112
|
+
Quellflüsse sind die Mulde, die Weißeritz, die Zschopau, die Weiße Elster und die Spree,
|
113
|
+
deren allgemeine Fließrichtung Norden ist und die ebenfalls zum Fluss-System der Elbe
|
114
|
+
gehören.</modalFeedback>
|
115
|
+
<modalFeedback identifier="FEEDBACK_16479834" outcomeIdentifier="FEEDBACKMODAL" showHide="show" title="Leider Falsch!">Die Elbe durchzieht den Freistaat von Südosten nach Nordwesten.
|
116
|
+
Wichtige Quellflüsse sind die Mulde, die Weißeritz, die Zschopau, die Weiße Elster und die
|
117
|
+
Spree, deren allgemeine Fließrichtung Norden ist und die ebenfalls zum Fluss-System der Elbe
|
118
|
+
gehören.</modalFeedback>
|
119
|
+
</assessmentItem>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Qti::V1::Models::Interactions::MatchInteraction do
|
4
|
+
let(:file) { File.join('spec', 'fixtures', 'items_1.2', 'matching.xml') }
|
5
|
+
let(:assessment) { Qti::V1::Models::Assessment.from_path!(file) }
|
6
|
+
let(:item) { assessment.assessment_items.first }
|
7
|
+
subject { described_class.new(item) }
|
8
|
+
|
9
|
+
it 'returns shuffle setting' do
|
10
|
+
expect(subject.shuffled?).to eq false
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns the answers' do
|
14
|
+
expect(subject.answers.map(&:item_body)).to eq(
|
15
|
+
['Magnify up to about 400 times. Sometimes requires colored staining of cells.',
|
16
|
+
"Uses a beam of electrons. Can provide details of cells' internal structure.",
|
17
|
+
'A distractor answer.']
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.matches' do
|
22
|
+
it 'matches the item in file' do
|
23
|
+
expect(described_class.matches(item)).to be_truthy
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#scoring_data_structs' do
|
28
|
+
it 'grabs scoring data value for matching questions' do
|
29
|
+
expect(subject.scoring_data_structs.first.values).to eq(
|
30
|
+
'question_1' => 'Magnify up to about 400 times. Sometimes requires colored staining of cells.',
|
31
|
+
'question_2' => "Uses a beam of electrons. Can provide details of cells' internal structure."
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#questions' do
|
37
|
+
it 'returns the questions' do
|
38
|
+
expect(subject.questions).to eq(
|
39
|
+
[{ id: 'question_1', question_body: 'Light Microscope' },
|
40
|
+
{ id: 'question_2', question_body: 'Electron Microscopes' }]
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -64,28 +64,4 @@ describe Qti::V2::Models::AssessmentItem do
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
68
|
-
describe '#scoring_data_structs' do
|
69
|
-
it 'grabs scoring data value for matching questions' do
|
70
|
-
assessment_item = Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/match.xml'
|
71
|
-
expect(assessment_item.interaction_model).to be_instance_of Qti::V2::Models::Interactions::MatchInteraction
|
72
|
-
expect(assessment_item.scoring_data_structs.first.values).to eq(
|
73
|
-
'C' => 'Romeo and Juliet',
|
74
|
-
'D' => "A Midsummer-Night's Dream",
|
75
|
-
'L' => "A Midsummer-Night's Dream",
|
76
|
-
'P' => 'The Tempest'
|
77
|
-
)
|
78
|
-
expect(assessment_item.interaction_model.questions).to eq(
|
79
|
-
[{ id: 'C', question_body: 'Capulet' },
|
80
|
-
{ id: 'D', question_body: 'Demetrius' },
|
81
|
-
{ id: 'L', question_body: 'Lysander' },
|
82
|
-
{ id: 'P', question_body: 'Prospero' }]
|
83
|
-
)
|
84
|
-
expect(assessment_item.interaction_model.answers.map(&:item_body)).to eq(
|
85
|
-
["A Midsummer-Night's Dream",
|
86
|
-
'Romeo and Juliet',
|
87
|
-
'The Tempest']
|
88
|
-
)
|
89
|
-
end
|
90
|
-
end
|
91
67
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Qti::V2::Models::Choices::SimpleAssociableChoice do
|
4
|
+
let(:io) { File.read('spec/fixtures/items_2.1/match2.xml') }
|
5
|
+
let(:nodes) { Nokogiri::XML(io).xpath('//xmlns:simpleAssociableChoice') }
|
6
|
+
let(:choices) { nodes.map { |node| described_class.new(node) } }
|
7
|
+
|
8
|
+
it 'returns the expected attributes' do
|
9
|
+
expected_attrs = [
|
10
|
+
%w(Match28433682 1 1 Weißeritz),
|
11
|
+
%w(Match7191791 1 1 Mulde),
|
12
|
+
%w(Match20473010 1 1 Saale),
|
13
|
+
%w(Match6429655 1 1 Spree),
|
14
|
+
%w(Match2675678 1 1 Dresden),
|
15
|
+
%w(Match9372581 1 1 Leipzig),
|
16
|
+
%w(Match22744006 1 1 Halle),
|
17
|
+
%w(Match17943221 1 1 Bautzen)
|
18
|
+
]
|
19
|
+
expect(choices.map { |c| [c.identifier, c.match_min, c.match_max, c.item_body] }).to eq expected_attrs
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Qti::V2::Models::Interactions::CategorizationInteraction do
|
4
|
+
let(:assessment_item) { Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/categorization.xml' }
|
5
|
+
subject { assessment_item.interaction_model }
|
6
|
+
|
7
|
+
it { is_expected.to be_an_instance_of(described_class) }
|
8
|
+
|
9
|
+
it 'returns shuffle setting' do
|
10
|
+
expect(subject.shuffled?).to eq true
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#scoring_data_structs' do
|
14
|
+
it 'returns the scoring data for categorization questions' do
|
15
|
+
expected_scoring_data_structs = [
|
16
|
+
Qti::V2::Models::ScoringData.new("A Midsummer-Night's Dream", "directedPair", id: "M", questions_ids: ["D", "L"]),
|
17
|
+
Qti::V2::Models::ScoringData.new('Romeo and Juliet', "directedPair", id: "R", questions_ids: ['C']),
|
18
|
+
Qti::V2::Models::ScoringData.new('The Tempest', "directedPair", id: "T", questions_ids: ['P']),
|
19
|
+
]
|
20
|
+
expect(subject.scoring_data_structs).to eq expected_scoring_data_structs
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,15 +1,79 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Qti::V2::Models::Interactions::MatchInteraction do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
context 'assessmentItem is implemented with <associateInteraction>' do
|
5
|
+
let(:assessment_item) { Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/match.xml' }
|
6
|
+
subject { assessment_item.interaction_model }
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
it { is_expected.to be_an_instance_of(described_class) }
|
9
|
+
|
10
|
+
it 'returns shuffle setting' do
|
11
|
+
expect(subject.shuffled?).to eq true
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#scoring_data_structs' do
|
15
|
+
it 'grabs scoring data value for matching questions' do
|
16
|
+
expect(subject.scoring_data_structs).to eq [
|
17
|
+
Qti::V2::Models::ScoringData.new('Prospero', 'Pair', id: 'P', question_id: 'A'),
|
18
|
+
Qti::V2::Models::ScoringData.new('Montague', 'Pair', id: 'M', question_id: 'C'),
|
19
|
+
Qti::V2::Models::ScoringData.new('Lysander', 'Pair', id: 'L', question_id: 'D')
|
20
|
+
]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#answers' do
|
25
|
+
it 'returns the correct_answers' do
|
26
|
+
expect(subject.answers.map(&:item_body)).to eq(%w[Lysander Montague Prospero])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#questions' do
|
31
|
+
it 'returns the questions' do
|
32
|
+
expect(subject.questions).to eq(
|
33
|
+
[{ id: 'A', question_body: 'Antonio' },
|
34
|
+
{ id: 'C', question_body: 'Capulet' },
|
35
|
+
{ id: 'D', question_body: 'Demetrius' }]
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
10
39
|
end
|
11
40
|
|
12
|
-
|
13
|
-
|
41
|
+
context 'assessmentItem is implemented with <matchInteraction>' do
|
42
|
+
let(:assessment_item) { Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/match2.xml' }
|
43
|
+
subject { assessment_item.interaction_model }
|
44
|
+
|
45
|
+
it { is_expected.to be_an_instance_of(described_class) }
|
46
|
+
|
47
|
+
it 'returns shuffle setting' do
|
48
|
+
expect(subject.shuffled?).to eq true
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#scoring_data_structs' do
|
52
|
+
it 'grabs scoring data value for matching questions' do
|
53
|
+
expect(subject.scoring_data_structs).to eq [
|
54
|
+
Qti::V2::Models::ScoringData.new('Dresden', 'Pair', id: 'Match2675678', question_id: 'Match28433682'),
|
55
|
+
Qti::V2::Models::ScoringData.new('Leipzig', 'Pair', id: 'Match9372581', question_id: 'Match7191791'),
|
56
|
+
Qti::V2::Models::ScoringData.new('Halle' , 'Pair', id: 'Match22744006', question_id: 'Match20473010'),
|
57
|
+
Qti::V2::Models::ScoringData.new('Bautzen', 'Pair', id: 'Match17943221', question_id: 'Match6429655')
|
58
|
+
]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#answers' do
|
63
|
+
it 'returns the correct_answers' do
|
64
|
+
expect(subject.answers.map(&:item_body)).to eq %w[Dresden Leipzig Halle Bautzen]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#questions' do
|
69
|
+
it 'returns the questions' do
|
70
|
+
expect(subject.questions).to eq(
|
71
|
+
[{ id: 'Match28433682', question_body: 'Weißeritz' },
|
72
|
+
{ id: 'Match7191791', question_body: 'Mulde' },
|
73
|
+
{ id: 'Match20473010', question_body: 'Saale' },
|
74
|
+
{ id: 'Match6429655', question_body: 'Spree' }]
|
75
|
+
)
|
76
|
+
end
|
77
|
+
end
|
14
78
|
end
|
15
79
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# ObjectSpace.each_object(Class).select { |c| c.name =~ /V1.*(?<!Base)Interaction$/ }.each do |klass|
|
2
|
+
# klass.class_eval do
|
3
|
+
# class << self
|
4
|
+
# alias_method :old_matches?, :matches?
|
5
|
+
# def matches?(node)
|
6
|
+
# raise ArgumentError.new("Expected Nokogiri::XML::Element and got #{node.class}") unless item_element?(node)
|
7
|
+
# old_matches?(node)
|
8
|
+
# end
|
9
|
+
# def item_element?(node)
|
10
|
+
# node.class == Nokogiri::XML::Element && node.name == 'item'
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
# 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.5.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-05-
|
12
|
+
date: 2017-05-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -165,6 +165,20 @@ dependencies:
|
|
165
165
|
- - ">="
|
166
166
|
- !ruby/object:Gem::Version
|
167
167
|
version: '0'
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: rubocop
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
175
|
+
type: :development
|
176
|
+
prerelease: false
|
177
|
+
version_requirements: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
168
182
|
- !ruby/object:Gem::Dependency
|
169
183
|
name: simplecov
|
170
184
|
requirement: !ruby/object:Gem::Requirement
|
@@ -223,10 +237,13 @@ files:
|
|
223
237
|
- lib/qti/v2/models/choices/simple_choice.rb
|
224
238
|
- lib/qti/v2/models/interactions.rb
|
225
239
|
- lib/qti/v2/models/interactions/base_interaction.rb
|
240
|
+
- lib/qti/v2/models/interactions/categorization_interaction.rb
|
226
241
|
- lib/qti/v2/models/interactions/choice_interaction.rb
|
227
242
|
- lib/qti/v2/models/interactions/extended_text_interaction.rb
|
228
243
|
- lib/qti/v2/models/interactions/gap_match_interaction.rb
|
229
244
|
- lib/qti/v2/models/interactions/match_interaction.rb
|
245
|
+
- lib/qti/v2/models/interactions/match_item_tag_processors/associate_interaction_tag_processor.rb
|
246
|
+
- lib/qti/v2/models/interactions/match_item_tag_processors/match_interaction_tag_processor.rb
|
230
247
|
- lib/qti/v2/models/scoring_data.rb
|
231
248
|
- spec/fixtures/items_1.2/choice.xml
|
232
249
|
- spec/fixtures/items_1.2/essay.xml
|
@@ -247,6 +264,7 @@ files:
|
|
247
264
|
- spec/fixtures/items_2.1/adaptive_template.xml
|
248
265
|
- spec/fixtures/items_2.1/associate.xml
|
249
266
|
- spec/fixtures/items_2.1/audio-video.xml
|
267
|
+
- spec/fixtures/items_2.1/categorization.xml
|
250
268
|
- spec/fixtures/items_2.1/choice.xml
|
251
269
|
- spec/fixtures/items_2.1/choice_aria.xml
|
252
270
|
- spec/fixtures/items_2.1/choice_fixed.xml
|
@@ -304,6 +322,7 @@ files:
|
|
304
322
|
- spec/fixtures/items_2.1/inline_choice_math.xml
|
305
323
|
- spec/fixtures/items_2.1/likert.xml
|
306
324
|
- spec/fixtures/items_2.1/match.xml
|
325
|
+
- spec/fixtures/items_2.1/match2.xml
|
307
326
|
- spec/fixtures/items_2.1/math.xml
|
308
327
|
- spec/fixtures/items_2.1/mc_calc3.xml
|
309
328
|
- spec/fixtures/items_2.1/mc_calc5.xml
|
@@ -422,11 +441,14 @@ files:
|
|
422
441
|
- spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
|
423
442
|
- spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
|
424
443
|
- spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
|
444
|
+
- spec/lib/qti/v1/models/interactions/match_interaction_spec.rb
|
425
445
|
- spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
|
426
446
|
- spec/lib/qti/v2/models/assessment_item_spec.rb
|
427
447
|
- spec/lib/qti/v2/models/assessment_test_spec.rb
|
428
448
|
- spec/lib/qti/v2/models/choices/gap_match_choice_spec.rb
|
449
|
+
- spec/lib/qti/v2/models/choices/simple_associable_choice_spec.rb
|
429
450
|
- spec/lib/qti/v2/models/choices/simple_choice_spec.rb
|
451
|
+
- spec/lib/qti/v2/models/interactions/categorization_interaction_spec.rb
|
430
452
|
- spec/lib/qti/v2/models/interactions/choice_interaction_spec.rb
|
431
453
|
- spec/lib/qti/v2/models/interactions/extended_text_interaction_spec.rb
|
432
454
|
- spec/lib/qti/v2/models/interactions/gap_match_interaction_spec.rb
|
@@ -434,6 +456,7 @@ files:
|
|
434
456
|
- spec/lib/qti_spec.rb
|
435
457
|
- spec/spec_helper.rb
|
436
458
|
- spec/support/custom_matchers.rb
|
459
|
+
- spec/support/monkey_patches.rb
|
437
460
|
homepage:
|
438
461
|
licenses: []
|
439
462
|
metadata: {}
|
@@ -477,6 +500,7 @@ test_files:
|
|
477
500
|
- spec/fixtures/items_2.1/adaptive_template.xml
|
478
501
|
- spec/fixtures/items_2.1/associate.xml
|
479
502
|
- spec/fixtures/items_2.1/audio-video.xml
|
503
|
+
- spec/fixtures/items_2.1/categorization.xml
|
480
504
|
- spec/fixtures/items_2.1/choice.xml
|
481
505
|
- spec/fixtures/items_2.1/choice_aria.xml
|
482
506
|
- spec/fixtures/items_2.1/choice_fixed.xml
|
@@ -534,6 +558,7 @@ test_files:
|
|
534
558
|
- spec/fixtures/items_2.1/inline_choice_math.xml
|
535
559
|
- spec/fixtures/items_2.1/likert.xml
|
536
560
|
- spec/fixtures/items_2.1/match.xml
|
561
|
+
- spec/fixtures/items_2.1/match2.xml
|
537
562
|
- spec/fixtures/items_2.1/math.xml
|
538
563
|
- spec/fixtures/items_2.1/mc_calc3.xml
|
539
564
|
- spec/fixtures/items_2.1/mc_calc5.xml
|
@@ -652,11 +677,14 @@ test_files:
|
|
652
677
|
- spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
|
653
678
|
- spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
|
654
679
|
- spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
|
680
|
+
- spec/lib/qti/v1/models/interactions/match_interaction_spec.rb
|
655
681
|
- spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
|
656
682
|
- spec/lib/qti/v2/models/assessment_item_spec.rb
|
657
683
|
- spec/lib/qti/v2/models/assessment_test_spec.rb
|
658
684
|
- spec/lib/qti/v2/models/choices/gap_match_choice_spec.rb
|
685
|
+
- spec/lib/qti/v2/models/choices/simple_associable_choice_spec.rb
|
659
686
|
- spec/lib/qti/v2/models/choices/simple_choice_spec.rb
|
687
|
+
- spec/lib/qti/v2/models/interactions/categorization_interaction_spec.rb
|
660
688
|
- spec/lib/qti/v2/models/interactions/choice_interaction_spec.rb
|
661
689
|
- spec/lib/qti/v2/models/interactions/extended_text_interaction_spec.rb
|
662
690
|
- spec/lib/qti/v2/models/interactions/gap_match_interaction_spec.rb
|
@@ -664,3 +692,4 @@ test_files:
|
|
664
692
|
- spec/lib/qti_spec.rb
|
665
693
|
- spec/spec_helper.rb
|
666
694
|
- spec/support/custom_matchers.rb
|
695
|
+
- spec/support/monkey_patches.rb
|