diff --git a/db/manifest b/db/manifest index 004eb74e6..ad2c35ab5 100755 --- a/db/manifest +++ b/db/manifest @@ -201,4 +201,5 @@ current_scores_use_median.sql current_scores_ams_index_sms_index_use_user_instrument.sql locidispid_in_score_histories.sql define_environment_in_db.sql -drop_session_invite_constraint.sql \ No newline at end of file +drop_session_invite_constraint.sql +sms_index_single_session.sql \ No newline at end of file diff --git a/db/up/sms_index_single_session.sql b/db/up/sms_index_single_session.sql new file mode 100644 index 000000000..07c56b4d1 --- /dev/null +++ b/db/up/sms_index_single_session.sql @@ -0,0 +1,157 @@ +-- changelog: +-- * allow session_id to be passed to sms_index, which skips all the access questions, and just makes sure you'll get back that session, with user scores +-- * in both sms_index and ams_index, in the user tmp table, return also internet score and the other user's audio latency + +-- 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, session_id VARCHAR) 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; + + IF session_id = 'any' THEN + -- 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; + + ELSE + INSERT INTO sms_music_session_tmp SELECT DISTINCT id, NULL::INTEGER AS tag, NULL::INTEGER AS latency + FROM music_sessions + WHERE music_sessions.id = session_id; + END IF; + + -- 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, full_score INTEGER, audio_latency INTEGER, internet_score 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 AS full_score, s.a_audio_latency, s.score + 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; + + -- 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 AS full_score, s.a_audio_latency, s.score + 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.full_score) 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, full_score INTEGER, audio_latency INTEGER, internet_score 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 AS full_score, s.a_audio_latency, s.score + 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 AS full_score, s.a_audio_latency, s.score + 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.full_score) 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/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb index a7f70124b..441e031d8 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/scheduled_session_daily.html.erb @@ -74,7 +74,7 @@ <%= (sess.latency / 2).round %> ms - <% if sess.latency <= (APP_CONFIG.max_good_full_score * 2) %> + <% if sess.latency <= (APP_CONFIG.max_good_full_score) %> <%= image_tag("http://www.jamkazam.com/assets/content/icon_green_score.png", alt: 'good score icon') %> <% else %> <%= image_tag("http://www.jamkazam.com/assets/content/icon_yellow_score.png", alt: 'fair score icon') %> diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb index 9c9a5a07f..662512572 100644 --- a/ruby/lib/jam_ruby/models/active_music_session.rb +++ b/ruby/lib/jam_ruby/models/active_music_session.rb @@ -319,12 +319,9 @@ module JamRuby # initialize the two temporary tables we use to drive ams_index and ams_users def self.ams_init(current_user, options = {}) - client_id = options[:client_id] - - connection = Connection.where(user_id: current_user.id, client_id: client_id).first! - my_locidispid = connection.locidispid + my_locidispid = current_user.last_jam_locidispid # 13 is an average audio gear value we use if they have not qualified any gear - my_audio_latency = connection.last_jam_audio_latency || current_user.last_jam_audio_latency || 13 + my_audio_latency = current_user.last_jam_audio_latency || 13 locidispid_expr = my_locidispid ? "#{my_locidispid}::bigint" : '0::bigint' self.connection.execute("select ams_index('#{current_user.id}'::varchar, #{locidispid_expr}, #{my_audio_latency}::integer)").check @@ -420,7 +417,7 @@ module JamRuby # ams_init must be called first. # user.audio_latency / 2 , + other_user.audio_latency of them / 2, + network latency /2 def self.ams_users - return User.select('users.*, ams_users_tmp.music_session_id, ams_users_tmp.latency') + return User.select('users.*, ams_users_tmp.music_session_id, ams_users_tmp.full_score, ams_users_tmp.audio_latency, ams_users_tmp.internet_score') .joins( %Q{ INNER JOIN @@ -444,7 +441,7 @@ module JamRuby user_scores = {} music_session_users.each do |user| - user_scores[user.id] = {latency: user.latency} + user_scores[user.id] = {full_score: user.full_score, audio_latency: user.audio_latency, internet_score: user.internet_score} end [music_sessions, user_scores] diff --git a/ruby/lib/jam_ruby/models/generic_state.rb b/ruby/lib/jam_ruby/models/generic_state.rb index 546006794..d6c0bc687 100644 --- a/ruby/lib/jam_ruby/models/generic_state.rb +++ b/ruby/lib/jam_ruby/models/generic_state.rb @@ -6,6 +6,10 @@ module JamRuby validates :env, :inclusion => {:in => ['development', 'staging', 'production', 'test']} + def self.env + GenericState.singleton.env + end + def self.allow_emails? database_environment = singleton.env diff --git a/ruby/lib/jam_ruby/models/geo_ip_locations.rb b/ruby/lib/jam_ruby/models/geo_ip_locations.rb index 490ad79ca..1f8caeb50 100644 --- a/ruby/lib/jam_ruby/models/geo_ip_locations.rb +++ b/ruby/lib/jam_ruby/models/geo_ip_locations.rb @@ -51,7 +51,7 @@ module JamRuby end end - {city: city, state: state, country: country, addr: addr, locidispid: (locid.nil? || ispid.nil?) ? nil : locid*1000000+ispid} + {city: city, state: state, country: country, addr: addr, locidispid: (locid.nil? || ispid.nil?) ? nil : Score.compute_locidispid(locid, ispid) } end def self.createx(locid, countrycode, region, city, postalcode, latitude, longitude, metrocode, areacode) diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index a1e541e6f..c3255c586 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -493,7 +493,7 @@ module JamRuby # retrieve users that have approved RSVPs def approved_rsvps - User.find_by_sql(%Q{select distinct ON(u.id) u.id, u.photo_url, u.first_name, u.last_name, json_agg(ii.id) as instrument_ids, json_agg(ii.description) as instrument_descriptions, json_agg(rs.proficiency_level) as instrument_proficiencies, json_agg(rr.id) as rsvp_request_ids + User.find_by_sql(%Q{select distinct ON(u.id) u.id, u.photo_url, u.first_name, u.last_name, u.last_jam_audio_latency, json_agg(ii.id) as instrument_ids, json_agg(ii.description) as instrument_descriptions, json_agg(rs.proficiency_level) as instrument_proficiencies, json_agg(rr.id) as rsvp_request_ids from rsvp_slots rs inner join rsvp_requests_rsvp_slots rrrs on rrrs.rsvp_slot_id = rs.id inner join rsvp_requests rr on rrrs.rsvp_request_id = rr.id @@ -590,15 +590,14 @@ module JamRuby # initialize the two temporary tables we use to drive sms_index and sms_users def self.sms_init(current_user, options = {}) - client_id = options[:client_id] + session_id = options[:session_id] || 'any' - connection = Connection.where(user_id: current_user.id, client_id: client_id).first! - my_locidispid = connection.locidispid + my_locidispid = current_user.last_jam_locidispid # 13 is an average audio gear value we use if they have not qualified any gear - my_audio_latency = connection.last_jam_audio_latency || current_user.last_jam_audio_latency || 13 + my_audio_latency = current_user.last_jam_audio_latency || 13 locidispid_expr = my_locidispid ? "#{my_locidispid}::bigint" : '0::bigint' # Have to pass in zero; NULL fails silently in the stored proc - self.connection.execute("SELECT sms_index('#{current_user.id}'::varchar, #{locidispid_expr}, #{my_audio_latency}::integer)").check + self.connection.execute("SELECT sms_index('#{current_user.id}'::varchar, #{locidispid_expr}, #{my_audio_latency}::integer, #{ActiveRecord::Base.connection.quote(session_id)}::varchar)").check end # Generate a list of music sessions (that are active) filtered by genre, language, keyword, and sorted @@ -691,7 +690,7 @@ module JamRuby # sms_init must be called first. # user.audio_latency / 2 , + other_user.audio_latency of them / 2, + network latency /2 def self.sms_users - return User.select('users.*, sms_users_tmp.music_session_id, sms_users_tmp.latency') + return User.select('users.*, sms_users_tmp.music_session_id, sms_users_tmp.full_score, sms_users_tmp.audio_latency, sms_users_tmp.internet_score') .joins( %Q{ INNER JOIN @@ -715,12 +714,29 @@ module JamRuby user_scores = {} music_session_users.each do |user| - user_scores[user.id] = {latency: user.latency} + user_scores[user.id] = {full_score: user.full_score, audio_latency: user.audio_latency, internet_score: user.internet_score} end + [music_sessions, user_scores] end + # returns a single session, but populates any other user info with latency scores, so that show_history.rabl can do it's business + def self.session_with_scores(current_user, music_session_id) + MusicSession.sms_init(current_user, {session_id: music_session_id}) + + music_session = MusicSession.find(music_session_id) + + music_session_users = MusicSession.sms_users.all + + user_scores = {} + music_session_users.each do |user| + user_scores[user.id] = {full_score: user.full_score, audio_latency: user.audio_latency, internet_score: user.internet_score} + end + + [music_session, user_scores] + end + def self.upcoming_sessions end diff --git a/ruby/lib/jam_ruby/models/search.rb b/ruby/lib/jam_ruby/models/search.rb index 761660c84..311341e23 100644 --- a/ruby/lib/jam_ruby/models/search.rb +++ b/ruby/lib/jam_ruby/models/search.rb @@ -225,8 +225,8 @@ module JamRuby 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') + rel = rel.select('current_scores.full_score, current_scores.score, regions.regionname') + rel = rel.group('current_scores.full_score, current_scores.score, regions.regionname') end ordering = self.order_param(params) diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index fc2468fa5..59e688aba 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -323,12 +323,26 @@ module JamRuby read_attribute(:music_session_id) end - def latency - return nil unless has_attribute?(:latency) - a = read_attribute(:latency) + # ===== ARTIFICIAL ATTRIBUTES CREATED BY ActiveMusicSession.ams_users, MusicSession.sms_uses + def full_score + return nil unless has_attribute?(:full_score) + a = read_attribute(:full_score) a.nil? ? nil : a.to_i end + def internet_score + return nil unless has_attribute?(:internet_score) + a = read_attribute(:internet_score) + a.nil? ? nil : a.to_i + end + + def audio_latency + return nil unless has_attribute?(:audio_latency) + a = read_attribute(:audio_latency) + a.nil? ? nil : a.to_i + end + # ====== END ARTIFICAL ATTRIBUTES + # mods comes back as text; so give ourselves a parsed version def mods_json @mods_json ||= mods ? JSON.parse(mods, symbolize_names: true) : {} @@ -1242,15 +1256,16 @@ module JamRuby end def update_audio_latency(connection, audio_latency) + if audio_latency > 2 + # updating the connection is best effort + if connection + connection.last_jam_audio_latency = audio_latency + connection.save + end - # updating the connection is best effort - if connection - connection.last_jam_audio_latency = audio_latency - connection.save + self.last_jam_audio_latency = audio_latency + self.save end - - self.last_jam_audio_latency = audio_latency - self.save end def top_followings 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 03f1a0bac..4297796a3 100644 --- a/ruby/spec/jam_ruby/models/active_music_session_spec.rb +++ b/ruby/spec/jam_ruby/models/active_music_session_spec.rb @@ -376,17 +376,25 @@ describe ActiveMusicSession do users.length.should == 2 if users[0].music_session_id == earlier_session.id users[0].id.should == creator.id - users[0].latency.should == 15 # (5 + 20 + 5) / 2 + users[0].full_score.should == 30 # (5 + 20 + 5) + users[0].audio_latency = 5 + users[0].internet_score = 20 users[1].music_session_id == later_session.id users[1].id.should == creator2.id - users[1].latency.should == 22 # (5 + 30 + 10) / 2 + users[1].full_score.should == 45 # (5 + 30 + 10) + users[1].audio_latency.should == 10 + users[1].internet_score.should == 30 else users[0].music_session_id.should == later_session.id users[0].id.should == creator2.id - users[0].latency.should == 22 # (5 + 30 + 10) / 2 + users[0].full_score.should == 45 # (5 + 30 + 10) + users[0].audio_latency.should == 10 + users[0].internet_score.should == 30 users[1].music_session_id == earlier_session.id users[1].id.should == creator.id - users[1].latency.should == 15 # (5 + 20 + 5) / 2 + users[1].full_score.should == 30 # (5 + 20 + 5) + users[1].audio_latency.should == 5 + users[1].internet_score.should == 20 end end end diff --git a/ruby/spec/jam_ruby/models/music_session_spec.rb b/ruby/spec/jam_ruby/models/music_session_spec.rb index 67571b2d0..dc458d5e6 100644 --- a/ruby/spec/jam_ruby/models/music_session_spec.rb +++ b/ruby/spec/jam_ruby/models/music_session_spec.rb @@ -411,6 +411,39 @@ describe MusicSession do end end + def session_with_scores(user, music_session_id) + ActiveRecord::Base.transaction do + return MusicSession.session_with_scores(user, music_session_id) + end + end + + describe "session_with_scores", no_transaction: true do + let(:conn) { FactoryGirl.create(:connection, user: creator) } + let(:searcher) { FactoryGirl.create(:user) } + let(:searcher_conn) { FactoryGirl.create(:connection, user: searcher, ip_address: '2.2.2.2') } + let(:default_opts) { {client_id: searcher_conn.client_id} } + 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, nil, {auserid: creator.id, buserid: searcher.id}) + end + + it "invalid session ID" do + expect {session_with_scores(searcher, 'blah')}.to raise_error(ActiveRecord::RecordNotFound) + end + + it "one session with scores" do + creator.last_jam_locidispid = conn.locidispid + creator.save! + + session = FactoryGirl.create(:music_session, creator: creator) + music_session, user_scores = session_with_scores(searcher, session.id) + music_session.latency.should be_nil # we don't return music_session.latency with session_with_scores, because it's used for sorting among many sessions + user_scores.length.should == 1 + user_scores[creator.id][:full_score].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) + end + end + describe "sms_index", no_transaction: true do describe "simple" do @@ -461,9 +494,9 @@ describe MusicSession do music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 music_sessions[0].tag.should == 3 # open session sort - music_sessions[0].latency.should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) / 2 + music_sessions[0].latency.should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) user_scores.length.should == 1 - user_scores[creator.id][:latency].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) / 2 + user_scores[creator.id][:full_score].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) end it "filters sessions in the past" do @@ -504,19 +537,19 @@ describe MusicSession do music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 music_sessions[0].tag.should == 3 # open session sort - music_sessions[0].latency.should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) / 2 + music_sessions[0].latency.should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) user_scores.length.should == 2 # the creator, and the invitee - user_scores[creator.id][:latency].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) / 2 - user_scores[invitee.id][:latency].should == ((network_score + searcher.last_jam_audio_latency + invitee.last_jam_audio_latency ) / 2).ceil + user_scores[creator.id][:full_score].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) + user_scores[invitee.id][:full_score].should == ((network_score + searcher.last_jam_audio_latency + invitee.last_jam_audio_latency )).ceil #search with the invitee this time. invitee_conn = FactoryGirl.create(:connection, user: invitee, ip_address: '3.3.3.3', locidispid: invitee.last_jam_locidispid) music_sessions, user_scores = sms(invitee, {client_id: invitee_conn.client_id}) music_sessions.length.should == 1 music_sessions[0].tag.should == 2 # invited sort - music_sessions[0].latency.should == ((network_score + invitee.last_jam_audio_latency + creator.last_jam_audio_latency ) / 2).ceil + music_sessions[0].latency.should == ((network_score + invitee.last_jam_audio_latency + creator.last_jam_audio_latency )).ceil user_scores.length.should == 1 # the creator, and the invitee - user_scores[creator.id][:latency].should == ((network_score + invitee.last_jam_audio_latency + creator.last_jam_audio_latency ) / 2).ceil + user_scores[creator.id][:full_score].should == ((network_score + invitee.last_jam_audio_latency + creator.last_jam_audio_latency )).ceil end it "does not show when it goes active" do @@ -631,20 +664,20 @@ describe MusicSession do music_session = music_sessions[0] music_session.should == music_session_1 music_session.tag.should == 1 # RSVP - music_session.latency.should == (bad_network_score + searcher_1.last_jam_audio_latency + creator_1.last_jam_audio_latency ) / 2 + music_session.latency.should == (bad_network_score + searcher_1.last_jam_audio_latency + creator_1.last_jam_audio_latency ) music_session = music_sessions[1] music_session.should == music_session_2 music_session.tag.should == 2 # INVITE - music_session.latency.should == (fair_network_score + searcher_1.last_jam_audio_latency + creator_2.last_jam_audio_latency ) / 2 + music_session.latency.should == (fair_network_score + searcher_1.last_jam_audio_latency + creator_2.last_jam_audio_latency ) music_session = music_sessions[2] music_session.should == music_session_3 music_session.tag.should == 3 # OPEN - music_session.latency.should == (good_network_score + searcher_1.last_jam_audio_latency + creator_3.last_jam_audio_latency ) / 2 + music_session.latency.should == (good_network_score + searcher_1.last_jam_audio_latency + creator_3.last_jam_audio_latency ) user_scores.length.should == 3 # the creator, and the invitee - user_scores[creator_1.id][:latency].should == (bad_network_score + searcher_1.last_jam_audio_latency + creator_1.last_jam_audio_latency ) / 2 + user_scores[creator_1.id][:full_score].should == (bad_network_score + searcher_1.last_jam_audio_latency + creator_1.last_jam_audio_latency ) # let's make music_session_3 invisible, and verify the count goes to 2 music_session_3.open_rsvps = false diff --git a/ruby/spec/support/maxmind.rb b/ruby/spec/support/maxmind.rb index d48a550e5..9e8ad59bd 100644 --- a/ruby/spec/support/maxmind.rb +++ b/ruby/spec/support/maxmind.rb @@ -159,12 +159,20 @@ def create_phony_database GeoIpBlocks.connection.execute("select generate_scores_dataset()").check end +def austin_ip + IPAddr.new(0x0FFFFFFF, Socket::AF_INET).to_s +end + +def dallas_ip + IPAddr.new(0x1FFFFFFF, Socket::AF_INET).to_s +end + # gets related models for an IP in the 1st block from the scores_better_test_data.sql def austin_geoip geoiplocation = GeoIpLocations.find_by_locid(17192) geoipblock = GeoIpBlocks.find_by_locid(17192) jamisp = JamIsp.find_by_beginip(geoipblock.beginip) - {jamisp: jamisp, geoiplocation: geoiplocation, geoipblock: geoipblock } + {jamisp: jamisp, geoiplocation: geoiplocation, geoipblock: geoipblock, locidispid: Score.compute_locidispid(geoiplocation.locid, jamisp.coid)} end # gets related models for an IP in the 1st block from the scores_better_test_data.sql @@ -172,7 +180,7 @@ def dallas_geoip geoiplocation = GeoIpLocations.find_by_locid(667) geoipblock = GeoIpBlocks.find_by_locid(667) jamisp = JamIsp.find_by_beginip(geoipblock.beginip) - {jamisp: jamisp, geoiplocation: geoiplocation, geoipblock: geoipblock} + {jamisp: jamisp, geoiplocation: geoiplocation, geoipblock: geoipblock, locidispid: Score.compute_locidispid(geoiplocation.locid, jamisp.coid)} end # attempts to make the creation of a score more straightforward. diff --git a/ruby/spec/support/utilities.rb b/ruby/spec/support/utilities.rb index b9db7f8ac..a16514c77 100644 --- a/ruby/spec/support/utilities.rb +++ b/ruby/spec/support/utilities.rb @@ -111,15 +111,15 @@ def app_config end def max_good_full_score - 20 + 40 end def max_yellow_full_score - 35 + 70 end def max_red_full_score - 50 + 100 end private diff --git a/web/app/assets/javascripts/accounts_session_detail.js b/web/app/assets/javascripts/accounts_session_detail.js index a148f4241..35b79b62b 100644 --- a/web/app/assets/javascripts/accounts_session_detail.js +++ b/web/app/assets/javascripts/accounts_session_detail.js @@ -9,6 +9,7 @@ var logger = context.JK.logger; var rest = context.JK.Rest(); var sessionUtils = context.JK.SessionUtils; + var helpBubble = context.JK.HelpBubbleHelper; var sessionId = null; var sessionData = null; var rsvpData = null; @@ -24,15 +25,6 @@ var inviteMusiciansUtil = null; var friendInput=null; - - 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}, - UNKNOWN: {description: "UNKNOWN", style: "latency-grey", min: -2, max: -2} - }; - function beforeShow(data) { sessionId = data.id; loadSessionData(); @@ -146,14 +138,18 @@ .done(function(rsvpResponse) { rsvpData = rsvpResponse; - renderSession(); + + app.user() + .done(function(userMe) { + renderSession(userMe); + }) }) .fail(app.ajaxError); }) .fail(app.ajaxError); } - function renderSession() { + function renderSession(userMe) { var hasPending = false; var isOwner = false; if (sessionData.user_id == context.JK.currentUserId) { @@ -202,65 +198,41 @@ var sessionInvitedHtml = generateSessionInvited(); var sessionPropertiesHtml = generateSessionProperties(); - var template = context._.template( + var $template = $(context._.template( $('#template-account-session-detail').html(), { has_pending: hasPending, is_owner: isOwner, notification_msg: sessionData.notification_msg, pending_rsvps: pendingRsvpHtml, session_rsvps: sessionRsvpsHtml, still_needed: sessionNeededHtml, invited_users: sessionInvitedHtml, session_properties: sessionPropertiesHtml, id: sessionData.id}, {variable: 'data'} - ); + )); - $sessionDetail.html(template); + var $offsetParent = $($sessionDetail).closest('.content-body'); + + $.each($template.find('.latency'), function(index, latencyBadge) { + var $latencyBadge = $(latencyBadge); + var full_score = $latencyBadge.attr('data-full-score') || null; + var internet_score = $latencyBadge.attr('data-internet-score') || null; + var audio_latency = $latencyBadge.attr('data-audio-latency') || null; + var latencyBadgeUserId = $latencyBadge.attr('data-user-id'); + var scoreOptions = {offsetParent: $offsetParent}; + helpBubble.scoreBreakdown($latencyBadge, context.JK.currentUserId == latencyBadgeUserId, full_score, userMe.last_jam_audio_latency, audio_latency, internet_score, scoreOptions); + + }); + + $sessionDetail.html($template); events(); } - function createLatency(user) { - var latencyStyle = LATENCY.UNREACHABLE.style, latencyDescription = LATENCY.UNREACHABLE.description - if (user.id === context.JK.currentUserId) { - latencyStyle = LATENCY.GOOD.style, latencyDescription = LATENCY.GOOD.description; - } - - 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 - 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 { - latencyDescription = LATENCY.POOR.description; - latencyStyle = LATENCY.POOR.style; - } - } - } - - return { - latency_style: latencyStyle, - latency_text: latencyDescription - }; - } - function generatePendingRsvps() { var resultHtml = ""; var rsvpHtml = ""; var instrumentLogoHtml = ""; var latencyHtml = ""; - $.each(sessionData.pending_rsvp_requests, function(index, request) { - if (request.user_id != context.JK.currentUserId) { - if ("instrument_list" in request && request.instrument_list != null) { - console.log(request.instrument_list) - $.each(request.instrument_list, function (index, instrument) { + $.each(sessionData.pending_rsvp_requests, function(index, pending_rsvp_request) { + if (pending_rsvp_request.user_id != context.JK.currentUserId) { + if ("instrument_list" in pending_rsvp_request && pending_rsvp_request.instrument_list != null) { + $.each(pending_rsvp_request.instrument_list, function (index, instrument) { var instrumentId = instrument == null ? null : instrument.id; var inst = context.JK.getInstrumentIcon24(instrumentId); instrumentLogoHtml += ' '; @@ -269,17 +241,17 @@ latencyHtml = context._.template( $("#template-account-session-latency").html(), - createLatency(request.user), + $.extend(sessionUtils.createLatency(pending_rsvp_request.user), pending_rsvp_request.user), {variable: 'data'} ); - var avatar_url = context.JK.resolveAvatarUrl(request.user.photo_url); + var avatar_url = context.JK.resolveAvatarUrl(pending_rsvp_request.user.photo_url); rsvpHtml = context._.template( $("#template-account-pending-rsvp").html(), - {user_id: request.user_id, avatar_url: avatar_url, - user_name: request.user.name, instruments: instrumentLogoHtml, - latency: latencyHtml, request_id: request.id}, + {user_id: pending_rsvp_request.user_id, avatar_url: avatar_url, + user_name: pending_rsvp_request.user.name, instruments: instrumentLogoHtml, + latency: latencyHtml, request_id: pending_rsvp_request.id}, {variable: 'data'} ); @@ -296,9 +268,9 @@ var rsvpHtml = ""; var instrumentLogoHtml = ""; var latencyHtml = ""; - $.each(sessionData.approved_rsvps, function(index, request) { - if ("instrument_list" in request) { - $.each(request.instrument_list, function(index, instrument) { + $.each(sessionData.approved_rsvps, function(index, approved_rsvp) { + if ("instrument_list" in approved_rsvp) { + $.each(approved_rsvp.instrument_list, function(index, instrument) { var instrumentId = instrument == null ? null : instrument.id; var inst = context.JK.getInstrumentIcon24(instrumentId); instrumentLogoHtml += ' '; @@ -307,16 +279,16 @@ latencyHtml = context._.template( $("#template-account-session-latency").html(), - createLatency(request), + $.extend(sessionUtils.createLatency(approved_rsvp), approved_rsvp), {variable: 'data'} ); - var avatar_url = request.resolved_photo_url; + var avatar_url = approved_rsvp.resolved_photo_url; var request_id = null; $.each(rsvpData, function(index, rsvp) { - if (rsvp.user_id == request.id) { + if (rsvp.user_id == approved_rsvp.id) { var approved = true; $.each(rsvp, function(index, rsvp_slot) { if (rsvp_slot.approved == false) { @@ -332,8 +304,8 @@ rsvpHtml = context._.template( $("#template-account-session-rsvp").html(), - {id: request.id, avatar_url: avatar_url, - user_name: request.name, instruments: instrumentLogoHtml, + {id: approved_rsvp.id, avatar_url: avatar_url, + user_name: approved_rsvp.name, instruments: instrumentLogoHtml, latency: latencyHtml, is_owner: sessionData.isOwner, request_id: request_id}, {variable: 'data'} ); diff --git a/web/app/assets/javascripts/findMusician.js b/web/app/assets/javascripts/findMusician.js index ea8b9f564..79c50d256 100644 --- a/web/app/assets/javascripts/findMusician.js +++ b/web/app/assets/javascripts/findMusician.js @@ -13,6 +13,8 @@ var page_num=1, page_count=0; var textMessageDialog = null; var $results = null; + var helpBubble = context.JK.HelpBubbleHelper; + var sessionUtils = context.JK.SessionUtils; function loadMusicians(queryString) { // squelch nulls and undefines @@ -85,23 +87,6 @@ return Math.round(score / 2) + " ms"; } - function score_to_color(score) { - // 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 <= 70) return "yellow"; - if (70 < score && score <= 100) return "red"; - return "blue"; - } - - function score_to_color_alt(score) { - // 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 <= 70) return "moderate"; - if (70 < score && score <= 100) return "poor"; - return "unacceptable"; - } function formatLocation(musician) { if(musician.city && musician.state) { @@ -167,6 +152,8 @@ var musician_actions = context.JK.fillTemplate(aTemplate, actionVals); var full_score = musician['full_score']; + + var scoreInfo = sessionUtils.scoreInfo(full_score, false) mVals = { avatar_url: context.JK.resolveAvatarUrl(musician.photo_url), profile_url: "/client#/profile/" + musician.id, @@ -182,22 +169,20 @@ musician_follow_template: follows, musician_action_template: musician_actions, 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) - + musician_score_color: scoreInfo.icon_name, + musician_score_color_alt: scoreInfo.description, + latency_style: scoreInfo.latency_style }; 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'}; + var scoreOptions = {offsetParent: $offsetParent}; 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) + helpBubble.scoreBreakdown($('.score-count', $rendering), false, full_score, myAudioLatency, musician['audio_latency'], musician['score'], scoreOptions); $results.append($rendering); } diff --git a/web/app/assets/javascripts/findSession.js b/web/app/assets/javascripts/findSession.js index 80e0fa67f..de5c795ea 100644 --- a/web/app/assets/javascripts/findSession.js +++ b/web/app/assets/javascripts/findSession.js @@ -94,11 +94,11 @@ } function renderActiveSessions(sessions) { - $.each(sessions, function(i, session) { - sessionList.renderActiveSession(session, $(CATEGORY.ACTIVE.id)); + $.each(sessions.sessions, function(i, session) { + sessionList.renderActiveSession(session, $(CATEGORY.ACTIVE.id), sessions.my_audio_latency); }); - afterLoadActiveSessions(sessions); + afterLoadActiveSessions(sessions.sessions); } function buildActiveSessionsQuery() { @@ -162,10 +162,10 @@ } function renderScheduledSessions(sessions) { - $.each(sessions, function(i, session) { - sessionList.renderInactiveSession(session, $(CATEGORY.SCHEDULED.id)); + $.each(sessions.sessions, function(i, session) { + sessionList.renderInactiveSession(session, $(CATEGORY.SCHEDULED.id), undefined, sessions.my_audio_latency); }); - afterLoadScheduledSessions(sessions); + afterLoadScheduledSessions(sessions.sessions); } function buildScheduledSessionsQuery() { diff --git a/web/app/assets/javascripts/helpBubbleHelper.js b/web/app/assets/javascripts/helpBubbleHelper.js new file mode 100644 index 000000000..9c9a05bd5 --- /dev/null +++ b/web/app/assets/javascripts/helpBubbleHelper.js @@ -0,0 +1,29 @@ +/** + * HelpBubble helper functions, for help bubbles with lots of arguments or logic + */ +(function (context, $) { + + "use strict"; + + context.JK = context.JK || {}; + var helpBubble = {}; + var rest = new context.JK.Rest(); + context.JK.HelpBubbleHelper = helpBubble; + var logger = context.JK.logger; + + var defaultScoreBreakDownOptions = {positions: ['right', 'top', 'bottom', 'left'], width:'600px', closeWhenOthersOpen: true }; + helpBubble.scoreBreakdown = function($element, isCurrentUser, full_score, myAudioLatency, otherAudioLatency, internetScore, options) { + options = options || {}; + options = $.extend({}, defaultScoreBreakDownOptions, options) + if(isCurrentUser) { + context.JK.helpBubble($element, 'musician-score-self', + {full_score: full_score ? Math.round(full_score / 2) : null, my_gear_latency: myAudioLatency, their_gear_latency: otherAudioLatency, internet_latency: internetScore}, + options); + } else { + context.JK.helpBubble($element, 'musician-score-count', + {full_score: full_score ? Math.round(full_score / 2) : null, my_gear_latency: myAudioLatency, their_gear_latency: otherAudioLatency, internet_latency: internetScore}, + options); + } + } + +})(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js index 705ccafae..21beca5eb 100644 --- a/web/app/assets/javascripts/sessionList.js +++ b/web/app/assets/javascripts/sessionList.js @@ -6,10 +6,11 @@ context.JK.SessionList = function(app) { var EVENTS = context.JK.EVENTS; var gearUtils = context.JK.GearUtils; + var sessionUtils = context.JK.SessionUtils; + var helpBubble = context.JK.HelpBubbleHelper; var logger = context.JK.logger; var rest = context.JK.Rest(); var ui = new context.JK.UIHelper(app); - var sessionUtils = context.JK.SessionUtils; var $activeSessionTemplate = $('#template-active-session-row'); var $inactiveSessionTemplate = $('#template-inactive-session-row'); var $notationFileTemplate = $('#template-notation-files'); @@ -19,15 +20,7 @@ var showJoinLink = true; var showRsvpLink = true; - var LATENCY = { - GOOD : {description: "GOOD", style: "latency-green", min: 0.0, max: 20.0}, - 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} - }; - - function renderActiveSession(session, tbGroup) { + function renderActiveSession(session, tbGroup, myAudioLatency) { $('#actionHeader', tbGroup).html('JOIN'); @@ -95,8 +88,17 @@ sessionVals.in_session_musicians = inSessionUsersHtml.length > 0 ? inSessionUsersHtml : 'N/A'; sessionVals.join_link_display_style = showJoinLink ? "block" : "none"; - var row = context.JK.fillTemplate($activeSessionTemplate.html(), sessionVals); - $(tbGroup).append(row); + var $row = $(context.JK.fillTemplate($activeSessionTemplate.html(), sessionVals)); + var $offsetParent = $(tbGroup).closest('.content'); + var $latencyBadge = $row.find('.latency-value'); + var full_score = $latencyBadge.attr('data-full-score') || null; + var internet_score = $latencyBadge.attr('data-internet-score') || null; + var audio_latency = $latencyBadge.attr('data-audio-latency') || null; + var latencyBadgeUserId = $latencyBadge.attr('data-user-id'); + var scoreOptions = {offsetParent: $offsetParent}; + helpBubble.scoreBreakdown($latencyBadge, context.JK.currentUserId == latencyBadgeUserId, full_score, myAudioLatency, audio_latency, internet_score, scoreOptions); + + $(tbGroup).append($row); if (showJoinLink) { // wire up the Join Link to the T&Cs dialog @@ -127,7 +129,7 @@ } } - function renderInactiveSession(session, tbGroup, $rowToUpdate) { + function renderInactiveSession(session, tbGroup, $rowToUpdate, myAudioLatency) { var openSlots = false; var hasInvitation = false; @@ -195,15 +197,25 @@ var sessionVals = buildSessionObject(session, notationFileHtml, rsvpUsersHtml, openSlotsHtml, latencyHtml); sessionVals.scheduled_start = session.pretty_scheduled_start_with_timezone; - var row = context.JK.fillTemplate($inactiveSessionTemplate.html(), sessionVals); + var $row = $(context.JK.fillTemplate($inactiveSessionTemplate.html(), sessionVals)); + + var $offsetParent = $(tbGroup).closest('.content'); + var $latencyBadge = $row.find('.latency-value'); + var full_score = $latencyBadge.attr('data-full-score') || null; + var internet_score = $latencyBadge.attr('data-internet-score') || null; + var audio_latency = $latencyBadge.attr('data-audio-latency') || null; + var latencyBadgeUserId = $latencyBadge.attr('data-user-id'); + var scoreOptions = {offsetParent: $offsetParent}; + helpBubble.scoreBreakdown($latencyBadge, context.JK.currentUserId == latencyBadgeUserId, full_score, myAudioLatency, audio_latency, internet_score, scoreOptions); + // initial page load if (!$rowToUpdate) { - $(tbGroup).append(row); + $(tbGroup).append($row); } // inline update after an RSVP submission / cancellation else { - $rowToUpdate.replaceWith(row); + $rowToUpdate.replaceWith($row); } var $parentRow = $('tr[data-session-id=' + session.id + ']', tbGroup); @@ -219,7 +231,7 @@ .one(EVENTS.RSVP_CANCELED, function() { rest.getSessionHistory(session.id) .done(function(response) { - renderInactiveSession(response, tbGroup, $parentRow); + renderInactiveSession(response, tbGroup, $parentRow, myAudioLatency); }); }) .one(EVENTS.DIALOG_CLOSED, function() { @@ -236,7 +248,7 @@ .one(EVENTS.RSVP_CANCELED, function() { rest.getSessionHistory(session.id) .done(function(response) { - renderInactiveSession(response, tbGroup, $parentRow); + renderInactiveSession(response, tbGroup, $parentRow, myAudioLatency); }); }) .one(EVENTS.DIALOG_CLOSED, function() { @@ -263,7 +275,7 @@ .one(EVENTS.RSVP_SUBMITTED, function() { rest.getSessionHistory(session.id) .done(function(response) { - renderInactiveSession(response, tbGroup, $parentRow); + renderInactiveSession(response, tbGroup, $parentRow, myAudioLatency); }); }) .one(EVENTS.DIALOG_CLOSED, function() { @@ -318,7 +330,7 @@ }; var musicianHtml = context.JK.fillTemplate($musicianTemplate.html(), musicianVals); - var latencyHtml = context.JK.fillTemplate($latencyTemplate.html(), createLatency(participant.user)); + var latencyHtml = context._.template($latencyTemplate.html(), $.extend(sessionUtils.createLatency(participant.user), participant.user), { variable: 'data' }); return [musicianHtml, latencyHtml]; } @@ -349,51 +361,11 @@ }; var musicianHtml = context.JK.fillTemplate($musicianTemplate.html(), musicianVals); - var latencyHtml = context.JK.fillTemplate($latencyTemplate.html(), createLatency(user)); + var latencyHtml = context._.template($latencyTemplate.html(), $.extend(sessionUtils.createLatency(user), user), { variable: 'data' }); return [musicianHtml, latencyHtml]; } - function createLatency(user) { - - var latencyStyle; - var latencyDescription; - - if (user.id === context.JK.currentUserId) { - latencyStyle = LATENCY.GOOD.style, latencyDescription = LATENCY.GOOD.description; - } - - else { - var latency = user.latency; - - 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 { - latencyStyle = LATENCY.UNREACHABLE.style - latencyDescription = LATENCY.UNREACHABLE.description - } - } - - return { - latency_style: latencyStyle, - latency_text: latencyDescription - }; - } - function createNotationFile(notation) { var notationVals = { file_url: notation.file_url, diff --git a/web/app/assets/javascripts/session_utils.js b/web/app/assets/javascripts/session_utils.js index a80aae99e..19754a981 100644 --- a/web/app/assets/javascripts/session_utils.js +++ b/web/app/assets/javascripts/session_utils.js @@ -11,6 +11,17 @@ context.JK.SessionUtils = sessionUtils; var logger = context.JK.logger; + + + var LATENCY = sessionUtils.LATENCY = { + ME : {description: "ME", style: "latency-me", min: -1, max: -1}, + GOOD : {description: "GOOD", style: "latency-good", min: 0.0, max: 40.0}, + MEDIUM : {description: "FAIR", style: "latency-fair", min: 40.0, max: 70.0}, + POOR : {description: "POOR", style: "latency-poor", min: 70.0, max: 100}, + UNACCEPTABLE: {description: "UNACCEPTABLE", style: "latency-unacceptable", min: 100, max: 10000000}, + UNKNOWN: {description: "UNKNOWN", style: "latency-unknown", min: -2, max: -2} + }; + sessionUtils.createOpenSlot = function($openSlotsTemplate, slot) { var inst = context.JK.getInstrumentIcon24(slot.instrument_id); @@ -52,4 +63,58 @@ } } + sessionUtils.scoreInfo = function(full_score, isSameUser) { + var latencyDescription; + var latencyStyle; + var iconName; + var description; + + if(isSameUser) { + latencyDescription = LATENCY.ME.description; + latencyStyle = LATENCY.ME.style; + iconName = 'purple'; + description = 'me'; + } + else if (!full_score) { + latencyDescription = LATENCY.UNKNOWN.description; + latencyStyle = LATENCY.UNKNOWN.style; + iconName = 'purple' + description = 'missing' + } + else if (full_score <= LATENCY.GOOD.max) { + latencyDescription = LATENCY.GOOD.description; + latencyStyle = LATENCY.GOOD.style; + iconName = 'green' + description = 'good' + } + else if (full_score <= LATENCY.MEDIUM.max) { + latencyDescription = LATENCY.MEDIUM.description; + latencyStyle = LATENCY.MEDIUM.style; + iconName = 'yellow'; + description = 'fair' + } + else if (full_score <= LATENCY.POOR.max) { + latencyDescription = LATENCY.POOR.description; + latencyStyle = LATENCY.POOR.style; + iconName = 'red' + description = 'poor' + } + else { + latencyStyle = LATENCY.UNACCEPTABLE.style; + latencyDescription = LATENCY.UNACCEPTABLE.description; + iconName = 'blue' + description = 'unacceptable' + } + + return { + latency_style: latencyStyle, + latency_text: latencyDescription, + icon_name: iconName, + description: description + }; + } + sessionUtils.createLatency = function(user) { + return sessionUtils.scoreInfo(user.full_score, user.id === context.JK.currentUserId) + } + })(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index 38785e099..932240096 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -110,6 +110,10 @@ options = {} } + $element.on('remove', function() { + $element.btOff(); + }) + var helpText = context._.template($('#template-help-' + templateName).html(), data, { variable: 'data' }); var holder = $('
'); diff --git a/web/app/assets/javascripts/web/session_info.js b/web/app/assets/javascripts/web/session_info.js index 3886a6068..7e8e0514d 100644 --- a/web/app/assets/javascripts/web/session_info.js +++ b/web/app/assets/javascripts/web/session_info.js @@ -9,15 +9,11 @@ var logger = context.JK.logger; var rest = JK.Rest(); var ui = new context.JK.UIHelper(app); + var sessionUtils = context.JK.SessionUtils; + var helpBubble = context.JK.HelpBubbleHelper; var $btnAction = $("#btn-action"); - - 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}, - UNKNOWN: {description: "UNKNOWN", style: "latency-grey", min: -2, max: -2} - }; + var $templateLatencyDetail = null; + var $landingSidebar = null; function addComment() { var comment = $("#txtSessionInfoComment").val(); @@ -66,70 +62,48 @@ } // this is done post-page load to allow websocket connection to be established - function addLatencyDetails() { - rest.getSessionHistory(musicSessionId) - .done(function(session) { - if (session.approved_rsvps && session.approved_rsvps.length > 0) { - // loop through each record in RSVPs, which has already been rendered, and extract - // the user ID - $('.rsvp-details').each(function(index) { - var $user = $(this).find('div[hoveraction="musician"]'); - var userId = $user.attr('user-id'); - var latency = null; - var latencyStyle = LATENCY.UNKNOWN.style; - var latencyDescription = LATENCY.UNKNOWN.description; + function addLatencyDetails(session) { + if (session.approved_rsvps && session.approved_rsvps.length > 0) { + // loop through each record in RSVPs, which has already been rendered, and extract + // the user ID + $('.rsvp-details').each(function(index) { + var $user = $(this).find('div[hoveraction="musician"]'); + var userId = $user.attr('user-id'); - // default current user to GOOD - if (userId === context.JK.currentUserId) { - latencyStyle = LATENCY.GOOD.style; - latencyDescription = LATENCY.GOOD.description; - } - else { - // find the corresponding user in the API response payload - for (var i=0; i < session.approved_rsvps.length; i++) { - if (session.approved_rsvps.id === userId) { - latency = session.approved_rsvps[i].latency; - break; - } - } - if (latency) { - 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; - } - } - else { - latencyStyle = LATENCY.UNKNOWN.style; - latencyDescription = LATENCY.UNKNOWN.description; - } - } + var user = null; + for (var i=0; i < session.approved_rsvps.length; i++) { + if (session.approved_rsvps[i].id === userId) { + user = session.approved_rsvps[i]; + break; + } + } + + if(user) { // add the latency details for this user to the UI - var latencyHtml = context.JK.fillTemplate($('#template-latency-detail').html(), { - latencyStyle: latencyStyle, - latencyDescription: latencyDescription - }); - - $(this).find('.latency-tags').append(latencyHtml); - }); - } - }); + var $latencyHtml = $(context.JK.fillTemplate($templateLatencyDetail.html(), + sessionUtils.createLatency(user))); + var $latencyBadge = $latencyHtml.find('.latency'); + app.user().done(function(userMe) { + helpBubble.scoreBreakdown($latencyBadge, context.JK.currentUserId == user.id, user.full_score, userMe.last_jam_audio_latency, user.audio_latency, user.internet_score, {offsetParent: $landingSidebar}); + }) + $(this).find('.latency-tags').append($latencyHtml); + } + else { + logger.warn("unable to find user in approved_rsvps"); + } + }); + } } function initialize() { registerScheduledSessionComment(); - var $parent = $('.landing-sidebar'); - context.JK.bindHoverEvents($parent); - context.JK.setInstrumentAssetPath($('.instrument-icon', $parent)); + $landingSidebar = $('.landing-sidebar'); + $templateLatencyDetail = $('#template-latency-detail'); + + context.JK.bindHoverEvents($landingSidebar); + context.JK.setInstrumentAssetPath($('.instrument-icon', $landingSidebar)); // render comments $(".landing-comment-scroller").empty(); @@ -141,6 +115,8 @@ context.JK.resolveAvatarUrl(val.creator.photo_url), $.timeago(val.created_at), true); }); } + + addLatencyDetails(response); }) .fail(function(xhr) { @@ -212,8 +188,6 @@ $("#txtSessionComment").blur(); } }); - - addLatencyDetails(); } this.initialize = initialize; diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index 86f8d3bf3..62a9e8d40 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -17,6 +17,7 @@ //= require jquery.custom-protocol //= require jquery.ba-bbq //= require jquery.icheck +//= require jquery.bt //= require AAA_Log //= require AAC_underscore //= require globals @@ -43,6 +44,8 @@ //= require custom_controls //= require ga //= require jam_rest +//= require session_utils +//= require helpBubbleHelper //= require facebook_rest //= require landing/init //= require landing/signup diff --git a/web/app/assets/stylesheets/client/account.css.scss b/web/app/assets/stylesheets/client/account.css.scss index f80ef3f02..a26e99251 100644 --- a/web/app/assets/stylesheets/client/account.css.scss +++ b/web/app/assets/stylesheets/client/account.css.scss @@ -294,8 +294,9 @@ .latency { font-size: 15px; height: 16px; - padding-left: 4px; + padding: 3px; width: 100%; + @include border-radius(2px); } #session-rsvps, #still-needed, #invited-users { diff --git a/web/app/assets/stylesheets/client/common.css.scss b/web/app/assets/stylesheets/client/common.css.scss index 08bb7e86e..fdd5027de 100644 --- a/web/app/assets/stylesheets/client/common.css.scss +++ b/web/app/assets/stylesheets/client/common.css.scss @@ -37,6 +37,13 @@ $border: hsl(210, 50%, 45%); $narrow-screen: 1000px; // 990 ? 1000 ? $short-screen: 600px; // toolbars / chrome for x768 +$latencyBadgeMe: #dddddd; +$latencyBadgeGood: #71a43b; +$latencyBadgeFair: #cc9900; +$latencyBadgePoor: #980006; +$latencyBadgeUnacceptable: #868686; +$latencyBadgeUnknown: #868686; + @mixin border_box_sizing { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; @@ -51,6 +58,44 @@ $short-screen: 600px; // toolbars / chrome for x768 box-sizing: content-box; } +@mixin border-radius($radius) { + -moz-border-radius:$radius; + -webkit-border-radius: $radius; + border-radius: $radius; + background-clip: padding-box; /* stops bg color from leaking outside the border: */ +} + +// Single side border-radius + +@mixin border-top-radius($radius) { + -webkit-border-top-right-radius: $radius; + border-top-right-radius: $radius; + -webkit-border-top-left-radius: $radius; + border-top-left-radius: $radius; + background-clip: padding-box; +} +@mixin border-right-radius($radius) { + -webkit-border-bottom-right-radius: $radius; + border-bottom-right-radius: $radius; + -webkit-border-top-right-radius: $radius; + border-top-right-radius: $radius; + background-clip: padding-box; +} +@mixin border-bottom-radius($radius) { + -webkit-border-bottom-right-radius: $radius; + border-bottom-right-radius: $radius; + -webkit-border-bottom-left-radius: $radius; + border-bottom-left-radius: $radius; + background-clip: padding-box; +} +@mixin border-left-radius($radius) { + -webkit-border-bottom-left-radius: $radius; + border-bottom-left-radius: $radius; + -webkit-border-top-left-radius: $radius; + border-top-left-radius: $radius; + background-clip: padding-box; +} + @mixin flat_dropdown { box-shadow: none !important; color: #666666; diff --git a/web/app/assets/stylesheets/client/findSession.css.scss b/web/app/assets/stylesheets/client/findSession.css.scss index 5f47c6d58..627b28192 100644 --- a/web/app/assets/stylesheets/client/findSession.css.scss +++ b/web/app/assets/stylesheets/client/findSession.css.scss @@ -1,3 +1,5 @@ +@import 'common.css.scss'; + #findSession { th, td { margin: 4px; padding:4px; } @@ -68,4 +70,8 @@ .end-of-list { margin-top:0; } + + .latency-value { + @include border-radius(2px); + } } \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/help.css.scss b/web/app/assets/stylesheets/client/help.css.scss index 691bc7c74..32074d802 100644 --- a/web/app/assets/stylesheets/client/help.css.scss +++ b/web/app/assets/stylesheets/client/help.css.scss @@ -1,4 +1,4 @@ -.screen { +.screen, body.web { .bt-wrapper { .bt-content { @@ -7,10 +7,15 @@ font-size:14px; p { + margin:1em; + line-height:150%; font-size:14px; } ul { font-size:14px; + margin-left: 2em; + list-style: disc; + color:#CCCCCC; } li { diff --git a/web/app/assets/stylesheets/client/sessionList.css.scss b/web/app/assets/stylesheets/client/sessionList.css.scss index 9e4884a5b..f6dc3c46d 100644 --- a/web/app/assets/stylesheets/client/sessionList.css.scss +++ b/web/app/assets/stylesheets/client/sessionList.css.scss @@ -1,6 +1,71 @@ @import "client/common"; +table.findsession-table, table.local-recordings, #account-session-detail { + + + + .latency-unacceptable { + width: 50px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + background-color:$latencyBadgeUnacceptable; + text-align:center; + } + + .latency-unknown { + width: 50px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + background-color:$latencyBadgeUnacceptable; + text-align:center; + } + + .latency-good { + width: 50px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + background-color:$latencyBadgeGood; + text-align:center; + } + + .latency-me { + width: 50px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + text-align:center; + background-color:$latencyBadgeMe; + color:black; + } + + .latency-fair { + width: 50px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + background-color:$latencyBadgeFair; + text-align:center; + } + + .latency-poor{ + width: 40px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + background-color:$latencyBadgePoor; + text-align:center; + } +} table.findsession-table, table.local-recordings { width:98%; height:10%; @@ -80,45 +145,6 @@ table.findsession-table, table.local-recordings { } } -.latency-grey { - width: 50px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#868686; - text-align:center; -} - -.latency-green { - width: 50px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#71a43b; - text-align:center; -} - -.latency-yellow { - width: 50px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#cc9900; - text-align:center; -} - -.latency-red { - width: 40px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#980006; - text-align:center; -} .avatar-tiny { float:left; diff --git a/web/app/assets/stylesheets/web/session_info.css.scss b/web/app/assets/stylesheets/web/session_info.css.scss new file mode 100644 index 000000000..975d9db0c --- /dev/null +++ b/web/app/assets/stylesheets/web/session_info.css.scss @@ -0,0 +1,56 @@ +@import "client/common"; + +body.web.session_info { + + table.musicians { + margin-left:4px; + } + + table.musicians td { + border-right:none; + border-top:none; + padding:2px; + vertical-align:middle !important; + } + + .latency { + width: 50px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + text-align:center; + @include border-radius(2px); + } + + .latency-unknown { + background-color:$latencyBadgeUnknown; + } + + .latency-unacceptable { + background-color:$latencyBadgeUnacceptable; + } + + .latency-good { + background-color:$latencyBadgeGood; + } + + .latency-fair{ + background-color:$latencyBadgeFair; + } + + .latency-poor { + background-color:$latencyBadgePoor; + } + + .latency-me { + width: 40px; + height: 10px; + font-family:Arial, Helvetica, sans-serif; + font-weight:200; + font-size:11px; + background-color:$latencyBadgeMe; + text-align:center; + color:black; + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/web/sessions.css.scss b/web/app/assets/stylesheets/web/sessions.css.scss index f0a39eb7c..8a30c08e0 100644 --- a/web/app/assets/stylesheets/web/sessions.css.scss +++ b/web/app/assets/stylesheets/web/sessions.css.scss @@ -1,54 +1,3 @@ #btnPlayPause { position: relative; -} - -table.musicians { - margin-top:-3px; -} - -table.musicians td { - border-right:none; - border-top:none; - padding:2px; - vertical-align:middle !important; - } - -.latency-grey { - width: 50px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#868686; - text-align:center; -} - -.latency-green { - width: 50px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#71a43b; - text-align:center; -} - -.latency-yellow { - width: 50px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#cc9900; - text-align:center; -} - -.latency-red { - width: 40px; - height: 10px; - font-family:Arial, Helvetica, sans-serif; - font-weight:200; - font-size:11px; - background-color:#980006; - text-align:center; } \ No newline at end of file diff --git a/web/app/assets/stylesheets/web/web.css b/web/app/assets/stylesheets/web/web.css index 37e75c4ac..41d1bea03 100644 --- a/web/app/assets/stylesheets/web/web.css +++ b/web/app/assets/stylesheets/web/web.css @@ -11,12 +11,14 @@ *= require client/ftue *= require client/user_dropdown *= require client/hoverBubble +*= require client/help *= require web/main *= require web/footer *= require web/recordings *= require web/welcome #= require web/sessions *= require web/events +*= require web/session_info *= require users/signinCommon *= require dialogs/dialog *= require landings/landing_page diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb index f3f460b50..afa0eb29f 100644 --- a/web/app/controllers/api_music_sessions_controller.rb +++ b/web/app/controllers/api_music_sessions_controller.rb @@ -532,7 +532,13 @@ class ApiMusicSessionsController < ApiController end def show_history - @history = MusicSession.find(params[:id]) + if current_user + ActiveRecord::Base.transaction do + @history, @user_scores = MusicSession.session_with_scores(current_user, params[:id]) + end + else + @history = MusicSession.find(params[:id]) + end end def claimed_recording_start diff --git a/web/app/helpers/score_helper.rb b/web/app/helpers/score_helper.rb index 1609e2378..9b1ddfe62 100644 --- a/web/app/helpers/score_helper.rb +++ b/web/app/helpers/score_helper.rb @@ -1,9 +1,20 @@ module ScoreHelper # helper method to make finding a user's score fault-tolerant - def user_score(user_id) + def user_score_old(user_id) @user_scores ||= {} user = @user_scores[user_id] - user ? user[:latency] : nil + user ? user[:full_score] : nil + end + + def user_score(user_id) + @user_scores ||= {} + user = @user_scores[user_id] || {} + { full_score: user[:full_score], audio_latency: user[:audio_latency], internet_score: user[:internet_score] } + end + + def last_jam_audio_latency(user) + user.last_jam_audio_latency ? user.last_jam_audio_latency.round : nil end end + diff --git a/web/app/views/api_music_sessions/ams_index.rabl b/web/app/views/api_music_sessions/ams_index.rabl index 05e15a27f..f602faffa 100644 --- a/web/app/views/api_music_sessions/ams_index.rabl +++ b/web/app/views/api_music_sessions/ams_index.rabl @@ -1,3 +1,8 @@ -object @music_sessions -extends "api_music_sessions/show_history" +node :my_audio_latency do |user| + current_user.last_jam_audio_latency.round if current_user.last_jam_audio_latency +end + +child @music_sessions => :sessions do + extends "api_music_sessions/show_history" +end diff --git a/web/app/views/api_music_sessions/show_history.rabl b/web/app/views/api_music_sessions/show_history.rabl index 9d9d42bca..51081a61f 100644 --- a/web/app/views/api_music_sessions/show_history.rabl +++ b/web/app/views/api_music_sessions/show_history.rabl @@ -93,10 +93,9 @@ else attributes :id, :sender_id, :receiver_id node do |invitation| - { - latency: user_score(invitation.receiver.id), - receiver_avatar_url: invitation.receiver.resolved_photo_url - } + user_score(invitation.receiver.id).merge({ + receiver_avatar_url: invitation.receiver.resolved_photo_url, audio_latency: last_jam_audio_latency(invitation.receiver) + }) end } @@ -104,11 +103,11 @@ else attributes :id, :photo_url, :first_name, :last_name, :name, :resolved_photo_url, :rsvp_request_id node do |user| - { - latency: user_score(user.id), + user_score(user.id).merge({ instrument_list: process_approved_rsvps(user), - rsvp_request_id: JSON.parse(user.rsvp_request_ids)[0] # there must always be a rsvp_request_id; and they should all be the same - } + rsvp_request_id: JSON.parse(user.rsvp_request_ids)[0], # there must always be a rsvp_request_id; and they should all be the same + audio_latency: last_jam_audio_latency(user) + }) end } @@ -127,7 +126,9 @@ else attributes :id, :photo_url, :name, :first_name, :last_name node do |user| - { latency: user_score(user.id), name: user.name } + user_score(user.id).merge({ + name: user.name, + audio_latency: last_jam_audio_latency(user)}) end } } @@ -156,7 +157,13 @@ else attributes :ip_address, :client_id, :joined_session_at node :user do |connection| - { :id => connection.user.id, :photo_url => connection.user.photo_url, :name => connection.user.name, :is_friend => connection.user.friends?(current_user), :connection_state => connection.aasm_state, latency: user_score(connection.user.id) } + user_score(connection.user.id).merge({ + :id => connection.user.id, + :photo_url => connection.user.photo_url, + :name => connection.user.name, + :is_friend => connection.user.friends?(current_user), + :connection_state => connection.aasm_state, + audio_latency: last_jam_audio_latency(connection.user)}) end child(:tracks => :tracks) { diff --git a/web/app/views/api_music_sessions/sms_index.rabl b/web/app/views/api_music_sessions/sms_index.rabl index 05e15a27f..f17cdc21f 100644 --- a/web/app/views/api_music_sessions/sms_index.rabl +++ b/web/app/views/api_music_sessions/sms_index.rabl @@ -1,3 +1,8 @@ -object @music_sessions -extends "api_music_sessions/show_history" +node :my_audio_latency do |user| + current_user.last_jam_audio_latency.round if current_user.last_jam_audio_latency +end + +child @music_sessions => :sessions do + extends "api_music_sessions/show_history" +end \ No newline at end of file diff --git a/web/app/views/api_search/index.rabl b/web/app/views/api_search/index.rabl index e7120fca6..93462e736 100644 --- a/web/app/views/api_search/index.rabl +++ b/web/app/views/api_search/index.rabl @@ -43,11 +43,11 @@ if @search.musicians_filter_search? end node :my_audio_latency do |user| - current_user.last_jam_audio_latency + current_user.last_jam_audio_latency.round if 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, :regionname, :score, :full_score, :audio_latency + attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score node :is_friend do |musician| @search.is_friend?(musician) @@ -79,6 +79,10 @@ if @search.musicians_filter_search? node :friend_count do |musician| @search.friend_count(musician) end node :recording_count do |musician| @search.record_count(musician) end node :session_count do |musician| @search.session_count(musician) end + + node :audio_latency do |musician| + last_jam_audio_latency(musician) + end } end diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl index eba9115d9..5dc6f0d02 100644 --- a/web/app/views/api_users/show.rabl +++ b/web/app/views/api_users/show.rabl @@ -68,3 +68,7 @@ end child :music_sessions => :sessions do attributes :id, :description, :musician_access, :approval_required, :fan_access end + +node :last_jam_audio_latency do |user| + user.last_jam_audio_latency.round if user.last_jam_audio_latency +end \ No newline at end of file diff --git a/web/app/views/clients/_account_session_detail.html.haml b/web/app/views/clients/_account_session_detail.html.haml index 7057069b8..ed08fbc17 100644 --- a/web/app/views/clients/_account_session_detail.html.haml +++ b/web/app/views/clients/_account_session_detail.html.haml @@ -159,5 +159,5 @@ %img{src: "{{data.avatar_url}}"} %script{type: 'text/template', id: 'template-account-session-latency'} - .latency{class: "{{data.latency_style}}"} + .latency{class: "{{data.latency_style}}", 'data-user-id' => "{{data.id}}", 'data-audio-latency' => "{{data.audio_latency || ''}}", 'data-full-score' => "{{data.full_score || ''}}", 'data-internet-score' => "{{data.internet_score || ''}}"} {{data.latency_text}} diff --git a/web/app/views/clients/_findSession.html.erb b/web/app/views/clients/_findSession.html.erb index 5b642c0f2..ec21dc8f4 100644 --- a/web/app/views/clients/_findSession.html.erb +++ b/web/app/views/clients/_findSession.html.erb @@ -242,8 +242,8 @@ + + \ 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 df1b044b4..6c2a91919 100644 --- a/web/app/views/clients/_musicians.html.erb +++ b/web/app/views/clients/_musicians.html.erb @@ -24,21 +24,12 @@