qti 0.4.16 → 0.5.16
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 +4 -4
 - data/lib/qti.rb +0 -1
 - data/lib/qti/v1/models/interactions/match_interaction.rb +0 -6
 - data/lib/qti/v2/models/choices/simple_associable_choice.rb +7 -0
 - data/lib/qti/v2/models/choices/simple_choice.rb +1 -0
 - data/lib/qti/v2/models/interactions.rb +7 -3
 - data/lib/qti/v2/models/interactions/categorization_interaction.rb +69 -0
 - data/lib/qti/v2/models/interactions/match_interaction.rb +29 -32
 - data/lib/qti/v2/models/interactions/match_item_tag_processors/associate_interaction_tag_processor.rb +75 -0
 - data/lib/qti/v2/models/interactions/match_item_tag_processors/match_interaction_tag_processor.rb +67 -0
 - data/lib/qti/v2/models/scoring_data.rb +3 -3
 - data/spec/fixtures/items_2.1/categorization.xml +35 -0
 - data/spec/fixtures/items_2.1/match.xml +19 -26
 - data/spec/fixtures/items_2.1/match2.xml +119 -0
 - data/spec/lib/qti/v1/models/interactions/match_interaction_spec.rb +44 -0
 - data/spec/lib/qti/v2/models/assessment_item_spec.rb +0 -24
 - data/spec/lib/qti/v2/models/choices/simple_associable_choice_spec.rb +21 -0
 - data/spec/lib/qti/v2/models/interactions/categorization_interaction_spec.rb +23 -0
 - data/spec/lib/qti/v2/models/interactions/match_interaction_spec.rb +71 -7
 - data/spec/support/monkey_patches.rb +14 -0
 - metadata +31 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 4883be4fd0b3c4f0f662068c6b7d42e2cfee0645
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 262e1f6ad0e5d3d80c844d30084bcb6eb461fcf0
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: beddd3cfcec82686646a5635773414d32502f58ea993719afb175f4ca9adaeed7ee9f6a622016618497a0a6f474915a0ff205d80fd0984f610ce1093675270ba
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 81bc3c599b5c15b0c1437d1abf2fe985676d1f9d2ec2e433f5be5d1cac458822a113eb1e5e6290d995315a05984cf541a89453e4a900597bd5fc5d799762184b
         
     | 
    
        data/lib/qti.rb
    CHANGED
    
    | 
         @@ -62,7 +62,6 @@ require 'qti/v1/models/choices/fill_blank_choice' 
     | 
|
| 
       62 
62 
     | 
    
         
             
            require 'qti/v1/models/scoring_data'
         
     | 
| 
       63 
63 
     | 
    
         | 
| 
       64 
64 
     | 
    
         
             
            require 'qti/v2/models/base'
         
     | 
| 
       65 
     | 
    
         
            -
            require 'qti/v2/models/interactions/base_interaction'
         
     | 
| 
       66 
65 
     | 
    
         
             
            require 'qti/v2/models/choices/simple_choice'
         
     | 
| 
       67 
66 
     | 
    
         
             
            require 'qti/v2/models/choices/simple_associable_choice'
         
     | 
| 
       68 
67 
     | 
    
         
             
            require 'qti/v2/models/choices/gap_match_choice'
         
     | 
| 
         @@ -3,18 +3,12 @@ module Qti 
     | 
|
| 
       3 
3 
     | 
    
         
             
                module Models
         
     | 
| 
       4 
4 
     | 
    
         
             
                  module Interactions
         
     | 
| 
       5 
5 
     | 
    
         
             
                    class MatchInteraction < BaseInteraction
         
     | 
| 
       6 
     | 
    
         
            -
                      attr_reader :node
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
6 
     | 
    
         
             
                      def self.matches(node)
         
     | 
| 
       9 
7 
     | 
    
         
             
                        matches = node.xpath('.//xmlns:response_lid')
         
     | 
| 
       10 
8 
     | 
    
         
             
                        return false if matches.count <= 1
         
     | 
| 
       11 
9 
     | 
    
         
             
                        new(node)
         
     | 
| 
       12 
10 
     | 
    
         
             
                      end
         
     | 
| 
       13 
11 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                      def initialize(node)
         
     | 
| 
       15 
     | 
    
         
            -
                        @node = node
         
     | 
| 
       16 
     | 
    
         
            -
                      end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
12 
     | 
    
         
             
                      def answers
         
     | 
| 
       19 
13 
     | 
    
         
             
                        @answers ||= answer_nodes.map do |node|
         
     | 
| 
       20 
14 
     | 
    
         
             
                          V1::Models::Choices::LogicalIdentifierChoice.new(node)
         
     | 
| 
         @@ -5,6 +5,13 @@ module Qti 
     | 
|
| 
       5 
5 
     | 
    
         
             
                module Models
         
     | 
| 
       6 
6 
     | 
    
         
             
                  module Choices
         
     | 
| 
       7 
7 
     | 
    
         
             
                    class SimpleAssociableChoice < SimpleChoice
         
     | 
| 
      
 8 
     | 
    
         
            +
                      def match_max
         
     | 
| 
      
 9 
     | 
    
         
            +
                        @_match_max ||= @node.attributes['matchMax'].value || 0
         
     | 
| 
      
 10 
     | 
    
         
            +
                      end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                      def match_min
         
     | 
| 
      
 13 
     | 
    
         
            +
                        @_match_min ||= @node.attributes['matchMin'].value || 0
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
       8 
15 
     | 
    
         
             
                    end
         
     | 
| 
       9 
16 
     | 
    
         
             
                  end
         
     | 
| 
       10 
17 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            require 'qti/v2/models/interactions/base_interaction'
         
     | 
| 
       2 
2 
     | 
    
         
             
            Dir["#{__dir__}/interactions/*.rb"].each { |f| load f }
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module Qti
         
     | 
| 
         @@ -7,8 +7,6 @@ module Qti 
     | 
|
| 
       7 
7 
     | 
    
         
             
                  module Interactions
         
     | 
| 
       8 
8 
     | 
    
         
             
                    # This one finds the correct parsing model based on the provided xml node
         
     | 
| 
       9 
9 
     | 
    
         
             
                    def self.interaction_model(node)
         
     | 
| 
       10 
     | 
    
         
            -
                      subclasses = constants.map { |c| const_get(c) }
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
10 
     | 
    
         
             
                      # Check for matches
         
     | 
| 
       13 
11 
     | 
    
         
             
                      matches = subclasses.each_with_object([]) do |interaction_class, result|
         
     | 
| 
       14 
12 
     | 
    
         
             
                        match = interaction_class.matches(node)
         
     | 
| 
         @@ -19,6 +17,12 @@ module Qti 
     | 
|
| 
       19 
17 
     | 
    
         | 
| 
       20 
18 
     | 
    
         
             
                      matches.first
         
     | 
| 
       21 
19 
     | 
    
         
             
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    def self.subclasses
         
     | 
