spanish-quizzer

An app to quiz you on Spanish vocabulary and verb conjugations
git clone https://git.ashermorgan.net/spanish-quizzer/
Log | Files | Refs | README

commit 83b8106aabdcf6c71815c552030cad3e4bbb91d7
parent f1bf078e53f95819a7aec3dab9b1c34941ee8f04
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Mon, 18 Jan 2021 16:45:12 -0800

Implement removeDuplicates setting.

Diffstat:
Mjs/app.js | 4++--
Mjs/filters.js | 22++++++++++++++++++++--
Mjs/global.js | 6+++++-
Mjs/settingsInput.js | 4++++
Mtests/test.filters.js | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mtests/test.global.js | 25+++++++++++++++++--------
6 files changed, 127 insertions(+), 19 deletions(-)

diff --git a/js/app.js b/js/app.js @@ -58,11 +58,11 @@ function loadVue() { CreateSession: function() { // Get prompts if (this.category === "vocab") { - this.prompts = Shuffle(ApplyFilters(Data.vocab, GetVocabFilters(this.filters), this.settings.multiplePrompts)); + this.prompts = Shuffle(ApplyFilters(Data.vocab, GetVocabFilters(this.filters), this.settings)); } else if (this.category === "verbs") { // Get prompts - this.prompts = Shuffle(ApplyFilters(Data.verbs, GetVerbFilters(this.filters), this.settings.multiplePrompts)); + this.prompts = Shuffle(ApplyFilters(Data.verbs, GetVerbFilters(this.filters), this.settings)); } // Set progress diff --git a/js/filters.js b/js/filters.js @@ -291,7 +291,11 @@ function GetVerbFilters(rawFilters) { * @param {Array} filters The io-filters. * @returns {Array} The prompts. */ -function ApplyFilters(terms, filters, multiplePrompts="Show together") { +function ApplyFilters(terms, filters, options={}) { + // Set options + if (!"multiplePrompts" in options) options.multiplePrompts = "Show together"; + if (!"removeDuplicates" in options) options.removeDuplicates = false; + // Filter terms let results = []; // Format: [[<output label>, <output>, <input label>, <input>]] for (let filter of filters) { @@ -319,7 +323,7 @@ function ApplyFilters(terms, filters, multiplePrompts="Show together") { // Check if multiple outputs exist if (prompts.length > 1) { - switch (multiplePrompts) { + switch (options.multiplePrompts) { case "Show one": // Set current prompt's output to a random prompt result[1] = prompts[Math.floor(Math.random() * (prompts.length - 1))] @@ -341,6 +345,20 @@ function ApplyFilters(terms, filters, multiplePrompts="Show together") { } } + // Remove duplicate prompts + if (options.removeDuplicates) { + results = results.filter((result, index) => { + return index === results.findIndex(obj => { + try { + return obj[0] === result[0] && obj[1] === result[1] && obj[2] === result[2] && obj[3] === result[3]; + } + catch { + return false; + } + }); + }); + } + // Return prompts return results; } diff --git a/js/global.js b/js/global.js @@ -66,6 +66,7 @@ function getSettings() { repeatPrompts: "Never", multiplePrompts: "Show together", multipleAnswers: "Require all", + removeDuplicates: false, }; // Parse settings @@ -101,9 +102,12 @@ function getSettings() { if (["Show together", "Show separately", "Show one"].includes(parsedSettings.multiplePrompts)) { settings.multiplePrompts = parsedSettings.multiplePrompts; } - if (["Require one", "Require any"].includes(parsedSettings.multipleAnswers)) { + if (["Require all", "Require any"].includes(parsedSettings.multipleAnswers)) { settings.multipleAnswers = parsedSettings.multipleAnswers; } + if ([true, false].includes(parsedSettings.removeDuplicates)) { + settings.removeDuplicates = parsedSettings.removeDuplicates; + } // Return parsed settings return settings; diff --git a/js/settingsInput.js b/js/settingsInput.js @@ -73,6 +73,10 @@ let settingsInput = Vue.component("settingsInput", { <option>Require any</option> </select> </div> + <div> + <input type="checkbox" id="settingsRemoveDuplicates" v-model="value.removeDuplicates"> + <label for="settingsRemoveDuplicates">Remove duplicate prompts</label> + </div> </div> `, }); diff --git a/tests/test.filters.js b/tests/test.filters.js @@ -757,6 +757,20 @@ describe("Filters", function() { ["C", "c", "Verb"], ]; + it("Should't effect prompts by default", function() { + // Initialize expected + let expected = [ + ["Upper", "A1, A2 , A3", "Lower", "a"], + ["Upper", "B1, B2", "Lower", "b"], + ]; + + // Call ApplyFilters + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}]); + + // Assert filtered vocab is correct + expect(actual).to.have.deep.members(expected); + }); + it("Shouldn't effect single prompts", function() { // Initialize expected let expected = [ @@ -764,7 +778,7 @@ describe("Filters", function() { ]; // Call ApplyFilters - let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Verb"}]}], "Show separately"); + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Verb"}]}], {multiplePrompts:"Show separately"}); // Assert filtered vocab is correct expect(actual).to.have.deep.members(expected); @@ -778,7 +792,7 @@ describe("Filters", function() { ]; // Call ApplyFilters - let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], "Show together"); + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], {multiplePrompts:"Show together"}); // Assert filtered vocab is correct expect(actual).to.have.deep.members(expected); @@ -795,7 +809,7 @@ describe("Filters", function() { ]; // Call ApplyFilters - let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], "Show separately"); + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], {multiplePrompts:"Show separately"}); // Assert filtered vocab is correct expect(actual).to.have.deep.members(expected); @@ -818,7 +832,7 @@ describe("Filters", function() { } // Call ApplyFilters - let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], "Show one"); + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], {multiplePrompts:"Show one"}); // Assert filtered vocab is correct expect(actual).to.have.deep.members(expected); @@ -846,7 +860,7 @@ describe("Filters", function() { } // Call ApplyFilters - let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], "Show one"); + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], {multiplePrompts:"Show one"}); // Assert filtered vocab is correct expect(actual).to.have.deep.members(expected); @@ -874,7 +888,7 @@ describe("Filters", function() { } // Call ApplyFilters - let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], "Show one"); + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], {multiplePrompts:"Show one"}); // Assert filtered vocab is correct expect(actual).to.have.deep.members(expected); @@ -885,6 +899,65 @@ describe("Filters", function() { } }); }); + + describe("removeDuplicates setting", function() { + // Initialize vocab2 + let vocab2 = [ + ["Upper", "Lower", "Type"], + ["A", "a", "Noun"], + ["B", "b", "Adjective"], + ["C", "c", "Verb"], + ]; + + it("Should't remove duplicate prompts by default", function() { + // Initialize expected + let expected = [ + ["Upper", "A", "Lower", "a"], + ["Upper", "B", "Lower", "b"], + ["Upper", "C", "Lower", "c"], + ["Upper", "A", "Lower", "a"], + ["Upper", "B", "Lower", "b"], + ]; + + // Call ApplyFilters + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[]}, {outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}]); + + // Assert filtered vocab is correct + expect(actual).to.have.deep.members(expected); + }); + + it("Should't remove duplicate prompts if equal to false", function() { + // Initialize expected + let expected = [ + ["Upper", "A", "Lower", "a"], + ["Upper", "B", "Lower", "b"], + ["Upper", "C", "Lower", "c"], + ["Upper", "A", "Lower", "a"], + ["Upper", "B", "Lower", "b"], + ]; + + // Call ApplyFilters + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[]}, {outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], {removeDuplicates:false}); + + // Assert filtered vocab is correct + expect(actual).to.have.deep.members(expected); + }); + + it("Should remove duplicate prompts if equal to true", function() { + // Initialize expected + let expected = [ + ["Upper", "A", "Lower", "a"], + ["Upper", "B", "Lower", "b"], + ["Upper", "C", "Lower", "c"], + ]; + + // Call ApplyFilters + let actual = ApplyFilters(vocab2, [{outputIndex:0, inputIndex:1, filters:[]}, {outputIndex:0, inputIndex:1, filters:[{index:2, value:"Noun|Adjective"}]}], {removeDuplicates:true}); + + // Assert filtered vocab is correct + expect(actual).to.have.deep.members(expected); + }); + }); }); describe("Shuffle method", function() { diff --git a/tests/test.global.js b/tests/test.global.js @@ -22,18 +22,23 @@ describe("Global.js", function() { let originalValue = localStorage.getItem("settings"); // Set localStorage settings - localStorage.setItem("settings", "{\"promptType\":\"Audio\",\"inputType\":\"Voice\",\"onMissedPrompt\":\"Tell me\",\"repeatPrompts\":\"5 prompts later\"}") + let expected = { + darkTheme: true, + promptType: "Audio", + inputType: "Voice", + onMissedPrompt: "Tell me", + repeatPrompts: "5 prompts later", + multiplePrompts: "Show one", + multipleAnswers: "Require any", + removeDuplicates: true, + }; + localStorage.setItem("settings", JSON.stringify(expected)); // Call getSettings let settings = getSettings(); // Assert settings loaded - expect(settings.promptType).to.equal("Audio"); - expect(settings.inputType).to.equal("Voice"); - expect(settings.onMissedPrompt).to.equal("Tell me"); - expect(settings.repeatPrompts).to.equal("5 prompts later"); - expect(settings.multiplePrompts).to.equal("Show together"); - expect(settings.multipleAnswers).to.equal("Require all"); + expect(settings).to.deep.equal(expected); // Restore original setting to localStorage localStorage.setItem("settings", originalValue); @@ -74,6 +79,9 @@ describe("Global.js", function() { expect(settings.inputType).to.equal("Text"); expect(settings.onMissedPrompt).to.equal("Correct me"); expect(settings.repeatPrompts).to.equal("Never"); + expect(settings.multiplePrompts).to.equal("Show together"); + expect(settings.multipleAnswers).to.equal("Require all"); + expect(settings.removeDuplicates).to.equal(false); // Restore original setting to localStorage localStorage.setItem("settings", originalValue); @@ -94,13 +102,14 @@ describe("Global.js", function() { repeatPrompts : "E", multiplePrompts : "F", multipleAnswers : "G", + removeDuplicates : "H", } // Call setSettings setSettings(settings); // Assert localStorage setting updated - expect(localStorage.getItem("settings")).to.equal(`{"darkTheme":"A","promptType":"B","inputType":"C","onMissedPrompt":"D","repeatPrompts":"E","multiplePrompts":"F","multipleAnswers":"G"}`); + expect(localStorage.getItem("settings")).to.equal(`{"darkTheme":"A","promptType":"B","inputType":"C","onMissedPrompt":"D","repeatPrompts":"E","multiplePrompts":"F","multipleAnswers":"G","removeDuplicates":"H"}`); // Restore original setting to localStorage localStorage.setItem("settings", originalValue);