Class: Senkyoshi::QTI

Inherits:
FileResource show all
Defined in:
lib/senkyoshi/models/qti.rb

Direct Known Subclasses

Assessment, QuestionBank, Survey

Instance Attribute Summary collapse

Attributes inherited from FileResource

#id

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from FileResource

#create_module

Methods inherited from Resource

#_find_directories, #_fix_path, #_matches_directory_xid?, #_search_and_replace, #cleanup, #fix_html, #matches_xid?, #strip_xid

Constructor Details

#initialize(resource_id = nil) ⇒ QTI

Returns a new instance of QTI.



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/senkyoshi/models/qti.rb', line 37

def initialize(resource_id = nil)
  super(resource_id)
  @title = ""
  @description = ""
  @quiz_type = ""
  @points_possible = 0
  @items = []
  @group_name = ""
  @workflow_state = "published"
  @available = true
end

Instance Attribute Details

#points_possibleObject (readonly)

Returns the value of attribute points_possible.



29
30
31
# File 'lib/senkyoshi/models/qti.rb', line 29

def points_possible
  @points_possible
end

Class Method Details

.from(data, pre_data, _resource_xids = nil) ⇒ Object



30
31
32
33
34
35
# File 'lib/senkyoshi/models/qti.rb', line 30

def self.from(data, pre_data, _resource_xids = nil)
  type = data.at("bbmd_assessmenttype").text
  qti_class = Senkyoshi.const_get QTI_TYPE[type]
  qti = qti_class.new(pre_data[:file_name])
  qti.iterate_xml(data, pre_data)
end

.get_pre_data(xml, _) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/senkyoshi/models/qti.rb', line 105

