diff --git a/web/app/assets/javascripts/fakeJamClient.js b/web/app/assets/javascripts/fakeJamClient.js index 98b64917b..4f5695abb 100644 --- a/web/app/assets/javascripts/fakeJamClient.js +++ b/web/app/assets/javascripts/fakeJamClient.js @@ -441,10 +441,19 @@ } + function SetVideoNetworkTestScore(numClients) { + + } + function GetNetworkTestScore() { return 8; } + + function GetVideoNetworkTestScore() { + return 8; + } + function SetLatencyTestBlocked(blocked) { } @@ -1044,6 +1053,8 @@ this.IsMyNetworkWireless = IsMyNetworkWireless; this.SetNetworkTestScore = SetNetworkTestScore; this.GetNetworkTestScore = GetNetworkTestScore; + this.SetVideoNetworkTestScore = SetVideoNetworkTestScore; + this.GetVideoNetworkTestScore = GetVideoNetworkTestScore; this.SetLatencyTestBlocked = SetLatencyTestBlocked; this.isLatencyTestBlocked = isLatencyTestBlocked; this.GetLastLatencyTestTimes = GetLastLatencyTestTimes; diff --git a/web/app/assets/javascripts/networkTestHelper.js b/web/app/assets/javascripts/networkTestHelper.js index 7481672b7..64de82b54 100644 --- a/web/app/assets/javascripts/networkTestHelper.js +++ b/web/app/assets/javascripts/networkTestHelper.js @@ -13,8 +13,10 @@ PktTestRateSweep: 4, RcvOnly: 5 } - var STARTING_NUM_CLIENTS = 4; - var PAYLOAD_SIZE = gon.global.ftue_network_test_packet_size; + var STARTING_NUM_CLIENTS_AUDIO = 4; + var STARTING_NUM_CLIENTS_VIDEO = 2; + var AUDIO_PAYLOAD_SIZE = gon.global.ftue_network_test_packet_size; + var VIDEO_PAYLOAD_SIZE = gon.global.ftue_network_test_packet_size_video; var MINIMUM_ACCEPTABLE_SESSION_SIZE = 2; var RETRY_THRESHOLD = 2; @@ -28,24 +30,32 @@ var $startNetworkTestBtn = null; var $foreverNetworkTestBtn = null; var $testResults = null; - var $testScore = null; + var $testScoreAudio = null; + var $testScoreVideo= null; var $testText = null; + var $inProgressText = null; + var $audioResultText = null; + var $videoResultText = null; var testedSuccessfully = false; var $scoringBar = null; var $goodMarker = null; var $goodLine = null; var $currentScore = null; - var $scoredClients = null; + var $scoredClientsAudio = null; + var $scoredClientsVideo = null; var $subscore = null; var $watchVideo = null; + var $container = null; var backendGuardTimeout = null; var primeGuardTimeout = null; var primeDeferred = null; var serverClientId = ''; - var scoring = false; - var numClientsToTest = STARTING_NUM_CLIENTS; - var testSummary = {attempts: [], final: null} + var audioScoring = false; + var videoScoring = false; + var numClientToTestAudio = STARTING_NUM_CLIENTS_AUDIO; + var numClientToTestVideo = STARTING_NUM_CLIENTS_VIDEO; + var testSummary = {audioAttempts: [], videoAttempts: [], final: null} var $self = $(this); var scoringZoneWidth = 100;//px var inGearWizard = false; @@ -124,30 +134,99 @@ function resetTestState() { serverClientId = ''; - scoring = false; - numClientsToTest = STARTING_NUM_CLIENTS; - testSummary = {attempts: []}; + audioScoring = false; + videoScoring = false; + numClientToTestAudio = STARTING_NUM_CLIENTS_AUDIO; + numClientToTestVideo = STARTING_NUM_CLIENTS_VIDEO; + testSummary = {audioAttempts: [], videoAttempts:[]}; configureStartButton(); - $scoredClients.empty(); + $scoredClientsAudio.empty(); $testResults.removeClass('good acceptable bad testing'); - $testText.empty(); + $testScoreAudio.removeClass('good acceptable bad testing'); + $testScoreVideo.removeClass('good acceptable bad testing'); + $scoredClientsAudio.text('-') + $scoredClientsVideo.text('-') + $inProgressText.empty(); + $audioResultText.empty(); + $audioResultText.hide(); + $videoResultText.empty(); + $videoResultText.hide(); $subscore.empty(); $currentScore.width(0); bandwidthSamples = []; } - function renderStartTest() { + function renderStartTestAudio() { configureStartButton(); $testResults.addClass('testing'); + $testScoreAudio.addClass('testing'); $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); + function renderStartTestVideo() { + configureStartButton(); + $testResults.addClass('testing'); + $testScoreVideo.addClass('testing'); + $goodLine.css('left', (gon.ftue_packet_rate_treshold * 100) + '%'); + $goodMarker.css('left', (gon.ftue_packet_rate_treshold * 100) + '%'); + } + + function renderStopTestAudio(score, text) { + if(!score || score.length == 0) { + $scoredClientsAudio.html('0'); + + $inProgressText.html('The audio test did not pass. Video is not tested in this case.

