Greasy Fork is available in English.

WK Auto Commit (edited)

Auto commit for Wanikani with critical list edit.

// ==UserScript==
// @name         WK Auto Commit (edited)
// @namespace    WKAUTOCOMMIT
// @version      0.42
// @description  Auto commit for Wanikani with critical list edit.
// @author       Johannes Mikulasch
// @match        http://www.wanikani.com/review/session*
// @match        https://www.wanikani.com/review/session*
// @match        http://www.wanikani.com/lesson/session*
// @match        https://www.wanikani.com/lesson/session*
// @grant        none
// @run-at       document-end
// @license      
// ==/UserScript==

/*
 * WK Auto Commit
 * If you typed in the correct answer then it is automatically commited.
 * Therefore, you have to use the 'enter' key way less than before.
 *
 * Version 0.42
 *  Added Mixed mode.
 * Version 0.41
 *  Fixed an issue with random mode when users did not have Ultimate Reorder script active.
 * Version 0.40
 *  Improved UI and such.
 * Version 0.35
 *  Edit by WillNiels to stop auto committing critical items
 * Version 0.3
 *  Script works now on the Lessons page too
 * Version 0.2
 *  Makes script work with Greasemonkey and Firefox
 * Version 0.1
 *  Initial version
 *
 */


/* jshint -W097 */
'use strict';

var activated = true;
var mode;
var click_threshold = 600;

var on_lessons_page = false;


// ---- Tweak these as needed ---- //
var percentCritical = '95'; // If you get an item correct less than this percent, it won't auto commit.
var randomChance = .50;  // If random is on it will only auto commit this often. ( 0 [never] to 1 [always] )

// Mixed mode, both rates apply
var percentCriticalMixed = '75'; // If you get an item correct less than this percent, it won't auto commit.
var randomChanceMixed = .80;  // Random chance to commit (limiting kanji only) if passed critical test.
// ------------------------------- //

//don't change these!
var apiKey;
var crit_list = [];
var thisItem;
var lastItem = null;
var roll = 0;

var RandomFn = Math.randomB || Math.random;

var detect_lessons_page = function() {
    // Returns true if on lessons page
    var current_url = window.location.href;
    var lessonsPattern = /^http[s]?:\/\/www.wanikani.com\/lesson\/session.*/;
    return lessonsPattern.test(current_url);
};

var toggle = function () {
    //Note: mode is only saved if user clicks the button.
    switch (mode) {
        case 'always': // To Mixed
            switchMode('mixed');
            break;
        case 'mixed': // To Critical
            if( on_lessons_page )
                switchMode('random');
            else 
                switchMode('critical');
            break;
        case 'critical': // To Random
            switchMode('random');
            break;
        case 'random': // To OFF
            switchMode('off');
            break;
        case 'off': // To Always
            switchMode('always');
            break;
    }
    saveMode();
};

var switchMode = function ( switchto ){
    switch (switchto) {
        case 'critical': // To Critical
            $("#WKAUTOCOMMIT_button").prop('title', "Switch to Random Mode");
            $("#WKAUTOCOMMIT_button").css({"opacity":"1.0"});
            $("#WKAUTOCOMMIT_button").css({"background-color":"#5C5"});
            $("#WKAUTOCOMMIT_button").text("Auto Commit: Critical List");
            mode = 'critical';
            generateList( percentCritical );
            break;
        case 'random': // To Random
            $("#WKAUTOCOMMIT_button").prop('title', "Switch auto commit OFF");
            $("#WKAUTOCOMMIT_button").css({"opacity":"1.0"});
            $("#WKAUTOCOMMIT_button").css({"background-color":"#55C"});
            $("#WKAUTOCOMMIT_button").text("Auto Commit: Random");
            mode = 'random';
            break;
        case 'off': // To OFF
            $("#WKAUTOCOMMIT_button").prop('title', "Switch to Always Mode");
            $("#WKAUTOCOMMIT_button").css({"opacity":"0.5"});
            $("#WKAUTOCOMMIT_button").css({"background-color":"#555"});
            $("#WKAUTOCOMMIT_button").text("Auto Commit: OFF");
            mode = 'off';
            break;
        case 'always': // To Always
            $("#WKAUTOCOMMIT_button").prop('title', "Switch to Mixed Mode");
            $("#WKAUTOCOMMIT_button").css({"opacity":"1.0"});
            $("#WKAUTOCOMMIT_button").css({"background-color":"#C55"});
            $("#WKAUTOCOMMIT_button").text("Auto Commit: Always");
            mode = 'always';
            break;
        case 'mixed': // To Always
            $("#WKAUTOCOMMIT_button").prop('title', "Switch to Critical Mode (or Random if on lessons)");
            $("#WKAUTOCOMMIT_button").css({"opacity":"1.0"});
            $("#WKAUTOCOMMIT_button").css({"background-color":"#2CC"});
            $("#WKAUTOCOMMIT_button").text("Auto Commit: Mixed");
            mode = 'mixed';
            generateList( percentCriticalMixed );
            break;
    }
};

var sanitize = function (str1) {
    var str2 = str1.replace(/\s/g, ''); // Removes Whitespaces
    str2 = str2.toLowerCase();
    return str2;
};

var commit = function () {
    $("#answer-form form button").click();
    setTimeout(function(){ $("#answer-form form button").click();}, click_threshold);
};

