This commit is contained in:
Seth Call 2014-08-18 10:37:55 -05:00
parent 5ae975c097
commit 0c3a43a177
46 changed files with 780 additions and 379 deletions

View File

@ -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
drop_session_invite_constraint.sql
sms_index_single_session.sql

View File

@ -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;

View File

@ -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]

View File

@ -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

View File

@ -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)

View File

@ -588,15 +588,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
@ -689,7 +688,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
@ -713,12 +712,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

View File

@ -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, round(current_scores.a_audio_latency) as audio_latency, regions.regionname')
rel = rel.group('current_scores.full_score, current_scores.score, current_scores.a_audio_latency, regions.regionname')
end
ordering = self.order_param(params)

View File

@ -320,12 +320,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) : {}
@ -1239,15 +1253,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

View File

@ -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

View File

@ -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

View File

@ -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, geoipblock.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, geoipblock.coid)}
end
# attempts to make the creation of a score more straightforward.

View File

@ -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();
@ -202,65 +194,44 @@
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};
app.user()
.done(function(userMe) {
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 += '<img data-instrument-id="' + instrumentId + '" src="' + inst + '" width="24" height="24" />&nbsp;';
@ -269,17 +240,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 +267,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 += '<img src="' + inst + '" width="24" height="24" />&nbsp;';
@ -307,16 +278,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 +303,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'}
);

View File

@ -13,6 +13,7 @@
var page_num=1, page_count=0;
var textMessageDialog = null;
var $results = null;
var helpBubble = context.JK.HelpBubbleHelper;
function loadMusicians(queryString) {
// squelch nulls and undefines
@ -190,14 +191,12 @@
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);
}

View File

@ -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() {

View File

@ -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' };
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);

View File

@ -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,

View File

@ -11,6 +11,16 @@
context.JK.SessionUtils = sessionUtils;
var logger = context.JK.logger;
var LATENCY = {
ME : {description: "ME", style: "latency-me", min: -1, max: -1},
GOOD : {description: "GOOD", style: "latency-good", min: 0.0, max: 20.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 +62,44 @@
}
}
sessionUtils.createLatency = function(user) {
var latencyStyle;
var latencyDescription;
if (user.id === context.JK.currentUserId) {
latencyStyle = LATENCY.ME.style, latencyDescription = LATENCY.ME.description;
}
else {
var latency = user.full_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 {
latencyStyle = LATENCY.UNACCEPTABLE.style
latencyDescription = LATENCY.UNACCEPTABLE.description
}
}
return {
latency_style: latencyStyle,
latency_text: latencyDescription
};
}
})(window, jQuery);

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -80,43 +80,65 @@ table.findsession-table, table.local-recordings {
}
}
.latency-grey {
.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:#868686;
background-color:$latencyBadgeUnacceptable;
text-align:center;
}
.latency-green {
.latency-good {
width: 50px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:11px;
background-color:#71a43b;
background-color:$latencyBadgeGood;
text-align:center;
}
.latency-yellow {
.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:#cc9900;
background-color:$latencyBadgeFair;
text-align:center;
}
.latency-red {
.latency-poor{
width: 40px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:11px;
background-color:#980006;
background-color:$latencyBadgePoor;
text-align:center;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -1,9 +1,15 @@
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
end

View File

@ -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

View File

@ -94,9 +94,8 @@ else
node do |invitation|
{
latency: user_score(invitation.receiver.id),
receiver_avatar_url: invitation.receiver.resolved_photo_url
}
}.merge(user_score(invitation.receiver.id))
end
}
@ -105,10 +104,9 @@ else
node do |user|
{
latency: user_score(user.id),
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
}
}.merge(user_score(user.id))
end
}
@ -127,7 +125,7 @@ else
attributes :id, :photo_url, :name, :first_name, :last_name
node do |user|
{ latency: user_score(user.id), name: user.name }
{ name: user.name }.merge(user_score(user.id))
end
}
}
@ -156,7 +154,7 @@ 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) }
{ :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 }.merge(user_score(connection.user.id))
end
child(:tracks => :tracks) {

View File

@ -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

View File

@ -43,7 +43,7 @@ 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) {

View File

@ -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

View File

@ -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}}

