diff --git a/admin/Gemfile b/admin/Gemfile
index fe8c1df52..751e53b9b 100644
--- a/admin/Gemfile
+++ b/admin/Gemfile
@@ -97,7 +97,7 @@ end
# gem 'capistrano'
# To use debugger
-gem 'debugger'
+#gem 'debugger' # not working with 2.1.2p95
group :development, :test do
gem 'capybara'
diff --git a/admin/app/admin/score_export.rb b/admin/app/admin/score_export.rb
new file mode 100644
index 000000000..2b223a531
--- /dev/null
+++ b/admin/app/admin/score_export.rb
@@ -0,0 +1,100 @@
+ActiveAdmin.register_page "Download CSV" do
+ menu :parent => 'Score'
+
+ page_action :create_csv, :method => :post do
+
+ puts params.inspect
+
+ start_time = params[:score_exports][:start]
+ end_time = params[:score_exports][:end]
+
+ if start_time.blank?
+ start_time = '1900-01-01'
+ end
+ start_time = "#{start_time}"
+ if end_time.blank?
+ end_time = (Time.now + 1.days).strftime('%F')
+ else
+ end_time = "#{end_time}"
+ end
+
+ scores = ScoreHistory
+ .select("from_city, from_regions.regionname as from_region_name, from_countries.countryname as from_country_name, from_isp,
+ to_city, to_regions.regionname as to_region_name, to_countries.countryname as to_country_name, to_isp,
+ min(score_histories.score) as min_latency, max(score_histories.score) as max_latency, avg(score_histories.score) as mean_latency, median(CAST(score_histories.score AS NUMERIC)) as median_latency, count(score_histories.score) as score_count")
+ .joins('LEFT JOIN countries AS from_countries ON from_countries.countrycode = from_country')
+ .joins('LEFT JOIN countries AS to_countries ON to_countries.countrycode = to_country')
+ .joins('LEFT JOIN regions AS from_regions ON from_regions.region = from_region')
+ .joins('LEFT JOIN regions AS to_regions ON to_regions.region = to_region')
+ .where("score_dt BETWEEN DATE '#{start_time}' AND DATE '#{end_time}'")
+ .order('from_city, from_regions.regionname, from_countries.countryname, from_isp, to_city, to_regions.regionname, to_countries.countryname, to_isp')
+ .group('from_city, from_regions.regionname, from_countries.countryname, from_isp, to_city, to_regions.regionname, to_countries.countryname, to_isp')
+ .limit(1_000_000)
+
+
+ csv_string = CSV.generate do |csv|
+ csv << ["From Country", "From Region", "From City", "From ISP", "To Country", "To Region", "To City", "To ISP", "Min Latency", "Max Latency", "Median Latency", "Mean Latency", 'Score Count']
+
+ scores.each do |score|
+ puts score.inspect
+ csv << [score.from_country_name, score.from_region_name, score.from_city, score.from_isp,
+ score.to_country_name, score.to_region_name, score.to_city, score.to_isp,
+ score[:min_latency], score[:max_latency], score[:median_latency], score[:mean_latency], score[:score_count]]
+ end
+ end
+
+
+ send_data csv_string,
+ :type => 'text/csv; charset=iso-8859-1; header=present',
+ :disposition => "attachment; filename=score_export-#{start_time}-#{end_time}.csv"
+ end
+
+
+ content :title => "Export Score" do
+ columns do
+ column do
+ semantic_form_for :score_exports, :url => admin_download_csv_create_csv_path, :builder => ActiveAdmin::FormBuilder do |f|
+ f.inputs do
+ f.input :start, :as => :datepicker
+ f.input :end, :as => :datepicker
+ end
+ f.actions do
+ f.action :submit, :label => 'Download CSV'
+ end
+ end
+ end
+ column do
+ panel "Usage" do
+ span "Select a start day and end day to generate a CSV with a score summary. Both fields are optional."
+ end
+ panel "Limitation 1" do
+ div do
+ span do "The system limits the number of rows exported to 1,000,000" end
+ end
+ end
+ panel "Limitation 2" do
+ div do
+ span do "This report uses the score_histories table, which can lag up to 1 hour behind data. You can force a score_history sweep by going to" end
+ span do link_to "Resque", "#{Gon.global.prefix}/resque/schedule" end
+ span do " and then clicking 'Queue Now' for ScoreHistorySweeper. When the job count goes from 1 to 0, the score_histories table is now completely up-to-date, and you can make a 'fresh' CSV." end
+ end
+ end
+ end
+ end
+
+
+ #panel "Upaid Registrations" do
+ # table_for Registration.unpaid.limit(10).order('created_at desc') do
+ # column "Registration" do |registration|
+ # link_to registration.id, admin_registration_path(registration)
+ # end
+ # column :user
+ # column :tour
+ # column "Payment" do |registration|
+ # status_tag((registration.paid? ? "Received" : "Pending"), (registration.paid? ? :ok : :warning))
+ # end
+ # end
+ #end
+
+ end
+end
\ No newline at end of file
diff --git a/admin/app/admin/score_history.rb b/admin/app/admin/score_history.rb
index ccd827eac..85ed34393 100644
--- a/admin/app/admin/score_history.rb
+++ b/admin/app/admin/score_history.rb
@@ -2,36 +2,81 @@ ActiveAdmin.register JamRuby::ScoreHistory, :as => 'Score History' do
menu :parent => 'Score'
config.batch_actions = false
+ config.sort_order = 'score_dt_desc'
config.clear_action_items!
config.filters = true
+ config.per_page = 100
+
+ filter :score
filter :score_dt
+ #filter :from_user_id_eq, :as => :autocomplete, :url => "#{Gon.global.prefix}/admin/users/autocomplete_user_email",
+ # :label => "From User", :required => false,
+ # :wrapper_html => { :style => "list-style: none" }
+
+ #autocomplete :user, :email, :full => true, :display_value => :autocomplete_display_name
+
+ filter :from_user_id, as: :string
+ filter :from_latency_tester_id
+ filter :from_isp
+ filter :from_country
+ filter :from_region
+ filter :from_city
+ filter :from_postal
+ filter :from_latitude
+ filter :from_latitude
+ filter :from_longitude
+ filter :to_user_id, as: :string
+ filter :to_latency_tester_id
+ filter :to_isp
+ filter :to_country
+ filter :to_region
+ filter :to_city
+ filter :to_postal
+ filter :to_latitude
+ filter :to_latitude
+ filter :to_longitude
+
+ before_filter only: :index do
+ @per_page = 1_000_000 if request.format == 'text/csv'
+ end
index do
- column :score
- column :score_dt
+ column "Score", :score
+ column "When", :score_dt
+ column "From User", :from_user_id do |score|
+ link_to score.from_user, admin_user_path(score.from_user) if score.from_user_id
+ end
+ column "From Latency Tester", :from_latency_tester_id do |score|
+ link_to score.from_latency_tester_id, admin_latency_testers_path if score.from_latency_tester_id
+ end
+ column "From IP", :from_addr do |score|
+ IPAddr.new(score.from_addr, Socket::AF_INET).to_s if score.from_addr
+ end
+ column "From ISP", :from_isp
+ column "From Country", :from_country
+ column "From Region", :from_region
+ column "From City", :from_city
+ column "From Postal", :from_postal
+ column "From Lat", :from_latitude
+ column "From Long", :from_longitude
+ column "From Client", :from_client_id
- column :from_client_id
- column :from_user_id
- column :from_latency_tester_id
- column :from_addr
- column :from_isp
- column :from_country
- column :from_region
- column :from_city
- column :from_postal
- column :from_latitude
- column :from_longitude
-
- column :to_client_id
- column :to_user_id
- column :to_latency_tester_id
- column :to_addr
- column :to_isp
- column :to_country
- column :to_region
- column :to_city
- column :to_postal
- column :to_latitude
- column :to_longitude
+ column "To User", :to_user_id do |score|
+ link_to score.to_user, admin_user_path(score.to_user) if score.to_user_id
+ end
+ column "To Latency Tester", :to_latency_tester_id do |score|
+ link_to score.to_latency_tester_id, admin_latency_testers_path if score.to_latency_tester_id
+ end
+ column "To IP", :to_addr do |score|
+ IPAddr.new(score.to_addr, Socket::AF_INET).to_s if score.to_addr
+ end
+ column "To ISP", :to_isp
+ column "To Country", :to_country
+ column "To Region", :to_region
+ column "To City", :to_city
+ column "To Postal", :to_postal
+ column "To Lat", :to_latitude
+ column "To Long", :to_longitude
+ column "To Client", :to_client_id
end
end
diff --git a/admin/app/assets/javascripts/admin_rest.js b/admin/app/assets/javascripts/admin_rest.js
index e41ea253a..64f49efdf 100644
--- a/admin/app/assets/javascripts/admin_rest.js
+++ b/admin/app/assets/javascripts/admin_rest.js
@@ -17,7 +17,7 @@
return $.ajax({
type: "POST",
dataType: "json",
- url: gon.global.prefix + 'api/mix/' + mixId + '/enqueue',
+ url: gon.global.prefix + '/api/mix/' + mixId + '/enqueue',
contentType: 'application/json',
processData: false
});
diff --git a/admin/app/assets/javascripts/mix_again.js b/admin/app/assets/javascripts/mix_again.js
index 5086e7a14..0272941f9 100644
--- a/admin/app/assets/javascripts/mix_again.js
+++ b/admin/app/assets/javascripts/mix_again.js
@@ -9,7 +9,7 @@
var $link = $(this);
restAdmin.tryMixAgain({mix_id: $link.attr('data-mix-id')})
.done(function(response) {
- $link.closest('div.mix-again').find('div.mix-again-dialog').html('
Mix enqueued
Resque Web').dialog();
+ $link.closest('div.mix-again').find('div.mix-again-dialog').html('Mix enqueued
Resque Web').dialog();
})
.error(function(jqXHR) {
$link.closest('div.mix-again').find('div.mix-again-dialog').html('Mix failed: ' + jqXHR.responseText).dialog();
diff --git a/admin/config/initializers/gon.rb b/admin/config/initializers/gon.rb
index 9eb7ab9da..d8e7bd43f 100644
--- a/admin/config/initializers/gon.rb
+++ b/admin/config/initializers/gon.rb
@@ -1 +1 @@
-Gon.global.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
\ No newline at end of file
+Gon.global.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] || ''
\ No newline at end of file
diff --git a/admin/migrate.sh b/admin/migrate.sh
new file mode 100755
index 000000000..a9afa1578
--- /dev/null
+++ b/admin/migrate.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+bundle exec jam_db up --connopts=dbname:jam host:localhost user:postgres password:postgres --verbose
diff --git a/db/manifest b/db/manifest
index 65fbf8688..8bad4f17c 100755
--- a/db/manifest
+++ b/db/manifest
@@ -195,4 +195,8 @@ max_mind_releases.sql
score_histories.sql
update_sms_index.sql
connection_allow_null_locidispid.sql
-track_user_in_scores.sql
\ No newline at end of file
+track_user_in_scores.sql
+median_aggregate.sql
+current_scores_use_median.sql
+current_scores_ams_index_sms_index_use_user_instrument.sql
+locidispid_in_score_histories.sql
\ No newline at end of file
diff --git a/db/up/current_scores_ams_index_sms_index_use_user_instrument.sql b/db/up/current_scores_ams_index_sms_index_use_user_instrument.sql
new file mode 100644
index 000000000..a3f7b7b10
--- /dev/null
+++ b/db/up/current_scores_ams_index_sms_index_use_user_instrument.sql
@@ -0,0 +1,163 @@
+-- this adds the user's latency, if available
+
+DROP VIEW current_scores;
+CREATE OR REPLACE VIEW current_scores AS
+
+ SELECT * FROM (SELECT * , row_number() OVER (PARTITION BY alocidispid, blocidispid, scorer ORDER BY full_score DESC) AS pcnum FROM
+ (SELECT * FROM
+ (SELECT percent_rank() over (PARTITION BY alocidispid, blocidispid ORDER BY full_score ASC) AS pc, * FROM
+ (SELECT tmp.*, (COALESCE(a_users.last_jam_audio_latency, 13) + COALESCE(b_users.last_jam_audio_latency, 13) + tmp.score) AS full_score, a_users.last_jam_audio_latency AS a_audio_latency, b_users.last_jam_audio_latency AS b_audio_latency FROM
+ (SELECT *, row_number() OVER (PARTITION BY alocidispid, blocidispid ORDER BY scores.created_at DESC) AS rownum FROM scores) tmp
+ LEFT JOIN users as a_users ON a_users.id = tmp.auserid
+ LEFT JOIN users as b_users ON b_users.id = tmp.buserid
+ WHERE rownum < 6) AS score_ranked)
+ AS tmp2 WHERE pc <= .5 ORDER BY pc DESC) pcs )
+ AS final WHERE pcnum < 2;
+
+
+-- check that the music_sessions does not currently have an active_music_sessions
+CREATE OR REPLACE FUNCTION sms_index (my_user_id VARCHAR, my_locidispid BIGINT, my_audio_latency INTEGER) RETURNS VOID STRICT VOLATILE AS $$
+ BEGIN
+ -- output table to hold tagged music sessions with latency
+ CREATE TEMPORARY TABLE sms_music_session_tmp (music_session_id VARCHAR(64) NOT NULL, tag INTEGER, latency INTEGER) ON COMMIT DROP;
+
+ -- populate sms_music_session_tmp as all music sessions
+ -- XXX: we should pass in enough info to match pagination/query to reduce the impact of this step
+ INSERT INTO sms_music_session_tmp SELECT DISTINCT id, NULL::INTEGER AS tag, NULL::INTEGER AS latency
+ FROM music_sessions
+ WHERE (scheduled_start IS NULL OR scheduled_start > (NOW() - (interval '15 minute')))
+ AND canceled = FALSE
+ AND id NOT IN (SELECT id FROM active_music_sessions);
+
+ -- tag accepted rsvp as 1
+ UPDATE sms_music_session_tmp q SET tag = 1 FROM rsvp_slots s, rsvp_requests_rsvp_slots rrs, rsvp_requests r WHERE
+ q.music_session_id = s.music_session_id AND
+ s.id = rrs.rsvp_slot_id AND
+ rrs.rsvp_request_id = r.id AND
+ r.user_id = my_user_id AND
+ rrs.chosen = TRUE AND
+ q.tag is NULL;
+
+ -- tag invitation as 2
+ UPDATE sms_music_session_tmp q SET tag = 2 FROM invitations i WHERE
+ q.music_session_id = i.music_session_id AND
+ i.receiver_id = my_user_id AND
+ q.tag IS NULL;
+
+ -- musician access as 3
+ UPDATE sms_music_session_tmp q SET tag = 3 FROM music_sessions m WHERE
+ q.music_session_id = m.id AND
+ m.open_rsvps = TRUE AND
+ q.tag IS NULL;
+
+ -- delete anything not tagged
+ DELETE FROM sms_music_session_tmp WHERE tag IS NULL;
+
+ -- output table to hold users involved in the sms_music_session_tmp sessions and their latency
+ CREATE TEMPORARY TABLE sms_users_tmp (music_session_id VARCHAR(64), user_id VARCHAR(64) NOT NULL, latency INTEGER) ON COMMIT DROP;
+
+ IF my_audio_latency > -1 THEN
+ -- populate sms_users_tmp with users that have an approved RSVP for sessions in the sms_music_session_tmp table, accompanied with full latency and music session
+ INSERT INTO sms_users_tmp SELECT q.music_session_id, users.id, s.full_score/2 AS latency
+ FROM sms_music_session_tmp q
+ INNER JOIN rsvp_slots ON rsvp_slots.music_session_id = q.music_session_id
+ INNER JOIN rsvp_requests_rsvp_slots ON rsvp_requests_rsvp_slots.rsvp_slot_id = rsvp_slots.id
+ INNER JOIN rsvp_requests ON rsvp_requests.id = rsvp_requests_rsvp_slots.rsvp_request_id
+ INNER JOIN users ON rsvp_requests.user_id = users.id
+ LEFT OUTER JOIN current_scores s ON s.alocidispid = users.last_jam_locidispid
+ WHERE
+ s.blocidispid = my_locidispid AND
+ rsvp_requests_rsvp_slots.chosen = TRUE;
+
+ -- populate sms_users_tmp with invited users for session in the sms_music_session_tmp table, accompanied with full latency and music session
+ -- specify NULL for music_session_id, because we don't want RSVP users to affect the AVG computed for each session later
+ INSERT INTO sms_users_tmp SELECT NULL, users.id, s.full_score/2 AS latency
+ FROM sms_music_session_tmp q
+ INNER JOIN invitations ON invitations.music_session_id = q.music_session_id
+ INNER JOIN users ON invitations.receiver_id = users.id
+ LEFT OUTER JOIN current_scores s ON s.alocidispid = users.last_jam_locidispid
+ WHERE
+ s.blocidispid = my_locidispid AND
+ users.id NOT IN (SELECT user_id FROM sms_users_tmp);
+ END IF;
+
+ -- calculate the average latency
+ UPDATE sms_music_session_tmp q SET latency = (select AVG(u.latency) FROM sms_users_tmp u WHERE
+ q.music_session_id = u.music_session_id);
+
+ RETURN;
+ END;
+$$ LANGUAGE plpgsql;
+
+-- my_audio_latency can have a special value of -1, which means 'unknown'.
+CREATE OR REPLACE FUNCTION ams_index (my_user_id VARCHAR, my_locidispid BIGINT, my_audio_latency INTEGER) RETURNS VOID STRICT VOLATILE AS $$
+ BEGIN
+ -- output table to hold tagged music sessions with latency
+ CREATE TEMPORARY TABLE ams_music_session_tmp (music_session_id VARCHAR(64) NOT NULL, tag INTEGER, latency INTEGER) ON COMMIT DROP;
+
+ -- populate ams_music_session_tmp as all music sessions
+ INSERT INTO ams_music_session_tmp SELECT DISTINCT id, NULL::INTEGER AS tag, NULL::INTEGER AS latency
+ FROM active_music_sessions;
+
+ -- TODO worry about active music session where my_user_id is the creator?
+ -- eh, maybe, but if the music session is active and you're the creator wouldn't you already be in it?
+ -- so maybe you're on another computer, so why care? plus seth is talking about auto rsvp'ing the session
+ -- for you, so maybe not a problem.
+
+ -- tag accepted rsvp as 1
+ UPDATE ams_music_session_tmp q SET tag = 1 FROM rsvp_slots s, rsvp_requests_rsvp_slots rrs, rsvp_requests r WHERE
+ q.music_session_id = s.music_session_id AND
+ s.id = rrs.rsvp_slot_id AND
+ rrs.rsvp_request_id = r.id AND
+ r.user_id = my_user_id AND
+ rrs.chosen = TRUE AND
+ q.tag is NULL;
+
+ -- tag invitation as 2
+ UPDATE ams_music_session_tmp q SET tag = 2 FROM invitations i WHERE
+ q.music_session_id = i.music_session_id AND
+ i.receiver_id = my_user_id AND
+ q.tag IS NULL;
+
+ -- musician access as 3
+ UPDATE ams_music_session_tmp q SET tag = 3 FROM music_sessions m WHERE
+ q.music_session_id = m.id AND
+ m.musician_access = TRUE AND
+ q.tag IS NULL;
+
+ -- delete anything not tagged
+ DELETE FROM ams_music_session_tmp WHERE tag IS NULL;
+
+ -- output table to hold users involved in the ams_music_session_tmp sessions and their latency
+ CREATE TEMPORARY TABLE ams_users_tmp (music_session_id VARCHAR(64), user_id VARCHAR(64) NOT NULL, latency INTEGER) ON COMMIT DROP;
+
+ IF my_audio_latency > -1 THEN
+ -- populate ams_users_tmp with users that have a connection for sessions in the ams_music_session_tmp table, accompanied with full latency and music session
+ INSERT INTO ams_users_tmp SELECT c.music_session_id, c.user_id, s.full_score/2 AS latency
+ FROM ams_music_session_tmp q
+ INNER JOIN connections c ON c.music_session_id = q.music_session_id
+ LEFT OUTER JOIN current_scores s ON s.alocidispid = c.locidispid
+ WHERE s.blocidispid = my_locidispid;
+
+ -- populate ams_users_tmp with users that have an approved RSVP for sessions inthe ams_music_session_tmp table, accompanied with full latency and music session
+ -- specify NULL for music_session_id, because we don't want RSVP users to affect the AVG computed for each session later
+ INSERT INTO ams_users_tmp SELECT NULL, users.id, s.full_score/2 AS latency
+ FROM ams_music_session_tmp q
+ INNER JOIN rsvp_slots ON rsvp_slots.music_session_id = q.music_session_id
+ INNER JOIN rsvp_requests_rsvp_slots ON rsvp_requests_rsvp_slots.rsvp_slot_id = rsvp_slots.id
+ INNER JOIN rsvp_requests ON rsvp_requests.id = rsvp_requests_rsvp_slots.rsvp_request_id
+ INNER JOIN users ON rsvp_requests.user_id = users.id
+ LEFT OUTER JOIN current_scores s ON s.alocidispid = users.last_jam_locidispid
+ WHERE
+ s.blocidispid = my_locidispid AND
+ rsvp_requests_rsvp_slots.chosen = TRUE AND
+ users.id NOT IN (SELECT user_id FROM ams_users_tmp);
+ END IF;
+
+ -- calculate the average latency
+ UPDATE ams_music_session_tmp q SET latency = (select AVG(u.latency) FROM ams_users_tmp u WHERE
+ q.music_session_id = u.music_session_id);
+
+ RETURN;
+ END;
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/db/up/current_scores_use_median.sql b/db/up/current_scores_use_median.sql
new file mode 100644
index 000000000..44a02e0f8
--- /dev/null
+++ b/db/up/current_scores_use_median.sql
@@ -0,0 +1,13 @@
+-- this results in a rough median; the only problem is that we don't avg if it's an even number. not a big deal truthfully, since eventually you'll have > 5
+
+DROP VIEW current_scores;
+CREATE OR REPLACE VIEW current_scores AS
+
+ SELECT * FROM (SELECT * , row_number() OVER (PARTITION BY alocidispid, blocidispid, scorer ORDER BY score DESC) AS pcnum FROM
+ (SELECT * FROM
+ (SELECT percent_rank() over (PARTITION BY alocidispid, blocidispid ORDER BY score ASC) AS pc, * FROM
+ (SELECT * FROM
+ (SELECT *, row_number() OVER (PARTITION BY alocidispid, blocidispid ORDER BY created_at DESC) AS rownum FROM scores) tmp
+ WHERE rownum < 6) AS score_ranked)
+ AS tmp2 WHERE pc <= .5 ORDER BY pc DESC) pcs )
+ AS final WHERE pcnum < 2;
diff --git a/db/up/locidispid_in_score_histories.sql b/db/up/locidispid_in_score_histories.sql
new file mode 100644
index 000000000..38846045b
--- /dev/null
+++ b/db/up/locidispid_in_score_histories.sql
@@ -0,0 +1,5 @@
+-- https://jamkazam.atlassian.net/browse/VRFS-1968
+-- store both locids in score_histories
+
+ALTER TABLE score_histories ADD COLUMN from_locidispid BIGINT NOT NULL;
+ALTER TABLE score_histories ADD COLUMN to_locidispid BIGINT NOT NULL;
\ No newline at end of file
diff --git a/db/up/median_aggregate.sql b/db/up/median_aggregate.sql
new file mode 100644
index 000000000..63bf77d96
--- /dev/null
+++ b/db/up/median_aggregate.sql
@@ -0,0 +1,23 @@
+-- from here: https://wiki.postgresql.org/wiki/Aggregate_Median
+CREATE OR REPLACE FUNCTION _final_median(numeric[])
+ RETURNS numeric
+AS
+$body$
+ SELECT AVG(val)
+ FROM (
+ SELECT val
+ FROM unnest($1) val
+ ORDER BY 1
+ LIMIT 2 - MOD(array_upper($1, 1), 2)
+ OFFSET CEIL(array_upper($1, 1) / 2.0) - 1
+ ) sub;
+$body$
+LANGUAGE sql ;
+-- IMMUTABLE not accepted by pg migrate
+
+CREATE AGGREGATE median(numeric) (
+ SFUNC=array_append,
+ STYPE=numeric[],
+ FINALFUNC=_final_median,
+ INITCOND='{}'
+);
diff --git a/db/up/scores_better_test_data.sql b/db/up/scores_better_test_data.sql
index 52a8e9842..0f5935cc6 100644
--- a/db/up/scores_better_test_data.sql
+++ b/db/up/scores_better_test_data.sql
@@ -86,10 +86,10 @@ CREATE OR REPLACE FUNCTION generate_scores_dataset () RETURNS VOID STRICT VOLATI
INSERT INTO cities (city, region, countrycode) select distinct city, region, countrycode from geoiplocations where length(city) > 0 and length(countrycode) > 0;
DELETE FROM regions;
- INSERT INTO regions (region, countrycode) select distinct region, countrycode from cities;
+ INSERT INTO regions (region, regionname, countrycode) select distinct region, region, countrycode from cities;
DELETE FROM countries;
- INSERT INTO countries (countrycode) select distinct countrycode from regions;
+ INSERT INTO countries (countrycode, countryname) select distinct countrycode, countrycode from regions;
END IF;
RETURN;
diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb
index 271bd5863..290fd93f4 100644
--- a/ruby/lib/jam_ruby/models/music_session.rb
+++ b/ruby/lib/jam_ruby/models/music_session.rb
@@ -111,6 +111,7 @@ module JamRuby
new_slot = RsvpSlot.new
new_slot.instrument_id = slot.instrument_id
new_slot.proficiency_level = slot.proficiency_level
+ new_slot.is_unstructured_rsvp = slot.is_unstructured_rsvp
new_session.rsvp_slots << new_slot
# get the request for this slot that was approved (should only be ONE)
@@ -409,7 +410,7 @@ module JamRuby
end
def has_mount?
- active_music_session && active_music_session.mount
+ !active_music_session.nil? && !active_music_session.mount.nil?
end
def can_cancel? user
diff --git a/ruby/lib/jam_ruby/models/rsvp_request.rb b/ruby/lib/jam_ruby/models/rsvp_request.rb
index 6ba1d2ab9..3558df969 100644
--- a/ruby/lib/jam_ruby/models/rsvp_request.rb
+++ b/ruby/lib/jam_ruby/models/rsvp_request.rb
@@ -253,7 +253,7 @@ module JamRuby
# send notification
if music_session.creator.id == user.id
- Notification.send_scheduled_session_rsvp_cancelled_org(music_session, user)
+ Notification.send_scheduled_session_rsvp_cancelled_org(music_session, rsvp_request.user)
else
Notification.send_scheduled_session_rsvp_cancelled(music_session, user)
end
diff --git a/ruby/lib/jam_ruby/models/score_history.rb b/ruby/lib/jam_ruby/models/score_history.rb
index 5c17640f6..4c82e3326 100644
--- a/ruby/lib/jam_ruby/models/score_history.rb
+++ b/ruby/lib/jam_ruby/models/score_history.rb
@@ -4,6 +4,9 @@ module JamRuby
self.table_name = 'score_histories'
+ belongs_to :from_user, class_name: 'JamRuby::User', foreign_key: 'from_user_id'
+ belongs_to :to_user, class_name: 'JamRuby::User', foreign_key: 'to_user_id'
+
def self.migrate_scores
generic_state = GenericState.singleton
@@ -12,14 +15,15 @@ module JamRuby
result = connection.execute(
"INSERT INTO score_histories
- (from_client_id, from_user_id, from_latency_tester_id, from_addr, from_isp, from_country, from_region, from_city, from_postal, from_latitude, from_longitude,
- to_client_id, to_user_id, to_latency_tester_id, to_addr, to_isp, to_country, to_region, to_city, to_postal, to_latitude, to_longitude,
+ (from_client_id, from_user_id, from_latency_tester_id, from_addr, from_locidispid, from_isp, from_country, from_region, from_city, from_postal, from_latitude, from_longitude,
+ to_client_id, to_user_id, to_latency_tester_id, to_addr, to_locidispid, to_isp, to_country, to_region, to_city, to_postal, to_latitude, to_longitude,
score, score_dt, scoring_data)
SELECT
s.anodeid AS from_client_id,
s.auserid AS from_user_id,
s.alatencytestid AS from_latency_tester_id,
s.aaddr AS from_addr,
+ s.alocidispid AS from_locidispid,
x.company AS from_isp,
a.countrycode AS from_country,
a.region AS from_region,
@@ -31,6 +35,7 @@ module JamRuby
s.buserid AS to_user_id,
s.blatencytestid AS to_latency_tester_id,
s.baddr AS to_addr,
+ s.blocidispid AS to_locidispid,
y.company AS to_isp,
b.countrycode AS to_country,
b.region AS to_region,
diff --git a/ruby/lib/jam_ruby/models/search.rb b/ruby/lib/jam_ruby/models/search.rb
index 4b1d1868b..761660c84 100644
--- a/ruby/lib/jam_ruby/models/search.rb
+++ b/ruby/lib/jam_ruby/models/search.rb
@@ -98,8 +98,11 @@ module JamRuby
M_ORDER_FOLLOWS = ['Most Followed', :followed]
M_ORDER_PLAYS = ['Most Plays', :plays]
M_ORDER_PLAYING = ['Playing Now', :playing]
- ORDERINGS = B_ORDERINGS = M_ORDERINGS = [M_ORDER_FOLLOWS, M_ORDER_PLAYS, M_ORDER_PLAYING]
- B_ORDERING_KEYS = M_ORDERING_KEYS = M_ORDERINGS.collect { |oo| oo[1] }
+ M_ORDER_LATENCY = ['Latency To Me', :latency]
+ M_ORDERINGS = [M_ORDER_LATENCY, M_ORDER_FOLLOWS, M_ORDER_PLAYS]
+ ORDERINGS = B_ORDERINGS = [M_ORDER_FOLLOWS, M_ORDER_PLAYS, M_ORDER_PLAYING]
+ M_ORDERING_KEYS = M_ORDERINGS.collect { |oo| oo[1] }
+ B_ORDERING_KEYS = B_ORDERINGS.collect { |oo| oo[1] }
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]]
@@ -150,7 +153,7 @@ module JamRuby
# puts "================ user #{user.inspect}"
# puts "================ conn #{conn.inspect}"
- rel = User.musicians_geocoded
+ rel = User.musicians # not musicians_geocoded on purpose; we allow 'unknowns' to surface in the search page
rel = rel.select('users.*')
rel = rel.group('users.id')
@@ -164,7 +167,7 @@ module JamRuby
# filter on scores using selections from params
# see M_SCORE_OPTS
- score_limit = TEST_SCORE
+ score_limit = ANY_SCORE
l = params[:score_limit]
unless l.nil?
score_limit = l
@@ -182,6 +185,7 @@ module JamRuby
score_join = 'left outer' # or 'inner'
score_min = nil
score_max = nil
+ # these score_min, score_max come from here (doubled): https://jamkazam.atlassian.net/browse/VRFS-1962
case score_limit
when GOOD_SCORE
score_join = 'inner'
@@ -190,14 +194,14 @@ module JamRuby
when MODERATE_SCORE
score_join = 'inner'
score_min = 40
- score_max = 80
+ score_max = 70
when POOR_SCORE
score_join = 'inner'
score_min = 80
- score_max = 120
+ score_max = 100
when UNACCEPTABLE_SCORE
score_join = 'inner'
- score_min = 120
+ score_min = 100
score_max = nil
when SCORED_SCORE
score_join = 'inner'
@@ -216,16 +220,20 @@ module JamRuby
rel = rel.joins("#{score_join} join current_scores on current_scores.alocidispid = users.last_jam_locidispid")
.where(['(current_scores.blocidispid = ? or current_scores.blocidispid is null)', locidispid])
- rel = rel.where(['current_scores.score > ?', score_min]) unless score_min.nil?
- rel = rel.where(['current_scores.score <= ?', score_max]) unless score_max.nil?
+ rel = rel.joins('LEFT JOIN regions ON regions.countrycode = users.country AND regions.region = users.state')
- rel = rel.select('current_scores.score')
- rel = rel.group('current_scores.score')
+ rel = rel.where(['current_scores.full_score > ?', score_min]) unless score_min.nil?
+ rel = rel.where(['current_scores.full_score <= ?', score_max]) unless score_max.nil?
+
+ rel = rel.select('current_scores.full_score, current_scores.score, current_scores.b_audio_latency as audio_latency, regions.regionname')
+ rel = rel.group('current_scores.full_score, current_scores.score, current_scores.b_audio_latency, regions.regionname')
end
ordering = self.order_param(params)
# puts "================ ordering #{ordering}"
case ordering
+ when :latency
+ # nothing to do. the sort added below 'current_scores.score ASC NULLS LAST' handles this
when :plays # FIXME: double counting?
# sel_str = "COUNT(records)+COUNT(sessions) AS play_count, #{sel_str}"
rel = rel.select('COUNT(records.id)+COUNT(sessions.id) AS search_play_count')
@@ -242,7 +250,7 @@ module JamRuby
end
unless locidispid.nil?
- rel = rel.order('current_scores.score ASC NULLS LAST')
+ rel = rel.order('current_scores.full_score ASC NULLS LAST')
end
rel = rel.order('users.created_at DESC')
@@ -386,15 +394,15 @@ module JamRuby
# an offline process and thus uses the last jam location as "home base"
locidispid = usr.last_jam_locidispid
- score_limit = 60
+ score_limit = 70
limit = 50
rel = User.musicians_geocoded
- .where(['created_at >= ? AND users.id != ?', since_date, usr.id])
+ .where(['users.created_at >= ? AND users.id != ?', since_date, usr.id])
.joins('inner join current_scores on users.last_jam_locidispid = current_scores.alocidispid')
.where(['current_scores.blocidispid = ?', locidispid])
- .where(['current_scores.score <= ?', score_limit])
- .order('current_scores.score') # best scores first
+ .where(['current_scores.full_score <= ?', score_limit])
+ .order('current_scores.full_score') # best scores first
.order('users.created_at DESC') # then most recent
.limit(limit)
@@ -418,7 +426,7 @@ module JamRuby
rel = GeoIpLocations.where_latlng(rel, params, current_user)
sel_str = 'bands.*'
- case ordering = self.order_param(params)
+ case ordering = self.order_param(params, B_ORDERING_KEYS)
when :plays # FIXME: double counting?
sel_str = "COUNT(records)+COUNT(msh) AS play_count, #{sel_str}"
rel = rel.joins("LEFT JOIN music_sessions AS msh ON msh.band_id = bands.id")
diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb
index 5f241d71b..06d7d97e4 100644
--- a/ruby/lib/jam_ruby/models/user.rb
+++ b/ruby/lib/jam_ruby/models/user.rb
@@ -116,6 +116,9 @@ module JamRuby
# diagnostics
has_many :diagnostics, :class_name => "JamRuby::Diagnostic"
+ # score history
+ has_many :from_score_histories, :class_name => "JamRuby::ScoreHistory", foreign_key: 'from_user_id'
+ has_many :to_score_histories, :class_name => "JamRuby::ScoreHistory", foreign_key: 'to_user_id'
# This causes the authenticate method to be generated (among other stuff)
#has_secure_password
diff --git a/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb b/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb
index f54215896..cd706285a 100644
--- a/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb
+++ b/ruby/lib/jam_ruby/resque/scheduled/music_session_scheduler.rb
@@ -27,8 +27,8 @@ module JamRuby
end
def run
- # get all weekly sessions that have ended in the last 15 minutes
- criteria = "recurring_mode = 'weekly' AND session_removed_at is not null AND canceled = false AND next_session_scheduled = false"
+ # get all weekly sessions that started at least 4 hours ago
+ criteria = "recurring_mode = 'weekly' AND scheduled_start + interval '4hours' < NOW() AND canceled = false AND next_session_scheduled = false"
MusicSession.find_each(:conditions => criteria) do |music_session|
music_session.copy
end
diff --git a/ruby/spec/jam_ruby/models/active_music_session_spec.rb b/ruby/spec/jam_ruby/models/active_music_session_spec.rb
index b59dd0b45..ab02b8281 100644
--- a/ruby/spec/jam_ruby/models/active_music_session_spec.rb
+++ b/ruby/spec/jam_ruby/models/active_music_session_spec.rb
@@ -354,8 +354,8 @@ describe ActiveMusicSession do
user = FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 5)
c3 = FactoryGirl.create(:connection, user: user, locidispid: 1, last_jam_audio_latency: 5)
- Score.createx(c1.locidispid, c1.client_id, c1.addr, c3.locidispid, c3.client_id, c3.addr, 20, nil)
- Score.createx(c2.locidispid, c2.client_id, c2.addr, c3.locidispid, c3.client_id, c3.addr, 30, nil)
+ Score.createx(c1.locidispid, c1.client_id, c1.addr, c3.locidispid, c3.client_id, c3.addr, 20, nil, nil, {auserid: creator.id, buserid: user.id})
+ Score.createx(c2.locidispid, c2.client_id, c2.addr, c3.locidispid, c3.client_id, c3.addr, 30, nil, nil, {auserid: creator2.id, buserid: user.id})
# make a transaction
diff --git a/ruby/spec/jam_ruby/models/music_session_spec.rb b/ruby/spec/jam_ruby/models/music_session_spec.rb
index da8692250..ad4cc67de 100644
--- a/ruby/spec/jam_ruby/models/music_session_spec.rb
+++ b/ruby/spec/jam_ruby/models/music_session_spec.rb
@@ -421,7 +421,7 @@ describe MusicSession do
let(:network_score) { 20 }
before(:each) do
- Score.createx(conn.locidispid, conn.client_id, conn.addr, searcher_conn.locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil)
+ Score.createx(conn.locidispid, conn.client_id, conn.addr, searcher_conn.locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil, nil, {auserid: creator.id, buserid: searcher.id})
end
it "no results" do
@@ -499,7 +499,7 @@ describe MusicSession do
FactoryGirl.create(:invitation, receiver:invitee, sender:creator, music_session: music_session)
# create a score between invitee, and searcher
- Score.createx(invitee.last_jam_locidispid, 'immaterial', 1, searcher_conn.locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil)
+ Score.createx(invitee.last_jam_locidispid, 'immaterial', 1, searcher_conn.locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil, nil, {auserid: invitee.id, buserid: searcher.id})
music_sessions, user_scores = sms(searcher, default_opts)
music_sessions.length.should == 1
@@ -580,14 +580,16 @@ describe MusicSession do
end
it "searcher_1" do
+
+
# create a bad score between searcher_1 and creator_1 (but we should still see it sort 1st because it's got an RSVP to the searcher)
- Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_1.locidispid, creator_conn_1.client_id, creator_conn_1.addr, bad_network_score, nil)
+ Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_1.locidispid, creator_conn_1.client_id, creator_conn_1.addr, bad_network_score, nil, nil, {auserid: searcher_1.id, buserid: creator_1.id})
# create a fair score between searcher_1 and creator_2 (but we should still see it sort 2st because it's got an invitation to the searcher)
- Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_2.locidispid, creator_conn_2.client_id, creator_conn_2.addr, fair_network_score, nil)
+ Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_2.locidispid, creator_conn_2.client_id, creator_conn_2.addr, fair_network_score, nil, nil, {auserid: searcher_1.id, buserid: creator_2.id})
# create a good score between searcher_1 and creator_3 (but we should still see it sort last because it's an open session; no affiliation with the searcher)
- Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_3.locidispid, creator_conn_3.client_id, creator_conn_3.addr, good_network_score, nil)
+ Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_3.locidispid, creator_conn_3.client_id, creator_conn_3.addr, good_network_score, nil, nil, {auserid: searcher_1.id, buserid: creator_3.id})
music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id})
diff --git a/ruby/spec/jam_ruby/models/musician_search_spec.rb b/ruby/spec/jam_ruby/models/musician_search_spec.rb
index a98985b17..f1cafa067 100644
--- a/ruby/spec/jam_ruby/models/musician_search_spec.rb
+++ b/ruby/spec/jam_ruby/models/musician_search_spec.rb
@@ -30,7 +30,10 @@ describe 'Musician search' do
@geomusicians << @user4
@geomusicians << @user5
- Score.delete_all
+ # from these scores:
+ # user1 has scores other users in user1 location, and with user2, user3, user4
+ # user2 has scores with users in user3 and user4 location
+ # Score.delete_all
Score.createx(1, 'a', 1, 1, 'a', 1, 10)
Score.createx(1, 'a', 1, 2, 'b', 2, 20)
Score.createx(1, 'a', 1, 3, 'c', 3, 30)
@@ -43,46 +46,46 @@ describe 'Musician search' do
it "finds all musicians" do
# expects all the musicians (geocoded)
- results = Search.musician_filter
+ results = Search.musician_filter({score_limit: Search::TEST_SCORE})
results.search_type.should == :musicians_filter
- results.results.count.should == @geomusicians.length
- results.results.should eq @geomusicians.reverse
+ results.results.count.should == @musicians.length
+ results.results.should eq @musicians.reverse
end
it "finds all musicians page 1" do
# expects all the musicians
- results = Search.musician_filter({page: 1})
+ results = Search.musician_filter({page: 1, score_limit: Search::TEST_SCORE})
results.search_type.should == :musicians_filter
- results.results.count.should == @geomusicians.length
- results.results.should eq @geomusicians.reverse
+ results.results.count.should == @musicians.length
+ results.results.should eq @musicians.reverse
end
it "finds all musicians page 2" do
# expects no musicians (all fit on page 1)
- results = Search.musician_filter({page: 2})
+ results = Search.musician_filter({page: 2, score_limit: Search::TEST_SCORE})
results.search_type.should == :musicians_filter
results.results.count.should == 0
end
it "finds all musicians page 1 per_page 3" do
# expects three of the musicians
- results = Search.musician_filter({per_page: 3})
+ results = Search.musician_filter({per_page: 3, score_limit: Search::TEST_SCORE})
results.search_type.should == :musicians_filter
results.results.count.should == 3
- results.results.should eq @geomusicians.reverse.slice(0, 3)
+ results.results.should eq @musicians.reverse.slice(0, 3)
end
it "finds all musicians page 2 per_page 3" do
# expects two of the musicians
- results = Search.musician_filter({page: 2, per_page: 3})
+ results = Search.musician_filter({page: 2, per_page: 3, score_limit: Search::TEST_SCORE})
results.search_type.should == :musicians_filter
- results.results.count.should == 2
- results.results.should eq @geomusicians.reverse.slice(3, 3)
+ results.results.count.should == 3
+ results.results.should eq @musicians.reverse.slice(3, 3)
end
it "finds all musicians page 3 per_page 3" do
# expects two of the musicians
- results = Search.musician_filter({page: 3, per_page: 3})
+ results = Search.musician_filter({page: 3, per_page: 3, score_limit: Search::TEST_SCORE})
results.search_type.should == :musicians_filter
results.results.count.should == 0
end
@@ -146,7 +149,7 @@ describe 'Musician search' do
f3.save
# @user2.followers.concat([@user3, @user4, @user2])
- results = Search.musician_filter({ :per_page => @musicians.size }, @user3)
+ results = Search.musician_filter({ :per_page => @musicians.size, score_limit: Search::TEST_SCORE, orderby: 'followed'}, @user3)
expect(results.results[0].id).to eq(@user2.id)
# check the follower count for given entry
@@ -157,7 +160,7 @@ describe 'Musician search' do
it 'paginates properly' do
# make sure pagination works right
- params = { :per_page => 2, :page => 1 }
+ params = { :per_page => 2, :page => 1 , score_limit: Search::TEST_SCORE}
results = Search.musician_filter(params)
expect(results.results.count).to be 2
end
@@ -218,7 +221,7 @@ describe 'Musician search' do
# create friendship record
Friendship.save(@user1.id, @user2.id)
# search on user2
- results = Search.musician_filter({}, @user2)
+ results = Search.musician_filter({score_limit: Search::TEST_SCORE}, @user2)
friend = results.results.detect { |mm| mm.id == @user1.id }
expect(friend).to_not be_nil
expect(results.friend_count(friend)).to be 1
@@ -239,7 +242,7 @@ describe 'Musician search' do
expect(recording.claimed_recordings.length).to be 1
expect(@user1.recordings.detect { |rr| rr == recording }).to_not be_nil
- results = Search.musician_filter({},@user1)
+ results = Search.musician_filter({score_limit: Search::TEST_SCORE},@user1)
# puts "====================== results #{results.inspect}"
uu = results.results.detect { |mm| mm.id == @user1.id }
expect(uu).to_not be_nil
@@ -257,7 +260,7 @@ describe 'Musician search' do
make_recording(@user1)
# order results by num recordings
- results = Search.musician_filter({ :orderby => 'plays' }, @user2)
+ results = Search.musician_filter({ orderby: 'plays', score_limit: Search::TEST_SCORE}, @user2)
# puts "========= results #{results.inspect}"
expect(results.results.length).to eq(2)
expect(results.results[0].id).to eq(@user1.id)
@@ -266,23 +269,24 @@ describe 'Musician search' do
# add more data and make sure order still correct
make_recording(@user3)
make_recording(@user3)
- results = Search.musician_filter({ :orderby => 'plays' }, @user2)
+ results = Search.musician_filter({ :orderby => 'plays', score_limit: Search::TEST_SCORE }, @user2)
expect(results.results.length).to eq(2)
expect(results.results[0].id).to eq(@user3.id)
expect(results.results[1].id).to eq(@user1.id)
end
it "by now playing" do
+ pending "these tests worked, so leaving them in, but we don't currently have 'Now Playing' in the find musicians screen"
# should get 1 result with 1 active session
make_session(@user1)
- results = Search.musician_filter({ :orderby => 'playing' }, @user2)
+ results = Search.musician_filter({ :orderby => 'playing', score_limit: Search::TEST_SCORE}, @user2)
expect(results.results.count).to be 1
expect(results.results.first.id).to eq(@user1.id)
# should get 2 results with 2 active sessions
# sort order should be created_at DESC
make_session(@user3)
- results = Search.musician_filter({ :orderby => 'playing' }, @user2)
+ results = Search.musician_filter({ :orderby => 'playing', score_limit: Search::TEST_SCORE}, @user2)
expect(results.results.count).to be 2
expect(results.results[0].id).to eq(@user3.id)
expect(results.results[1].id).to eq(@user1.id)
@@ -299,7 +303,7 @@ describe 'Musician search' do
@user1.reload
ii = @user1.instruments.detect { |inst| inst.id == 'tuba' }
expect(ii).to_not be_nil
- results = Search.musician_filter({ :instrument => ii.id })
+ results = Search.musician_filter({ :instrument => ii.id, score_limit: Search::TEST_SCORE })
results.results.each do |rr|
expect(rr.instruments.detect { |inst| inst.id=='tuba' }.id).to eq(ii.id)
end
@@ -313,13 +317,13 @@ describe 'Musician search' do
# short distance
results = Search.musician_filter({ :per_page => num,
:distance => 10,
- :city => 'Apex' }, @user1)
+ :city => 'Apex', score_limit: Search::TEST_SCORE }, @user1)
expect(results.results.count).to be num
# long distance
results = Search.musician_filter({ :per_page => num,
:distance => 1000,
:city => 'Miami',
- :state => 'FL' }, @user1)
+ :state => 'FL', score_limit: Search::TEST_SCORE }, @user1)
expect(results.results.count).to be num
end
@@ -327,14 +331,14 @@ describe 'Musician search' do
pending 'distance search changes'
expect(@user1.lat).to_not be_nil
# uses the location of @user1
- results = Search.musician_filter({ :distance => 10, :per_page => User.musicians.count }, @user1)
+ results = Search.musician_filter({ :distance => 10, :per_page => User.musicians.count, score_limit: Search::TEST_SCORE }, @user1)
expect(results.results.count).to be User.musicians.count
end
it "finds no musicians within a given distance of location" do
pending 'distance search changes'
expect(@user1.lat).to_not be_nil
- results = Search.musician_filter({ :distance => 10, :city => 'San Francisco' }, @user1)
+ results = Search.musician_filter({ :distance => 10, :city => 'San Francisco', score_limit: Search::TEST_SCORE }, @user1)
expect(results.results.count).to be 0
end
diff --git a/ruby/spec/jam_ruby/models/score_history_spec.rb b/ruby/spec/jam_ruby/models/score_history_spec.rb
index 67fcdae11..8c16dfc0c 100644
--- a/ruby/spec/jam_ruby/models/score_history_spec.rb
+++ b/ruby/spec/jam_ruby/models/score_history_spec.rb
@@ -38,6 +38,7 @@ describe ScoreHistory do
score_history.from_user_id.should == score1.auserid
score_history.from_latency_tester_id.should == score1.alatencytestid
score_history.from_addr.should == score1.aaddr
+ score_history.from_locidispid.should == score1.alocidispid
score_history.from_isp.should == austin[:jamisp].jam_company.company
score_history.from_country.should == austin[:geoiplocation].countrycode
score_history.from_region.should == austin[:geoiplocation].region
@@ -49,6 +50,7 @@ describe ScoreHistory do
score_history.to_user_id.should == score1.buserid
score_history.to_latency_tester_id.should == score1.blatencytestid
score_history.to_addr.should == score1.baddr
+ score_history.to_locidispid.should == score1.blocidispid
score_history.to_isp.should == dallas[:jamisp].jam_company.company
score_history.to_country.should == dallas[:geoiplocation].countrycode
score_history.to_region.should == dallas[:geoiplocation].region
diff --git a/ruby/spec/jam_ruby/models/score_spec.rb b/ruby/spec/jam_ruby/models/score_spec.rb
index c360cf881..195642167 100644
--- a/ruby/spec/jam_ruby/models/score_spec.rb
+++ b/ruby/spec/jam_ruby/models/score_spec.rb
@@ -10,141 +10,305 @@ describe Score do
let(:latency_tester2) { FactoryGirl.create(:latency_tester) }
let(:score_with_latency_tester) { s1, s2 = Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo', { alatencytestid: latency_tester1.id, blatencytestid: latency_tester2.id}); s1 }
- before do
- Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo')
- Score.createx(1234, 'anodeid', 0x01020304, 3456, 'cnodeid', 0x03040506, 30, nil)
- Score.createx(1234, 'anodeid', 0x01020304, 3456, 'cnodeid', 0x03040506, 40, Time.new.utc-3600)
- end
- it "count" do
- Score.count.should == 6
- end
- it 'a to b' do
- s = Score.where(alocidispid: 1234, blocidispid: 2345).limit(1).first
- s.should_not be_nil
- s.alocidispid.should == 1234
- s.anodeid.should eql('anodeid')
- s.aaddr.should == 0x01020304
- s.blocidispid.should == 2345
- s.bnodeid.should eql('bnodeid')
- s.baddr.should == 0x02030405
- s.score.should == 20
- s.scorer.should == 0
- s.score_dt.should_not be_nil
- s.scoring_data.should eq('foo')
- end
-
- it 'b to a' do
- s = Score.where(alocidispid: 2345, blocidispid: 1234).limit(1).first
- s.should_not be_nil
- s.alocidispid.should == 2345
- s.anodeid.should eql('bnodeid')
- s.aaddr.should == 0x02030405
- s.blocidispid.should == 1234
- s.bnodeid.should eql('anodeid')
- s.baddr.should == 0x01020304
- s.score.should == 20
- s.scorer.should == 1
- s.score_dt.should_not be_nil
- s.scoring_data.should be_nil
- end
-
- it 'a to c' do
- s = Score.where(alocidispid: 1234, blocidispid: 3456).limit(1).first
- s.should_not be_nil
- s.alocidispid.should == 1234
- s.anodeid.should eql('anodeid')
- s.aaddr.should == 0x01020304
- s.blocidispid.should == 3456
- s.bnodeid.should eql('cnodeid')
- s.baddr.should == 0x03040506
- s.score.should == 30
- s.scorer.should == 0
- s.score_dt.should_not be_nil
- s.scoring_data.should be_nil
- end
-
- it 'c to a' do
- s = Score.where(alocidispid: 3456, blocidispid: 1234).limit(1).first
- s.should_not be_nil
- s.alocidispid.should == 3456
- s.anodeid.should eql('cnodeid')
- s.aaddr.should == 0x03040506
- s.blocidispid.should == 1234
- s.bnodeid.should eql('anodeid')
- s.baddr.should == 0x01020304
- s.score.should == 30
- s.scorer.should == 1
- s.score_dt.should_not be_nil
- s.scoring_data.should be_nil
- end
-
- it 'delete a to c' do
- Score.deletex(1234, 3456)
- Score.count.should == 2
- Score.where(alocidispid: 1234, blocidispid: 3456).limit(1).first.should be_nil
- Score.where(alocidispid: 3456, blocidispid: 1234).limit(1).first.should be_nil
- Score.where(alocidispid: 1234, blocidispid: 2345).limit(1).first.should_not be_nil
- Score.where(alocidispid: 2345, blocidispid: 1234).limit(1).first.should_not be_nil
- end
-
- it 'findx' do
- Score.findx(1234, 1234).should == -1
- Score.findx(1234, 2345).should == 20
- Score.findx(1234, 3456).should == 30
-
- Score.findx(2345, 1234).should == 20
- Score.findx(2345, 2345).should == -1
- Score.findx(2345, 3456).should == -1
-
- Score.findx(3456, 1234).should == 30
- Score.findx(3456, 2345).should == -1
- Score.findx(3456, 3456).should == -1
- end
-
- it "test shortcut for making scores from connections" do
- user1 = FactoryGirl.create(:user)
- conn1 = FactoryGirl.create(:connection, user: user1, addr: 0x01020304, locidispid: 5)
- user2 = FactoryGirl.create(:user)
- conn2 = FactoryGirl.create(:connection, user: user2, addr: 0x11121314, locidispid: 6)
- user3 = FactoryGirl.create(:user)
- conn3 = FactoryGirl.create(:connection, user: user3, addr: 0x21222324, locidispid: 7)
-
- Score.findx(5, 6).should == -1
- Score.findx(6, 5).should == -1
- Score.findx(5, 7).should == -1
- Score.findx(7, 5).should == -1
- Score.findx(6, 7).should == -1
- Score.findx(7, 6).should == -1
-
- Score.score_conns(conn1, conn2, 12)
- Score.score_conns(conn1, conn3, 13)
- Score.score_conns(conn2, conn3, 23)
-
- Score.findx(5, 6).should == 12
- Score.findx(6, 5).should == 12
- Score.findx(5, 7).should == 13
- Score.findx(7, 5).should == 13
- Score.findx(6, 7).should == 23
- Score.findx(7, 6).should == 23
- end
-
- describe "createx" do
- it "creates with user info" do
- score_with_user.touch
- score_with_user.auserid.should == user1.id
- score_with_user.buserid.should == user2.id
- score_with_user.alatencytestid.should be_nil
- score_with_user.blatencytestid.should be_nil
+ describe "with default scores" do
+ before do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 3456, 'cnodeid', 0x03040506, 30, nil)
+ Score.createx(1234, 'anodeid', 0x01020304, 3456, 'cnodeid', 0x03040506, 40, Time.new.utc-3600)
end
- it "creates with latency-tester info" do
- score_with_latency_tester.touch
- score_with_latency_tester.auserid.should be_nil
- score_with_latency_tester.buserid.should be_nil
- score_with_latency_tester.alatencytestid.should == latency_tester1.id
- score_with_latency_tester.blatencytestid.should == latency_tester2.id
+
+ it "count" do
+ Score.count.should == 6
+ end
+
+ it 'a to b' do
+ s = Score.where(alocidispid: 1234, blocidispid: 2345).limit(1).first
+ s.should_not be_nil
+ s.alocidispid.should == 1234
+ s.anodeid.should eql('anodeid')
+ s.aaddr.should == 0x01020304
+ s.blocidispid.should == 2345
+ s.bnodeid.should eql('bnodeid')
+ s.baddr.should == 0x02030405
+ s.score.should == 20
+ s.scorer.should == 0
+ s.score_dt.should_not be_nil
+ s.scoring_data.should eq('foo')
+ end
+
+ it 'b to a' do
+ s = Score.where(alocidispid: 2345, blocidispid: 1234).limit(1).first
+ s.should_not be_nil
+ s.alocidispid.should == 2345
+ s.anodeid.should eql('bnodeid')
+ s.aaddr.should == 0x02030405
+ s.blocidispid.should == 1234
+ s.bnodeid.should eql('anodeid')
+ s.baddr.should == 0x01020304
+ s.score.should == 20
+ s.scorer.should == 1
+ s.score_dt.should_not be_nil
+ s.scoring_data.should be_nil
+ end
+
+ it 'a to c' do
+ s = Score.where(alocidispid: 1234, blocidispid: 3456).limit(1).first
+ s.should_not be_nil
+ s.alocidispid.should == 1234
+ s.anodeid.should eql('anodeid')
+ s.aaddr.should == 0x01020304
+ s.blocidispid.should == 3456
+ s.bnodeid.should eql('cnodeid')
+ s.baddr.should == 0x03040506
+ s.score.should == 30
+ s.scorer.should == 0
+ s.score_dt.should_not be_nil
+ s.scoring_data.should be_nil
+ end
+
+ it 'c to a' do
+ s = Score.where(alocidispid: 3456, blocidispid: 1234).limit(1).first
+ s.should_not be_nil
+ s.alocidispid.should == 3456
+ s.anodeid.should eql('cnodeid')
+ s.aaddr.should == 0x03040506
+ s.blocidispid.should == 1234
+ s.bnodeid.should eql('anodeid')
+ s.baddr.should == 0x01020304
+ s.score.should == 30
+ s.scorer.should == 1
+ s.score_dt.should_not be_nil
+ s.scoring_data.should be_nil
+ end
+
+ it 'delete a to c' do
+ Score.deletex(1234, 3456)
+ Score.count.should == 2
+ Score.where(alocidispid: 1234, blocidispid: 3456).limit(1).first.should be_nil
+ Score.where(alocidispid: 3456, blocidispid: 1234).limit(1).first.should be_nil
+ Score.where(alocidispid: 1234, blocidispid: 2345).limit(1).first.should_not be_nil
+ Score.where(alocidispid: 2345, blocidispid: 1234).limit(1).first.should_not be_nil
+ end
+
+ it 'findx' do
+ Score.findx(1234, 1234).should == -1
+ Score.findx(1234, 2345).should == 20
+ Score.findx(1234, 3456).should == 30
+
+ Score.findx(2345, 1234).should == 20
+ Score.findx(2345, 2345).should == -1
+ Score.findx(2345, 3456).should == -1
+
+ Score.findx(3456, 1234).should == 30
+ Score.findx(3456, 2345).should == -1
+ Score.findx(3456, 3456).should == -1
+ end
+
+ it "test shortcut for making scores from connections" do
+ user1 = FactoryGirl.create(:user)
+ conn1 = FactoryGirl.create(:connection, user: user1, addr: 0x01020304, locidispid: 5)
+ user2 = FactoryGirl.create(:user)
+ conn2 = FactoryGirl.create(:connection, user: user2, addr: 0x11121314, locidispid: 6)
+ user3 = FactoryGirl.create(:user)
+ conn3 = FactoryGirl.create(:connection, user: user3, addr: 0x21222324, locidispid: 7)
+
+ Score.findx(5, 6).should == -1
+ Score.findx(6, 5).should == -1
+ Score.findx(5, 7).should == -1
+ Score.findx(7, 5).should == -1
+ Score.findx(6, 7).should == -1
+ Score.findx(7, 6).should == -1
+
+ Score.score_conns(conn1, conn2, 12)
+ Score.score_conns(conn1, conn3, 13)
+ Score.score_conns(conn2, conn3, 23)
+
+ Score.findx(5, 6).should == 12
+ Score.findx(6, 5).should == 12
+ Score.findx(5, 7).should == 13
+ Score.findx(7, 5).should == 13
+ Score.findx(6, 7).should == 23
+ Score.findx(7, 6).should == 23
+ end
+
+ describe "createx" do
+ it "creates with user info" do
+ score_with_user.touch
+ score_with_user.auserid.should == user1.id
+ score_with_user.buserid.should == user2.id
+ score_with_user.alatencytestid.should be_nil
+ score_with_user.blatencytestid.should be_nil
+ end
+
+ it "creates with latency-tester info" do
+ score_with_latency_tester.touch
+ score_with_latency_tester.auserid.should be_nil
+ score_with_latency_tester.buserid.should be_nil
+ score_with_latency_tester.alatencytestid.should == latency_tester1.id
+ score_with_latency_tester.blatencytestid.should == latency_tester2.id
+ end
+ end
+ end
+
+ # current_scores is a view that tries to take the median of up to the last 5 entries
+ describe "current_scores" do
+ it "works with empty data set" do
+ result = Score.connection.execute('SELECT * FROM current_scores')
+ result.check
+ result.ntuples.should == 0
+ end
+
+ it "works with one score" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo')
+ result = Score.connection.execute('SELECT * FROM current_scores')
+ result.check
+ result.ntuples.should == 2
+ result[0]['alocidispid'].to_i.should == 1234
+ result[0]['scorer'].to_i.should == 0
+ result[1]['alocidispid'].to_i.should == 2345
+ result[1]['scorer'].to_i.should == 1
+ end
+
+ it "works with two scores in same location" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo') # median
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 25, nil, 'foo')
+
+ result = Score.connection.execute('SELECT * FROM current_scores')
+ result.check
+ result.ntuples.should == 2
+ result[0]['score'].to_i.should == 20
+ result[1]['score'].to_i.should == 20
+ end
+
+ it "works with three scores in same location" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 25, nil, 'foo') # median
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 30, nil, 'foo')
+
+ result = Score.connection.execute('SELECT * FROM current_scores')
+ result.check
+ result.ntuples.should == 2
+ result[0]['score'].to_i.should == 25
+ result[1]['score'].to_i.should == 25
+ end
+
+ it "works with six scores in same location" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo') # we'll make sure this is old, so it won't be in the set
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 25, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 30, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 31, nil, 'foo')# median
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 32, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 33, nil, 'foo')
+
+ Score.connection.execute("UPDATE scores set created_at = TIMESTAMP '#{1.days.ago}' WHERE score = 20").cmdtuples.should == 2
+
+ result = Score.connection.execute('SELECT * FROM current_scores')
+ result.check
+ result.ntuples.should == 2
+ result[0]['score'].to_i.should == 31
+ result[1]['score'].to_i.should == 31
+
+ # now push back score with 33 to the very back, which will shift the median up to 30
+ Score.connection.execute("UPDATE scores set created_at = TIMESTAMP '#{2.days.ago}' WHERE score = 33").check
+
+ result = Score.connection.execute('SELECT * FROM current_scores')
+ result.check
+ result.ntuples.should == 2
+ result[0]['score'].to_i.should == 30
+ result[1]['score'].to_i.should == 30
+ end
+
+ it "works with one score each in different locations" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo') # median
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 25, nil, 'foo')
+
+ result = Score.connection.execute('SELECT * FROM current_scores ORDER BY score')
+ result.check
+ result.ntuples.should == 4
+
+ result[0]['score'].to_i.should == 20
+ result[1]['score'].to_i.should == 20
+ result[2]['score'].to_i.should == 25
+ result[3]['score'].to_i.should == 25
+ end
+
+ it "works with multiple scores in different locations" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo') # median
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 25, nil, 'foo') # median
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 30, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 35, nil, 'foo')
+
+ result = Score.connection.execute('SELECT * FROM current_scores ORDER BY score')
+ result.check
+ result.ntuples.should == 4
+
+ result[0]['score'].to_i.should == 20
+ result[1]['score'].to_i.should == 20
+ result[2]['score'].to_i.should == 25
+ result[3]['score'].to_i.should == 25
+ end
+
+ it "works with multiple scores in different locations" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 25, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 30, nil, 'foo') # median
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 35, nil, 'foo') # median
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 40, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 45, nil, 'foo')
+
+ result = Score.connection.execute('SELECT * FROM current_scores ORDER BY score')
+ result.check
+ result.ntuples.should == 4
+
+ result[0]['score'].to_i.should == 30
+ result[1]['score'].to_i.should == 30
+ result[2]['score'].to_i.should == 35
+ result[3]['score'].to_i.should == 35
+
+
+ end
+
+ it "works with over 6 scores in different locations" do
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 20, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 25, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 30, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 35, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 40, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 45, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 45, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 50, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 55, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 60, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2345, 'bnodeid', 0x02030405, 65, nil, 'foo')
+ Score.createx(1234, 'anodeid', 0x01020304, 2346, 'bnodeid', 0x02030405, 70, nil, 'foo')
+
+ Score.connection.execute("UPDATE scores set created_at = TIMESTAMP '#{1.days.ago}' WHERE score = 20 OR score = 25").cmdtuples.should == 4
+
+ result = Score.connection.execute('SELECT * FROM current_scores ORDER BY score')
+ result.check
+ result.ntuples.should == 4
+
+ result[0]['score'].to_i.should == 45
+ result[1]['score'].to_i.should == 45
+ result[2]['score'].to_i.should == 50
+ result[3]['score'].to_i.should == 50
+
+
+ Score.connection.execute("UPDATE scores set created_at = TIMESTAMP '#{2.days.ago}' WHERE score = 65 OR score = 70").cmdtuples.should == 4
+
+ result = Score.connection.execute('SELECT * FROM current_scores ORDER BY score')
+ result.check
+ result.ntuples.should == 4
+
+ result[0]['score'].to_i.should == 40
+ result[1]['score'].to_i.should == 40
+ result[2]['score'].to_i.should == 45
+ result[3]['score'].to_i.should == 45
+
+
end
end
diff --git a/ruby/spec/jam_ruby/resque/music_session_scheduler_spec.rb b/ruby/spec/jam_ruby/resque/music_session_scheduler_spec.rb
index ac4d95146..af872943b 100644
--- a/ruby/spec/jam_ruby/resque/music_session_scheduler_spec.rb
+++ b/ruby/spec/jam_ruby/resque/music_session_scheduler_spec.rb
@@ -18,8 +18,8 @@ describe "MusicSessionScheduler" do
MusicSession.all.count.should == 1
- # end the session
- ms.session_removed_at = Time.now
+ # move the session back more than 4 hours
+ ms.scheduled_start = Time.now - 5.hours
ms.save!
# run the scheduler again
@@ -27,7 +27,6 @@ describe "MusicSessionScheduler" do
MusicSession.all.count.should == 2
- MusicSession.where(:session_removed_at => nil).count.should == 1
MusicSession.where(:next_session_scheduled => true).count.should == 1
end
@@ -40,7 +39,7 @@ describe "MusicSessionScheduler" do
@scheduler.run
MusicSession.all.count.should == 1
- ms.session_removed_at = Time.now
+ ms.scheduled_start = Time.now - 3.hours
ms.save!
@scheduler.run
diff --git a/web/Rakefile b/web/Rakefile
index d120b3602..f4019acfc 100644
--- a/web/Rakefile
+++ b/web/Rakefile
@@ -2,7 +2,10 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+#require 'resque/tasks'
+#require 'resque/scheduler/tasks'
require 'resque/tasks'
+require 'resque/scheduler/tasks'
require File.expand_path('../config/application', __FILE__)
SampleApp::Application.load_tasks
diff --git a/web/app/assets/javascripts/accounts_session_detail.js b/web/app/assets/javascripts/accounts_session_detail.js
index 76f9b2401..a148f4241 100644
--- a/web/app/assets/javascripts/accounts_session_detail.js
+++ b/web/app/assets/javascripts/accounts_session_detail.js
@@ -21,6 +21,8 @@
var $templateOpenSlots = null;
var instrument_logo_map = context.JK.getInstrumentIconMap24();
var invitationDialog = null;
+ var inviteMusiciansUtil = null;
+ var friendInput=null;
var LATENCY = {
@@ -42,7 +44,11 @@
function inviteMusicians(e) {
e.preventDefault();
- invitationDialog.showEmailDialog();
+ friendInput = inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians',
+ sessionId);
+ inviteMusiciansUtil.loadFriends();
+ $(friendInput).show();
+ // invitationDialog.showEmailDialog();
}
function cancelRsvpRequest(e) {
@@ -120,6 +126,7 @@
$sessionPageBtn.on('click', openSessionPage);
$screen.find(".approveRsvpRequest").on('click', approveRsvpRequest);
$screen.find(".declineRsvpRequest").on('click', declineRsvpRequest);
+ $(friendInput).focus(function() { $(this).val(''); })
$screen.find(".cancelSessionRsvp").on('click', function(e) {
e.preventDefault();
@@ -393,6 +400,10 @@
$sessionDetail = $screen.find("#account-session-detail-div");
$shareUrl = $screen.find('.share-url');
invitationDialog = invitationDlg;
+
+ inviteMusiciansUtil = new JK.InviteMusiciansUtil(JK.app);
+ inviteMusiciansUtil.initialize(JK.FriendSelectorDialogInstance);
+
$templateOpenSlots = $('#template-open-slots');
}
diff --git a/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js b/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js
index 228b0077f..895927135 100644
--- a/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js
+++ b/web/app/assets/javascripts/dialog/rsvpSubmitDialog.js
@@ -28,11 +28,15 @@
$('.schedule-recurrence', $dialog).html("Recurs " + response.recurring_mode + " on this day at this time");
}
+ var hasOpenSlots = response.open_slots && response.open_slots.length > 0;
+
+
if (response['is_unstructured_rsvp?']) {
- $('.rsvp-instruments', $dialog).append('Any Instrument
');
+ var checkedState = hasOpenSlots ? '' : 'checked="checked"'
+ $('.rsvp-instruments', $dialog).append('Play Any Instrument You Like
');
}
- if (response.open_slots && response.open_slots.length > 0) {
+ if (hasOpenSlots) {
$.each(response.open_slots, function(index, val) {
var instrument = val.instrument_id;
diff --git a/web/app/assets/javascripts/findMusician.js b/web/app/assets/javascripts/findMusician.js
index f29dc9afb..ea8b9f564 100644
--- a/web/app/assets/javascripts/findMusician.js
+++ b/web/app/assets/javascripts/findMusician.js
@@ -12,6 +12,7 @@
var did_show_musician_page = false;
var page_num=1, page_count=0;
var textMessageDialog = null;
+ var $results = null;
function loadMusicians(queryString) {
// squelch nulls and undefines
@@ -88,8 +89,8 @@
// these are raw scores as reported by client (round trip times)
if (score == null) return "purple";
if (0 < score && score <= 40) return "green";
- if (40 < score && score <= 80) return "yellow";
- if (80 < score && score <= 120) return "red";
+ if (40 < score && score <= 70) return "yellow";
+ if (70 < score && score <= 100) return "red";
return "blue";
}
@@ -97,11 +98,26 @@
// these are raw scores as reported by client (round trip times)
if (score == null) return "missing";
if (0 < score && score <= 40) return "good";
- if (40 < score && score <= 80) return "moderate";
- if (80 < score && score <= 120) return "poor";
+ if (40 < score && score <= 70) return "moderate";
+ if (70 < score && score <= 100) return "poor";
return "unacceptable";
}
+ function formatLocation(musician) {
+ if(musician.city && musician.state) {
+ return musician.city + ', ' + musician.regionname
+ }
+ else if(musician.city) {
+ return musician.city
+ }
+ else if(musician.state) {
+ return musician.regionname
+ }
+ else {
+ return 'Location Unavailable'
+ }
+ }
+
function renderMusicians() {
var ii, len;
var mTemplate = $('#template-find-musician-row').html();
@@ -110,6 +126,7 @@
var mVals, musician, renderings='';
var instr_logos, instr;
var follows, followVals, aFollow;
+ var myAudioLatency = musicianList.my_audio_latency;
for (ii=0, len=musicians.length; ii < len; ii++) {
musician = musicians[ii];
@@ -149,12 +166,12 @@
};
var musician_actions = context.JK.fillTemplate(aTemplate, actionVals);
- var joined_score = musician['joined_score']
+ var full_score = musician['full_score'];
mVals = {
avatar_url: context.JK.resolveAvatarUrl(musician.photo_url),
profile_url: "/client#/profile/" + musician.id,
musician_name: musician.name,
- musician_location: musician.city + ', ' + musician.state,
+ musician_location: formatLocation(musician),
instruments: instr_logos,
biography: musician['biography'],
follow_count: musician['follow_count'],
@@ -164,14 +181,27 @@
musician_id: musician['id'],
musician_follow_template: follows,
musician_action_template: musician_actions,
- musician_one_way_score: score_to_text(joined_score),
- musician_score_color: score_to_color(joined_score),
- musician_score_color_alt: score_to_color_alt(joined_score)
+ musician_one_way_score: score_to_text(full_score),
+ musician_score_color: score_to_color(full_score),
+ musician_score_color_alt: score_to_color_alt(full_score)
+
};
- var musician_row = context.JK.fillTemplate(mTemplate, mVals);
- renderings += musician_row;
+ var $rendering = $(context.JK.fillTemplate(mTemplate, mVals))
+
+ var $offsetParent = $results.closest('.content');
+ var options = {positions: ['top', 'bottom', 'right', 'left'], offsetParent: $offsetParent};
+ var scoreOptions = {positions: ['right', 'top', 'bottom', 'left'], offsetParent: $offsetParent, width:'600px'};
+ context.JK.helpBubble($('.follower-count', $rendering), 'musician-follower-count', {}, options);
+ context.JK.helpBubble($('.friend-count', $rendering), 'musician-friend-count', {}, options);
+ context.JK.helpBubble($('.recording-count', $rendering), 'musician-recording-count', {}, options);
+ context.JK.helpBubble($('.session-count', $rendering), 'musician-session-count', {}, options);
+ context.JK.helpBubble($('.score-count', $rendering), 'musician-score-count',
+ {full_score: full_score ? Math.round(full_score / 2) : null, my_gear_latency: myAudioLatency, their_gear_latency:musician['audio_latency'], internet_latency: musician['score']},
+ scoreOptions)
+
+ $results.append($rendering);
}
- $('#musician-filter-results').append(renderings);
+
$('.search-m-friend').on('click', friendMusician);
$('.search-m-follow').on('click', followMusician);
@@ -279,6 +309,8 @@
};
app.bindScreen('musicians', screenBindings);
+ $results = $('#musician-filter-results');
+
events();
}
diff --git a/web/app/assets/javascripts/inviteMusicians.js b/web/app/assets/javascripts/inviteMusicians.js
index 604641e1d..60d60b067 100644
--- a/web/app/assets/javascripts/inviteMusicians.js
+++ b/web/app/assets/javascripts/inviteMusicians.js
@@ -59,6 +59,8 @@
addInvitation(dd.name, dd.id);
});
}).fail(app.ajaxError);
+
+ return friendInput;
}
this.clearSelections = function() {
@@ -133,7 +135,7 @@
} else {
$(friendInput).select();
- context.alert('Invitation already exists for this musician.');
+ // context.alert('Invitation already exists for this musician.');
}
}
diff --git a/web/app/assets/javascripts/notificationPanel.js b/web/app/assets/javascripts/notificationPanel.js
index d16b674b0..2c50316de 100644
--- a/web/app/assets/javascripts/notificationPanel.js
+++ b/web/app/assets/javascripts/notificationPanel.js
@@ -309,10 +309,15 @@
}
var $action_btn = $notification.find($btnNotificationAction);
- $action_btn.text(actionText);
- $action_btn.click(function() {
- callback(payload);
- });
+ if (actionText === '') {
+ $action_btn.hide();
+ }
+ else {
+ $action_btn.text(actionText);
+ $action_btn.click(function() {
+ callback(payload);
+ });
+ }
}
else if (type === context.JK.MessageType.MUSICIAN_RECORDING_SAVED || type === context.JK.MessageType.BAND_RECORDING_SAVED) {
diff --git a/web/app/assets/javascripts/scheduled_session.js b/web/app/assets/javascripts/scheduled_session.js
index 63c9713b4..7b7de7843 100644
--- a/web/app/assets/javascripts/scheduled_session.js
+++ b/web/app/assets/javascripts/scheduled_session.js
@@ -117,14 +117,14 @@
var firstSession = function() {
var $firstSession = $scheduledSessions.children().first().find('input[name="scheduled-session-info"]');
$firstSession.attr('checked', 'checked');
- createSessionSettings.selectedSessionId = $firstSession.attr('id');
+ createSessionSettings.selectedSessionId = $firstSession.attr('data-session-id');
};
if (createSessionSettings.selectedSessionId == null) {
firstSession();
}
else {
- var $selectedSession = $scheduledSessions.children().first().find('input[name="scheduled-session-info"][id="' + createSessionSettings.selectedSessionId + '"]');
+ var $selectedSession = $scheduledSessions.children().first().find('input[name="scheduled-session-info"][data-session-id="' + createSessionSettings.selectedSessionId + '"]');
if ($selectedSession.length)
$selectedSession.attr('checked', 'checked');
else
@@ -349,6 +349,7 @@
function beforeMoveStep1() {
if (createSessionSettings.createType == 'start-scheduled') {
+ createSessionSettings.selectedSessionId = $scheduledSessions.find('.iradio_minimal.checked input[name="scheduled-session-info"]').attr('data-session-id');
var session = scheduledSessions[createSessionSettings.selectedSessionId];
if(session == null) {
@@ -382,7 +383,7 @@
var startTime = new Date(session.scheduled_start);
var diffTime = startTime.getTime() - currentTime.getTime();
if (diffTime > ONE_HOUR) {
- var confirmDialog = new context.JK.ConfirmDialog(app, "Start Session Now",
+ var confirmDialog = new context.JK.ConfirmDialog(app, "START SESSION NOW",
"You are starting a session that is scheduled to begin more than one hour from now. Are you sure you want to do this?",
"Future Session", moveToFinish);
confirmDialog.initialize();
@@ -416,7 +417,7 @@
createSessionSettings.startTime = $startTimeList.val();
createSessionSettings.endTime = $endTimeList.val();
createSessionSettings.notations = [];
- createSessionSettings.selectedSessionId = $scheduledSessions.find('input[name="scheduled-session-info"][checked="checked"]').attr('id');
+ createSessionSettings.selectedSessionId = $scheduledSessions.find('.iradio_minimal.checked input[name="scheduled-session-info"]').attr('data-session-id');
createSessionSettings.timezone.value = $timezoneList.val();
createSessionSettings.timezone.label = $timezoneList.get(0).options[$timezoneList.get(0).selectedIndex].text;
createSessionSettings.recurring_mode.label = $recurringModeList.get(0).options[$recurringModeList.get(0).selectedIndex].text;
diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js
index 323a0ee84..25a5e0915 100644
--- a/web/app/assets/javascripts/session.js
+++ b/web/app/assets/javascripts/session.js
@@ -32,6 +32,7 @@
var playbackControls = null;
var promptLeave = false;
var rateSessionDialog = null;
+ var friendInput=null;
var rest = context.JK.Rest();
@@ -133,6 +134,7 @@
.done(function(){
initializeSession();
})
+
}
function notifyWithUserInfo(title , text, clientId) {
@@ -1354,7 +1356,10 @@
}
function inviteMusicians() {
- inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians', sessionId);
+ friendInput = inviteMusiciansUtil.inviteSessionUpdate('#update-session-invite-musicians',
+ sessionId);
+ inviteMusiciansUtil.loadFriends();
+ $(friendInput).show();
}
function events() {
@@ -1365,6 +1370,7 @@
$('#recording-start-stop').on('click', startStopRecording);
$('#open-a-recording').on('click', openRecording);
$('#session-invite-musicians').on('click', inviteMusicians);
+ $('#session-invite-musicians2').on('click', inviteMusicians);
$('#track-settings').click(function() {
configureTrackDialog.refresh();
configureTrackDialog.showVoiceChatPanel(true);
@@ -1376,6 +1382,7 @@
.on('pause', onPause)
.on('play', onPlay)
.on('change-position', onChangePlayPosition);
+ $(friendInput).focus(function() { $(this).val(''); })
}
this.initialize = function(localRecordingsDialogInstance, recordingFinishedDialogInstance, friendSelectorDialog) {
diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js
index b471e5a1f..4321cc183 100644
--- a/web/app/assets/javascripts/sessionList.js
+++ b/web/app/assets/javascripts/sessionList.js
@@ -21,9 +21,9 @@
var LATENCY = {
GOOD : {description: "GOOD", style: "latency-green", min: 0.0, max: 20.0},
- MEDIUM : {description: "MEDIUM", style: "latency-yellow", min: 20.0, max: 40.0},
- POOR : {description: "POOR", style: "latency-red", min: 40.0, max: 10000000000.0},
- UNREACHABLE: {description: "UNREACHABLE", style: "latency-grey", min: -1, max: -1},
+ MEDIUM : {description: "MEDIUM", style: "latency-yellow", min: 20.0, max: 35.0},
+ POOR : {description: "POOR", style: "latency-red", min: 35.0, max: 50},
+ UNACCEPTABLE: {description: "UNACCEPTABLE", style: "latency-grey", min: 50, max: 10000000},
UNKNOWN: {description: "UNKNOWN", style: "latency-grey", min: -2, max: -2}
};
@@ -350,7 +350,10 @@
}
function createLatency(user) {
- var latencyStyle = LATENCY.UNREACHABLE.style, latencyDescription = LATENCY.UNREACHABLE.description
+
+ var latencyStyle;
+ var latencyDescription;
+
if (user.id === context.JK.currentUserId) {
latencyStyle = LATENCY.GOOD.style, latencyDescription = LATENCY.GOOD.description;
}
@@ -358,24 +361,25 @@
else {
var latency = user.latency;
- if (!latency || latency === 1000) {
- // 1000 is a magical number returned by new scoring API to indicate one or more people in the session have an unknown score
+ if (!latency) {
latencyDescription = LATENCY.UNKNOWN.description;
latencyStyle = LATENCY.UNKNOWN.style;
}
+ else if (latency <= LATENCY.GOOD.max) {
+ latencyDescription = LATENCY.GOOD.description;
+ latencyStyle = LATENCY.GOOD.style;
+ }
+ else if (latency > LATENCY.MEDIUM.min && latency <= LATENCY.MEDIUM.max) {
+ latencyDescription = LATENCY.MEDIUM.description;
+ latencyStyle = LATENCY.MEDIUM.style;
+ }
+ else if (latency > LATENCY.POOR.min && latency <= LATENCY.UNACCEPTABLE.max) {
+ latencyDescription = LATENCY.POOR.description;
+ latencyStyle = LATENCY.POOR.style;
+ }
else {
- if (latency <= LATENCY.GOOD.max) {
- latencyDescription = LATENCY.GOOD.description;
- latencyStyle = LATENCY.GOOD.style;
- }
- else if (latency > LATENCY.MEDIUM.min && latency <= LATENCY.MEDIUM.max) {
- latencyDescription = LATENCY.MEDIUM.description;
- latencyStyle = LATENCY.MEDIUM.style;
- }
- else {
- latencyDescription = LATENCY.POOR.description;
- latencyStyle = LATENCY.POOR.style;
- }
+ latencyStyle = LATENCY.UNREACHABLE.style
+ latencyDescription = LATENCY.UNREACHABLE.description
}
}
diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js
index 872825c79..38785e099 100644
--- a/web/app/assets/javascripts/utils.js
+++ b/web/app/assets/javascripts/utils.js
@@ -106,12 +106,14 @@
if (!data) {
data = {}
}
+ if(!options) {
+ options = {}
+ }
+
var helpText = context._.template($('#template-help-' + templateName).html(), data, { variable: 'data' });
-
var holder = $('');
holder.append(helpText);
-
context.JK.hoverBubble($element, helpText, options);
}
@@ -183,7 +185,7 @@
cornerRadius: 0,
cssStyles: {
fontSize: '11px',
- color: 'white',
+ color: '#cccccc',
whiteSpace: 'normal'
}
};
diff --git a/web/app/assets/javascripts/web/session_info.js b/web/app/assets/javascripts/web/session_info.js
index 7e8ef3dac..d95684437 100644
--- a/web/app/assets/javascripts/web/session_info.js
+++ b/web/app/assets/javascripts/web/session_info.js
@@ -174,7 +174,10 @@
$('.call-to-action').html('Tell the session organizer if you can no longer join this session');
$btnAction.html('CANCEL RSVP');
$btnAction.click(function(e) {
- ui.launchRsvpCancelDialog(musicSessionId, rsvp.id);
+ ui.launchRsvpCancelDialog(musicSessionId, rsvp.id)
+ .one(EVENTS.RSVP_CANCELED, function() {
+ location.reload();
+ });
});
}
}
@@ -184,7 +187,10 @@
$('.call-to-action').html("Tell the session organizer you'd like to play in this session");
$btnAction.html('RSVP NOW!');
$btnAction.click(function(e) {
- ui.launchRsvpSubmitDialog(musicSessionId);
+ ui.launchRsvpSubmitDialog(musicSessionId)
+ .one(EVENTS.RSVP_SUBMITTED, function() {
+ location.reload();
+ })
});
}
})
@@ -201,14 +207,6 @@
});
addLatencyDetails();
-
- $(document).on(EVENTS.RSVP_SUBMITTED, function() {
- location.reload();
- });
-
- $(document).on(EVENTS.RSVP_CANCELED, function() {
- location.reload();
- });
}
this.initialize = initialize;
diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css
index d6325a7c0..68b4073ce 100644
--- a/web/app/assets/stylesheets/client/client.css
+++ b/web/app/assets/stylesheets/client/client.css
@@ -53,6 +53,7 @@
*= require ./searchResults
*= require ./clientUpdate
*= require ./musician
+ *= require ./help
*= require ./jquery-ui-overrides
*= require web/audioWidgets
*= require web/recordings
diff --git a/web/app/assets/stylesheets/client/help.css.scss b/web/app/assets/stylesheets/client/help.css.scss
new file mode 100644
index 000000000..691bc7c74
--- /dev/null
+++ b/web/app/assets/stylesheets/client/help.css.scss
@@ -0,0 +1,43 @@
+.screen {
+ .bt-wrapper {
+ .bt-content {
+
+ color:#cccccc;
+
+ font-size:14px;
+
+ p {
+ font-size:14px;
+ }
+ ul {
+ font-size:14px;
+ }
+
+ li {
+ margin-left:1em;
+ margin-bottom:.5em;
+ }
+
+ .definition {
+ font-weight:bold;
+ }
+
+ .help-musician-score-count {
+ .measurement {
+
+ }
+
+ .measurement-value {
+ font-size:24px;
+ }
+
+ .measurement-absent {
+ font-style:italic;
+ font-size:12px;
+ display:block;
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/client/musician.css.scss b/web/app/assets/stylesheets/client/musician.css.scss
index 54a310ee9..9498cda70 100644
--- a/web/app/assets/stylesheets/client/musician.css.scss
+++ b/web/app/assets/stylesheets/client/musician.css.scss
@@ -24,6 +24,18 @@
}
}
+#musicians-screen {
+
+ .filter-element.desc.instrument-selector {
+ margin-left:2px;
+ float:left;
+
+ & + .dropdown-wrapper .dropdown-container {
+ width:150px;
+ }
+ }
+}
+
#musician-filter-results {
margin: 0 10px 0px 10px;
diff --git a/web/app/assets/stylesheets/web/main.css.scss b/web/app/assets/stylesheets/web/main.css.scss
index d3725237e..ab7a08f43 100644
--- a/web/app/assets/stylesheets/web/main.css.scss
+++ b/web/app/assets/stylesheets/web/main.css.scss
@@ -599,9 +599,6 @@ strong {
}
}
-body.jam.web.welcome .no-websocket-connection {
- display:none;
-}
-body.jam.web.register .no-websocket-connection {
+body.jam.web .no-websocket-connection {
display:none;
}
\ No newline at end of file
diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb
index 8859fcbe4..212a8e12b 100644
--- a/web/app/controllers/users_controller.rb
+++ b/web/app/controllers/users_controller.rb
@@ -228,9 +228,6 @@ class UsersController < ApplicationController
if !@user.nil? && !@user.errors.any?
UserMailer.welcome_message(@user).deliver
- sign_in @user
- redirect_to :client
- return
elsif !@user.nil?
# new user with validation errors;
logger.debug("#{@user} has errors. can not sign in until remedied. #{@user.errors.inspect}")
@@ -463,6 +460,9 @@ JS
end
def load_location(remote_ip, location = nil)
+ # useful if you need to repro something on 127.0.0.1
+ # remote_ip = ' 23.119.29.89'
+
@location = location
if @location.nil?
@@ -471,7 +471,6 @@ JS
@location[:country] = "US" if @location[:country].nil?
- # right now we only accept US signups for beta
@countriesx = MaxMindManager.countries
# populate regions based on current country
@regions = MaxMindManager.regions(@location[:country])
diff --git a/web/app/views/api_feeds/show.rabl b/web/app/views/api_feeds/show.rabl
index 140828833..e502fcbf7 100644
--- a/web/app/views/api_feeds/show.rabl
+++ b/web/app/views/api_feeds/show.rabl
@@ -60,7 +60,7 @@ glue :music_session do
attributes :id, :name, :location, :photo_url
}
- child(:active_music_session => :music_session) do
+ child(:active_music_session => :active_music_session) do
# only show mount info if fan_access is public. Eventually we'll also need to show this in other scenarios, like if invited
child({:mount => :mount}, :if => lambda { |music_session| music_session.fan_access}) {
attributes :id, :name, :sourced, :listeners, :bitrate, :subtype, :url
diff --git a/web/app/views/api_search/index.rabl b/web/app/views/api_search/index.rabl
index fd53ba9c2..e7120fca6 100644
--- a/web/app/views/api_search/index.rabl
+++ b/web/app/views/api_search/index.rabl
@@ -41,9 +41,13 @@ if @search.musicians_filter_search?
node :page_count do |foo|
@search.page_count
end
+
+ node :my_audio_latency do |user|
+ current_user.last_jam_audio_latency
+ end
child(:results => :musicians) {
- attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :musician, :photo_url, :biography, :joined_score
+ attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score, :audio_latency
node :is_friend do |musician|
@search.is_friend?(musician)
diff --git a/web/app/views/clients/_account_session_detail.html.haml b/web/app/views/clients/_account_session_detail.html.haml
index 6f14962e8..4d6ee95c0 100644
--- a/web/app/views/clients/_account_session_detail.html.haml
+++ b/web/app/views/clients/_account_session_detail.html.haml
@@ -16,7 +16,7 @@
.right
%a.cancel-rsvp.button-orange{href: "#"} CANCEL RSVP
%a.session-detail-page.button-orange{href: "#", rel:'external'} SESSION PAGE
- %a.invite-others.button-orange{href: "#"} INVITE OTHERS
+ %a.invite-others.button-orange{'layout-link' => 'select-invites','href' => "#"} INVITE OTHERS
.clearall
#account-session-detail-div
@@ -160,4 +160,4 @@
%script{type: 'text/template', id: 'template-account-session-latency'}
.latency{class: "{{data.latency_style}}"}
- {{data.latency_text}}
\ No newline at end of file
+ {{data.latency_text}}
diff --git a/web/app/views/clients/_account_session_properties.html.haml b/web/app/views/clients/_account_session_properties.html.haml
index 16d59f872..69a6364d5 100644
--- a/web/app/views/clients/_account_session_properties.html.haml
+++ b/web/app/views/clients/_account_session_properties.html.haml
@@ -80,7 +80,6 @@
Fan Access:
.right-column
%select#session-prop-fans-access
- %option{value: "listen-chat-band"} Fans may listen, chat with the band
%option{value: "listen-chat-each", selected: "selected"} Fans may listen, chat with each other
%option{value: "no-listen-chat"} Fans may not listen to session
.clearall.right-no-left
@@ -95,7 +94,6 @@
%option{value: "Standard"} Standard
%option{value: "Creative Commons"} Creative Commons
%option{value: "Offline"} Offline
- %option{value: "Jamtracks"} Jamtracks
.clearall.left-column
Notation Files:
.right-column
diff --git a/web/app/views/clients/_help.html.erb b/web/app/views/clients/_help.html.erb
index 9aad16a7c..1a531a89b 100644
--- a/web/app/views/clients/_help.html.erb
+++ b/web/app/views/clients/_help.html.erb
@@ -40,4 +40,42 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/app/views/clients/_musicians.html.erb b/web/app/views/clients/_musicians.html.erb
index 47da7d626..df1b044b4 100644
--- a/web/app/views/clients/_musicians.html.erb
+++ b/web/app/views/clients/_musicians.html.erb
@@ -1,5 +1,5 @@
-<%= content_tag(:div, :layout => 'screen', 'layout-id' => 'musicians', :class => "screen secondary") do -%>
+<%= content_tag(:div, :layout => 'screen', 'layout-id' => 'musicians', :class => "screen secondary", id: 'musicians-screen') do -%>
<%= content_tag(:div, :class => :content) do -%>
<%= content_tag(:div, :class => 'content-head') do -%>
<%= content_tag(:div, image_tag("content/icon_musicians.png", {:height => 19, :width => 19}), :class => 'content-icon') %>
@@ -56,13 +56,13 @@
-