lib/gitsu/user_list.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Gitsu
# Copyright (C) 2013 drrb
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

module GitSu
    class UserList
        MATCH_STRATEGIES = [
            # Whole word of name
            lambda { |search_term, user| user.name =~ /\b#{search_term}\b/i },

            # Beginning of word in name
            lambda { |search_term, user| user.name =~ /\b#{search_term}/i },

            # Initials
            lambda { |search_term, user| user.initials =~ /#{search_term}/i },

            # Segment anywhere in name or email
            lambda do |search_term, user|
                "#{user.name} #{user.email}" =~ /#{search_term}/i
            end
        ]

        def initialize(user_file)
            @user_file = user_file
        end

        def add(user)
            @user_file.write(user)
        end

        def list
            @user_file.read
        end

        def find(*search_terms)
            all_users = list
            searches = all_matching_users(all_users, search_terms)
            searches.each do |search|
                if search.matches.empty?
                    raise "No user found matching '#{search.term}'"
                end
            end

            find_unique_combination(searches) or raise "Couldn't find a combination of users matching #{search_terms.quote.to_sentence}"
        end

        private
        class Search
            attr_accessor :term, :matches
            def initialize(term)
                @term, @matches = term, []
            end
        end

        def all_matching_users(all_users, search_terms)
            searches = search_terms.map {|search_term| Search.new(search_term)}
            searches.each do |search|
                MATCH_STRATEGIES.each do |strategy|
                    search.matches += all_users.select { |user| strategy.call(search.term, user) }
                end
                search.matches.uniq!
            end
        end

        def find_unique_combination(searches)
            searches = searches.clone
            # Generate all combinations
            combinations = [[]]
            searches.each do |search|
                previous_combos = combinations.clone
                combinations = []
                previous_combos.each do |combo|
                    search.matches.each do |match|
                        combo_extension = combo.clone
                        combo_extension << match
                        combinations << combo_extension
                    end
                end
            end
            combinations.find do |combo|
                combo.uniq.size == combo.size
            end
        end
    end
end