WaniKani Dashboard Leech List Unburnable Edit

Shows top leeches on dashboard (replaces critical items) and all leeches on a dedicated page (replaces critical items)

当前为 2019-09-18 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name          WaniKani Dashboard Leech List Unburnable Edit
// @namespace     https://www.wanikani.com
// @description   Shows top leeches on dashboard (replaces critical items) and all leeches on a dedicated page (replaces critical items)
// @author        ukebox (edited by Pep95)
// @version       1.2.5
// @require       https://code.jquery.com/jquery-3.3.1.min.js#sha256=FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=
// @include       https://www.wanikani.com/dashboard
// @include       https://www.wanikani.com/
// @include       https://www.wanikani.com/critical-items
// @grant         none
// @run-at        document-end
// ==/UserScript==

/*
jshint esversion: 6
*/

(function() {
    'use strict';

    let sumval;
    let dom = {};
    dom.$ = jQuery.noConflict(true);

    if (!window.wkof) {
        let response = confirm('WaniKani Dashboard Leech List script 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;
    }

    const leechThreshold = 1;
    const config = {
        wk_items: {
            options: {
                review_statistics: true,
                assignments: true
            },
            filter: {
                level: '1..+0',
                srs: '1..8'
            }
        }
    };

    window.wkof.include('ItemData');
    window.wkof.ready('ItemData').then(getItems).then(determineLeeches).then(updatePage);

    function getItems() {
        return window.wkof.ItemData.get_items(config);
    }

    function determineLeeches(items) {
        return items.filter(item => isLeech(item));
    }

    function summer( item ) {
        var sum = 0;
        console.log( "sum1: "+sum+" "+item);
        for( var impcnt in item ) {
            console.log( "sum1: "+sum+" what is item.impcnt: "+item.impcnt );
            if( item.hasOwnProperty( impcnt ) && item.impcnt == 1) {
                sum += parseFloat( item[impcnt] );
                console.log( "sum1: "+sum+" "+item );
            }
        }
        return sum;
    }

    function isLeech(item) {

        if (item.review_statistics === undefined) {
            return false;
        }

        let reviewStats = item.review_statistics;
        let meaningScore = computeLeechScore(reviewStats.meaning_incorrect, reviewStats.meaning_current_streak);
        let readingScore = computeLeechScore(reviewStats.reading_incorrect, reviewStats.reading_current_streak);

        item.leech_score = Math.max(meaningScore, readingScore);

        if (meaningScore < readingScore) {
            item.highestincorrect = reviewStats.reading_incorrect;
            item.highestincorrectstreak = reviewStats.reading_current_streak;
        } else {
            item.highestincorrect = reviewStats.meaning_incorrect;
            item.highestincorrectstreak = reviewStats.meaning_current_streak;
        }

        item.startleech = 9 - (item.assignments.srs_stage - item.highestincorrectstreak);

        switch(item.startleech) {
            case 8:
                if (item.highestincorrect>18) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            case 7:
                if (item.highestincorrect>14) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            case 6:
                if (item.highestincorrect>11) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            case 5:
                if (item.highestincorrect>7) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            case 4:
                if (item.highestincorrect>5) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            case 3:
                if (item.highestincorrect>2) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            case 2:
                if (item.highestincorrect>0) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            case 1:
                if (item.highestincorrect>0) {
                    item.impossible = "不可能"
                    item.impcnt = 1
                } else {
                    item.impossible = " "
                    item.impcnt = 0
                }
                break;
            default:
                item.impossible = " "
                item.impcnt = 0
        }

        //var summed = summer( item );
        //console.log( "sum: "+summed );

        return meaningScore >= leechThreshold || readingScore >= leechThreshold;
    }

    function computeLeechScore(incorrect, currentStreak) {
        return incorrect / Math.pow((currentStreak || 0.5), 1.5);
    }


    function updatePage(items) {

        let is_dashboard = window.location.pathname !== "/critical-items";
        let totalleeches = items.length;

        if (is_dashboard) {
            items = items.sort((a, b) => (b.highestincorrect - a.highestincorrect)||(a.highestincorrectstreak - b.highestincorrectstreak)).slice(0,10);
        } else {
            items = items.sort((a, b) => (b.highestincorrect - a.highestincorrect)||(a.highestincorrectstreak - b.highestincorrectstreak));
        }

        console.log(items);

        makeLeechList(items, is_dashboard, totalleeches);
    }

    function round(number, decimals)
    {
        return +(Math.round(number + "e+" + decimals) + "e-" + decimals);
    }

    function makeLeechList(items, for_dashboard, totalleeches) {
        let rows = "";
        let sumval = 0;
        //DateTim = "";
        //writer = "";

        //temp = "C:\Leeches " + LocalDateTime.now() + ".txt";

        //set fso = CreateObject("Scripting.FileSystemObject");
        //set s   = fso.CreateTextFile(temp, True);

        items.forEach(item => {
            let type = item.assignments.subject_type;
            //use slug by default (for kanji and vocab)
            let representation = item.data.slug;

            //The slug of a radical just has its name, we want the actual symbol.
            if (type === 'radical') {
                if (item.data.characters) {
                    //use characters for radicals when possible
                    representation = item.data.characters;
                } else if (item.data.character_images) {
                    //use SVG image for scalability
                    let image_data = item.data.character_images.find(x => x.content_type === "image/svg+xml" && x.metadata.inline_styles);
                    if (image_data) {
                        representation = `<img style="height: 1em; width: 1em; filter: invert(100%);" src="${image_data.url}" />`;
                    }
                }
            }

            rows+=`<tr class="${type}"><td><a href="${item.data.document_url}"><span lang="ja">${representation}</span><span class="pull-right"><table style="width:150px"><td width="40%" align="right"> ${item.impossible} </td><td width="30%" align="right">${item.highestincorrect}/${item.highestincorrectstreak}</td><td width="30%" align="right">${round(item.leech_score, 2)}</td></table> </span></a></td></tr>`;

            if (item.impcnt == 1) {
                sumval = sumval + 1;
            }

            //s.writeline(representation);

        });

        //s.Close();

        let sectionContent = `<h3 class="small-caps">${for_dashboard ? 'Top ' : ''}Leeches${for_dashboard ? ' (' + totalleeches + ')' : ''}</h3>
                              <table>
                                <tbody style="display: table-row-group;">
                                  ${rows}
                                </tbody>
                              </table>
                              <div class="see-more">
                                <a class="small-caps" ${for_dashboard ? 'href="critical-items"' : ''}>${for_dashboard ? 'See More Leeches...' : items.length + ' leeches total (' + sumval + ' burn-only leeches)'}</a>
                              </div>`;
        dom.$('.low-percentage').html(sectionContent);
    }

})();