diff --git a/ruby/lib/jam_ruby/models/search.rb b/ruby/lib/jam_ruby/models/search.rb index 5ec766695..acb82fdc0 100644 --- a/ruby/lib/jam_ruby/models/search.rb +++ b/ruby/lib/jam_ruby/models/search.rb @@ -103,6 +103,18 @@ module JamRuby DISTANCE_OPTS = B_DISTANCE_OPTS = M_DISTANCE_OPTS = [['Any', 0], [1000.to_s, 1000], [500.to_s, 500], [250.to_s, 250], [100.to_s, 100], [50.to_s, 50], [25.to_s, 25]] + # the values for score ranges are raw roundtrip scores. david often talks of one way scores (<= 20 is good), but + # the client reports scores as roundtrip and the server uses those values throughout + GOOD_SCORE = '.-40' + MODERATE_SCORE = '40-80' + POOR_SCORE = '80-120' + UNACCEPTABLE_SCORE = '120-.' + SCORED_SCORE = '.-.' # does not appear in menu choices + TEST_SCORE = '.-60' # does not appear in menu choices + ANY_SCORE = '' + M_SCORE_OPTS = [['Any', ANY_SCORE], ['Good', GOOD_SCORE], ['Moderate', MODERATE_SCORE], ['Poor', POOR_SCORE], ['Unacceptable', UNACCEPTABLE_SCORE]] + M_SCORE_DEFAULT = ANY_SCORE + F_SORT_RECENT = ['Most Recent', :date] F_SORT_OLDEST = ['Most Liked', :likes] F_SORT_LENGTH = ['Most Played', :plays] @@ -123,7 +135,7 @@ module JamRuby # produce a list of musicians (users where musician is true) # params: # instrument - instrument to search for or blank - # score_limit - score must be <= this to be included in the result (this is a test against the raw score) + # score_limit - a range specification for score, see M_SCORE_OPTS above. # handled by relation_pagination: # page - page number to fetch (origin 1) # per_page - number of entries per page @@ -151,11 +163,11 @@ module JamRuby # weeded out # filter on scores using selections from params - # todo scott what is the real limit? - score_limit = 60 + # see M_SCORE_OPTS + score_limit = TEST_SCORE l = params[:score_limit] - unless l.nil? or l.to_i <= 0 - score_limit = l.to_i + unless l.nil? + score_limit = l end # puts "================ score_limit #{score_limit}" @@ -165,9 +177,47 @@ module JamRuby # puts "================ locidispid #{locidispid}" unless locidispid.nil? - rel = rel.joins('inner join scores on scores.alocidispid = users.last_jam_locidispid') + # score_join of left allows for null scores, whereas score_join of inner requires a score however good or bad + # this is ANY_SCORE: + score_join = 'left' # or 'inner' + score_min = nil + score_max = nil + case score_limit + when GOOD_SCORE + score_join = 'inner' + score_min = nil + score_max = 40 + when MODERATE_SCORE + score_join = 'inner' + score_min = 40 + score_max = 80 + when POOR_SCORE + score_join = 'inner' + score_min = 80 + score_max = 120 + when UNACCEPTABLE_SCORE + score_join = 'inner' + score_min = 120 + score_max = nil + when SCORED_SCORE + score_join = 'inner' + score_min = nil + score_max = nil + when TEST_SCORE + score_join = 'inner' + score_min = nil + score_max = 60 + when ANY_SCORE + # the default of ANY setup above applies + else + # the default of ANY setup above applies + end + + rel = rel.joins("#{score_join} join scores on scores.alocidispid = users.last_jam_locidispid") .where(['scores.blocidispid = ?', locidispid]) - .where(['scores.score <= ?', score_limit]) + + rel = rel.where(['scores.score > ?', score_min]) unless score_min.nil? + rel = rel.where(['scores.score <= ?', score_max]) unless score_max.nil? rel = rel.select('scores.score') rel = rel.group('scores.score') @@ -192,7 +242,7 @@ module JamRuby end unless locidispid.nil? - rel = rel.order('scores.score') + rel = rel.order('scores.score ASC NULLS LAST') end rel = rel.order('users.created_at DESC') diff --git a/web/app/assets/javascripts/findMusician.js b/web/app/assets/javascripts/findMusician.js index e10458b3b..b2e388427 100644 --- a/web/app/assets/javascripts/findMusician.js +++ b/web/app/assets/javascripts/findMusician.js @@ -41,14 +41,10 @@ queryString += "instrument=" + instrument + '&'; } - // distance filter - var query_param = $('#musician_query_distance').val(); - if (query_param !== null && query_param.length > 0) { - var matches = query_param.match(/(\d+)/); - if (0 < matches.length) { - var distance = matches[0]; - queryString += "distance=" + distance + '&'; - } + // score filter + var query_param = $('#musician_query_score').val(); + if (query_param !== null) { + queryString += "score_limit=" + query_param + '&'; } loadMusicians(queryString); } @@ -228,7 +224,7 @@ } function events() { - $('#musician_query_distance').change(refreshDisplay); + $('#musician_query_score').change(refreshDisplay); $('#musician_instrument').change(refreshDisplay); $('#musician_order_by').change(refreshDisplay); diff --git a/web/app/views/clients/_musician_filter.html.erb b/web/app/views/clients/_musician_filter.html.erb index 429c54659..a32ae7485 100644 --- a/web/app/views/clients/_musician_filter.html.erb +++ b/web/app/views/clients/_musician_filter.html.erb @@ -13,12 +13,12 @@ <% end -%> <%= content_tag(:div, :class => 'filter-element wrapper') do -%> - <%= content_tag(:div, 'Within', :class => 'filter-element desc') %> + <%= content_tag(:div, 'Latency:', :class => 'filter-element desc') %> <%= content_tag(:div, :class => 'query-distance-params') do -%> - <%= select_tag('musician_query_distance', options_for_select(Search::M_DISTANCE_OPTS, Search::M_MILES_DEFAULT)) %> + <%= select_tag('musician_query_score', options_for_select(Search::M_SCORE_OPTS, Search::M_SCORE_DEFAULT)) %> <% end -%> <%= content_tag(:div, :class => 'filter-element') do -%> - miles of <%= content_tag(:span, current_user ? current_user.current_city(request.remote_ip) : '', :id => 'musician-filter-city') %> + to <%= content_tag(:span, current_user ? current_user.current_city(request.remote_ip) : '', :id => 'musician-filter-city') %> <% end -%> <% end -%> <%= content_tag(:div, diff --git a/web/spec/features/musician_search_spec.rb b/web/spec/features/musician_search_spec.rb index d0f290d48..61e6bd34f 100644 --- a/web/spec/features/musician_search_spec.rb +++ b/web/spec/features/musician_search_spec.rb @@ -4,15 +4,19 @@ describe "Musician Search", :js => true, :type => :feature, :capybara_feature => subject { page } - let(:user) { FactoryGirl.create(:user) } - before(:all) do poltergeist_setup end before(:each) do + @user = FactoryGirl.create(:user, last_jam_locidispid: 1) + @user2 = FactoryGirl.create(:user, last_jam_locidispid: 1) + + Score.delete_all + Score.createx(1, 'a', 1, 1, 'a', 1, 10) + ActiveRecord::Base.logger.debug '====================================== begin ======================================' - sign_in_poltergeist user + sign_in_poltergeist @user visit "/client#/musicians" end diff --git a/web/spec/requests/musician_search_api_spec.rb b/web/spec/requests/musician_search_api_spec.rb index 88b0eec3d..5e6f67f0a 100644 --- a/web/spec/requests/musician_search_api_spec.rb +++ b/web/spec/requests/musician_search_api_spec.rb @@ -33,6 +33,7 @@ describe "Musician Search API", :type => :api do @users << @user3 @users << @user4 + # 0-40 good, 40-80 moderate, 80-120 poor, 120-? unacceptable Score.createx(1, 'a', 1, 1, 'a', 1, 10) Score.createx(1, 'a', 1, 2, 'b', 2, 20) Score.createx(2, 'b', 2, 2, 'b', 2, 30) @@ -45,22 +46,22 @@ describe "Musician Search API", :type => :api do get_query good_response expect(json['musicians'].count).to be [Search::M_PER_PAGE, User.musicians_geocoded.count].min - puts json.inspect + # puts json.inspect end context 'score filtering' do it "gets no musicians" do - get_query({score_limit: 5}) + get_query({score_limit: Search::POOR_SCORE}) good_response (json['musicians'] || []).count.should == 0 end it "gets musicians for long-distance locations" do - get_query({:city => 'Miami', :distance => 1000}) + get_query({score_limit: Search::GOOD_SCORE}) good_response - expect(json['musicians'].count).to be >= 1 + (json['musicians'] || []).count.should == 5 end end