canvas_qti_to_learnosity_converter 2.2.0 → 2.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e102ffcbd4d59f3fb3e466bdfada0f614ed1ae8438e2e63322454d1585203f7
4
- data.tar.gz: 8f52c78fc0e604827e947095e4ca12ed2a1da248a2d97fa9ca18721da255e0c7
3
+ metadata.gz: a2f612956cbc00ab89e47a628c2c7d9007053f1533f5ec5cf5d6f6066b5d0b95
4
+ data.tar.gz: 196ec2ae80fee84fd92812a7d720218efc9219c7f97fb11c04b79681b093657f
5
5
  SHA512:
6
- metadata.gz: 96621e2221a06448c6a351cee7f460ef5067c470cc84102b9b2e37bab8d8d6e77c9ee81ca006d7336cffb42ac4d1972b3a957eb2e31f8f7f8fd2b3125ffc8d70
7
- data.tar.gz: e184a67f1c709ed6189bb2d7fe8aee3484d03a2f0a8ee25747fed902c3fbe78f62634f4f2aa878976624e70c5f97eef551e49dc7300981f4ba19a4b7b982ec69
6
+ metadata.gz: 8289a948c65d4506923e9097c1bfbef83cd1e7b89f2a2d80ce6bd86eb86b416948883ef81a693a574b09a4187d37c7a6fb73259e838c5a7296c917d952f78c65
7
+ data.tar.gz: 2a4a8d92ec9a9739cb4048c7698e61af46c0ad9691a4d154f49573c1ce6e38c3d0c3b12e25db1cea931c017303f58bd6b04afac42c58a34e1bfffcf235cbc208
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /vendor/
9
10
 
10
11
  .byebug_history
11
12
 
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  end
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.16"
21
+ spec.add_development_dependency "bundler", "~> 2.3"
22
22
  spec.add_development_dependency "byebug"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
  spec.add_development_dependency "rspec", "~> 3.0"
@@ -45,6 +45,11 @@ module CanvasQtiToLearnosityConverter
45
45
  }
46
46
 
47
47
  class CanvasQuestionTypeNotSupportedError < RuntimeError
48
+ attr_reader :question_type
49
+ def initialize(question_type)
50
+ @question_type = question_type.to_s
51
+ super("Unsupported question type #{@question_type}")
52
+ end
48
53
  end
49
54
 
50
55
  class CanvasQtiQuiz
@@ -78,8 +83,8 @@ module CanvasQtiToLearnosityConverter
78
83
  end
79
84
 
80
85
  def self.add_files_to_assets(assets, path, text)
