X-Git-Url: http://git.shiar.nl/sheet.git/blobdiff_plain/20332e82f5c6365a8d65c75192985d846a99a2dd..c7530c743eb2d8f45167ae0a9ed641559a4d550e:/word/quiz.js diff --git a/word/quiz.js b/word/quiz.js index d32368b..1aaab61 100644 --- a/word/quiz.js +++ b/word/quiz.js @@ -6,56 +6,62 @@ Array.prototype.shuffle = function () { return this; }; +Set.prototype.filter = function (f) { + return new Set([...this].filter(f)); +}; + class WordQuiz { dataselect(json) { - this.data = json; - this.cats = {}; // category lookup - for (let i in json) { - let cat = json[i][3]; - if (this.cats[cat]) { - this.cats[cat].push(i); - } - else { - this.cats[cat] = [i]; - } - } - return this.datafilter(json); + this.data = this.datafilter(json); + let rows = Object.values(this.data); + rows = rows.filter(row => !row[3].length); // remove referenced categories + return rows.shuffle(); } datafilter(json) { // find viable rows from json data - let rows = Object.values(json); + let ids = new Set(Object.keys(json)); + const selection = {...json}; // clone if (this.preset.cat !== undefined) { - rows = []; - let children = this.cats[this.preset.cat]; + ids.clear(); + let children = [this.preset.cat]; for (let loop = 0; children.length && loop < 20; loop++) { - rows.push(...children); - children = children.map(cat => this.cats[cat]).filter(is => is).flat(); + for (let child of children) ids.add(child.toString()); + children = children.map(cat => json[cat][3]).filter(is => is).flat() } - rows = rows.map(row => json[row]).filter(row => row[2]); + } + if (this.preset.image) { + ids = ids.filter(id => json[id][2]); } if (this.preset.level !== undefined) { - rows = rows.filter(row => row[1] <= this.preset.level); + ids = ids.filter(id => json[id][1] <= this.preset.level); } - { - let cats = new Set(); - let subcats = rows.map(row => row[3]); // direct parents - for (let loop = 0; subcats.length && loop < 20; loop++) { - subcats.forEach(cat => cats.add(cat)); - subcats = subcats.map(row => json[row] && json[row][3]).filter(val => val); // recurse grandparents + // keep only wanted ids + for (let id in selection) { + if (id && !ids.has(id)) { + delete selection[id]; } - rows = rows.filter(row => !cats.has(row[2])); // remove referenced categories } - return rows.shuffle(); + + // retain orphaned references in grandparent categories + for (let id in selection) { + selection[id][3] = function subresolve(subs) { + //console.log(subs); + return (subs || []).flatMap(sub => + sub in selection ? [sub] : subresolve(json[sub][3]) + ); + }(selection[id][3]); + } + return selection; } load(dataurl) { this.preset = {}; let input; if (input = window.location.hash.match(/\d+/)) { - this.preset.cat = input[0]; + this.preset.cat = parseInt(input[0]); } if (window.location.hash.match(/a/)) { this.preset.level = 3;