Add typo detector & update some dependencies

This commit is contained in:
2021-10-01 21:01:07 +01:00
parent 33cacf597a
commit c0100596cf
10 changed files with 167 additions and 128 deletions

View File

@@ -1,6 +1,6 @@
/* eslint-disable indent */
/* eslint-disable no-tabs */
const functions = require("firebase-functions").region("europe-west2");//.region("europe-west2")
const levenshtein = require('js-levenshtein');
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
@@ -238,6 +238,7 @@ exports.createProgress = functions.https.onCall((data, context) => {
}
return 0;
}),
typo: false,
}
return {
@@ -400,6 +401,7 @@ function cleanseVocabString(item) {
* @return {integer} totalQuestions Total number of questions in the set (including duplicates after incorrect answers).
* @return {integer} totalCorrect Total number of correct answers so far.
* @return {integer} totalIncorrect Total number of incorrect answers so far.
* @return {boolean} typo Whether the inputted answer is likely to include a typo.
*/
exports.processAnswer = functions.https.onCall((data, context) => {
const uid = context.auth.uid;
@@ -458,6 +460,24 @@ exports.processAnswer = functions.https.onCall((data, context) => {
}
});
if (!isCorrectAnswer && !progressDoc.data().typo) {
let typo = false;
cleansedSplitCorrectAnswers.forEach((answer, index, array) => {
const levDistance = levenshtein(answer, cleansedInputAnswer);
if (levDistance <= 1 ||
answer.length > 5 && levDistance <= 3 ||
answer.length > 10 && levDistance <= 4) {
docData.typo = true;
transaction.set(progressDocId, docData);
typo = true;
array.length = index + 1;
}
});
if (typo) return {
typo: true,
};
}
let prevCorrect = progressDoc.data().current_correct;
var returnData = {
@@ -471,8 +491,11 @@ exports.processAnswer = functions.https.onCall((data, context) => {
totalQuestions: docData.questions.length,
totalCorrect: docData.correct.length,
totalIncorrect: docData.incorrect.length,
typo: false,
}
docData.typo = false;
if (isCorrectAnswer) {
if (mode === "lives") {
returnData.lives = docData.lives;

View File

@@ -120,9 +120,9 @@
}
},
"@google-cloud/common": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.7.1.tgz",
"integrity": "sha512-BJfcV5BShbunYcn5HniebXLVp2Y6fpuesNegyar5CG8H2AKYHlKxnVID+FSwy92WAW4N2lpGdvxRsmiAn8Fc3w==",
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.7.2.tgz",
"integrity": "sha512-5Q9f74IbZaY6xAwJSNFy5SrGwbm1j7mpv+6A/r+K2dymjsXBH5UauB0tziaMwWoVVaMq1IQnZF9lgtfqqvxcUg==",
"optional": true,
"requires": {
"@google-cloud/projectify": "^2.0.0",
@@ -137,9 +137,9 @@
}
},
"@google-cloud/firestore": {
"version": "4.15.0",
"resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.0.tgz",
"integrity": "sha512-0hJnzkGeEGcFtyJ6PWYOzBT5xYcm7V1xZCQIeG0dIH989OPnWGJoM2ZUZGFNIxRB24KtbRasoy75+8dyYpKAyw==",
"version": "4.15.1",
"resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz",
"integrity": "sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA==",
"optional": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@@ -171,9 +171,9 @@
"optional": true
},
"@google-cloud/storage": {
"version": "5.14.0",
"resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.14.0.tgz",
"integrity": "sha512-tc8IrD1ZfKOm0WoC2r3+YG8K7NdaxsubedM3KYOf0m2QqqD4j9gYuEqIegs+jGoV2fr1XMibb9g/4DLp5Sv5kg==",
"version": "5.14.1",
"resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.14.1.tgz",
"integrity": "sha512-rDwL5QKFs4p20lXep/ELYscCpCiaiPK9H9QTnPTqRQgswsDO0p+SEupq0Uw00+r4SfbHnjtvYTzBFlTu7Gn34g==",
"optional": true,
"requires": {
"@google-cloud/common": "^3.7.0",
@@ -389,9 +389,9 @@
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
},
"@types/node": {
"version": "16.7.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz",
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA=="
"version": "16.7.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.13.tgz",
"integrity": "sha512-pLUPDn+YG3FYEt/pHI74HmnJOWzeR+tOIQzUx93pi9M7D8OE7PSLr97HboXwk5F+JS+TLtWuzCOW97AHjmOXXA=="
},
"@types/qs": {
"version": "6.9.7",
@@ -1196,9 +1196,9 @@
}
},
"firebase-admin": {
"version": "9.11.1",
"resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-9.11.1.tgz",
"integrity": "sha512-Y9fjelljy6MKqwsSbM/UN1k8gBQh5zfm5fCTe0Z6Gch2T3nDUIPsTcf+jfe4o40/MPYuybili9XJjTMmM2e5MQ==",
"version": "9.11.0",
"resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-9.11.0.tgz",
"integrity": "sha512-68fXdwcKF99LkWBE33M5hnLwjvGpbCRznIOtZVsiBqZdM9iwxlTfNEpAckh++o3GdJcSLRUWmIN+MKqPUsxoCA==",
"requires": {
"@firebase/database": "^0.10.0",
"@firebase/database-types": "^0.7.2",
@@ -1212,9 +1212,9 @@
}
},
"firebase-functions": {
"version": "3.15.4",
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.15.4.tgz",
"integrity": "sha512-6Zq+QIqdslZLsSwWg25Hv39cgFBZr0oUAbCjfe/MXqSHMy8ZK/1Vdy/WKx5IRC6hE7+JrmfVylIyEonTyNcheA==",
"version": "3.15.3",
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.15.3.tgz",
"integrity": "sha512-1FupNg/bSrCH5All5BQ3ld7STKHWl3RAqlM2Dwf96Mf2RtOEeGt18Slh23A78igZTj7b++1Lg6fE2aGgzJT8LQ==",
"requires": {
"@types/cors": "^2.8.5",
"@types/express": "4.17.3",
@@ -1283,22 +1283,22 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
},
"gaxios": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.0.tgz",
"integrity": "sha512-pHplNbslpwCLMyII/lHPWFQbJWOX0B3R1hwBEOvzYi1GmdKZruuEHK4N9V6f7tf1EaPYyF80mui1+344p6SmLg==",
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.1.tgz",
"integrity": "sha512-9qXV7yrMCGzTrphl9/YGMVH41oSg0rhn1j3wJWed4Oqk45/hXDD2wBT5J1NjQcqTCcv4g3nFnyQ7reSRHNgBgw==",
"optional": true,
"requires": {
"abort-controller": "^3.0.0",
"extend": "^3.0.2",
"https-proxy-agent": "^5.0.0",
"is-stream": "^2.0.0",
"node-fetch": "^2.3.0"
"node-fetch": "^2.6.1"
}
},
"gcp-metadata": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.0.tgz",
"integrity": "sha512-L9XQUpvKJCM76YRSmcxrR4mFPzPGsgZUH+GgHMxAET8qc6+BhRJq63RLhWakgEO2KKVgeSDVfyiNjkGSADwNTA==",
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz",
"integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==",
"optional": true,
"requires": {
"gaxios": "^4.0.0",
@@ -1306,9 +1306,9 @@
}
},
"gcs-resumable-upload": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-3.3.0.tgz",
"integrity": "sha512-MQKWi+9hOSTyg5/SI1NBW4gAjL1wlkoevHefvr1PCBBXH4uKYLsug5qRrcotWKolDPLfWS51cWaHRN0CTtQNZw==",
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-3.3.1.tgz",
"integrity": "sha512-WyC0i4VkslIdrdmeM5PNuGzANALLXTG5RoHb08OE30gYT+FEvCDPiA8KOjV2s1wOu9ngEW4+IuzBjtP/ni7UdQ==",
"optional": true,
"requires": {
"abort-controller": "^3.0.0",
@@ -1365,9 +1365,9 @@
}
},
"google-auth-library": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.8.0.tgz",
"integrity": "sha512-I2DPwbBbQicoLqPbUOcq7oxtWewbLO6Za2jZ5QM9Lz1hXxPJVXYXBUrb8lP9626SRTQQWIzNSWJuEDtu0pI4ag==",
"version": "7.9.1",
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.9.1.tgz",
"integrity": "sha512-cWGykH2WBR+UuYPGRnGVZ6Cjq2ftQiEIFjQWNIRIauZH7hUWoYTr/lkKUqLTYt5dex77nlWWVQ8aPV80mhfp5w==",
"optional": true,
"requires": {
"arrify": "^2.0.0",
@@ -1382,9 +1382,9 @@
}
},
"google-gax": {
"version": "2.24.3",
"resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.24.3.tgz",
"integrity": "sha512-0Rb2i2GWCEEYi1/EjQt1QsFW2Jwzm1ob21kYc7UpOmkfsmTXuyhzK7Aeyxxpo7QT/Qh+50vqER1b2ruq6WGDXg==",
"version": "2.25.1",
"resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.25.1.tgz",
"integrity": "sha512-wvirrn34kKe42NRF9uy68ukM/2CWT2ce3abS2SOJaMe7Ecdya1Zcd54WAX9WAWnD0WoAfieeibD4o1Ijue8iJw==",
"optional": true,
"requires": {
"@grpc/grpc-js": "~1.3.0",
@@ -1592,6 +1592,11 @@
"@panva/asn1.js": "^1.0.0"
}
},
"js-levenshtein": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
"integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1899,9 +1904,9 @@
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.2.tgz",
"integrity": "sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA==",
"optional": true
},
"node-forge": {

View File

@@ -14,8 +14,9 @@
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^9.11.1",
"firebase-functions": "^3.15.4"
"firebase-admin": "^9.11.0",
"firebase-functions": "^3.15.3",
"js-levenshtein": "^1.1.6"
},
"devDependencies": {
"eslint": "^7.32.0",

133
package-lock.json generated
View File

@@ -1951,9 +1951,9 @@
}
},
"@google-cloud/precise-date": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-2.0.3.tgz",
"integrity": "sha512-+SDJ3ZvGkF7hzo6BGa8ZqeK3F6Z4+S+KviC9oOK+XCs3tfMyJCh/4j93XIWINgMMDIh9BgEvlw4306VxlXIlYA=="
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-2.0.4.tgz",
"integrity": "sha512-nOB+mZdevI/1Si0QAfxWfzzIqFdc7wrO+DYePFvgbOoMtvX+XfFTINNt7e9Zg66AbDbWCPRnikU+6f5LTm9Wyg=="
},
"@google-cloud/projectify": {
"version": "2.1.0",
@@ -1966,9 +1966,9 @@
"integrity": "sha512-d4VSA86eL/AFTe5xtyZX+ePUjE8dIFu2T8zmdeNBSa5/kNgXPCx/o/wbFNHAGLJdGnk1vddRuMESD9HbOC8irw=="
},
"@google-cloud/pubsub": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-2.17.0.tgz",
"integrity": "sha512-9Xya69A5VAYVEGf651jy071RuBIjv+jpyozSc3j8V21LIiKRr9x+KyplHcLTYWdj+uXbP9cry8Ck8JEFc7GiqQ==",
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-2.18.1.tgz",
"integrity": "sha512-L2ejjRPszBybsRXJMLHN19UimpchNLNrtE7hJtoZxcy4fhITQGIDk1Ba4LceJYgSMJGA/YatZMYNavgyYpxhvA==",
"requires": {
"@google-cloud/paginator": "^3.0.0",
"@google-cloud/precise-date": "^2.0.0",
@@ -4159,46 +4159,11 @@
"integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM="
},
"ansi-align": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
"integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
"integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
"requires": {
"string-width": "^3.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": {
"ansi-regex": "^4.1.0"
}
}
"string-width": "^4.1.0"
}
},
"ansi-colors": {
@@ -5188,9 +5153,9 @@
}
},
"big-integer": {
"version": "1.6.48",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
"version": "1.6.49",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.49.tgz",
"integrity": "sha512-KJ7VhqH+f/BOt9a3yMwJNmcZjG53ijWMTjSAGMveQWyLwqIiwkjNP5PFgDob3Snnx86SjDj6I89fIbv0dkQeNw=="
},
"big.js": {
"version": "5.2.2",
@@ -7038,13 +7003,14 @@
}
},
"degenerator": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-2.2.0.tgz",
"integrity": "sha512-aiQcQowF01RxFI4ZLFMpzyotbQonhNpBao6dkI8JPk5a+hmSjR5ErHp2CQySmQe8os3VBqLCIh87nDBgZXvsmg==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.1.tgz",
"integrity": "sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ==",
"requires": {
"ast-types": "^0.13.2",
"escodegen": "^1.8.1",
"esprima": "^4.0.0"
"esprima": "^4.0.0",
"vm2": "^3.9.3"
}
},
"del": {
@@ -8863,11 +8829,6 @@
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"fast-safe-stringify": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
},
"fast-text-encoding": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
@@ -9169,9 +9130,9 @@
}
},
"firebase-tools": {
"version": "9.16.5",
"resolved": "https://registry.npmjs.org/firebase-tools/-/firebase-tools-9.16.5.tgz",
"integrity": "sha512-dp/cvt+39wv5CO+MzX36snmRnvn5j7Nn73QfKiIvHXAT5Ek/fRJn2pWnaxP+bhd19SuEY1Buf8PcdlMl42hzlw==",
"version": "9.19.0",
"resolved": "https://registry.npmjs.org/firebase-tools/-/firebase-tools-9.19.0.tgz",
"integrity": "sha512-jo9IhtddYBXEwO5m99oPZ53H4KInfhyYWD5+j6LD1bCsT9M95u+hNx+oXnRBVNTJjbwvlv/stF+zDy1WrpU1FA==",
"requires": {
"@google-cloud/pubsub": "^2.7.0",
"@types/archiver": "^5.1.0",
@@ -9214,7 +9175,7 @@
"ora": "^3.4.0",
"portfinder": "^1.0.23",
"progress": "^2.0.3",
"proxy-agent": "^4.0.0",
"proxy-agent": "^5.0.0",
"request": "^2.87.0",
"rimraf": "^3.0.0",
"semver": "^5.7.1",
@@ -13709,14 +13670,14 @@
}
},
"logform": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
"integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz",
"integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==",
"requires": {
"colors": "^1.2.1",
"fast-safe-stringify": "^2.0.4",
"fecha": "^4.2.0",
"ms": "^2.1.1",
"safe-stable-stringify": "^1.1.0",
"triple-beam": "^1.3.0"
},
"dependencies": {
@@ -15337,9 +15298,9 @@
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
"pac-proxy-agent": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-4.1.0.tgz",
"integrity": "sha512-ejNgYm2HTXSIYX9eFlkvqFp8hyJ374uDf0Zq5YUAifiSh1D6fo+iBivQZirGvVv8dCYUsLhmLBRhlAYvBKI5+Q==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz",
"integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==",
"requires": {
"@tootallnate/once": "1",
"agent-base": "6",
@@ -15347,17 +15308,17 @@
"get-uri": "3",
"http-proxy-agent": "^4.0.1",
"https-proxy-agent": "5",
"pac-resolver": "^4.1.0",
"pac-resolver": "^5.0.0",
"raw-body": "^2.2.0",
"socks-proxy-agent": "5"
}
},
"pac-resolver": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-4.2.0.tgz",
"integrity": "sha512-rPACZdUyuxT5Io/gFKUeeZFfE5T7ve7cAkE5TUZRRfuKP0u5Hocwe48X7ZEm6mYB+bTB0Qf+xlVlA/RM/i6RCQ==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.0.tgz",
"integrity": "sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==",
"requires": {
"degenerator": "^2.2.0",
"degenerator": "^3.0.1",
"ip": "^1.1.5",
"netmask": "^2.0.1"
}
@@ -16884,16 +16845,16 @@
}
},
"proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-4.0.1.tgz",
"integrity": "sha512-ODnQnW2jc/FUVwHHuaZEfN5otg/fMbvMxz9nMSUQfJ9JU7q2SZvSULSsjLloVgJOiv9yhc8GlNMKc4GkFmcVEA==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz",
"integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==",
"requires": {
"agent-base": "^6.0.0",
"debug": "4",
"http-proxy-agent": "^4.0.0",
"https-proxy-agent": "^5.0.0",
"lru-cache": "^5.1.1",
"pac-proxy-agent": "^4.1.0",
"pac-proxy-agent": "^5.0.0",
"proxy-from-env": "^1.0.0",
"socks-proxy-agent": "^5.0.0"
},
@@ -18354,6 +18315,11 @@
"ret": "~0.1.10"
}
},
"safe-stable-stringify": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz",
"integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -20679,15 +20645,15 @@
}
},
"boxen": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz",
"integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
"integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
"requires": {
"ansi-align": "^3.0.0",
"camelcase": "^6.2.0",
"chalk": "^4.1.0",
"cli-boxes": "^2.2.1",
"string-width": "^4.2.0",
"string-width": "^4.2.2",
"type-fest": "^0.20.2",
"widest-line": "^3.1.0",
"wrap-ansi": "^7.0.0"
@@ -20971,6 +20937,11 @@
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
},
"vm2": {
"version": "3.9.3",
"resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.3.tgz",
"integrity": "sha512-smLS+18RjXYMl9joyJxMNI9l4w7biW8ilSDaVRvFBDwOH8P0BK1ognFQTpg0wyQ6wIKLTblHJvROW692L/E53Q=="
},
"w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",

