您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays your level for each SRS stage.
- // ==UserScript==
- // @name Wanikani: Levels by SRS
- // @namespace http://tampermonkey.net/
- // @version 1.1.7
- // @description Displays your level for each SRS stage.
- // @author Kumirei
- // @match https://www.wanikani.com/dashboard
- // @match https://www.wanikani.com
- // @include *preview.wanikani.com*
- // @grant none
- // ==/UserScript==
- /*jshint esversion: 8 */
- ;(function () {
- //check that the Wanikani Framework is installed
- var script_name = 'Levels By SRS'
- 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
- }
- //if it's installed then do the stuffs
- else {
- wkof.include('Menu,Settings,ItemData')
- wkof.ready('Menu,Settings,ItemData').then(load_settings).then(install_menu).then(add_css).then(fetch_and_update)
- }
- // Fetches items and updates display
- function fetch_and_update() {
- fetch_items().then(process_items).then(update_display)
- }
- // Fetches the relevant items
- function fetch_items() {
- var [promise, resolve] = new_promise()
- var config = {
- wk_items: {
- options: { assignments: true },
- filters: { level: '1..+0' },
- },
- }
- wkof.ItemData.get_items(config).then(resolve)
- return promise
- }
- // Retreives the levels by srs
- function process_items(data) {
- // Sort by level
- var levels = {}
- let item
- for (var i = 0; i < data.length; i++) {
- item = data[i]
- var level = item.data.level
- if (!levels[level]) levels[level] = []
- levels[level].push(item)
- }
- // Go through items level by level
- var srs_levels = {
- Ini: [0, 0, 0],
- App: [0, 0, 0],
- Gur: [0, 0, 0],
- Mas: [0, 0, 0],
- Enl: [0, 0, 0],
- Bur: [0, 0, 0],
- }
- for (i = 1; i < wkof.user.level + 1; i++) {
- // Get counts for level
- var by_srs = { Ini: 0, App: 0, Gur: 0, Mas: 0, Enl: 0, Bur: 0, total: 0 }
- for (var j = 0; j < levels[i].length; j++) {
- item = levels[i][j]
- if (item.assignments)
- by_srs[
- ['Ini', 'App', 'App', 'App', 'App', 'Gur', 'Gur', 'Mas', 'Enl', 'Bur'][
- item.assignments.srs_stage
- ]
- ]++
- else by_srs.Ini++
- by_srs.total++
- }
- // Check if srs_level should be increased
- var types = ['Ini', 'App', 'Gur', 'Mas', 'Enl', 'Bur']
- var cumulative = 0
- for (j = 0; j < types.length; j++) {
- var count = by_srs[types[j]]
- if (
- 1 - cumulative / by_srs.total >= wkof.settings.levels_by_srs.threshold / 100 &&
- i == srs_levels[types[j]][0] + 1
- ) {
- srs_levels[types[j]][0]++
- } else if (
- 1 - cumulative / by_srs.total <= wkof.settings.levels_by_srs.threshold / 100 &&
- i == srs_levels[types[j]][0] + 1
- ) {
- srs_levels[types[j]][1] = 1 - cumulative / by_srs.total
- srs_levels[types[j]][2] = by_srs.total
- }
- cumulative += count
- }
- }
- return srs_levels
- }
- // Updates the display element
- function update_display(srs_levels) {
- var types = ['App', 'Gur', 'Mas', 'Enl', 'Bur']
- // If the element doesn't already exist, create it
- var display = $('#levels_by_srs')
- if (!display.length) {
- display = $('<div id="levels_by_srs"' + (is_dark_theme() ? ' class="dark_theme"' : '') + '></div>')
- for (var i = 0; i < types.length; i++)
- display.append(
- '<div class="' +
- types[i] +
- '"><span class="level_label">Level: </span><span class="value"></span></div>',
- )
- $('.srs-progress').append(display)
- }
- // Update
- for (let i = 0; i < types.length; i++) {
- var elem = $(display).find('.' + types[i] + ' span.value')[0]
- elem.innerText = srs_levels[types[i]][0]
- elem.parentElement.setAttribute(
- 'title',
- Math.floor(srs_levels[types[i]][1] * 100) +
- '% to level ' +
- (srs_levels[types[i]][0] + 1) +
- ' (' +
- Math.round(srs_levels[types[i]][1] * srs_levels[types[i]][2]) +
- ' of ' +
- srs_levels[types[i]][2] +
- ')',
- )
- }
- }
- // Load stored settings or set defaults
- function load_settings() {
- var defaults = { threshold: 90 }
- return wkof.Settings.load('levels_by_srs', defaults)
- }
- // Installs the options button in the menu
- function install_menu() {
- var config = {
- name: 'levels_by_srs',
- submenu: 'Settings',
- title: 'Levels By SRS',
- on_click: open_settings,
- }
- wkof.Menu.insert_script_link(config)
- }
- // Create the options
- function open_settings(items) {
- var config = {
- script_id: 'levels_by_srs',
- title: 'Levels By SRS',
- on_save: fetch_and_update,
- content: {
- threshold: {
- type: 'number',
- label: 'Threshold',
- hover_tip: 'Percentage to consider level done',
- default: 90,
- },
- },
- }
- var dialog = new wkof.Settings(config)
- dialog.open()
- }
- // Adds the script's CSS to the page
- function add_css() {
- $('head').append(`<style id="levels_by_srs_CSS">
- #levels_by_srs {
- background: #434343;
- border-radius: 0 0 3px 3px;
- height: 30px;
- line-height: 30px;
- color: rgb(240, 240, 240);
- display: flex;
- justify-content: space-around;
- }
- #levels_by_srs > div {
- display: flex;
- flex: 1;
- justify-content: center;
- }
- #levels_by_srs .level_label {
- font-size: 16px;
- margin-right: 5px;
- }
- #levels_by_srs .value {
- font-size: 16px;
- font-weight: normal;
- }
- #levels_by_srs.dark_theme {
- background: #232629;
- }
- #levels_by_srs.dark_theme > div:not(:last-child) {
- border-right: 1px solid #31363b;
- margin-right: 5px;
- }
- #levels_by_srs.dark_theme > div:last-child {
- border-right: 1px solid transparent;
- }
- .srs-progress > ul > li {
- border-radius: 0 !important;
- }
- </style>`)
- }
- // Returns a promise and a resolve function
- function new_promise() {
- var resolve,
- promise = new Promise((res, rej) => {
- resolve = res
- })
- return [promise, resolve]
- }
- // 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
- )
- }
- })()