qti 0.2.12 → 0.2.14
Sign up to get free protection for your applications and to get access to all the features.
- 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">
|