| 
      
 22 
     | 
    
         
            +
                      constants.map { |c| const_get(c) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                               .reject { |c| c.name =~ /Implementations|Base/ }
         
     | 
| 
      
 24 
     | 
    
         
            +
                               .select { |c| c.name =~ /^Qti::V2.*Interaction$/ }
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
       22 
26 
     | 
    
         
             
                  end
         
     | 
| 
       23 
27 
     | 
    
         
             
                end
         
     | 
| 
       24 
28 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'match_interaction'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Qti
         
     | 
| 
      
 4 
     | 
    
         
            +
              module V2
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Models
         
     | 
| 
      
 6 
     | 
    
         
            +
                  module Interactions
         
     | 
| 
      
 7 
     | 
    
         
            +
                    class CategorizationInteraction < MatchInteraction
         
     | 
| 
      
 8 
     | 
    
         
            +
                      def self.matches(node)
         
     | 
| 
      
 9 
     | 
    
         
            +
                        if use_match_interaction_implementation?(node)
         
     | 
| 
      
 10 
     | 
    
         
            +
                          new(node, MatchItemTagProcesssors::MatchInteractionTagProcessor)
         
     | 
| 
      
 11 
     | 
    
         
            +
                        else
         
     | 
| 
      
 12 
     | 
    
         
            +
                          false
         
     | 
| 
      
 13 
     | 
    
         
            +
                        end
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      def self.use_match_interaction_implementation?(node)
         
     | 
| 
      
 17 
     | 
    
         
            +
                        MatchItemTagProcesssors::MatchInteractionTagProcessor.match_interaction_tag?(node) &&
         
     | 
| 
      
 18 
     | 
    
         
            +
                          MatchItemTagProcesssors::MatchInteractionTagProcessor.number_of_questions_per_answer(node)
         
     | 
| 
      
 19 
     | 
    
         
            +
                                                                               .any? { |n| n != 1 }
         
     | 
| 
      
 20 
     | 
    
         
            +
                      end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                      def scoring_data_structs
         
     | 
| 
      
 23 
     | 
    
         
            +
                        questions_categories_choices_hash.map do |category_choice, questions_choices|
         
     | 
| 
      
 24 
     | 
    
         
            +
                          ScoringData.new(category_choice.text, 'directedPair',
         
     | 
| 
      
 25 
     | 
    
         
            +
                            id: node_identifier(category_choice),
         
     | 
| 
      
 26 
     | 
    
         
            +
                            questions_ids: questions_choices.map { |q| node_identifier(q) })
         
     | 
| 
      
 27 
     | 
    
         
            +
                        end
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                      private
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                      def questions_categories_choices_hash
         
     | 
| 
      
 33 
     | 
    
         
            +
                        category_choices.each_with_object({}) do |category_choice, hash|
         
     | 
| 
      
 34 
     | 
    
         
            +
                          hash[category_choice] = questions_for_category_choice(category_choice)
         
     | 
| 
      
 35 
     | 
    
         
            +
                        end
         
     | 
| 
      
 36 
     | 
    
         
            +
                      end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                      def questions_for_category_choice(choice)
         
     | 
| 
      
 39 
     | 
    
         
            +
                        choice_identifier = node_identifier(choice)
         
     | 
| 
      
 40 
     | 
    
         
            +
                        category_questions_ids = implementation.question_response_pairs
         
     | 
| 
      
 41 
     | 
    
         
            +
                                                               .select { |_, category_id| category_id == choice_identifier }
         
     | 
| 
      
 42 
     | 
    
         
            +
                                                               .map { |question_id, _| question_id }
         
     | 
| 
      
 43 
     | 
    
         
            +
                        question_choices.select { |q| category_questions_ids.include? node_identifier(q) }
         
     | 
| 
      
 44 
     | 
    
         
            +
                      end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                      def category_choices
         
     | 
| 
      
 47 
     | 
    
         
            +
                        @_category_choices ||= implementation.choices.select { |c| categories_ids.include? node_identifier(c) }
         
     | 
| 
      
 48 
     | 
    
         
            +
                      end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                      def question_choices
         
     | 
| 
      
 51 
     | 
    
         
            +
                        @_question_choices ||= implementation.choices.select { |c| questions_ids.include? node_identifier(c) }
         
     | 
| 
      
 52 
     | 
    
         
            +
                      end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                      def categories_ids
         
     | 
| 
      
 55 
     | 
    
         
            +
                        @_categories_ids ||= implementation.question_response_pairs.map { |_, category_id| category_id }.uniq
         
     | 
| 
      
 56 
     | 
    
         
            +
                      end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                      def questions_ids
         
     | 
| 
      
 59 
     | 
    
         
            +
                        @_questions_ids ||= implementation.question_response_pairs.map { |question_id, _| question_id }.uniq
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                      def node_identifier(node)
         
     | 
| 
      
 63 
     | 
    
         
            +
                        node.attributes['identifier'].value
         
     | 
| 
      
 64 
     | 
    
         
            +
                      end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    end
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,51 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'match_item_tag_processors/match_interaction_tag_processor'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'match_item_tag_processors/associate_interaction_tag_processor'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
       1 
4 
     | 
    
         
             
            module Qti
         
     | 
| 
       2 
5 
     | 
    
         
             
              module V2
         
     | 
| 
       3 
6 
     | 
    
         
             
                module Models
         
     | 
| 
       4 
7 
     | 
    
         
             
                  module Interactions
         
     | 
| 
       5 
8 
     | 
    
         
             
                    class MatchInteraction < BaseInteraction
         
     | 
| 
       6 
     | 
    
         
            -
                       
     | 
| 
       7 
     | 
    
         
            -
                        matches = node.xpath('//xmlns:matchInteraction')
         
     | 
| 
       8 
     | 
    
         
            -
                        return false if matches.count != 1
         
     | 
| 
       9 
     | 
    
         
            -
                        new(node)
         
     | 
| 
       10 
     | 
    
         
            -
                      end
         
     | 
| 
      
 9 
     | 
    
         
            +
                      extend Forwardable
         
     | 
| 
       11 
10 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                       
     | 
| 
       13 
     | 
    
         
            -
                        node.xpath('.//xmlns:correctResponse//xmlns:value')
         
     | 
| 
       14 
     | 
    
         
            -
                            .map { |value| value.content.split.first }
         
     | 
| 
       15 
     | 
    
         
            -
                            .map { |id| { id: id, question_body: choices_by_identifier[id].content } }
         
     | 
| 
       16 
     | 
    
         
            -
                      end
         
     | 
| 
      
 11 
     | 
    
         
            +
                      attr_reader :implementation
         
     | 
| 
       17 
12 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                      def  
     | 
| 
       19 
     | 
    
         
            -
                        node 
     | 
| 
      
 13 
     | 
    
         
            +
                      def initialize(node, implementation)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        super(node)
         
     | 
| 
      
 15 
     | 
    
         
            +
                        @implementation = implementation.new(node)
         
     | 
| 
       20 
16 
     | 
    
         
             
                      end
         
     | 
| 
       21 
17 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                       
     | 
| 
       23 
     | 
    
         
            -
                        answer_nodes.map { |node| Choices::SimpleAssociableChoice.new(node) }
         
     | 
| 
       24 
     | 
    
         
            -
                      end
         
     | 
| 
      
 18 
     | 
    
         
            +
                      def_delegators :@implementation, :answers, :questions, :shuffled?
         
     | 
| 
       25 
19 
     | 
    
         | 
| 
       26 
20 
     | 
    
         
             
                      def scoring_data_structs
         
     | 
| 
       27 
     | 
    
         
            -
                         
     | 
| 
       28 
     | 
    
         
            -
                          value.content.split
         
     | 
| 
       29 
     | 
    
         
            -
                        end
         
     | 
| 
       30 
     | 
    
         
            -
                        question_response_id_mapping = Hash[question_response_pairs]
         
     | 
| 
       31 
     | 
    
         
            -
                        data = question_response_id_mapping.reduce({}) do |acc, pair|
         
     | 
| 
       32 
     | 
    
         
            -
                          question_id, answer_id = pair
         
     | 
| 
       33 
     | 
    
         
            -
                          acc.update question_id => choices_by_identifier[answer_id].content
         
     | 
| 
       34 
     | 
    
         
            -
                        end
         
     | 
| 
       35 
     | 
    
         
            -
                        [ScoringData.new(data, 'directedPair')]
         
     | 
| 
      
 21 
     | 
    
         
            +
                        implementation.scoring_data_structs
         
     | 
| 
       36 
22 
     | 
    
         
             
                      end
         
     | 
| 
       37 
23 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
                       
     | 
| 
      
 24 
     | 
    
         
            +
                      def self.matches(node)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        implementation =
         
     | 
| 
      
 26 
     | 
    
         
            +
                          if use_associate_interaction_implementation?(node)
         
     | 
| 
      
 27 
     | 
    
         
            +
                            MatchItemTagProcesssors::AssociateInteractionTagProcessor
         
     | 
| 
      
 28 
     | 
    
         
            +
                          elsif use_match_interaction_implementation?(node)
         
     | 
| 
      
 29 
     | 
    
         
            +
                            MatchItemTagProcesssors::MatchInteractionTagProcessor
         
     | 
| 
      
 30 
     | 
    
         
            +
                          end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                        return false unless implementation.present?
         
     | 
| 
      
 33 
     | 
    
         
            +
                        new(node, implementation)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      end
         
     | 
| 
       39 
35 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                      def  
     | 
| 
       41 
     | 
    
         
            -
                         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                        end
         
     | 
| 
      
 36 
     | 
    
         
            +
                      def self.use_associate_interaction_implementation?(node)
         
     | 
| 
      
 37 
     | 
    
         
            +
                        MatchItemTagProcesssors::AssociateInteractionTagProcessor.associate_interaction_tag?(node) &&
         
     | 
| 
      
 38 
     | 
    
         
            +
                          MatchItemTagProcesssors::AssociateInteractionTagProcessor.number_of_questions_per_answer(node)
         
     | 
| 
      
 39 
     | 
    
         
            +
                                                                                   .all? { |n| n == 1 }
         
     | 
| 
       45 
40 
     | 
    
         
             
                      end
         
     | 
| 
       46 
41 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
                      def  
     | 
| 
       48 
     | 
    
         
            -
                         
     | 
| 
      
 42 
     | 
    
         
            +
                      def self.use_match_interaction_implementation?(node)
         
     | 
| 
      
 43 
     | 
    
         
            +
                        MatchItemTagProcesssors::MatchInteractionTagProcessor.match_interaction_tag?(node) &&
         
     | 
| 
      
 44 
     | 
    
         
            +
                          MatchItemTagProcesssors::MatchInteractionTagProcessor.number_of_questions_per_answer(node)
         
     | 
| 
      
 45 
     | 
    
         
            +
                                                                               .all? { |n| n == 1 }
         
     | 
| 
       49 
46 
     | 
    
         
             
                      end
         
     | 
| 
       50 
47 
     | 
    
         
             
                    end
         
     | 
| 
       51 
48 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/qti/v2/models/interactions/match_item_tag_processors/associate_interaction_tag_processor.rb
    ADDED
    
    | 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Qti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module V2
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Models
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module Interactions
         
     | 
| 
      
 5 
     | 
    
         
            +
                    module MatchItemTagProcesssors
         
     | 
| 
      
 6 
     | 
    
         
            +
                      class AssociateInteractionTagProcessor < Interactions::BaseInteraction
         
     | 
| 
      
 7 
     | 
    
         
            +
                        def self.associate_interaction_tag?(node)
         
     | 
| 
      
 8 
     | 
    
         
            +
                          node.xpath('.//xmlns:associateInteraction').count == 1
         
     | 
| 
      
 9 
     | 
    
         
            +
                        end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                        def self.number_of_questions_per_answer(node)
         
     | 
| 
      
 12 
     | 
    
         
            +
                          question_response_pairs = node.xpath('.//xmlns:correctResponse//xmlns:value').map do |value|
         
     | 
| 
      
 13 
     | 
    
         
            +
                            value.content.split
         
     | 
| 
      
 14 
     | 
    
         
            +
                          end
         
     | 
| 
      
 15 
     | 
    
         
            +
                          count = Hash.new { 0 }
         
     | 
| 
      
 16 
     | 
    
         
            +
                          question_response_pairs.reduce(count) do |acc, pair|
         
     | 
| 
      
 17 
     | 
    
         
            +
                            acc.update pair.last => acc[pair.last] + 1
         
     | 
| 
      
 18 
     | 
    
         
            +
                          end
         
     | 
| 
      
 19 
     | 
    
         
            +
                          count.values
         
     | 
| 
      
 20 
     | 
    
         
            +
                        end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                        def shuffled?
         
     | 
| 
      
 23 
     | 
    
         
            +
                          node.at_xpath('.//xmlns:associateInteraction').attributes['shuffle']&.value.try(:downcase) == 'true'
         
     | 
| 
      
 24 
     | 
    
         
            +
                        end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                        def questions
         
     | 
| 
      
 27 
     | 
    
         
            +
                          questions_ids.map { |id| { id: id, question_body: choices_by_identifier[id].content } }
         
     | 
| 
      
 28 
     | 
    
         
            +
                        end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                        def answers
         
     | 
| 
      
 31 
     | 
    
         
            +
                          answer_nodes.map { |node| Choices::SimpleAssociableChoice.new(node) }
         
     | 
| 
      
 32 
     | 
    
         
            +
                        end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                        def scoring_data_structs
         
     | 
| 
      
 35 
     | 
    
         
            +
                          question_response_pairs.map do |question_id, answer_id|
         
     | 
| 
      
 36 
     | 
    
         
            +
                            content = choices_by_identifier[answer_id].content
         
     | 
| 
      
 37 
     | 
    
         
            +
                            ScoringData.new(content, 'Pair', id: answer_id, question_id: question_id)
         
     | 
| 
      
 38 
     | 
    
         
            +
                          end
         
     | 
| 
      
 39 
     | 
    
         
            +
                        end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                        private
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                        def choices_by_identifier
         
     | 
| 
      
 44 
     | 
    
         
            +
                          @_choices_by_identifier ||= choices.reduce({}) do |acc, choice|
         
     | 
| 
      
 45 
     | 
    
         
            +
                            acc.update choice.attributes['identifier'].value => choice
         
     | 
| 
      
 46 
     | 
    
         
            +
                          end
         
     | 
| 
      
 47 
     | 
    
         
            +
                        end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                        def answer_nodes
         
     | 
| 
      
 50 
     | 
    
         
            +
                          @_answer_nodes ||= choices.select { |c| answer_ids.include?(c.attributes['identifier'].value) }
         
     | 
| 
      
 51 
     | 
    
         
            +
                        end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                        def questions_ids
         
     | 
| 
      
 54 
     | 
    
         
            +
                          @_questions_ids ||= question_response_pairs.map { |question_id, _| question_id }
         
     | 
| 
      
 55 
     | 
    
         
            +
                        end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                        def answer_ids
         
     | 
| 
      
 58 
     | 
    
         
            +
                          @_answer_ids ||= question_response_pairs.map { |_, answer_id| answer_id }
         
     | 
| 
      
 59 
     | 
    
         
            +
                        end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                        def choices
         
     | 
| 
      
 62 
     | 
    
         
            +
                          node.xpath('.//xmlns:simpleAssociableChoice')
         
     | 
| 
      
 63 
     | 
    
         
            +
                        end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                        def question_response_pairs
         
     | 
| 
      
 66 
     | 
    
         
            +
                          node.xpath('.//xmlns:correctResponse//xmlns:value').map do |value|
         
     | 
| 
      
 67 
     | 
    
         
            +
                            value.content.split
         
     | 
| 
      
 68 
     | 
    
         
            +
                          end
         
     | 
| 
      
 69 
     | 
    
         
            +
                        end
         
     | 
| 
      
 70 
     | 
    
         
            +
                      end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/qti/v2/models/interactions/match_item_tag_processors/match_interaction_tag_processor.rb
    ADDED
    
    | 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Qti
         
     | 
| 
      
 2 
     | 
    
         
            +
              module V2
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Models
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module Interactions
         
     | 
| 
      
 5 
     | 
    
         
            +
                    module MatchItemTagProcesssors
         
     | 
| 
      
 6 
     | 
    
         
            +
                      class MatchInteractionTagProcessor < Interactions::BaseInteraction
         
     | 
| 
      
 7 
     | 
    
         
            +
                        def self.match_interaction_tag?(node)
         
     | 
| 
      
 8 
     | 
    
         
            +
                          node.xpath('//xmlns:matchInteraction').count == 1
         
     | 
| 
      
 9 
     | 
    
         
            +
                        end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                        def self.number_of_questions_per_answer(node)
         
     | 
| 
      
 12 
     | 
    
         
            +
                          correct_categories = node.xpath('.//xmlns:correctResponse//xmlns:value')
         
     | 
| 
      
 13 
     | 
    
         
            +
                                                   .map { |value| value.content.split.last }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                          correct_categories.each_with_object(Hash.new(0)) { |category_id, counts| counts[category_id] += 1 }.values
         
     | 
| 
      
 16 
     | 
    
         
            +
                        end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                        def questions
         
     | 
| 
      
 19 
     | 
    
         
            +
                          questions_ids.map { |id| { id: id, question_body: choices_by_identifier[id].content } }
         
     | 
| 
      
 20 
     | 
    
         
            +
                        end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                        def shuffled?
         
     | 
| 
      
 23 
     | 
    
         
            +
                          node.at_xpath('.//xmlns:matchInteraction').attributes['shuffle']&.value.try(:downcase) == 'true'
         
     | 
| 
      
 24 
     | 
    
         
            +
                        end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                        def answers
         
     | 
| 
      
 27 
     | 
    
         
            +
                          answer_nodes.map { |node| Choices::SimpleAssociableChoice.new(node) }
         
     | 
| 
      
 28 
     | 
    
         
            +
                        end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                        def scoring_data_structs
         
     | 
| 
      
 31 
     | 
    
         
            +
                          question_response_pairs.map do |question_id, answer_id|
         
     | 
| 
      
 32 
     | 
    
         
            +
                            content = choices_by_identifier[answer_id].content
         
     | 
| 
      
 33 
     | 
    
         
            +
                            ScoringData.new(content, 'Pair', id: answer_id, question_id: question_id)
         
     | 
| 
      
 34 
     | 
    
         
            +
                          end
         
     | 
| 
      
 35 
     | 
    
         
            +
                        end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                        def choices
         
     | 
| 
      
 38 
     | 
    
         
            +
                          node.xpath('.//xmlns:simpleAssociableChoice')
         
     | 
| 
      
 39 
     | 
    
         
            +
                        end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                        def question_response_pairs
         
     | 
| 
      
 42 
     | 
    
         
            +
                          node.xpath('.//xmlns:correctResponse//xmlns:value').map do |value|
         
     | 
| 
      
 43 
     | 
    
         
            +
                            value.content.split
         
     | 
| 
      
 44 
     | 
    
         
            +
                          end
         
     | 
| 
      
 45 
     | 
    
         
            +
                        end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                        private
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                        def questions_ids
         
     | 
| 
      
 50 
     | 
    
         
            +
                          @_questions_ids ||= question_response_pairs.map { |question_id, _| question_id }
         
     | 
| 
      
 51 
     | 
    
         
            +
                        end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                        def choices_by_identifier
         
     | 
| 
      
 54 
     | 
    
         
            +
                          @choices_by_identifier ||= choices.reduce({}) do |acc, choice|
         
     | 
| 
      
 55 
     | 
    
         
            +
                            acc.update choice.attributes['identifier'].value => choice
         
     | 
| 
      
 56 
     | 
    
         
            +
                          end
         
     | 
| 
      
 57 
     | 
    
         
            +
                        end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                        def answer_nodes
         
     | 
| 
      
 60 
     | 
    
         
            +
                          node.xpath('.//xmlns:matchInteraction//xmlns:simpleMatchSet[2]//xmlns:simpleAssociableChoice')
         
     | 
| 
      
 61 
     | 
    
         
            +
                        end
         
     | 
| 
      
 62 
     | 
    
         
            +
                      end
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,9 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Qti
         
     | 
| 
       2 
2 
     | 
    
         
             
              module V2
         
     | 
| 
       3 
3 
     | 
    
         
             
                module Models
         
     | 
| 
       4 
     | 
    
         
            -
                  ScoringData = Struct.new(:values, :type, :id, :case) do
         
     | 
| 
       5 
     | 
    
         
            -
                    def initialize(values,  
     | 
| 
       6 
     | 
    
         
            -
                      super(values,  
     | 
| 
      
 4 
     | 
    
         
            +
                  ScoringData = Struct.new(:values, :type, :id, :case, :question_id, :questions_ids) do
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def initialize(values, type, options={})
         
     | 
| 
      
 6 
     | 
    
         
            +
                      super(values, type, options[:id], options[:case], options[:question_id], options[:questions_ids])
         
     | 
| 
       7 
7 
     | 
    
         
             
                    end
         
     | 
| 
       8 
8 
     | 
    
         
             
                  end
         
     | 
| 
       9 
9 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <?xml version="1.0" encoding="UTF-8"?>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p2  http://www.imsglobal.org/xsd/qti/qtiv2p2/imsqti_v2p2.xsd" identifier="match" title="Characters and Plays" adaptive="false" timeDependent="false">
         
     | 
| 
      
 3 
     | 
    
         
            +
              <responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="directedPair">
         
     | 
| 
      
 4 
     | 
    
         
            +
                <correctResponse>
         
     | 
| 
      
 5 
     | 
    
         
            +
                  <value>C R</value>
         
     | 
| 
      
 6 
     | 
    
         
            +
                  <value>D M</value>
         
     | 
| 
      
 7 
     | 
    
         
            +
                  <value>L M</value>
         
     | 
| 
      
 8 
     | 
    
         
            +
                  <value>P T</value>
         
     | 
| 
      
 9 
     | 
    
         
            +
                </correctResponse>
         
     | 
| 
      
 10 
     | 
    
         
            +
                <mapping defaultValue="0">
         
     | 
| 
      
 11 
     | 
    
         
            +
                  <mapEntry mapKey="C R" mappedValue="1"/>
         
     | 
| 
      
 12 
     | 
    
         
            +
                  <mapEntry mapKey="D M" mappedValue="0.5"/>
         
     | 
| 
      
 13 
     | 
    
         
            +
                  <mapEntry mapKey="L M" mappedValue="0.5"/>
         
     | 
| 
      
 14 
     | 
    
         
            +
                  <mapEntry mapKey="P T" mappedValue="1"/>
         
     | 
| 
      
 15 
     | 
    
         
            +
                </mapping>
         
     | 
| 
      
 16 
     | 
    
         
            +
              </responseDeclaration>
         
     | 
| 
      
 17 
     | 
    
         
            +
              <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"/>
         
     | 
| 
      
 18 
     | 
    
         
            +
              <itemBody>
         
     | 
| 
      
 19 
     | 
    
         
            +
                <matchInteraction responseIdentifier="RESPONSE" shuffle="true" maxAssociations="4">
         
     | 
| 
      
 20 
     | 
    
         
            +
                  <prompt>Match the following characters to the Shakespeare play they appeared in:</prompt>
         
     | 
| 
      
 21 
     | 
    
         
            +
                  <simpleMatchSet>
         
     | 
| 
      
 22 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="C" matchMax="1">Capulet</simpleAssociableChoice>
         
     | 
| 
      
 23 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="D" matchMax="1">Demetrius</simpleAssociableChoice>
         
     | 
| 
      
 24 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="L" matchMax="1">Lysander</simpleAssociableChoice>
         
     | 
| 
      
 25 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="P" matchMax="1">Prospero</simpleAssociableChoice>
         
     | 
| 
      
 26 
     | 
    
         
            +
                  </simpleMatchSet>
         
     | 
| 
      
 27 
     | 
    
         
            +
                  <simpleMatchSet>
         
     | 
| 
      
 28 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="M" matchMax="4">A Midsummer-Night's Dream</simpleAssociableChoice>
         
     | 
| 
      
 29 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="R" matchMax="4">Romeo and Juliet</simpleAssociableChoice>
         
     | 
| 
      
 30 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="T" matchMax="4">The Tempest</simpleAssociableChoice>
         
     | 
| 
      
 31 
     | 
    
         
            +
                  </simpleMatchSet>
         
     | 
| 
      
 32 
     | 
    
         
            +
                </matchInteraction>
         
     | 
| 
      
 33 
     | 
    
         
            +
              </itemBody>
         
     | 
| 
      
 34 
     | 
    
         
            +
              <responseProcessing template="http://www.imsglobal.org/question/qti_v2p2/rptemplates/map_response"/>
         
     | 
| 
      
 35 
     | 
    
         
            +
            </assessmentItem>
         
     | 
| 
         @@ -1,35 +1,28 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            <?xml version="1.0" encoding=" 
     | 
| 
       2 
     | 
    
         
            -
            <assessmentItem xmlns="http://www.imsglobal.org/xsd/ 
     | 
| 
       3 
     | 
    
         
            -
              <responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType=" 
     | 
| 
      
 1 
     | 
    
         
            +
            <?xml version="1.0" encoding="utf-8"?>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 http://www.imsglobal.org/xsd/qti/qtiv2p1/imsqti_v2p1p2.xsd" identifier="associate" title="Shakespearian Rivals" adaptive="false" timeDependent="false">
         
     | 
| 
      
 3 
     | 
    
         
            +
              <responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="pair">
         
     | 
| 
       4 
4 
     | 
    
         
             
                <correctResponse>
         
     | 
| 
       5 
     | 
    
         
            -
                  <value> 
     | 
| 
       6 
     | 
    
         
            -
                  <value> 
     | 
| 
       7 
     | 
    
         
            -
                  <value>L 
     | 
| 
       8 
     | 
    
         
            -
                  <value>P T</value>
         
     | 
| 
      
 5 
     | 
    
         
            +
                  <value>A P</value>
         
     | 
| 
      
 6 
     | 
    
         
            +
                  <value>C M</value>
         
     | 
| 
      
 7 
     | 
    
         
            +
                  <value>D L</value>
         
     | 
| 
       9 
8 
     | 
    
         
             
                </correctResponse>
         
     | 
| 
       10 
9 
     | 
    
         
             
                <mapping defaultValue="0">
         
     | 
| 
       11 
     | 
    
         
            -
                  <mapEntry mapKey=" 
     | 
| 
       12 
     | 
    
         
            -
                  <mapEntry mapKey=" 
     | 
| 
       13 
     | 
    
         
            -
                  <mapEntry mapKey="L 
     | 
| 
       14 
     | 
    
         
            -
                  <mapEntry mapKey="P T" mappedValue="1"/>
         
     | 
| 
      
 10 
     | 
    
         
            +
                  <mapEntry mapKey="A P" mappedValue="2"/>
         
     | 
| 
      
 11 
     | 
    
         
            +
                  <mapEntry mapKey="C M" mappedValue="1"/>
         
     | 
| 
      
 12 
     | 
    
         
            +
                  <mapEntry mapKey="D L" mappedValue="1"/>
         
     | 
| 
       15 
13 
     | 
    
         
             
                </mapping>
         
     | 
| 
       16 
14 
     | 
    
         
             
              </responseDeclaration>
         
     | 
| 
       17 
15 
     | 
    
         
             
              <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"/>
         
     | 
| 
       18 
16 
     | 
    
         
             
              <itemBody>
         
     | 
| 
       19 
     | 
    
         
            -
                < 
     | 
| 
       20 
     | 
    
         
            -
                  <prompt> 
     | 
| 
       21 
     | 
    
         
            -
                  < 
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
                  </ 
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                    <simpleAssociableChoice identifier="M" matchMax="4">A Midsummer-Night's Dream</simpleAssociableChoice>
         
     | 
| 
       29 
     | 
    
         
            -
                    <simpleAssociableChoice identifier="R" matchMax="4">Romeo and Juliet</simpleAssociableChoice>
         
     | 
| 
       30 
     | 
    
         
            -
                    <simpleAssociableChoice identifier="T" matchMax="4">The Tempest</simpleAssociableChoice>
         
     | 
| 
       31 
     | 
    
         
            -
                  </simpleMatchSet>
         
     | 
| 
       32 
     | 
    
         
            -
                </matchInteraction>
         
     | 
| 
      
 17 
     | 
    
         
            +
                <associateInteraction responseIdentifier="RESPONSE" shuffle="true" maxAssociations="3">
         
     | 
| 
      
 18 
     | 
    
         
            +
                  <prompt>Hidden in this list of characters from famous Shakespeare plays are three pairs of rivals. Can you match each character to his adversary?</prompt>
         
     | 
| 
      
 19 
     | 
    
         
            +
                  <simpleAssociableChoice identifier="A" matchMax="1">Antonio</simpleAssociableChoice>
         
     | 
| 
      
 20 
     | 
    
         
            +
                  <simpleAssociableChoice identifier="C" matchMax="1">Capulet</simpleAssociableChoice>
         
     | 
| 
      
 21 
     | 
    
         
            +
                  <simpleAssociableChoice identifier="D" matchMax="1">Demetrius</simpleAssociableChoice>
         
     | 
| 
      
 22 
     | 
    
         
            +
                  <simpleAssociableChoice identifier="L" matchMax="1">Lysander</simpleAssociableChoice>
         
     | 
| 
      
 23 
     | 
    
         
            +
                  <simpleAssociableChoice identifier="M" matchMax="1">Montague</simpleAssociableChoice>
         
     | 
| 
      
 24 
     | 
    
         
            +
                  <simpleAssociableChoice identifier="P" matchMax="1">Prospero</simpleAssociableChoice>
         
     | 
| 
      
 25 
     | 
    
         
            +
                </associateInteraction>
         
     | 
| 
       33 
26 
     | 
    
         
             
              </itemBody>
         
     | 
| 
       34 
     | 
    
         
            -
              <responseProcessing template="http://www.imsglobal.org/question/ 
     | 
| 
      
 27 
     | 
    
         
            +
              <responseProcessing template="http://www.imsglobal.org/question/qti_v2p1/rptemplates/map_response"/>
         
     | 
| 
       35 
28 
     | 
    
         
             
            </assessmentItem>
         
     | 
| 
         @@ -0,0 +1,119 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <?xml version="1.0" encoding="UTF-8"?>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <!--This file was created using: Onyx Editor, Version 3.4.3 (Full, licensed version), (c)2012 BPS Bildungsportal Sachsen GmbH-->
         
     | 
| 
      
 3 
     | 
    
         
            +
            <assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p2 http://www.imsglobal.org/xsd/qti/qtiv2p2/imsqti_v2p2.xsd" identifier="Matchsingle_143114773" title="match (single)" adaptive="false" timeDependent="false">
         
     | 
| 
      
 4 
     | 
    
         
            +
              <responseDeclaration identifier="RESPONSE" cardinality="multiple" baseType="directedPair">
         
     | 
| 
      
 5 
     | 
    
         
            +
                <correctResponse>
         
     | 
| 
      
 6 
     | 
    
         
            +
                  <value>Match28433682 Match2675678</value>
         
     | 
| 
      
 7 
     | 
    
         
            +
                  <value>Match7191791 Match9372581</value>
         
     | 
| 
      
 8 
     | 
    
         
            +
                  <value>Match20473010 Match22744006</value>
         
     | 
| 
      
 9 
     | 
    
         
            +
                  <value>Match6429655 Match17943221</value>
         
     | 
| 
      
 10 
     | 
    
         
            +
                </correctResponse>
         
     | 
| 
      
 11 
     | 
    
         
            +
              </responseDeclaration>
         
     | 
| 
      
 12 
     | 
    
         
            +
              <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float">
         
     | 
| 
      
 13 
     | 
    
         
            +
                <defaultValue>
         
     | 
| 
      
 14 
     | 
    
         
            +
                  <value>0.0</value>
         
     | 
| 
      
 15 
     | 
    
         
            +
                </defaultValue>
         
     | 
| 
      
 16 
     | 
    
         
            +
              </outcomeDeclaration>
         
     | 
| 
      
 17 
     | 
    
         
            +
              <outcomeDeclaration identifier="MAXSCORE" cardinality="single" baseType="float">
         
     | 
| 
      
 18 
     | 
    
         
            +
                <defaultValue>
         
     | 
| 
      
 19 
     | 
    
         
            +
                  <value>1.0</value>
         
     | 
| 
      
 20 
     | 
    
         
            +
                </defaultValue>
         
     | 
| 
      
 21 
     | 
    
         
            +
              </outcomeDeclaration>
         
     | 
| 
      
 22 
     | 
    
         
            +
              <outcomeDeclaration identifier="FEEDBACKBASIC" cardinality="single" baseType="identifier">
         
     | 
| 
      
 23 
     | 
    
         
            +
                <defaultValue>
         
     | 
| 
      
 24 
     | 
    
         
            +
                  <value>empty</value>
         
     | 
| 
      
 25 
     | 
    
         
            +
                </defaultValue>
         
     | 
| 
      
 26 
     | 
    
         
            +
              </outcomeDeclaration>
         
     | 
| 
      
 27 
     | 
    
         
            +
              <outcomeDeclaration identifier="FEEDBACKMODAL" cardinality="multiple" baseType="identifier" view="testConstructor"/>
         
     | 
| 
      
 28 
     | 
    
         
            +
              <itemBody>
         
     | 
| 
      
 29 
     | 
    
         
            +
                <div>Der wichtigste, größte und einzig schiffbare Fluss des Bundeslandes Sachsens ist die
         
     | 
| 
      
 30 
     | 
    
         
            +
                  Elbe. Die verschiedene Quellflüsse der Elbe durchziehen die sächsischen Städte.
         
     | 
| 
      
 31 
     | 
    
         
            +
                  <br/>Ordne anhand des Flusslaufs die Quellflüsse den gegebenen Städten zu.</div>
         
     | 
| 
      
 32 
     | 
    
         
            +
                <matchInteraction responseIdentifier="RESPONSE" shuffle="true" maxAssociations="0">
         
     | 
| 
      
 33 
     | 
    
         
            +
                  <simpleMatchSet>
         
     | 
| 
      
 34 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match28433682" fixed="false" matchMin="1" matchMax="1">Weißeritz</simpleAssociableChoice>
         
     | 
| 
      
 35 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match7191791" fixed="false" matchMin="1" matchMax="1">Mulde</simpleAssociableChoice>
         
     | 
| 
      
 36 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match20473010" fixed="false" matchMin="1" matchMax="1">Saale</simpleAssociableChoice>
         
     | 
| 
      
 37 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match6429655" fixed="false" matchMin="1" matchMax="1">Spree</simpleAssociableChoice>
         
     | 
| 
      
 38 
     | 
    
         
            +
                  </simpleMatchSet>
         
     | 
| 
      
 39 
     | 
    
         
            +
                  <simpleMatchSet>
         
     | 
| 
      
 40 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match2675678" fixed="false" matchMin="1" matchMax="1">Dresden</simpleAssociableChoice>
         
     | 
| 
      
 41 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match9372581" fixed="false" matchMin="1" matchMax="1">Leipzig</simpleAssociableChoice>
         
     | 
| 
      
 42 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match22744006" fixed="false" matchMin="1" matchMax="1">Halle</simpleAssociableChoice>
         
     | 
| 
      
 43 
     | 
    
         
            +
                    <simpleAssociableChoice identifier="Match17943221" fixed="false" matchMin="1" matchMax="1">Bautzen</simpleAssociableChoice>
         
     | 
| 
      
 44 
     | 
    
         
            +
                  </simpleMatchSet>
         
     | 
| 
      
 45 
     | 
    
         
            +
                </matchInteraction>
         
     | 
| 
      
 46 
     | 
    
         
            +
              </itemBody>
         
     | 
| 
      
 47 
     | 
    
         
            +
              <responseProcessing>
         
     | 
| 
      
 48 
     | 
    
         
            +
                <responseCondition>
         
     | 
| 
      
 49 
     | 
    
         
            +
                  <responseIf>
         
     | 
| 
      
 50 
     | 
    
         
            +
                    <isNull>
         
     | 
| 
      
 51 
     | 
    
         
            +
                      <variable identifier="RESPONSE"/>
         
     | 
| 
      
 52 
     | 
    
         
            +
                    </isNull>
         
     | 
| 
      
 53 
     | 
    
         
            +
                    <setOutcomeValue identifier="FEEDBACKBASIC">
         
     | 
| 
      
 54 
     | 
    
         
            +
                      <baseValue baseType="identifier">empty</baseValue>
         
     | 
| 
      
 55 
     | 
    
         
            +
                    </setOutcomeValue>
         
     | 
| 
      
 56 
     | 
    
         
            +
                  </responseIf>
         
     | 
| 
      
 57 
     | 
    
         
            +
                  <responseElseIf>
         
     | 
| 
      
 58 
     | 
    
         
            +
                    <match>
         
     | 
| 
      
 59 
     | 
    
         
            +
                      <variable identifier="RESPONSE"/>
         
     | 
| 
      
 60 
     | 
    
         
            +
                      <correct identifier="RESPONSE"/>
         
     | 
| 
      
 61 
     | 
    
         
            +
                    </match>
         
     | 
| 
      
 62 
     | 
    
         
            +
                    <setOutcomeValue identifier="SCORE">
         
     | 
| 
      
 63 
     | 
    
         
            +
                      <sum>
         
     | 
| 
      
 64 
     | 
    
         
            +
                        <variable identifier="SCORE"/>
         
     | 
| 
      
 65 
     | 
    
         
            +
                        <variable identifier="MAXSCORE"/>
         
     | 
| 
      
 66 
     | 
    
         
            +
                      </sum>
         
     | 
| 
      
 67 
     | 
    
         
            +
                    </setOutcomeValue>
         
     | 
| 
      
 68 
     | 
    
         
            +
                    <setOutcomeValue identifier="FEEDBACKBASIC">
         
     | 
| 
      
 69 
     | 
    
         
            +
                      <baseValue baseType="identifier">correct</baseValue>
         
     | 
| 
      
 70 
     | 
    
         
            +
                    </setOutcomeValue>
         
     | 
| 
      
 71 
     | 
    
         
            +
                  </responseElseIf>
         
     | 
| 
      
 72 
     | 
    
         
            +
                  <responseElse>
         
     | 
| 
      
 73 
     | 
    
         
            +
                    <setOutcomeValue identifier="FEEDBACKBASIC">
         
     | 
| 
      
 74 
     | 
    
         
            +
                      <baseValue baseType="identifier">incorrect</baseValue>
         
     | 
| 
      
 75 
     | 
    
         
            +
                    </setOutcomeValue>
         
     | 
| 
      
 76 
     | 
    
         
            +
                  </responseElse>
         
     | 
| 
      
 77 
     | 
    
         
            +
                </responseCondition>
         
     | 
| 
      
 78 
     | 
    
         
            +
                <responseCondition>
         
     | 
| 
      
 79 
     | 
    
         
            +
                  <responseIf>
         
     | 
| 
      
 80 
     | 
    
         
            +
                    <and>
         
     | 
| 
      
 81 
     | 
    
         
            +
                      <match>
         
     | 
| 
      
 82 
     | 
    
         
            +
                        <baseValue baseType="identifier">correct</baseValue>
         
     | 
| 
      
 83 
     | 
    
         
            +
                        <variable identifier="FEEDBACKBASIC"/>
         
     | 
| 
      
 84 
     | 
    
         
            +
                      </match>
         
     | 
| 
      
 85 
     | 
    
         
            +
                    </and>
         
     | 
| 
      
 86 
     | 
    
         
            +
                    <setOutcomeValue identifier="FEEDBACKMODAL">
         
     | 
| 
      
 87 
     | 
    
         
            +
                      <multiple>
         
     | 
| 
      
 88 
     | 
    
         
            +
                        <variable identifier="FEEDBACKMODAL"/>
         
     | 
| 
      
 89 
     | 
    
         
            +
                        <baseValue baseType="identifier">FEEDBACK_27448254</baseValue>
         
     | 
| 
      
 90 
     | 
    
         
            +
                      </multiple>
         
     | 
| 
      
 91 
     | 
    
         
            +
                    </setOutcomeValue>
         
     | 
| 
      
 92 
     | 
    
         
            +
                  </responseIf>
         
     | 
| 
      
 93 
     | 
    
         
            +
                </responseCondition>
         
     | 
| 
      
 94 
     | 
    
         
            +
                <responseCondition>
         
     | 
| 
      
 95 
     | 
    
         
            +
                  <responseIf>
         
     | 
| 
      
 96 
     | 
    
         
            +
                    <and>
         
     | 
| 
      
 97 
     | 
    
         
            +
                      <match>
         
     | 
| 
      
 98 
     | 
    
         
            +
                        <baseValue baseType="identifier">incorrect</baseValue>
         
     | 
| 
      
 99 
     | 
    
         
            +
                        <variable identifier="FEEDBACKBASIC"/>
         
     | 
| 
      
 100 
     | 
    
         
            +
                      </match>
         
     | 
| 
      
 101 
     | 
    
         
            +
                    </and>
         
     | 
| 
      
 102 
     | 
    
         
            +
                    <setOutcomeValue identifier="FEEDBACKMODAL">
         
     | 
| 
      
 103 
     | 
    
         
            +
                      <multiple>
         
     | 
| 
      
 104 
     | 
    
         
            +
                        <variable identifier="FEEDBACKMODAL"/>
         
     | 
| 
      
 105 
     | 
    
         
            +
                        <baseValue baseType="identifier">FEEDBACK_16479834</baseValue>
         
     | 
| 
      
 106 
     | 
    
         
            +
                      </multiple>
         
     | 
| 
      
 107 
     | 
    
         
            +
                    </setOutcomeValue>
         
     | 
| 
      
 108 
     | 
    
         
            +
                  </responseIf>
         
     | 
| 
      
 109 
     | 
    
         
            +
                </responseCondition>
         
     | 
| 
      
 110 
     | 
    
         
            +
              </responseProcessing>
         
     | 
| 
      
 111 
     | 
    
         
            +
              <modalFeedback identifier="FEEDBACK_27448254" outcomeIdentifier="FEEDBACKMODAL" showHide="show" title="Richtig!">Die Elbe durchzieht den Freistaat von Südosten nach Nordwesten. Wichtige
         
     | 
| 
      
 112 
     | 
    
         
            +
                Quellflüsse sind die Mulde, die Weißeritz, die Zschopau, die Weiße Elster und die Spree,
         
     | 
| 
      
 113 
     | 
    
         
            +
                deren allgemeine Fließrichtung Norden ist und die ebenfalls zum Fluss-System der Elbe
         
     | 
| 
      
 114 
     | 
    
         
            +
                gehören.</modalFeedback>
         
     | 
| 
      
 115 
     | 
    
         
            +
              <modalFeedback identifier="FEEDBACK_16479834" outcomeIdentifier="FEEDBACKMODAL" showHide="show" title="Leider Falsch!">Die Elbe durchzieht den Freistaat von Südosten nach Nordwesten.
         
     | 
| 
      
 116 
     | 
    
         
            +
                Wichtige Quellflüsse sind die Mulde, die Weißeritz, die Zschopau, die Weiße Elster und die
         
     | 
| 
      
 117 
     | 
    
         
            +
                Spree, deren allgemeine Fließrichtung Norden ist und die ebenfalls zum Fluss-System der Elbe
         
     | 
| 
      
 118 
     | 
    
         
            +
                gehören.</modalFeedback>
         
     | 
| 
      
 119 
     | 
    
         
            +
            </assessmentItem>
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Qti::V1::Models::Interactions::MatchInteraction do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:file) { File.join('spec', 'fixtures', 'items_1.2', 'matching.xml') }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:assessment) { Qti::V1::Models::Assessment.from_path!(file) }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:item) { assessment.assessment_items.first }
         
     | 
