diff --git a/src/js/account-controller.js b/src/js/account-controller.js
index 4ed197bcb..654f4442e 100644
--- a/src/js/account-controller.js
+++ b/src/js/account-controller.js
@@ -13,6 +13,7 @@ import * as AllTimeStats from "./all-time-stats";
import * as DB from "./db";
import * as TestLogic from "./test-logic";
import * as UI from "./ui";
+import * as Tribe from "./tribe";
var gmailProvider = new firebase.auth.GoogleAuthProvider();
@@ -308,6 +309,10 @@ firebase.auth().onAuthStateChanged(function (user) {
$(".pageLogin .preloader").addClass("hidden");
$("#menu .icon-button.account .text").text(displayName);
+ try {
+ Tribe.setName(displayName);
+ } catch {}
+
// showFavouriteThemesAtTheTop();
CommandlineLists.updateThemeCommands();
@@ -349,6 +354,20 @@ firebase.auth().onAuthStateChanged(function (user) {
ChallengeController.setup(challengeName);
}, 1000);
}
+ if (/\/tribe/.test(window.location.pathname)) {
+ if (/\/tribe_.+/.test(window.location.pathname)) {
+ let code = window.location.pathname.split("/")[1];
+ code = code.substring(5);
+ code = "room" + code;
+ Tribe.setAutoJoin(code);
+ }
+ UI.changePage("tribe");
+ }
+ if (!Tribe.socket.connected && Tribe.autoJoin != undefined) {
+ if (Tribe.state === -1) {
+ Tribe.init();
+ }
+ }
});
$(".pageLogin .register input").keyup((e) => {
diff --git a/src/js/account.js b/src/js/account.js
index 1f9cfa532..fc4e58146 100644
--- a/src/js/account.js
+++ b/src/js/account.js
@@ -34,6 +34,32 @@ export function getDataAndInit() {
snap.name = user.displayName;
DB.setSnapshot(snap);
DB.updateName(user.uid, user.displayName);
+ } else {
+ //invalid, get new
+ // Notifications.add("Invalid name", 0);
+ let promptVal = null;
+ let cdnVal = undefined;
+
+ while (
+ promptVal === null ||
+ cdnVal === undefined ||
+ cdnVal.data.status < 0
+ ) {
+ promptVal = prompt(
+ "Your name is either invalid or unavailable (you also need to do this if you used Google Sign Up). Please provide a new display name (cannot be longer than 14 characters, can only contain letters, numbers, underscores, dots and dashes):"
+ );
+ cdnVal = await CloudFunctions.changeDisplayName({
+ uid: user.uid,
+ name: promptVal,
+ });
+ if (cdnVal.data.status === 1) {
+ alert("Name updated", 1);
+ location.reload();
+ } else if (cdnVal.data.status < 0) {
+ alert(cdnVal.data.message, 0);
+ }
+ }
+ }
}
if (snap.refactored === false) {
CloudFunctions.removeSmallTests({ uid: user.uid });
diff --git a/src/js/config.js b/src/js/config.js
index b76c1cd59..91d3a8fcd 100644
--- a/src/js/config.js
+++ b/src/js/config.js
@@ -15,6 +15,7 @@ import * as LanguagePicker from "./language-picker";
import * as TestLogic from "./test-logic";
import * as PaceCaret from "./pace-caret";
import * as UI from "./ui";
+import * as Tribe from "./tribe";
export let cookieConfig = null;
export let dbConfigLoaded = false;
@@ -143,7 +144,10 @@ export async function saveToCookie(noDbCheck = false) {
}
//numbers
-export function setNumbers(numb, nosave) {
+export function setNumbers(numb, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (config.mode === "quote") {
numb = false;
}
@@ -153,10 +157,14 @@ export function setNumbers(numb, nosave) {
} else {
$("#top .config .numbersMode .text-button").addClass("active");
}
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
export function toggleNumbers() {
+ if (!Tribe.checkIfCanChangeConfig(false)) {
+ return;
+ }
config.numbers = !config.numbers;
if (config.mode === "quote") {
config.numbers = false;
@@ -166,11 +174,15 @@ export function toggleNumbers() {
} else {
$("#top .config .numbersMode .text-button").removeClass("active");
}
+ Tribe.syncConfig();
saveToCookie();
}
//punctuation
-export function setPunctuation(punc, nosave) {
+export function setPunctuation(punc, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (config.mode === "quote") {
punc = false;
}
@@ -180,10 +192,14 @@ export function setPunctuation(punc, nosave) {
} else {
$("#top .config .punctuationMode .text-button").addClass("active");
}
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
export function togglePunctuation() {
+ if (!Tribe.checkIfCanChangeConfig(false)) {
+ return;
+ }
config.punctuation = !config.punctuation;
if (config.mode === "quote") {
config.punctuation = false;
@@ -193,11 +209,15 @@ export function togglePunctuation() {
} else {
$("#top .config .punctuationMode .text-button").removeClass("active");
}
+ Tribe.syncConfig();
saveToCookie();
}
-export function setMode(mode, nosave) {
+export function setMode(mode, nosave, mp = false) {
if (TestUI.testRestarting) return;
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (mode !== "words" && Funbox.active === "memory") {
Notifications.add("Memory funbox can only be used with words mode.", 0);
return;
@@ -267,6 +287,7 @@ export function setMode(mode, nosave) {
}
// setPaceCaret("off", true);
}
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
@@ -295,7 +316,10 @@ export function togglePlaySoundOnError() {
}
//difficulty
-export function setDifficulty(diff, nosave) {
+export function setDifficulty(diff, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (
(diff !== "normal" && diff !== "expert" && diff !== "master") ||
diff == undefined
@@ -303,8 +327,9 @@ export function setDifficulty(diff, nosave) {
diff = "normal";
}
config.difficulty = diff;
- if (!nosave) TestLogic.restart(false, nosave);
+ if (!nosave) TestLogic.restart(false, nosave, mp);
TestUI.updateModesNotice();
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
@@ -324,15 +349,20 @@ export function toggleBlindMode() {
}
config.blindMode = blind;
TestUI.updateModesNotice();
+ Tribe.syncConfig();
saveToCookie();
}
-export function setBlindMode(blind, nosave) {
+export function setBlindMode(blind, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (blind == undefined) {
blind = false;
}
config.blindMode = blind;
TestUI.updateModesNotice();
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
@@ -392,7 +422,10 @@ export function setChartStyle(chartStyle, nosave) {
if (!nosave) saveToCookie();
}
-export function setStopOnError(soe, nosave) {
+export function setStopOnError(soe, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (soe == undefined || soe === true || soe === false) {
soe = "off";
}
@@ -401,6 +434,7 @@ export function setStopOnError(soe, nosave) {
config.confidenceMode = "off";
}
TestUI.updateModesNotice();
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
@@ -491,38 +525,54 @@ export function setPaceCaretCustomSpeed(val, nosave) {
}
//min wpm
-export function setMinWpm(minwpm, nosave) {
+export function setMinWpm(minwpm, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (minwpm == undefined) {
minwpm = "off";
}
config.minWpm = minwpm;
TestUI.updateModesNotice();
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
-export function setMinWpmCustomSpeed(val, nosave) {
+export function setMinWpmCustomSpeed(val, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (val == undefined || Number.isNaN(parseInt(val))) {
val = 100;
}
config.minWpmCustomSpeed = val;
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
//min acc
-export function setMinAcc(min, nosave) {
+export function setMinAcc(min, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (min == undefined) {
min = "off";
}
config.minAcc = min;
TestUI.updateModesNotice();
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
-export function setMinAccCustom(val, nosave) {
+export function setMinAccCustom(val, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (val == undefined || Number.isNaN(parseInt(val))) {
val = 90;
}
config.minAccCustom = val;
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
@@ -835,6 +885,10 @@ export function setTimerStyle(style, nosave) {
if (style == null || style == undefined) {
style = "bar";
}
+ if (Tribe.state >= 10 && style != "mini") {
+ Notifications.add("You can only use the mini timer style in Tribe", 0);
+ return;
+ }
config.timerStyle = style;
if (!nosave) saveToCookie();
}
@@ -910,12 +964,15 @@ export function toggleKeyTips() {
}
//mode
-export function setTimeConfig(time, nosave) {
+export function setTimeConfig(time, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (time === null || isNaN(time) || time < 0) {
time = 15;
}
time = parseInt(time);
- if (!nosave) setMode("time", nosave);
+ if (!nosave) setMode("time", nosave, mp);
config.time = time;
$("#top .config .time .text-button").removeClass("active");
if (![15, 30, 60, 120].includes(time)) {
@@ -924,11 +981,15 @@ export function setTimeConfig(time, nosave) {
$("#top .config .time .text-button[timeConfig='" + time + "']").addClass(
"active"
);
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
//quote length
-export function setQuoteLength(len, nosave, multipleMode) {
+export function setQuoteLength(len, nosave, multipleMode, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (Array.isArray(len)) {
//config load
if (len.length === 1 && len[0] === -1) len = [1];
@@ -952,15 +1013,19 @@ export function setQuoteLength(len, nosave, multipleMode) {
"#top .config .quoteLength .text-button[quoteLength='" + ql + "']"
).addClass("active");
});
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
-export function setWordCount(wordCount, nosave) {
+export function setWordCount(wordCount, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (wordCount === null || isNaN(wordCount) || wordCount < 0) {
wordCount = 10;
}
wordCount = parseInt(wordCount);
- if (!nosave) setMode("words", nosave);
+ if (!nosave) setMode("words", nosave, mp);
config.words = wordCount;
$("#top .config .wordCount .text-button").removeClass("active");
if (![10, 25, 50, 100, 200].includes(wordCount)) {
@@ -969,6 +1034,7 @@ export function setWordCount(wordCount, nosave) {
$(
"#top .config .wordCount .text-button[wordCount='" + wordCount + "']"
).addClass("active");
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
@@ -1115,7 +1181,10 @@ export function toggleFreedomMode() {
saveToCookie();
}
-export function setConfidenceMode(cm, nosave) {
+export function setConfidenceMode(cm, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (cm == undefined) {
cm = "off";
}
@@ -1124,7 +1193,7 @@ export function setConfidenceMode(cm, nosave) {
config.freedomMode = false;
config.stopOnError = "off";
}
-
+ Tribe.syncConfig();
TestUI.updateModesNotice();
if (!nosave) saveToCookie();
}
@@ -1194,7 +1263,10 @@ export function setCustomThemeColors(colors, nosave) {
if (!nosave) saveToCookie();
}
-export function setLanguage(language, nosave) {
+export function setLanguage(language, nosave, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
if (language == null || language == undefined) {
language = "english";
}
@@ -1206,6 +1278,7 @@ export function setLanguage(language, nosave) {
} catch (e) {
console.log("Analytics unavailable");
}
+ Tribe.syncConfig();
if (!nosave) saveToCookie();
}
@@ -1310,12 +1383,13 @@ export function setFontSize(fontSize, nosave) {
}
config.fontSize = fontSize;
$("#words").removeClass("size125");
- $("#caret, #paceCaret").removeClass("size125");
$("#words").removeClass("size15");
- $("#caret, #paceCaret").removeClass("size15");
$("#words").removeClass("size2");
- $("#caret, #paceCaret").removeClass("size2");
$("#words").removeClass("size3");
+
+ $("#caret, #paceCaret").removeClass("size125");
+ $("#caret, #paceCaret").removeClass("size15");
+ $("#caret, #paceCaret").removeClass("size2");
$("#caret, #paceCaret").removeClass("size3");
$("#miniTimerAndLiveWpm").removeClass("size125");
@@ -1323,22 +1397,40 @@ export function setFontSize(fontSize, nosave) {
$("#miniTimerAndLiveWpm").removeClass("size2");
$("#miniTimerAndLiveWpm").removeClass("size3");
+ $("#typingTest .tribePlayers").removeClass("size125");
+ $("#typingTest .tribePlayers").removeClass("size15");
+ $("#typingTest .tribePlayers").removeClass("size2");
+ $("#typingTest .tribePlayers").removeClass("size3");
+
+ $("#tribeDiff").removeClass("size125");
+ $("#tribeDiff").removeClass("size15");
+ $("#tribeDiff").removeClass("size2");
+ $("#tribeDiff").removeClass("size3");
+
if (fontSize == 125) {
$("#words").addClass("size125");
$("#caret, #paceCaret").addClass("size125");
$("#miniTimerAndLiveWpm").addClass("size125");
+ $("#typingTest .tribePlayers").addClass("size125");
+ $("#tribeDiff").addClass("size125");
} else if (fontSize == 15) {
$("#words").addClass("size15");
$("#caret, #paceCaret").addClass("size15");
$("#miniTimerAndLiveWpm").addClass("size15");
+ $("#typingTest .tribePlayers").addClass("size15");
+ $("#tribeDiff").addClass("size15");
} else if (fontSize == 2) {
$("#words").addClass("size2");
$("#caret, #paceCaret").addClass("size2");
$("#miniTimerAndLiveWpm").addClass("size2");
+ $("#typingTest .tribePlayers").addClass("size2");
+ $("#tribeDiff").addClass("size2");
} else if (fontSize == 3) {
$("#words").addClass("size3");
$("#caret, #paceCaret").addClass("size3");
$("#miniTimerAndLiveWpm").addClass("size3");
+ $("#typingTest .tribePlayers").addClass("size3");
+ $("#tribeDiff").addClass("size3");
}
if (!nosave) saveToCookie();
}
diff --git a/src/js/exports.js b/src/js/exports.js
index 8504d2dde..6d32cfaa8 100644
--- a/src/js/exports.js
+++ b/src/js/exports.js
@@ -7,8 +7,7 @@ global.getuid = Misc.getuid;
//these exports are just for debugging in the browser
-global.MP = MP;
-global.addnotif = Notifications.add;
+global.Tribe = Tribe;
global.snapshot = DB.getSnapshot;
global.config = Config;
diff --git a/src/js/global-dependencies.js b/src/js/global-dependencies.js
index 7ef9eb475..cce3e2689 100644
--- a/src/js/global-dependencies.js
+++ b/src/js/global-dependencies.js
@@ -3,7 +3,6 @@
import Chart from "chart.js";
import chartTrendline from "chartjs-plugin-trendline";
import chartAnnotation from "chartjs-plugin-annotation";
-import seedrandom from "seedrandom";
Chart.plugins.register(chartTrendline);
Chart.plugins.register(chartAnnotation);
@@ -14,6 +13,7 @@ import * as ResultFilters from "./result-filters";
import Config from "./config";
import * as SimplePopups from "./simple-popups";
import * as AccountController from "./account-controller";
+import * as Tribe from "./tribe";
import "./caps-warning";
import "./support-popup";
import "./version-popup";
diff --git a/src/js/input-controller.js b/src/js/input-controller.js
index b3d828dd7..850dc99f4 100644
--- a/src/js/input-controller.js
+++ b/src/js/input-controller.js
@@ -20,6 +20,7 @@ import * as TimerProgress from "./timer-progress";
import * as TestTimer from "./test-timer";
import * as Focus from "./focus";
import * as ShiftTracker from "./shift-tracker";
+import * as Tribe from "./tribe";
$("#wordsInput").keypress((event) => {
event.preventDefault();
@@ -51,6 +52,10 @@ function handleTab(event) {
// $("#customTextPopup .textarea").val() + "\t"
// );
return;
+ } else if (Tribe.state >= 10) {
+ if (Tribe.state < 28) {
+ event.preventDefault();
+ }
} else if (
$(".pageTest").hasClass("active") &&
!TestUI.resultCalculating &&
@@ -324,6 +329,23 @@ function handleSpace(event, isEnter) {
}
} //end of line wrap
+ let wpmAndRaw = TestLogic.calculateWpmAndRaw();
+
+ let acc = Misc.roundTo2(TestStats.calculateAccuracy());
+
+ let progress = 0;
+ if (Config.mode === "time") {
+ progress = 100 - ((TestTimer.time + 1) / Config.time) * 100;
+ } else {
+ let outof = TestLogic.words.length;
+ if (Config.mode === "words") {
+ outof = Config.words;
+ }
+ progress = Math.floor((TestLogic.currentWordIndex / (outof - 1)) * 100);
+ }
+
+ Tribe.sendTestProgress(wpmAndRaw.wpm, wpmAndRaw.raw, acc, progress);
+
Caret.updatePosition();
if (Config.keymapMode === "react") {
@@ -754,6 +776,11 @@ $(document).keydown(function (event) {
// if (Config.showOutOfFocusWarning) return;
}
+ if (Tribe.state == 20) {
+ event.preventDefault();
+ return;
+ }
+
//tab
if (
(event.key == "Tab" && !Config.swapEscAndTab) ||
diff --git a/src/js/popups/custom-text-popup.js b/src/js/popups/custom-text-popup.js
index ee64e6215..1779cd4a6 100644
--- a/src/js/popups/custom-text-popup.js
+++ b/src/js/popups/custom-text-popup.js
@@ -4,6 +4,7 @@ import * as Misc from "./misc";
import * as Notifications from "./notifications";
import * as TestLogic from "./test-logic";
import * as WordFilterPopup from "./word-filter-popup";
+import * as Tribe from "./tribe";
let wrapper = "#customTextPopupWrapper";
let popup = "#customTextPopup";
@@ -154,6 +155,7 @@ $("#customTextPopup .apply").click(() => {
ManualRestart.set();
TestLogic.restart();
hide();
+ Tribe.syncConfig();
});
$("#customTextPopup .wordfilter").click(() => {
diff --git a/src/js/test/funbox.js b/src/js/test/funbox.js
index 38fee9ba2..d704d7e6c 100644
--- a/src/js/test/funbox.js
+++ b/src/js/test/funbox.js
@@ -5,6 +5,7 @@ import * as Misc from "./misc";
import * as ManualRestart from "./manual-restart-tracker";
import Config, * as UpdateConfig from "./config";
import * as Settings from "./settings";
+import * as Tribe from "./tribe";
export let active = "none";
let memoryTimer = null;
@@ -70,8 +71,11 @@ export function toggleScript(...params) {
}
}
-export async function activate(funbox, mode) {
- if (TestLogic.active || TestUI.resultVisible) {
+export async function activate(funbox, mode, mp = false) {
+ if (!Tribe.checkIfCanChangeConfig(mp)) {
+ return;
+ }
+ if (TestLogic.active || (TestUI.resultVisible && Tribe.state < 10)) {
Notifications.add(
"You can only change the funbox before starting a test.",
0
@@ -97,7 +101,7 @@ export async function activate(funbox, mode) {
$("#wordsWrapper").removeClass("hidden");
// }
- if (mode === null || mode === undefined) {
+ if ((mode === null || mode === undefined) && funbox !== "none") {
let list = await Misc.getFunboxList();
mode = list.filter((f) => f.name === funbox)[0].type;
}
@@ -159,6 +163,7 @@ export async function activate(funbox, mode) {
Settings.groups.layout.updateButton();
}
}
+ Tribe.syncConfig();
TestUI.updateModesNotice();
return true;
}
diff --git a/src/js/test/test-logic.js b/src/js/test/test-logic.js
index ad4d94a2a..cc9e69f4c 100644
--- a/src/js/test/test-logic.js
+++ b/src/js/test/test-logic.js
@@ -27,6 +27,7 @@ import * as DB from "./db";
import * as ThemeColors from "./theme-colors";
import * as CloudFunctions from "./cloud-functions";
import * as TestLeaderboards from "./test-leaderboards";
+import * as Tribe from "./tribe";
export let notSignedInLastResult = null;
@@ -578,7 +579,13 @@ export async function init() {
// }
}
-export function restart(withSameWordset = false, nosave = false, event) {
+export function restart(
+ withSameWordset = false,
+ nosave = false,
+ event,
+ tribe = false
+) {
+ if (Tribe.state >= 10 && !tribe) return;
if (TestUI.testRestarting || TestUI.resultCalculating) {
try {
event.preventDefault();
@@ -904,7 +911,7 @@ export function addWord() {
TestUI.addWord(randomWord);
}
-export function finish(difficultyFailed = false) {
+export function finish(difficultyFailed = false, mp_outOfTime = false) {
if (!active) return;
if (Config.mode == "zen" && input.current.length != 0) {
input.pushHistory();
@@ -950,6 +957,29 @@ export function finish(difficultyFailed = false) {
ChartController.result.options.annotation.annotations = [];
+ if (Tribe.state >= 10) {
+ $(".pageTest #nextTestButton").addClass("hidden");
+ $(".pageTest #backToLobbyButton").addClass("hidden");
+ $(".pageTest #readyButton").removeClass("hidden");
+ $(".pageTest #restartTestButtonWithSameWordset").addClass("hidden");
+ $(".pageTest #goBackToLobbyButton").removeClass("hidden");
+ $(".pageTest #practiseMissedWordsButton").addClass("hidden");
+ $(".pageTest #result .tribeResultChat").removeClass("hidden");
+ if (Tribe.room.isLeader) {
+ // $(".pageTest #backToLobbyButton").removeClass("hidden");
+ // $(".pageTest #nextTestButton").removeClass("hidden");
+ $(".pageTest #readyButton").addClass("hidden");
+ }
+ } else {
+ $(".pageTest #nextTestButton").removeClass("hidden");
+ $(".pageTest #backToLobbyButton").addClass("hidden");
+ $(".pageTest #readyButton").addClass("hidden");
+ $(".pageTest #restartTestButtonWithSameWordset").removeClass("hidden");
+ $(".pageTest #goBackToLobbyButton").addClass("hidden");
+ $(".pageTest #practiseMissedWordsButton").removeClass("hidden");
+ $(".pageTest #result .tribeResultChat").addClass("hidden");
+ }
+
$("#result #resultWordsHistory").addClass("hidden");
if (Config.alwaysShowDecimalPlaces) {
@@ -1204,6 +1234,8 @@ export function finish(difficultyFailed = false) {
Notifications.add("Test invalid - AFK detected", 0);
} else if (isRepeated) {
Notifications.add("Test invalid - repeated", 0);
+ } else if (mp_outOfTime) {
+ Notifications.add("Test failed - out of time", 0);
} else if (
(Config.mode === "time" && mode2 < 15 && mode2 > 0) ||
(Config.mode === "time" && mode2 == 0 && testtime < 15) ||
@@ -1671,6 +1703,9 @@ export function finish(difficultyFailed = false) {
if (difficultyFailed) {
otherText += "
failed";
}
+ if (mp_outOfTime) {
+ otherText += "
out of time";
+ }
if (afkDetected) {
otherText += "
afk detected";
}
@@ -1717,10 +1752,30 @@ export function finish(difficultyFailed = false) {
TestUI.setResultCalculating(false);
$("#words").empty();
ChartController.result.resize();
+ Tribe.scrollChat();
if (Config.alwaysShowWordsHistory) {
TestUI.toggleResultWords();
}
});
+ Tribe.testFinished({
+ wpm: stats.wpm,
+ acc: stats.acc,
+ raw: stats.wpmRaw,
+ char: `${stats.correctChars + stats.correctSpaces}/${
+ stats.incorrectChars
+ }/${stats.extraChars}/${stats.missedChars}`,
+ con: consistency,
+ duration: testtime,
+ invalid: TestStats.invalid,
+ failed: difficultyFailed,
+ outOfTime: mp_outOfTime,
+ afk: afkDetected,
+ chartData: {
+ wpm: TestStats.wpmHistory,
+ raw: rawWpmPerSecond,
+ err: errorsArray,
+ },
+ });
}
export function fail() {
diff --git a/src/js/test/test-stats.js b/src/js/test/test-stats.js
index dc0ac2127..cae0d58db 100644
--- a/src/js/test/test-stats.js
+++ b/src/js/test/test-stats.js
@@ -322,6 +322,7 @@ export function calculateStats() {
5
);
let acc = Misc.roundTo2(TestStats.calculateAccuracy());
+ if (isNaN(acc)) acc = 0;
return {
wpm: isNaN(wpm) ? 0 : wpm,
wpmRaw: isNaN(wpmraw) ? 0 : wpmraw,
diff --git a/src/js/test/test-timer.js b/src/js/test/test-timer.js
index db708b6f3..9d40b3b37 100644
--- a/src/js/test/test-timer.js
+++ b/src/js/test/test-timer.js
@@ -10,6 +10,7 @@ import * as Funbox from "./funbox";
import * as TestLogic from "./test-logic";
import * as Caret from "./caret";
import * as Keymap from "./keymap";
+import * as Tribe from "./tribe";
export let time = 0;
let timer = null;
@@ -24,6 +25,10 @@ export function start() {
(function loop(expectedStepEnd) {
const delay = expectedStepEnd - performance.now();
timer = setTimeout(function () {
+ if (!TestLogic.active) {
+ clearTimeout(timer);
+ return;
+ }
time++;
$(".pageTest #premidSecondsLeft").text(Config.time - time);
if (
@@ -40,6 +45,31 @@ export function start() {
let acc = Misc.roundTo2(TestStats.calculateAccuracy());
+ let progress = 0;
+
+ if (Config.mode === "time") {
+ progress = 100 - ((time + 1) / Config.time) * 100;
+ } else {
+ let outof = TestLogic.words.length;
+ if (Config.mode === "words") {
+ outof = Config.words;
+ }
+ progress = Math.floor((TestLogic.currentWordIndex / (outof - 1)) * 100);
+ }
+
+ Tribe.sendTestProgress(wpmAndRaw.wpm, wpmAndRaw.raw, acc, progress);
+ Tribe.updateTribeDiff(wpmAndRaw.wpm);
+
+ if (
+ Tribe.state >= 21 &&
+ Tribe.state <= 28 &&
+ time >= 5 &&
+ TestLogic.input.current === "" &&
+ TestLogic.input.getHistory().length === 0
+ ) {
+ TestLogic.finish();
+ }
+
if (Funbox.active === "layoutfluid" && Config.mode === "time") {
const layouts = ["qwerty", "dvorak", "colemak"];
let index = 0;
diff --git a/src/js/test/test-ui.js b/src/js/test/test-ui.js
index 159b3c371..82c792c8a 100644
--- a/src/js/test/test-ui.js
+++ b/src/js/test/test-ui.js
@@ -13,6 +13,8 @@ import * as Commandline from "./commandline";
import * as OutOfFocus from "./out-of-focus";
import * as ManualRestart from "./manual-restart-tracker";
import * as PractiseMissed from "./practise-missed";
+import * as Tribe from "./tribe";
+import * as UI from "./ui";
export let currentWordElementIndex = 0;
export let resultVisible = false;
@@ -885,13 +887,21 @@ $(document.body).on("click", "#practiseMissedWordsButton", () => {
$(document).on("keypress", "#nextTestButton", (event) => {
if (event.keyCode == 13) {
- TestLogic.restart();
+ if (Tribe.state >= 10) {
+ Tribe.startTest();
+ } else {
+ TestLogic.restart();
+ }
}
});
$(document.body).on("click", "#nextTestButton", () => {
ManualRestart.set();
- TestLogic.restart();
+ if (Tribe.state >= 10) {
+ Tribe.startTest();
+ } else {
+ TestLogic.restart();
+ }
});
$(document).on("keypress", "#showWordHistoryButton", (event) => {
@@ -926,3 +936,11 @@ $(document).on("keypress", "#restartTestButtonWithSameWordset", (event) => {
$("#wordsWrapper").on("click", () => {
focusWords();
});
+
+$(document).on("keypress", "#goBackToLobbyButton", (event) => {
+ UI.changePage("tribe");
+});
+
+$(document.body).on("click", "#goBackToLobbyButton", (event) => {
+ UI.changePage("tribe");
+});
diff --git a/src/js/tribe.js b/src/js/tribe.js
index d58ec77c1..87c4d4b61 100644
--- a/src/js/tribe.js
+++ b/src/js/tribe.js
@@ -1,28 +1,47 @@
import InputSuggestions from "./input-suggestions";
import * as MatchmakingStatus from "./tribe-mm-status";
import TribeDefaultConfigs from "./tribe-default-configs";
+import * as Misc from "./misc";
+import * as UI from "./ui";
+import Config, * as UpdateConfig from "./config";
+import * as CustomText from "./custom-text";
+import * as Notifications from "./notifications";
+import * as Funbox from "./funbox";
+import * as ThemeColors from "./theme-colors";
+import Chart from "chart.js";
+import * as TestLogic from "./test-logic";
+import * as TestUI from "./test-ui";
+import * as Commandline from "./commandline";
+import * as CommandlineLists from "./commandline-lists";
+import seedrandom from "seedrandom";
-let MP = {
- state: -1,
- socket: io(
- window.location.hostname === "localhost"
- ? "http://localhost:3000"
- : "https://tribe.monkeytype.com",
- {
- // socket: io("http://localhost:3000", {
- autoConnect: false,
- secure: true,
- reconnectionAttempts: 1,
- }
- ),
- reconnectionAttempts: 0,
- maxReconnectionAttempts: 1,
- activePage: "preloader",
- pageTransition: false,
- expectedVersion: "0.8.2",
-};
+export let state = -1;
+export let socket = io(
+ window.location.hostname === "localhost"
+ ? "http://localhost:3000"
+ : "https://tribe.monkeytype.com",
+ {
+ // socket: io("http://localhost:3000", {
+ autoConnect: false,
+ secure: true,
+ reconnectionAttempts: 1,
+ }
+);
+export let reconnectionAttempts = 0;
+export let maxReconnectionAttempts = 1;
+export let activePage = "preloader";
+export let pageTransition = false;
+export let expectedVersion = "0.8.2";
-let scrollChat = true;
+let room = undefined;
+let name = undefined;
+let autoJoin = undefined;
+
+export function setAutoJoin(code) {
+ autoJoin = code;
+}
+
+let shouldScrollChat = true;
let lobbySuggestions;
let resultSuggestions;
@@ -64,45 +83,45 @@ let tribeSounds = {
//28 - leader finished
//29 - everybody finished
-function mp_init() {
+export function init() {
$(".pageTribe .preloader .icon").html(
``
);
$(".pageTribe .preloader .text").text("Connecting to Tribe");
- MP.socket.connect();
+ socket.connect();
}
-function mp_changeActiveSubpage(newPage) {
- if (MP.pageTransition) return;
- if (newPage === MP.activePage) return;
- MP.pageTransition = true;
+function changeActiveSubpage(newPage) {
+ if (pageTransition) return;
+ if (newPage === activePage) return;
+ pageTransition = true;
- swapElements(
- $(`.pageTribe .${MP.activePage}`),
+ UI.swapElements(
+ $(`.pageTribe .${activePage}`),
$(`.pageTribe .${newPage}`),
250,
() => {
if (newPage === "prelobby") {
- MP.socket.emit("mp_get_online_stats");
+ socket.emit("mp_get_online_stats");
}
if (newPage === "lobby") {
$(".pageTribe .lobby .chat .input input").focus();
}
- MP.pageTransition = false;
- MP.activePage = newPage;
+ pageTransition = false;
+ activePage = newPage;
}
);
}
-function mp_refreshUserList() {
+function refreshUserList() {
$(".pageTribe .lobby .userlist .list").empty();
$(".pageTest #result .tribeResultChat .userlist .list").empty();
let usersArray = [];
let names = [];
- Object.keys(MP.room.users).forEach((sid) => {
- let u = MP.room.users[sid];
+ Object.keys(room.users).forEach((sid) => {
+ let u = room.users[sid];
u.sid = sid;
- if (sid !== MP.socket.id) {
+ if (sid !== socket.id) {
names.push(u.name);
}
usersArray.push(u);
@@ -113,8 +132,8 @@ function mp_refreshUserList() {
sortedUsers.forEach((user) => {
let icons = "";
if (user.isLeader) {
- if (user.sid === MP.socket.id) {
- MP.room.isLeader = true;
+ if (user.sid === socket.id) {
+ room.isLeader = true;
}
icons += `