def self.get_pre_data(xml, _)
  {
    original_file_name: xml.xpath("/COURSEASSESSMENT/
      ASMTID/@value").first.text,
    one_question_at_a_time: xml.xpath("/COURSEASSESSMENT/
      DELIVERYTYPE/@value").first.text,
    time_limit: xml.xpath("/COURSEASSESSMENT/
      TIMELIMIT/@value").first.text,
    access_code: xml.xpath("/COURSEASSESSMENT/
      PASSWORD/@value").first.text,
    allowed_attempts: xml.xpath("/COURSEASSESSMENT/
      ATTEMPTCOUNT/@value").first.text,
    unlimited_attempts: xml.xpath("/COURSEASSESSMENT/
      FLAGS/ISUNLIMITEDATTEMPTS/@value").first.text,
    cant_go_back: xml.xpath("/COURSEASSESSMENT/
      FLAGS/ISBACKTRACKPROHIBITED/@value").first.text,
    show_correct_answers: xml.xpath("/COURSEASSESSMENT/
      FLAGS/SHOWCORRECTANSWER/@value").first.text,
  }
end

Instance Method Details

#canvas_conversion(course, resources) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/senkyoshi/models/qti.rb', line 126

def canvas_conversion(course, resources)
  assessment = CanvasCc::CanvasCC::Models::Assessment.new
  assessment.identifier = @id
  assignment_group = AssignmentGroup.find_or_create(course, @group_name)
  assignment = create_assignment(assignment_group.identifier)
  assignment.quiz_identifier_ref = assessment.identifier
  course.assignments << assignment
  assessment = setup_assessment(assessment, assignment, resources)
  assessment = create_items(course, assessment, resources)
  course.assessments << assessment
  course
end

#canvas_module?(item) ⇒ Boolean

Returns:

  • (Boolean)


186
187
188
# File 'lib/senkyoshi/models/qti.rb', line 186

def canvas_module?(item)
  item.is_a? CanvasCc::CanvasCC::Models::QuestionGroup
end

#create_assignment(group_id) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/senkyoshi/models/qti.rb', line 207

def create_assignment(group_id)
  assignment = CanvasCc::CanvasCC::Models::Assignment.new
  assignment.identifier = Senkyoshi.create_random_hex
  assignment.assignment_group_identifier_ref = group_id
  assignment.title = @title
  assignment.position = 1
  assignment.submission_types << "online_quiz"
  assignment.grading_type = "points"
  assignment.workflow_state = @workflow_state
  assignment.points_possible = @points_possible
  assignment
end

#create_items(course, assessment, resources) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/senkyoshi/models/qti.rb', line 162

def create_items(course, assessment, resources)
  questions = get_questions(course)
  assessment.items = []
  questions.each do |item|
    if canvas_module?(item)
      assessment.items << item
    else
      assessment.items << item.canvas_conversion(assessment, resources)
    end
  end
  assessment
end

#get_question_group(course, item) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/senkyoshi/models/qti.rb', line 190

def get_question_group(course, item)
  if item[:questions]
    questions = course.question_banks.flat_map(&:questions)
    canvas_questions = item[:questions].flat_map do |question|
      questions.detect { |q| q.original_identifier == question }
    end.compact
  end
  question_group = CanvasCc::CanvasCC::Models::QuestionGroup.new
  question_group.identifier = Senkyoshi.create_random_hex
  question_group.title = "Question Group"
  question_group.selection_number = item[:selection_number]
  question_group.questions = canvas_questions || []
  question_group.sourcebank_ref = item[:file_name]
  question_group.points_per_item = item[:weight]
  question_group
end

#get_questions(course) ⇒ Object



175
176
177
178
179
180
181
182
183
184
# File 'lib/senkyoshi/models/qti.rb', line 175

def get_questions(course)
  @items = @items - ["", nil]
  @items.flat_map do |item|
    if !item[:selection_number]
      Question.from(item)
    else
      get_question_group(course, item)
    end
  end
end

#get_quiz_pool_items(selection_order) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/senkyoshi/models/qti.rb', line 86

def get_quiz_pool_items(selection_order)
  selection_order.flat_map do |selection|
    weight = selection.previous.at("qmd_weighting").text
    selection_number = selection.at("selection_number").text
    item = {
      weight: weight,
      selection_number: selection_number,
    }
    if selection.at("sourcebank_ref")
      sourcebank_ref = selection.at("sourcebank_ref").text
      item[:file_name] = sourcebank_ref
    elsif selection.at("or_selection")
      questions = selection.search("selection_metadata").map(&:text)
      item[:questions] = questions
    end
    item
  end
end

#iterate_xml(data, pre_data) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/senkyoshi/models/qti.rb', line 49

def iterate_xml(data, pre_data)
  @group_name = pre_data[:category] || data.at("bbmd_assessmenttype").text
  @id = pre_data[:assignment_id] || pre_data[:file_name]
  @title = data.at("assessment").attributes["title"].value
  @points_possible = data.at("qmd_absolutescore_max").text
  set_assessment_details(pre_data)
  @due_at = pre_data[:due_at]

  description = data.at("presentation_material").
    at("mat_formattedtext").text
  instructions = data.at("rubric").
    at("mat_formattedtext").text
  @description = %{
    #{description}
    #{instructions}
  }
  @items = data.search("item").to_a
  @items += get_quiz_pool_items(data.search("selection_ordering"))
  self
end

#set_assessment_details(pre_data) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/senkyoshi/models/qti.rb', line 70

def set_assessment_details(pre_data)
  @time_limit = pre_data[:time_limit]
  @allowed_attempts = pre_data[:allowed_attempts]
  @allowed_attempts = -1 if pre_data[:unlimited_attempts] == "true"
  @cant_go_back = pre_data[:cant_go_back]
  @show_correct_answers = pre_data[:show_correct_answers]
  if pre_data[:access_code] && !pre_data[:access_code].empty?
    @access_code = pre_data[:access_code]
  end
  if pre_data[:one_question_at_a_time] == "QUESTION_BY_QUESTION"
    @one_question_at_a_time = "true"
  else
    @one_question_at_a_time = "false"
  end
end

#setup_assessment(assessment, assignment, resources) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/senkyoshi/models/qti.rb', line 139

def setup_assessment(assessment, assignment, resources)
  assessment.title = @title
  assessment.description = fix_html(@description, resources)
  if @items.count.zero?
    assessment.description +=
      "Empty Quiz -- No questions were contained in the blackboard quiz"
  end
  assessment.available = @available
  assessment.quiz_type = @quiz_type
  assessment.points_possible = @points_possible
  assessment.time_limit = @time_limit
  assessment.access_code = @access_code
  assessment.allowed_attempts = @allowed_attempts
  assessment.cant_go_back = @cant_go_back
  assessment.show_correct_answers = @show_correct_answers
  assessment.one_question_at_a_time = @one_question_at_a_time
  if @due_at && !@due_at.empty?
    assessment.due_at = Time.strptime(@due_at, "%Y-%m-%d %H:%M:%S %z")
  end
  assessment.assignment = assignment
  assessment
end