您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
See your progress charted over time on the WaniKani dashboard page! Progress is broken down by SRS stage, and you can hover for detail.
// ==UserScript== // @name WaniKani Progress Chart // @version 0.1.1 // @description See your progress charted over time on the WaniKani dashboard page! Progress is broken down by SRS stage, and you can hover for detail. // @require https://cdn.rawgit.com/curious-attempt-bunny/wanikani-user-script-helper/4374eae6a4a284c3c3da9d50caa83b8e1a1a6e5d/loader.js // @require https://cdn.jsdelivr.net/npm/[email protected]/d3.js // @require https://cdn.jsdelivr.net/gh/novus/[email protected]/build/nv.d3.js // @author hitechbunny // @include https://www.wanikani.com/ // @include https://www.wanikani.com/dashboard // @include https://www.wanikani.com/review // @namespace https://greasyfork.org/users/149329 // @run-at document-end // @grant none // ==/UserScript== (function() { 'use strict'; // Hook into App Store try { $('.app-store-menu-item').remove(); $('<li class="app-store-menu-item"><a href="https://community.wanikani.com/t/there-are-so-many-user-scripts-now-that-discovering-them-is-hard/20709">App Store</a></li>').insertBefore($('.navbar .dropdown-menu .nav-header:contains("Account")')); window.appStoreRegistry = window.appStoreRegistry || {}; window.appStoreRegistry[GM_info.script.uuid] = GM_info; localStorage.appStoreRegistry = JSON.stringify(appStoreRegistry); } catch (e) {} var head = document.getElementsByTagName('head')[0]; if (head) { var link = document.createElement('link'); link.type = 'text/css'; link.href = 'https://cdn.rawgit.com/novus/nvd3/v1.8.1/build/nv.d3.css'; link.rel = 'stylesheet'; head.appendChild(link); } $('.dashboard .container .row:first').prepend('<div id="progres-timeline-chart"><svg style="height:300px; width:100%;"></svg></div>'); window.WKHelper.init(GM_info, function() { function update() { d3.csv('https://wanikanitools-golang.curiousattemptbunny.com/srs/status/history.csv?api_key='+window.WKHelper.api_key_v2, function(raw) { var keys = ["Apprentice1", "Apprentice2", "Apprentice3", "Apprentice4", "Guru1", "Guru2", "Master", "Enlightened", "Burned"].reverse(); var data = []; var nameToSeries = {}; var rowNumber = 1; if (raw.length > 0) { var padRow = JSON.parse(JSON.stringify(raw[raw.length-1])); padRow.EpochSeconds = ""+(parseInt(padRow.EpochSeconds)+(60*60*3)); raw.push(padRow); } raw.forEach(function(row) { keys.forEach(function(name) { if (name == 'UTCDateTime' || name == 'EpochSeconds' || name == 'UserLevel' || name == 'Total' || name == 'LeechTotal') { return; } if (name.indexOf("Leech") != -1) { return; } if (!nameToSeries[name]) { nameToSeries[name] = {key: name.replace("1", " I").replace("2", " II").replace("3", " III").replace("4", " IV"), values: []}; data.push(nameToSeries[name]); } nameToSeries[name].values.push([parseInt(row.EpochSeconds)*1000, parseInt(row[name])]); // nameToSeries[name].values.push([rowNumber, parseInt(row[name])]); }); rowNumber += 1; }); nv.addGraph(function() { var chart = nv.models.stackedAreaChart() .margin({right: 100}) .x(function(d) { return d[0]; }) //We can modify the data accessor functions... .y(function(d) { return d[1]; }) //...in case your data is formatted differently. .useInteractiveGuideline(true) //Tooltips which show all data points. Very nice! .rightAlignYAxis(true) //Let's move the y-axis to the right side. .showControls(true) //Allow user to choose 'Stacked', 'Stream', 'Expanded' mode. .clipEdge(true) .interpolate("step") .interactive(true) .showLegend(false) .pointActive(function(d) { return false; }) .controlOptions(["Stacked","Expanded"]) .controlLabels({"stacked":"Stacked","expanded":"Proportions"}) .color(['#dd0093','#dd0093','#dd0093','#dd0093','#882d9e','#882d9e','#294ddb', '#0093dd', '#434343'].reverse()) ; //Format x-axis labels with custom function. chart.xAxis .tickFormat(function(d) { return d3.time.format('%x')(new Date(d)); }); chart.yAxis .tickFormat(d3.format(',.0f')); d3.select('#progres-timeline-chart svg') .datum(data) .call(chart); nv.utils.windowResize(chart.update); return chart; }); }); } update(); }); })();