qti 1.0.11 → 2.0.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/qti.rb +72 -19
  4. data/lib/qti/content_packaging.rb +0 -8
  5. data/lib/qti/models/assessment_meta.rb +0 -2
  6. data/lib/qti/models/base.rb +0 -5
  7. data/lib/qti/models/manifest.rb +1 -7
  8. data/lib/qti/models/metadata.rb +0 -7
  9. data/lib/qti/models/resource.rb +4 -10
  10. data/lib/qti/sanitizer.rb +0 -4
  11. data/lib/qti/v1/models/assessment.rb +1 -3
  12. data/lib/qti/v1/models/assessment_item.rb +0 -3
  13. data/lib/qti/v1/models/base.rb +0 -2
  14. data/lib/qti/v1/models/choices/fill_blank_choice.rb +0 -2
  15. data/lib/qti/v1/models/choices/logical_identifier_choice.rb +0 -2
  16. data/lib/qti/v1/models/interactions.rb +0 -4
  17. data/lib/qti/v1/models/interactions/base_fill_blank_interaction.rb +1 -1
  18. data/lib/qti/v1/models/interactions/formula_interaction.rb +2 -4
  19. data/lib/qti/v1/models/interactions/match_interaction.rb +2 -2
  20. data/lib/qti/v1/models/numerics/exact_match.rb +0 -2
  21. data/lib/qti/v1/models/numerics/margin_error.rb +0 -2
  22. data/lib/qti/v1/models/numerics/precision.rb +1 -3
  23. data/lib/qti/v1/models/numerics/within_range.rb +0 -2
  24. data/lib/qti/v1/models/question_group.rb +0 -3
  25. data/lib/qti/v2/models/assessment_item.rb +0 -3
  26. data/lib/qti/v2/models/assessment_test.rb +2 -5
  27. data/lib/qti/v2/models/base.rb +0 -2
  28. data/lib/qti/v2/models/choices/gap_match_choice.rb +0 -2
  29. data/lib/qti/v2/models/choices/simple_associable_choice.rb +0 -2
  30. data/lib/qti/v2/models/choices/simple_choice.rb +0 -2
  31. data/lib/qti/v2/models/interactions.rb +0 -3
  32. data/lib/qti/v2/models/interactions/ordering_interaction.rb +0 -2
  33. data/lib/qti/v2/models/non_assessment_test.rb +2 -4
  34. data/lib/qti/version.rb +1 -1
  35. data/spec/gemfiles/nokogiri-1.6.gemfile.lock +149 -0
  36. data/spec/gemfiles/nokogiri-1.8.gemfile.lock +149 -0
  37. data/spec/gemfiles/rails-5.2.gemfile.lock +222 -0
  38. data/spec/gemfiles/{rails-5.0.gemfile → rails-6.0.gemfile} +1 -1
  39. data/spec/lib/qti/assessment_item_exporter_spec.rb +17 -21
  40. data/spec/lib/qti/exporter_spec.rb +73 -81
  41. data/spec/lib/qti/models/assessment_meta_spec.rb +0 -2
  42. data/spec/lib/qti/models/base_spec.rb +20 -15
  43. data/spec/lib/qti/models/manifest_spec.rb +0 -2
  44. data/spec/lib/qti/models/metadata_spec.rb +0 -2
  45. data/spec/lib/qti/models/resource_spec.rb +0 -2
  46. data/spec/lib/qti/v1/models/assessment_item_spec.rb +9 -13
  47. data/spec/lib/qti/v1/models/assessment_spec.rb +3 -6
  48. data/spec/lib/qti/v1/models/choices/fill_blank_choice_spec.rb +0 -2
  49. data/spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb +0 -2
  50. data/spec/lib/qti/v1/models/interactions/base_interaction_spec.rb +1 -3
  51. data/spec/lib/qti/v1/models/interactions/canvas_multiple_dropdown_spec.rb +0 -2
  52. data/spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb +0 -2
  53. data/spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb +0 -2
  54. data/spec/lib/qti/v1/models/interactions/formula_interaction_spec.rb +0 -2
  55. data/spec/lib/qti/v1/models/interactions/match_interaction_spec.rb +0 -2
  56. data/spec/lib/qti/v1/models/interactions/numeric_interaction_spec.rb +0 -2
  57. data/spec/lib/qti/v1/models/interactions/ordering_interaction_spec.rb +0 -2
  58. data/spec/lib/qti/v1/models/interactions/string_interaction_spec.rb +0 -2
  59. data/spec/lib/qti/v1/models/interactions/upload_interaction_spec.rb +0 -2
  60. data/spec/lib/qti/v1/models/interactions_spec.rb +0 -2
  61. data/spec/lib/qti/v1/models/numerics/exact_match_spec.rb +0 -2
  62. data/spec/lib/qti/v1/models/numerics/margin_error_spec.rb +0 -2
  63. data/spec/lib/qti/v1/models/numerics/precision_spec.rb +0 -2
  64. data/spec/lib/qti/v1/models/numerics/scoring_base_spec.rb +0 -2
  65. data/spec/lib/qti/v1/models/numerics/scoring_node_spec.rb +0 -2
  66. data/spec/lib/qti/v1/models/numerics/within_range_spec.rb +0 -2
  67. data/spec/lib/qti/v1/models/question_group_spec.rb +0 -2
  68. data/spec/lib/qti/v1/models/stimulus_item_spec.rb +0 -2
  69. data/spec/lib/qti/v2/models/assessment_item_spec.rb +0 -2
  70. data/spec/lib/qti/v2/models/assessment_test_spec.rb +1 -4
  71. data/spec/lib/qti/v2/models/choices/gap_match_choice_spec.rb +0 -2
  72. data/spec/lib/qti/v2/models/choices/simple_associable_choice_spec.rb +0 -2
  73. data/spec/lib/qti/v2/models/choices/simple_choice_spec.rb +0 -2
  74. data/spec/lib/qti/v2/models/interactions/categorization_interaction_spec.rb +0 -2
  75. data/spec/lib/qti/v2/models/interactions/choice_interaction_spec.rb +0 -2
  76. data/spec/lib/qti/v2/models/interactions/extended_text_interaction_spec.rb +0 -2
  77. data/spec/lib/qti/v2/models/interactions/gap_match_interaction_spec.rb +0 -2
  78. data/spec/lib/qti/v2/models/interactions/match_interaction_spec.rb +0 -2
  79. data/spec/lib/qti/v2/models/interactions/ordering_interaction_spec.rb +0 -2
  80. data/spec/lib/qti/v2/models/interactions/short_text_interaction_spec.rb +0 -2
  81. data/spec/lib/qti/v2/models/non_assessment_test_spec.rb +0 -2
  82. data/spec/lib/qti/v2/models/object_element_spec.rb +0 -2
  83. data/spec/lib/qti/v2/models/stimulus_item_spec.rb +0 -2
  84. data/spec/lib/qti_spec.rb +0 -2
  85. data/spec/spec_helper.rb +5 -7
  86. data/spec/support/custom_matchers.rb +0 -2
  87. metadata +70 -70
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '0369a1eaf87bdecfae0f4c08e738088d1c065ee3'
4
- data.tar.gz: 7d9672b8b3e612cd0458730e17abd25a23458763
3
+ metadata.gz: e4aee322bc3949281194bb63959f4ef4bf084d03
4
+ data.tar.gz: 782d6a831b7ec7c309781592924d1b683e6e2407
5
5
  SHA512:
