From 819787ff54335a68b34b7d9729f6d7e28870d8ac Mon Sep 17 00:00:00 2001 From: Mischa POSLAWSKY Date: Mon, 25 Oct 2021 22:57:11 +0200 Subject: [PATCH] word/memory: card game to find matching pairs Another quiz concept well suited to this image dataset. Initially populated with distinct sets of grebes (currently the only untranslated references) to experiment with variance as a somewhat unique selling point. --- Makefile | 7 +++++-- word/memory.js | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ word/memory.plp | 48 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 word/memory.js create mode 100644 word/memory.plp diff --git a/Makefile b/Makefile index ad2f7a0..0742e97 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ sitemap.xml: tools/mksitemap light.css: tools/stripcss base.css $(call cmdsave,$^) -word: word/put.js data/wordlist.en.json data/wordlist.nl.json data/wordlist.ru.json +word: word/put.js data/wordlist.en.json data/wordlist.nl.json data/wordlist.ru.json data/wordpairs.json word/put.js: $(download) tools/wget-ifmodified https://github.com/kriszyp/put-selector/raw/master/put.js $@ @@ -73,9 +73,12 @@ data/wordlist.en.inc.pl: tools/mkwordlist data/wordlist.version.txt $(call cmdsave,$<) data/wordlist.%.inc.pl: tools/mkwordlist data/wordlist.version.txt $(call cmdsave,$< $*) -data/wordlist.%.json: data/wordlist.%.inc.pl +data/word%.json: data/word%.inc.pl $(call cmdsave,perl -MJSON=encode_json -E "print encode_json(do \$$ARGV[0])" ./$<) +data/wordpairs.inc.pl: data/wordlist.version.txt + @perl -I. -MShiar_Sheet::DB -MData::Dump=pp -E 'say pp(Shiar_Sheet::DB->connect->select("word w JOIN word a ON w.id=a.ref" => "w.id, a.id", {"a.lang"=>undef})->map or exit 1)' >$@ + .SECONDARY: data/font/%.ttf data/font/%.ttf: find /usr/share/fonts/truetype/ ~/.fonts/ -iname "$(@F)" | head -1 | xargs -i ln -sf {} $@ diff --git a/word/memory.js b/word/memory.js new file mode 100644 index 0000000..0e523a1 --- /dev/null +++ b/word/memory.js @@ -0,0 +1,56 @@ +class WordMemory { + turn(click) { + let target = click.currentTarget; + if (!target.classList.contains('turn')) { + // show an open card + this.turned.push(target); + put(target, '.turn'); + } + else if (this.turned.length < 2) { + return; // keep open + } + + if (this.turned.length <= 1) { + return; // first choice + } + + // compare two cards + let match = this.pairs[this.turned[0].id] == this.turned[1].id + || this.pairs[this.turned[1].id] == this.turned[0].id; + if (!match && !this.turned[0].classList.contains('bad')) { + put(this.turned[0], '.bad'); // indicate failure on first card + return; + } + + if (match) { + // lock both as correct + this.turned.forEach(card => put(card, '.good![onclick]')); + this.turned = []; + return; + } + + // fold back earlier cards + this.turned.splice(0, 2) + .forEach(card => put(card, '!.turn!.bad')); + } + + constructor() { + this.dataurl = '/data/wordpairs.json'; + fetch(this.dataurl).then(res => res.json()).then(pairs => { + this.turned = []; + this.pairs = pairs; + this.form = document.getElementById('quiz'); + this.cards = Object.entries(pairs).flat() + .map(e => e.toString()) + .sort(() => {return .5 - Math.random()}) // shuffle + this.cards.forEach(word => { + put(this.form, + 'figure>img[src=$]<', `/data/word/en/${word}.jpg`, + {onclick: e => this.turn(e), id: word} + ); + }); + }); + } +}; + +new WordMemory(); diff --git a/word/memory.plp b/word/memory.plp new file mode 100644 index 0000000..d12cc75 --- /dev/null +++ b/word/memory.plp @@ -0,0 +1,48 @@ +<(../common.inc.plp)><: + +Html({ + raw => <<'EOT', + + + +EOT +}); +say '

memory

'; -- 2.30.0