您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Calculates the percentage of known kanji for each JLPT level, Joyo grade, Frequency bracket, and various other sources.
当前为
// ==UserScript== // @name Wanikani: Progress Percentages // @namespace http://tampermonkey.net/ // @version 1.0.0 // @description Calculates the percentage of known kanji for each JLPT level, Joyo grade, Frequency bracket, and various other sources. // @author Kumirei // @match https://www.wanikani.com/ // @match https://www.wanikani.com/dashboard // @require https://gf.qytechs.cn/scripts/377613-wanikani-open-framework-jlpt-joyo-and-frequency-filters/code/Wanikani%20Open%20Framework%20JLPT,%20Joyo,%20and%20Frequency%20filters.user.js // @require https://gf.qytechs.cn/scripts/377638-wanikani-open-framework-subject-ids-filter/code/Wanikani%20Open%20Framework%20Subject%20IDs%20filter.user.js // @license MIT; http://opensource.org/licenses/MIT // @grant none // ==/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); // Fetch progress storage var progress = JSON.parse(localStorage.getItem('WKProgressPercentages')); if (progress == null) progress = { last_level: 0, unlearned_ids: {}, 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}; 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 } } } var dialog = new wkof.Settings(config); dialog.open(); } // 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)=>{ var highest_level = progress.last_level; var current_level = wkof.user.level; for (var key in data) { var id = data[key].id; var item_level = data[key].data.level; if (id in progress.unlearned_ids || (item_level > progress.last_level && item_level <= current_level)) { if (item_level > highest_level) highest_level = item_level; 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) { if (level < 1) { progress.other[val[1]].learned++; progress.other[val[1]].total += level; } else progress[val[1]][level].learned++; } }); delete progress.unlearned_ids[id]; } else progress.unlearned_ids[id] = 1; } } progress.last_level = highest_level; localStorage.setItem('WKProgressPercentages', JSON.stringify(progress)); 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; if (key != "other") var percent = (show_cum ? cumulative[0]/cumulative[1] : learned/total); else percent = total; percent = Math.floor(percent*(percent < 0.1 ? 1000 : 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('<style id="progress_percentages">'+ '.progress_percentages {'+ ' margin: 15px 0 15px;'+ ' position: relative;'+ '}'+ '.progress_percentages > div {'+ ' border-radius: 3px;'+ ' background: #434343 !important;'+ ' padding: 5px 0;'+ '}'+ '.stage {'+ ' display: inline-block;'+ ' width: 20%;'+ ' text-align: center;'+ ' color: rgb(240,240,240);'+ '}'+ '.progress_percentages span {'+ ' display: inline;'+ ' font-size: 16px;'+ ' border-radius: 5px;'+ '}'+ '.progress_percentages .level {'+ ' font-weight: bold;'+ '}'+ '.joyo_percentages {'+ ' width: 14.25%;'+ '}'+ '.progress_percentages .hidden {'+ ' display: none;'+ '}'+ '.progress_percentages .btn {'+ ' height: 100%;'+ ' position: absolute;'+ ' box-shadow: none !important;'+ ' padding: 0 5px;'+ ' line-height: 30px;'+ ' width: 20px;'+ ' text-shadow: none;'+ ' color: rgb(240,240,240);'+ ' border: none;'+ '}'+ '.progress_percentages .next.btn {'+ ' right: 0;'+ '}'+ '</style>'); if (is_dark_theme()) $('head').append('<style id="progress_percentages_dark">'+ '.progress_percentages {'+ ' box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.7), 2px 2px 2px rgba(0, 0, 0, 0.7);'+ '}'+ '.progress_percentages > div {'+ ' background: #232629 !important;'+ '}'+ '</style>'); // 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 btn'; next_button.innerHTML = '<i class="link icon-chevron-right"></i>'; next_button.onclick = toggle_percentages; next_button.current = active_set; next_button.next = next; section.appendChild(next_button); var prev_button = document.createElement('div'); prev_button.className = 'prev btn'; prev_button.innerHTML = '<i class="link icon-chevron-left"></i>'; prev_button.onclick = toggle_percentages; prev_button.current = active_set; prev_button.next = prev; section.appendChild(prev_button); var list = document.createElement('div'); 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('<div class="'+key+'_percentages stage '+(key==active_set?"":"hidden")+'" title="'+percentages[key][stage].learned+' of '+percentages[key][stage].total+' learned"><span class="level">'+prefix+label+' </span><span class="percent">'+percentages[key][stage].percent+'%</span></div>'); } } section.appendChild(list); $('.progression').before(section); } // Switches which percentages are showing function toggle_percentages(event) { var button = event.target; if (button.nodeName == "I") button = button.parentElement; var current_set = button.current; var next_set = button.next; $('.'+current_set+'_percentages').toggleClass('hidden'); $('.'+next_set+'_percentages').toggleClass('hidden'); var next_button = $('.progress_percentages .next')[0]; var prev_button = $('.progress_percentages .prev')[0]; var [next, prev] = get_new_sets(next_set); next_button.next = next; next_button.current = next_set; prev_button.next = prev; prev_button.current = next_set; localStorage.setItem('WKProgressPercentagesActiveSet', next_set) } // Returns the next and previous sets function get_new_sets(current_set) { var sets = ["jlpt", "joyo", "freq", "other"]; var current_index = sets.indexOf(current_set); return [sets[(current_index+1)%4], sets[(current_index+3)%4]]; } // Handy little function that rfindley wrote. Checks whether the theme is dark. function is_dark_theme() { // Grab the <html> background color, average the RGB. If less than 50% bright, it's dark theme. return $('body').css('background-color').match(/\((.*)\)/)[1].split(',').slice(0,3).map(str => Number(str)).reduce((a, i) => a+i)/(255*3) < 0.5; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址