View File

@ -242,8 +242,8 @@
<script type="text/template" id="template-latency">
<tr class="mb15">
<td class="{latency_style}">
{latency_text}
<td class="{{data.latency_style}} latency-value" 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}}
</td>
</tr>
<tr><td><div style='height:5px;'>&nbsp;</div></td></tr>

View File

@ -78,4 +78,13 @@
</ul>
</div>
</script>
<script type="text/template" id="template-help-musician-score-self">
<div class="help-musician-score-self">
<p>You are looking at your own account.</p>
<p>Try hovering over other user's latency score to find out your one-way latency to them.</p>
<p><span class="definition">Your Audio Gear Latency:</span> <span class="measurement my-gear-latency"><span class="measurement-value">{{data.my_gear_latency ? data.my_gear_latency + ' ms': '13 ms*'}}</span> <span class="measurement-absent">{{data.my_gear_latency ? '' : "(you have not qualified any gear, so we picked an average gear latency)"}}</span></span></p>
</div>
</script>

View File

@ -30,15 +30,6 @@
<!-- avatar -->
<div class="avatar-small"><img src="{avatar_url}" /></div>
</div>
<!-- todo scott vfrs-1455 i need a template tutorial to define the three variables that substitute here:
score:
musician_one_way_score is joined_score / 2;
musician_score_color is green, yellow, red, blue, or purple (depending upon value of joined_score)
musician_score_color_alt is good, moderate, poor, unacceptable,or missing
-->
<!-- <div class="left" style="***help***">
{musician_one_way_score} <img src="../assets/content/icon_{musician_score_color}_score.png" alt="{musician_score_color_alt}" width="12" height="12" align="absmiddle"/>
</div> -->
<div class="right musician-following" style="width: 120px;">
<div class="bold">FOLLOWING:</div>
<table class="musicians" cellpadding="0" cellspacing="5">{musician_follow_template}</table>

View File