| 
      
 7 
     | 
    
         
            +
              subject { described_class.new(item) }
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              it 'returns shuffle setting' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                expect(subject.shuffled?).to eq false
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              it 'returns the answers' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                expect(subject.answers.map(&:item_body)).to eq(
         
     | 
| 
      
 15 
     | 
    
         
            +
                  ['Magnify up to about 400 times. Sometimes requires colored staining of cells.',
         
     | 
| 
      
 16 
     | 
    
         
            +
                   "Uses a beam of electrons. Can provide details of cells' internal structure.",
         
     | 
| 
      
 17 
     | 
    
         
            +
                   'A distractor answer.']
         
     | 
| 
      
 18 
     | 
    
         
            +
                )
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              describe '.matches' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                it 'matches the item in file' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  expect(described_class.matches(item)).to be_truthy
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              describe '#scoring_data_structs' do
         
     | 
| 
      
 28 
     | 
    
         
            +
                it 'grabs scoring data value for matching questions' do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  expect(subject.scoring_data_structs.first.values).to eq(
         
     | 
| 
      
 30 
     | 
    
         
            +
                    'question_1' => 'Magnify up to about 400 times. Sometimes requires colored staining of cells.',
         
     | 
| 
      
 31 
     | 
    
         
            +
                    'question_2' => "Uses a beam of electrons. Can provide details of cells' internal structure."
         
     | 
| 
      
 32 
     | 
    
         
            +
                  )
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              describe '#questions' do
         
     | 
