To bridge the gap of difficulty between multiple choice and typing exercises this script changes the box color (green/red) depending on whether the answer is correct so far and displays a keyboard of keys for the remaining characters to get to the correct answer.
I am sharing in case someone finds it useful and wants to build on it.
// ==UserScript==
// @name Memrise - TypeHelper
// @namespace http://tampermonkey.net/
// @version 0.1
// @match https://www.memrise.com/course/*/garden/*
// @match https://www.memrise.com/garden/review/*
// @grant none
// ==/UserScript==
$(document).ready(function() {
//Events
MEMRISE.garden._events.start.push(() => {
$('body').on('.typing input', 'input', function(e) {
console.debug(e);
mark();
keyboard();
});
$('body').on('select', function(e) {
console.debug(e);
mark();
keyboard();
});
})
MEMRISE.garden._events.activate.push(() => {
console.debug('activate');
keyboard(true);
})
//Marking
function mark(){
if(MEMRISE.garden.box.template === 'typing'){
var input = MEMRISE.garden.box.$input.input.val();
var answer = MEMRISE.garden.box.testData.answer.value;
if(input === ''){
markNone();
}else if(answer.startsWith(input)){
markCorrect();
}else{
markIncorrect();
}
}
}
function markCorrect(){
MEMRISE.garden.box.$input.input.addClass('correct');
MEMRISE.garden.box.$input.input.removeClass('incorrect');
}
function markIncorrect(){
MEMRISE.garden.box.$input.input.addClass('incorrect');
MEMRISE.garden.box.$input.input.removeClass('correct');
}
function markNone(){
MEMRISE.garden.box.$input.input.removeClass('correct');
MEMRISE.garden.box.$input.input.removeClass('incorrect');
}
///Keyboard
var shuffled_answer; //to maintain the same order/shuffle once
function keyboard(shuffle = false){
if(MEMRISE.garden.box.template === 'typing'){
var input = MEMRISE.garden.box.$input.input.val();
var answer = MEMRISE.garden.box.testData.answer.value;
var rest = answer.rest(input);
if(shuffle){
shuffled_answer = answer.shuffle();
}
display(shuffled_answer.keep(rest));
}
}
function empty(){
$('.keyboard.clearfix').empty();
}
function addKey(c){
$('.keyboard.clearfix').append('<a class="shiny-box">' + c + '</a>')
}
function display(str){
empty();
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i);
addKey(c);
}
}
})
//Utils
String.prototype.shuffle = function () {
var a = this.split(''),
n = a.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return a.join('');
}
String.prototype.rest = function(str) {
var index = 0;
for(var i = 0; i < this.length; i++) {
if(this.charAt(i) === str.charAt(i)){
index++;
}else{
break;
}
}
return this.substring(index, this.length);
}
String.prototype.keep = function(str) {
var r = [];
var cs = str.split('');
for(var i = 0; i < this.length; i++){
var c = this.charAt(i);
if(cs.includes(c)){
r.push(c);
const index = cs.indexOf(c);
if (index > -1) {
cs.splice(index, 1);
}
}
}
return r.join('');
}
1 Like
Great idea, thanks for sharing!
@lurkmoophy: what do you think, wouldn’t this be a great extension for the web app?
Nice, is this script supposed to be typed in the console when you inspect the code.
My pleasure, thanks! I improved it a little (for example, if the current_streak < 5, the first letter is colored green, there will be at least 7 keys even if the word is small)
$(document).ready(function() {
function main(first=false){
if(MEMRISE.garden.box.template === 'typing'){
var current_streak = streak();
if(current_streak < 10){
mark();
keyboard(first);
}else if(current_streak < 20){
mark();
}else{
empty();
}
}
}
function streak(){
return MEMRISE.garden.box.thinguser.current_streak;
}
//Events
MEMRISE.garden._events.start.push(() => {
$('body').on('.typing input', 'input', function(e) {
console.debug(e);
main();
});
$('body').on('select', function(e) {
console.debug(e);
main();
});
})
MEMRISE.garden._events.activate.push(() => {
console.debug('activate');
main(true);
})
//Marking
function mark(){
var input = MEMRISE.garden.box.$input.input.val();
var answer = MEMRISE.garden.box.testData.answer.value;
if(input === ''){
markNone();
}else if(answer.startsWith(input)){
markCorrect();
}else{
markIncorrect();
}
}
function markCorrect(){
MEMRISE.garden.box.$input.input.addClass('correct');
MEMRISE.garden.box.$input.input.removeClass('incorrect');
}
function markIncorrect(){
MEMRISE.garden.box.$input.input.addClass('incorrect');
MEMRISE.garden.box.$input.input.removeClass('correct');
}
function markNone(){
MEMRISE.garden.box.$input.input.removeClass('correct');
MEMRISE.garden.box.$input.input.removeClass('incorrect');
}
///Keyboard
var shuffled_answer;
function keyboard(shuffle = false){
var input = MEMRISE.garden.box.$input.input.val();
var answer = MEMRISE.garden.box.testData.answer.value;
if(shuffle){
var choices = MEMRISE.garden.box.testData.choices;
console.debug(choices);
if(/*choices !== undefined &&*/ choices.length < 10){
console.debug('CHOICES');
answer = choices.join('').addMissingChars(answer);
}
if(answer.length < 7){
var add = 7 - answer.length;
answer = answer + choices.join('').shuffle().substr(0, add);
}
shuffled_answer = answer.shuffle();
console.debug(shuffled_answer);
}
display(shuffled_answer.remove(input));
if(shuffle && streak() < 5) {
colorChar(MEMRISE.garden.box.testData.answer.value.charAt(0));
}
}
function empty(){
$('.keyboard.clearfix').empty();
}
function colorChar(c){
$('.keyboard.clearfix').find("a:contains('" + c + "')").eq(0).css("background-color", "chartreuse");
}
function addKey(c){
if(c === ' ') return;
var box = $('<a class="shiny-box">' + c + '</a>');
$('.keyboard.clearfix').append(box);
}
function display(str){
empty();
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i);
addKey(c);
}
}
})
//Utils
String.prototype.shuffle = function () {
var a = this.split(''),
n = a.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return a.join('');
}
String.prototype.rest = function(str) {
var index = 0;
for(var i = 0; i < this.length; i++) {
if(this.charAt(i) === str.charAt(i)){
index++;
}else{
break;
}
}
return this.substring(index, this.length);
}
String.prototype.keep = function(str) {
var r = [];
var cs = str.split('');
for(var i = 0; i < this.length; i++){
var c = this.charAt(i);
if(cs.includes(c)){
r.push(c);
const index = cs.indexOf(c);
if (index > -1) {
cs.splice(index, 1);
}
}
}
return r.join('');
}
String.prototype.remove = function(str) {
var r = [];
var cs = str.split('');
for(var i = 0; i < this.length; i++){
var c = this.charAt(i);
if(cs.includes(c)){
const index = cs.indexOf(c);
if(index > -1) {
cs.splice(index, 1);
}
}else{
r.push(c);
}
}
return r.join('');
}
String.prototype.addMissingChars = function(str) {
var cs = str.split('');
for(var i = 0; i < this.length; i++){
var c = this.charAt(i);
if(cs.includes(c)){
const index = cs.indexOf(c);
if(index > -1) {
cs.splice(index, 1);
}
}
}
return this + cs.join('');
}
I use Tampermonkey (Firefox addon), which handles all the injection for you 
Thank you so much it is working now 
1 Like