Skip to content

Commit

Permalink
feat(import_1.2): Support Canvas Multiple Dropdown
Browse files Browse the repository at this point in the history
refs QUIZ-3731

Test Plan:
  QA-CR

Change-Id: I69f8f17da8b98bd7ceb4a85c5daf6c1f1a06cf27
Reviewed-on: https://gerrit.instructure.com/146197
Tested-by: Jenkins
Reviewed-by: Han Yan <[email protected]>
Product-Review: Steve Kacsmark <[email protected]>
QA-Review: Steve Kacsmark <[email protected]>
  • Loading branch information
Steve Kacsmark committed Apr 16, 2018
1 parent 14728a5 commit b95006a
Show file tree
Hide file tree
Showing 7 changed files with 576 additions and 42 deletions.
2 changes: 1 addition & 1 deletion lib/qti/v1/models/interactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Models
module Interactions
# This one finds the correct parsing model based on the provided xml node
def self.interaction_model(node, parent)
ordered_classes = [FormulaInteraction, NumericInteraction]
ordered_classes = [CanvasMultipleDropdownInteraction, FormulaInteraction, NumericInteraction]
ordered_classes.each do |interaction_class|
match = interaction_class.matches(node, parent)
return match if match
Expand Down
49 changes: 49 additions & 0 deletions lib/qti/v1/models/interactions/base_fill_blank_interaction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module Qti
module V1
module Models
module Interactions
class BaseFillBlankInteraction < BaseInteraction
CANVAS_REGEX = /(\[.+?\])/

def canvas_stem_items(item_prompt)
item_prompt.split(CANVAS_REGEX).map.with_index do |stem_item, index|
if stem_item.match CANVAS_REGEX
stem_blank(index, canvas_blank_id(stem_item))
else
stem_text(index, stem_item)
end
end
end

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

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

def canvas_blank_id(stem_item)
blank_id = nil
node.xpath('.//xmlns:response_lid').children.map do |response_lid_node|
if stem_item.include?(response_lid_node.text)
blank_id = response_lid_node.parent.attributes['ident']&.value
end
end
blank_id
end
end
end
end
end
end
84 changes: 84 additions & 0 deletions lib/qti/v1/models/interactions/canvas_multiple_dropdown.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
module Qti
module V1
module Models
module Interactions
class CanvasMultipleDropdownInteraction < BaseFillBlankInteraction
# This will know if a class matches
def self.matches(node, parent)
field_entry = node.xpath('.//xmlns:fieldentry')[0]
return false unless field_entry&.text == 'multiple_dropdowns_question'
new(node, parent)
end

def stem_items
canvas_stem_items(node.at_xpath('.//xmlns:presentation/xmlns:material/xmlns:mattext').text)
end

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

def scoring_data_structs
answers.map do |answer|
ScoringData.new(
{
id: answer[:entry_id],
position: position_for_entry(answer[:entry_id]),
item_body: answer[:blank_text]
},
rcardinality,
id: answer[:value]
)
end
end

def text_for_entry(entry_id)
blanks
@blank_choices[entry_id][:item_body]
end

def position_for_entry(entry_id)
blanks
@blank_choices[entry_id][:position]
end

def answers
@node.xpath('.//xmlns:respcondition/xmlns:setvar[@varname="SCORE"]').map do |points|
entry = points.at_xpath('preceding-sibling::xmlns:conditionvar/xmlns:varequal')
{
value: entry[:respident],
entry_id: entry.text,
blank_text: text_for_entry(entry.text),
action: points[:action],
point_value: points.text
}
end
end

private

def blank_choice(bnode, index)
bnode_id = bnode[:ident]
choice = {
id: bnode_id,
position: index + 1,
item_body: bnode.at_xpath('.//xmlns:mattext').text
}
@blank_choices ||= {}
@blank_choices[bnode_id] = choice
choice
end
end
end
end
end
end
43 changes: 2 additions & 41 deletions lib/qti/v1/models/interactions/fill_blank_interaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Qti
module V1
module Models
module Interactions
class FillBlankInteraction < BaseInteraction
class FillBlankInteraction < BaseFillBlankInteraction
CANVAS_REGEX = /(\[.+?\])/

# This will know if a class matches
Expand All @@ -24,23 +24,12 @@ def canvas_multiple_fib?

def stem_items
if canvas_multiple_fib?
canvas_stem_items
canvas_stem_items(node.at_xpath('.//xmlns:mattext').text)
else
qti_stem_items
end
end

def canvas_stem_items
item_prompt_words = node.at_xpath('.//xmlns:mattext').text.split(CANVAS_REGEX)
item_prompt_words.map.with_index do |stem_item, index|
if stem_item.match CANVAS_REGEX
stem_blank(index, canvas_blank_id(stem_item))
else
stem_text(index, stem_item)
end
end
end

def qti_stem_items
stem_item_nodes = node.xpath('.//xmlns:presentation').children
stem_item_nodes.map.with_index do |stem_item, index|
Expand Down Expand Up @@ -109,41 +98,13 @@ def answer_nodes
end
end

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

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