View File

@@ -12,7 +12,7 @@
"firebase": "^8.10.0",
"firebase-admin": "^9.11.0",
"firebase-functions": "^3.14.1",
"firebase-tools": "^9.16.5",
"firebase-tools": "^9.19.0",
"firebaseui": "^5.0.0",
"normalize-url": "^6.1.0",
"rc-slider": "^9.7.2",

View File

@@ -287,6 +287,15 @@ export default withRouter(class Progress extends React.Component {
answer: this.state.answerInput,
progressId: this.props.match.params.progressId,
}).then(async (result) => {
if (result.data.typo) {
this.setState({
typo: true,
loading: false,
canProceed: true,
});
return true;
}
const data = result.data;
let newState = {
currentAnswerStatus: data.correct,
@@ -302,6 +311,7 @@ export default withRouter(class Progress extends React.Component {
currentVocabId: data.currentVocabId,
loading: false,
canProceed: true,
typo: false,
};
if (data.correct) {
@@ -425,6 +435,7 @@ export default withRouter(class Progress extends React.Component {
answerInput: "",
loading: false,
canProceed: true,
typo: false,
});
}
}
@@ -499,6 +510,7 @@ export default withRouter(class Progress extends React.Component {
loading={this.state.loading}
></Button>
</form>
<p className={!this.state.typo ? "hide" : ""}>Are you sure?</p>
<div className="correct-answers">
{
this.state.currentCorrect && this.state.currentCorrect.length > 0
@@ -619,7 +631,7 @@ export default withRouter(class Progress extends React.Component {
<input
type="text"
name="answer_input"
className={`answer-input ${this.state.currentAnswerStatus ? "answer-input--correct" : "answer-input--incorrect"}`}
className={`answer-input ${this.state.currentAnswerStatus ? "answer--correct" : "answer--incorrect"}`}
value={this.state.answerInput}
ref={inputEl => (this.answerInput = inputEl)}
readOnly
@@ -632,7 +644,12 @@ export default withRouter(class Progress extends React.Component {
loading={this.state.loading}
></Button>
</form>
<div className={`correct-answers ${this.state.currentAnswerStatus ? "correct-answers--correct" : "correct-answers--incorrect"}`}>
<p className={this.state.currentAnswerStatus ? "answer--correct" : "answer--incorrect"}>
{
this.state.currentAnswerStatus ? "Correct!" : "Incorrect"
}
</p>
<div className="correct-answers">
{
this.state.currentCorrect
?

View File

@@ -169,7 +169,7 @@ button:focus-visible, a:focus-visible {
}
input {
border-top: none;
border-top: none;
border-right: none;
border-left: none;
border-bottom: 2px solid var(--overlay-color);
@@ -177,6 +177,7 @@ input {
color: var(--text-color);
font: inherit;
min-width: 100px;
width: 0;
}
input:focus {
@@ -390,6 +391,10 @@ label .MuiIconButton-label > input {
margin-left: 12px;
}
.hide {
visibility: hidden;
}
@media screen and (max-width: 420px) {
.progress-history-container > div > *:nth-child(2), .progress-history-container--complete > div > *:nth-last-child(3), .progress-history-container--incomplete > div > *:nth-last-child(4) {
display: none;

View File

@@ -58,5 +58,4 @@
input[type=text].set-title-input {
flex: 1;
width: 0;
}

View File

@@ -16,11 +16,11 @@
caret-color: transparent;
}
input.answer-input--correct {
.answer--correct {
color: #3ac535;
}
input.answer-input--incorrect {
.answer--incorrect {
color: #ff5252;
}

View File

@@ -104,6 +104,7 @@ describe("Parandum Cloud Functions", () => {
assert.strictEqual(snapAfter.switch_language, false);
assert.strictEqual(snapAfter.uid, userOne);
assert.strictEqual(snapAfter.mode, "questions");
assert.strictEqual(snapAfter.typo, false);
assert.deepStrictEqual(termOneSnapAfter, {
item: termOne,
@@ -188,6 +189,7 @@ describe("Parandum Cloud Functions", () => {
assert.strictEqual(snapAfter.switch_language, false);
assert.strictEqual(snapAfter.uid, userOne);
assert.strictEqual(snapAfter.mode, "questions");
assert.strictEqual(snapAfter.typo, false);
});
it("createProgress can create new lives mode progress file from existing set", async () => {
@@ -243,6 +245,7 @@ describe("Parandum Cloud Functions", () => {
assert.strictEqual(snapAfter.uid, userOne);
assert.strictEqual(snapAfter.mode, "lives");
assert.strictEqual(snapAfter.lives, 2);
assert.strictEqual(snapAfter.typo, false);
});
it("createProgress can create new progress file from public set they aren't the owner of", async () => {
@@ -333,6 +336,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
};
const termDataOne = {
"item": termOne,
@@ -391,6 +395,7 @@ describe("Parandum Cloud Functions", () => {
totalQuestions: 3,
totalCorrect: 0,
totalIncorrect: 1,
typo: false,
}),
hamjest.is({
mode: "questions",
@@ -407,6 +412,7 @@ describe("Parandum Cloud Functions", () => {
totalQuestions: 3,
totalCorrect: 0,
totalIncorrect: 1,
typo: false,
})
));
@@ -429,6 +435,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
}),
hamjest.is({
correct: [],
@@ -446,6 +453,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
})
));
@@ -476,6 +484,7 @@ describe("Parandum Cloud Functions", () => {
assert.strictEqual(snapAfterCorrectData.switch_language, false);
assert.strictEqual(snapAfterCorrectData.uid, userOne);
assert.strictEqual(snapAfterCorrectData.mode, "questions");
assert.strictEqual(snapAfterCorrectData.typo, false);
});
it("processAnswer returns correct data", async () => {
@@ -495,6 +504,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
};
const termDataOne = {
"item": termOne,
@@ -541,6 +551,7 @@ describe("Parandum Cloud Functions", () => {
totalQuestions: 2,
totalCorrect: 0,
totalIncorrect: 1,
typo: false,
});
assert.strictEqual(returnAfterCorrect.mode, "questions");
@@ -576,6 +587,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
};
const termDataOne = {
"item": termOne,
@@ -637,6 +649,7 @@ describe("Parandum Cloud Functions", () => {
totalQuestions: 2,
totalCorrect: 0,
totalIncorrect: 0,
typo: false,
});
const snapAfterTermOneAnswerOneData = await progressDocId.get().then((doc) => doc.data());
@@ -656,6 +669,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
});
const returnAfterIncorrect = await processAnswer(secondTermAnswerTwoRequestData);
@@ -679,6 +693,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
}),
hamjest.is({
correct: [],
@@ -696,6 +711,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
})
));
@@ -730,6 +746,7 @@ describe("Parandum Cloud Functions", () => {
assert.strictEqual(snapAfterCorrectData.switch_language, false);
assert.strictEqual(snapAfterCorrectData.uid, userOne);
assert.strictEqual(snapAfterCorrectData.mode, "questions");
assert.strictEqual(snapAfterCorrectData.typo, false);
}).timeout(5000);
it("processAnswer ignores punctuation", async () => {
@@ -750,6 +767,7 @@ describe("Parandum Cloud Functions", () => {
switch_language: false,
uid: userOne,
mode: "questions",
typo: false,
};
const termDataOne = {
"item": termOne,