6
- metadata.gz: 387299550290124d9825e0195ea6f3ba4b3bc2137d7caf75ac94908584daaf2c5b59155ae9394d47c4849dcbc1d82aeb86825c90a9932b1ce9447bb55291aeab
7
- data.tar.gz: 74f0d0de3c9e519c899e84ffadfabd0df9fde95078da77b6114273dcbed97aad1751603739aa1d27b557eef4550d1abf25fea6d7e6ea5aadd21a8dcd694fcdaa
6
+ metadata.gz: ba7ecb2c6765ed021d6ff31d90918b9dc7ce52f8ba62d107e69f52fbd896939417e7d016401bdecdc5f55bf28bfb146b1c424c7dc2819ec7331b83622107ace8
7
+ data.tar.gz: 0edb24529f59bf862e4687aa09d0a3c6e5f703c9ef4f947947de92e5dcedde7fddf8b887607b5489ba00c8755fc79638f2cc7b4d5f2b3c59e92f4f99e5233986
data/README.md CHANGED
@@ -81,7 +81,7 @@ Individual spec runs can be started like so:
81
81
 
82
82
  ```bash
83
83
  docker-compose run --rm app /bin/bash -l -c \
84
- "BUNDLE_GEMFILE=spec/gemfiles/rails-5.2.gemfile rvm-exec 2.5 rspec"
84
+ "BUNDLE_GEMFILE=spec/gemfiles/rails-6.0.gemfile rvm-exec 2.5 rspec"
85
85
  ```