var check_input = function () {

    if (on_lessons_page) {
        var currentItem = $.jStorage.get("l/currentQuizItem");
        var currentquestiontype = $.jStorage.get("l/questionType");
    } else {
        var currentItem = $.jStorage.get("currentItem");
        var currentquestiontype = $.jStorage.get("questionType");

        // If the item is critical, don't auto submit
        if(mode == 'critical' || mode == 'mixed' ){
            thisItem = (currentItem.rad || currentItem.voc || currentItem.kan);
            for( var i in crit_list ){
                if( crit_list[i] == thisItem ){
                    return;
                }
            }
        }

    }


    // Random chance to block the item.
    if( currentItem != lastItem  ){
        roll = RandomFn(); //Really be careful here, weird things happen to the random function in my case.
    }
    //console.log("Roll is set to: " + roll + " with type: " + typeof(roll));

    lastItem = currentItem;

    if( mode == 'random'){
        if(roll > randomChance ){
            //console.log("Roll is more than the chance so we won't autocommit.");
            if(mode != 'random') console.log("This should never happen... random != " + mode);
            return;
        }
    }else if( mode == 'mixed' && currentItem.kan ){
        if(roll > randomChanceMixed ){
            //In mixed mode, kanji are randomly blocked but at a lower rate.
            if(mode != 'random') console.log("This should never happen... random != " + mode);
            return;
        }
    }


    var currentresponse = $("#user-response").val();

    var currentitem_response = null;

    // Get possible responses from current item depending on the task (reading or meaning)
    if (currentquestiontype === "meaning") {
        currentitem_response = currentItem.en;
        if (currentItem.syn) {
            currentitem_response = currentitem_response.concat(currentItem.syn);
        }
    } else if (currentquestiontype === "reading") {
        if (currentItem.voc) { // Vocab word
            currentitem_response = currentItem.kana;
        } else if (currentItem.emph === 'kunyomi') { // Kanji: Kun reading
            currentitem_response = currentItem.kun;
        } else if (currentItem.emph === 'onyomi') { // Kanji: On reading 
            currentitem_response = currentItem.on;
        } else {
            console.log("WK Auto Commit: Could not find response");
        }
    }

    for (var i in currentitem_response) {
        if (sanitize(currentresponse) === sanitize(currentitem_response[i]) ) {
            commit();
        }
    }
};

var register_check_input = function () {
    $("#user-response").on("keyup", function (event) {    
        if (mode != 'off') {
            check_input();
        }
    });
};

var addButtons = function () {

    $("<div />", {
        id : "WKAUTOCOMMIT_button",
        title : "Switch to Critical Mode",
    })
        .text("Auto Commit: Always")
        .css({"background-color":"#C55"})
        .css({"opacity":"1"})
        .css({"display":"inline-block"})
        .css({"font-size":"0.8125em"})
        .css({"color":"#FFF"})
        .css({"cursor":"pointer"})
        .css({"padding":"10px"})
        .css({"vertical-align":"bottom"})
        .on("click", toggle)
        .prependTo("footer");
};

var generateList = function (percent){
    crit_list = [];

    $.getJSON('/api/user/'+apiKey+'/critical-items/' + percent, function(json){
        if (json.error && json.error.code === 'user_not_found') {
            localStorage.removeItem('apiKey');
        }
        $(json.requested_information).each(function(i,v){
            try {
                var thing = v.character
                crit_list.push(thing);
            } catch(e) {}
        });
    });
};

var saveMode = function () {
    if( on_lessons_page )
        localStorage.setItem('wkac_lesson_mode',mode);
    else
        localStorage.setItem('wkac_review_mode',mode);
}

var loadMode = function () {
    if( on_lessons_page )
        mode = localStorage.getItem('wkac_lesson_mode');
    else
        mode = localStorage.getItem('wkac_review_mode');
}

//Thank you Wanikani Real Numbers
function retrieveAPIkey() {
    for(var i=0;i<document.getElementsByClassName('span6').length;i++){
        if(document.getElementsByClassName('span6')[i].getAttribute('placeholder')=="Key has not been generated")
            apiKey = document.getElementsByClassName('span6') [i].getAttribute('value');
    }
    alert('WaniKani Real Numbers API key set to: ' + apiKey);
    if (apiKey) {
        localStorage.setItem('apiKey', apiKey);
        localStorage.setItem('WRN_doneReviews', 'true');
        //GM_setValue('apikey', apikey);
        //GM_setValue('doneReviews', true);
    }
}

var init = function () {  
    console.log('WK Auto Commit (a plugin for Wanikani): Initialization started');
    on_lessons_page = detect_lessons_page();
    addButtons();
    register_check_input();

    apiKey = localStorage.getItem('apiKey');
    if (!apiKey) {
        if (window.location.href.indexOf('account') != - 1) {
            retrieveAPIkey();
            apiKey = localStorage.getItem('apiKey');
        } else {
            var okcancel = confirm('WaniKani Auto Commit has no API key entered!\nPress OK to go to your settings page and retrieve your API key!');
            if (okcancel == true) {
                window.location = 'https://www.wanikani.com/account';
            }
        }
    }

    loadMode();
    if(!mode ){
        mode = 'always';
        saveMode();
    }

    switchMode(mode);

    console.log('WK Auto Commit: Initialization ended');
};

$(function(){
    init();
});