@ -77,8 +77,10 @@
<%= render "clients/hoverBand" %>
<%= render "clients/hoverSession" %>
<%= render "clients/hoverRecording" %>
<%= render "clients/help" %>
<%= render 'dialogs/dialogs' %>
<script type="text/javascript">
$(function () {

View File

@ -1,3 +1,5 @@
- provide(:page_name, 'session_info')
- unless @music_session.nil?
- provide(:title, @music_session.name)
@ -154,5 +156,4 @@
%script{:type => 'text/template', :id => 'template-latency-detail'}
%table.musicians{:cellpadding => 0, :cellspacing => 0}
%tr.mb15
%td{:class => "{latencyStyle}"} {latencyDescription}
%td{:class => "{latency_style} latency"} {latency_text}

View File

@ -0,0 +1,17 @@
namespace :password do
desc "Resets every password in the database to jam123. development only!"
task smash: :environment do
raise "This rake taske is only available in development" unless Rails.env == 'development'
pw = 'jam123'
User.all.each do |user|
user.updating_password = true
user.password = pw
user.password_confirmation = pw
user.save
end
end
end

View File

@ -25,7 +25,7 @@ describe ApiMusicSessionsController do
get :ams_index, {client_id: conn.client_id}
response.should be_success
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 0
json[:sessions].length.should == 0
end
it "just self" do
@ -36,8 +36,8 @@ describe ApiMusicSessionsController do
get :ams_index, {client_id: conn.client_id}
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 1
json[0][:active_music_session][:participants][0][:user][:latency].should be_nil
json[:sessions].length.should == 1
json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should be_nil
end
it "someone else with no score with self" do
@ -48,8 +48,8 @@ describe ApiMusicSessionsController do
get :ams_index, {client_id: conn.client_id}
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 1
json[0][:active_music_session][:participants][0][:user][:latency].should be_nil
json[:sessions].length.should == 1
json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should be_nil
end
it "someone else with a score with a self" do
@ -61,8 +61,8 @@ describe ApiMusicSessionsController do
get :ams_index, {client_id: conn.client_id}
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 1
json[0][:active_music_session][:participants][0][:user][:latency].should == 17.5.ceil
json[:sessions].length.should == 1
json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should == 35 # 5 + 20 + 10
end
it "someone else with a score with a self, and another with an approved RSVP" do
@ -84,23 +84,23 @@ describe ApiMusicSessionsController do
get :ams_index, {client_id: conn.client_id}
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 1
json[0][:active_music_session][:participants][0][:user][:latency].should_not be_nil
json[0][:approved_rsvps].length.should == 2
json[:sessions].length.should == 1
json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should_not be_nil
json[:sessions][0][:approved_rsvps].length.should == 2
if json[0][:approved_rsvps][0][:id] == third_user.id
found_third_user = json[0][:approved_rsvps][0]
found_creator = json[0][:approved_rsvps][1]
if json[:sessions][0][:approved_rsvps][0][:id] == third_user.id
found_third_user = json[:sessions][0][:approved_rsvps][0]
found_creator = json[:sessions][0][:approved_rsvps][1]
found_creator[:id].should == other.id
else
found_third_user = json[0][:approved_rsvps][1]
found_creator = json[0][:approved_rsvps][0]
found_third_user = json[:sessions][0][:approved_rsvps][1]
found_creator = json[:sessions][0][:approved_rsvps][0]
found_third_user[:id].should == third_user.id
found_creator[:id].should == other.id
end
found_third_user[:latency].should == nil
found_creator[:latency].should == ((network_score + user.last_jam_audio_latency + other.last_jam_audio_latency ) / 2 ).ceil
found_third_user[:full_score].should == nil
found_creator[:full_score].should == ((network_score + user.last_jam_audio_latency + other.last_jam_audio_latency )).ceil
end
end
@ -111,7 +111,7 @@ describe ApiMusicSessionsController do
get :sms_index, {client_id: conn.client_id}
response.should be_success
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 0
json[:sessions].length.should == 0
end
it "just self" do
@ -120,9 +120,9 @@ describe ApiMusicSessionsController do
get :sms_index, {client_id: conn.client_id}
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 1
json[0][:approved_rsvps][0][:id].should == user.id
json[0][:approved_rsvps][0][:latency].should be_nil # you don't get scores to self
json[:sessions].length.should == 1
json[:sessions][0][:approved_rsvps][0][:id].should == user.id
json[:sessions][0][:approved_rsvps][0][:full_score].should be_nil # you don't get scores to self
end
it "someone else with no score with self" do
@ -131,9 +131,9 @@ describe ApiMusicSessionsController do
get :sms_index, {client_id: conn.client_id}
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 1
json[0][:approved_rsvps][0][:id].should == other.id
json[0][:approved_rsvps][0][:latency].should be_nil # there is no score with 'other '
json[:sessions].length.should == 1
json[:sessions][0][:approved_rsvps][0][:id].should == other.id
json[:sessions][0][:approved_rsvps][0][:full_score].should be_nil # there is no score with 'other '
end
it "scores with invitees and RSVP's" do
@ -150,11 +150,11 @@ describe ApiMusicSessionsController do
get :sms_index, {client_id: conn.client_id}
json = JSON.parse(response.body, :symbolize_names => true)
json.length.should == 1
json[0][:approved_rsvps][0][:id].should == other.id
json[0][:approved_rsvps][0][:latency].should == ((network_score + user.last_jam_audio_latency + other.last_jam_audio_latency) / 2).ceil
json[0][:invitations][0][:receiver_id].should == invitee.id
json[0][:invitations][0][:latency].should == ((network_score + user.last_jam_audio_latency + invitee.last_jam_audio_latency) / 2).ceil
json[:sessions].length.should == 1
json[:sessions][0][:approved_rsvps][0][:id].should == other.id
json[:sessions][0][:approved_rsvps][0][:full_score].should == ((network_score + user.last_jam_audio_latency + other.last_jam_audio_latency)).ceil
json[:sessions][0][:invitations][0][:receiver_id].should == invitee.id
json[:sessions][0][:invitations][0][:full_score].should == ((network_score + user.last_jam_audio_latency + invitee.last_jam_audio_latency)).ceil
end
end

View File

@ -4,7 +4,7 @@ describe ApiUsersController do
render_views
let(:user) { FactoryGirl.create(:user) }
let (:conn) { FactoryGirl.create(:connection, :user => user) }
let (:conn) { FactoryGirl.create(:connection, user: user, last_jam_audio_latency: 5) }
before(:each) do
@ -14,23 +14,34 @@ describe ApiUsersController do
describe "audio_latency" do
it "updates both connection and user" do
post :audio_latency, id: user.id, client_id: conn.client_id, audio_latency: 1.5, :format => 'json'
post :audio_latency, id: user.id, client_id: conn.client_id, audio_latency: 3.5, :format => 'json'
response.should be_success
conn.reload
conn.last_jam_audio_latency.should == 1.5
conn.last_jam_audio_latency.should == 3.5
user.reload
conn.user.last_jam_audio_latency.should == 1.5
conn.user.last_jam_audio_latency.should == 3.5
end
it "if connection does not exist, user is still updated" do
post :audio_latency, id: user.id, client_id: 'nothingness', audio_latency: 1.5, :format => 'json'
post :audio_latency, id: user.id, client_id: 'nothingness', audio_latency: 3.5, :format => 'json'
response.should be_success
user.reload
conn.user.last_jam_audio_latency.should == 1.5
conn.user.last_jam_audio_latency.should == 3.5
end
it "ignores latencies of 2 or less" do
post :audio_latency, id: user.id, client_id: conn.client_id, audio_latency: 2, :format => 'json'
response.should be_success
conn.reload
conn.last_jam_audio_latency.should == 5
user.reload
conn.user.last_jam_audio_latency.should == 5
end
end
end

View File

@ -4,9 +4,14 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
subject { page }
let(:user) { FactoryGirl.create(:user) }
let(:austin) { austin_geoip }
let(:dallas) { dallas_geoip }
let(:user) { FactoryGirl.create(:user, last_jam_locidispid: austin_geoip[:geoiplocation].) }
let(:finder) { FactoryGirl.create(:user) }
before(:each) do
UserMailer.deliveries.clear
ActiveMusicSession.delete_all
@ -23,8 +28,7 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
before(:each) do
emulate_client
sign_in_poltergeist user
visit "/client#/findSession"
fast_signin(user, "/client#/findSession")
FactoryGirl.create(:friendship, :user => user, :friend => finder)
end
@ -43,7 +47,7 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
describe "listing behavior" do
describe "active sessions" do
let!(:session1) { FactoryGirl.create(:single_user_session) }
let!(:session1_creator) { FactoryGirl.create(:single_user_session) }
it "find one active session" do
find('#btn-refresh').trigger(:click)
@ -62,6 +66,17 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
# find('#end-of-session-list')
# page.all('div#sessions-active .found-session').count.should == 21
end
it "shows latency information correctly" do
find('#btn-refresh').trigger(:click)
page.assert_selector('div#sessions-active .found-session', count: 1)
find(".latency-value.latency-unknown[data-user-id='#{session1_creator.id}']", text: 'UNKNOWN')
# create score with viewer and creator
score1, score2 = create_score(austin, dallas, { auserid: session1_creator.id, buserid: user.id }) # creates scores with very recent created_at, so it should be skipped
session1_creator
#screenshot_and_open_image
end
end
describe "scheduled sessions" do

View File

@ -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, geoipblock.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, geoipblock.coid)}
end
# attempts to make the creation of a score more straightforward.

View File

@ -569,7 +569,7 @@ module JamWebsockets
user = valid_login(username, password, token, client_id)
# protect against this user swamping the server
if Connection.where(user_id: user.id).count >= @max_connections_per_user
if user && Connection.where(user_id: user.id).count >= @max_connections_per_user
@log.warn "user #{user.id}/#{user.email} unable to connect due to max_connections_per_user #{@max_connections_per_user}"
raise SessionError, 'max_user_connections'
end