def scoring_data_id(node)
node.attributes['respident']&.value || node.attributes['ident']&.value
end

def scoring_data_case(node)
node.attributes['case']&.value || 'no'
end

def canvas_blank_id(stem_item)
blank_id = nil
node.xpath('.//xmlns:response_lid').children.map do |response_lid_node|
if stem_item.include?(response_lid_node.text)
blank_id = response_lid_node.parent.attributes['ident']&.value
end
end
blank_id
end
end
end
end
Expand Down
167 changes: 167 additions & 0 deletions spec/fixtures/items_1.2/canvas_multiple_dropdown.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<questestinterop xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd">
<assessment ident="ie797010092a6c1798006e216ba4c9c90" title="Multiple Drop Down">
<qtimetadata>
<qtimetadatafield>
<fieldlabel>cc_maxattempts</fieldlabel>
<fieldentry>1</fieldentry>
</qtimetadatafield>
</qtimetadata>
<section ident="root_section">
<item ident="id9d8b63d85a03f2987646622805b61cf" title="Question">
<itemmetadata>
<qtimetadata>
<qtimetadatafield>
<fieldlabel>question_type</fieldlabel>
<fieldentry>multiple_dropdowns_question</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>points_possible</fieldlabel>
<fieldentry>1.0</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>assessment_question_identifierref</fieldlabel>
<fieldentry>i7ad7f9841cc58f0a1392816b78aaa878</fieldentry>
</qtimetadatafield>
</qtimetadata>
</itemmetadata>
<presentation>
<material>
<mattext texttype="text/html">&lt;div&gt;&lt;p&gt;Roses are [color1], violets are [color2].&lt;/p&gt;&lt;/div&gt;</mattext>
</material>
<response_lid ident="response_color1">
<material>
<mattext>color1</mattext>
</material>
<render_choice>
<response_label ident="6548">
<material>
<mattext texttype="text/plain">red</mattext>
</material>
</response_label>
<response_label ident="5550">
<material>
<mattext texttype="text/plain">plaid</mattext>
</material>
</response_label>
</render_choice>
</response_lid>
<response_lid ident="response_color2">
<material>
<mattext>color2</mattext>
</material>
<render_choice>
<response_label ident="6951">
<material>
<mattext texttype="text/plain">blue</mattext>
</material>
</response_label>
<response_label ident="4500">
<material>
<mattext texttype="text/plain">paisely</mattext>
</material>
</response_label>
</render_choice>
</response_lid>
</presentation>
<resprocessing>
<outcomes>
<decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
</outcomes>
<respcondition continue="Yes">
<conditionvar>
<other/>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="general_fb"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="response_color1">6548</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="6548_fb"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="response_color1">5550</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="5550_fb"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="response_color2">6951</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="6951_fb"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="response_color2">4500</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="4500_fb"/>
</respcondition>
<respcondition>
<conditionvar>
<varequal respident="response_color1">6548</varequal>
</conditionvar>
<setvar varname="SCORE" action="Add">50.00</setvar>
</respcondition>
<respcondition>
<conditionvar>
<varequal respident="response_color2">6951</varequal>
</conditionvar>
<setvar varname="SCORE" action="Add">50.00</setvar>
</respcondition>
</resprocessing>
<itemfeedback ident="general_fb">
<flow_mat>
<material>
<mattext texttype="text/html">&lt;p&gt;Roses come in many colors, violets probably do too.&lt;/p&gt;
&lt;p&gt;Never the less, the correct answers were &lt;strong&gt;red&lt;/strong&gt; and &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="correct_fb">
<flow_mat>
<material>
<mattext texttype="text/html">&lt;p&gt;Completing the poem, is left to you.&lt;/p&gt;</mattext>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="general_incorrect_fb">
<flow_mat>
<material>
<mattext texttype="text/html">&lt;p&gt;Those aren't colors, you meant &lt;strong&gt;red&lt;/strong&gt; and &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="6548_fb">
<flow_mat>
<material>
<mattext texttype="text/html">&lt;p&gt;Yes! &lt;strong&gt;Red&lt;/strong&gt;.&lt;/p&gt;</mattext>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="5550_fb">
<flow_mat>
<material>
<mattext texttype="text/html">&lt;p&gt;I'm pretty sure you meant &lt;strong&gt;red.&lt;/strong&gt;&lt;/p&gt;</mattext>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="6951_fb">
<flow_mat>
<material>
<mattext texttype="text/html">&lt;p&gt;Yes, &lt;strong&gt;blue&lt;/strong&gt;!&lt;/p&gt;</mattext>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="4500_fb">
<flow_mat>
<material>
<mattext texttype="text/html">&lt;p&gt;Did you also chose plaid? You wanted to &lt;strong&gt;blue&lt;/strong&gt;.&lt;/p&gt;</mattext>
</material>
</flow_mat>
</itemfeedback>
</item>
</section>
</assessment>
</questestinterop>
Loading

0 comments on commit b95006a

Please sign in to comment.