Class: Qti::V1::Models::Interactions::BaseFillBlankInteraction

Inherits:
BaseInteraction show all
Defined in:
lib/qti/v1/models/interactions/base_fill_blank_interaction.rb

Constant Summary collapse

SCORING_VAREQUAL_XPATH =

A per-answer comment is carried by a respcondition of the same shape as a scoring one, so only the conditions that award points can be read as correct answers.

'.//xmlns:resprocessing/xmlns:respcondition[xmlns:setvar]' \
'/xmlns:conditionvar/xmlns:varequal'.freeze

Instance Attribute Summary

Attributes inherited from BaseInteraction

#node

Attributes inherited from Models::Base

#doc, #manifest, #package_root, #path, #resource

Instance Method Summary collapse

Methods inherited from BaseInteraction

#answer_feedback, canvas_custom_fitb?, #canvas_item_feedback, canvas_multiple_fib?, #initialize, #locked_choices, matches, maybe_question_type, new_quizzes_fib?, question_type, #rcardinality, #scoring_data_structs, #shuffled?

Methods inherited from Base

#qti_version, #return_inner_content!, #sanitize_attributes, #sanitize_attributes_by_node

Methods inherited from Models::Base

#css_with_single_check, from_path!, #initialize, #parse_html, #parse_xml, #preprocess_xml_doc, #raise_unsupported, #remap_href_path, #sanitize_content!, #xpath_with_single_check

Constructor Details

This class inherits a constructor from Qti::V1::Models::Interactions::BaseInteraction

Instance Method Details

#blank_id(stem_item) ⇒ Object



47
48
49
50
51
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 47

def blank_id(stem_item)
  return stem_item unless canvas_custom_fitb?
  return canvas_blank_id(stem_item) unless new_quizzes_fib?
  nq_blank_id(stem_item)
end

#blank_value(blank_id) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 53

def blank_value(blank_id)
  return nq_blank_value(blank_id) if new_quizzes_fib?

  blank = canvas_fib_responses.find { |response| response[:id] == blank_id }
  correct_choice = blank[:choices].find { |c| c[:id] == correct_choice_id(blank) }
  (correct_choice || {})[:item_body] || blank&.dig(:choices, 0, :item_body)
end

#canvas_blank_id(stem_item) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 76

def canvas_blank_id(stem_item)
  blank_id = nil
  node.xpath('.//xmlns:response_lid/xmlns:material').children.map do |response_lid_node|
    if stem_item == response_lid_node.text
      blank_id = response_lid_node.ancestors('response_lid').first.attributes['ident']&.value
    end
  end
  blank_id
end

#canvas_custom_fitb? ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 68

def canvas_custom_fitb?
  @canvas_custom_fitb ||= BaseInteraction.canvas_custom_fitb?(@node)
end

#canvas_fib_response_ids ⇒ Object



108
109
110
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 108

def canvas_fib_response_ids
  @canvas_fib_response_ids ||= canvas_fib_responses.map { |b| "[#{b[:id].sub(/^response_/, '')}]" }
end

#canvas_fib_responses ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 94

def canvas_fib_responses
  @base_canvas_blanks ||= node.xpath('.//xmlns:response_lid').map do |resp|
    index = 0
    {
      id: resp[:ident],
      choices:
        resp.xpath('.//xmlns:response_label').map do |bnode|
          canvas_blank_choice(bnode, index += 1)
        end
    }
  end
  @base_canvas_blanks
end

#canvas_stem_items(item_prompt) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 13

def canvas_stem_items(item_prompt)
  item_prompt = sanitize_attributes(item_prompt)
  item_prompt.split(CANVAS_BLANK_REGEX).map.with_index do |stem_item, index|
    if canvas_fib_response_ids.include?(stem_item)
      # Strip the brackets before searching
      value = stem_item[1..-2]
      blank_id = blank_id(value)
      blank_name = blank_value(blank_id) || value
      stem_blank(index, blank_id, blank_name)
    else
      stem_text(index, stem_item)
    end
  end
end

#correct_answer_map ⇒ Object



112
113
114
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 112

def correct_answer_map
  @correct_answer_map ||= correct_answers
end

#new_quizzes_fib? ⇒ Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 72

def new_quizzes_fib?
  @new_quizzes_fib ||= BaseInteraction.new_quizzes_fib?(@node)
end

#nq_blank_id(stem_item) ⇒ Object



86
87
88
89
90
91
92
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 86

def nq_blank_id(stem_item)
  blank_id = nil
  node.xpath('.//xmlns:response_lid').map do |resp|
    blank_id = resp[:ident] if resp[:ident] == "response_#{stem_item}"
  end
  blank_id
end

#nq_blank_value(blank_id) ⇒ Object

The correct answer value is not necessarily the first one in NQ



62
63
64
65
66
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 62

def nq_blank_value(blank_id)
  blank = canvas_fib_responses.find { |response| response[:id] == blank_id }
  correct_choice = blank[:choices].find { |choice| choice[:id] == correct_answer_map[blank_id] }
  correct_choice[:item_body]
end

#stem_blank(index, blank_id, blank_name) ⇒ Object



28
29
30
31
32
33
34
35
36
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 28

def stem_blank(index, blank_id, blank_name)
  {
    id: "stem_#{index}",
    position: index + 1,
    type: 'blank',
    blank_id: blank_id,
    blank_name: blank_name
  }
end

#stem_text(index, value) ⇒ Object



38
39
40
41
42
43
44
45
# File 'lib/qti/v1/models/interactions/base_fill_blank_interaction.rb', line 38

def stem_text(index, value)
  {
    id: "stem_#{index}",
    position: index + 1,
    type: 'text',
    value: value
  }
end