86
86
 
87
87
  If you'd like to mount your git checkout within the docker container running
data/lib/qti.rb CHANGED
@@ -1,4 +1,16 @@
1
+ require 'action_view'
2
+ require 'active_support/core_ext/array/access'
3
+ require 'active_support/core_ext/string'
4
+ require 'active_support/core_ext/hash/except'
5
+ require 'active_support/core_ext/module/delegation'
6
+ require 'dry-struct'
1
7
  require 'find'
8
+ require 'mathml2latex'
9
+ require 'nokogiri'
10
+ require 'pathname'
11
+ require 'sanitize'
12
+ require 'uri'
13
+ require 'zip'
2
14
 
3
15
  module Qti
4
16
  class Importer
@@ -57,22 +69,60 @@ module Qti
57
69
  end
58
70
  end
59
71
 
60
- require 'active_support/core_ext/string'
61
- require 'active_support/core_ext/module/delegation'
72
+ # The load order of all of these is important.
73
+
74
+ require 'null_logger'
75
+
76
+ require 'qti/version'
77
+
78
+ require 'qti/assessment_item_exporter'
79
+ require 'qti/content_packaging'
80
+ require 'qti/exporter'
81
+ require 'qti/sanitizer'
82
+ require 'qti/xpath_helpers'
83
+
84
+ require 'qti/content_packaging/simple_choice'
85
+ require 'qti/content_packaging/choice_interaction'
86
+ require 'qti/content_packaging/assessment_item'
87
+ require 'qti/content_packaging/outcome_declaration'
88
+ require 'qti/content_packaging/assessment_test'
62
89
 
63
- require 'qti/models/manifest'
64
90
  require 'qti/models/base'
91
+ require 'qti/models/assessment_meta'
65
92
 
66
93
  require 'qti/v1/models/base'
67
- require 'qti/v1/models/interactions/base_interaction'
68
- require 'qti/v1/models/interactions/base_fill_blank_interaction'
69
- require 'qti/v1/models/interactions/choice_interaction'
70
-
71
94
  require 'qti/v1/models/assessment'
95
+
96
+ require 'qti/v2/models/base'
97
+ require 'qti/v2/models/assessment_test'
98
+
99
+ require 'qti/models/metadata'
100
+ require 'qti/models/resource'
101
+ require 'qti/models/manifest'
102
+
72
103
  require 'qti/v1/models/assessment_item'
73
104
  require 'qti/v1/models/choices/logical_identifier_choice'
74
105
  require 'qti/v1/models/choices/fill_blank_choice'
75
106
  require 'qti/v1/models/scoring_data'
107
+ require 'qti/v1/models/stimulus_item'
108
+ require 'qti/v1/models/question_group'
109
+
110
+ require 'qti/v1/models/interactions/base_interaction'
111
+ require 'qti/v1/models/interactions/choice_interaction'
112
+
113
+ require 'qti/v1/models/interactions/base_fill_blank_interaction'
114
+ require 'qti/v1/models/interactions/canvas_multiple_dropdown'
115
+ require 'qti/v1/models/interactions/fill_blank_interaction'
116
+ require 'qti/v1/models/interactions/formula_interaction'
117
+ require 'qti/v1/models/interactions/match_interaction'
118
+ require 'qti/v1/models/interactions/numeric_interaction'
119
+ require 'qti/v1/models/interactions/ordering_interaction'
120
+ require 'qti/v1/models/interactions/string_interaction'
121
+ require 'qti/v1/models/interactions/upload_interaction'
122
+
123
+ require 'qti/v1/models/interactions'
124
+
125
+ require 'qti/v1/models/numerics/scoring_base'
76
126
 
