This commit is contained in:
Seth Call 2014-05-27 10:23:16 -05:00
parent a2bf56beac
commit dff3fa4870
19 changed files with 646 additions and 94 deletions

View File

@ -29,9 +29,12 @@ module JamRuby
# websocket gateway got a client with the same client_id as an already-connected client
DUPLICATE_CLIENT = 'DUPLICATE_CLIENT'
# info about how the test went
NETWORK_TEST_RESULT = 'NETWORK_TEST_RESULT'
DIAGNOSTIC_TYPES = [NO_HEARTBEAT_ACK, WEBSOCKET_CLOSED_REMOTELY, EXPIRED_STALE_CONNECTION,
MISSING_CLIENT_STATE, UNKNOWN_MESSAGE_TYPE, MISSING_ROUTE_TO,
DUPLICATE_CLIENT, WEBSOCKET_CLOSED_LOCALLY]
DUPLICATE_CLIENT, WEBSOCKET_CLOSED_LOCALLY, NETWORK_TEST_RESULT]
# creator types #
CLIENT = 'client'

View File

@ -3,9 +3,16 @@ module JamRuby
belongs_to :connection, class_name: 'JamRuby::Connection', foreign_key: :client_id, primary_key: :client_id
def heartbeat_interval_client
nil
end
def connection_expire_time_client
nil
end
def self.select_latency_tester
LatencyTester.joins(:connection).first
LatencyTester.joins(:connection).first!
end
# we need to find that latency_tester with the specified connection (and reconnect it)

View File

@ -132,6 +132,7 @@
if (!(context.JK.hasOneConfiguredDevice())) {
app.afterFtue = function() { submitForm(evt); };
app.layout.startNewFtue();
alert("dere")
return false;
}

View File

