// ==UserScript==
// @name WaniKani Lesson Cap
// @namespace https://github.com/valeth
// @version 0.6.4
// @description Limits the amount of lessons you can do with your current review queue.
// @author valeth
// @match https://www.wanikani.com/dashboard
// @match https://www.wanikani.com/lesson
// @match https://www.wanikani.com/lesson/session
// @grant none
// @run-at document-end
// @license MIT
// ==/UserScript==
/* jshint ignore:start */
const debugging = false;
// Generated by CoffeeScript 2.0.2
(function() {
// =======[ WKOF Guard ]=======
// coffeelint: disable=max_line_length
var btn_continue, calculate_score, confirmed, continue_button, default_settings, get_items, get_or_wait, install_menu, install_settings, log, render_all, render_available, render_results, round2, settings, settings_dialog, srs_levels, start_button, titleize, update;
if (window.wkof == null) {
confirmed = confirm('WaniKani Lesson Cap requires the WaniKani Open Framework.\nDo you want to be forwarded to the installation instructions?');
if (confirmed) {
window.location.href = "https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549";
}
return;
}
// coffeelint: enable=max_line_length
// =======[ Globals ]=======
btn_continue = void 0;
settings_dialog = void 0;
default_settings = {
max_score: 100
};
srs_levels = [
{
stage: 1,
rating: 6,
ident: 'apprentice1'
},
{
stage: 2,
rating: 3,
ident: 'apprentice2'
},
{
stage: 3,
rating: 1.04,
ident: 'apprentice3'
},
{
stage: 4,
rating: 0.51,
ident: 'apprentice4'
},
{
stage: 5,
rating: 0.14,
ident: 'guru1'
},
{
stage: 6,
rating: 0.07,
ident: 'guru2'
},
{
stage: 7,
rating: 0.03,
ident: 'master'
},
{
stage: 8,
rating: 0.01,
ident: 'enlightened'
}
];
// =======[ Utility functions ]=======
log = {
info: function(message) {
return console.log("[WKLC] " + message);
},
error: function(message) {
return console.error("[WKLC] " + message);
},
debug: function(message) {
if (debugging) {
return console.log("[WKLC] " + message);
}
},
inspect: function(thing) {
if (debugging) {
return console.debug(thing);
}
}
};
// Format a given string into "titleized" format.
// Example:
// someIdentifier1 -> Some Identifier 1
titleize = function(string) {
var char, i, len, ref, tmp;
tmp = string[0].toUpperCase();
ref = string.slice(1);
for (i = 0, len = ref.length; i < len; i++) {
char = ref[i];
if (char === char.toUpperCase()) {
tmp += ` ${char}`;
} else {
tmp += char;
}
}
return tmp;
};
round2 = function(num) {
return Math.round(num * 100) / 100;
};
get_or_wait = function(key, callback) {
var value;
value = wkof.get_state(key);
if (value != null) {
return callback(value);
}
return wkof.wait_state(key, "*", function(value, _) {
return callback(value);
});
};
// =======[ Rendering ]=======
start_button = function(action) {
var btn_start, lesson_queue_count;
btn_start = $("#start-session > a");
if (btn_start[0] == null) {
return;
}
lesson_queue_count = $("#lesson-queue-count");
switch (action) {
case "disable":
log.info("Disabling lesson start button...");
btn_start.addClass("wklc-force-hidden");
return lesson_queue_count.addClass("wklc-lesson-count");
case "enable":
log.info("Enabling lesson start button...");
btn_start.removeClass("wklc-force-hidden");
return lesson_queue_count.removeClass("wklc-lesson-count");
}
};
continue_button = function(action) {
if (btn_continue == null) {
btn_continue = $("#lesson-ready-continue");
}
if (btn_continue[0] == null) {
return;
}
switch (action) {
case "disable":
log.info("Disabling lesson continue button...");
return btn_continue.remove();
case "enable":
log.info("Enabling lesson continue button...");
return $("#screen-lesson-ready .btn-set").append(btn_continue);
}
};
render_all = function() {
return get_items(function(score, stats) {
var batch_size, batches, max_score, remaining_score, score_per_item;
render_results(score, stats);
batch_size = $.jStorage.get("l/batchSize");
max_score = settings("max_score");
remaining_score = max_score - score;
score_per_item = batch_size * (srs_levels[0].rating / 2);
batches = Math.floor(remaining_score / score_per_item);
if (batches >= 1) {
start_button("enable");
}
if (batches >= 2) {
continue_button("enable");
}
return render_available(batch_size, batches);
});
};
render_results = function(score, stats) {
var max_score, wklc, wklc_items;
if ($("#lessons-summary")[0] == null) {
return;
}
log.debug("Rendering results...");
wklc = $(".wklc");
if (wklc[0] != null) {
wklc.remove();
}
max_score = settings("max_score");
wklc_items = stats.reduce(function(acc, stat, index) {
return acc += `<li class='wklc-item wklc-${srs_levels[index].ident}'\n title='${titleize(srs_levels[index].ident)}'>\n <span>${round2(stat.count)}</span>\n <span>(${round2(stat.score)})</span>\n</li>`;
}, "");
return $("#lessons-summary").prepend($(`<div class="wklc">\n <ul class="wklc-items">${wklc_items}</ul>\n <div class='wklc-right'>\n <div class='wklc-item wklc-score'>\n <span>Score:</span>\n <span>${round2(score)}</span> / <span>${max_score}</span>\n </div>\n <button class='wklc-item wklc-btn-settings'\n title='Settings'>⚙</button>\n </div>\n</div>`));
};
render_available = function(batch_size, batches) {
var allowed_lessons, lessons_queue_count, title;
if ($("#lessons-summary")[0] == null) {
return;
}
allowed_lessons = $(".wklc-allowed-lessons");
if (allowed_lessons[0] != null) {
allowed_lessons.remove();
}
lessons_queue_count = +$("#lesson-queue-count").text();
if (lessons_queue_count === 0 && !debugging) {
return;
}
title = `This is the amount of batches of ${batch_size}\nlessons you can do without exceeding the max score.`;
allowed_lessons = $(`<span class='wklc-allowed-lessons' title='${title}'>\n ${batches + ' Available'}\n</span>`);
if (batches < 1) {
allowed_lessons.addClass("disabled");
allowed_lessons.attr("title", "Lessons button disabled because you can do\nless than one session before exceeding max score.");
}
return $("#start-session").append(allowed_lessons);
};
// ======[ API Requests and Calculations ]=======
get_items = function(callback) {
return wkof.ItemData.get_items({
wk_items: {
options: {
assignments: true
},
filters: {
srs: {
value: ["lock", "burn"],
invert: true
},
level: "1 to +0" // from first level to current
}
}
}).then(function(items) {
var score, stats;
[score, stats] = calculate_score(items);
return callback(score, stats);
});
};
calculate_score = function(items) {
var stats, total_score;
stats = srs_levels.map(function() {
return {
count: 0,
score: 0.0
};
});
items.forEach(function(cur) {
var stage;
stage = cur.assignments.srs_stage - 1;
if (stage < 0 || stage > 7) {
return;
}
stats[stage].count += 1;
return stats[stage].score = (stats[stage].count * srs_levels[stage].rating) / 2;
});
wkof.set_state("wklc.stats", stats);
total_score = stats.reduce(function(acc, cur) {
return acc += round2(cur.score);
}, 0);
wkof.set_state("wklc.current_score", total_score);
return [total_score, stats];
};
// =======[ Setup ]=======
update = function() {
// need to disable buttons on every update again
start_button("disable");
continue_button("disable");
return render_all();
};
install_menu = function() {
var open_settings;
open_settings = function() {
if (settings_dialog != null) {
return settings_dialog.open();
}
};
wkof.Menu.insert_script_link({
script_id: "wklc",
submenu: "Settings",
title: "WaniKani Lesson Cap",
on_click: open_settings
});
return $(document).on("click", ".wklc-btn-settings", open_settings);
};
settings = function(key) {
return wkof.settings.wklc[key];
};
install_settings = function() {
var save_settings;
save_settings = function() {
wkof.Settings.save("wklc");
update();
return log.info("Settings saved");
};
wkof.Settings.load("wklc", default_settings);
return settings_dialog = new wkof.Settings({
script_id: "wklc",
title: "WaniKani Lesson Cap",
on_save: save_settings,
settings: {
pg_general: {
type: "page",
label: "General",
content: {
max_score: {
type: "number",
label: "Max score"
}
}
}
}
});
};
$(document).on("click", "#batch-items .active-quiz", update);
$(document).on("click", "#quiz-ready-continue", update);
$(document).ready(function() {
var modules;
modules = "Apiv2, ItemData, Menu, Settings";
// coffeelint: disable=max_line_length
wkof.load_css("https://raw.githubusercontent.com/valeth/wanikani-lesson-cap/wkof/compiled/style.css");
// coffeelint: enable=max_line_length
wkof.include(modules);
wkof.ready("Menu").then(install_menu);
wkof.ready("Settings").then(install_settings);
return wkof.ready(modules).then(update);
});
}).call(this);
/* jshint ignore:end */