qti 0.1.2 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/null_logger.rb +7 -0
- data/lib/qti.rb +10 -0
- data/lib/qti/assessment_item_exporter.rb +67 -0
- data/lib/qti/content_packaging.rb +15 -0
- data/lib/qti/content_packaging/assessment_item.rb +10 -0
- data/lib/qti/content_packaging/assessment_test.rb +9 -0
- data/lib/qti/content_packaging/choice_interaction.rb +12 -0
- data/lib/qti/content_packaging/outcome_declaration.rb +10 -0
- data/lib/qti/content_packaging/simple_choice.rb +11 -0
- data/lib/qti/exporter.rb +168 -0
- data/lib/qti/item_exporter_factory.rb +15 -0
- data/lib/qti/true_false_item_exporter.rb +7 -0
- data/spec/qti/exporter_spec.rb +55 -0
- data/spec/spec_helper.rb +2 -0
- metadata +74 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c740d1b3ac0a16f4661dd5ec3fe25691e3aacc4
|
4
|
+
data.tar.gz: d487bd97b470c0948c4512e52cab356777c28674
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af2cbeb0a5efc6aefd940b238b57a6bc5c273b0601096323ea6beece7137b6c1fcacaa28c6a98840704d656d22bd3214d2661874bc6ad796a4b68b4813caeb2a
|
7
|
+
data.tar.gz: 4b3b108554561f85eda5915f773b301ea396f6ec7e39ea2c46963498ab479f717b5f9f4198682c0bf86c73730f7f665cf330950fca3a69277c776fafb0bf25bd
|
data/lib/null_logger.rb
ADDED
data/lib/qti.rb
CHANGED
@@ -46,6 +46,8 @@ module Qti
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
require 'active_support/core_ext/string'
|
50
|
+
|
49
51
|
require 'qti/models/manifest'
|
50
52
|
require 'qti/models/base'
|
51
53
|
|
@@ -59,3 +61,11 @@ require 'qti/v2/models/choices/simple_choice'
|
|
59
61
|
require 'qti/v2/models/interactions/choice_interaction'
|
60
62
|
require 'qti/v2/models/assessment_item'
|
61
63
|
require 'qti/v2/models/assessment_test'
|
64
|
+
|
65
|
+
require 'zip'
|
66
|
+
require 'qti/exporter'
|
67
|
+
|
68
|
+
require 'qti/content_packaging'
|
69
|
+
require 'qti/assessment_item_exporter'
|
70
|
+
|
71
|
+
require 'null_logger'
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Qti
|
2
|
+
class AssessmentItemExporter
|
3
|
+
attr_reader :index, :assessment_item, :package_root_path
|
4
|
+
|
5
|
+
def initialize(index, assessment_item, args = {})
|
6
|
+
@index = index
|
7
|
+
@assessment_item = assessment_item
|
8
|
+
@package_root_path = args[:package_root_path] || '.'
|
9
|
+
end
|
10
|
+
|
11
|
+
def export
|
12
|
+
File.open(File.join(package_root_path, "item-#{index + 1}.xml"), 'wb') do |f|
|
13
|
+
f.write xml_string_for_assessment_item(assessment_item)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def xml_string_for_assessment_item(assessment_item)
|
20
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
21
|
+
xml.assessmentItem(assesment_item_attributes) do
|
22
|
+
xml.responseDeclaration('identifier' => 'RESPONSE',
|
23
|
+
'cardinality' => cardinality_for_response(assessment_item),
|
24
|
+
'baseType' => 'identifier') do
|
25
|
+
xml.correctResponse do
|
26
|
+
xml.value assessment_item.response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
xml_assessment_item_body(xml, assessment_item)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
builder.to_xml
|
33
|
+
end
|
34
|
+
|
35
|
+
def cardinality_for_response(assessment_item)
|
36
|
+
if assessment_item.response.is_a? Array
|
37
|
+
'multiple'
|
38
|
+
else
|
39
|
+
'single'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def xml_assessment_item_body(xml, assessment_item)
|
44
|
+
xml.itemBody do
|
45
|
+
xml.choiceInteraction(interaction_params(assessment_item.interaction)) do
|
46
|
+
xml.prompt assessment_item.interaction.prompt
|
47
|
+
assessment_item.interaction.choices.each do |choice|
|
48
|
+
xml.simpleChoice(choice.body, 'identifier' => choice.identifier, 'fixed' => choice.fixed)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def interaction_params(interaction)
|
55
|
+
{ 'responseIdentifier' => 'RESPONSE',
|
56
|
+
'shuffle' => interaction.shuffle,
|
57
|
+
'maxChoices' => interaction.maxChoices }
|
58
|
+
end
|
59
|
+
|
60
|
+
def assesment_item_attributes
|
61
|
+
{ 'xmlns' => 'http://www.imsglobal.org/xsd/imsqti_v2p2', 'xmlns:xi' => 'http://www.w3.org/2001/XInclude',
|
62
|
+
'xmlns:m' => 'http://www.w3.org/1998/Math/MathML', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
63
|
+
'xsi:schemaLocation' => 'http://www.imsglobal.org/xsd/imsqti_v2p2
|
64
|
+
http://www.imsglobal.org/xsd/qti/qtiv2p2/imsqti_v2p2.xsd' }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'dry-struct'
|
2
|
+
|
3
|
+
module Qti
|
4
|
+
module ContentPackaging
|
5
|
+
module Types
|
6
|
+
include Dry::Types.module
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'qti/content_packaging/outcome_declaration'
|
12
|
+
require 'qti/content_packaging/simple_choice'
|
13
|
+
require 'qti/content_packaging/choice_interaction'
|
14
|
+
require 'qti/content_packaging/assessment_item'
|
15
|
+
require 'qti/content_packaging/assessment_test'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Qti
|
2
|
+
module ContentPackaging
|
3
|
+
class AssessmentItem < Dry::Struct
|
4
|
+
attribute :identifier, Types::Strict::String
|
5
|
+
attribute :title, Types::Strict::String
|
6
|
+
attribute :interaction, ContentPackaging::ChoiceInteraction
|
7
|
+
attribute :response, Types::Strict::Array.member(String) | Types::Strict::String
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Qti
|
2
|
+
module ContentPackaging
|
3
|
+
class AssessmentTest < Dry::Struct
|
4
|
+
attribute :title, Types::Strict::String
|
5
|
+
attribute :items, Types::Strict::Array.member(ContentPackaging::AssessmentItem)
|
6
|
+
attribute :outcome_declarations, Types::Strict::Array.member(ContentPackaging::OutcomeDeclaration)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Qti
|
2
|
+
module ContentPackaging
|
3
|
+
class ChoiceInteraction < Dry::Struct
|
4
|
+
constructor_type :schema
|
5
|
+
|
6
|
+
attribute :prompt, Types::Strict::String
|
7
|
+
attribute :shuffle, Types::Strict::Bool.default(false)
|
8
|
+
attribute :maxChoices, Types::Coercible::Int
|
9
|
+
attribute :choices, Types::Strict::Array.member(ContentPackaging::SimpleChoice)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Qti
|
2
|
+
module ContentPackaging
|
3
|
+
class OutcomeDeclaration < Dry::Struct
|
4
|
+
attribute :identifier, Types::Strict::String
|
5
|
+
attribute :baseType, Types::Strict::String
|
6
|
+
attribute :cardinality, Types::Strict::String
|
7
|
+
attribute :defaultValue, Types::Strict::String | Types::Coercible::Int | Types::Coercible::Float
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Qti
|
2
|
+
module ContentPackaging
|
3
|
+
class SimpleChoice < Dry::Struct
|
4
|
+
constructor_type :schema
|
5
|
+
|
6
|
+
attribute :body, Types::Strict::String
|
7
|
+
attribute :identifier, Types::Strict::String
|
8
|
+
attribute :fixed, Types::Strict::Bool.default(true)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/qti/exporter.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
module Qti
|
2
|
+
class Exporter
|
3
|
+
attr_reader :assessment_test, :package_root_path, :exported_file_path, :logger
|
4
|
+
|
5
|
+
def initialize(assessment_test, args = {})
|
6
|
+
@logger = args[:logger] || NullLogger.new
|
7
|
+
@assessment_test = assessment_test
|
8
|
+
@package_root_path = args[:package_root_path] || '.'
|
9
|
+
@exported_file_path =
|
10
|
+
File.join(File.expand_path('..', package_root_path), File.basename(export_file_name)) + '.zip'
|
11
|
+
end
|
12
|
+
|
13
|
+
def export
|
14
|
+
Dir.mkdir(package_root_path) unless File.exist?(package_root_path)
|
15
|
+
create_assessment_xml
|
16
|
+
create_imsmanifest_xml
|
17
|
+
export_items
|
18
|
+
compress_package
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def export_file_name
|
24
|
+
@export_file_name ||= "#{assessment_test.title.camelcase.gsub(/\s+/, '')}#{file_timestamp}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_timestamp
|
28
|
+
Time.now.utc.strftime('%Y%m%d%H%M%S')
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_assessment_xml
|
32
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
33
|
+
xml.assessmentTest(assesment_test_attributes(title: assessment_test.title)) do
|
34
|
+
outcome_declarations(xml, assessment_test)
|
35
|
+
xml.testPart do
|
36
|
+
xml_assessment_section(xml)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
File.open(File.join(package_root_path, 'assessment.xml'), 'wb') do |f|
|
42
|
+
f.write builder.to_xml
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def outcome_declarations(xml, assessment_test)
|
47
|
+
assessment_test.outcome_declarations.each do |outcome_declaration|
|
48
|
+
xml.outcomeDeclaration('baseType' => outcome_declaration.baseType,
|
49
|
+
'cardinality' => outcome_declaration.cardinality,
|
50
|
+
'identifier' => outcome_declaration.identifier) do
|
51
|
+
xml.defaultValue do
|
52
|
+
xml.value outcome_declaration.defaultValue
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def xml_assessment_section(xml)
|
59
|
+
xml.assessmentSection('identifier' => 'S1', 'visible' => 'true', 'title' => 'Section 1') do
|
60
|
+
assessment_test.items.each_with_index do |item, index|
|
61
|
+
xml.assessmentItemRef('identifier' => item.identifier, 'href' => "item-#{index + 1}.xml")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_imsmanifest_xml
|
67
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
68
|
+
xml.manifest(imsmanifest_attributes) do
|
69
|
+
manifest_metadata(xml)
|
70
|
+
manifest_resources(xml)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
File.open(File.join(package_root_path, 'imsmanifest.xml'), 'wb') do |f|
|
75
|
+
f.write builder.to_xml
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def manifest_metadata(xml)
|
80
|
+
xml.metadata do
|
81
|
+
xml.schema 'QTIv2.2 Package'
|
82
|
+
xml.schemaversion '1.0.0'
|
83
|
+
learning_object_metadata(xml)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def learning_object_metadata(xml)
|
88
|
+
imsmd_ns = xml['imsmd']
|
89
|
+
|
90
|
+
imsmd_ns.lom do
|
91
|
+
imsmd_ns.general do
|
92
|
+
imsmd_ns.identifier do
|
93
|
+
imsmd_ns.entry 'FB-02'
|
94
|
+
end
|
95
|
+
imsmd_ns.title do
|
96
|
+
imsmd_ns.string(assessment_test.title, 'language' => 'en')
|
97
|
+
end
|
98
|
+
imsmd_ns.language 'en'
|
99
|
+
imsmd_ns.description do
|
100
|
+
imsmd_ns.string('Instructure QTI package.' \
|
101
|
+
'Feedback XML used as an example of unprocessable entity', 'language' => 'en')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
keywords(xml)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def keywords(xml)
|
109
|
+
keywords = %w(feedback modal test inline block)
|
110
|
+
keywords.each do |keyword|
|
111
|
+
xml['imsmd'].keyword do
|
112
|
+
xml['imsmd'].string(keyword, 'language' => 'en')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def manifest_resources(xml)
|
118
|
+
xml.resources do
|
119
|
+
xml.resource('href' => 'assessment.xml', 'type' => 'imsqti_test_xmlv2p2', 'identifier' => 'TEST') do
|
120
|
+
xml.file('href' => 'assessment.xml')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def export_items
|
126
|
+
assessment_test.items.each_with_index do |assessment_item, index|
|
127
|
+
Qti::AssessmentItemExporter.new(index, assessment_item, package_root_path: package_root_path).export
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def assesment_test_attributes(args = {})
|
132
|
+
{ 'xmlns' => 'http://www.imsglobal.org/xsd/imsqti_v2p2', 'xmlns:xi' => 'http://www.w3.org/2001/XInclude',
|
133
|
+
'xmlns:m' => 'http://www.w3.org/1998/Math/MathML', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
134
|
+
'xsi:schemaLocation' => 'http://www.imsglobal.org/xsd/imsqti_v2p2' \
|
135
|
+
'http://www.imsglobal.org/xsd/qti/qtiv2p2/imsqti_v2p2.xsd' }.merge(args)
|
136
|
+
end
|
137
|
+
|
138
|
+
def imsmanifest_attributes
|
139
|
+
{ 'xmlns' => 'http://www.imsglobal.org/xsd/imscp_v1p1', 'xmlns:imsmd' => 'http://ltsc.ieee.org/xsd/LOM',
|
140
|
+
'xmlns:imsqti' => 'http://www.imsglobal.org/xsd/imsqti_v2p2', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
141
|
+
'xsi:schemaLocation' => 'http://www.imsglobal.org/xsd/imscp_v1p1 ' \
|
142
|
+
'http://www.imsglobal.org/xsd/qti/qtiv2p2/qtiv2p2_imscpv1p2_v1p0.xsd' \
|
143
|
+
'http://ltsc.ieee.org/xsd/LOM http://www.imsglobal.org/xsd/imsmd_loose_v1p3p2.xsd' \
|
144
|
+
'http://www.imsglobal.org/xsd/imsqti_metadata_v2p2' \
|
145
|
+
'http://www.imsglobal.org/xsd/qti/qtiv2p2/imsqti_metadata_v2p2.xsd' }
|
146
|
+
end
|
147
|
+
|
148
|
+
def compress_package
|
149
|
+
Zip::File.open(exported_file_path, 'w') do |zipfile|
|
150
|
+
add_all_files(zipfile, package_root_path)
|
151
|
+
end
|
152
|
+
|
153
|
+
FileUtils.rm_rf(package_root_path)
|
154
|
+
exported_file_path
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_all_files(zipfile, package_root_path)
|
158
|
+
Dir["#{package_root_path}/**/**"].each do |file|
|
159
|
+
begin
|
160
|
+
entry = file.sub(package_root_path + '/', '')
|
161
|
+
zipfile.add(entry, file)
|
162
|
+
rescue Zip::EntryExistsError
|
163
|
+
logger.info("#{file} already exists")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Qti
|
2
|
+
class ItemExporterFactory
|
3
|
+
EXPORTER_CLASS = { 'TrueFalse' => TrueFalseItemExporter }.freeze
|
4
|
+
|
5
|
+
def self.create(item, args = {})
|
6
|
+
exporter_class = EXPORTER_CLASS[item.interaction_type] || NullExporter
|
7
|
+
exporter_class.new(item, args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class NullExporter < ItemExporter
|
12
|
+
def export
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Qti::Exporter do
|
4
|
+
let(:assessment_test) do
|
5
|
+
Qti::ContentPackaging::AssessmentTest.new(
|
6
|
+
title: 'Example test',
|
7
|
+
items: [
|
8
|
+
Qti::ContentPackaging::AssessmentItem.new(
|
9
|
+
identifier: '1', title: 'Question 1', response: 'true',
|
10
|
+
interaction: Qti::ContentPackaging::ChoiceInteraction.new(
|
11
|
+
prompt: 'Is 1+1 equals 2?', maxChoices: 1,
|
12
|
+
choices: [
|
13
|
+
Qti::ContentPackaging::SimpleChoice.new(
|
14
|
+
identifier: 'true', body: 'True'
|
15
|
+
),
|
16
|
+
Qti::ContentPackaging::SimpleChoice.new(
|
17
|
+
identifier: 'false', body: 'False'
|
18
|
+
)
|
19
|
+
]
|
20
|
+
)
|
21
|
+
)
|
22
|
+
],
|
23
|
+
outcome_declarations: [
|
24
|
+
Qti::ContentPackaging::OutcomeDeclaration.new(
|
25
|
+
identifier: 'TEST_total', baseType: 'float', cardinality: 'single', defaultValue: 0.0
|
26
|
+
),
|
27
|
+
Qti::ContentPackaging::OutcomeDeclaration.new(
|
28
|
+
identifier: 'S1', baseType: 'float', cardinality: 'single', defaultValue: 0.0
|
29
|
+
)
|
30
|
+
]
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'creates the zip file' do
|
35
|
+
dir = Dir.mktmpdir
|
36
|
+
|
37
|
+
exporter = Qti::Exporter.new(assessment_test, package_root_path: dir)
|
38
|
+
exporter.export
|
39
|
+
|
40
|
+
expect(File.exist?(exporter.exported_file_path)).to be_truthy
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'contains an imsnanifest.xml and an assessment.xml files' do
|
44
|
+
dir = Dir.mktmpdir
|
45
|
+
|
46
|
+
exporter = Qti::Exporter.new(assessment_test, package_root_path: dir)
|
47
|
+
exporter.export
|
48
|
+
|
49
|
+
Zip::File.open(exporter.exported_file_path, 'r') do |zip_file|
|
50
|
+
expect(zip_file.glob('imsmanifest.xml').first).to be_present
|
51
|
+
expect(zip_file.glob('assessment.xml').first).to be_present
|
52
|
+
expect(zip_file.glob('item-1.xml').first).to be_present
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,58 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qti
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hannah Bottalla
|
8
|
+
- Robinson Rodríguez
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2017-
|
12
|
+
date: 2017-03-06 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 4.2.6
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 4.2.6
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: dry-struct
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.2.1
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.2.1
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rubyzip
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 1.2.0
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.2.0
|
13
56
|
- !ruby/object:Gem::Dependency
|
14
57
|
name: bundler
|
15
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +67,20 @@ dependencies:
|
|
24
67
|
- - "~>"
|
25
68
|
- !ruby/object:Gem::Version
|
26
69
|
version: '1.11'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: byebug
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 9.0.5
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 9.0.5
|
27
84
|
- !ruby/object:Gem::Dependency
|
28
85
|
name: rake
|
29
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,16 +168,28 @@ dependencies:
|
|
111
168
|
description:
|
112
169
|
email:
|
113
170
|
- hannah@instructure.com
|
114
|
-
-
|
171
|
+
- rrodriguez-bd@instructure.com
|
172
|
+
- quizzes@instructure.com
|
115
173
|
executables: []
|
116
174
|
extensions: []
|
117
175
|
extra_rdoc_files: []
|
118
176
|
files:
|
119
177
|
- README.md
|
120
178
|
- Rakefile
|
179
|
+
- lib/null_logger.rb
|
121
180
|
- lib/qti.rb
|
181
|
+
- lib/qti/assessment_item_exporter.rb
|
182
|
+
- lib/qti/content_packaging.rb
|
183
|
+
- lib/qti/content_packaging/assessment_item.rb
|
184
|
+
- lib/qti/content_packaging/assessment_test.rb
|
185
|
+
- lib/qti/content_packaging/choice_interaction.rb
|
186
|
+
- lib/qti/content_packaging/outcome_declaration.rb
|
187
|
+
- lib/qti/content_packaging/simple_choice.rb
|
188
|
+
- lib/qti/exporter.rb
|
189
|
+
- lib/qti/item_exporter_factory.rb
|
122
190
|
- lib/qti/models/base.rb
|
123
191
|
- lib/qti/models/manifest.rb
|
192
|
+
- lib/qti/true_false_item_exporter.rb
|
124
193
|
- lib/qti/v1/models/assessment.rb
|
125
194
|
- lib/qti/v1/models/assessment_item.rb
|
126
195
|
- lib/qti/v1/models/base.rb
|
@@ -297,6 +366,7 @@ files:
|
|
297
366
|
- spec/fixtures/tests/tests/rtest25.xml
|
298
367
|
- spec/fixtures/tests/tests/rtest26.xml
|
299
368
|
- spec/fixtures/tests/tests/rtest27.xml
|
369
|
+
- spec/qti/exporter_spec.rb
|
300
370
|
- spec/qti/models/base_spec.rb
|
301
371
|
- spec/qti/models/manifest_spec.rb
|
302
372
|
- spec/qti/v1/models/assessment_item_spec.rb
|
@@ -496,6 +566,7 @@ test_files:
|
|
496
566
|
- spec/fixtures/tests/tests/rtest25.xml
|
497
567
|
- spec/fixtures/tests/tests/rtest26.xml
|
498
568
|
- spec/fixtures/tests/tests/rtest27.xml
|
569
|
+
- spec/qti/exporter_spec.rb
|
499
570
|
- spec/qti/models/base_spec.rb
|
500
571
|
- spec/qti/models/manifest_spec.rb
|
501
572
|
- spec/qti/v1/models/assessment_item_spec.rb
|