qti 0.2.12 → 0.2.14
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/Rakefile +9 -1
- data/lib/qti/v1/models/assessment.rb +2 -2
- data/lib/qti/v1/models/assessment_item.rb +5 -29
- data/lib/qti/v1/models/interactions/base_interaction.rb +33 -0
- data/lib/qti/v1/models/interactions/choice_interaction.rb +44 -0
- data/lib/qti/v1/models/interactions/match_interaction.rb +60 -0
- data/lib/qti/v1/models/interactions/ordering_interaction.rb +23 -0
- data/lib/qti/v1/models/interactions/string_interaction.rb +1 -3
- data/lib/qti/v1/models/interactions.rb +1 -3
- data/lib/qti/v1/models/scoring_data.rb +7 -0
- data/lib/qti/v2/models/assessment_item.rb +2 -6
- data/lib/qti/v2/models/choices/simple_associable_choice.rb +12 -0
- data/lib/qti/v2/models/interactions/base_interaction.rb +43 -0
- data/lib/qti/v2/models/interactions/choice_interaction.rb +2 -12
- data/lib/qti/v2/models/interactions/extended_text_interaction.rb +1 -5
- data/lib/qti/v2/models/interactions/match_interaction.rb +52 -0
- data/lib/qti/v2/models/scoring_data.rb +7 -0
- data/lib/qti.rb +6 -0
- data/spec/fixtures/items_1.2/matching.xml +74 -0
- data/spec/fixtures/items_1.2/multiple_answer.xml +1 -1
- data/spec/fixtures/items_1.2/multiple_choice.xml +1 -1
- data/spec/fixtures/items_1.2/ordering.xml +20 -20
- data/spec/fixtures/items_1.2/true_false.xml +1 -1
- data/spec/fixtures/items_2.1/match.xml +33 -39
- data/spec/fixtures/test_qti_1.2/quiz.xml +209 -216
- data/spec/lib/qti/v1/models/assessment_item_spec.rb +20 -2
- data/spec/lib/qti/v1/models/interactions/{logical_identifier_interaction_spec.rb → choice_interaction_spec.rb} +1 -1
- data/spec/lib/qti/v2/models/assessment_item_spec.rb +24 -0
- metadata +15 -5
- data/lib/qti/v1/models/interactions/logical_identifier_interaction.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e3dbac8ff4eda0f1c6f67c6f8e7e1673ac8014b
|
4
|
+
data.tar.gz: 807c9a6be3ea4e1887966bb5734015dc017efa04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a628c8aa5c49fdea190b112136ab3ad22861725437b7c167c2ac6188ae7970a5641a6d794243726d4b9c24c0986ad33900d22816a4576fa056e5acc50c328db8
|
7
|
+
data.tar.gz: 1a92b8176ca835e95923c936ae5c86b77c60e9ba702c7f6dd0d84d082c1ae6aa6eb63a670681bbfb34bb54ada67391c2ab394f4d6182f631712bf57b5376e83f
|
data/Rakefile
CHANGED
@@ -5,11 +5,11 @@ module Qti
|
|
5
5
|
module Models
|
6
6
|
class Assessment < Qti::V1::Models::Base
|
7
7
|
def title
|
8
|
-
@title ||= xpath_with_single_check('
|
8
|
+
@title ||= xpath_with_single_check('.//xmlns:assessment/@title')&.content
|
9
9
|
end
|
10
10
|
|
11
11
|
def assessment_items
|
12
|
-
@doc.xpath('
|
12
|
+
@doc.xpath('.//xmlns:item')
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -7,8 +7,6 @@ module Qti
|
|
7
7
|
class AssessmentItem < Qti::V1::Models::Base
|
8
8
|
attr_reader :doc
|
9
9
|
|
10
|
-
ScoringData = Struct.new(:values, :rcardinality)
|
11
|
-
|
12
10
|
def initialize(item)
|
13
11
|
@doc = item
|
14
12
|
end
|
@@ -16,8 +14,8 @@ module Qti
|
|
16
14
|
def item_body
|
17
15
|
@item_body ||= begin
|
18
16
|
node = @doc.dup
|
19
|
-
presentation = node.at_xpath('
|
20
|
-
prompt = presentation.at_xpath('
|
17
|
+
presentation = node.at_xpath('.//xmlns:presentation')
|
18
|
+
prompt = presentation.at_xpath('.//xmlns:mattext').content
|
21
19
|
sanitize_content!(prompt)
|
22
20
|
end
|
23
21
|
end
|
@@ -32,12 +30,12 @@ module Qti
|
|
32
30
|
|
33
31
|
def points_possible
|
34
32
|
@points_possible ||= begin
|
35
|
-
@doc.at_xpath('.//decvar/@maxvalue')&.value || @doc.at_xpath('.//decvar/@defaultval')&.value
|
33
|
+
@doc.at_xpath('.//xmlns:decvar/@maxvalue')&.value || @doc.at_xpath('.//xmlns:decvar/@defaultval')&.value
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
37
|
def rcardinality
|
40
|
-
@rcardinality ||= @doc.at_xpath('.//response_lid/@rcardinality').value
|
38
|
+
@rcardinality ||= @doc.at_xpath('.//xmlns:response_lid/@rcardinality').value
|
41
39
|
end
|
42
40
|
|
43
41
|
def interaction_model
|
@@ -47,29 +45,7 @@ module Qti
|
|
47
45
|
end
|
48
46
|
|
49
47
|
def scoring_data_structs
|
50
|
-
@scoring_data_structs ||=
|
51
|
-
if ordering?
|
52
|
-
scoring_data_structs_for_ordering
|
53
|
-
else
|
54
|
-
default_scoring_data_structs
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def default_scoring_data_structs
|
61
|
-
choice_nodes = doc.xpath('.//respcondition')
|
62
|
-
choice_nodes.select { |choice_node| choice_node.at_xpath('.//setvar').content.to_f.positive? }
|
63
|
-
.map { |value_node| ScoringData.new(value_node.at_xpath('.//varequal').content, rcardinality) }
|
64
|
-
end
|
65
|
-
|
66
|
-
def scoring_data_structs_for_ordering
|
67
|
-
correct_order = @doc.xpath('.//conditionvar/varequal').map{|node| node.content }
|
68
|
-
[ScoringData.new(correct_order, rcardinality)]
|
69
|
-
end
|
70
|
-
|
71
|
-
def ordering?
|
72
|
-
rcardinality == 'Ordered'
|
48
|
+
@scoring_data_structs ||= interaction_model.scoring_data_structs
|
73
49
|
end
|
74
50
|
end
|
75
51
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Qti
|
2
|
+
module V1
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
class BaseInteraction < Qti::V1::Models::Base
|
6
|
+
attr_reader :node
|
7
|
+
|
8
|
+
def self.matches(node)
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(node)
|
13
|
+
@node = node
|
14
|
+
end
|
15
|
+
|
16
|
+
def shuffled?
|
17
|
+
@node.at_xpath('.//xmlns:render_choice/@shuffle')&.value == 'Yes'
|
18
|
+
end
|
19
|
+
|
20
|
+
def scoring_data_structs
|
21
|
+
raise NotImplementedError
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def rcardinality
|
27
|
+
@rcardinality ||= @node.at_xpath('.//xmlns:response_lid/@rcardinality').value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Qti
|
2
|
+
module V1
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
class ChoiceInteraction < BaseInteraction
|
6
|
+
# This will know if a class matches
|
7
|
+
def self.matches(node)
|
8
|
+
matches = node.xpath('.//xmlns:response_lid')
|
9
|
+
return false if matches.count > 1 || matches.empty?
|
10
|
+
rcardinality = matches.first.attributes['rcardinality']&.value || 'Single'
|
11
|
+
return false if rcardinality == 'Ordered'
|
12
|
+
new(node)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(node)
|
16
|
+
@node = node
|
17
|
+
end
|
18
|
+
|
19
|
+
def shuffled?
|
20
|
+
node.at_xpath('.//xmlns:render_choice/@shuffle')&.value == 'Yes'
|
21
|
+
end
|
22
|
+
|
23
|
+
def answers
|
24
|
+
@answers ||= answer_nodes.map do |node|
|
25
|
+
V1::Models::Choices::LogicalIdentifierChoice.new(node)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def scoring_data_structs
|
30
|
+
choice_nodes = node.xpath('.//xmlns:respcondition')
|
31
|
+
set_var_nodes = choice_nodes.select { |choice_node| choice_node.at_xpath('.//xmlns:setvar').content.to_f.positive? }
|
32
|
+
set_var_nodes.map { |value_node| ScoringData.new(value_node.at_xpath('.//xmlns:varequal').content, rcardinality) }
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def answer_nodes
|
38
|
+
node.xpath('.//xmlns:response_label')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Qti
|
2
|
+
module V1
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
class MatchInteraction < BaseInteraction
|
6
|
+
attr_reader :node
|
7
|
+
|
8
|
+
def self.matches(node)
|
9
|
+
matches = node.xpath('.//xmlns:response_lid')
|
10
|
+
return false if matches.count <= 1
|
11
|
+
new(node)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(node)
|
15
|
+
@node = node
|
16
|
+
end
|
17
|
+
|
18
|
+
def answers
|
19
|
+
@answers ||= answer_nodes.map do |node|
|
20
|
+
V1::Models::Choices::LogicalIdentifierChoice.new(node)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def questions
|
25
|
+
node.xpath('.//xmlns:response_lid').map do |lid_node|
|
26
|
+
question_body = lid_node.at_xpath('.//xmlns:mattext').text
|
27
|
+
{ id: lid_node.attributes['ident'].value, question_body: question_body }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def scoring_data_structs
|
32
|
+
matches = node.xpath('.//xmlns:varequal').map do |node|
|
33
|
+
[node.attributes['respident'].value, answers_map[node.content]]
|
34
|
+
end
|
35
|
+
[Models::ScoringData.new(Hash[matches], rcardinality)]
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def answers_map
|
41
|
+
@answers_map ||= answers.reduce({}) do |acc, answer|
|
42
|
+
acc.update answer.identifier => answer.item_body
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def answer_nodes
|
47
|
+
responses = []
|
48
|
+
response_ids = {}
|
49
|
+
node.xpath('.//xmlns:response_label').each do |answer_node|
|
50
|
+
ident = answer_node.attributes['ident'].value
|
51
|
+
responses << answer_node unless response_ids.key? ident
|
52
|
+
response_ids[ident] = 1
|
53
|
+
end
|
54
|
+
responses
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Qti
|
2
|
+
module V1
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
class OrderingInteraction < ChoiceInteraction
|
6
|
+
# This will know if a class matches
|
7
|
+
def self.matches(node)
|
8
|
+
matches = node.xpath('.//xmlns:response_lid')
|
9
|
+
return false if matches.count > 1 || matches.empty?
|
10
|
+
rcardinality = matches.first.attributes['rcardinality']&.value || 'Single'
|
11
|
+
return false if rcardinality != 'Ordered'
|
12
|
+
new(node)
|
13
|
+
end
|
14
|
+
|
15
|
+
def scoring_data_structs
|
16
|
+
correct_order = node.xpath('.//xmlns:varequal').map(&:content)
|
17
|
+
[ScoringData.new(correct_order, rcardinality)]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -2,14 +2,12 @@ module Qti
|
|
2
2
|
module V1
|
3
3
|
module Models
|
4
4
|
module Interactions
|
5
|
-
class StringInteraction <
|
5
|
+
class StringInteraction < BaseInteraction
|
6
6
|
@node_name = 'response_str'.freeze
|
7
7
|
# This will know if a class matches
|
8
8
|
def self.matches(node)
|
9
9
|
matches = node.children.children.select { |n| n.name == @node_name }
|
10
10
|
return false if matches.empty?
|
11
|
-
|
12
|
-
raise Qti::UnsupportedSchema if matches.size > 1
|
13
11
|
new(matches.first)
|
14
12
|
end
|
15
13
|
|
@@ -39,16 +39,12 @@ module Qti
|
|
39
39
|
|
40
40
|
def interaction_model
|
41
41
|
@interaction_model ||= begin
|
42
|
-
V2::Models::Interactions.interaction_model(
|
42
|
+
V2::Models::Interactions.interaction_model(@doc)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
def scoring_data_structs
|
47
|
-
@scoring_data_structs ||=
|
48
|
-
type = xpath_with_single_check('//xmlns:responseDeclaration/@baseType').content
|
49
|
-
value_nodes = @doc.xpath('//xmlns:responseDeclaration/xmlns:correctResponse/xmlns:value')
|
50
|
-
value_nodes.map { |value_node| ScoringData.new(value_node.content, type) }
|
51
|
-
end
|
47
|
+
@scoring_data_structs ||= interaction_model.scoring_data_structs
|
52
48
|
end
|
53
49
|
|
54
50
|
private
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Qti
|
2
|
+
module V2
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
class BaseInteraction < Qti::V2::Models::Base
|
6
|
+
attr_reader :node
|
7
|
+
|
8
|
+
def self.matches(node)
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(node)
|
13
|
+
@node = node
|
14
|
+
end
|
15
|
+
|
16
|
+
def shuffled?
|
17
|
+
@node.at_xpath('.//render_choice/@shuffle')&.value == 'Yes'
|
18
|
+
end
|
19
|
+
|
20
|
+
def scoring_data_structs
|
21
|
+
@scoring_data_structs ||= begin
|
22
|
+
type = xpath_with_single_check('//xmlns:responseDeclaration/@baseType').content
|
23
|
+
value_nodes = node.xpath('//xmlns:responseDeclaration/xmlns:correctResponse/xmlns:value')
|
24
|
+
value_nodes.map { |value_node| Models::ScoringData.new(value_node.content, type) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def xpath_with_single_check(xpath)
|
29
|
+
node_list = node.xpath(xpath)
|
30
|
+
raise Qti::ParseError, 'Too many matches' if node_list.count > 1
|
31
|
+
node_list.first
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def rcardinality
|
37
|
+
@rcardinality ||= @node.at_xpath('.//response_lid/@rcardinality').value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -2,25 +2,15 @@ module Qti
|
|
2
2
|
module V2
|
3
3
|
module Models
|
4
4
|
module Interactions
|
5
|
-
class ChoiceInteraction <
|
6
|
-
@node_name = 'choiceInteraction'.freeze
|
7
|
-
# This will know if a class matches
|
5
|
+
class ChoiceInteraction < BaseInteraction
|
8
6
|
def self.matches(node)
|
9
|
-
matches = node.
|
7
|
+
matches = node.xpath('.//xmlns:choiceInteraction')
|
10
8
|
return false if matches.empty?
|
11
9
|
|
12
10
|
raise Qti::UnsupportedSchema if matches.size > 1
|
13
11
|
new(matches.first)
|
14
12
|
end
|
15
13
|
|
16
|
-
def initialize(node)
|
17
|
-
@node = node
|
18
|
-
end
|
19
|
-
|
20
|
-
def shuffled?
|
21
|
-
@node.attributes['shuffle'].value == 'true'
|
22
|
-
end
|
23
|
-
|
24
14
|
def answers
|
25
15
|
@answers ||= answer_nodes.map do |node|
|
26
16
|
V2::Models::Choices::SimpleChoice.new(node)
|
@@ -2,7 +2,7 @@ module Qti
|
|
2
2
|
module V2
|
3
3
|
module Models
|
4
4
|
module Interactions
|
5
|
-
class ExtendedTextInteraction <
|
5
|
+
class ExtendedTextInteraction < BaseInteraction
|
6
6
|
@node_name = 'extendedTextInteraction'.freeze
|
7
7
|
# This will know if a class matches
|
8
8
|
def self.matches(node)
|
@@ -13,10 +13,6 @@ module Qti
|
|
13
13
|
new(matches.first)
|
14
14
|
end
|
15
15
|
|
16
|
-
def initialize(node)
|
17
|
-
@node = node
|
18
|
-
end
|
19
|
-
|
20
16
|
# not used yet
|
21
17
|
def expected_lines
|
22
18
|
@node.attributes['expectedLines']&.value&.to_i || 0
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Qti
|
2
|
+
module V2
|
3
|
+
module Models
|
4
|
+
module Interactions
|
5
|
+
class MatchInteraction < BaseInteraction
|
6
|
+
def self.matches(node)
|
7
|
+
matches = node.xpath('//xmlns:matchInteraction')
|
8
|
+
return false if matches.empty?
|
9
|
+
|
10
|
+
raise Qti::UnsupportedSchema if matches.size > 1
|
11
|
+
new(node)
|
12
|
+
end
|
13
|
+
|
14
|
+
def questions
|
15
|
+
node.xpath('.//xmlns:correctResponse//xmlns:value')
|
16
|
+
.map { |value| value.content.split.first }
|
17
|
+
.map { |id| { id: id, question_body: choices_by_identifier[id].content } }
|
18
|
+
end
|
19
|
+
|
20
|
+
def answers
|
21
|
+
answer_nodes.map { |node| Choices::SimpleAssociableChoice.new(node) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def scoring_data_structs
|
25
|
+
question_response_pairs = node.xpath('.//xmlns:correctResponse//xmlns:value').map do |value|
|
26
|
+
value.content.split
|
27
|
+
end
|
28
|
+
question_response_id_mapping = Hash[question_response_pairs]
|
29
|
+
data = question_response_id_mapping.reduce({}) do |acc, pair|
|
30
|
+
question_id, answer_id = pair
|
31
|
+
acc.update question_id => choices_by_identifier[answer_id].content
|
32
|
+
end
|
33
|
+
[ScoringData.new(data, 'directedPair')]
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def choices_by_identifier
|
39
|
+
choices = node.xpath('.//xmlns:simpleAssociableChoice')
|
40
|
+
@choices_by_identifier ||= choices.reduce({}) do |acc, choice|
|
41
|
+
acc.update choice.attributes['identifier'].value => choice
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def answer_nodes
|
46
|
+
node.xpath('.//xmlns:matchInteraction//xmlns:simpleMatchSet[2]//xmlns:simpleAssociableChoice')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/qti.rb
CHANGED
@@ -52,14 +52,20 @@ require 'qti/models/manifest'
|
|
52
52
|
require 'qti/models/base'
|
53
53
|
|
54
54
|
require 'qti/v1/models/base'
|
55
|
+
require 'qti/v1/models/interactions/base_interaction'
|
56
|
+
require 'qti/v1/models/interactions/choice_interaction'
|
55
57
|
require 'qti/v1/models/assessment'
|
56
58
|
require 'qti/v1/models/assessment_item'
|
57
59
|
require 'qti/v1/models/choices/logical_identifier_choice'
|
60
|
+
require 'qti/v1/models/scoring_data'
|
58
61
|
|
59
62
|
require 'qti/v2/models/base'
|
63
|
+
require 'qti/v2/models/interactions/base_interaction'
|
60
64
|
require 'qti/v2/models/choices/simple_choice'
|
65
|
+
require 'qti/v2/models/choices/simple_associable_choice'
|
61
66
|
require 'qti/v2/models/assessment_item'
|
62
67
|
require 'qti/v2/models/assessment_test'
|
68
|
+
require 'qti/v2/models/scoring_data'
|
63
69
|
|
64
70
|
require 'zip'
|
65
71
|
require 'qti/exporter'
|
@@ -0,0 +1,74 @@
|
|
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 title="" ident="4772">
|
4
|
+
<itemmetadata>
|
5
|
+
<qtimetadata>
|
6
|
+
<qtimetadatafield>
|
7
|
+
<fieldlabel>question_type</fieldlabel>
|
8
|
+
<fieldentry>matching_question</fieldentry>
|
9
|
+
</qtimetadatafield>
|
10
|
+
</qtimetadata>
|
11
|
+
</itemmetadata>
|
12
|
+
<presentation>
|
13
|
+
<material>
|
14
|
+
<mattext texttype="text/html">Match the statements with the correct type of microscope</mattext>
|
15
|
+
</material>
|
16
|
+
<response_lid ident="question_1" rcardinality="Single">
|
17
|
+
<material>
|
18
|
+
<mattext texttype="text/plain">Light Microscope</mattext>
|
19
|
+
</material>
|
20
|
+
<render_choice>
|
21
|
+
<response_label ident="8440">
|
22
|
+
<material>
|
23
|
+
<mattext texttype="text/plain">Magnify up to about 400 times. Sometimes requires colored staining of cells.</mattext>
|
24
|
+
</material>
|
25
|
+
</response_label>
|
26
|
+
<response_label ident="5653">
|
27
|
+
<material>
|
28
|
+
<mattext texttype="text/plain">Uses a beam of electrons. Can provide details of cells' internal structure.</mattext>
|
29
|
+
</material>
|
30
|
+
</response_label>
|
31
|
+
</render_choice>
|
32
|
+
</response_lid>
|
33
|
+
<response_lid ident="question_2" rcardinality="Single">
|
34
|
+
<material>
|
35
|
+
<mattext texttype="text/plain">Electron Microscopes</mattext>
|
36
|
+
</material>
|
37
|
+
<render_choice>
|
38
|
+
<response_label ident="8440">
|
39
|
+
<material>
|
40
|
+
<mattext texttype="text/plain">Magnify up to about 400 times. Sometimes requires colored staining of cells.</mattext>
|
41
|
+
</material>
|
42
|
+
</response_label>
|
43
|
+
<response_label ident="5653">
|
44
|
+
<material>
|
45
|
+
<mattext texttype="text/plain">Uses a beam of electrons. Can provide details of cells' internal structure.</mattext>
|
46
|
+
</material>
|
47
|
+
</response_label>
|
48
|
+
<response_label ident="7777">
|
49
|
+
<material>
|
50
|
+
<mattext texttype="text/plain">A distractor answer.</mattext>
|
51
|
+
</material>
|
52
|
+
</response_label>
|
53
|
+
</render_choice>
|
54
|
+
</response_lid>
|
55
|
+
</presentation>
|
56
|
+
<resprocessing>
|
57
|
+
<outcomes>
|
58
|
+
<decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
|
59
|
+
</outcomes>
|
60
|
+
<respcondition>
|
61
|
+
<conditionvar>
|
62
|
+
<varequal respident="question_1">8440</varequal>
|
63
|
+
</conditionvar>
|
64
|
+
<setvar varname="SCORE" action="Add">50.00</setvar>
|
65
|
+
</respcondition>
|
66
|
+
<respcondition>
|
67
|
+
<conditionvar>
|
68
|
+
<varequal respident="question_2">5653</varequal>
|
69
|
+
</conditionvar>
|
70
|
+
<setvar varname="SCORE" action="Add">50.00</setvar>
|
71
|
+
</respcondition>
|
72
|
+
</resprocessing>
|
73
|
+
</item>
|
74
|
+
</questestinterop>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
2
2
|
|
3
|
-
<questestinterop>
|
3
|
+
<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">
|
4
4
|
|
5
5
|
<assessment title="Quiz" ident="A1001">
|
6
6
|
<section title="Main" ident="S1002">
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
2
2
|
|
3
|
-
<questestinterop>
|
3
|
+
<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">
|
4
4
|
|
5
5
|
<assessment title="1.2 Import Quiz" ident="A1001">
|
6
6
|
<section title="Main" ident="S1002">
|