jam-cloud/ruby/lib/jam_ruby/models/band_search.rb

242 lines
6.9 KiB
Ruby

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[1] => '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