| 
      
 37 
     | 
    
         
            +
                it 'returns the questions' do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  expect(subject.questions).to eq(
         
     | 
| 
      
 39 
     | 
    
         
            +
                    [{ id: 'question_1', question_body: 'Light Microscope' },
         
     | 
| 
      
 40 
     | 
    
         
            +
                     { id: 'question_2', question_body: 'Electron Microscopes' }]
         
     | 
| 
      
 41 
     | 
    
         
            +
                  )
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -64,28 +64,4 @@ describe Qti::V2::Models::AssessmentItem do 
     | 
|
| 
       64 
64 
     | 
    
         
             
                  end
         
     | 
| 
       65 
65 
     | 
    
         
             
                end
         
     | 
| 
       66 
66 
     | 
    
         
             
              end
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
              describe '#scoring_data_structs' do
         
     | 
| 
       69 
     | 
    
         
            -
                it 'grabs scoring data value for matching questions' do
         
     | 
| 
       70 
     | 
    
         
            -
                  assessment_item = Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/match.xml'
         
     | 
| 
       71 
     | 
    
         
            -
                  expect(assessment_item.interaction_model).to be_instance_of Qti::V2::Models::Interactions::MatchInteraction
         
     | 
| 
       72 
     | 
    
         
            -
                  expect(assessment_item.scoring_data_structs.first.values).to eq(
         
     | 
| 
       73 
     | 
    
         
            -
                    'C' => 'Romeo and Juliet',
         
     | 
| 
       74 
     | 
    
         
            -
                    'D' => "A Midsummer-Night's Dream",
         
     | 
| 
       75 
     | 
    
         
            -
                    'L' => "A Midsummer-Night's Dream",
         
     | 
| 
       76 
     | 
    
         
            -
                    'P' => 'The Tempest'
         
     | 
| 
       77 
     | 
    
         
            -
                  )
         
     | 