77
127
  require 'qti/v1/models/numerics/exact_match'
78
128
  require 'qti/v1/models/numerics/margin_error'
@@ -80,23 +130,26 @@ require 'qti/v1/models/numerics/precision'
80
130
  require 'qti/v1/models/numerics/scoring_data'
81
131
  require 'qti/v1/models/numerics/scoring_node'
82
132
  require 'qti/v1/models/numerics/within_range'
83
- require 'qti/v1/models/stimulus_item'
84
- require 'qti/v1/models/question_group'
85
133
 
86
- require 'qti/v2/models/base'
87
- require 'qti/v2/models/choices/simple_choice'
88
- require 'qti/v2/models/choices/simple_associable_choice'
89
- require 'qti/v2/models/choices/gap_match_choice'
90
134
  require 'qti/v2/models/assessment_item'
91
135
  require 'qti/v2/models/stimulus_item'
92
- require 'qti/v2/models/assessment_test'
136
+ require 'qti/v2/models/interactions'
93
137
  require 'qti/v2/models/non_assessment_test'
94
138
  require 'qti/v2/models/scoring_data'
95
139
 
96
- require 'zip'
97
- require 'qti/exporter'
140
+ require 'qti/v2/models/interactions/base_interaction'
98
141
 
99
- require 'qti/content_packaging'
100
- require 'qti/assessment_item_exporter'
142
+ require 'qti/v2/models/interactions/categorization_interaction'
143
+ require 'qti/v2/models/interactions/choice_interaction'
144
+ require 'qti/v2/models/interactions/extended_text_interaction'
145
+ require 'qti/v2/models/interactions/gap_match_interaction'
146
+ require 'qti/v2/models/interactions/match_interaction'
147
+ require 'qti/v2/models/interactions/ordering_interaction'
148
+ require 'qti/v2/models/interactions/short_text_interaction'
101
149
 
102
- require 'null_logger'
150
+ require 'qti/v2/models/interactions/match_item_tag_processors/associate_interaction_tag_processor'
151
+ require 'qti/v2/models/interactions/match_item_tag_processors/match_interaction_tag_processor'
152
+
153
+ require 'qti/v2/models/choices/simple_choice'
154
+ require 'qti/v2/models/choices/simple_associable_choice'
155
+ require 'qti/v2/models/choices/gap_match_choice'
@@ -1,5 +1,3 @@
1
- require 'dry-struct'
2
-
3
1
  module Qti
4
2
  module ContentPackaging
5
3
  module Types
@@ -7,9 +5,3 @@ module Qti
7
5
  end
8
6
  end
9
7
  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'
@@ -1,5 +1,3 @@
1
- require 'qti/v1/models/base'
2
-
3
1
  module Qti
4
2
  module Models
5
3
  class AssessmentMeta < Qti::Models::Base
@@ -1,8 +1,3 @@
1
- require 'nokogiri'
2
- require 'pathname'
3
- require 'mathml2latex'
4
- require 'qti/sanitizer'
5
-
6
1
  module Qti
7
2
  class ParseError < StandardError; end
8
3
  class SpecificationViolation < StandardError; end
@@ -1,15 +1,9 @@
1
- require 'qti/v1/models/base'
2
- require 'qti/models/assessment_meta'
3
- require 'qti/v1/models/assessment'
4
- require 'qti/v2/models/assessment_test'
5
- require 'qti/v2/models/non_assessment_test'
6
- require 'qti/models/resource'
7
-
8
1
  module Qti
9
2
  module Models
10
3
  class Manifest < Qti::Models::Base
