您需要先安装一个扩展,例如 篡改猴、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.2.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 // @include *preview.wanikani.com* // @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 // @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); // 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: 'search', } 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: { search: 'Left of search', below_srs: 'Below SRS boxes', }, on_change: (setting, value)=>{ let elem = $('.progress_percentages'); if (value=="search") $('#search-form').before(elem); if (value=="below_srs") $('.srs-progress').after(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; if (key != "other") var 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(`<style id="progress_percentages"> .progress_percentages { display: flex; height: 28px; background: #434343; color: rgb(240, 240, 240); line-height: 28px; margin-bottom: 0; border-radius: 5px; text-align: center; grid-row: 1; grid-column: 1 / span 2; margin-top: 15px; } #search-form { grid-row: 1; } .progress_percentages .PPprogress { display: flex; width: 100%; justify-content: space-around; } .progress_percentages .PPbtn { width: 20px; height: auto; color: rgb(240,240,240); padding: 0 5px; cursor: pointer; } .progress_percentages .level { font-weight: bold; } .progress_percentages span { font-size: 16px; } #search > div > div > div { display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 20px 20px; } #search-form { grid-column: 3; width: 100% !important; } </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 PPbtn'; next_button.innerHTML = '<i class="link icon-chevron-right"></i>'; 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 = '<i class="link icon-chevron-left"></i>'; 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('<div class="'+key+'_percentages stage '+(key==active_set?"":"hidden")+'" id="'+key+'_'+stage+'" title="'+percentages[key][stage].learned+(key!="other"?' of '+percentages[key][stage].total:"")+' learned"><span class="level">'+prefix+label+' </span><span class="percent">'+percentages[key][stage].percent+'%</span></div>'); } } section.appendChild(prev_button); section.appendChild(list); section.appendChild(next_button); if (wkof.settings.progress_percentages.position == "search") $('#search-form').before(section); else $(".srs-progress").after(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或关注我们的公众号极客氢云获取最新地址