| 
       78 
     | 
    
         
            -
                  expect(assessment_item.interaction_model.questions).to eq(
         
     | 
| 
       79 
     | 
    
         
            -
                    [{ id: 'C', question_body: 'Capulet' },
         
     | 
| 
       80 
     | 
    
         
            -
                     { id: 'D', question_body: 'Demetrius' },
         
     | 
| 
       81 
     | 
    
         
            -
                     { id: 'L', question_body: 'Lysander' },
         
     | 
| 
       82 
     | 
    
         
            -
                     { id: 'P', question_body: 'Prospero' }]
         
     | 
| 
       83 
     | 
    
         
            -
                  )
         
     | 
| 
       84 
     | 
    
         
            -
                  expect(assessment_item.interaction_model.answers.map(&:item_body)).to eq(
         
     | 
| 
       85 
     | 
    
         
            -
                    ["A Midsummer-Night's Dream",
         
     | 
| 
       86 
     | 
    
         
            -
                     'Romeo and Juliet',
         
     | 
| 
       87 
     | 
    
         
            -
                     'The Tempest']
         
     | 
| 
       88 
     | 
    
         
            -
                  )
         
     | 
| 
       89 
     | 
    
         
            -
                end
         
     | 
| 
       90 
     | 
    
         
            -
              end
         
     | 