11
4
  include Qti::Models::ResourceGroup
12
5
  include Qti::XPathHelpers
6
+
13
7
  def assessment_test(resource_id = nil)
14
8
  resource_id ||= assessment_identifiers.first
15
9
  test = assessment_from_identifier(resource_id)
@@ -52,12 +52,5 @@ module Qti
52
52
  taxon(node.xpath('imsmd:taxon')&.first, path)
53
53
  end
54
54
  end
55
-
56
- module MetaDataBase
57
- delegate :taxonpath, to: :@meta_data, allow_nil: true
58
- def metadata_from_node!(node)
59
- @meta_data ||= MetaData.new(node)
60
- end
61
- end
62
55
  end
63
56
  end
@@ -1,16 +1,10 @@
1
- require 'qti/v1/models/base'
2
- require 'qti/models/assessment_meta'
3
- require 'qti/v1/models/assessment'
4
- require 'qti/v2/models/assessment_test'
5
- require 'qti/v2/models/non_assessment_test'
6
- require 'qti/xpath_helpers'
7
- require 'qti/models/metadata'
8
-
9
1
  module Qti
10
2
  module Models
11
3
  class Resource < Qti::Models::Base
12
- include Qti::Models::MetaDataBase
13
4
  include Qti::XPathHelpers
5
+
6
+ delegate :taxonpath, to: :@metadata, allow_nil: true
7
+
14
8
  def initialize(node, parent)
15
9
  @node = node
16
10
  @parent = parent
@@ -24,7 +18,7 @@ module Qti
24
18
  end
25
19
 
26
20
  def metadata
27
- @metadata = metadata_from_node!(@node)
21
+ @metadata ||= MetaData.new(@node)
28
22
  end
29
23
 
30
24
  def canvas_metadata
@@ -1,7 +1,3 @@
1
- require 'nokogiri'
2
- require 'sanitize'
3
- require 'uri'
4
-
5
1
  module Qti
6
2
  class Sanitizer
