2015-05-07 14:41:27 +00:00
|
|
|
module JamRuby
|
2015-05-07 17:11:24 +00:00
|
|
|
class BandSearch < BaseSearch
|
2015-05-07 14:41:27 +00:00
|
|
|
|
2015-05-18 04:00:12 +00:00
|
|
|
cattr_accessor :jschema, :search_meta
|
2015-05-07 14:41:27 +00:00
|
|
|
attr_accessor :user_counters
|
|
|
|
|
|
2015-05-26 08:43:11 +00:00
|
|
|
serialize :data_blob, JSON
|
|
|
|
|
|
2015-05-07 14:41:27 +00:00
|
|
|
KEY_BAND_SEARCH_TYPE = 'band_search_type'
|
2015-05-27 04:10:05 +00:00
|
|
|
KEY_BAND_STATUS = 'band_status'
|
2015-05-27 02:58:04 +00:00
|
|
|
KEY_PLAY_COMMIT = 'play_commitment'
|
2015-05-27 04:10:05 +00:00
|
|
|
KEY_TOUR_OPTION = 'touring_option'
|
2015-05-27 05:08:56 +00:00
|
|
|
KEY_PERF_SAMPLES = 'performance_samples'
|
2015-05-18 04:00:12 +00:00
|
|
|
KEY_HIRE_MAX_COST = 'max_cost'
|
|
|
|
|
KEY_HIRE_FREE = 'free_gigs'
|
2015-05-07 14:41:27 +00:00
|
|
|
|
2015-05-26 08:43:11 +00:00
|
|
|
TO_JOIN = 'to_join'
|
|
|
|
|
TO_HIRE = 'to_hire'
|
|
|
|
|
|
|
|
|
|
BAND_SEARCH_TYPE_VALS = [TO_JOIN, TO_HIRE]
|
2015-05-07 14:41:27 +00:00
|
|
|
BAND_SEARCH_TYPES = {
|
2015-05-26 08:43:11 +00:00
|
|
|
TO_JOIN => 'search bands',
|
|
|
|
|
TO_HIRE => 'search bands to hire',
|
2015-05-07 14:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
2015-05-27 04:10:05 +00:00
|
|
|
SKILL_VAL_STRS = [ANY_VAL_STR, 'amateur', 'professional']
|
|
|
|
|
|
2015-05-07 14:41:27 +00:00
|
|
|
SORT_VALS = %W{ distance latency }
|
|
|
|
|
SORT_ORDERS = {
|
2015-05-07 17:11:24 +00:00
|
|
|
SORT_VALS[0] => 'Distance to Me',
|
2015-05-07 14:41:27 +00:00
|
|
|
SORT_VALS[1] => 'Latency to Me',
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-18 04:00:12 +00:00
|
|
|
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)',
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-27 04:10:05 +00:00
|
|
|
BAND_STATUS_VALS = [ANY_VAL_STR,
|
2015-05-07 14:41:27 +00:00
|
|
|
GenrePlayer::VIRTUAL_BAND,
|
|
|
|
|
GenrePlayer::TRADITIONAL_BAND,
|
|
|
|
|
]
|
2015-05-27 04:10:05 +00:00
|
|
|
BAND_STATUSS = {
|
|
|
|
|
BAND_STATUS_VALS[0] => 'Any',
|
|
|
|
|
BAND_STATUS_VALS[1] => 'Virtual Band',
|
|
|
|
|
BAND_STATUS_VALS[2] => 'Traditional Band',
|
2015-05-07 14:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PLAY_COMMIT_VALS = [ANY_VAL_STR,
|
|
|
|
|
'1',
|
|
|
|
|
'2',
|
2015-05-26 06:39:43 +00:00
|
|
|
'3',
|
2015-05-27 02:58:04 +00:00
|
|
|
'4',
|
2015-05-07 14:41:27 +00:00
|
|
|
]
|
|
|
|
|
PLAY_COMMITS = {
|
|
|
|
|
PLAY_COMMIT_VALS[0] => 'Any',
|
|
|
|
|
PLAY_COMMIT_VALS[1] => 'Infrequent',
|
2015-05-27 02:58:04 +00:00
|
|
|
PLAY_COMMIT_VALS[2] => 'Once a Week',
|
|
|
|
|
PLAY_COMMIT_VALS[3] => '2-3 Times Per Week',
|
|
|
|
|
PLAY_COMMIT_VALS[4] => '4+ Times Per Week',
|
2015-05-07 14:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TOUR_OPTION_VALS = [ANY_VAL_STR,
|
2015-05-27 02:58:04 +00:00
|
|
|
VAL_YES,
|
|
|
|
|
VAL_NO,
|
2015-05-07 14:41:27 +00:00
|
|
|
]
|
|
|
|
|
TOUR_OPTIONS = {
|
|
|
|
|
TOUR_OPTION_VALS[0] => 'Any',
|
2015-05-27 02:58:04 +00:00
|
|
|
TOUR_OPTION_VALS[1] => VAL_YES,
|
|
|
|
|
TOUR_OPTION_VALS[2] => VAL_NO,
|
2015-05-07 14:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
2015-05-18 04:00:12 +00:00
|
|
|
PERF_SAMPLES_VALS = TOUR_OPTION_VALS.clone
|
|
|
|
|
PERF_SAMPLES = TOUR_OPTIONS.clone
|
|
|
|
|
|
|
|
|
|
def self.json_schema
|
|
|
|
|
return @@jschema if @@jschema
|
|
|
|
|
@@jschema = {
|
2015-05-26 08:43:11 +00:00
|
|
|
TO_JOIN => BaseSearch.json_schema.merge({
|
2015-05-27 04:10:05 +00:00
|
|
|
KEY_SKILL => self::SKILL_VAL_STRS[0].to_s,
|
|
|
|
|
KEY_BAND_STATUS => BAND_STATUS_VALS[0],
|
2015-05-18 04:00:12 +00:00
|
|
|
KEY_PLAY_COMMIT => PLAY_COMMIT_VALS[0],
|
|
|
|
|
KEY_TOUR_OPTION => TOUR_OPTION_VALS[0],
|
|
|
|
|
}),
|
2015-05-26 08:43:11 +00:00
|
|
|
TO_HIRE => {
|
2015-05-18 04:00:12 +00:00
|
|
|
KEY_SORT_ORDER => self::HIRE_SORT_VALS[0],
|
|
|
|
|
KEY_GENRES => [],
|
2015-05-27 04:10:05 +00:00
|
|
|
KEY_SKILL => self::SKILL_VAL_STRS[0].to_s,
|
2015-05-18 04:00:12 +00:00
|
|
|
KEY_GIGS => self::GIG_COUNTS[0].to_s,
|
|
|
|
|
KEY_PERF_SAMPLES => self::PERF_SAMPLES[0].to_s,
|
|
|
|
|
KEY_HIRE_MAX_COST => 0,
|
2015-05-21 05:47:14 +00:00
|
|
|
KEY_HIRE_FREE => 1,
|
2015-05-18 04:00:12 +00:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
end
|
2015-05-07 14:41:27 +00:00
|
|
|
|
2015-05-18 04:00:12 +00:00
|
|
|
def self.search_filter_meta
|
|
|
|
|
return @@search_meta if @@search_meta
|
2015-05-26 08:43:11 +00:00
|
|
|
toJoinMeta = super(self.json_schema[TO_JOIN])
|
2015-05-19 05:48:29 +00:00
|
|
|
toJoinMeta.merge!({
|
2015-05-27 04:10:05 +00:00
|
|
|
KEY_BAND_STATUS => { keys: BAND_STATUS_VALS, map: BAND_STATUSS },
|
2015-05-19 05:48:29 +00:00
|
|
|
KEY_PLAY_COMMIT => { keys: PLAY_COMMIT_VALS, map: PLAY_COMMITS },
|
|
|
|
|
KEY_TOUR_OPTION => { keys: TOUR_OPTION_VALS, map: TOUR_OPTIONS }
|
|
|
|
|
})
|
2015-05-26 08:43:11 +00:00
|
|
|
toHireMeta = super(self.json_schema[TO_HIRE],
|
2015-05-20 09:24:53 +00:00
|
|
|
{ keys: HIRE_SORT_VALS, map: HIRE_SORT_ORDERS })
|
2015-05-21 05:47:14 +00:00
|
|
|
toHireMeta.merge!({
|
|
|
|
|
KEY_PERF_SAMPLES => { keys: PERF_SAMPLES_VALS, map: PERF_SAMPLES },
|
|
|
|
|
})
|
2015-05-18 04:00:12 +00:00
|
|
|
@@search_meta = {
|
2015-05-26 08:43:11 +00:00
|
|
|
TO_JOIN => toJoinMeta,
|
|
|
|
|
TO_HIRE => toHireMeta,
|
2015-05-18 04:00:12 +00:00
|
|
|
}
|
|
|
|
|
end
|
2015-05-07 14:41:27 +00:00
|
|
|
|
|
|
|
|
def self.search_target_class
|
2015-05-22 12:09:14 +00:00
|
|
|
Band
|
2015-05-07 14:41:27 +00:00
|
|
|
end
|
|
|
|
|
|
2015-05-22 12:09:14 +00:00
|
|
|
def _sort_order(rel, filter)
|
|
|
|
|
rel
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def _genres(rel, filter)
|
|
|
|
|
super(rel, filter)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def _concert_gigs(rel, filter)
|
2015-05-26 06:39:43 +00:00
|
|
|
gg = filter[KEY_GIGS].to_i
|
|
|
|
|
rel = rel.where(concert_count: gg) if 0 <= gg
|
2015-05-22 12:09:14 +00:00
|
|
|
rel
|
|
|
|
|
end
|
|
|
|
|
|
2015-05-27 04:10:05 +00:00
|
|
|
def _band_status(rel, filter)
|
|
|
|
|
case filter[KEY_BAND_STATUS]
|
2015-05-26 06:39:43 +00:00
|
|
|
when GenrePlayer::VIRTUAL_BAND
|
2015-05-27 04:10:05 +00:00
|
|
|
rel.where(band_status: GenrePlayer::VIRTUAL_BAND.sub('_band',''))
|
2015-05-26 06:39:43 +00:00
|
|
|
when GenrePlayer::TRADITIONAL_BAND
|
2015-05-27 04:10:05 +00:00
|
|
|
rel.where(band_status: GenrePlayer::TRADITIONAL_BAND.sub('_band',''))
|
2015-05-26 06:39:43 +00:00
|
|
|
else
|
|
|
|
|
rel
|
2015-05-22 12:09:14 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-05-27 02:58:04 +00:00
|
|
|
def _play_commitment(rel, filter)
|
2015-05-26 06:39:43 +00:00
|
|
|
unless ANY_VAL_STR == filter[KEY_PLAY_COMMIT]
|
|
|
|
|
rel = rel.where(play_commitment: filter[KEY_PLAY_COMMIT].to_i)
|
|
|
|
|
end
|
2015-05-22 12:09:14 +00:00
|
|
|
rel
|
|
|
|
|
end
|
|
|
|
|
|
2015-05-27 04:10:05 +00:00
|
|
|
def _touring_option(rel, filter)
|
2015-05-22 12:09:14 +00:00
|
|
|
case filter[KEY_TOUR_OPTION]
|
2015-05-27 02:58:04 +00:00
|
|
|
when VAL_YES
|
2015-05-26 06:39:43 +00:00
|
|
|
rel.where(touring_option: true)
|
2015-05-27 02:58:04 +00:00
|
|
|
when VAL_NO
|
2015-05-26 06:39:43 +00:00
|
|
|
rel.where(touring_option: false)
|
|
|
|
|
else
|
|
|
|
|
rel
|
2015-05-22 12:09:14 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-05-27 05:08:56 +00:00
|
|
|
def _performance_samples(rel, filter)
|
|
|
|
|
case filter[KEY_PERF_SAMPLES]
|
|
|
|
|
when VAL_YES
|
|
|
|
|
rel.joins("LEFT OUTER JOIN performance_samples AS ps ON ps.player_id = bands.id AND player_type = '#{self.class.name}'").where(["ps.id IS NOT NULL"])
|
|
|
|
|
when VAL_NO
|
|
|
|
|
rel.joins("LEFT OUTER JOIN performance_samples AS ps ON ps.player_id = bands.id AND player_type = '#{self.class.name}'").where(["ps.id IS NULL"])
|
|
|
|
|
else
|
|
|
|
|
rel
|
|
|
|
|
end
|
2015-05-22 12:09:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def _max_cost(rel, filter)
|
2015-05-26 06:39:43 +00:00
|
|
|
if 0 < (max_cost = filter[KEY_HIRE_MAX_COST].to_i)
|
|
|
|
|
col = Band.arel_table[:gig_minimum]
|
2015-05-27 02:58:04 +00:00
|
|
|
rel = rel.where(col.lteq(max_cost)).where(col.gt(0))
|
2015-05-26 06:39:43 +00:00
|
|
|
end
|
2015-05-22 12:09:14 +00:00
|
|
|
rel
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def _free_gigs(rel, filter)
|
2015-05-27 02:58:04 +00:00
|
|
|
case filter[KEY_HIRE_FREE]
|
|
|
|
|
when VAL_YES
|
2015-05-26 06:39:43 +00:00
|
|
|
rel.where(free_gigs: true)
|
2015-05-27 02:58:04 +00:00
|
|
|
when VAL_NO
|
2015-05-26 06:39:43 +00:00
|
|
|
rel.where(free_gigs: false)
|
|
|
|
|
else
|
|
|
|
|
rel
|
2015-05-22 12:09:14 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def _skill_level(rel, filter)
|
2015-05-27 04:10:05 +00:00
|
|
|
case filter[KEY_SKILL]
|
|
|
|
|
when SKILL_VAL_STRS[1]
|
|
|
|
|
rel.where(band_type: SKILL_VAL_STRS[1])
|
|
|
|
|
when SKILL_VAL_STRS[2]
|
|
|
|
|
rel.where(band_type: SKILL_VAL_STRS[2])
|
2015-05-26 06:39:43 +00:00
|
|
|
else
|
|
|
|
|
rel
|
|
|
|
|
end
|
2015-05-22 12:09:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def do_search(filter)
|
|
|
|
|
rel = Band.unscoped
|
|
|
|
|
filter.keys.each do |fkey|
|
|
|
|
|
mname = "_#{fkey}"
|
2015-05-26 08:43:11 +00:00
|
|
|
if self.respond_to?(mname)
|
2015-05-22 12:09:14 +00:00
|
|
|
rel = self.send(mname.to_sym, rel, filter)
|
|
|
|
|
end
|
|
|
|
|
end
|
2015-05-07 14:41:27 +00:00
|
|
|
rel
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def search_includes(rel)
|
2015-05-26 08:43:11 +00:00
|
|
|
rel.includes([:instruments])
|
2015-05-07 14:41:27 +00:00
|
|
|
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 = { }
|
|
|
|
|
@user_counters[bb.id] << counters
|
|
|
|
|
end
|
|
|
|
|
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?
|
2015-05-18 04:00:12 +00:00
|
|
|
self.data_blob == self.class.json_schema
|
2015-05-07 14:41:27 +00:00
|
|
|
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
|
|
|
|
|
|
2015-05-18 04:00:12 +00:00
|
|
|
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
|
|
|
|
|
|
2015-05-26 08:43:11 +00:00
|
|
|
def reset_search_results(subtype=TO_JOIN)
|
2015-05-18 04:00:12 +00:00
|
|
|
reset_filter(subtype)
|
|
|
|
|
search_results_page(subtype)
|
|
|
|
|
end
|
|
|
|
|
|
2015-05-26 08:43:11 +00:00
|
|
|
def self.search_filter_json(user, subtype=TO_JOIN)
|
2015-05-18 04:00:12 +00:00
|
|
|
self.user_search_filter(user).json[subtype]
|
|
|
|
|
end
|
|
|
|
|
|
2015-05-26 08:43:11 +00:00
|
|
|
def search_filter_for_subtype(subtype)
|
|
|
|
|
self.data_blob[subtype]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def search_results_page(subtype=TO_JOIN, filter=nil, page=1)
|
2015-05-18 04:00:12 +00:00
|
|
|
if filter
|
|
|
|
|
reset_filter(subtype, filter)
|
|
|
|
|
else
|
2015-05-26 08:43:11 +00:00
|
|
|
filter = self.search_filter_for_subtype(subtype)
|
2015-05-18 04:00:12 +00:00
|
|
|
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
|
|
|
|
|
|
2015-05-07 14:41:27 +00:00
|
|
|
end
|
|
|
|
|
end
|