| 
       91 
67 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Qti::V2::Models::Choices::SimpleAssociableChoice do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:io) { File.read('spec/fixtures/items_2.1/match2.xml') }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:nodes) { Nokogiri::XML(io).xpath('//xmlns:simpleAssociableChoice') }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:choices) { nodes.map { |node| described_class.new(node) } }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              it 'returns the expected attributes' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                expected_attrs = [
         
     | 
| 
      
 10 
     | 
    
         
            +
                  %w(Match28433682 1 1 Weißeritz),
         
     | 
| 
      
 11 
     | 
    
         
            +
                  %w(Match7191791 1 1 Mulde),
         
     | 
| 
      
 12 
     | 
    
         
            +
                  %w(Match20473010 1 1 Saale),
         
     | 
| 
      
 13 
     | 
    
         
            +
                  %w(Match6429655 1 1 Spree),
         
     | 
| 
      
 14 
     | 
    
         
            +
                  %w(Match2675678 1 1 Dresden),
         
     | 
| 
      
 15 
     | 
    
         
            +
                  %w(Match9372581 1 1 Leipzig),
         
     | 
| 
      
 16 
     | 
    
         
            +
                  %w(Match22744006 1 1 Halle),
         
     | 
| 
      
 17 
     | 
    
         
            +
                  %w(Match17943221 1 1 Bautzen)
         
     | 
| 
      
 18 
     | 
    
         
            +
                ]
         
     | 
