Merge pull request #7 from Miodec/master

update
This commit is contained in:
UnrealApex 2021-03-18 17:31:54 -07:00 committed by GitHub
commit b1303c2821
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 15242 additions and 736 deletions

View file

@ -14,6 +14,10 @@ Sometimes your browser has old files cached and the bug you are experiencing mig
**Describe the bug**
A clear and concise description of what the bug is.
**Did it happen in incognito mode?**
Sometimes things work in incognito mode, which allows me to further track down the issue.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'

View file

@ -472,7 +472,7 @@ exports.resetPersonalBests = functions.https.onCall(
}
);
function checkIfPB(uid, obj, userdata) {
async function checkIfPB(uid, obj, userdata) {
let pbs = null;
if (obj.mode == "quote") {
return false;
@ -1459,30 +1459,30 @@ exports.testCompleted = functions.https.onRequest(async (request, response) => {
// let createdDocId = e.id;
return Promise.all([
checkLeaderboards(
request.obj,
"global",
banned,
name,
verified,
emailVerified
),
checkLeaderboards(
request.obj,
"daily",
banned,
name,
verified,
emailVerified
),
// checkLeaderboards(
// request.obj,
// "global",
// banned,
// name,
// verified,
// emailVerified
// ),
// checkLeaderboards(
// request.obj,
// "daily",
// banned,
// name,
// verified,
// emailVerified
// ),
checkIfPB(request.uid, request.obj, userdata),
checkIfTagPB(request.uid, request.obj),
])
.then(async (values) => {
let globallb = values[0].insertedAt;
let dailylb = values[1].insertedAt;
let ispb = values[2];
let tagPbs = values[3];
// let globallb = values[0].insertedAt;
// let dailylb = values[1].insertedAt;
let ispb = values[0];
let tagPbs = values[1];
let createdDocId = await stripAndSave(request.uid, request.obj);
createdDocId = createdDocId.id;
// console.log(values);
@ -1493,67 +1493,18 @@ exports.testCompleted = functions.https.onRequest(async (request, response) => {
let newTypingStats = await getIncrementedTypingStats(userdata, obj);
if (
// obj.mode === "time" &&
// (obj.mode2 == "15" || obj.mode2 == "60") &&
// obj.language === "english"
globallb !== null &&
dailylb !== null
) {
let updatedLbMemory = await getUpdatedLbMemory(
userdata,
obj.mode,
obj.mode2,
globallb,
dailylb
);
db.collection("users").doc(request.uid).update({
startedTests: newTypingStats.newStarted,
completedTests: newTypingStats.newCompleted,
timeTyping: newTypingStats.newTime,
lbMemory: updatedLbMemory,
});
} else {
db.collection("users").doc(request.uid).update({
startedTests: newTypingStats.newStarted,
completedTests: newTypingStats.newCompleted,
timeTyping: newTypingStats.newTime,
});
}
let usr =
userdata.discordId !== undefined
? userdata.discordId
: userdata.name;
if (
globallb !== null &&
globallb.insertedAt >= 0 &&
globallb.insertedAt <= 9 &&
globallb.newBest
) {
let lbstring = `${obj.mode} ${obj.mode2} global`;
console.log(
`sending command to the bot to announce lb update ${
userdata.discordId
} ${globallb + 1} ${lbstring} ${obj.wpm}`
);
announceLbUpdate(
usr,
globallb.insertedAt + 1,
lbstring,
obj.wpm,
obj.rawWpm,
obj.acc
);
}
db.collection("users").doc(request.uid).update({
startedTests: newTypingStats.newStarted,
completedTests: newTypingStats.newCompleted,
timeTyping: newTypingStats.newTime,
});
// }
let returnobj = {
resultCode: null,
globalLeaderboard: globallb,
dailyLeaderboard: dailylb,
lbBanned: banned,
// globalLeaderboard: globallb,
// dailyLeaderboard: dailylb,
// lbBanned: banned,
name: name,
createdId: createdDocId,
needsToVerify: values[0].needsToVerify,
@ -2340,145 +2291,327 @@ exports.unlinkDiscord = functions.https.onRequest((request, response) => {
}
});
async function checkLeaderboards(
resultObj,
type,
banned,
name,
verified,
emailVerified
) {
//lb disable
// return {
// insertedAt: null,
// };
//
try {
if (resultObj.funbox !== "none") {
return {
insertedAt: null,
};
exports.checkLeaderboards = functions.https.onRequest(
async (request, response) => {
response.set("Access-Control-Allow-Origin", origin);
if (request.method === "OPTIONS") {
// Send response to OPTIONS requests
response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.set(
"Access-Control-Allow-Headers",
"Authorization,Content-Type"
);
response.set("Access-Control-Max-Age", "3600");
response.status(204).send("");
return;
}
if (emailVerified === false)
return {
insertedAt: null,
needsToVerifyEmail: true,
};
if (!name)
return {
insertedAt: null,
noName: true,
};
if (banned)
return {
insertedAt: null,
banned: true,
};
if (verified === false)
return {
insertedAt: null,
needsToVerify: true,
};
request = request.body.data;
if (
resultObj.mode === "time" &&
["15", "60"].includes(String(resultObj.mode2)) &&
resultObj.language === "english"
) {
return db
.runTransaction(async (t) => {
const lbdoc = await t.get(
db
.collection("leaderboards")
.where("mode", "==", String(resultObj.mode))
.where("mode2", "==", String(resultObj.mode2))
.where("type", "==", type)
);
let lbData;
let docid = `${String(resultObj.mode)}_${String(
resultObj.mode2
)}_${type}`;
if (lbdoc.docs.length === 0) {
console.log(
`no ${resultObj.mode} ${resultObj.mode2} ${type} leaderboard found - creating`
);
let toAdd = {
size: 20,
mode: String(resultObj.mode),
mode2: String(resultObj.mode2),
type: type,
};
t.set(
try {
if (request.emailVerified === false) {
response.status(200).send({
data: {
needsToVerifyEmail: true,
},
});
return;
}
if (request.name === undefined) {
response.status(200).send({
data: {
noName: true,
},
});
return;
}
if (request.banned) {
response.status(200).send({
data: {
banned: true,
},
});
return;
}
if (request.verified === false) {
response.status(200).send({
data: {
needsToVerify: true,
},
});
return;
}
request.result.name = request.name;
if (
request.result.mode === "time" &&
["15", "60"].includes(String(request.result.mode2)) &&
request.result.language === "english" &&
request.result.funbox === "none"
) {
let global = await db
.runTransaction(async (t) => {
const lbdoc = await t.get(
db
.collection("leaderboards")
.doc(
`${String(resultObj.mode)}_${String(resultObj.mode2)}_${type}`
),
toAdd
.where("mode", "==", String(request.result.mode))
.where("mode2", "==", String(request.result.mode2))
.where("type", "==", "global")
);
lbData = toAdd;
} else {
lbData = lbdoc.docs[0].data();
}
let boardInfo = lbData;
if (
boardInfo.minWpm === undefined ||
boardInfo.board.length !== boardInfo.size ||
(boardInfo.minWpm !== undefined &&
resultObj.wpm > boardInfo.minWpm &&
boardInfo.board.length === boardInfo.size)
) {
let boardData = lbData.board;
let lb = new Leaderboard(
boardInfo.size,
resultObj.mode,
resultObj.mode2,
boardInfo.type,
boardData
);
let insertResult = lb.insert(resultObj);
if (insertResult.insertedAt >= 0) {
t.update(db.collection("leaderboards").doc(docid), {
size: lb.size,
type: lb.type,
board: lb.board,
minWpm: lb.getMinWpm(),
});
// let lbData;
let docid = `${String(request.result.mode)}_${String(
request.result.mode2
)}_${"global"}`;
// if (lbdoc.docs.length === 0) {
// console.log(
// `no ${request.mode} ${request.mode2} ${type} leaderboard found - creating`
// );
// let toAdd = {
// size: 20,
// mode: String(request.mode),
// mode2: String(request.mode2),
// type: type,
// };
// t.set(
// db
// .collection("leaderboards")
// .doc(
// `${String(request.mode)}_${String(request.mode2)}_${type}`
// ),
// toAdd
// );
// lbData = toAdd;
// } else {
// lbData = lbdoc.docs[0].data();
// }
let boardInfo = lbdoc.docs[0].data();
if (
boardInfo.minWpm === undefined ||
boardInfo.board.length !== boardInfo.size ||
(boardInfo.minWpm !== undefined &&
request.result.wpm > boardInfo.minWpm &&
boardInfo.board.length === boardInfo.size)
) {
let boardData = boardInfo.board;
let lb = new Leaderboard(
boardInfo.size,
request.result.mode,
request.result.mode2,
boardInfo.type,
boardData
);
let insertResult = lb.insert(request.result);
if (insertResult.insertedAt >= 0) {
t.update(db.collection("leaderboards").doc(docid), {
size: lb.size,
type: lb.type,
board: lb.board,
minWpm: lb.getMinWpm(),
});
}
return insertResult;
} else {
//not above leaderboard minwpm
return {
insertedAt: -1,
};
}
})
.catch((error) => {
console.error(
`error in transaction checking leaderboards - ${error}`
);
return {
status: -999,
message: error,
};
});
let daily = await db
.runTransaction(async (t) => {
const lbdoc = await t.get(
db
.collection("leaderboards")
.where("mode", "==", String(request.result.mode))
.where("mode2", "==", String(request.result.mode2))
.where("type", "==", "daily")
);
// let lbData;
let docid = `${String(request.result.mode)}_${String(
request.result.mode2
)}_${"daily"}`;
// if (lbdoc.docs.length === 0) {
// console.log(
// `no ${request.mode} ${request.mode2} ${type} leaderboard found - creating`
// );
// let toAdd = {
// size: 20,
// mode: String(request.mode),
// mode2: String(request.mode2),
// type: type,
// };
// t.set(
// db
// .collection("leaderboards")
// .doc(
// `${String(request.mode)}_${String(request.mode2)}_${type}`
// ),
// toAdd
// );
// lbData = toAdd;
// } else {
// lbData = lbdoc.docs[0].data();
// }
let boardInfo = lbdoc.docs[0].data();
if (
boardInfo.minWpm === undefined ||
boardInfo.board.length !== boardInfo.size ||
(boardInfo.minWpm !== undefined &&
request.result.wpm > boardInfo.minWpm &&
boardInfo.board.length === boardInfo.size)
) {
let boardData = boardInfo.board;
let lb = new Leaderboard(
boardInfo.size,
request.result.mode,
request.result.mode2,
boardInfo.type,
boardData
);
let insertResult = lb.insert(request.result);
if (insertResult.insertedAt >= 0) {
t.update(db.collection("leaderboards").doc(docid), {
size: lb.size,
type: lb.type,
board: lb.board,
minWpm: lb.getMinWpm(),
});
}
return insertResult;
} else {
//not above leaderboard minwpm
return {
insertedAt: -1,
};
}
})
.catch((error) => {
console.error(
`error in transaction checking leaderboards - ${error}`
);
return {
insertedAt: insertResult,
status: -999,
message: error,
};
} else {
//not above leaderboard minwpm
return {
insertedAt: -999,
};
}
})
.catch((error) => {
console.error(
`error in transaction checking leaderboards - ${error}`
});
//send discord update
let usr =
request.discordId !== undefined ? request.discordId : request.name;
if (
global !== null &&
global.insertedAt >= 0 &&
global.insertedAt <= 9 &&
global.newBest
) {
let lbstring = `${request.result.mode} ${request.result.mode2} global`;
console.log(
`sending command to the bot to announce lb update ${usr} ${
global.insertedAt + 1
} ${lbstring} ${request.result.wpm}`
);
return {
insertedAt: null,
};
announceLbUpdate(
usr,
global.insertedAt + 1,
lbstring,
request.result.wpm,
request.result.rawWpm,
request.result.acc,
request.result.consistency
);
}
//
if (
// obj.mode === "time" &&
// (obj.mode2 == "15" || obj.mode2 == "60") &&
// obj.language === "english"
global !== null ||
daily !== null
) {
let updatedLbMemory = await getUpdatedLbMemory(
request.lbMemory,
request.result.mode,
request.result.mode2,
global,
daily
);
db.collection("users").doc(request.uid).update({
lbMemory: updatedLbMemory,
});
}
response.status(200).send({
data: {
status: 2,
daily: daily,
global: global,
},
});
} else {
return {
insertedAt: null,
};
return;
} else {
response.status(200).send({
data: {
daily: {
insertedAt: null,
},
global: {
insertedAt: null,
},
},
});
return;
}
} catch (e) {
console.log(e);
response.status(200).send({
data: {
status: -999,
message: e,
},
});
return;
}
} catch (e) {
console.error(
`error while checking leaderboards - ${e} - ${type} ${resultObj}`
);
return {
insertedAt: null,
};
}
}
);
// async function checkLeaderboards(
// resultObj,
// type,
// banned,
// name,
// verified,
// emailVerified
// ) {
// //lb disable
// // return {
// // insertedAt: null,
// // };
// //
// try {
// } catch (e) {
// console.error(
// `error while checking leaderboards - ${e} - ${type} ${resultObj}`
// );
// return {
// insertedAt: null,
// };
// }
// }
exports.getLeaderboard = functions.https.onCall((request, response) => {
return db

File diff suppressed because it is too large Load diff

View file

@ -115,6 +115,9 @@ const refactoredSrc = [
"./src/js/test/keymap.js",
"./src/js/test/live-wpm.js",
"./src/js/test/caps-warning.js",
"./src/js/test/live-acc.js",
"./src/js/test/test-leaderboards.js",
"./src/js/test/timer-progress.js",
];
//legacy files

10518
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -37,3 +37,6 @@ export const removeSmallTests = firebase
export const resetPersonalBests = firebase
.functions()
.httpsCallable("resetPersonalBests");
export const checkLeaderboards = firebase
.functions()
.httpsCallable("checkLeaderboards");

View file

@ -129,7 +129,7 @@ let commands = {
id: "toggleShowLiveAcc",
display: "Toggle live accuracy display",
exec: () => {
toggleShowLiveAcc();
LiveAcc.show();
},
},
{

View file

@ -14,6 +14,8 @@ export function getSnapshot() {
}
export function setSnapshot(newSnapshot) {
delete newSnapshot.banned;
delete newSnapshot.verified;
dbSnapshot = newSnapshot;
}
@ -27,6 +29,9 @@ export async function initSnapshot() {
tags: [],
favouriteThemes: [],
refactored: false,
banned: undefined,
verified: undefined,
emailVerified: undefined,
lbMemory: {
time15: {
global: null,
@ -92,6 +97,9 @@ export async function initSnapshot() {
started: data.startedTests,
completed: data.completedTests,
};
snap.banned = data.banned;
snap.verified = data.verified;
snap.emailVerified = user.emailVerified;
try {
if (data.lbMemory.time15 !== undefined) {
snap.lbMemory.time15 = data.lbMemory.time15;

View file

@ -44,3 +44,6 @@ import * as TestUI from "./test-ui";
import * as Keymap from "./keymap";
import * as LiveWpm from "./live-wpm";
import * as CapsWarning from "./caps-warning";
import * as LiveAcc from "./live-acc";
import * as TestLeaderboards from "./test-leaderboards";
import * as TimerProgress from "./timer-progress";

View file

@ -1,4 +1,5 @@
//test logic
let testActive = false;
let wordsList = [];
let currentWordIndex = 0;
let currentInput = "";
@ -11,7 +12,6 @@ let randomQuote = null;
let bailout = false;
//test timer
let testActive = false;
let time = 0;
let timer = null;
@ -750,15 +750,15 @@ function showWords() {
if (Config.mode === "zen") {
$(document.querySelector(".word")).remove();
}
if (Config.keymapMode === "next") {
Keymap.highlightKey(
wordsList[currentWordIndex]
.substring(currentInput.length, currentInput.length + 1)
.toString()
.toUpperCase()
);
} else {
if (Config.keymapMode === "next") {
Keymap.highlightKey(
wordsList[currentWordIndex]
.substring(currentInput.length, currentInput.length + 1)
.toString()
.toUpperCase()
);
}
}
TestUI.updateActiveElement();
@ -907,193 +907,6 @@ function highlightBadWord(index, showError) {
$($("#words .word")[index]).addClass("error");
}
function showTimer() {
let op = Config.showTimerProgress ? Config.timerOpacity : 0;
if (Config.mode != "zen" && Config.timerStyle === "bar") {
$("#timerWrapper").stop(true, true).removeClass("hidden").animate(
{
opacity: op,
},
125
);
} else if (Config.timerStyle === "text") {
$("#timerNumber")
.stop(true, true)
.removeClass("hidden")
.css("opacity", 0)
.animate(
{
opacity: op,
},
125
);
} else if (Config.mode == "zen" || Config.timerStyle === "mini") {
if (op > 0) {
$("#miniTimerAndLiveWpm .time")
.stop(true, true)
.removeClass("hidden")
.animate(
{
opacity: op,
},
125
);
}
}
}
function hideTimer() {
$("#timerWrapper").stop(true, true).animate(
{
opacity: 0,
},
125
);
$("#miniTimerAndLiveWpm .time")
.stop(true, true)
.animate(
{
opacity: 0,
},
125,
() => {
$("#miniTimerAndLiveWpm .time").addClass("hidden");
}
);
$("#timerNumber").stop(true, true).animate(
{
opacity: 0,
},
125
);
}
function restartTimer() {
if (Config.timerStyle === "bar") {
if (Config.mode === "time") {
$("#timer").stop(true, true).animate(
{
width: "100vw",
},
0
);
} else if (Config.mode === "words" || Config.mode === "custom") {
$("#timer").stop(true, true).animate(
{
width: "0vw",
},
0
);
}
}
}
function updateTimer() {
if (!Config.showTimerProgress) return;
if (
Config.mode === "time" ||
(Config.mode === "custom" && CustomText.isTimeRandom)
) {
let maxtime = Config.time;
if (Config.mode === "custom" && CustomText.isTimeRandom) {
maxtime = CustomText.time;
}
if (Config.timerStyle === "bar") {
let percent = 100 - ((time + 1) / maxtime) * 100;
$("#timer")
.stop(true, true)
.animate(
{
width: percent + "vw",
},
1000,
"linear"
);
} else if (Config.timerStyle === "text") {
let displayTime = Misc.secondsToString(maxtime - time);
if (maxtime === 0) {
displayTime = Misc.secondsToString(time);
}
$("#timerNumber").html("<div>" + displayTime + "</div>");
} else if (Config.timerStyle === "mini") {
let displayTime = Misc.secondsToString(maxtime - time);
if (maxtime === 0) {
displayTime = Misc.secondsToString(time);
}
$("#miniTimerAndLiveWpm .time").html(displayTime);
}
} else if (
Config.mode === "words" ||
Config.mode === "custom" ||
Config.mode === "quote"
) {
if (Config.timerStyle === "bar") {
let outof = wordsList.length;
if (Config.mode === "words") {
outof = Config.words;
}
if (Config.mode === "custom") {
if (CustomText.isWordRandom) {
outof = CustomText.word;
} else {
outof = CustomText.text.length;
}
}
let percent = Math.floor(((currentWordIndex + 1) / outof) * 100);
$("#timer")
.stop(true, true)
.animate(
{
width: percent + "vw",
},
250
);
} else if (Config.timerStyle === "text") {
let outof = wordsList.length;
if (Config.mode === "words") {
outof = Config.words;
}
if (Config.mode === "custom") {
if (CustomText.isWordRandom) {
outof = CustomText.word;
} else {
outof = CustomText.text.length;
}
}
if (outof === 0) {
$("#timerNumber").html("<div>" + `${inputHistory.length}` + "</div>");
} else {
$("#timerNumber").html(
"<div>" + `${inputHistory.length}/${outof}` + "</div>"
);
}
} else if (Config.timerStyle === "mini") {
let outof = wordsList.length;
if (Config.mode === "words") {
outof = Config.words;
}
if (Config.mode === "custom") {
if (CustomText.isWordRandom) {
outof = CustomText.word;
} else {
outof = CustomText.text.length;
}
}
if (Config.words === 0) {
$("#miniTimerAndLiveWpm .time").html(`${inputHistory.length}`);
} else {
$("#miniTimerAndLiveWpm .time").html(`${inputHistory.length}/${outof}`);
}
}
} else if (Config.mode == "zen") {
if (Config.timerStyle === "text") {
$("#timerNumber").html("<div>" + `${inputHistory.length}` + "</div>");
} else {
$("#miniTimerAndLiveWpm .time").html(`${inputHistory.length}`);
}
}
}
function countChars() {
let correctWordChars = 0;
let correctChars = 0;
@ -1261,8 +1074,9 @@ function showResult(difficultyFailed = false) {
Focus.set(false);
Caret.hide();
LiveWpm.hide();
hideLiveAcc();
hideTimer();
hideCrown();
LiveAcc.hide();
TimerProgress.hide();
Keymap.hide();
let stats = calculateStats();
if (stats === undefined) {
@ -1659,7 +1473,6 @@ function showResult(difficultyFailed = false) {
) {
if (firebase.auth().currentUser != null) {
completedEvent.uid = firebase.auth().currentUser.uid;
//check local pb
AccountIcon.loading(true);
let dontShowCrown = false;
@ -1683,12 +1496,11 @@ function showResult(difficultyFailed = false) {
if (lpb < stats.wpm && stats.wpm < highestwpm) {
dontShowCrown = true;
}
if (ConfigSet.mode == "quote") dontShowCrown(true);
if (Config.mode == "quote") dontShowCrown = true;
if (lpb < stats.wpm) {
//new pb based on local
pbDiff = Math.abs(stats.wpm - lpb);
if (!dontShowCrown) {
hideCrown();
showCrown();
$("#result .stats .wpm .crown").attr(
"aria-label",
@ -1731,10 +1543,6 @@ function showResult(difficultyFailed = false) {
);
ChartController.result.update({ duration: 0 });
}
if (Config.mode === "time" && (mode2 === 15 || mode2 === 60)) {
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html("checking...");
}
if (activeTags.length == 0) {
$("#result .stats .tags").addClass("hidden");
@ -1810,7 +1618,17 @@ function showResult(difficultyFailed = false) {
}
}
});
if (
completedEvent.funbox === "none" &&
completedEvent.language === "english" &&
completedEvent.mode === "time" &&
["15", "60"].includes(String(completedEvent.mode2))
) {
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html(
`checking <i class="fas fa-spin fa-fw fa-circle-notch"></i>`
);
}
CloudFunctions.testCompleted({
uid: firebase.auth().currentUser.uid,
obj: completedEvent,
@ -1852,6 +1670,7 @@ function showResult(difficultyFailed = false) {
);
} else if (e.data.resultCode === 1 || e.data.resultCode === 2) {
completedEvent.id = e.data.createdId;
TestLeaderboards.check(completedEvent);
if (e.data.resultCode === 2) {
completedEvent.isPb = true;
}
@ -1892,178 +1711,6 @@ function showResult(difficultyFailed = false) {
console.log("Analytics unavailable");
}
if (
Config.mode === "time" &&
(mode2 == "15" || mode2 == "60") &&
DB.getSnapshot() !== null
) {
const lbUpIcon = `<i class="fas fa-angle-up"></i>`;
const lbDownIcon = `<i class="fas fa-angle-down"></i>`;
const lbRightIcon = `<i class="fas fa-angle-right"></i>`;
//global
let globalLbString = "";
const glb = e.data.globalLeaderboard;
let glbMemory;
try {
glbMemory = DB.getSnapshot().lbMemory[Config.mode + mode2]
.global;
} catch {
glbMemory = null;
}
let dontShowGlobalDiff =
glbMemory == null || glbMemory === -1 ? true : false;
let globalLbDiff = null;
if (glb === null) {
globalLbString = "global: not found";
} else if (glb.insertedAt === -1) {
dontShowGlobalDiff = true;
globalLbDiff = glbMemory - glb.insertedAt;
DB.updateLbMemory(
Config.mode,
mode2,
"global",
glb.insertedAt
);
globalLbString = "global: not qualified";
} else if (glb.insertedAt >= 0) {
if (glb.newBest) {
globalLbDiff = glbMemory - glb.insertedAt;
DB.updateLbMemory(
Config.mode,
mode2,
"global",
glb.insertedAt
);
let str = Misc.getPositionString(glb.insertedAt + 1);
globalLbString = `global: ${str}`;
} else {
globalLbDiff = glbMemory - glb.foundAt;
DB.updateLbMemory(
Config.mode,
mode2,
"global",
glb.foundAt
);
let str = Misc.getPositionString(glb.foundAt + 1);
globalLbString = `global: ${str}`;
}
}
if (!dontShowGlobalDiff) {
let sString =
globalLbDiff === 1 || globalLbDiff === -1 ? "" : "s";
if (globalLbDiff > 0) {
globalLbString += ` <span class="lbChange" aria-label="You've gained ${globalLbDiff} position${sString}" data-balloon-pos="left">(${lbUpIcon}${globalLbDiff})</span>`;
} else if (globalLbDiff === 0) {
globalLbString += ` <span class="lbChange" aria-label="Your position remained the same" data-balloon-pos="left">(${lbRightIcon}${globalLbDiff})</span>`;
} else if (globalLbDiff < 0) {
globalLbString += ` <span class="lbChange" aria-label="You've lost ${globalLbDiff} position${sString}" data-balloon-pos="left">(${lbDownIcon}${globalLbDiff})</span>`;
}
}
//daily
let dailyLbString = "";
const dlb = e.data.dailyLeaderboard;
let dlbMemory;
try {
dlbMemory = DB.getSnapshot().lbMemory[Config.mode + mode2]
.daily;
} catch {
dlbMemory = null;
}
let dontShowDailyDiff =
dlbMemory == null || dlbMemory === -1 ? true : false;
let dailyLbDiff = null;
if (dlb === null) {
dailyLbString = "daily: not found";
} else if (dlb.insertedAt === -1) {
dontShowDailyDiff = true;
dailyLbDiff = dlbMemory - dlb.insertedAt;
DB.updateLbMemory(
Config.mode,
mode2,
"daily",
dlb.insertedAt
);
dailyLbString = "daily: not qualified";
} else if (dlb.insertedAt >= 0) {
if (dlb.newBest) {
dailyLbDiff = dlbMemory - dlb.insertedAt;
DB.updateLbMemory(
Config.mode,
mode2,
"daily",
dlb.insertedAt
);
let str = Misc.getPositionString(dlb.insertedAt + 1);
dailyLbString = `daily: ${str}`;
} else {
dailyLbDiff = dlbMemory - dlb.foundAt;
DB.updateLbMemory(
Config.mode,
mode2,
"daily",
dlb.foundAt
);
let str = Misc.getPositionString(dlb.foundAt + 1);
dailyLbString = `daily: ${str}`;
}
}
if (!dontShowDailyDiff) {
let sString =
dailyLbDiff === 1 || dailyLbDiff === -1 ? "" : "s";
if (dailyLbDiff > 0) {
dailyLbString += ` <span class="lbChange" aria-label="You've gained ${dailyLbDiff} position${sString}" data-balloon-pos="left">(${lbUpIcon}${dailyLbDiff})</span>`;
} else if (dailyLbDiff === 0) {
dailyLbString += ` <span class="lbChange" aria-label="Your position remained the same" data-balloon-pos="left">(${lbRightIcon}${dailyLbDiff})</span>`;
} else if (dailyLbDiff < 0) {
dailyLbString += ` <span class="lbChange" aria-label="You've lost ${dailyLbDiff} position${sString}" data-balloon-pos="left">(${lbDownIcon}${dailyLbDiff})</span>`;
}
}
$("#result .stats .leaderboards .bottom").html(
globalLbString + "<br>" + dailyLbString
);
// CloudFunctions.saveLbMemory({
// uid: firebase.auth().currentUser.uid,
// obj: DB.getSnapshot().lbMemory,
// }).then((d) => {
// if (d.data.returnCode === 1) {
// } else {
// Notifications.add(
// `Error saving lb memory ${d.data.message}`,
// 4000
// );
// }
// });
}
if (
e.data.dailyLeaderboard === null &&
e.data.globalLeaderboard === null
) {
$("#result .stats .leaderboards").addClass("hidden");
}
if (e.data.needsToVerifyEmail === true) {
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html(
`please verify your email<br>to access leaderboards - <a onClick="sendVerificationEmail()">resend email</a>`
);
} else if (e.data.lbBanned) {
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html("banned");
} else if (e.data.name === false) {
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html(
"update your name to access leaderboards"
);
} else if (e.data.needsToVerify === true) {
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html(
"verification needed to access leaderboards"
);
}
if (e.data.resultCode === 2) {
//new pb
showCrown();
@ -2249,12 +1896,12 @@ function startTest() {
testActive = true;
TestStats.setStart(performance.now());
TestStats.resetKeypressTimings();
restartTimer();
showTimer();
TimerProgress.restart();
TimerProgress.show();
$("#liveWpm").text("0");
LiveWpm.show();
showLiveAcc();
updateTimer();
LiveAcc.show();
TimerProgress.update(time, wordsList, currentWordIndex, inputHistory);
clearTimeout(timer);
if (activeFunbox === "memory") {
@ -2278,7 +1925,7 @@ function startTest() {
Config.mode === "time" ||
(Config.mode === "custom" && CustomText.isTimeRandom)
) {
updateTimer();
TimerProgress.update(time, wordsList, currentWordIndex, inputHistory);
}
let wpmAndRaw = liveWpmAndRaw();
LiveWpm.update(wpmAndRaw.wpm, wpmAndRaw.raw);
@ -2463,8 +2110,8 @@ function restartTest(withSameWordset = false, nosave = false, event) {
Caret.hide();
testActive = false;
LiveWpm.hide();
hideLiveAcc();
hideTimer();
LiveAcc.hide();
TimerProgress.hide();
bailout = false;
paceCaret = null;
if (paceCaret !== null) clearTimeout(paceCaret.timeout);
@ -2808,70 +2455,6 @@ function liveWpmAndRaw() {
};
}
function updateLiveAcc(acc) {
if (!testActive || !Config.showLiveAcc) {
hideLiveAcc();
} else {
showLiveAcc();
}
let number = Math.floor(acc);
if (Config.blindMode) {
number = 100;
}
document.querySelector("#miniTimerAndLiveWpm .acc").innerHTML = number + "%";
document.querySelector("#liveAcc").innerHTML = number + "%";
}
function showLiveAcc() {
if (!Config.showLiveAcc) return;
if (!testActive) return;
if (Config.timerStyle === "mini") {
// $("#miniTimerAndLiveWpm .wpm").css("opacity", Config.timerOpacity);
if (!$("#miniTimerAndLiveWpm .acc").hasClass("hidden")) return;
$("#miniTimerAndLiveWpm .acc")
.removeClass("hidden")
.css("opacity", 0)
.animate(
{
opacity: Config.timerOpacity,
},
125
);
} else {
// $("#liveWpm").css("opacity", Config.timerOpacity);
if (!$("#liveAcc").hasClass("hidden")) return;
$("#liveAcc").removeClass("hidden").css("opacity", 0).animate(
{
opacity: Config.timerOpacity,
},
125
);
}
}
function hideLiveAcc() {
// $("#liveWpm").css("opacity", 0);
// $("#miniTimerAndLiveWpm .wpm").css("opacity", 0);
$("#liveAcc").animate(
{
opacity: Config.timerOpacity,
},
125,
() => {
$("#liveAcc").addClass("hidden");
}
);
$("#miniTimerAndLiveWpm .acc").animate(
{
opacity: Config.timerOpacity,
},
125,
() => {
$("#miniTimerAndLiveWpm .acc").addClass("hidden");
}
);
}
function toggleResultWordsDisplay() {
if (TestUI.resultVisible) {
if ($("#resultWordsHistory").stop(true, true).hasClass("hidden")) {
@ -4016,7 +3599,7 @@ $(document).keydown(function (event) {
}
let acc = Misc.roundTo2(TestStats.calculateAccuracy());
updateLiveAcc(acc);
LiveAcc.update(acc);
});
function handleTab(event) {
@ -4202,7 +3785,7 @@ function handleBackspace(event) {
Sound.playClick(Config.playSoundOnClick);
if (Config.keymapMode === "react") {
Keymap.flashKey(event.code, true);
} else if (Config.keymapMode === "next") {
} else if (Config.keymapMode === "next" && Config.mode !== "zen") {
Keymap.highlightKey(
wordsList[currentWordIndex]
.substring(currentInput.length, currentInput.length + 1)
@ -4372,7 +3955,7 @@ function handleSpace(event, isEnter) {
if (Config.keymapMode === "react") {
Keymap.flashKey(event.code, true);
} else if (Config.keymapMode === "next") {
} else if (Config.keymapMode === "next" && Config.mode !== "zen") {
Keymap.highlightKey(
wordsList[currentWordIndex]
.substring(currentInput.length, currentInput.length + 1)
@ -4386,7 +3969,7 @@ function handleSpace(event, isEnter) {
Config.mode === "quote" ||
Config.mode === "zen"
) {
updateTimer();
TimerProgress.update(time, wordsList, currentWordIndex, inputHistory);
}
if (
Config.mode == "time" ||
@ -4665,7 +4248,7 @@ function handleAlpha(event) {
//keymap
if (Config.keymapMode === "react") {
Keymap.flashKey(event.key, thisCharCorrect);
} else if (Config.keymapMode === "next") {
} else if (Config.keymapMode === "next" && Config.mode !== "zen") {
Keymap.highlightKey(
wordsList[currentWordIndex]
.substring(currentInput.length, currentInput.length + 1)

View file

@ -4,6 +4,7 @@ import layouts from "./layouts";
//TODO remove after wordslist and currentinput and current word index are in a module
export function highlightKey(currentKey) {
if (Config.mode === "zen") return;
try {
if ($(".active-key") != undefined) {
$(".active-key").removeClass("active-key");

61
src/js/test/live-acc.js Normal file
View file

@ -0,0 +1,61 @@
import Config from './config';
export function update(acc) {
let number = Math.floor(acc);
if (Config.blindMode) {
number = 100;
}
document.querySelector("#miniTimerAndLiveWpm .acc").innerHTML = number + "%";
document.querySelector("#liveAcc").innerHTML = number + "%";
}
export function show() {
if (!Config.showLiveAcc) return;
// if (!testActive) return;
if (Config.timerStyle === "mini") {
// $("#miniTimerAndLiveWpm .wpm").css("opacity", Config.timerOpacity);
if (!$("#miniTimerAndLiveWpm .acc").hasClass("hidden")) return;
$("#miniTimerAndLiveWpm .acc")
.removeClass("hidden")
.css("opacity", 0)
.animate(
{
opacity: Config.timerOpacity,
},
125
);
} else {
// $("#liveWpm").css("opacity", Config.timerOpacity);
if (!$("#liveAcc").hasClass("hidden")) return;
$("#liveAcc").removeClass("hidden").css("opacity", 0).animate(
{
opacity: Config.timerOpacity,
},
125
);
}
}
export function hide() {
// $("#liveWpm").css("opacity", 0);
// $("#miniTimerAndLiveWpm .wpm").css("opacity", 0);
$("#liveAcc").animate(
{
opacity: Config.timerOpacity,
},
125,
() => {
$("#liveAcc").addClass("hidden");
}
);
$("#miniTimerAndLiveWpm .acc").animate(
{
opacity: Config.timerOpacity,
},
125,
() => {
$("#miniTimerAndLiveWpm .acc").addClass("hidden");
}
);
}

View file

@ -0,0 +1,185 @@
import * as CloudFunctions from "./cloud-functions";
import * as DB from "./db";
import * as Notifications from "./notification-center";
import Config from "./config";
import * as Misc from "./misc";
let textTimeouts = [];
export function check(completedEvent) {
try {
if (
completedEvent.funbox === "none" &&
completedEvent.language === "english" &&
completedEvent.mode === "time" &&
["15", "60"].includes(String(completedEvent.mode2))
) {
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html(
`checking <i class="fas fa-spin fa-fw fa-circle-notch"></i>`
);
textTimeouts.push(
setTimeout(() => {
$("#result .stats .leaderboards .bottom").html(
`still checking <i class="fas fa-spin fa-fw fa-circle-notch"></i>`
);
}, 5000)
);
textTimeouts.push(
setTimeout(() => {
$("#result .stats .leaderboards .bottom").html(
`leaderboard seems<br>to be very busy <i class="fas fa-spin fa-fw fa-circle-notch"></i>`
);
}, 10000)
);
let lbRes = completedEvent;
delete lbRes.keySpacing;
delete lbRes.keyDuration;
delete lbRes.chartData;
CloudFunctions.checkLeaderboards({
uid: completedEvent.uid,
lbMemory: DB.getSnapshot().lbMemory,
emailVerified: DB.getSnapshot().emailVerified,
name: DB.getSnapshot().name,
banned: DB.getSnapshot().banned,
verified: DB.getSnapshot().verified,
discordId: DB.getSnapshot().discordId,
result: lbRes,
})
.then((data) => {
Misc.clearTimeouts(textTimeouts);
show(data.data, completedEvent.mode2);
})
.catch((e) => {
$("#result .stats .leaderboards").addClass("hidden");
Notifications.add(e, -1);
});
}
} catch (e) {
Notifications.add(`Error while checking leaderboards: ${e}`, -1);
}
}
export function show(data, mode2) {
let string = "";
if (data.needsToVerifyEmail === true) {
string = `please verify your email<br>to access leaderboards - <a onClick="sendVerificationEmail()">resend email</a>`;
} else if (data.lbBanned) {
string = "banned";
} else if (data.name === false) {
string = "update your name to access leaderboards";
} else if (data.needsToVerify === true) {
string = "verification needed to access leaderboards";
} else {
const lbUpIcon = `<i class="fas fa-angle-up"></i>`;
const lbDownIcon = `<i class="fas fa-angle-down"></i>`;
const lbRightIcon = `<i class="fas fa-angle-right"></i>`;
//global
let globalLbString = "";
const glb = data.global;
let glbMemory;
try {
glbMemory = DB.getSnapshot().lbMemory[Config.mode + mode2].global;
} catch {
glbMemory = null;
}
let dontShowGlobalDiff =
glbMemory == null || glbMemory === -1 ? true : false;
let globalLbDiff = null;
if (glb.status === -999) {
globalLbString = "global: error - " + glb.message;
} else if (glb === null) {
globalLbString = "global: not found";
} else if (glb.insertedAt === -1) {
dontShowGlobalDiff = true;
globalLbDiff = glbMemory - glb.insertedAt;
DB.updateLbMemory(Config.mode, mode2, "global", glb.insertedAt);
globalLbString = "global: not qualified";
} else if (glb.insertedAt >= 0) {
if (glb.newBest) {
globalLbDiff = glbMemory - glb.insertedAt;
DB.updateLbMemory(Config.mode, mode2, "global", glb.insertedAt);
let str = Misc.getPositionString(glb.insertedAt + 1);
globalLbString = `global: ${str}`;
} else {
globalLbDiff = glbMemory - glb.foundAt;
DB.updateLbMemory(Config.mode, mode2, "global", glb.foundAt);
let str = Misc.getPositionString(glb.foundAt + 1);
globalLbString = `global: ${str}`;
}
}
if (!dontShowGlobalDiff) {
let sString = globalLbDiff === 1 || globalLbDiff === -1 ? "" : "s";
if (globalLbDiff > 0) {
globalLbString += ` <span class="lbChange" aria-label="You've gained ${globalLbDiff} position${sString}" data-balloon-pos="left">(${lbUpIcon}${globalLbDiff})</span>`;
} else if (globalLbDiff === 0) {
globalLbString += ` <span class="lbChange" aria-label="Your position remained the same" data-balloon-pos="left">(${lbRightIcon}${globalLbDiff})</span>`;
} else if (globalLbDiff < 0) {
globalLbString += ` <span class="lbChange" aria-label="You've lost ${globalLbDiff} position${sString}" data-balloon-pos="left">(${lbDownIcon}${globalLbDiff})</span>`;
}
}
//daily
let dailyLbString = "";
const dlb = data.daily;
let dlbMemory;
try {
dlbMemory = DB.getSnapshot().lbMemory[Config.mode + mode2].daily;
} catch {
dlbMemory = null;
}
let dontShowDailyDiff =
dlbMemory == null || dlbMemory === -1 ? true : false;
let dailyLbDiff = null;
if (dlb.status === -999) {
dailyLbString = "daily: error - " + dlb.message;
} else if (dlb === null) {
dailyLbString = "daily: not found";
} else if (dlb.insertedAt === -1) {
dontShowDailyDiff = true;
dailyLbDiff = dlbMemory - dlb.insertedAt;
DB.updateLbMemory(Config.mode, mode2, "daily", dlb.insertedAt);
dailyLbString = "daily: not qualified";
} else if (dlb.insertedAt >= 0) {
if (dlb.newBest) {
dailyLbDiff = dlbMemory - dlb.insertedAt;
DB.updateLbMemory(Config.mode, mode2, "daily", dlb.insertedAt);
let str = Misc.getPositionString(dlb.insertedAt + 1);
dailyLbString = `daily: ${str}`;
} else {
dailyLbDiff = dlbMemory - dlb.foundAt;
DB.updateLbMemory(Config.mode, mode2, "daily", dlb.foundAt);
let str = Misc.getPositionString(dlb.foundAt + 1);
dailyLbString = `daily: ${str}`;
}
}
if (!dontShowDailyDiff) {
let sString = dailyLbDiff === 1 || dailyLbDiff === -1 ? "" : "s";
if (dailyLbDiff > 0) {
dailyLbString += ` <span class="lbChange" aria-label="You've gained ${dailyLbDiff} position${sString}" data-balloon-pos="left">(${lbUpIcon}${dailyLbDiff})</span>`;
} else if (dailyLbDiff === 0) {
dailyLbString += ` <span class="lbChange" aria-label="Your position remained the same" data-balloon-pos="left">(${lbRightIcon}${dailyLbDiff})</span>`;
} else if (dailyLbDiff < 0) {
dailyLbString += ` <span class="lbChange" aria-label="You've lost ${dailyLbDiff} position${sString}" data-balloon-pos="left">(${lbDownIcon}${dailyLbDiff})</span>`;
}
}
string = globalLbString + "<br>" + dailyLbString;
// CloudFunctions.saveLbMemory({
// uid: firebase.auth().currentUser.uid,
// obj: DB.getSnapshot().lbMemory,
// }).then((d) => {
// if (d.data.returnCode === 1) {
// } else {
// Notifications.add(
// `Error saving lb memory ${d.data.message}`,
// 4000
// );
// }
// });
}
$("#result .stats .leaderboards").removeClass("hidden");
$("#result .stats .leaderboards .bottom").html(string);
}

View file

@ -1,7 +1,7 @@
import * as Notifications from "./notification-center";
import * as ThemeColors from "./theme-colors";
import Config from "./config";
import * as DB from "./config";
import * as DB from "./db";
export let currentWordElementIndex = 0;
export let resultVisible = false;

View file

@ -0,0 +1,190 @@
import Config from "./config";
import * as CustomText from "./custom-text";
import * as Misc from "./misc";
export function show() {
let op = Config.showTimerProgress ? Config.timerOpacity : 0;
if (Config.mode != "zen" && Config.timerStyle === "bar") {
$("#timerWrapper").stop(true, true).removeClass("hidden").animate(
{
opacity: op,
},
125
);
} else if (Config.timerStyle === "text") {
$("#timerNumber")
.stop(true, true)
.removeClass("hidden")
.css("opacity", 0)
.animate(
{
opacity: op,
},
125
);
} else if (Config.mode == "zen" || Config.timerStyle === "mini") {
if (op > 0) {
$("#miniTimerAndLiveWpm .time")
.stop(true, true)
.removeClass("hidden")
.animate(
{
opacity: op,
},
125
);
}
}
}
export function hide() {
$("#timerWrapper").stop(true, true).animate(
{
opacity: 0,
},
125
);
$("#miniTimerAndLiveWpm .time")
.stop(true, true)
.animate(
{
opacity: 0,
},
125,
() => {
$("#miniTimerAndLiveWpm .time").addClass("hidden");
}
);
$("#timerNumber").stop(true, true).animate(
{
opacity: 0,
},
125
);
}
export function restart() {
if (Config.timerStyle === "bar") {
if (Config.mode === "time") {
$("#timer").stop(true, true).animate(
{
width: "100vw",
},
0
);
} else if (Config.mode === "words" || Config.mode === "custom") {
$("#timer").stop(true, true).animate(
{
width: "0vw",
},
0
);
}
}
}
//TODO remove the parameters once they are inside a module
export function update(time, wordsList, currentWordIndex, inputHistory) {
if (
Config.mode === "time" ||
(Config.mode === "custom" && CustomText.isTimeRandom)
) {
let maxtime = Config.time;
if (Config.mode === "custom" && CustomText.isTimeRandom) {
maxtime = CustomText.time;
}
if (Config.timerStyle === "bar") {
let percent = 100 - ((time + 1) / maxtime) * 100;
$("#timer")
.stop(true, true)
.animate(
{
width: percent + "vw",
},
1000,
"linear"
);
} else if (Config.timerStyle === "text") {
let displayTime = Misc.secondsToString(maxtime - time);
if (maxtime === 0) {
displayTime = Misc.secondsToString(time);
}
$("#timerNumber").html("<div>" + displayTime + "</div>");
} else if (Config.timerStyle === "mini") {
let displayTime = Misc.secondsToString(maxtime - time);
if (maxtime === 0) {
displayTime = Misc.secondsToString(time);
}
$("#miniTimerAndLiveWpm .time").html(displayTime);
}
} else if (
Config.mode === "words" ||
Config.mode === "custom" ||
Config.mode === "quote"
) {
if (Config.timerStyle === "bar") {
let outof = wordsList.length;
if (Config.mode === "words") {
outof = Config.words;
}
if (Config.mode === "custom") {
if (CustomText.isWordRandom) {
outof = CustomText.word;
} else {
outof = CustomText.text.length;
}
}
let percent = Math.floor(((currentWordIndex + 1) / outof) * 100);
$("#timer")
.stop(true, true)
.animate(
{
width: percent + "vw",
},
250
);
} else if (Config.timerStyle === "text") {
let outof = wordsList.length;
if (Config.mode === "words") {
outof = Config.words;
}
if (Config.mode === "custom") {
if (CustomText.isWordRandom) {
outof = CustomText.word;
} else {
outof = CustomText.text.length;
}
}
if (outof === 0) {
$("#timerNumber").html("<div>" + `${inputHistory.length}` + "</div>");
} else {
$("#timerNumber").html(
"<div>" + `${inputHistory.length}/${outof}` + "</div>"
);
}
} else if (Config.timerStyle === "mini") {
let outof = wordsList.length;
if (Config.mode === "words") {
outof = Config.words;
}
if (Config.mode === "custom") {
if (CustomText.isWordRandom) {
outof = CustomText.word;
} else {
outof = CustomText.text.length;
}
}
if (Config.words === 0) {
$("#miniTimerAndLiveWpm .time").html(`${inputHistory.length}`);
} else {
$("#miniTimerAndLiveWpm .time").html(`${inputHistory.length}/${outof}`);
}
}
} else if (Config.mode == "zen") {
if (Config.timerStyle === "text") {
$("#timerNumber").html("<div>" + `${inputHistory.length}` + "</div>");
} else {
$("#miniTimerAndLiveWpm .time").html(`${inputHistory.length}`);
}
}
}

View file

@ -573,11 +573,21 @@ function setShowTimerProgress(timer, nosave) {
timer = false;
}
ConfigSet.showTimerProgress(timer);
if (Config.showTimerProgress) {
TimerProgress.show();
} else {
TimerProgress.hide();
}
if (!nosave) saveConfigToCookie();
}
function toggleShowTimerProgress() {
ConfigSet.showTimerProgress(!Config.showTimerProgress);
if (Config.showTimerProgress) {
TimerProgress.show();
} else {
TimerProgress.hide();
}
saveConfigToCookie();
}
@ -609,11 +619,21 @@ function setShowLiveAcc(live, nosave) {
live = false;
}
ConfigSet.showLiveAcc(live);
if (live) {
LiveAcc.show();
} else {
LiveAcc.hide();
}
if (!nosave) saveConfigToCookie();
}
function toggleShowLiveAcc() {
function toggleLiveAcc() {
ConfigSet.showLiveAcc(!Config.showLiveAcc);
if (Config.showLiveAcc) {
LiveAcc.show();
} else {
LiveAcc.hide();
}
saveConfigToCookie();
}
@ -745,9 +765,10 @@ function setTimeConfig(time, nosave) {
function setQuoteLength(len, nosave, multipleMode) {
if (Array.isArray(len)) {
//config load
if (len.length === 1 && len[0] === -1) len = [1];
ConfigSet.quoteLength(len);
} else {
if (!Array.isArray(ConfigSet.quoteLength)) Config.quoteLength([]);
if (!Array.isArray(ConfigSet.quoteLength)) ConfigSet.quoteLength([]);
if (len === null || isNaN(len) || len < -2 || len > 3) {
len = 1;
}
@ -1264,6 +1285,7 @@ function applyConfig(configObj) {
setOppositeShiftMode(configObj.oppositeShiftMode, true);
setMode(configObj.mode, true);
setMonkey(configObj.monkey, true);
setRepeatQuotes(configObj.repeatQuotes, true);
setActiveLanguageGroup();

View file

@ -2570,9 +2570,10 @@ key {
margin: 0;
}
.text {
& > .text {
align-self: normal;
color: var(--text-color);
grid-area: text;
}
.buttons {
@ -2706,6 +2707,10 @@ key {
overflow: revert;
height: auto;
&.customTheme {
margin-top: 0.5rem;
}
.text {
align-self: center;
}
@ -2770,9 +2775,10 @@ key {
grid-template-columns: 2fr 1fr;
grid-template-areas:
"title tabs"
"text text"
"buttons buttons";
column-gap: 2rem;
row-gap: 0.5rem;
// row-gap: 0.5rem;
.tabs {
display: grid;
@ -2811,6 +2817,7 @@ key {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 0.5rem;
margin-top: 0.5rem;
}
}
}

View file

@ -150,11 +150,15 @@
<div id="quoteSearchPopupWrapper" class="hidden">
<div id="quoteSearchPopup" mode="">
<div class="title">Quote Search</div>
<input id="searchBox" class="searchBox" type="text" maxLength="200" autocomplete="off"/>
<input
id="searchBox"
class="searchBox"
type="text"
maxlength="200"
autocomplete="off"
/>
<div id="extraResults">No search results</div>
<div id="quoteSearchResults" class="quoteSearchResults">
</div>
<div id="quoteSearchResults" class="quoteSearchResults"></div>
</div>
</div>
<div id="tagsWrapper" class="hidden">
@ -1518,7 +1522,7 @@
<div>Jackson</div>
<div>Nicholas</div>
<div>Kenn</div>
<div>Kieren</div>
<div>Ennui</div>
<div>mweepigeon</div>
<div>Stephen</div>
<div>Pulsing Penguin</div>
@ -1912,6 +1916,11 @@
</div>
<div class="section funbox">
<h1>funbox</h1>
<div class="text">
These are special modes that change the website in some
special way (by altering the word generation, behaviour of the
website or the looks). Give each one of them a try!
</div>
<div class="buttons"></div>
</div>
<div class="sectionSpacer"></div>
@ -2125,6 +2134,11 @@
</div>
<div class="section layout">
<h1>layout override</h1>
<div class="text">
With this setting you can emulate other layouts. This setting
is best kept default, as it can break things like dead keys
and alt layers.
</div>
<div class="buttons"></div>
</div>
<div class="sectionSpacer"></div>
@ -2876,27 +2890,27 @@
tabContent="custom"
class="tabContent section customTheme hidden"
>
<label class="text">background</label>
<label class="colorText">background</label>
<span class="colorPicker">
<label for="--bg-color">#000000</label>
<input type="color" value="#000000" id="--bg-color" />
</span>
<label class="text">main</label>
<label class="colorText">main</label>
<span class="colorPicker">
<label for="--main-color">#000000</label>
<input type="color" value="#000000" id="--main-color" />
</span>
<label class="text">caret</label>
<label class="colorText">caret</label>
<span class="colorPicker">
<label for="--caret-color">#000000</label>
<input type="color" value="#000000" id="--caret-color" />
</span>
<label class="text">sub</label>
<label class="colorText">sub</label>
<span class="colorPicker">
<label for="--sub-color">#000000</label>
<input type="color" value="#000000" id="--sub-color" />
</span>
<label class="text">text</label>
<label class="colorText">text</label>
<span class="colorPicker">
<label for="--text-color">#000000</label>
<input type="color" value="#000000" id="--text-color" />
@ -2904,12 +2918,12 @@
<span class="spacer"></span>
<label class="text">error</label>
<label class="colorText">error</label>
<span class="colorPicker">
<label for="--error-color">#000000</label>
<input type="color" value="#000000" id="--error-color" />
</span>
<label class="text">extra error</label>
<label class="colorText">extra error</label>
<span class="colorPicker">
<label for="--error-extra-color">#000000</label>
<input
@ -2921,7 +2935,7 @@
<p>colorful mode</p>
<label class="text">error</label>
<label class="colorText">error</label>
<span class="colorPicker">
<!-- Change variable names here -->
<label for="--colorful-error-color">#000000</label>
@ -2931,7 +2945,7 @@
id="--colorful-error-color"
/>
</span>
<label class="text">extra error</label>
<label class="colorText">extra error</label>
<span class="colorPicker">
<!-- Change variable names here -->
<label for="--colorful-error-extra-color">#000000</label>

View file

@ -247,7 +247,7 @@
"unterlassen Sie",
"während",
"Presse",
"Schließen",
"schließen",
"Nacht",
"realen",
"Leben",
@ -574,7 +574,7 @@
"Board",
"Freude",
"Winter",
"sa",
"sah",
"geschrieben",
"wilden",
"Instrument",
@ -590,7 +590,7 @@
"weich",
"Spaß",
"hell",
"Gases",
"Gas",
"Wetter",
"Monat",
"Million",
@ -771,8 +771,8 @@
"schützen",
"Mittag",
"Ernte",
"modernen",
"Elementes",
"modern",
"Element",
"treffen",
"Schüler",
"Ecke",
@ -878,7 +878,7 @@
"Angebot",
"Segment",
"Sklave",
"ente",
"Ente",
"Augenblick",
"Markt",
"Grad",
@ -929,7 +929,7 @@
"führen",
"Erfahrung",
"Partitur",
"apfel",
"Apfel",
"gekauft",
"geführt",
"Tonhöhe",
@ -976,7 +976,6 @@
"Baumwolle",
"geboren",
"bestimmen",
"Quart",
"neun",
"Lastwagen",
"Lärm",

View file

@ -32178,6 +32178,96 @@
"source": "Mr. Robot",
"length": 43,
"id": 5412
},
{
"text": "No man or woman alive, magical or not, has ever escaped some form of injury, whether physical, mental, or emotional.",
"source": "J. K. Rowling, The Tales of Beedle the Bard",
"length": 116,
"id": 5413
},
{
"text": "Death comes for us all in the end.",
"source": "J. K. Rowling, The Tales of Beedle the Bard",
"length": 34,
"id": 5414
},
{
"text": "Magic causes as much trouble as it cures.",
"source": "J. K. Rowling, The Tales of Beedle the Bard",
"length": 41,
"id": 5415
},
{
"text": "The heroes and heroines who triumph in his stories are not those with the most powerful magic, but rather those who demonstrate the most kindness, common sense and ingenuity.",
"source": "J. K. Rowling, The Tales of Beedle the Bard",
"length": 174,
"id": 5416
},
{
"text": "As the Wheel of Time turns, places wear many names. Men wear many names, many faces. Different faces, but always the same man. Yet no one knows the Great Pattern the Wheel weaves, or even the Pattern of an Age. We can only watch, and study, and hope.",
"source": "Robert Jordan, Wheel of Time: The Eye of the World",
"length": 250,
"id": 5417
},
{
"text": "We can't go back, Mat. The Wheel has turned, for better or worse. And it will keep on turning, as lights die and forests dim, storms call and skies break. Turn it will. The Wheel is not hope, and the Wheel does not care, the Wheel simply is. But so long as it turns, folk may hope, folk may care. For with light that fades, another will eventually grow, and each storm that rages must eventually die. As long as the Wheel turns.",
"source": "Robert Jordan, Wheel of Time: The Eye of the World",
"length": 428,
"id": 5418
},
{
"text": "You tried to help the people of the market. You mostly failed. This is life. The longer you live, the more you fail. Failure is the mark of a life well lived. In turn, the only way to live without failure is to be of no use to anyone. Trust me, I've practiced",
"source": "Brandon Sanderson, Stormlight Archive: Oathbringer",
"length": 259,
"id": 5419
},
{
"text": "Because the world is round, it turns me on. Because the world is round. Because the wind is high, it blows my mind. Because the wind is high. Love is old, love is new. Love is all, love is you. Because the sky is blue, it makes me cry. Because the sky is blue.",
"source": "The Beatles",
"length": 260,
"id": 5420
},
{
"text": "But stories don't end. They continue as long as you're alive. You just have to get on with things. Turn the page, start a new chapter, find out what's in store for you next, and keep your fingers crossed that it's not too awful. Even if you know in your heart and soul that it most probably will be.",
"source": "Darren Shan, Slawter",
"length": 299,
"id": 5421
},
{
"text": "You can't hang around waiting for somebody else to pull your strings. Destiny's what you make of it. You have to face whatever life throws at you. And if it throws more than you'd like, more than you think you can handle? Well then you just have to find the heroism within yourself and play out the hand you've been dealt. The universe never sets a challenge that can't be met. You just need to believe in yourself in order to find the strength to face it.",
"source": "Darren Shan, Hell's Heroes",
"length": 456,
"id": 5422
},
{
"text": "Most patients report a night of dreamless sleep after only one viewing of this videocassette. Consult your technician if you are experiencing delayed results and/or unwanted side effects. Do not see a doctor.",
"source": "LOCAL58TV, Real Sleep",
"length": 208,
"id": 5423
},
{
"text": "If you look for the light, you can often find it. But if you look for the dark, that is all you will ever see.",
"source": "The Legend of Korra",
"length": 110,
"id": 5424
},
{
"text": "Now, if you two don't mind I'll be off to bed before either of you come up with another clever idea to get us killed - or worse, expelled!",
"source": "Harry Potter and the Philosophers Stone",
"length": 138,
"id": 5425
},
{
"text": "The County Weather Service has issued a warning for a meteorological event. This warning is effective immediately and continues until sunrise tomorrow morning. Citizens are advised not to observe this event with the naked eye.",
"source": "LOCAL58TV, Weather Service",
"length": 226,
"id": 5426
},
{
"text": "Jack heard it again. There is a voice from space. Jack, do you see me? I have become something else. Listen to the silver box. The stars are moving now. Do you see the hungry eye? Here I am.",
"source": "Gemini Home Entertainment, Artificial Computer Learning",
"length": 190,
"id": 5427
}
]
}

View file

@ -0,0 +1,29 @@
{
"language": "filipino",
"groups": [
[
0,
100
],
[
101,
300
],
[
301,
600
],
[
601,
9999
]
],
"quotes": [
{
"text": "Ang hindi magmahal sa sariling wika ay higit sa hayop at malansang isda; kaya ating pagyamaning kusa, gaya ng inang sa atin ay nagpala.",
"source": "Dr. José P. Rizal",
"length": 135,
"id": 1
}
]
}

View file

@ -20,7 +20,7 @@
"id": 2
},
{
"text": "Belajar tanpa berpikir itu tidaklah berguna, tapi berpikir tanpa belajar itu sangatlah berbahaya",
"text": "Belajar tanpa berpikir itu tidaklah berguna, tapi berpikir tanpa belajar itu sangatlah berbahaya.",
"source": "Ir. Soekarno",
"length": 97,
"id": 3
@ -32,7 +32,7 @@
"id": 4
},
{
"text": "Barang siapa ingin mutiara, harus berani terjun di lautan yang dalam",
"text": "Barang siapa ingin mutiara, harus berani terjun di lautan yang dalam.",
"source": "Ir. Soekarno",
"length": 68,
"id": 5
@ -110,7 +110,7 @@
"id": 17
},
{
"text": "Bangsa yang besar adalah bangsa yang menghormati jasa pahlawannya.",
"text": "Bangsa yang besar adalah bangsa yang menghormati jasa pahlawannya.",
"source": "Ir. Soekarno",
"length": 67,
"id": 18
@ -122,7 +122,7 @@
"id": 19
},
{
"text": "Kurang cerdas dapat diperbaiki dengan belajar. Kurang cakap dapat dihilangkan dengan pengalaman. Namun tidak jujur itu sulit diperbaiki",
"text": "Kurang cerdas dapat diperbaiki dengan belajar. Kurang cakap dapat dihilangkan dengan pengalaman. Namun tidak jujur itu sulit diperbaiki.",
"source": "Mohammad Hatta",
"length": 136,
"id": 20
@ -308,7 +308,7 @@
"id": 51
},
{
"text": "Tahukah kamu? Hal-hal kecil sering kali membunuh kita dengan cara yang lebih besar, pelan-pelan, dalam jangka waktu Yang panjang. Semua kebiasaan itu membuatku dihantam kehilangan. Tak usah kamu tanya bagaimana sesaknya. Kamu tahu bagaimana rasanya menjabarkan sedih, tidak akan cukup jika hanya dengan sekadar kata pedih. Kehilangan membuatku tak ingin mengenali diriku sendiri. Aku berusaha untuk menjadi orang lain. Aku mencoba menikmati hari-hari yang bukan diriku lagi. Sebab, menjadi diriku artinya aku sama sekali tidak bisa melepaskanmu.",
"text": "Tahukah kamu? Hal-hal kecil sering kali membunuh kita dengan cara yang lebih besar, pelan-pelan, dalam jangka waktu yang panjang. Semua kebiasaan itu membuatku dihantam kehilangan. Tak usah kamu tanya bagaimana sesaknya. Kamu tahu bagaimana rasanya menjabarkan sedih, tidak akan cukup jika hanya dengan sekadar kata pedih. Kehilangan membuatku tak ingin mengenali diriku sendiri. Aku berusaha untuk menjadi orang lain. Aku mencoba menikmati hari-hari yang bukan diriku lagi. Sebab, menjadi diriku artinya aku sama sekali tidak bisa melepaskanmu.",
"source": "Buya Hamka",
"length": 543,
"id": 52

View file

@ -150,6 +150,48 @@
"source": "Manuel García, Conrado Miguel - Momentos estelares de la probabilidad y estadística",
"length": 417,
"id": 22
},
{
"text": "Dentro de veinte años estarás más decepcionado por las cosas que no hiciste, que por las que hiciste. Así que suelta las amarras. Navega lejos del puerto seguro. Atrapa los vientos alisios en tus velas. Explora. Sueña. Descubre.",
"source": "Mark Twain",
"length": 228,
"id": 23
},
{
"text": "He fallado más de 9000 mil tiros en mi carrera. He perdido casi 300 partidos. En 26 ocasiones, pude hacer la canasta que ganara el partido y fallé. He fracasado una y otra vez en mi vida. Y por esa razón he triunfado",
"source": "Michael Jordan",
"length": 216,
"id": 24
},
{
"text": "La falta de miedo es como un músculo. Sé por propia experiencia que cuanto más lo ejercitas más natural se convierte el no dejar que los miedos guíen tu vida.",
"source": "Arianna Huffington",
"length": 158,
"id": 25
},
{
"text": "Para evitar la crítica no hagas nada, no digas nada, no seas nada.",
"source": "Elbert Hubbard",
"length": 66,
"id": 26
},
{
"text": "La mente es todo. Te conviertes en lo que piensas",
"source": "Buda (Buddha)",
"length": 49,
"id": 27
},
{
"text": "La vida es una oportunidad, benefíciate de ella. La vida es belleza, admírala. La vida es un sueño, alcánzalo. La vida es un desafío, cumple. La vida es un deber, complétala. La vida es un juego, juégala. La vida es una promesa, cúmplela. La vida es pena, supérala. La vida es una canción, cántala. La vida es lucha, acéptala. La vida es una tragedia, enfréntala. La vida es una aventura, atrévete. La vida es suerte, hazlo. La vida es demasiado preciosa, no la destruyas. La vida es vida, lucha por ella.",
"source": "Madre Teresa",
"length": 505,
"id": 28
},
{
"text": "He sido impresionado con la urgencia de hacer. Saber no es suficiente, debemos aplicar. Estar dispuesto no es suficiente, debemos hacer",
"source": "Brady Shirel",
"length": 135,
"id": 29
}
]
}

View file

@ -1,10 +1,22 @@
{
"language": "swedish",
"groups": [
[0, 100],
[101, 300],
[301, 600],
[601, 9999]
[
0,
100
],
[
101,
300
],
[
301,
600
],
[
601,
9999
]
],
"quotes": [
{
@ -348,6 +360,30 @@
"source": "Arne Sand, Ljugarstriden",
"length": 143,
"id": 57
},
{
"text": "Provensalerna är nästan slösaktigare än svenskarna. Provensalska bönder och även köpmän är periodvis patologiskt slösaktiga och kan spela bort hus och hem på ett tärningskast.",
"source": "Evert Taube, Vallfart till Trubadurien och Toscana",
"length": 175,
"id": 58
},
{
"text": "Karl den stores storhet är en storgermansk propagandamyt! Karln var i det närmaste analfabet, hans konstintresse var en barbars lyxfröjd.",
"source": "Evert Taube, Vallfart till Trubadurien och Toscana",
"length": 137,
"id": 59
},
{
"text": "När man vill uppleva poesins monumentalitet eller himlaflykt eller innerligaste ömhet och smek eller torterande melankoli eller daggstänk av lyriska tårar eller förtvivlans gråt ur rödkantade ögon i en ungkarlslya där lakanen bränner som nässlor, nattskjortan dryper av ångestsvett och djävulen står i tamburen, då skall man läsa Dante.",
"source": "Evert Taube, Vallfart till Trubadurien och Toscana",
"length": 336,
"id": 60
},
{
"text": "En målare, som endast sett honom, skulle ha blivit förtjust; en musiker, som hört, skulle bringats till förtvivlan.",
"source": "Victoria Benedictsson, Pengar",
"length": 115,
"id": 61
}
]
}
}

View file

@ -24,6 +24,12 @@
"source": "Universal Declaration of Human Rights",
"length": 150,
"id": 1
},
{
"text": "ข้อ 2 ทุกคนย่อมมีสิทธิและอิสรภาพบรรดาที่กำหนดไว้ในปฏิญญานี้ โดยปราศจากความแตกต่างไม่ว่าชนิดใด ๆ ดังเช่น เชื้อชาติ ผิว เพศ ภาษา ศาสนา ความคิดเห็นทางการเมืองหรือทางอื่น เผ่าพันธุ์แห่งชาติ หรือสังคม ทรัพย์สิน กำเนิด หรือสถานะอื่น ๆ\\nอนึ่งจะไม่มีความแตกต่างใด ๆ ตามมูลฐานแห่งสถานะทางการเมือง ทางการศาล หรือทางการระหว่างประเทศของประเทศหรือดินแดนที่บุคคลสังกัด ไม่ว่าดินแดนนี้จะเป็นเอกราช อยู่ในความพิทักษ์มิได้ปกครองตนเอง หรืออยู่ภายใต้การจำกัดอธิปไตยใด ๆ ทั้งสิ้น",
"source": "Universal Declaration of Human Rights",
"length": 459,
"id": 2
}
]
}