Please click HERE for help information.'); + } + else { + $scoredClientsAudio.html(score); + } + + if(text && text.length > 0) { + $audioResultText.text(text); + } $testResults.removeClass('testing'); + $testScoreAudio.removeClass('testing'); + + } + + function renderStopTestVideo(score, text) { + logger.debug("renderStopTestVideo", score, text) + + // don't show the audio result text until the test is over (it looks confusing otherwise). + if($audioResultText.text() && $audioResultText.text().length > 0) { + $audioResultText.show(); + } + + $inProgressText.text('Your router and Internet service will support:') + + if(!score || score.length == 0) { + $scoredClientsVideo.html('-'); + } + else { + + if(score < 2) { + $scoredClientsVideo.html('0') + $videoResultText.html('No other players when in a video + audio session.').show(); + $testScoreVideo.addClass('acceptable'); + } + else { + $scoredClientsVideo.html(score); + + var summary = "Video + audio sessions with up to " + score + " players"; + + if (text && text.length > 0) { + // presence of text means there was an error on the last test pass. + summary += '. Note that there was an error when testing for ' + (score + 1) + 'players. Support code=' + text + } + + $videoResultText.html(summary).show(); + } + } + + $testResults.removeClass('testing'); + $testScoreVideo.removeClass('testing'); } function postDiagnostic() { @@ -205,8 +284,8 @@ } } - function testFinished() { - var attempt = getCurrentAttempt(); + function testFinishedAudio() { + var attempt = getCurrentAttemptAudio(); if (!testSummary.final) { testSummary.final = {reason: attempt.reason}; @@ -216,7 +295,7 @@ var success = false; if (reason == "success") { - renderStopTest(attempt.num_clients, "Your router and Internet service will support sessions of up to " + attempt.num_clients + " JamKazam musicians.") + renderStopTestAudio(attempt.num_clients, "Audio-only sessions with up to " + attempt.num_clients + " players") testedSuccessfully = true; if (!testSummary.final.num_clients) { testSummary.final.num_clients = attempt.num_clients; @@ -231,112 +310,253 @@ context.jamClient.SetNetworkTestScore(attempt.num_clients); if (testSummary.final.num_clients == 2) { - $testResults.addClass('acceptable'); + $testScoreAudio.addClass('acceptable'); } else { - $testResults.addClass('good'); + $testScoreAudio.addClass('good'); } success = true; } else if (reason == "minimum_client_threshold") { context.jamClient.SetNetworkTestScore(0); - renderStopTest('', "We're sorry, but your router and Internet service will not effectively support JamKazam sessions. Please click the HELP button for more information.") + renderStopTestAudio('', "We're sorry, but your router and Internet service will not effectively support JamKazam sessions. Please click the HELP button for more information.") storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.bandwidth, avgBandwidth(attempt.num_clients - 1)); } else if (reason == "unreachable" || reason == "no-transmit") { context.jamClient.SetNetworkTestScore(0); // https://jamkazam.atlassian.net/browse/VRFS-2323 - renderStopTest('', "We're sorry, but your router will not support JamKazam in its current configuration. Please click HERE for more information."); + renderStopTestAudio('', "We're sorry, but your router will not support JamKazam in its current configuration. Please click HERE for more information."); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.stun, attempt.num_clients); } else if (reason == "internal_error") { context.JK.alertSupportedNeeded("The JamKazam client software had an unexpected problem while scoring your Internet connection."); - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else if (reason == "remote_peer_cant_test") { context.JK.alertSupportedNeeded("The JamKazam service is experiencing technical difficulties."); - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else if (reason == "server_comm_timeout") { gearUtils.skipNetworkTest(); context.JK.alertSupportedNeeded("Communication with the JamKazam network service has timed out." + appendContextualStatement()); - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else if (reason == 'backend_gone') { context.JK.alertSupportedNeeded("The JamKazam client is experiencing technical difficulties."); - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else if (reason == "invalid_response") { gearUtils.skipNetworkTest(); context.JK.alertSupportedNeeded("The JamKazam client software had an unexpected problem while scoring your Internet connection.

Reason: " + attempt.backend_data.reason + '.'); - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else if (reason == 'no_servers') { gearUtils.skipNetworkTest(); context.JK.Banner.showAlert("No network test servers are available." + appendContextualStatement()); - renderStopTest('', ''); + renderStopTestAudio('', ''); testedSuccessfully = true; storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else if (reason == 'no_network') { context.JK.Banner.showAlert("Please try again later. Your network appears down."); - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.noNetwork); } else if (reason == "rest_api_error") { gearUtils.skipNetworkTest(); context.JK.alertSupportedNeeded("Unable to acquire a network test server." + appendContextualStatement()); testedSuccessfully = true; - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else if (reason == "timeout") { gearUtils.skipNetworkTest(); context.JK.alertSupportedNeeded("Communication with the JamKazam network service timed out." + appendContextualStatement()); testedSuccessfully = true; - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } else { gearUtils.skipNetworkTest(); context.JK.alertSupportedNeeded("The JamKazam client software had a logic error while scoring your Internet connection."); - renderStopTest('', ''); + renderStopTestAudio('', ''); storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); } - numClientsToTest = STARTING_NUM_CLIENTS; - scoring = false; - configureStartButton(); + numClientToTestAudio = STARTING_NUM_CLIENTS_AUDIO; + audioScoring = false; postDiagnostic(); if (success) { - $self.triggerHandler(NETWORK_TEST_DONE) + + startVideoTest(); + if(forever) { prepareNetworkTest(); } } else { + configureStartButton(); + $self.triggerHandler(NETWORK_TEST_FAIL) } } - function getCurrentAttempt() { - return testSummary.attempts[testSummary.attempts.length - 1]; + function testFinishedVideo() { + + var attempt = getCurrentAttemptVideo(); + + if (!testSummary.video_final) { + testSummary.video_final = {reason: attempt.reason, num_clients: attempt.num_clients}; + } + + if (!testSummary.video_final.num_clients) { + testSummary.video_final.num_clients = attempt.num_clients; + } + + var reason = testSummary.video_final.reason; + var success = false; + + logger.debug("testFinishedVideo", testSummary) + + if (reason == "success") { + renderStopTestVideo(attempt.num_clients, null) + //testedSuccessfully = true; + if (!testSummary.video_final.num_clients) { + testSummary.video_final.num_clients = attempt.num_clients; + } + + // context.jamClient.GetNetworkTestScore() == 0 is a rough approximation if the user has passed the FTUE before + if (inGearWizard || context.jamClient.GetVideoNetworkTestScore() == 0) { + //trackedPass = true; + //lastNetworkFailure = null; + //context.JK.GA.trackNetworkTest(context.JK.detectOS(), testSummary.final.num_clients); + } + + context.jamClient.SetVideoNetworkTestScore(attempt.num_clients); + if (!testSummary.video_final.num_clients) { + $testScoreVideo.addClass('acceptable'); + } + else if (testSummary.video_final.num_clients >= 2) { + $testScoreVideo.addClass('good'); + } + else { + $testScoreVideo.addClass('acceptable'); + } + success = true; + } + else if (reason == "minimum_client_threshold") { + context.jamClient.SetVideoNetworkTestScore(testSummary.video_final.num_clients - 1); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason) + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.bandwidth, avgBandwidth(attempt.num_clients - 1)); + } + else if (reason == "unreachable" || reason == "no-transmit") { + context.jamClient.SetVideoNetworkTestScore(testSummary.video_final.num_clients - 1); + // https://jamkazam.atlassian.net/browse/VRFS-2323 + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + // storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.stun, attempt.num_clients); + } + else if (reason == "internal_error") { + context.JK.alertSupportedNeeded("The JamKazam client software had an unexpected problem while scoring your Internet connection."); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else if (reason == "remote_peer_cant_test") { + context.JK.alertSupportedNeeded("The JamKazam service is experiencing technical difficulties."); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else if (reason == "server_comm_timeout") { + //gearUtils.skipNetworkTest(); + context.JK.alertSupportedNeeded("Communication with the JamKazam network service has timed out."); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else if (reason == 'backend_gone') { + context.JK.alertSupportedNeeded("The JamKazam client is experiencing technical difficulties."); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else if (reason == "invalid_response") { + //gearUtils.skipNetworkTest(); + context.JK.alertSupportedNeeded("The JamKazam client software had an unexpected problem while scoring your Internet connection.

Reason: " + attempt.backend_data.reason + '.'); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else if (reason == 'no_servers') { + // gearUtils.skipNetworkTest(); + context.JK.Banner.showAlert("No network test servers are available."); + renderStopTestVideo(null, reason); + //testedSuccessfully = true; + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else if (reason == 'no_network') { + context.JK.Banner.showAlert("Please try again later. Your network appears down."); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.noNetwork); + } + else if (reason == "rest_api_error") { + //gearUtils.skipNetworkTest(); + context.JK.alertSupportedNeeded("Unable to acquire a network test server."); + //testedSuccessfully = true; + renderStopTestVideo(null, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else if (reason == "timeout") { + //gearUtils.skipNetworkTest(); + context.JK.alertSupportedNeeded("Communication with the JamKazam network service timed out."); + //testedSuccessfully = true; + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + else { + //gearUtils.skipNetworkTest(); + context.JK.alertSupportedNeeded("The JamKazam client software had a logic error while scoring your Internet connection."); + renderStopTestVideo(testSummary.video_final.num_clients - 1, reason); + //storeLastNetworkFailure(context.JK.GA.NetworkTestFailReasons.jamerror); + } + + numClientToTestVideo = STARTING_NUM_CLIENTS_VIDEO; + videoScoring = false; + configureStartButton(); + postDiagnostic(); + + $self.triggerHandler(NETWORK_TEST_DONE) } - function isFirstAttempt() { - return testSummary.attempts.length == 0 || testSummary.attempts.length == 1; + function startVideoTest() { + + videoScoring = true; + + renderStartTestVideo(); + + setTimeout(attemptTestPassVideo, 500); + } + + function getCurrentAttemptAudio() { + return testSummary.audioAttempts[testSummary.audioAttempts.length - 1]; + } + function getCurrentAttemptVideo() { + return testSummary.videoAttempts[testSummary.videoAttempts.length - 1]; + } + + function isFirstAttemptAudio() { + return testSummary.audioAttempts.length == 0 || testSummary.audioAttempts.length == 1; + } + + function isFirstAttemptVideo() { + return testSummary.videoAttempts.length == 0 || testSummary.videoAttempts.length == 1; } function hasGoneDown() { var goneDown = false; - context._.each(testSummary.attempts, function(attempt) { - if(attempt.num_clients == STARTING_NUM_CLIENTS - 1) { + context._.each(testSummary.audioAttempts, function(attempt) { + if(attempt.num_clients == STARTING_NUM_CLIENTS_AUDIO - 1) { goneDown = true return false; } @@ -354,8 +574,8 @@ var testSessionSize = null; var numSameSizeTests = 0; - for(i = testSummary.attempts.length - 1; i >= 0; i--) { - var attempt = testSummary.attempts[i]; + for(i = testSummary.audioAttempts.length - 1; i >= 0; i--) { + var attempt = testSummary.audioAttempts[i]; if(testSessionSize === null) { // this is the 1st loop through. just recording the testSessionSize @@ -381,13 +601,20 @@ function primeTimedOut() { logger.warn("backend never completed priming pump phase"); - scoring = false; + audioScoring = false; primeDeferred.reject(); } function backendTimedOut() { - testSummary.final = {reason: 'backend_gone'} - testFinished(); + + if (audioScoring) { + testSummary.final = {reason: 'backend_gone'} + testFinishedAudio(); + } + else { + testSummary.video_final = {reason: 'backend_gone'} + testFinishedVideo(); + } } function cancel() { @@ -429,36 +656,67 @@ }, (gon.ftue_network_test_duration + 5) * 1000); } - function attemptTestPass() { + function attemptTestPassAudio() { var attempt = {}; - attempt.payload_size = PAYLOAD_SIZE; + attempt.payload_size = AUDIO_PAYLOAD_SIZE; attempt.duration = gon.ftue_network_test_duration; attempt.test_type = 'PktTest400LowLatency'; - attempt.num_clients = numClientsToTest; + attempt.num_clients = numClientToTestAudio; attempt.server_client_id = serverClientId; attempt.received_progress = false; - testSummary.attempts.push(attempt); + testSummary.audioAttempts.push(attempt); + + $scoredClientsAudio.text(numClientToTestAudio); //context.jamClient.StopNetworkTest(''); - $testText.text("Simulating the network traffic of a " + numClientsToTest + "-person session."); + $inProgressText.html("Simulating the network traffic of a " + numClientToTestAudio + "-person audio-only session. Video will be tested next."); updateProgress(0, false); setBackendGuard(); - logger.debug("network test attempt: " + numClientsToTest + "-person session, 400 packets/s, " + PAYLOAD_SIZE + " byte payload") + audioScoring = true; + logger.debug("network test attempt: " + numClientToTestAudio + "-person audio session, 400 packets/s, " + AUDIO_PAYLOAD_SIZE + " byte payload") context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(false), createTimeoutCallbackName(false), NETWORK_TEST_TYPES.PktTest400LowLatency, gon.ftue_network_test_duration, - numClientsToTest - 1, - PAYLOAD_SIZE, gon.global.ftue_network_test_backend_retries); + numClientToTestAudio - 1, + AUDIO_PAYLOAD_SIZE, gon.global.ftue_network_test_backend_retries); } + function attemptTestPassVideo() { + + var attempt = {}; + attempt.payload_size = VIDEO_PAYLOAD_SIZE; + attempt.duration = gon.ftue_network_test_duration; + attempt.test_type = 'PktTest400LowLatency'; + attempt.num_clients = numClientToTestVideo; + attempt.server_client_id = serverClientId; + attempt.received_progress = false; + testSummary.videoAttempts.push(attempt); + + $scoredClientsVideo.text(numClientToTestVideo); + //context.jamClient.StopNetworkTest(''); + + $inProgressText.html("Simulating the network traffic of a " + numClientToTestVideo + "-person video-enabled session."); + + updateProgress(0, false); + + setBackendGuard(); + + logger.debug("network test attempt: " + numClientToTestVideo + "-person video session, 400 packets/s, " + VIDEO_PAYLOAD_SIZE + " byte payload") + context.jamClient.TestNetworkPktBwRate(serverClientId, createSuccessCallbackName(false), createTimeoutCallbackName(false), + NETWORK_TEST_TYPES.PktTest400LowLatency, + gon.ftue_network_test_duration, + numClientToTestVideo - 1, + VIDEO_PAYLOAD_SIZE, gon.global.ftue_network_test_backend_retries); + } + // you have to score a little to 'prime' the logic to know whether it's on wireless or not function primePump() { - scoring = true; + audioScoring = true; primeDeferred = new $.Deferred(); setPrimeGuard(); @@ -467,21 +725,21 @@ NETWORK_TEST_TYPES.PktTest400LowLatency, PRIME_PUMP_TIME, 2, - PAYLOAD_SIZE, gon.global.ftue_network_test_backend_retries); + AUDIO_PAYLOAD_SIZE, gon.global.ftue_network_test_backend_retries); return primeDeferred; } function cancelTest() { - scoring = false; + audioScoring = false; configureStartButton(); - renderStopTest(); + renderStopTestAudio(); $self.triggerHandler(NETWORK_TEST_CANCEL) } function postPumpRun() { -// check if on Wifi 1st + // check if on Wifi 1st var isWireless = context.jamClient.IsMyNetworkWireless(); if (isWireless == -1) { logger.warn("unable to determine if the user is on wireless or not for network test. skipping prompt.") @@ -493,7 +751,7 @@ cancelTest(); }}, {name: 'RUN NETWORK TEST ANYWAY', click: function () { - attemptTestPass(); + attemptTestPassAudio(); ; }} ], @@ -503,7 +761,7 @@ "A WiFi connection is likely to cause significant issues in both latency and audio quality.

"}) } else { - attemptTestPass(); + attemptTestPassAudio(); } } @@ -565,16 +823,15 @@ } function prepareNetworkTest() { - if (scoring) return false; - + if (audioScoring || videoScoring) return false; setTimeout(function() { logger.info("starting network test"); resetTestState(); - scoring = true; + audioScoring = true; $self.triggerHandler(NETWORK_TEST_START); - renderStartTest(); + renderStartTestAudio(); rest.getLatencyTester() .done(function (response) { // ensure there are no tests ongoing @@ -598,7 +855,7 @@ cancelTest(); }}, {name: 'RUN NETWORK TEST ANYWAY', click: function () { - attemptTestPass(); + attemptTestPassAudio(); ; }} ], @@ -622,7 +879,7 @@ testSummary.final = {reason: 'rest_api_error'} } } - testFinished(); + testFinishedAudio(); }) }, pauseForRecentScoresTime()) @@ -660,7 +917,7 @@ return; } clearPrimeGuard(); - scoring = false; + audioScoring = false; logger.debug("the prime pump routine timed out") primeDeferred.reject(); } @@ -682,60 +939,60 @@ // the interface is wireless, or not setTimeout(function () { logger.debug("pump primed"); - scoring = false; + audioScoring = false; primeDeferred.resolve(); }, 500); // give backend room to breath for timing/race issues } } - function networkTestComplete(data) { + function networkTestCompleteAudio(data) { if(!isAttemptingPass()) { logger.error("networkTestComplete: already completed the test pass. indicates backend sent > 1 final event"); return; } - var attempt = getCurrentAttempt(); + var attempt = getCurrentAttemptAudio(); function refineTest(up) { if (up === null) { - logger.debug("retrying test at size: " + numClientsToTest); - setTimeout(attemptTestPass, 500); // wait a second to avoid race conditions with client/server comm + logger.debug("retrying test at size: " + numClientToTestAudio); + setTimeout(attemptTestPassAudio, 500); // wait a second to avoid race conditions with client/server comm } else if (up) { - if (numClientsToTest == gon.ftue_network_test_max_clients) { + if (numClientToTestAudio == gon.ftue_network_test_max_clients) { attempt.reason = "success"; - testFinished(); + testFinishedAudio(); } else if(hasGoneDown()) { // this means we've gone up before... so don't go back down (i.e., creating a loop) attempt.reason = "success"; - testSummary.final = { reason: 'success', num_clients: numClientsToTest } - testFinished(); + testSummary.final = { reason: 'success', num_clients: numClientToTestAudio } + testFinishedAudio(); } else { - numClientsToTest++; - logger.debug("increasing number of clients to " + numClientsToTest); - setTimeout(attemptTestPass, 500); // wait a second to avoid race conditions with client/server comm + numClientToTestAudio++; + logger.debug("increasing number of clients to " + numClientToTestAudio); + setTimeout(attemptTestPassAudio, 500); // wait a second to avoid race conditions with client/server comm } } else { // reduce numclients if we can - if (numClientsToTest == MINIMUM_ACCEPTABLE_SESSION_SIZE) { + if (numClientToTestAudio == MINIMUM_ACCEPTABLE_SESSION_SIZE) { // we are too low already. fail the user attempt.reason = "minimum_client_threshold"; - testFinished(); + testFinishedAudio(); } - else if (numClientsToTest > STARTING_NUM_CLIENTS) { + else if (numClientToTestAudio > STARTING_NUM_CLIENTS_AUDIO) { // this means we've gone up before... so don't go back down (i.e., creating a loop) attempt.reason = "success"; - testSummary.final = { reason: 'success', num_clients: numClientsToTest - 1 } - testFinished(); + testSummary.final = { reason: 'success', num_clients: numClientToTestAudio - 1 } + testFinishedAudio(); } else { - numClientsToTest--; - logger.debug("reducing number of clients to " + numClientsToTest); - setTimeout(attemptTestPass, 500); // wait a second to avoid race conditions with client/server comm + numClientToTestAudio--; + logger.debug("reducing number of clients to " + numClientToTestAudio); + setTimeout(attemptTestPassAudio, 500); // wait a second to avoid race conditions with client/server comm } } } @@ -771,36 +1028,36 @@ if (data.reason == "unreachable") { logger.debug("network test: unreachable (STUN issue or similar)") attempt.reason = data.reason; - testFinished(); + testFinishedAudio(); } else if (data.reason == "no-transmit") { logger.debug("network test: no-transmit (STUN issue or similar)"); attempt.reason = data.reason; - testFinished(); + testFinishedAudio(); } else if (data.reason == "internal_error") { // oops logger.debug("network test: internal_error (client had a unexpected problem)"); attempt.reason = data.reason; - testFinished(); + testFinishedAudio(); } 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(); + testFinishedAudio(); } else if (data.reason == "server_comm_timeout") { logger.debug("network test: server_comm_timeout (communication with server problem)") attempt.reason = data.reason; - testFinished(); + testFinishedAudio(); } 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(); + testFinishedAudio(); } else { // success... but we still have to verify if this data is within threshold @@ -826,9 +1083,123 @@ } - function networkTestTimeout(data) { + function networkTestCompleteVideo(data) { if(!isAttemptingPass()) { - logger.error("networkTestTimeout: already completed the test pass. indicates backend sent > 1 final event"); + logger.error("networkTestCompleteVideo: already completed the test pass. indicates backend sent > 1 final event"); + return; + } + + var attempt = getCurrentAttemptVideo(); + + function refineTest(up) { + if (up === null) { + logger.debug("retrying video test at size: " + numClientToTestVideo); + setTimeout(attemptTestPassVideo, 500); // wait a second to avoid race conditions with client/server comm + } + else if (up) { + if (numClientToTestVideo == gon.ftue_network_test_max_clients) { + attempt.reason = "success"; + testFinishedVideo(); + } + else { + numClientToTestVideo++; + logger.debug("increasing number of clients to " + numClientToTestVideo); + setTimeout(attemptTestPassVideo, 500); // wait a second to avoid race conditions with client/server comm + } + } + else { + attempt.reason = "success"; + testSummary.video_final = { reason: 'success', num_clients: numClientToTestVideo - 1 } + testFinishedVideo(); + } + } + + attempt.backend_data = data; + + if (data.progress === true) { + + setBackendGuard(); + + 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; + + bandwidthSamples.push(data.upthroughput); + + updateProgress(throughput, true); + } + } + } + else { + clearBackendGuard(); + logger.debug("network video test pass completed. data: ", data); + + if (data.reason == "unreachable") { + logger.debug("video network test: unreachable (STUN issue or similar)") + attempt.reason = data.reason; + testFinishedVideo(); + } + else if (data.reason == "no-transmit") { + logger.debug("video network test: no-transmit (STUN issue or similar)"); + attempt.reason = data.reason; + testFinishedVideo(); + } + else if (data.reason == "internal_error") { + // oops + logger.debug("video network test: internal_error (client had a unexpected problem)"); + attempt.reason = data.reason; + testFinishedVideo(); + } + else if (data.reason == "remote_peer_cant_test") { + // old client + logger.debug("video network test: remote_peer_cant_test (old client)") + attempt.reason = data.reason; + testFinishedVideo(); + } + else if (data.reason == "server_comm_timeout") { + logger.debug("video network test: server_comm_timeout (communication with server problem)") + attempt.reason = data.reason; + testFinishedVideo(); + } + else { + if (!data.downthroughput || !data.upthroughput) { + // we have to assume this is bad. just not a reason we know about in code + logger.debug("video network test: no test data (unknown issue? " + data.reason + ")") + attempt.reason = "invalid_response"; + testFinishedVideo(); + } + else { + // success... but we still have to verify if this data is within threshold + if (data.downthroughput < gon.ftue_packet_rate_treshold) { + logger.debug("video 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("video 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("vido network test: success") + refineTest(true); + } + } + } + } + + } + + function networkTestTimeoutAudio(data) { + if(!isAttemptingPass()) { + logger.error("networkTestTimeout: already completed the audio test pass. indicates backend sent > 1 final event"); return; } @@ -836,10 +1207,26 @@ logger.warn("network timeout when testing latency test: " + data); - var attempt = getCurrentAttempt(); + var attempt = getCurrentAttemptAudio(); attempt.reason = 'timeout'; attempt.backend_data = data; - testFinished(); + testFinishedAudio(); + } + + function networkTestTimeoutVideo(data) { + if(!isAttemptingPass()) { + logger.error("networkTestTimeout: already completed the video test pass. indicates backend sent > 1 final event"); + return; + } + + clearBackendGuard(); + + logger.warn("network timeout when testing latency test: " + data); + + var attempt = getCurrentAttemptVideo(); + attempt.reason = 'timeout'; + attempt.backend_data = data; + testFinishedVideo(); } function hasScoredNetworkSuccessfully() { @@ -847,7 +1234,7 @@ } function configureStartButton() { - if (scoring) { + if (audioScoring || videoScoring) { $startNetworkTestBtn.text('NETWORK TEST RUNNING...').removeClass('button-orange').addClass('button-grey') } else { @@ -856,11 +1243,11 @@ } function initializeNextButtonState() { - $dialog.setNextState(hasScoredNetworkSuccessfully() && !scoring); + $dialog.setNextState(hasScoredNetworkSuccessfully() && !audioScoring && !videoScoring); } function initializeBackButtonState() { - $dialog.setBackState(!scoring); + $dialog.setBackState(!audioScoring && !videoScoring); } function beforeHide() { @@ -886,23 +1273,38 @@ if ($startNetworkTestBtn.length == 0) throw 'no start network test button found in network-test' $testResults = $step.find('.network-test-results'); - $testScore = $step.find('.network-test-score'); + $testScoreAudio = $step.find('.network-test-score-audio'); + $scoredClientsAudio = $testScoreAudio.find('.scored-clients'); + $testScoreVideo = $step.find('.network-test-score-video'); + $scoredClientsVideo = $testScoreVideo.find('.scored-clients'); $testText = $step.find('.network-test-text'); + $inProgressText = $step.find('.in-progress') + $audioResultText = $step.find('.audio-result') + $videoResultText = $step.find('.video-result') $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'); $watchVideo = $step.find('.watch-video'); + $container = $step.find('.network-test'); + if(inGearWizard) { + $container.attr('data-mode', 'gear-wizard') + } + else { + $container.attr('data-mode', 'standalone') + } $startNetworkTestBtn.on('click', function () { forever = false; prepareNetworkTest(); + return false; }); if(context.JK.currentUserAdmin) { $foreverNetworkTestBtn.on('click', function() { forever = true; prepareNetworkTest(); + return false; }).show(); } @@ -920,10 +1322,25 @@ primePumpTimeout(data) }; context.JK.HandleNetworkTestSuccessForGearWizard = function (data) { - networkTestComplete(data) + if(audioScoring) { + networkTestCompleteAudio(data); + } + else if(videoScoring) { + networkTestCompleteVideo(data); + } + else { + logger.warn("unknown state in HandleNetworkTestSuccessForGearWizard"); + } + }; // pin to global for bridge callback context.JK.HandleNetworkTestTimeoutForGearWizard = function (data) { - networkTestTimeout(data) + if(audioScoring) { + networkTestTimeoutAudio(data); + } + else if(videoScoring) { + networkTestTimeoutVideo(data); + } + }; // pin to global for bridge callback } else { @@ -934,17 +1351,30 @@ primePumpTimeout(data) }; context.JK.HandleNetworkTestSuccessForDialog = function (data) { - networkTestComplete(data) + if(audioScoring) { + networkTestCompleteAudio(data); + } + else if(videoScoring) { + networkTestCompleteVideo(data); + } + else { + logger.warn("unknown state in HandleNetworkTestSuccessForDialog"); + } }; // pin to global for bridge callback context.JK.HandleNetworkTestTimeoutForDialog = function (data) { - networkTestTimeout(data) + if(audioScoring) { + networkTestTimeoutAudio(data); + } + else if(videoScoring) { + networkTestTimeoutVideo(data); + } }; // pin to global for bridge callback } } this.isScoring = function () { - return scoring; + return audioScoring || videoScoring; }; this.hasScoredNetworkSuccessfully = hasScoredNetworkSuccessfully; this.initialize = initialize; diff --git a/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss b/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss index 0204fffe5..f2e90692b 100644 --- a/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss +++ b/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss @@ -400,14 +400,18 @@ display:none; } - .network-test-score { - height: 24px; + .network-test-score-audio, .network-test-score-video { + white-space:nowrap; + height: 40px; padding: 10px; color: white; - font-size: 20px; + font-size: 16px; background-color: #222; text-align: center; - margin-bottom: 20px; + margin-bottom: 10px; + width:50%; + @include border_box_sizing; + float:left; &.good { background-color: #72a43b; @@ -418,6 +422,8 @@ &.bad { background-color: #7B0C00; } + + .scored-clients{display:inline} } .scoring-bar { @@ -425,8 +431,10 @@ height: 20px; left: 0; position: relative; + margin-bottom:10px; //display:inline-block; - display: none; + //display: none; + visibility:hidden; .current-score { background-color: gray; @@ -479,7 +487,12 @@ } } .network-test-text { - + ul { + margin-top:10px; + } + li { + margin-bottom:10px; + } } .instructions { @@ -492,13 +505,14 @@ &.testing { text-align: left; - .network-test-score { - display: none; + .network-test-score-audio { + //display: none; } .scoring-bar { display: inline-block; margin-bottom: 10px; + visibility:visible; } .network-test-text { @@ -511,20 +525,20 @@ } &.good { - .network-test-score { - background-color: #72a43b; + .network-test-score-audio, .network-test-score-video { + // background-color: #72a43b; } } &.acceptable { - .network-test-score { - background-color: #D6A800; + .network-test-score-audio, .network-test-score-video { + //background-color: #D6A800; } } &.bad { - .network-test-score { - background-color: #7B0C00; + .network-test-score-audio, .network-test-score-video { + //background-color: #7B0C00; } } } diff --git a/web/app/assets/stylesheets/dialogs/networkTestDialog.css.scss b/web/app/assets/stylesheets/dialogs/networkTestDialog.css.scss index 1c799915b..a25c250f6 100644 --- a/web/app/assets/stylesheets/dialogs/networkTestDialog.css.scss +++ b/web/app/assets/stylesheets/dialogs/networkTestDialog.css.scss @@ -10,5 +10,15 @@ .network-test-results { height:268px ! important; } + + + .gear-wizard-only { + display:none; + } + &[data-mode="gear-wizard"] { + .gear-wizard-only { + display:inline; + } + } } } \ No newline at end of file diff --git a/web/app/views/clients/_network_test.html.haml b/web/app/views/clients/_network_test.html.haml index db61e567a..38a432239 100644 --- a/web/app/views/clients/_network_test.html.haml +++ b/web/app/views/clients/_network_test.html.haml @@ -1,5 +1,7 @@ .network-test - .help-text In this step, you will test your router and Internet connection to ensure that you can play in online sessions, and to see how many musicians can be in a session with you based on your internet connection. If you don't want to play online in real-time sessions, you can click NEXT to skip this step. + .help-text + %span In this step, you will test your router and Internet connection to ensure that you can play in online sessions, and to see how many musicians can be in a session with you based on your internet connection. + %span.gear-wizard-only  If you don't want to play online in real-time sessions, you can click NEXT to skip this step. .wizard-step-content .wizard-step-column %h2 Instructions @@ -21,12 +23,23 @@ .wizard-step-column %h2 Test Results .network-test-results.ftue-box + .network-test-score-audio + Audio: + .scored-clients + - + .network-test-score-video + Video: + .scored-clients + - .scoring-bar .current-score testing... .subscore .good-marker .good-line - .network-test-score - .scored-clients - .network-test-text \ No newline at end of file + + .network-test-text + .in-progress + %ul + %li.audio-result + %li.video-result diff --git a/web/config/application.rb b/web/config/application.rb index 534079cc6..2baaf5aee 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -282,8 +282,11 @@ if defined?(Bundler) config.ftue_network_test_duration = 10 # max number of people to test config.ftue_network_test_max_clients = 8 - # packet size (bytes) of test + # packet size (bytes) of audio-only test config.ftue_network_test_packet_size = 60 + # packet size (bytes) of audio + video test + config.ftue_network_test_packet_size_video = 500 + # number of times that the backend retries before giving up config.ftue_network_test_backend_retries = 3 # amount of time that we want passed until we run the next network test diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb index 05c7d47fc..ba60612db 100644 --- a/web/config/initializers/gon.rb +++ b/web/config/initializers/gon.rb @@ -1,5 +1,6 @@ Gon.global.facebook_app_id = Rails.application.config.facebook_app_id Gon.global.ftue_network_test_packet_size = Rails.application.config.ftue_network_test_packet_size +Gon.global.ftue_network_test_packet_size_video = Rails.application.config.ftue_network_test_packet_size_video Gon.global.ftue_network_test_backend_retries = Rails.application.config.ftue_network_test_backend_retries Gon.global.twitter_public_account = Rails.application.config.twitter_public_account Gon.global.scoring_get_work_interval = Rails.application.config.scoring_get_work_interval diff --git a/web/spec/features/network_test_spec.rb b/web/spec/features/network_test_spec.rb index 4f8df53ce..5073e8a70 100644 --- a/web/spec/features/network_test_spec.rb +++ b/web/spec/features/network_test_spec.rb @@ -32,7 +32,8 @@ describe "Network Test", :js => true, :type => :feature, :capybara_feature => tr # start the test find('.start-network-test').trigger(:click) find('.user-btn', text: 'RUN NETWORK TEST ANYWAY').trigger(:click) - find('.scored-clients', text: '5') + find('.network-test-score-audio .scored-clients', text: '5') + find('.network-test-score-video .scored-clients', text: '2') wait_for_ajax # waiting for Diagnostic post to finish