From d78e5a17943a28c5286dec0ddeaa2133c8f3fac1 Mon Sep 17 00:00:00 2001 From: Jack Date: Sat, 8 Aug 2020 20:35:28 +0100 Subject: [PATCH] added backend result validation --- functions/index.js | 41 ++++++++++++++++++++++++++++++++++++++++- public/js/misc.js | 4 ++++ public/js/script.js | 12 ++++++++---- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/functions/index.js b/functions/index.js index 8454751d4..35f49a3e5 100644 --- a/functions/index.js +++ b/functions/index.js @@ -368,6 +368,41 @@ function stdDev(array) { ); } +function roundTo2(num) { + return Math.round((num + Number.EPSILON) * 100) / 100; +} + +function validateResult(result) { + if (result.wpm > result.rawWpm) { + console.error( + `Could not validate result for ${result.uid}. ${result.wpm} > ${result.rawWpm}` + ); + return false; + } + let wpm = roundTo2((result.correctChars * (60 / result.testDuration)) / 5); + let raw = roundTo2((result.allChars * (60 / result.testDuration)) / 5); + if ( + wpm < result.wpm - result.wpm * 0.01 || + wpm > result.wpm + result.wpm * 0.01 + ) { + console.error( + `Could not validate result for ${result.uid}. ${wpm} != ${result.wpm}` + ); + return false; + } + + if ( + raw < result.rawWpm - result.rawWpm * 0.01 || + raw > result.rawWpm + result.rawWpm * 0.01 + ) { + console.error( + `Could not validate result for ${result.uid}. ${raw} != ${result.rawWpm}` + ); + return false; + } + return true; +} + exports.testCompleted = functions.https.onCall(async (request, response) => { try { if (request.uid === undefined || request.obj === undefined) { @@ -401,6 +436,10 @@ exports.testCompleted = functions.https.onCall(async (request, response) => { return { resultCode: -1 }; } + if (!validateResult(obj)) { + return { resultCode: -4 }; + } + let keySpacing = null; let keyDuration = null; @@ -452,7 +491,7 @@ exports.testCompleted = functions.https.onCall(async (request, response) => { request.obj.name = name; //check keyspacing and duration here - if (obj.mode === "time") { + if (obj.mode === "time" && obj.wpm > 130) { if (verified === false || verified === undefined) { if (keySpacing !== null && keyDuration !== null) { if ( diff --git a/public/js/misc.js b/public/js/misc.js index 9c664aa81..0433732a9 100644 --- a/public/js/misc.js +++ b/public/js/misc.js @@ -206,3 +206,7 @@ function hexToHSL(H) { string: "hsl(" + h + "," + s + "%," + l + "%)", }; } + +function roundTo2(num) { + return Math.round((num + Number.EPSILON) * 100) / 100; +} diff --git a/public/js/script.js b/public/js/script.js index 09023f67d..7e9829d57 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -1220,10 +1220,6 @@ function countChars() { }; } -function roundTo2(num) { - return Math.round((num + Number.EPSILON) * 100) / 100; -} - function calculateStats() { if (config.mode == "words" && config.difficulty == "normal") { if (inputHistory.length != wordsList.length) return; @@ -1259,6 +1255,11 @@ function calculateStats() { acc: acc, correctChars: chars.correctWordChars, incorrectChars: chars.incorrectChars + chars.extraChars + chars.missedChars, + allChars: + chars.allCorrectChars + + chars.spaces + + chars.incorrectChars + + chars.extraChars, time: testSeconds, spaces: chars.spaces, correctSpaces: chars.correctSpaces, @@ -1486,6 +1487,7 @@ function showResult(difficultyFailed = false) { rawWpm: stats.wpmRaw, correctChars: stats.correctChars + stats.correctSpaces, incorrectChars: stats.incorrectChars, + allChars: stats.allChars, acc: stats.acc, mode: config.mode, mode2: mode2, @@ -1596,6 +1598,8 @@ function showResult(difficultyFailed = false) { "Could not verify. Result not saved. Refresh or contact Miodec on Discord.", 4000 ); + } else if (e.data.resultCode === -4) { + showNotification("Result data invalid", 4000); } else if (e.data.resultCode === -999) { console.error("internal error: " + e.data.message); showNotification(