81
- text.scan(/%24IMS-CC-FILEBASE%24\/([^"]+)/).flatten.each do |asset_path|
82
- decoded_path = URI.unescape(asset_path)
86
+ text.scan(/(%24|\$)IMS-CC-FILEBASE\1\/([^"]+)/) do |_delimiter, asset_path|
87
+ decoded_path = CGI.unescape(asset_path)
83
88
  assets[decoded_path] ||= []
84
89
  assets[decoded_path].push(path)
85
90
  end
@@ -106,7 +111,7 @@ module CanvasQtiToLearnosityConverter
106
111
  if question_class
107
112
  question = question_class.new(xml)
108
113
  else
109
- raise CanvasQuestionTypeNotSupportedError
114
+ raise CanvasQuestionTypeNotSupportedError.new(type)
110
115
  end
111
116
 
112
117
  [learnosity_type, question]
@@ -116,19 +121,22 @@ module CanvasQtiToLearnosityConverter
116
121
  title.gsub(/["']/, "")
117
122
  end
118
123
 
119
- def self.convert(qti, assets)
124
+ def self.convert(qti, assets, errors)
120
125
  quiz = CanvasQtiQuiz.new(qti_string: qti)
121
126
  assessment = quiz.css("assessment")
122
127
  ident = assessment.attribute("ident").value
123
128
  assets[ident] = {}
129
+ errors[ident] = []
124
130
 
125
131
  items = []
126
132
 
127
133
  quiz.css("item").each.with_index do |item, index|
128
134
  begin
135
+ item_title = item.attribute("title").value
129
136
  learnosity_type, quiz_item = convert_item(qti_string: item.to_html)
130
137
 
131
138
  item = {
139
+ title: item_title,
132
140
  type: learnosity_type,
133
141
  data: quiz_item.to_learnosity,
134
142
  dynamic_content_data: quiz_item.dynamic_content_data()
@@ -138,8 +146,19 @@ module CanvasQtiToLearnosityConverter
138
146
  path = [items.count - 1, :data]
139
147
 
140
148
  quiz_item.add_learnosity_assets(assets[ident], path)
141
- rescue CanvasQuestionTypeNotSupportedError
142
- nil
149
+ rescue CanvasQuestionTypeNotSupportedError => e
150
+ errors[ident].push({
151
+ index: index,
152
+ error_type: "unsupported_question",
153
+ question_type: e.question_type.to_s,
154
+ message: e.message,
155
+ })
156
+ rescue StandardError => e
157
+ errors[ident].push({
158
+ index: index,
159
+ error_type: e.class.to_s,
160
+ message: e.message,
161
+ })
143
162
  end
144
163
  end
145
164
 
@@ -172,14 +191,16 @@ module CanvasQtiToLearnosityConverter
172
191
  paths = imscc_quiz_paths(parsed_manifest)
173
192
 
174
193
  assets = {}
194
+ errors = {}
175
195
  converted_assesments = paths.map do |qti_path|
176
196
  qti = zip_file.find_entry(qti_path).get_input_stream.read
177
- convert(qti, assets)
197
+ convert(qti, assets, errors)
178
198
  end
179
199
 
180
200
  {
181
201
  assessments: converted_assesments,
182
202
  assets: assets,
203
+ errors: errors,
183
204
  }
184
205
  end
185
206
  end
@@ -28,6 +28,7 @@ module CanvasQtiToLearnosityConverter
28
28
  {
29
29
  "scoring_type" => "exactMatch",
30
30
  "valid_response" => {
31
+ "score" => extract_points_possible,
31
32
  "value" => [[{
32
33
  "method" => "equivValue",
33
34
  "value" => "{{var:answer}}\\pm#{pm}"
@@ -6,6 +6,9 @@ module CanvasQtiToLearnosityConverter
6
6
  {
7
7
  type: "longtextV2",
8
8
  stimulus: extract_stimulus(),
9
+ validation: {
10
+ max_score: extract_points_possible,
11
+ },
9
12
  }
10
13
  end
11
14
 
@@ -6,6 +6,9 @@ module CanvasQtiToLearnosityConverter
6
6
  {
7
7
  type: "fileupload",
8
8
  stimulus: extract_stimulus(),
9
+ validation: {
10
+ max_score: extract_points_possible,
11
+ },
9
12
  allow_pdf: true,
10
13
  allow_jpg: true,
11
14
  allow_gif: true,
@@ -42,7 +42,8 @@ module CanvasQtiToLearnosityConverter
42
42
  create_responses(responses, 0, all_responses, [])
43
43
 
44
44
  {
45
- "scoring_type" => "partialMatch",
45
+ "scoring_type" => "partialMatchV2",
46
+ "rounding" => "none",
46
47
  "valid_response" => all_responses.shift,
47
48
  "alt_responses" => all_responses
48
49
  }
@@ -50,7 +51,7 @@ module CanvasQtiToLearnosityConverter
50
51
 
51
52
  def create_responses(blank_responses, depth, result, current_response)
52
53
  if depth == blank_responses.count
53
- result.push({ "value" => current_response })
54
+ result.push({ "score" => extract_points_possible, "value" => current_response })
54
55
  return
55
56
  end
56
57
 
@@ -4,19 +4,20 @@ module CanvasQtiToLearnosityConverter
4
4
  class MatchingQuestion < QuizQuestion
5
5
  def to_learnosity
6
6
  {
7
- type: "association",
7
+ type: "clozedropdown",
8
8
  stimulus: extract_stimulus(),
9
- stimulus_list: extract_stimulus_list(),
9
+ template: extract_template(),
10
10
  validation: extract_validation(),
11
11
  possible_responses: extract_responses(),
12
12
  duplicate_responses: true,
13
+ shuffle_options: true,
13
14
  }
14
15
  end
15
16
 
16
- def extract_stimulus_list()
17
+ def extract_template()
17
18
  @xml.css("item > presentation > response_lid > material > mattext").map do |node|
18
- extract_mattext(node)
19
- end
19
+ "<p>#{extract_mattext(node)} {{response}}</p>"
20
+ end.join("\n")
20
21
  end
21
22
 
22
23
  def extract_response_idents()
@@ -48,18 +49,20 @@ module CanvasQtiToLearnosityConverter
48
49
  end.flatten
49
50
 
50
51
  {
51
- "scoring_type" => "partialMatch",
52
+ "scoring_type" => "partialMatchV2",
53
+ "rounding" => "none",
52
54
  "valid_response" => {
53
- "value" => valid_responses
55
+ "value" => valid_responses,
56
+ "score" => extract_points_possible,
54
57
  }
55
58
  }
56
59
  end
57
60
 
58
61
  def extract_responses()
59
- response_node = @xml.css("item > presentation > response_lid").first
60
-
61
- response_node.css("response_label mattext").map do |node|
62
- extract_mattext(node)
62
+ @xml.css("item > presentation > response_lid").map do |response|
63
+ response.css("response_label mattext").map do |node|
64
+ extract_mattext(node)
65
+ end
63
66
  end
64
67
  end
65
68
 
@@ -30,6 +30,7 @@ module CanvasQtiToLearnosityConverter
30
30
  "scoring_type" => "exactMatch",
31
31
  "valid_response" => {
32
32
  "value" => [correct_value],
33
+ "score" => extract_points_possible,
33
34
  },
34
35
  }
35
36
  end
@@ -81,8 +82,13 @@ module CanvasQtiToLearnosityConverter
81
82
  and > varequal')
82
83
  alt_responses = correct_condition.map(&:text)
83
84
  {
84
- "scoring_type" => "partialMatch",
85
- "alt_responses" => alt_responses,
85
+ "scoring_type" => "partialMatchV2",
86
+ "rounding" => "none",
87
+ "penalty" => extract_points_possible,
88
+ "valid_response" => {
89
+ "score" => extract_points_possible,
90
+ "value" => alt_responses,
91
+ },
86
92
  }
87
93
  end
88
94
  end
@@ -28,9 +28,11 @@ module CanvasQtiToLearnosityConverter
28
28
  end.flatten
29
29
 
30
30
  {
31
- "scoring_type" => "partialMatch",
31
+ "scoring_type" => "partialMatchV2",
32
+ "rounding" => "none",
32
33
  "valid_response" => {
33
34
  "value" => valid_responses,
35
+ "score" => extract_points_possible,
34
36
  }
35
37
  }
36
38
  end
@@ -41,6 +41,7 @@ module CanvasQtiToLearnosityConverter
41
41
  "value" => [{
42
42
  "method" => "equivValue",
43
43
  "value" => "#{bounds[:center]}\\pm#{bounds[:pm]}",
44
+ "score" => extract_points_possible,
44
45
  }]
45
46
  }
46
47
  end
@@ -14,6 +14,12 @@ module CanvasQtiToLearnosityConverter
14
14
  extract_mattext(mattext)
15
15
  end
16
16
 
17
+ def extract_points_possible
18
+ @xml.css(%{ item > itemmetadata > qtimetadata >
19
+ qtimetadatafield > fieldlabel:contains("points_possible")})
20
+ &.first&.next&.text&.to_f || 1.0
21
+ end
22
+
17
23
  def extract_mattext(mattext_node)
18
24
  mattext_node.content
19
25
  end
@@ -20,11 +20,11 @@ module CanvasQtiToLearnosityConverter
20
20
  def extract_validation()
21
21
  correct_responses = @xml.css('item > resprocessing >
22
22
  respcondition[continue="No"] > conditionvar > varequal')
23
- correct_response = { "value" => correct_responses.shift.text }
23
+ correct_response = { "value" => correct_responses.shift.text, "score" => extract_points_possible}
24
24
  {
25
25
  "scoring_type" => "exactMatch",
26
26
  "valid_response" => correct_response,
27
- "alt_responses" => correct_responses.map { |res| { "value" => res.text } }
27
+ "alt_responses" => correct_responses.map { |res| { "value" => res.text, "score" => extract_points_possible } }
28
28
  }
29
29
  end
30
30
 
@@ -1,3 +1,3 @@
1
1
  module CanvasQtiToLearnosityConverter
2
- VERSION = "2.2.0"
2
+ VERSION = "2.4.0"
3
3
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canvas_qti_to_learnosity_converter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Atomic Jolt
8
8
  - Nick Benoit
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-08-13 00:00:00.000000000 Z
12
+ date: 2022-10-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '1.16'
20
+ version: '2.3'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '1.16'
27
+ version: '2.3'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: byebug
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -95,7 +95,7 @@ dependencies:
95
95
  - - ">="
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
- description:
98
+ description:
99
99
  email:
100
100
  - support@atomicjolt.com
101
101
  executables: []
@@ -132,7 +132,7 @@ homepage: https://github.com/atomicjolt/qti_to_learnosity_converter
132
132
  licenses:
133
133
  - MIT
134
134
  metadata: {}
135
- post_install_message:
135
+ post_install_message:
136
136
  rdoc_options: []
137
137
  require_paths:
138
138
  - lib
@@ -147,9 +147,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
147
  - !ruby/object:Gem::Version
148
148
  version: '0'
149
149
  requirements: []
150
- rubyforge_project:
151
- rubygems_version: 2.7.6
152
- signing_key:
150
+ rubygems_version: 3.3.15
151
+ signing_key:
153
152
  specification_version: 4
154
153
  summary: Converts canvas qti to learnosity JSON
155
154
  test_files: []