302 lines
9.3 KiB
Ruby
302 lines
9.3 KiB
Ruby
module JamRuby
|
|
class MusicianSearch < BaseSearch
|
|
|
|
cattr_accessor :jschema, :search_meta
|
|
attr_accessor :user_counters
|
|
|
|
KEY_STUDIOS = 'studio_sessions'
|
|
KEY_AGES = 'ages'
|
|
KEY_INTERESTS = 'interests'
|
|
|
|
SORT_VALS = %W{ latency distance }
|
|
SORT_ORDERS = {
|
|
SORT_VALS[0] => 'Latency to Me',
|
|
SORT_VALS[1] => 'Distance to Me'
|
|
}
|
|
|
|
STUDIO_COUNTS = [ANY_VAL_INT, 0, 1, 2, 3, 4]
|
|
STUDIOS_LABELS = {
|
|
STUDIO_COUNTS[0] => 'Any',
|
|
STUDIO_COUNTS[1] => 'under 10',
|
|
STUDIO_COUNTS[2] => '10 to 50',
|
|
STUDIO_COUNTS[3] => '50 to 100',
|
|
STUDIO_COUNTS[4] => 'over 100'
|
|
}
|
|
|
|
AGE_COUNTS = [10, 20, 30, 40, 50]
|
|
AGES = {
|
|
AGE_COUNTS[0] => 'Teens',
|
|
AGE_COUNTS[1] => "20's",
|
|
AGE_COUNTS[2] => "30's",
|
|
AGE_COUNTS[3] => "40's",
|
|
AGE_COUNTS[4] => "50+"
|
|
}
|
|
|
|
INTEREST_VALS = [ANY_VAL_STR,
|
|
GenrePlayer::VIRTUAL_BAND,
|
|
GenrePlayer::TRADITIONAL_BAND,
|
|
GenrePlayer::PAID_SESSION,
|
|
GenrePlayer::FREE_SESSION,
|
|
GenrePlayer::COWRITING,
|
|
]
|
|
INTERESTS = {
|
|
INTEREST_VALS[0] => 'Any',
|
|
INTEREST_VALS[1] => 'Virtual Band',
|
|
INTEREST_VALS[2] => 'Traditional Band',
|
|
INTEREST_VALS[3] => 'Paid Sessions',
|
|
INTEREST_VALS[4] => 'Free Sessions',
|
|
INTEREST_VALS[5] => 'Co-Writing'
|
|
}
|
|
|
|
def self.json_schema
|
|
return @@jschema if @@jschema
|
|
@@jschema = BaseSearch.json_schema.merge({
|
|
KEY_INTERESTS => INTEREST_VALS[0],
|
|
KEY_STUDIOS => STUDIO_COUNTS[0].to_s,
|
|
KEY_AGES => [],
|
|
KEY_SKILL => self::SKILL_VALS[0].to_s,
|
|
})
|
|
end
|
|
|
|
def self.search_filter_meta
|
|
return @@search_meta if @@search_meta
|
|
@@search_meta = super.merge({
|
|
interests: { keys: INTEREST_VALS, map: INTERESTS },
|
|
ages: { keys: AGE_COUNTS, map: AGES }
|
|
})
|
|
end
|
|
|
|
def self.search_target_class
|
|
User
|
|
end
|
|
|
|
def _ages(rel)
|
|
unless (vals = json[KEY_AGES]).blank?
|
|
return rel if vals.detect { |vv| ANY_VAL_INT == vv }
|
|
arels = []
|
|
vals.each do |val|
|
|
today = Date.today
|
|
case val.to_i
|
|
when 10
|
|
arels << User.where("birth_date >= ? AND birth_date < ?",
|
|
today - 20.years, today - 10.years)
|
|
when 20
|
|
arels << User.where("birth_date >= ? AND birth_date < ?",
|
|
today - 30.years, today - 20.years)
|
|
when 30
|
|
arels << User.where("birth_date >= ? AND birth_date < ?",
|
|
today - 40.years, today - 50.years)
|
|
when 40
|
|
arels << User.where("birth_date >= ? AND birth_date < ?",
|
|
today - 50.years, today - 40.years)
|
|
when 50
|
|
arels << User.where("birth_date <= ?", today - 50.years)
|
|
end
|
|
end
|
|
rel = rel.where("birth_date IS NOT NULL")
|
|
sql = "(#{arels.map(&:where_values).flatten.join(') OR (')})"
|
|
rel = rel.where(sql)
|
|
end
|
|
rel
|
|
end
|
|
|
|
def _studios(rel)
|
|
ss = json[KEY_STUDIOS].to_i
|
|
rel = rel.where('studio_session_count = ?', ss) if 0 <= ss
|
|
rel
|
|
end
|
|
|
|
def _gigs(rel)
|
|
gg = json[KEY_GIGS].to_i
|
|
rel = rel.where('concert_count = ?',gg) if 0 <= gg
|
|
rel
|
|
end
|
|
|
|
def _skills(rel)
|
|
if 0 < (val = json[KEY_SKILL].to_i)
|
|
rel = rel.where(skill_level: val)
|
|
end
|
|
rel
|
|
end
|
|
|
|
def _interests(rel)
|
|
val = json[KEY_INTERESTS]
|
|
if val.present? && ANY_VAL_STR != val
|
|
rel = rel.where("#{val} = ?", true)
|
|
end
|
|
rel
|
|
end
|
|
|
|
def _sort_order(rel)
|
|
val = json[self.class::KEY_SORT_ORDER]
|
|
if self.class::SORT_VALS[1] == val
|
|
locidispid = self.user.last_jam_locidispid || 0
|
|
my_locid = locidispid / 1000000
|
|
rel = rel.joins("LEFT JOIN geoiplocations AS my_geo ON my_geo.locid = #{my_locid}")
|
|
rel = rel.joins("LEFT JOIN geoiplocations AS other_geo ON users.last_jam_locidispid/1000000 = other_geo.locid")
|
|
rel = rel.group("users.id, my_geo.geog, other_geo.geog")
|
|
rel = rel.order('st_distance(my_geo.geog, other_geo.geog)')
|
|
else
|
|
rel = rel.joins("LEFT JOIN current_scores ON current_scores.a_userid = users.id AND current_scores.b_userid = '#{self.user.id}'")
|
|
rel = rel.order('current_scores.full_score ASC')
|
|
end
|
|
rel
|
|
end
|
|
|
|
def do_search(params={})
|
|
rel = User.musicians.where('users.id <> ?', self.user.id)
|
|
rel = self._genres(rel)
|
|
rel = self._ages(rel)
|
|
rel = self._studios(rel)
|
|
rel = self._gigs(rel)
|
|
rel = self._skills(rel)
|
|
rel = self._instruments(rel)
|
|
rel = self._interests(rel)
|
|
rel = self._sort_order(rel)
|
|
rel
|
|
end
|
|
|
|
def search_includes(rel)
|
|
rel.includes([:instruments, :followings, :friends])
|
|
end
|
|
|
|
def process_results_page(_results)
|
|
@results = _results
|
|
@user_counters = {} and return self unless user
|
|
|
|
@user_counters = @results.inject({}) { |hh,val| hh[val.id] = []; hh }
|
|
mids = "'#{@results.map(&:id).join("','")}'"
|
|
|
|
# this gets counts for each search result on friends/follows/records/sessions
|
|
@results.each do |uu|
|
|
counters = { }
|
|
counters[COUNT_FRIEND] = Friendship.where(:user_id => uu.id).count
|
|
counters[COUNT_FOLLOW] = Follow.where(:followable_id => uu.id).count
|
|
counters[COUNT_RECORD] = ClaimedRecording.where(:user_id => uu.id).count
|
|
counters[COUNT_SESSION] = MusicSession.where(:user_id => uu.id).count
|
|
@user_counters[uu.id] << counters
|
|
end
|
|
|
|
# this section determines follow/like/friend status for each search result
|
|
# so that action links can be activated or not
|
|
rel = User.select("users.id AS uid")
|
|
rel = rel.joins("LEFT JOIN follows ON follows.user_id = '#{user.id}'")
|
|
rel = rel.where(["users.id IN (#{mids}) AND follows.followable_id = users.id"])
|
|
rel.all.each { |val| @user_counters[val.uid] << RESULT_FOLLOW }
|
|
|
|
rel = User.select("users.id AS uid")
|
|
rel = rel.joins("LEFT JOIN friendships AS friends ON friends.friend_id = '#{user.id}'")
|
|
rel = rel.where(["users.id IN (#{mids}) AND friends.user_id = users.id"])
|
|
rel.all.each { |val| @user_counters[val.uid] << RESULT_FRIEND }
|
|
|
|
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 = ''
|
|
if 0 < (val = jj[KEY_INSTRUMENTS]).length
|
|
str += ", Instruments = "
|
|
instr_ids = val.collect { |stored_instrument| stored_instrument['id'] }
|
|
instrs = Instrument.where(["id IN (?)", instr_ids]).order(:description)
|
|
instrs.each_with_index do |ii, idx|
|
|
proficiency = val.detect { |stored_instrument| stored_instrument['id'] == ii.id }['level']
|
|
str += "#{ii.description} / #{INSTRUMENT_PROFICIENCY[proficiency.to_i]}"
|
|
str += ', ' unless idx==(instrs.length-1)
|
|
end
|
|
end
|
|
|
|
if (val = jj[KEY_INTERESTS]) != INTEREST_VALS[0]
|
|
str += ", Interest = #{INTERESTS[val]}"
|
|
end
|
|
if (val = jj[KEY_SKILL].to_i) != SKILL_VALS[0]
|
|
str += ", Skill = #{SKILL_LEVELS[val]}"
|
|
end
|
|
if (val = jj[KEY_STUDIOS].to_i) != STUDIO_COUNTS[0]
|
|
str += ", Studio Sessions = #{STUDIOS_LABELS[val]}"
|
|
end
|
|
if (val = jj[KEY_GIGS].to_i) != GIG_COUNTS[0]
|
|
str += ", Concert Gigs = #{GIG_LABELS[val]}"
|
|
end
|
|
val = jj[KEY_AGES].map(&:to_i)
|
|
val.sort!
|
|
if !val.blank?
|
|
str += ", Ages = "
|
|
val.each_with_index do |vv, idx|
|
|
str += "#{AGES[vv]}"
|
|
str += ', ' unless idx==(val.length-1)
|
|
end
|
|
end
|
|
if 0 < (val = jj[KEY_GENRES]).length
|
|
str += ", Genres = "
|
|
genres = Genre.where(["id IN (?)", val]).order('description').pluck(:description)
|
|
genres.each_with_index do |gg, idx|
|
|
str += "#{gg}"
|
|
str += ', ' unless idx==(genres.length-1)
|
|
end
|
|
end
|
|
str += ", Sort = #{SORT_ORDERS[json_value(MusicianSearch::KEY_SORT_ORDER)]}"
|
|
|
|
if str.start_with?(', ')
|
|
# trim off any leading ,
|
|
str = str[2..-1]
|
|
end
|
|
str = 'Current Search: ' + str
|
|
str
|
|
end
|
|
|
|
end
|
|
end
|