| 
      
 19 
     | 
    
         
            +
                expect(choices.map { |c| [c.identifier, c.match_min, c.match_max, c.item_body] }).to eq expected_attrs
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Qti::V2::Models::Interactions::CategorizationInteraction do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:assessment_item) { Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/categorization.xml' }
         
     | 
| 
      
 5 
     | 
    
         
            +
              subject { assessment_item.interaction_model }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              it { is_expected.to be_an_instance_of(described_class) }
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              it 'returns shuffle setting' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                expect(subject.shuffled?).to eq true
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              describe '#scoring_data_structs' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                it 'returns the scoring data for categorization questions' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                  expected_scoring_data_structs = [
         
     | 
| 
      
 16 
     | 
    
         
            +
                    Qti::V2::Models::ScoringData.new("A Midsummer-Night's Dream", "directedPair", id: "M", questions_ids: ["D", "L"]),
         
     | 
| 
      
 17 
     | 
    
         
            +
                    Qti::V2::Models::ScoringData.new('Romeo and Juliet', "directedPair", id: "R", questions_ids: ['C']),
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Qti::V2::Models::ScoringData.new('The Tempest', "directedPair", id: "T", questions_ids: ['P']),
         
     | 
| 
      
 19 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  expect(subject.scoring_data_structs).to eq expected_scoring_data_structs
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,15 +1,79 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'spec_helper'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            describe Qti::V2::Models::Interactions::MatchInteraction do
         
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
              context 'assessmentItem is implemented with <associateInteraction>' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                let(:assessment_item) { Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/match.xml' }
         
     | 
| 
      
 6 
     | 
    
         
            +
                subject { assessment_item.interaction_model }
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 8 
     | 
    
         
            +
                it { is_expected.to be_an_instance_of(described_class) }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                it 'returns shuffle setting' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  expect(subject.shuffled?).to eq true
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                describe '#scoring_data_structs' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                  it 'grabs scoring data value for matching questions' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                    expect(subject.scoring_data_structs).to eq [
         
     | 
| 
      
 17 
     | 
    
         
            +
                      Qti::V2::Models::ScoringData.new('Prospero', 'Pair', id: 'P', question_id: 'A'),
         
     | 
| 
      
 18 
     | 
    
         
            +
                      Qti::V2::Models::ScoringData.new('Montague', 'Pair', id: 'M', question_id: 'C'),
         
     | 
| 
      
 19 
     | 
    
         
            +
                      Qti::V2::Models::ScoringData.new('Lysander', 'Pair', id: 'L', question_id: 'D')
         
     | 
| 
      
 20 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                describe '#answers' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                  it 'returns the correct_answers' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                    expect(subject.answers.map(&:item_body)).to eq(%w[Lysander Montague Prospero])
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                describe '#questions' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  it 'returns the questions' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                    expect(subject.questions).to eq(
         
     | 
| 
      
 33 
     | 
    
         
            +
                      [{ id: 'A', question_body: 'Antonio' },
         
     | 
| 
      
 34 
     | 
    
         
            +
                       { id: 'C', question_body: 'Capulet' },
         
     | 
| 
      
 35 
     | 
    
         
            +
                       { id: 'D', question_body: 'Demetrius' }]
         
     | 
| 
      
 36 
     | 
    
         
            +
                    )
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
       10 
39 
     | 
    
         
             
              end
         
     | 
| 
       11 
40 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
               
     | 
| 
       13 
     | 
    
         
            -
                 
     | 
| 
      
 41 
     | 
    
         
            +
              context 'assessmentItem is implemented with <matchInteraction>' do
         
     | 
| 
      
 42 
     | 
    
         
            +
                let(:assessment_item) { Qti::V2::Models::AssessmentItem.from_path! 'spec/fixtures/items_2.1/match2.xml' }
         
     | 
| 
      
 43 
     | 
    
         
            +
                subject { assessment_item.interaction_model }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                it { is_expected.to be_an_instance_of(described_class) }
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                it 'returns shuffle setting' do
         
     | 
| 
      
 48 
     | 
    
         
            +
                  expect(subject.shuffled?).to eq true
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                describe '#scoring_data_structs' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                  it 'grabs scoring data value for matching questions' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                    expect(subject.scoring_data_structs).to eq [
         
     | 
| 
      
 54 
     | 
    
         
            +
                      Qti::V2::Models::ScoringData.new('Dresden', 'Pair', id: 'Match2675678', question_id: 'Match28433682'),
         
     | 
| 
      
 55 
     | 
    
         
            +
                      Qti::V2::Models::ScoringData.new('Leipzig', 'Pair', id: 'Match9372581', question_id: 'Match7191791'),
         
     | 
| 
      
 56 
     | 
    
         
            +
                      Qti::V2::Models::ScoringData.new('Halle'  , 'Pair', id: 'Match22744006', question_id: 'Match20473010'),
         
     | 
| 
      
 57 
     | 
    
         
            +
                      Qti::V2::Models::ScoringData.new('Bautzen', 'Pair', id: 'Match17943221', question_id: 'Match6429655')
         
     | 
| 
      
 58 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                describe '#answers' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  it 'returns the correct_answers' do
         
     | 
| 
      
 64 
     | 
    
         
            +
                    expect(subject.answers.map(&:item_body)).to eq %w[Dresden Leipzig Halle Bautzen]
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                describe '#questions' do
         
     | 
| 
      
 69 
     | 
    
         
            +
                  it 'returns the questions' do
         
     | 
| 
      
 70 
     | 
    
         
            +
                    expect(subject.questions).to eq(
         
     | 
| 
      
 71 
     | 
    
         
            +
                      [{ id: 'Match28433682', question_body: 'Weißeritz' },
         
     | 
| 
      
 72 
     | 
    
         
            +
                       { id: 'Match7191791', question_body: 'Mulde' },
         
     | 
| 
      
 73 
     | 
    
         
            +
                       { id: 'Match20473010', question_body: 'Saale' },
         
     | 
| 
      
 74 
     | 
    
         
            +
                       { id: 'Match6429655', question_body: 'Spree' }]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    )
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
       14 
78 
     | 
    
         
             
              end
         
     | 
| 
       15 
79 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # ObjectSpace.each_object(Class).select { |c| c.name =~ /V1.*(?<!Base)Interaction$/ }.each do |klass|
         
     | 
| 
      
 2 
     | 
    
         
            +
            #   klass.class_eval do
         
     | 
| 
      
 3 
     | 
    
         
            +
            #     class << self
         
     | 
| 
      
 4 
     | 
    
         
            +
            #       alias_method :old_matches?, :matches?
         
     | 
| 
      
 5 
     | 
    
         
            +
            #       def matches?(node)
         
     | 
| 
      
 6 
     | 
    
         
            +
            #         raise ArgumentError.new("Expected Nokogiri::XML::Element and got #{node.class}") unless item_element?(node)
         
     | 
| 
      
 7 
     | 
    
         
            +
            #         old_matches?(node)
         
     | 
| 
      
 8 
     | 
    
         
            +
            #       end
         
     | 
| 
      
 9 
     | 
    
         
            +
            #       def item_element?(node)
         
     | 
| 
      
 10 
     | 
    
         
            +
            #         node.class == Nokogiri::XML::Element && node.name == 'item'
         
     | 
| 
      
 11 
     | 
    
         
            +
            #       end
         
     | 
| 
      
 12 
     | 
    
         
            +
            #     end
         
     | 
| 
      
 13 
     | 
    
         
            +
            #   end
         
     | 
| 
      
 14 
     | 
    
         
            +
            # end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: qti
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.5.16
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Hannah Bottalla
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2017-05- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2017-05-17 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: activesupport
         
     | 
| 
         @@ -165,6 +165,20 @@ dependencies: 
     | 
|
| 
       165 
165 
     | 
    
         
             
                - - ">="
         
     | 
| 
       166 
166 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       167 
167 
     | 
    
         
             
                    version: '0'
         
     | 
| 
      
 168 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 169 
     | 
    
         
            +
              name: rubocop
         
     | 
| 
      
 170 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 171 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 172 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 173 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 174 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 175 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 176 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 177 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 178 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 179 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 180 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 181 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
       168 
182 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       169 
183 
     | 
    
         
             
              name: simplecov
         
     | 
| 
       170 
184 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -223,10 +237,13 @@ files: 
     | 
|
| 
       223 
237 
     | 
    
         
             
            - lib/qti/v2/models/choices/simple_choice.rb
         
     | 
| 
       224 
238 
     | 
    
         
             
            - lib/qti/v2/models/interactions.rb
         
     | 
| 
       225 
239 
     | 
    
         
             
            - lib/qti/v2/models/interactions/base_interaction.rb
         
     | 
| 
      
 240 
     | 
    
         
            +
            - lib/qti/v2/models/interactions/categorization_interaction.rb
         
     | 
| 
       226 
241 
     | 
    
         
             
            - lib/qti/v2/models/interactions/choice_interaction.rb
         
     | 
| 
       227 
242 
     | 
    
         
             
            - lib/qti/v2/models/interactions/extended_text_interaction.rb
         
     | 
| 
       228 
243 
     | 
    
         
             
            - lib/qti/v2/models/interactions/gap_match_interaction.rb
         
     | 
| 
       229 
244 
     | 
    
         
             
            - lib/qti/v2/models/interactions/match_interaction.rb
         
     | 
| 
      
 245 
     | 
    
         
            +
            - lib/qti/v2/models/interactions/match_item_tag_processors/associate_interaction_tag_processor.rb
         
     | 
| 
      
 246 
     | 
    
         
            +
            - lib/qti/v2/models/interactions/match_item_tag_processors/match_interaction_tag_processor.rb
         
     | 
| 
       230 
247 
     | 
    
         
             
            - lib/qti/v2/models/scoring_data.rb
         
     | 
| 
       231 
248 
     | 
    
         
             
            - spec/fixtures/items_1.2/choice.xml
         
     | 
| 
       232 
249 
     | 
    
         
             
            - spec/fixtures/items_1.2/essay.xml
         
     | 
| 
         @@ -247,6 +264,7 @@ files: 
     | 
|
| 
       247 
264 
     | 
    
         
             
            - spec/fixtures/items_2.1/adaptive_template.xml
         
     | 
| 
       248 
265 
     | 
    
         
             
            - spec/fixtures/items_2.1/associate.xml
         
     | 
| 
       249 
266 
     | 
    
         
             
            - spec/fixtures/items_2.1/audio-video.xml
         
     | 
| 
      
 267 
     | 
    
         
            +
            - spec/fixtures/items_2.1/categorization.xml
         
     | 
| 
       250 
268 
     | 
    
         
             
            - spec/fixtures/items_2.1/choice.xml
         
     | 
| 
       251 
269 
     | 
    
         
             
            - spec/fixtures/items_2.1/choice_aria.xml
         
     | 
| 
       252 
270 
     | 
    
         
             
            - spec/fixtures/items_2.1/choice_fixed.xml
         
     | 
| 
         @@ -304,6 +322,7 @@ files: 
     | 
|
| 
       304 
322 
     | 
    
         
             
            - spec/fixtures/items_2.1/inline_choice_math.xml
         
     | 
| 
       305 
323 
     | 
    
         
             
            - spec/fixtures/items_2.1/likert.xml
         
     | 
| 
       306 
324 
     | 
    
         
             
            - spec/fixtures/items_2.1/match.xml
         
     | 
| 
      
 325 
     | 
    
         
            +
            - spec/fixtures/items_2.1/match2.xml
         
     | 
| 
       307 
326 
     | 
    
         
             
            - spec/fixtures/items_2.1/math.xml
         
     | 
| 
       308 
327 
     | 
    
         
             
            - spec/fixtures/items_2.1/mc_calc3.xml
         
     | 
| 
       309 
328 
     | 
    
         
             
            - spec/fixtures/items_2.1/mc_calc5.xml
         
     | 
| 
         @@ -422,11 +441,14 @@ files: 
     | 
|
| 
       422 
441 
     | 
    
         
             
            - spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
         
     | 
| 
       423 
442 
     | 
    
         
             
            - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
         
     | 
| 
       424 
443 
     | 
    
         
             
            - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
         
     | 
| 
      
 444 
     | 
    
         
            +
            - spec/lib/qti/v1/models/interactions/match_interaction_spec.rb
         
     | 
| 
       425 
445 
     | 
    
         
             
            - spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
         
     | 
| 
       426 
446 
     | 
    
         
             
            - spec/lib/qti/v2/models/assessment_item_spec.rb
         
     | 
| 
       427 
447 
     | 
    
         
             
            - spec/lib/qti/v2/models/assessment_test_spec.rb
         
     | 
| 
       428 
448 
     | 
    
         
             
            - spec/lib/qti/v2/models/choices/gap_match_choice_spec.rb
         
     | 
| 
      
 449 
     | 
    
         
            +
            - spec/lib/qti/v2/models/choices/simple_associable_choice_spec.rb
         
     | 
| 
       429 
450 
     | 
    
         
             
            - spec/lib/qti/v2/models/choices/simple_choice_spec.rb
         
     | 
| 
      
 451 
     | 
    
         
            +
            - spec/lib/qti/v2/models/interactions/categorization_interaction_spec.rb
         
     | 
| 
       430 
452 
     | 
    
         
             
            - spec/lib/qti/v2/models/interactions/choice_interaction_spec.rb
         
     | 
| 
       431 
453 
     | 
    
         
             
            - spec/lib/qti/v2/models/interactions/extended_text_interaction_spec.rb
         
     | 
| 
       432 
454 
     | 
    
         
             
            - spec/lib/qti/v2/models/interactions/gap_match_interaction_spec.rb
         
     | 
| 
         @@ -434,6 +456,7 @@ files: 
     | 
|
| 
       434 
456 
     | 
    
         
             
            - spec/lib/qti_spec.rb
         
     | 
| 
       435 
457 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
       436 
458 
     | 
    
         
             
            - spec/support/custom_matchers.rb
         
     | 
| 
      
 459 
     | 
    
         
            +
            - spec/support/monkey_patches.rb
         
     | 
| 
       437 
460 
     | 
    
         
             
            homepage: 
         
     | 
| 
       438 
461 
     | 
    
         
             
            licenses: []
         
     | 
| 
       439 
462 
     | 
    
         
             
            metadata: {}
         
     | 
| 
         @@ -477,6 +500,7 @@ test_files: 
     | 
|
| 
       477 
500 
     | 
    
         
             
            - spec/fixtures/items_2.1/adaptive_template.xml
         
     | 
| 
       478 
501 
     | 
    
         
             
            - spec/fixtures/items_2.1/associate.xml
         
     | 
| 
       479 
502 
     | 
    
         
             
            - spec/fixtures/items_2.1/audio-video.xml
         
     | 
| 
      
 503 
     | 
    
         
            +
            - spec/fixtures/items_2.1/categorization.xml
         
     | 
| 
       480 
504 
     | 
    
         
             
            - spec/fixtures/items_2.1/choice.xml
         
     | 
| 
       481 
505 
     | 
    
         
             
            - spec/fixtures/items_2.1/choice_aria.xml
         
     | 
| 
       482 
506 
     | 
    
         
             
            - spec/fixtures/items_2.1/choice_fixed.xml
         
     | 
| 
         @@ -534,6 +558,7 @@ test_files: 
     | 
|
| 
       534 
558 
     | 
    
         
             
            - spec/fixtures/items_2.1/inline_choice_math.xml
         
     | 
| 
       535 
559 
     | 
    
         
             
            - spec/fixtures/items_2.1/likert.xml
         
     | 
| 
       536 
560 
     | 
    
         
             
            - spec/fixtures/items_2.1/match.xml
         
     | 
| 
      
 561 
     | 
    
         
            +
            - spec/fixtures/items_2.1/match2.xml
         
     | 
| 
       537 
562 
     | 
    
         
             
            - spec/fixtures/items_2.1/math.xml
         
     | 
| 
       538 
563 
     | 
    
         
             
            - spec/fixtures/items_2.1/mc_calc3.xml
         
     | 
| 
       539 
564 
     | 
    
         
             
            - spec/fixtures/items_2.1/mc_calc5.xml
         
     | 
| 
         @@ -652,11 +677,14 @@ test_files: 
     | 
|
| 
       652 
677 
     | 
    
         
             
            - spec/lib/qti/v1/models/choices/logical_identifier_choice_spec.rb
         
     | 
| 
       653 
678 
     | 
    
         
             
            - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
         
     | 
| 
       654 
679 
     | 
    
         
             
            - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
         
     | 
| 
      
 680 
     | 
    
         
            +
            - spec/lib/qti/v1/models/interactions/match_interaction_spec.rb
         
     | 
| 
       655 
681 
     | 
    
         
             
            - spec/lib/qti/v1/models/interactions/string_interaction_spec.rb
         
     | 
| 
       656 
682 
     | 
    
         
             
            - spec/lib/qti/v2/models/assessment_item_spec.rb
         
     | 
| 
       657 
683 
     | 
    
         
             
            - spec/lib/qti/v2/models/assessment_test_spec.rb
         
     | 
| 
       658 
684 
     | 
    
         
             
            - spec/lib/qti/v2/models/choices/gap_match_choice_spec.rb
         
     | 
| 
      
 685 
     | 
    
         
            +
            - spec/lib/qti/v2/models/choices/simple_associable_choice_spec.rb
         
     | 
| 
       659 
686 
     | 
    
         
             
            - spec/lib/qti/v2/models/choices/simple_choice_spec.rb
         
     | 
| 
      
 687 
     | 
    
         
            +
            - spec/lib/qti/v2/models/interactions/categorization_interaction_spec.rb
         
     | 
| 
       660 
688 
     | 
    
         
             
            - spec/lib/qti/v2/models/interactions/choice_interaction_spec.rb
         
     | 
| 
       661 
689 
     | 
    
         
             
            - spec/lib/qti/v2/models/interactions/extended_text_interaction_spec.rb
         
     | 
| 
       662 
690 
     | 
    
         
             
            - spec/lib/qti/v2/models/interactions/gap_match_interaction_spec.rb
         
     | 
| 
         @@ -664,3 +692,4 @@ test_files: 
     | 
|
| 
       664 
692 
     | 
    
         
             
            - spec/lib/qti_spec.rb
         
     | 
| 
       665 
693 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
       666 
694 
     | 
    
         
             
            - spec/support/custom_matchers.rb
         
     | 
| 
      
 695 
     | 
    
         
            +
            - spec/support/monkey_patches.rb
         
     |