// ==UserScript== // @name Wanikani: Progress Percentages // @namespace http://tampermonkey.net/ // @version 1.2.8 // @description Calculates the percentage of known kanji for each JLPT level, Joyo grade, Frequency bracket, and various other sources. // @author Kumirei // @include /^https://(www|preview).wanikani.com/(dashboard)?$/ // @require https://greasyfork.org/scripts/377613-wanikani-open-framework-jlpt-joyo-and-frequency-filters/code/Wanikani%20Open%20Framework%20JLPT,%20Joyo,%20and%20Frequency%20filters.user.js // @license MIT; http://opensource.org/licenses/MIT // @grant none // @downloadURL https://update.greasyfork.org/scripts/377575/Wanikani%3A%20Progress%20Percentages.user.js // @updateURL https://update.greasyfork.org/scripts/377575/Wanikani%3A%20Progress%20Percentages.meta.js // ==/UserScript== ;(function () { // Make sure WKOF is installed var wkof = window.wkof if (!wkof) { var response = confirm( 'Wanikani: JLPT Progress requires WaniKani Open Framework.\n Click "OK" to be forwarded to installation instructions.', ) if (response) window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549' return } else { // Install menu wkof.include('Menu,Settings') wkof.ready('Menu,Settings').then(load_settings).then(install_menu) // Initiate progress variable var progress = { jlpt: { 1: { learned: 0, total: 1232 }, 2: { learned: 0, total: 367 }, 3: { learned: 0, total: 367 }, 4: { learned: 0, total: 166 }, 5: { learned: 0, total: 79 }, }, joyo: { 1: { learned: 0, total: 80 }, 2: { learned: 0, total: 160 }, 3: { learned: 0, total: 200 }, 4: { learned: 0, total: 200 }, 5: { learned: 0, total: 185 }, 6: { learned: 0, total: 181 }, 9: { learned: 0, total: 1130 }, }, freq: { 500: { learned: 0, total: 500 }, 1000: { learned: 0, total: 500 }, 1500: { learned: 0, total: 500 }, 2000: { learned: 0, total: 500 }, 2500: { learned: 0, total: 500 }, }, other: { nhk: { learned: 0, total: 0 }, news: { learned: 0, total: 0 }, aozora: { learned: 0, total: 0 }, twitter: { learned: 0, total: 0 }, wikipedia: { learned: 0, total: 0 }, }, } // Fetch lesson info then process it wkof.include('ItemData') wkof.ready('ItemData').then(update_progress).then(calculate_percentages).then(display_data) } // Loads settings function load_settings() { var defaults = { cumulative: false, threshold: 1, position: 'top' } wkof.Settings.load('progress_percentages', defaults) } // Installs the options button in the menu function install_menu() { var config = { name: 'progress_percentages_settings', submenu: 'Settings', title: 'Progress Percentages', on_click: open_settings, } wkof.Menu.insert_script_link(config) } // Creates the options function open_settings(items) { var config = { script_id: 'progress_percentages', title: 'Progress Percentages', content: { cumulative: { type: 'checkbox', label: 'Cumulative percentages', hover_tip: 'Eg. N3 = N3 + N4 + N4', default: false, }, threshold: { type: 'list', label: 'Learned threshold', hover_tip: 'Items at or above this SRS level will be counted as learned', multi: false, size: 9, default: '1', content: { 1: 'Apprentice 1', 2: 'Apprentice 2', 3: 'Apprentice 3', 4: 'Apprentice 4', 5: 'Guru 1', 6: 'Guru 2', 7: 'Master', 8: 'Enlightened', 9: 'Burned', }, }, position: { type: 'dropdown', label: 'Position', hover_tip: 'Position of the Progress Percentages element on the dashboard', default: 'search', content: { top: 'Top of page', below_srs: 'Below SRS boxes', }, on_change: (setting, value) => { let elem = $('.progress_percentages') elem.toggleClass('span12', value == 'top') if (value == 'top') $('#search-form').before(elem) if (value == 'below_srs') $('.srs-progress').append(elem) }, }, }, on_save: () => { progress = { jlpt: { 1: { learned: 0, total: 1232 }, 2: { learned: 0, total: 367 }, 3: { learned: 0, total: 367 }, 4: { learned: 0, total: 166 }, 5: { learned: 0, total: 79 }, }, joyo: { 1: { learned: 0, total: 80 }, 2: { learned: 0, total: 160 }, 3: { learned: 0, total: 200 }, 4: { learned: 0, total: 200 }, 5: { learned: 0, total: 185 }, 6: { learned: 0, total: 181 }, 9: { learned: 0, total: 1130 }, }, freq: { 500: { learned: 0, total: 500 }, 1000: { learned: 0, total: 500 }, 1500: { learned: 0, total: 500 }, 2000: { learned: 0, total: 500 }, 2500: { learned: 0, total: 500 }, }, other: { nhk: { learned: 0, total: 0 }, news: { learned: 0, total: 0 }, aozora: { learned: 0, total: 0 }, twitter: { learned: 0, total: 0 }, wikipedia: { learned: 0, total: 0 }, }, } update_progress().then(calculate_percentages).then(update_element) }, } var dialog = new wkof.Settings(config) dialog.open() } // Updates element function update_element(percentages) { for (var key in percentages) { for (var level in percentages[key]) { var stage = key == 'jlpt' ? 6 - level : level var elem = $('#' + key + '_' + stage)[0] elem.title = percentages[key][stage].learned + (key != 'other' ? ' of ' + percentages[key][stage].total : '') + ' learned' elem.children[1].innerText = percentages[key][stage].percent + '%' } } } // Retreives lesson data function update_progress() { var resolve, promise = new Promise((res, rej) => { resolve = res }) var config = { wk_items: { options: { assignments: true }, filters: { item_type: 'kan', include_jlpt_data: true, include_joyo_data: true, include_frequency_data: true, }, }, } wkof.ItemData.get_items(config).then((data) => { for (var key in data) { if (data[key].assignments && data[key].assignments.started_at != null) { var keys = [ ['jlpt_level', 'jlpt'], ['joyo_grade', 'joyo'], ['frequency', 'freq'], ['nhk_frequency', 'nhk'], ['news_frequency', 'news'], ['aozora_frequency', 'aozora'], ['twitter_frequency', 'twitter'], ['wikipedia_frequency', 'wikipedia'], ] keys.forEach((val, i) => { var level = data[key][val[0]] if (level && data[key].assignments.srs_stage >= wkof.settings.progress_percentages.threshold) { if (level < 1) { progress.other[val[1]].learned++ progress.other[val[1]].total += level } else progress[val[1]][level].learned++ } }) } } resolve() }) return promise } function calculate_percentages() { var show_cum = wkof.settings.progress_percentages.cumulative var percentages = { jlpt: { 1: {}, 2: {}, 3: {}, 4: {}, 5: {} }, joyo: { 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 9: {} }, freq: { 500: {}, 1000: {}, 1500: {}, 2000: {}, 2500: {} }, other: { nhk: {}, news: {}, aozora: {}, twitter: {}, wikipedia: {} }, } for (var key in percentages) { var cumulative = [0, 0] for (var level in percentages[key]) { var stage = key == 'jlpt' ? 6 - level : level var learned = progress[key][stage].learned var total = progress[key][stage].total cumulative[0] += learned cumulative[1] += total let percent if (key != 'other') percent = show_cum ? cumulative[0] / cumulative[1] : learned / total else percent = total percent = percent < 0.1 ? Math.floor(percent * 1000) / 10 : Math.floor(percent * 100) percentages[key][stage].percent = percent percentages[key][stage].learned = show_cum ? cumulative[0] : learned percentages[key][stage].total = show_cum ? cumulative[1] : total } } return percentages } function display_data(percentages) { // Add css $('head').append(``) if (is_dark_theme()) { $('head').append(``) } // Add elements var section = document.createElement('section') section.className = 'progress_percentages' var active_set = localStorage.getItem('WKProgressPercentagesActiveSet') || 'jlpt' var [next, prev] = get_new_sets(active_set) var next_button = document.createElement('div') next_button.className = 'next PPbtn' next_button.innerHTML = '' next_button.onclick = toggle_percentages next_button.current = active_set next_button.next = next var prev_button = document.createElement('div') prev_button.className = 'prev PPbtn' prev_button.innerHTML = '' prev_button.onclick = toggle_percentages prev_button.current = active_set prev_button.next = prev var list = document.createElement('div') list.className = 'PPprogress' for (var key in percentages) { for (var level in percentages[key]) { var stage = key == 'jlpt' ? 6 - level : level var prefix = key == 'jlpt' ? 'N' : key == 'joyo' ? 'G' : key == 'freq' ? 'F' : '' var label = key == 'other' ? stage == 'nhk' ? 'NHK' : stage.charAt(0).toUpperCase() + stage.slice(1) : key == 'freq' ? stage / 500 : stage $(list).append( '