// ==UserScript==
// @name Wanikani Burn Manager
// @namespace rfindley
// @description Mass Resurrect/Retire of Burn items on WaniKani
// @version 2.0.5
// @include https://www.wanikani.com/*
// @exclude https://www.wanikani.com/lesson*
// @exclude https://www.wanikani.com/review*
// @copyright 2016+, Robin Findley
// @license MIT; http://opensource.org/licenses/MIT
// @run-at document-end
// @grant none
// @downloadURL https://update.greasyfork.icu/scripts/18822/Wanikani%20Burn%20Manager.user.js
// @updateURL https://update.greasyfork.icu/scripts/18822/Wanikani%20Burn%20Manager.meta.js
// ==/UserScript==
window.burnmgr = {};
(function(gobj) {
/* globals $, wkof */
/* eslint no-multi-spaces: "off" */
//===================================================================
// Initialization of the Wanikani Open Framework.
//-------------------------------------------------------------------
var script_name = 'Burn Manager';
if (!window.wkof) {
if (confirm(script_name+' requires Wanikani Open Framework.\nDo you want to be forwarded to the installation instructions?')) {
window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549';
}
return;
}
wkof.include('ItemData,Menu');
wkof.ready('ItemData,Menu').then(startup);
var mgr_added = false, busy = false, items, items_by_id;
function startup() {
wkof.Menu.insert_script_link({
name: 'burnmgr',
submenu: 'Open',
title: 'Burn Manager',
on_click: open_burnmgr
});
}
function open_burnmgr() {
// Add the manager if not already.
if (!mgr_added) add_mgr();
$('#burn_mgr').slideDown();
$('html, body').animate({scrollTop:0},800);
}
var srslvls = ['Apprentice 1','Apprentice 2','Apprentice 3','Apprentice 4','Guru 1','Guru 2','Master','Enlightened','Burned'];
//-------------------------------------------------------------------
// Display the Burn Manager object.
//-------------------------------------------------------------------
function add_mgr() {
var html =
'
';
var readings, reading_str, important_reading, meanings, meaning_str, synonyms, synonym_str;
switch (itype) {
case 'rad':
meanings = item.data.meanings.filter(primary);
meaning_str = meanings.map(meaning).join(', ');
str += '
Item: ';
if (item.data.characters !== null) {
str += item.data.characters+'';
} else {
str += '

';
}
str += 'Meaning: '+toTitleCase(meaning_str)+'
';
if (item.study_materials && item.study_materials.meaning_synonyms.length > 0) {
str += 'Synonyms: '+toTitleCase(item.study_materials.meaning_synonyms.join(', '))+'
';
}
break;
case 'kan':
readings = item.data.readings.filter(primary);
important_reading = readings[0].type;
reading_str = readings.map(reading).join(', ');
meanings = item.data.meanings.filter(primary);
meaning_str = meanings.map(meaning).join(', ');
str += '
Item: '+item.data.characters+'';
str += toTitleCase(important_reading)+':
'+reading_str+'';
str += 'Meaning: '+toTitleCase(meaning_str)+'
';
if (item.study_materials && item.study_materials.meaning_synonyms.length > 0) {
str += 'Synonyms: '+toTitleCase(item.study_materials.meaning_synonyms.join(', '))+'
';
}
break;
case 'voc':
readings = item.data.readings.filter(primary);
reading_str = readings.map(reading).join(', ');
meanings = item.data.meanings.filter(primary);
meaning_str = meanings.map(meaning).join(', ');
str += '
Item: '+item.data.characters+'';
str += 'Reading:
'+reading_str+'';
str += 'Meaning: '+toTitleCase(meaning_str)+'
';
if (item.study_materials && item.study_materials.meaning_synonyms.length > 0) {
str += 'Synonyms: '+toTitleCase(item.study_materials.meaning_synonyms.join(', '))+'
';
}
break;
}
str += 'Level: '+item.data.level+'
';
str += 'SRS Level: '+srslvls[item.assignments.srs_stage-1]+'
';
str += 'Currently: '+status+'
';
str += '
';
hinfo.html(str);
hinfo.css('left', target.offset().left - target.position().left);
hinfo.css('top', target.offset().top + target.outerHeight() + 3);
hinfo.removeClass('hidden');
break;
//-----------------------------
case 'mouseleave':
hinfo.addClass('hidden');
break;
}
}
//-------------------------------------------------------------------
// Filters and maps
//-------------------------------------------------------------------
function primary(info) {return info.primary;}
function meaning(info) {return info.meaning;}
function reading(info) {return info.reading;}
//-------------------------------------------------------------------
// Make first letter of each word upper-case.
//-------------------------------------------------------------------
function toTitleCase(str) {
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
//-------------------------------------------------------------------
// Read the user's "initial state" setting.
//-------------------------------------------------------------------
function read_initial_state() {
return Number($('#burn_mgr_initial input:checked').val());
}
//-------------------------------------------------------------------
// Run when user clicks 'Preview' button
//-------------------------------------------------------------------
function on_preview(e, refresh) {
if (refresh !== true) e.preventDefault();
if (busy) return;
var preview_is_open = $('#burn_mgr .preview').is(':visible');
if (preview_is_open) {
$('#burn_mgr .preview').html('').slideUp();
busy = true;
fetch_items(true /* force_update */).then(populate_data.bind(null, refresh));
} else {
busy = true;
fetch_items(true /* force_update */).then(populate_data.bind(null, refresh));
}
}
//-------------------------------------------------------------------
// Fetch the requested items
//-------------------------------------------------------------------
function fetch_items(force_update) {
var levels = $('#burn_mgr_levels').val();
if (levels === '') levels = '*';
var item_type = [];
if ($('#burn_mgr_rad').attr('checked') === 'checked') item_type.push('rad');
if ($('#burn_mgr_kan').attr('checked') === 'checked') item_type.push('kan');
if ($('#burn_mgr_voc').attr('checked') === 'checked') item_type.push('voc');
$('#burn_mgr .status .message').html('Fetching data...');
$('#burn_mgr .status').slideDown();
return wkof.ItemData.get_items({
wk_items: {
options: {subjects: true, assignments: true, study_materials: true},
filters: {
have_burned: true,
level: levels,
item_type: item_type
}
}
}, {force_update: force_update});
}
//-------------------------------------------------------------------
// Populate the item data on-screen.
//-------------------------------------------------------------------
function populate_data(refresh, data) {
// Hide the "Loading" message.
busy = false;
$('#burn_mgr .status').slideUp();
items = data;
items_by_id = wkof.ItemData.get_index(items, 'subject_id');
window.items = items;
var html = '';
var itypes = ['radical', 'kanji', 'vocabulary'];
var state = read_initial_state();
if (refresh === true) state = 0;
var get_initial = [
/* 0 */ function(item) {return can_retire(item);}, // Show current item state.
/* 1 */ function(item) {return true;}, // Mark all items for resurrection.
/* 2 */ function(item) {return false;}, // Mark all items for retirement.
][state];
var items_by_level = wkof.ItemData.get_index(items, 'level');
var item_html, items_by_type, level_items, itype3, list;
for (var level = 1; level <= wkof.user.level; level++) {
level_items = items_by_level[level];
if (!level_items) continue;
items_by_type = wkof.ItemData.get_index(level_items, 'item_type');
item_html = '';
$.each(itypes, populate_by_type);
html +=
''+
'