<commit_before>module SearchResults

  class ResultMapperBuilder

    attr_reader :result
    attr_accessor :strategy

    def initialize(result_adapter)
      @result = result_adapter
    end

    def to_flatten_results
      @flatten_results ||= strategy_mapper_class.new(remove_type_from_result).to_flatten_results
    end

    private

    def remove_type_from_result
      @result.select {|k,v| !/type/.match(k.to_s)}
    end

    def strategy_mapper
      @strategy ||= @result["type"] || "default"
    end

    def strategy_mapper_class
      "SearchResults::ResultMapper#{strategy_mapper.to_s.camelize}".constantize
    end

    def self.strategy_builder(result_type)
      result_type || :default
    end

    def self.strategy_class_builder(result_type)
      "SearchResults::#{strategy_builder(result_type).to_s.camelize}GroupsBuilder".constantize
    end

    def self.build_result_groups(result_adapter)
      strategy_class_builder(result_adapter.type).new(result_adapter).build_result_groups
    end

  end

  class GroupsBuilder

    attr_reader :result

    def initialize(result)
      @result = result
    end

    def parent_ids
      @result.parent
    end

    def child_ids
      @result.child
    end

    def columns
      @result.columns
    end

    def empty_result
      {}
    end

    def is_parent?(depth)
      depth == Depth::PARENT
    end

    def klass
      /Default|Cross/.match(self.class.name)[0].constantize
    end

    def vals_by_property_id(vals)
      vals.group_by { |v| v.property_id }
    end

  end

  class CompareGroupsBuilder < GroupsBuilder
    def build_result_groups
      vals = LingsProperty.with_id(vals_ids_for_compare)
      vals_by_prop_ids = vals_by_property_id(vals)

      {}.tap do |groups|
        vals_by_prop_ids.keys.each do |prop_id|
          props = vals_by_prop_ids[prop_id]
          groups[props.first.id] = compare_property_value props
        end
        groups["type"]="compare"
      end
    end

    private

    def depth_for_compare
      @result.depth_for_compare
    end

    def vals_ids_for_compare
      is_parent?(depth_for_compare) ? parent_ids : child_ids
    end

    def compare_property_value(vals)
      prop_values = vals.map(&:property_value).uniq

      prop_values.count == 1 ? vals.first.map(&:id) : vals.map(&:id)
    end
  end

  class CrossGroupsBuilder < GroupsBuilder
    def build_result_groups

      vals = LingsProperty.with_id(vals_ids_for_cross)
      vals_by_prop_ids = vals_by_property_id(vals)

      prop_values = [].tap do |p|
        vals_by_prop_ids.keys.each do |prop_id|
          p << vals_by_prop_ids[prop_id].map(&:property_value).uniq
        end
      end

      first_prop = prop_values.first<commit_msg>Fixed a bug on CompareGroupsBuilder when common values<commit_after>module SearchResults

  class ResultMapperBuilder

    attr_reader :result
    attr_accessor :strategy

    def initialize(result_adapter)
      @result = result_adapter
    end

    def to_flatten_results
      @flatten_results ||= strategy_mapper_class.new(remove_type_from_result).to_flatten_results
    end

    private

    def remove_type_from_result
      @result.select {|k,v| !/type/.match(k.to_s)}
    end

    def strategy_mapper
      @strategy ||= @result["type"] || "default"
    end

    def strategy_mapper_class
      "SearchResults::ResultMapper#{strategy_mapper.to_s.camelize}".constantize
    end

    def self.strategy_builder(result_type)
      result_type || :default
    end

    def self.strategy_class_builder(result_type)
      "SearchResults::#{strategy_builder(result_type).to_s.camelize}GroupsBuilder".constantize
    end

    def self.build_result_groups(result_adapter)
      strategy_class_builder(result_adapter.type).new(result_adapter).build_result_groups
    end

  end

  class GroupsBuilder

    attr_reader :result

    def initialize(result)
      @result = result
    end

    def parent_ids
      @result.parent
    end

    def child_ids
      @result.child
    end

    def columns
      @result.columns
    end

    def empty_result
      {}
    end

    def is_parent?(depth)
      depth == Depth::PARENT
    end

    def klass
      /Default|Cross/.match(self.class.name)[0].constantize
    end

    def vals_by_property_id(vals)
      vals.group_by { |v| v.property_id }
    end

  end

  class CompareGroupsBuilder < GroupsBuilder
    def build_result_groups
      vals = LingsProperty.with_id(vals_ids_for_compare)
      vals_by_prop_ids = vals_by_property_id(vals)

      {}.tap do |groups|
        vals_by_prop_ids.keys.each do |prop_id|
          props = vals_by_prop_ids[prop_id]
          groups[props.first.id] = compare_property_value props
        end
        groups["type"]="compare"
      end
    end

    private

    def depth_for_compare
      @result.depth_for_compare
    end

    def vals_ids_for_compare
      is_parent?(depth_for_compare) ? parent_ids : child_ids
    end

    def compare_property_value(vals)
      prop_values = vals.map(&:property_value).uniq

      prop_values.count == 1 ? [vals.map(&:id).first] : vals.map(&:id)
    end
  end

  class CrossGroupsBuilder < GroupsBuilder
    def build_result_groups

      vals = LingsProperty.with_id(vals_ids_for_cross)
      vals_by_prop_ids = vals_by_property_id(vals)

      prop_values = [].tap do |p|
        vals_by_prop_ids.keys.each do |prop_id|
          p << vals_by_prop_ids[prop_id].map(&:property_value).uniq
        end
      end

      first_prop = prop_values.first
{'fraction_non_alphanumeric': 0.07956403269754768, 'fraction_numerical': 0.0007266121707538601, 'mean_word_length': 2.866573033707865, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6433371', 'n_tokens_mistral': 1869, 'n_tokens_neox': 1781, 'n_words': 318}