@ -444,7 +444,7 @@
function SessionStartRecording() {}
function SessionStopPlay() {}
function SessionStopRecording() {}
function SessionAddPlayTrack() {}
function SessionAddPlayTrack() {return true;}
function SessionRemoveAllPlayTracks(){}
function isSessionTrackPlaying() { return false; }
function SessionCurrrentPlayPosMs() { return 0; }
@ -675,17 +675,39 @@
fakeJamClientRecordings = fakeRecordingsImpl;
}
function OnLoggedIn(userId, sessionToken) {
}
function OnLoggedOut() {
}
function UserAttention(option) {
function TestNetworkPktBwRate(targetClientId, successCallback, timeoutCallback, testType, duration, numClients, payloadSize) {
var progress = {progress:true,
upthroughput:.95,
downthroughput:.95,
upjitter: 2.3,
downjitter: 2.3
}
var count = 0;
var interval = setInterval(function() {
eval(successCallback + "(" + JSON.stringify(progress) + ");");
if(progress.upthroughput < 1) {
progress.upthroughput += .05;
}
if(progress.downthroughput < 1) {
progress.downthroughput += .05;
}
count++;
if(count == duration) {
clearInterval(interval);
delete progress['progress']
progress.pass = true;
eval(successCallback + "(" + JSON.stringify(progress) + ");");
}
}, 1000);
}
function StopNetworkTest(targetClientId) {}
function OnLoggedIn(userId, sessionToken) {}
function OnLoggedOut() {}
function UserAttention(option) {}
function log(level, message) {
console.log("beep : " + message)
@ -902,6 +924,9 @@
this.RegisterP2PMessageCallbacks = RegisterP2PMessageCallbacks;
this.SetFakeRecordingImpl = SetFakeRecordingImpl;
// network test
this.TestNetworkPktBwRate = TestNetworkPktBwRate;
this.StopNetworkTest = StopNetworkTest;
this.log = log;
this.getOperatingMode = getOperatingMode;
this.clientID = "devtester";

View File

@ -89,6 +89,8 @@
register : "Register",
download : "DownloadClient",
audioTest : "AudioTest",
trackConfig : "AudioTrackConfig",
networkTest : "NetworkTest",
sessionCount : "SessionCount",
sessionMusicians : "SessionMusicians",
sessionQuality : "SessionQuality",
@ -281,6 +283,23 @@
context.ga('send', 'event', category, target, data);
}
function trackNetworkTest(platform, numUsers) {
var normalizedPlatform = translatePlatformForGA(platform);
context.ga('send', 'event', categories.networkTest, 'Passed', normalizedPlatform, numUsers);
}
function trackAudioTestCompletion(platform) {
var normalizedPlatform = translatePlatformForGA(platform);
context.ga('send', 'event', categories.audioTest, 'Passed', normalizedPlatform);
}
function trackConfigureTracksCompletion(platform) {
var normalizedPlatform = translatePlatformForGA(platform);
context.ga('send', 'event', categories.trackConfig, 'Passed', normalizedPlatform);
}
var GA = {};
GA.Categories = categories;
@ -294,6 +313,9 @@
GA.trackRegister = trackRegister;
GA.trackDownload = trackDownload;
GA.trackFTUECompletion = trackFTUECompletion;
GA.trackNetworkTest = trackNetworkTest;
GA.trackAudioTestCompletion = trackAudioTestCompletion;
GA.trackConfigureTracksCompletion = trackConfigureTracksCompletion;
GA.trackSessionCount = trackSessionCount;
GA.trackSessionMusicians = trackSessionMusicians;
GA.trackSessionQuality = trackSessionQuality;

View File

@ -103,6 +103,27 @@
}
function onCanceled() {
if (app.cancelFtue) {
app.cancelFtue();
app.afterFtue = null;
app.cancelFtue = null;
}
return closeDialog();
}
function onClosed() {
if (app.afterFtue) {
// If there's a function to invoke, invoke it.
app.afterFtue();
app.afterFtue = null;
app.cancelFtue = null;
}
return closeDialog();
}
function closeDialog() {
wizard.onCloseDialog();
app.layout.closeDialog('gear-wizard');
@ -111,8 +132,8 @@
function events() {
$(wizard).on('step_changed', onStepChanged);
$(wizard).on('wizard_cancel', closeDialog);
$(wizard).on('wizard_close', closeDialog);
$(wizard).on('wizard_cancel', onCanceled);
$(wizard).on('wizard_close', onClosed);
}
function setNextState(enabled) {

View File

@ -179,7 +179,13 @@
return false;
}
return save(tracks);
var saved = save(tracks);
if(saved) {
context.JK.GA.trackConfigureTracksCompletion(context.JK.detectOS());
}
return saved;
}
function beforeShow() {

View File

@ -5,6 +5,18 @@
context.JK = context.JK || {};
context.JK.StepNetworkTest = function (app, $dialog) {
var NETWORK_TEST_TYPES = {
RestPhase : 0,
PktTest100NormalLatency : 1,
PktTest200MediumLatency : 2,
PktTest400LowLatency : 3,
PktTestRateSweep : 4,
RcvOnly : 5
}
var STARTING_NUM_CLIENTS = 4;
var PAYLOAD_SIZE = 100;
var MINIMUM_ACCEPTABLE_SESSION_SIZE = 2;
var rest = context.JK.Rest();
var logger = context.JK.logger;
var $step = null;
@ -16,64 +28,355 @@
var $testScore = null;
var $testText = null;
var testedSuccessfully = false;
var serverClientId = null;
var $scoringBar = null;
var $goodMarker = null;
var $goodLine = null;
var $currentScore = null;
var $scoredClients = null;
var $subscore = null;
var serverClientId = '';
var isScoring = false;
var numClientsToTest = STARTING_NUM_CLIENTS;
var testSummary = {attempts : [], final:null}
var scoringZoneWidth = 100;//px
function reset() {
serverClientId = '';
isScoring = false;
numClientsToTest = STARTING_NUM_CLIENTS;
testSummary = {attempts : []};
}
function renderStartTest() {
$scoredClients.empty();
$testResults.removeClass('good acceptable bad').addClass('testing');
$testText.empty();
$subscore.empty();
updateControlsState();
$currentScore.width(0);
$goodLine.css('left', (gon.ftue_packet_rate_treshold * 100) + '%');
$goodMarker.css('left', (gon.ftue_packet_rate_treshold * 100) + '%');
}
function renderStopTest(score, text) {
$scoredClients.html(score);
$testText.html(text);
$testResults.removeClass('testing');
}
function postDiagnostic() {
rest.createDiagnostic({
type: 'NETWORK_TEST_RESULT',
data: {client_type: context.JK.clientType(), client_id: context.JK.JamServer.clientID, summary:testSummary}
});
}
function testFinished() {
var attempt = getCurrentAttempt();
if(!attempt.final) {
attempt.final = {reason : attempt.reason};
}
var reason = attempt.final.reason;
if(reason == "success") {
renderStopTest(attempt.num_clients, "Your router and Internet service will support sessions of up to " + attempt.num_clients + " JamKazam musicians.")
testedSuccessfully = true;
if(!attempt.final.num_clients) {
attempt.final.num_clients = attempt.num_clients;
}
context.JK.GA.trackNetworkTest(context.JK.detectOS(), attempt.final.num_clients);
//context.jamClient.updateLatencyTestScore(attempt.num_clients);
if(attempt.final.num_clients == 2) {
$testResults.addClass('acceptable');
}
else {
$testResults.addClass('good');
}
}
else if(reason == "minimum_client_threshold") {
renderStopTest('', "We're sorry, but your router and Internet service will not effectively support JamKazam sessions. Please click the HELP button for more information.")
}
else if(reason == "unreachable") {
renderStopTest('', "We're sorry, but your router will not support JamKazam in its current configuration. Please click the HELP button for more information.");
}
else if(reason == "internal_error") {
context.JK.alertSupportedNeeded("The JamKazam client software had an unexpected problem while scoring your Internet connection.");
renderStopTest('', '');
}
else if(reason == "remote_peer_cant_test") {
context.JK.alertSupportedNeeded("JamKazam is experiencing technical difficulties.");
renderStopTest('', '');
}
else if(reason == "invalid_response") {
context.JK.alertSupportedNeeded("The JamKazam client software had an unexpected problem while scoring your Internet connection. Reason=" + attempt.backend_data.reason + '.');
renderStopTest('', '');
}
else if(reason == 'no_servers') {
context.JK.alertSupportedNeeded("No network test servers are available. You can skip this step for now.");
renderStopTest('', '');
testedSuccessfully = true;
}
else if(reason == 'no_network') {
context.JK.Banner.showAlert("Please try again later. Your network appears down.");
renderStopTest('', '');
}
else if(reason == "rest_api_error") {
context.JK.alertSupportedNeeded("Unable to network test servers are available. You can skip this step for now.");
testedSuccessfully = true;
renderStopTest('', '');
}
else if(reason == "timeout") {
context.JK.alertSupportedNeeded("Unable to network test servers timed out. You can skip this step for now.");
testedSuccessfully = true;
renderStopTest('', '');
}
else {
context.JK.alertSupportedNeeded("The JamKazam client software had a logic error while scoring your Internet connection.");
renderStopTest('', '');
}
numClientsToTest = STARTING_NUM_CLIENTS;
isScoring = false;
updateControlsState();
postDiagnostic();
}
function getCurrentAttempt() {
return testSummary.attempts[testSummary.attempts.length - 1];
}
function attemptTestPass() {
var attempt = {};
attempt.payload_size = PAYLOAD_SIZE;
attempt.duration = gon.ftue_network_test_duration;
attempt.test_type = 'PktTest400LowLatency';
attempt.num_clients = numClientsToTest;
attempt.server_client_id = serverClientId;
attempt.received_progress = false;
testSummary.attempts.push(attempt);
//context.jamClient.StopNetworkTest('');
$testText.text("Simulating the network traffic of a " + numClientsToTest + "-person session.");
updateProgress(0, false);
$currentScore.css
context.jamClient.TestNetworkPktBwRate(serverClientId, TEST_SUCCESS_CALLBACK, TEST_TIMEOUT_CALLBACK,
NETWORK_TEST_TYPES.PktTest400LowLatency,
gon.ftue_network_test_duration,
numClientsToTest,
PAYLOAD_SIZE);
}
function startNetworkTest() {
isScoring = true;
numClientsToTest = STARTING_NUM_CLIENTS;
renderStartTest();
rest.getLatencyTester()
.done(function(response) {
// ensure there are no tests ongoing
serverClientId = response.client_id;
logger.info("beginning network test against client_id: " + clientId);
logger.info("beginning network test against client_id: " + serverClientId);
context.jamClient.TestNetworkPktBwRate(serverClientId, TEST_SUCCESS_CALLBACK, TEST_TIMEOUT_CALLBACK);
attemptTestPass();
})
.fail(function() {
isScoring = false;
logger.error("arguments:", arguments);
if(context.JK.isNetworkError(arguments)) {
context.JK.Banner.showAlert("Please try again latery. Your network appears down.");
.fail(function(jqXHR) {
if(jqXHR.status == 404) {
// means there are no network testers available.
// we have to skip this part of the UI
testSummary.final = {reason: 'no_servers'}
}
else {
logger.error("unable to get latency tester from server");
if(context.JK.isNetworkError(arguments)) {
testSummary.final = {reason: 'no_network'}
}
else {
testSummary.final = {reason: 'rest_api_error'}
}
}
testFinished();
})
logger.info("starting network test");
return false;
}
function networkTestSuccess() {
console.log("success arguments: ", arguments);
context.jamClient.StopNetworkTest(serverClientId);
function updateProgress(throughput, showSubscore) {
var width = throughput * 100;
$currentScore.stop().data('showSubscore', showSubscore);
if(!showSubscore) {
$subscore.text('');
}
$currentScore.animate({
duration: 1000,
width: width + '%'
}, {
step: function (now, fx) {
if(showSubscore) {
var newWidth = ( 100 * parseFloat($currentScore.css('width')) / parseFloat($currentScore.parent().css('width')) );
$subscore.text((Math.round(newWidth * 10) / 10) + '%');
}
}
}).css('overflow', 'visible');
;
}
function networkTestTimeout() {
console.log("timeout arguments:", arguments);
context.jamClient.StopNetworkTest(serverClientId);
function networkTestSuccess(data) {
var attempt = getCurrentAttempt();
function refineTest(up) {
if(up) {
if(numClientsToTest == gon.ftue_network_test_max_clients) {
attempt.reason = "success";
testFinished();
}
else {
numClientsToTest++;
logger.debug("increasing number of clients to " + numClientsToTest);
setTimeout(attemptTestPass, 1);
}
}
else {
// reduce numclients if we can
if(numClientsToTest == MINIMUM_ACCEPTABLE_SESSION_SIZE) {
// we are too low already. fail the user
attempt.reason = "minimum_client_threshold";
testFinished();
}
else if(numClientsToTest > STARTING_NUM_CLIENTS) {
// this means we've gone up before... so don't go back down (i.e., creating a loop)
attempt.reason = "success";
attempt.final = { reason:'success', num_clients: numClientsToTest - 1 }
testFinished();
}
else {
numClientsToTest--;
logger.debug("reducing number of clients to " + numClientsToTest);
setTimeout(attemptTestPass, 1);
}
}
}
attempt.backend_data = data;
if(data.progress === true) {
var animate = true;
if(data.downthroughput && data.upthroughput) {
if(data.downthroughput > 0 || data.upthroughput > 0) {
attempt.received_progress = true;
animate = true;
}
if(attempt.received_progress) {
// take the lower
var throughput= data.downthroughput < data.upthroughput ? data.downthroughput : data.upthroughput;
updateProgress(throughput, true);
}
}
}
else {
logger.debug("network test pass success. data: ", data);
if(data.reason == "unreachable") {
// STUN
logger.debug("network test: unreachable (STUN issue or similar)");
attempt.reason = data.reason;
testFinished();
}
else if(data.reason == "internal_error") {
// oops
logger.debug("network test: internal_error (client had a unexpected problem)");
attempt.reason = data.reason;
testFinished();
}
else if(data.reason == "remote_peer_cant_test") {
// old client
logger.debug("network test: remote_peer_cant_test (old client)")
attempt.reason = data.reason;
testFinished();
}
else {
if(!data.downthroughput || !data.upthroughput) {
// we have to assume this is bad. just not a reason we know about in code
logger.debug("network test: no test data (unknown issue? " + data.reason + ")")
attempt.reason = "invalid_response";
testFinished();
}
else {
// success... but we still have to verify if this data is within threshold
if(data.downthroughput < gon.ftue_packet_rate_treshold) {
logger.debug("network test: downthroughput too low. downthroughput: " + data.downthroughput + ", threshold: " + gon.ftue_packet_rate_treshold);
refineTest(false);
}
else if(data.upthroughput < gon.ftue_packet_rate_treshold) {
logger.debug("network test: upthroughput too low. upthroughput: " + data.upthroughput + ", threshold: " + gon.ftue_packet_rate_treshold);
refineTest(false);
}
else {
// true success. we can accept this score
logger.debug("network test: success")
refineTest(true);
}
}
}
// VRFS-1742
// context.jamClient.StopNetworkTest(serverClientId);
}
}
function networkTestTimeout(data) {
logger.warn("network timeout when testing latency test: " + data);
var attempt = getCurrentAttempt();
attempt.reason = 'timeout';
attempt.backend_data = data;
testFinished();
}
function hasScoredNetworkSuccessfully() {
return testedSuccessfully;
}
function updateControlsState() {
initializeNextButtonState();
initializeBackButtonState();
}
function initializeNextButtonState() {
$dialog.setNextState(hasScoredNetworkSuccessfully());
$dialog.setNextState(hasScoredNetworkSuccessfully() && !isScoring);
}
function initializeBackButtonState() {
$dialog.setNextState();
$dialog.setBackState(!isScoring);
}
function newSession() {
isScoring = false;
// XXX context.jamClient.stopNetworkTest();
reset();
//context.jamClient.StopNetworkTest('');
}
function beforeShow() {
initializeNextButtonState();
reset();
updateControlsState();
}
function initialize(_$step) {
@ -83,7 +386,12 @@
$testResults = $step.find('.network-test-results');
$testScore = $step.find('.network-test-score');
$testText = $step.find('.network-test-text');
$scoringBar = $step.find('.scoring-bar');
$goodMarker = $step.find('.good-marker');
$goodLine =$step.find('.good-line');
$currentScore = $step.find('.current-score');
$scoredClients= $step.find('.scored-clients');
$subscore = $step.find('.subscore');
$startNetworkTestBtn.on('click', startNetworkTest);
}

View File

@ -932,9 +932,15 @@
// lie for now until IO questions finalize
validIOScore = true;
onSuccessfulScore();
renderScoringStopped();
}
function onSuccessfulScore() {
}
// refocused affects how IO testing occurs.
// on refocus=true:
// * reuse IO score if it was good/acceptable
@ -1049,7 +1055,9 @@
return false;
}
else {
//XXX rename profile
context.jamClient.FTUESave(true);
context.JK.GA.trackAudioTestCompletion(context.JK.detectOS());
return true;
}

View File

@ -13,6 +13,7 @@
var $wizardSteps = null;
var $currentWizardStep = null;
var $wizardButtons = null;
var $btnHelp = null;
var $btnNext = null;
var $btnBack = null;
var $btnClose = null;
@ -21,7 +22,7 @@
var $self = $(this);
function totalSteps() {
return STEPS.length;
return context.JK.dkeys(STEPS).length;
}
function beforeHideStep() {
@ -62,7 +63,7 @@
var stepInfo = STEPS[step];
if(stepInfo.handleNext) {
var result = stepInfo.handleNext.call(stepInfo);
if(!result) {return false;}
if(result === false) {return false;}
}
previousStep = step;
@ -81,25 +82,32 @@
$currentWizardStep = $nextWizardStep;
context.JK.GA.virtualPageView(location.pathname + location.search + location.hash, $currentWizardStep.attr('dialog-title'));
$self.triggerHandler('step_changed', {step:step});
// update buttons
var $wizardButtonsContent = $(context._.template($templateButtons.html(), {}, {variable: 'data'}));
$btnHelp = $wizardButtonsContent.find('.btn-help');
$btnBack = $wizardButtonsContent.find('.btn-back');
$btnNext = $wizardButtonsContent.find('.btn-next');
$btnClose = $wizardButtonsContent.find('.btn-close');
$btnCancel = $wizardButtonsContent.find('.btn-cancel');
// hide help button if on last step
if (step == totalSteps() - 1) {
$btnHelp.hide();
}
// hide back button if 1st step or last step
if (step == 0 && step == totalSteps() - 1) {
if (step == 0 || step == totalSteps() - 1) {
$btnBack.hide();
}
// hide next button if not on last step
// hide next button if on last step
if (step == totalSteps() - 1) {
$btnNext.hide();
}
// hide close if on last step
// hide close if not on last step
if (step != totalSteps() - 1) {
$btnClose.hide();
}
@ -130,7 +138,7 @@
previousStep = null;
step = args.d1;
step = args != null ? args.d1 : 0;
if (!step) step = 0;
step = parseInt(step);
moveToStep();
@ -177,7 +185,6 @@
}
function initialize(_$dialog, _$wizardSteps, _STEPS) {
$dialog = _$dialog;
$wizardSteps = _$wizardSteps;
STEPS = _STEPS;

View File

@ -678,9 +678,9 @@
function startNewFtue() {
var step = 0;
setWizardStep(step);
wizardShowFunctions[step]();
showDialog('ftue');
//setWizardStep(step);
//wizardShowFunctions[step]();
showDialog('gear-wizard');
}
function setWizardStep(targetStepId) {

View File

@ -46,7 +46,13 @@
for (i=0; i < localMusicTracks.length; i++) {
var track = {};
track.client_track_id = localMusicTracks[i].id;
track.instrument_id = context.JK.client_to_server_instrument_map[localMusicTracks[i].instrument_id].server_id;
if(localMusicTracks[i].instrument_id === 0) {
track.instrument_id = context.JK.server_to_client_instrument_map["Other"].server_id;
}
else {
track.instrument_id = context.JK.client_to_server_instrument_map[localMusicTracks[i].instrument_id].server_id;
}
if (localMusicTracks[i].stereo) {
track.sound = "stereo";
}

View File

@ -57,7 +57,7 @@
margin-top:20px;
}
.ftue-buttons {
.wizard-buttons {
position: absolute;
bottom: 0;
width:100%;
@ -67,7 +67,7 @@
}
.ftue-buttons-holder {
.wizard-buttons-holder {
float:right;
}
@ -151,6 +151,9 @@
width:25%;
}
.watch-video {
margin-top:29px;
}
.select-audio-input-device {
margin-bottom:20px;
}
@ -378,6 +381,10 @@
}
}
.watch-video {
margin-top:45px;
}
.icon-instrument-select {
padding:3px 0; // to combine 24 of .current-instrument + 3x on either side
margin:0 auto 15px; // 15 margin-bottom to match tracks on the left
@ -478,13 +485,21 @@
&[track-count="2"] {
.ftue-input {
width:50%;
width:49%;
display:inline-block;
&:nth-of-type(1) {
float:left;
&:after {
float:left;
content: ',';
padding-right:3px;
}
}
&:nth-of-type(2) {
float:right;
}
}
/**.ftue-input:nth-child(1)::before {
content: ',';
padding-right:3px;
}*/
}
}
}
@ -499,6 +514,9 @@
}
}
.watch-video {
margin-top:97px;
}
.voicechat-option {
@ -625,6 +643,10 @@
margin-top:22px;
}
.watch-video {
margin-top:90px;
}
a.start-network-test {
margin-top:20px;
}
@ -635,6 +657,8 @@
color:white;
font-size:20px;
background-color:#222;
text-align:center;
margin-bottom:20px;
&.good {
background-color: #72a43b;
@ -647,6 +671,63 @@
}
}
.scoring-bar {
width:100%;
height:20px;
left:0;
position:relative;
//display:inline-block;
display:none;
.current-score {
background-color:gray;
border-right:1px solid white;
border-top:1px solid #ccc;
border-bottom:1px solid #ccc;
border-left:1px solid #ccc;
height:20px;
display:inline-block;
position:relative;
left:0;
min-width:55px;
text-align:left;
padding-left:5px;
@include border_box_sizing;
font-size:12px;
color:white;
.subscore {
font-size:10px;
color:white;
bottom:-15px;
right:-16px;
position:absolute;
}
}
.good-marker {
position:absolute;
text-align:center;
left:95%;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #72a43b;
margin-left:-5px;
top:-7px;
}
.good-line {
position:absolute;
height:100%;
left:95%;
width:1px;
background-color: #72a43b;
margin-left:-0.5px;
top:0;
}
}
.network-test-text {
}
@ -655,16 +736,41 @@
height: 248px ! important;
@include border_box_sizing;
&.testing {
text-align:left;
.network-test-score {
font-size:16px;
display:none;
}
.scoring-bar {
display:inline-block;
margin-bottom:10px;
}
.network-test-text {
background-image: url('/assets/shared/spinner.gif');
background-repeat:no-repeat;
background-position:center;
//background-image: url('/assets/shared/spinner.gif');
//background-repeat:no-repeat;
//background-position:center;
//width:128px;
height:128px;
//height:128px;
}
}
&.good {
.network-test-score {
background-color: #72a43b;
}
}
&.acceptable {
.network-test-score {
background-color: #D6A800;
}
}
&.bad {
.network-test-score {
background-color: #7B0C00;
}
}
}
@ -674,10 +780,15 @@
.wizard-step-content .wizard-step-column {
&:nth-of-type(1) {
width:50%;
height:350px;
}
&:nth-of-type(2) {
width:50%;
}
ul {
margin-bottom:20px;
}
}
}

View File

@ -52,6 +52,9 @@ class ClientsController < ApplicationController
gon.fp_upload_dir = Rails.application.config.filepicker_upload_dir
gon.allow_force_native_client = Rails.application.config.allow_force_native_client
gon.ftue_io_wait_time = Rails.application.config.ftue_io_wait_time
gon.ftue_packet_rate_treshold = Rails.application.config.ftue_packet_rate_treshold
gon.ftue_network_test_duration = Rails.application.config.ftue_network_test_duration
gon.ftue_network_test_max_clients = Rails.application.config.ftue_network_test_max_clients
# is this the native client or browser?
@nativeClient = is_native_client?

View File

@ -4,9 +4,9 @@
- total_steps = 7
.ftue-buttons
.ftue-buttons-holder
%a.button-grey{href: '#'} HELP
.wizard-buttons
.wizard-buttons-holder
%a.button-grey.btn-help{href: '#'} HELP
- if step > 0 && step != total_steps
%a.button-orange.btn-back{href:'#'} BACK
- if step != total_steps

View File

@ -217,10 +217,10 @@
.wizard-step-column
%h2 Instructions
.ftue-box.instructions
Find the Direct Monitoring control on your audio interface.<br>
%ul
%li If a button, push it into its off position
%li If a knob, turn it so that 100% of audio is from your computer, and 0% is from the direct monitor
%li Check that computer is connected to router using Ethernet cable.
%li Click Start Network Test button.
%li View test results.
.center
%a.button-orange.watch-video{href:'#'} WATCH VIDEO
.wizard-step-column
@ -232,7 +232,14 @@
.wizard-step-column
%h2 Test Results
.network-test-results.ftue-box
.scoring-bar
.current-score
testing...
.subscore
.good-marker
.good-line
.network-test-score
.scored-clients
.network-test-text
@ -246,28 +253,26 @@
%p Have fun and thanks for joining us!
%p — Team JamKazam
.wizard-step-column
%h2
Tutorial Videos
%ul
%li
%a Creating a Session
%li
%a Finding a Session
%li
%a Playing in a Session
%li
%a Connecting with Other Musicians
%li
%a Making and Sharing Recordings
%li
%a Broadcasting Your Sessions
%h2
Other Valuable Resource Links
%ul
%li
%a JamKazam Support Center
%li
%a JamKazam Community Forum
%h2 Tutorial Videos
%ul
%li
%a Creating a Session
%li
%a Finding a Session
%li
%a Playing in a Session
%li
%a Connecting with Other Musicians
%li
%a Making and Sharing Recordings
%li
%a Broadcasting Your Sessions
%h2 Other Valuable Resource Links
%ul
%li
%a JamKazam Support Center
%li
%a JamKazam Community Forum
.wizard-buttons
%script{type: 'text/template', id: 'template-ftuesteps'}
@ -289,9 +294,9 @@
%script{type: 'text/template', id: 'template-wizard-buttons'}
.ftue-buttons-holder
.wizard-buttons-holder
%a.button-grey.btn-cancel{href:'#', 'layout-action' => 'close'} CANCEL
%a.button-grey{href: '#'} HELP
%a.button-grey.btn-help{href: '#'} HELP
%a.button-orange.btn-back{href:'#'} BACK
%a.button-orange.btn-next{href:'#'} NEXT
%a.button-orange.btn-close{href:'#', 'layout-action' => 'close'} CLOSE

View File

@ -235,5 +235,11 @@ if defined?(Bundler)
# how long should the frontend wait for the IO to stabilize before asking for a IO score?
config.ftue_io_wait_time = 10
# what should the threshold be for us to say, 'this person can't play at this rate' during the network test
config.ftue_packet_rate_treshold = 0.95
# how long to test at each network test step
config.ftue_network_test_duration = 10
# max number of people to test
config.ftue_network_test_max_clients = 8
end
end

View File

@ -1,7 +1,20 @@
require 'spec_helper'
describe ApiFeedsController do
describe ApiLatencyTestersController do
render_views
before(:each) do
LatencyTester.delete_all
end
describe "match" do
it "insists on login" do
get :match
response.status.should == 403
end
it "throws 404 if no latency testers"
end
end

View File

@ -480,10 +480,10 @@ module JamWebsockets
default_expire = @connect_time_expire_client
end
heartbeat_interval = user.try(:heartbeat_interval_client) || default_heartbeat
heartbeat_interval = (user && user.heartbeat_interval_client) || default_heartbeat
heartbeat_interval = heartbeat_interval.to_i
heartbeat_interval = default_heartbeat if heartbeat_interval == 0 # protect against bad config
connection_expire_time = user.try(:connection_expire_time_client) || default_expire
connection_expire_time = (user && user.connection_expire_time_client) || default_expire
connection_expire_time = connection_expire_time.to_i
connection_expire_time = default_expire if connection_expire_time == 0 # protect against bad config
connection_stale_time = default_stale # no user override exists for this; not a very meaningful time right now
@ -825,7 +825,7 @@ module JamWebsockets
# by not catching any exception here, a PermissionError will be thrown if this isn't valid
# if for some reason the client is trying to send to a client that it doesn't
# belong to
access_p2p(to_client_id, context.user, client_msg)
#access_p2p(to_client_id, context.user, client_msg)
if to_client_id.nil? || to_client_id == 'undefined' # javascript translates to 'undefined' in many cases
raise SessionError, "empty client_id specified in peer-to-peer message"