WaniKani Level Duration

This will display the number of days since your last level-up. Two display options are offered. By RhosVeedcy.

安装此脚本?
作者推荐脚本

您可能也喜欢Wanikani: Level Duration 2

安装此脚本
  1. // ==UserScript==
  2. // @name WaniKani Level Duration
  3. // @namespace https://www.wanikani.com
  4. // @description This will display the number of days since your last level-up. Two display options are offered. By RhosVeedcy.
  5. // @version 1.3.3
  6. // @include https://www.wanikani.com/
  7. // @include https://www.wanikani.com/dashboard
  8. // @include https://www.wanikani.com/level/*
  9. // @include https://www.wanikani.com/radicals*
  10. // @include https://www.wanikani.com/lattice/*
  11. // @include https://www.wanikani.com/kanji*
  12. // @include https://www.wanikani.com/vocabulary*
  13. // @include https://www.wanikani.com/community*
  14. // @include https://www.wanikani.com/chat/*
  15. // @include https://www.wanikani.com/about
  16. // @include https://www.wanikani.com/api
  17. // @include https://www.wanikani.com/faq
  18. // @run-at document-end
  19. // @grant GM_registerMenuCommand
  20.  
  21. // ==/UserScript==
  22.  
  23.  
  24. function get(id) {
  25. console.log('get fct');
  26. if (id && typeof id === 'string') {
  27. console.log(id);
  28. id = document.getElementById(id);
  29. }
  30. return id || null;
  31. }
  32.  
  33.  
  34. function dateSuffix(d) {
  35. if(d>3 && d<21) return 'th'; // http://stackoverflow.com/questions/15397372/javascript-new-date-ordinal-st-nd-rd-th
  36. switch (d % 10) {
  37. case 1: return "st";
  38. case 2: return "nd";
  39. case 3: return "rd";
  40. default: return "th";
  41. }
  42. }
  43.  
  44.  
  45. function GMsetup() {
  46.  
  47. if (GM_registerMenuCommand) {
  48.  
  49. GM_registerMenuCommand('WaniKani Level Duration: Switch display type', function() {
  50. var curDType = localStorage.getItem("WKlvldurDType") || 0;
  51. curDType++;
  52. curDType %= 2;
  53. localStorage.setItem("WKlvldurDType", curDType);
  54. location.reload();
  55. });
  56.  
  57. GM_registerMenuCommand('WaniKani Level Duration: Set manually', function() {
  58. var minusDays = prompt('How many days ago did you level up?');
  59. if (minusDays != null) {
  60. minusDays = Number(minusDays);
  61. if (isNaN(minusDays) || minusDays < 0) {
  62. return;
  63. }
  64. var d = new Date();
  65. var n = d.getTime();
  66. minusDays *= 24*60*60*1000;
  67. localStorage.setItem("WKlvlupLevTime", n - minusDays); // record level-up time
  68. location.reload();
  69. }
  70. });
  71.  
  72. }
  73. }
  74.  
  75.  
  76. function checkLevel() {
  77.  
  78. console.log("checkLevel() start");
  79.  
  80. var lastKnownLevel = localStorage.getItem("WKlvlupPrevLevel") || 1;
  81. var levelEls = document.getElementsByClassName("levels");
  82.  
  83. if (!levelEls || !levelEls[0]) {
  84.  
  85. return -1;
  86. }
  87.  
  88. var spanEls = levelEls[0].getElementsByTagName("span");
  89.  
  90. if (!spanEls || !spanEls[0]) {
  91.  
  92. return -1;
  93. }
  94.  
  95.  
  96. var curlevel = spanEls[0].innerHTML || lastKnownLevel;
  97.  
  98. var prev = Number(lastKnownLevel);
  99. var cur = Number(curlevel);
  100. var next = prev + 1;
  101.  
  102. if (cur == next) {
  103. console.log("leveled up!");
  104. var d = new Date();
  105. var n = d.getTime();
  106. localStorage.setItem("WKlvlupLevTime", n); // record level-up time
  107. localStorage.setItem("WKlvlupPrevLevel", cur); // update 'lastKnownLevel' for next time
  108.  
  109. } else if (cur != prev) {
  110. // either this is the first time we're running, or there's a different user here,
  111. // or the user's subscription status has changed, or something else weird is going on.
  112.  
  113. // if cur == 2, assume the user's subscription expired; leave everything be and wait for renewal. Otherwise,
  114.  
  115. if (cur != 2 || ! localStorage.getItem("WKlvlupPrevLevel")) {
  116.  
  117.  
  118. // clear WKlvlupLevTime to make sure we don't display incorrect level info
  119. console.log("reinitializing");
  120. localStorage.setItem("WKlvlupLevTime", 0);
  121. localStorage.setItem("WKlvlupPrevLevel", cur); // update 'lastKnownLevel' for next time
  122. }
  123.  
  124. } //else cur == prev, so 'lastKnownLevel' is still correct (or it will continue to default to 1 if it hasn't been stored yet)
  125.  
  126. console.log("prev level: ", prev);
  127. console.log("cur level: ", cur);
  128. console.log("next level: ", next);
  129. console.log("checkLevel() end");
  130.  
  131. return cur;
  132. }
  133.  
  134.  
  135.  
  136. function displayLastLevTime( curLevel ) {
  137.  
  138. console.log('displayLastLevTime()');
  139.  
  140. var lastKnownLevel = localStorage.getItem("WKlvlupPrevLevel") || 1;
  141. var levTime = localStorage.getItem("WKlvlupLevTime") || 0;
  142. var wkPage = window.location.pathname;
  143.  
  144. if (levTime != 0 && curLevel == lastKnownLevel) {
  145.  
  146. var datetime = new Date(Number(levTime));
  147. var now = new Date;
  148. var one10thDay = 24*60*60*100; // hours*minutes*seconds*milliseconds/10
  149. var diffDays = (Math.round((now.getTime() - datetime.getTime())/(one10thDay))) / 10;
  150. var curDType = localStorage.getItem("WKlvldurDType") || 0;
  151.  
  152. console.log("diffDays = ", diffDays);
  153. console.log("displayType = ", curDType);
  154.  
  155. if (curDType == 0) { // display type 0
  156.  
  157. var levelsbox = document.getElementsByClassName("levels")[0].getElementsByTagName("a")[0];
  158.  
  159. if (levelsbox) {
  160.  
  161. var t2 = document.createElement('div');
  162. t2.innerHTML = '<div id="WKlvldurLBTxt"> </div>'+
  163. '</div>';
  164.  
  165. levelsbox.appendChild(t2);
  166.  
  167. var thing3 = get("WKlvldurLBTxt");
  168.  
  169. if (thing3 && diffDays >= 0) {
  170.  
  171. var dayString = ((diffDays > 1.0) ? " days)" : " day)");
  172.  
  173. if (diffDays < 0.1) {
  174.  
  175. diffDays = "< 0.1"; // (< 0.1 day)
  176. }
  177.  
  178. thing3.innerHTML = "(" + diffDays + dayString;
  179.  
  180. // this next block is to make everything else in the navbar line up properly (popups mainly)
  181.  
  182. var boxnames = ["title", "lessons", "reviews", "radicals", "kanji", "vocabulary", "account"];
  183.  
  184. for (var i=0; i < boxnames.length; i++) {
  185.  
  186. var innerStr = '<div id=' + boxnames[i] + 'xxlvlup' + ' style="color:#F2F2F2"> </div>'+ '</div>';
  187. var thebox = document.getElementsByClassName(boxnames[i])[0].getElementsByTagName("a")[0];
  188. var stubby = document.createElement('div');
  189. stubby.innerHTML = innerStr;
  190. thebox.appendChild(stubby);
  191. var theThing = get(boxnames[i]+'xxlvlup');
  192. theThing.innerHTML = ".";
  193. }
  194. }
  195. }
  196. } else if (wkPage === "/" || wkPage === "/dashboard") { // display type 1
  197.  
  198. var celebrationImg = get("WKlvlupImg");
  199. var celebrationTxt = get("WKlvlupTxt");
  200.  
  201. if (celebrationImg || celebrationTxt) { return; } // WK LevelUP Celebrator is doing its thing, don't crash the party
  202.  
  203. var msg = get("search");
  204.  
  205. if (msg) {
  206.  
  207. var t = document.createElement('div');
  208.  
  209. t.innerHTML = '<div id="WKlvldurTxt" align="center" style="margin:18px;text-align:center;line-height:110%;font-size:100%;"> </div>'+
  210. '</div>';
  211.  
  212. t.style.fontFamily = "'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif";
  213. msg.appendChild(t);
  214.  
  215. var thing2 = get("WKlvldurTxt");
  216.  
  217. if (thing2) {
  218.  
  219. var daynames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
  220. var monthnames = ["January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December "];
  221. var dd = datetime.getDate();
  222. var hours = datetime.getHours();
  223. var minutes = datetime.getMinutes();
  224. var ampm = "AM";
  225.  
  226. if (hours > 12) {
  227.  
  228. hours -= 12;
  229. ampm = "PM";
  230. }
  231.  
  232. if (minutes < 10) {
  233.  
  234. minutes = "0" + String(minutes);
  235. }
  236.  
  237. var theTxt = "You reached Level " + curLevel + " on " + daynames[datetime.getDay()] + ", " + monthnames[datetime.getMonth()] + dd + dateSuffix(dd) + " at " + hours + ":" + minutes + " " + ampm;
  238.  
  239. if (diffDays >= 0 && diffDays < 0.1) {
  240.  
  241. theTxt += " (< 0.1 day ago)";
  242. } else if (diffDays >= 0.1 && diffDays <= 1) {
  243.  
  244. theTxt += " (" + diffDays + " day ago)";
  245.  
  246. } else if (diffDays > 1) {
  247.  
  248. theTxt += " (" + diffDays + " days ago)";
  249. }
  250.  
  251. thing2.innerHTML= theTxt;
  252. }
  253. }
  254. }
  255. }
  256. }
  257.  
  258.  
  259. function init () {
  260.  
  261. console.log('init() start');
  262.  
  263. var curDType = localStorage.getItem("WKlvldurDType");
  264. if (!curDType) {
  265. localStorage.setItem("WKlvldurDType", 0);
  266. }
  267. console.log('init() end');
  268. }
  269.  
  270.  
  271.  
  272. function main () {
  273.  
  274. var curLevel;
  275.  
  276. console.log("pathname: ", window.location.pathname);
  277.  
  278. console.log("main()");
  279.  
  280. init();
  281.  
  282. GMsetup();
  283.  
  284. curLevel = checkLevel();
  285.  
  286. if (curLevel != -1) {
  287.  
  288. displayLastLevTime(curLevel);
  289. }
  290. }
  291.  
  292. window.addEventListener("load", main, false);
  293.  
  294. console.log('script load end');