module JamRuby class BandSearch < BaseSearch cattr_accessor :jschema, :search_meta attr_accessor :user_counters KEY_BAND_SEARCH_TYPE = 'band_search_type' KEY_BAND_TYPE = 'band_type' KEY_PLAY_COMMIT = 'play_commit' KEY_TOUR_OPTION = 'tour_option' KEY_PERF_SAMPLES = 'perform_samples' KEY_HIRE_MAX_COST = 'max_cost' KEY_HIRE_FREE = 'free_gigs' BAND_SEARCH_TYPE_VALS = %W{ to_join to_hire } BAND_SEARCH_TYPES = { BAND_SEARCH_TYPE_VALS[0] => 'search bands', BAND_SEARCH_TYPE_VALS[1] => 'search bands to hire', } SORT_VALS = %W{ distance latency } SORT_ORDERS = { SORT_VALS[0] => 'Distance to Me', SORT_VALS[1] => 'Latency to Me', } HIRE_SORT_VALS = %W{ distance price_asc price_desc } HIRE_SORT_ORDERS = { HIRE_SORT_VALS[0] => 'Distance to Me', HIRE_SORT_VALS[1] => 'Gig Minimum Price (Low to High)', HIRE_SORT_VALS[2] => 'Gig Minimum Price (High to Low)', } BAND_TYPE_VALS = [ANY_VAL_STR, GenrePlayer::VIRTUAL_BAND, GenrePlayer::TRADITIONAL_BAND, ] BAND_TYPES = { BAND_TYPE_VALS[0] => 'Any', BAND_TYPE_VALS[1] => 'Virtual Band', BAND_TYPE_VALS[2] => 'Traditional Band', } PLAY_COMMIT_VALS = [ANY_VAL_STR, '0', '1', '2', ] PLAY_COMMITS = { PLAY_COMMIT_VALS[0] => 'Any', PLAY_COMMIT_VALS[1] => 'Infrequent', PLAY_COMMIT_VALS[2] => 'Once a week', PLAY_COMMIT_VALS[3] => 'More than once a week', } TOUR_OPTION_VALS = [ANY_VAL_STR, 'yes', 'no', ] TOUR_OPTIONS = { TOUR_OPTION_VALS[0] => 'Any', TOUR_OPTION_VALS[1] => 'Yes', TOUR_OPTION_VALS[2] => 'No', } PERF_SAMPLES_VALS = TOUR_OPTION_VALS.clone PERF_SAMPLES = TOUR_OPTIONS.clone def self.json_schema return @@jschema if @@jschema @@jschema = { BAND_SEARCH_TYPE_VALS[0] => BaseSearch.json_schema.merge({ KEY_BAND_TYPE => BAND_TYPE_VALS[0], KEY_PLAY_COMMIT => PLAY_COMMIT_VALS[0], KEY_TOUR_OPTION => TOUR_OPTION_VALS[0], }), BAND_SEARCH_TYPE_VALS[1] => { KEY_SORT_ORDER => self::HIRE_SORT_VALS[0], KEY_GENRES => [], KEY_SKILL => self::SKILL_VALS[0].to_s, KEY_GIGS => self::GIG_COUNTS[0].to_s, KEY_PERF_SAMPLES => self::PERF_SAMPLES[0].to_s, KEY_HIRE_MAX_COST => 0, KEY_HIRE_FREE => 0, }, } end def self.search_filter_meta return @@search_meta if @@search_meta toJoinMeta = super(self.json_schema[BAND_SEARCH_TYPE_VALS[0]]) toJoinMeta.merge!({ KEY_BAND_TYPE => { keys: BAND_TYPE_VALS, map: BAND_TYPES }, KEY_PLAY_COMMIT => { keys: PLAY_COMMIT_VALS, map: PLAY_COMMITS }, KEY_TOUR_OPTION => { keys: TOUR_OPTION_VALS, map: TOUR_OPTIONS } }) @@search_meta = { BAND_SEARCH_TYPE_VALS[0] => toJoinMeta, BAND_SEARCH_TYPE_VALS[1] => super(self.json_schema[BAND_SEARCH_TYPE_VALS[1]], { keys: HIRE_SORT_VALS, map: HIRE_SORT_ORDERS }), } end def self.search_target_class User end def do_search(params={}) rel = User.musicians.where('users.id <> ?', self.user.id) rel = self._sort_order(rel) rel end def search_includes(rel) rel.includes([:instruments, :followings, :friends]) end def process_results_page(_results) @results = _results if user @user_counters = @results.inject({}) { |hh,val| hh[val.id] = []; hh } mids = "'#{@results.map(&:id).join("','")}'" # this gets counts for each search result @results.each do |bb| counters = { } counters[COUNT_FOLLOW] = Follow.where(:followable_id => bb.id).count counters[COUNT_RECORD] = Recording.where(:band_id => bb.id).count counters[COUNT_SESSION] = MusicSession.where(:band_id => bb.id).count @user_counters[bb.id] << counters end # this section determines follow/like/friend status for each search result # so that action links can be activated or not rel = Band.select("bands.id AS bid") rel = rel.joins("LEFT JOIN follows ON follows.user_id = '#{user.id}'") rel = rel.where(["bands.id IN (#{mids}) AND follows.followable_id = bands.id"]) rel.all.each { |val| @user_counters[val.bid] << RESULT_FOLLOW } else @user_counters = {} end self end private def _count(musician, key) if mm = @user_counters[musician.id] return mm.detect { |ii| ii.is_a?(Hash) }[key] end if @user_counters 0 end public def follow_count(musician) _count(musician, COUNT_FOLLOW) end def friend_count(musician) _count(musician, COUNT_FRIEND) end def record_count(musician) _count(musician, COUNT_RECORD) end def session_count(musician) _count(musician, COUNT_SESSION) end def is_friend?(musician) if mm = @user_counters[musician.id] return mm.include?(RESULT_FRIEND) end if @user_counters false end def is_follower?(musician) if mm = @user_counters[musician.id] return mm.include?(RESULT_FOLLOW) end if @user_counters false end def search_type self.class.to_s end def is_blank? self.data_blob == self.class.json_schema end def description if self.is_blank? return 'Click search button to look for musicians with similar interests, skill levels, etc.' end jj = self.json str = 'Current Search: ' str += "Sort = #{SORT_ORDERS[json_value(BandSearch::KEY_SORT_ORDER)]}" str end def reset_filter(subtype, data=nil) data ||= self.class.json_schema[subtype] dblob = self.data_blob dblob[subtype] = data self.data_blob = dblob self.save end def reset_search_results(subtype=BAND_SEARCH_TYPE_VALS[0]) reset_filter(subtype) search_results_page(subtype) end def self.search_filter_json(user, subtype=BAND_SEARCH_TYPE_VALS[0]) self.user_search_filter(user).json[subtype] end def search_results_page(subtype=BAND_SEARCH_TYPE_VALS[0], filter=nil, page=1) if filter reset_filter(subtype, filter) else filter = self.data_blob[subtype] end rel = do_search(filter) @page_number = [page.to_i, 1].max rel = rel.paginate(:page => @page_number, :per_page => self.class::PER_PAGE) rel = self.search_includes(rel) @page_count = rel.total_pages process_results_page(rel.all) end end end