7
3
  ELEMENTS_REMAP = {
@@ -1,11 +1,9 @@
1
- require 'qti/v1/models/base'
2
- require 'qti/models/assessment_meta'
3
-
4
1
  module Qti
5
2
  module V1
6
3
  module Models
7
4
  class Assessment < Qti::V1::Models::Base
8
5
  include Qti::Models::AssessmentMetaBase
6
+
9
7
  GROUP_ID = 'xmlns:section/xmlns:selection_ordering'.freeze
10
8
 
11
9
  def title
@@ -1,6 +1,3 @@
1
- require 'qti/v1/models/base'
2
- require 'qti/v1/models/interactions'
3
-
4
1
  module Qti
5
2
  module V1
6
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/models/base'
2
-
3
1
  module Qti
4
2
  module V1
5
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/v1/models/base'
2
-
3
1
  module Qti
4
2
  module V1
5
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/v1/models/base'
2
-
3
1
  module Qti
4
2
  module V1
5
3
  module Models
@@ -1,7 +1,3 @@
1
- require 'active_support/core_ext/hash/except'
2
- # Populate the subclasses
3
- Dir["#{__dir__}/interactions/*.rb"].each { |f| load f }
4
-
5
1
  module Qti
6
2
  module V1
7
3
  module Models
@@ -3,7 +3,7 @@ module Qti
3
3
  module Models
4
4
  module Interactions
5
5
  class BaseFillBlankInteraction < BaseInteraction
6
- CANVAS_REGEX ||= /(\[.+?\])/
6
+ CANVAS_REGEX ||= /(\[.+?\])/.freeze
7
7
 
8
8
  def canvas_stem_items(item_prompt)
9
9
  item_prompt.split(CANVAS_REGEX).map.with_index do |stem_item, index|
@@ -37,13 +37,11 @@ module Qti
37
37
  end
38
38
 
39
39
  def answer_tolerance
40
- @answer_tolernance ||= @node.at_xpath('.//xmlns:answer_tolerance').text
40
+ @answer_tolerance ||= @node.at_xpath('.//xmlns:answer_tolerance').text
41
41
  end
42
42
 
43
43
  def margin_of_error
44
- if answer_tolerance.ends_with? '%'
45
- return { margin: answer_tolerance[0..-2], margin_type: 'percent' }
46
- end
44
+ return { margin: answer_tolerance[0..-2], margin_type: 'percent' } if answer_tolerance.ends_with? '%'
47
45
  { margin: answer_tolerance, margin_type: 'absolute' }
48
46
  end
49
47
 
@@ -26,7 +26,7 @@ module Qti
26
26
  end
27
27
 
28
28
  def scoring_data_structs
29
- @scoring_data ||= parse_scoring_data
29
+ @scoring_data_structs ||= parse_scoring_data
30
30
  end
31
31
 
32
32
  def distractors
@@ -38,7 +38,7 @@ module Qti
38
38
  private
39
39
 
40
40
  def parse_scoring_data
41
- # This preserves the original behavior while not breaking on itemfeedback
41
+ # This preserves the original behavior while not breaking on item feedback
42
42
  path = './/xmlns:respcondition/xmlns:setvar/../xmlns:conditionvar/xmlns:varequal'
43
43
  matches = node.xpath(path).map do |node|
44
44
  [node.attributes['respident'].value, answers_map[node.content]]
@@ -1,5 +1,3 @@
1
- require 'qti/v1/models/numerics/scoring_base'
2
-
3
1
  module Qti
4
2
  module V1
5
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/v1/models/numerics/scoring_base'
2
-
3
1
  module Qti
4
2
  module V1
5
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/v1/models/numerics/scoring_base'
2
-
3
1
  module Qti
4
2
  module V1
5
3
  module Models
@@ -55,7 +53,7 @@ module Qti
55
53
  end
56
54
  # this is not exactly significant digits
57
55
  # trailing zeros are ignored
58
- # because gt_node and lte_ndoe don't expect trailing zeros
56
+ # because gt_node and lte_node don't expect trailing zeros
59
57
  sig
60
58
  end
61
59
  end
@@ -1,5 +1,3 @@
1
- require 'qti/v1/models/numerics/scoring_base'
2
-
3
1
  module Qti
4
2
  module V1
5
3
  module Models
@@ -1,6 +1,3 @@
1
- require 'qti/v1/models/base'
2
- require 'qti/v1/models/interactions'
3
-
4
1
  module Qti
5
2
  module V1
6
3
  module Models
@@ -1,6 +1,3 @@
1
- require 'qti/v2/models/base'
2
- require 'qti/v2/models/interactions'
3
-
4
1
  module Qti
5
2
  module V2
6
3
  module Models
@@ -1,20 +1,17 @@
1
- require 'qti/v2/models/base'
2
- require 'qti/models/assessment_meta'
3
- require 'qti/xpath_helpers'
4
-
5
1
  module Qti
6
2
  module V2
7
3
  module Models
8
4
  class AssessmentTest < Qti::V2::Models::Base
9
5
  include Qti::Models::AssessmentMetaBase
10
6
  include Qti::XPathHelpers
7
+
11
8
  def title
12
9
  @title ||= xpath_with_single_check('//xmlns:assessmentTest/@title')&.content || File.basename(@path, '.xml')
13
10
  end
14
11
 
15
12
  def assessment_items
16
13
  # Return the xml files we should be parsing
17
- @assessment_item_reference_hrefs ||= begin
14
+ @assessment_items ||= begin
18
15
  @doc.xpath('//xmlns:assessmentItemRef/@href').map(&:content).map do |href|
19
16
  { path: remap_href_path(href), resource: self }
20
17
  end
@@ -1,5 +1,3 @@
1
- require 'qti/models/base'
2
-
3
1
  module Qti
4
2
  module V2
5
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/v2/models/base'
2
-
3
1
  module Qti
4
2
  module V2
5
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/v2/models/base'
2
-
3
1
  module Qti
4
2
  module V2
5
3
  module Models
@@ -1,5 +1,3 @@
1
- require 'qti/v2/models/base'
2
-
3
1
  module Qti
4
2
  module V2
5
3
  module Models