Below is a patch implementing #2 and #3 (ability to choose location and units). Note that it is a reverse diff where the minuses are the changes and the pluses are the original. In other words, what is says as “new version” is actually the old version. Most patch utilities have a flag that you can use to tell it the patch is reversed.
===================================================================
--- Current Version
+++ New Version
@@ -3,9 +3,9 @@
// @namespace wkreviewclock
// @description Adds a clock to WaniKani review session statistics and estimates the remaining time.
// @include http://www.wanikani.com/review*
// @include https://www.wanikani.com/review*
-// @version 1.1
+// @version 1.0
// @author Markus Tuominen
// @grant none
// @license GPL version 3 or later: http://www.gnu.org/copyleft/gpl.html
// @source https://github.com/Markus98/wk-review-clock
@@ -21,10 +21,8 @@
const averageStatsKey = 'reviewRateAverageStats';
const scriptId = 'WKReviewClock'
const defaultSettings = {
- units: 'rph',
- location: 'toprightright',
showTimer: true,
showRate: true,
showRemaining: true,
updateInterval: 1.0,
@@ -76,10 +74,10 @@
const reviewsDoneNumber = parseInt(document.getElementById('completed-count').textContent);
const reviewRate = time !== 0 ? reviewsDoneNumber/time : 0; // reviews/sec
if (showRate) {
- const formattedRate = formatRate(reviewRate, 'short');
- statHtmlElems.rate.span.textContent = (hideRateRemaining ? '—' : formattedRate) + '';
+ const formattedRate = (reviewRate*3600).toFixed(1); // reviews/hour
+ statHtmlElems.rate.span.textContent = (hideRateRemaining ? '—' : formattedRate) + ' r/h';
}
const reviewsAvailableNumber = parseInt(document.getElementById('available-count').textContent);
const timeRemaining = reviewsAvailableNumber / reviewRate; // seconds
@@ -148,23 +146,9 @@
}
statHtmlElems.updateVisibility();
// append statsDiv to header
- let parent;
- const header = document.createElement('span');
- const location = wkof.settings[scriptId].location;
- if (location == 'toprightright') {
- parent = document.getElementById('stats');
- parent.append(header);
- } else if (location == 'toprightleft') {
- parent = document.getElementById('stats');
- parent.prepend(header);
- header.style.cssText = 'margin-right: 2em';
- } else if (location == 'bottom') {
- parent = document.getElementById('reviews');
- parent.append(header);
- header.classList.add('wkrc_bottom');
- }
+ const header = document.getElementById('stats');
header.appendChild(statHtmlElems.timer.icon);
header.appendChild(statHtmlElems.timer.span);
header.appendChild(statHtmlElems.rate.icon);
header.appendChild(statHtmlElems.rate.span);
@@ -253,9 +237,9 @@
// Saved time and rate
const lastTime = parseFloat(localStorage.getItem(timerTimeKey));
const lastTimeStr = isNaN(lastTime) ? '—' : getTimeString(splitToHourMinSec(lastTime));
const lastRate = parseFloat(localStorage.getItem(timerRateKey));
- const lastRateStr = formatRate(lastRate);
+ const lastRateStr = isNaN(lastRate) ? '—' : (lastRate*3600).toFixed(1);
// Average rate
const avgStats = getAverageStats();
if (!avgStats.mostRecentAdded && lastTime > ignoreInterval && lastRate > 0) {
@@ -264,18 +248,18 @@
avgStats.mostRecentAdded = true;
setAverageStats(avgStats);
}
const avgRate = avgStats.rateSum / avgStats.reviews; // reviews/second
- const avgRateStr = formatRate(avgRate, 'short');
+ const avgRateStr = isNaN(avgRate) ? '—' : (parseFloat(avgRate)*3600).toFixed(1);
// Estimate time for current reviews
const numOfReviews = parseInt(reviewCountSpan.textContent);
const estimatedTime = numOfReviews / avgRate;
const estimatedTimeStr = getTimeString(splitToHourMinSec(estimatedTime), false);
// Set stats text content
timeSpan.textContent = `Duration: ${lastTimeStr}`;
- rateSpan.textContent = `Review rate: ${lastRateStr} (avg. ${avgRateStr}) (${avgStats.reviews} sessions)`;
+ rateSpan.textContent = `Review rate: ${lastRateStr} reviews per hour (avg. ${avgRateStr} r/h) (${avgStats.reviews} sessions)`;
estimatedTimeDiv.textContent =
!showEstimatedSessionTime || isNaN(estimatedTime) || numOfReviews === 0 ?
'' : `~${estimatedTimeStr}`;
@@ -285,32 +269,8 @@
footer.appendChild(resetAvgButton);
reviewCountSpan.appendChild(estimatedTimeDiv);
}
-let shortUnitNames = {'rph': 'r/h', 'rpm': 'r/m', 'mp100r': 'm/100r'}
-let unitNames = {'rph': 'reviews/hr', 'rpm': 'reviews/min', 'mp100r': 'min/100 reviews'}
-function formatRate(rps, format) {
- if (isNaN(rps) || rps < 0.00001) {
- return '—';
- }
- rps = parseFloat(rps);
- const units = wkof.settings[scriptId].units;
- let res;
- if (units == 'rph') {
- res = rps*3600;
- } else if (units == 'rpm') {
- res = rps*60;
- } else if (units == 'mp100r') {
- res = 1/rps/60*100;
- }
- if (format == 'short') {
- return res.toFixed(1) + ' ' + shortUnitNames[units];
- } else {
- return res.toFixed(1) + ' ' + unitNames[units];
- }
-
-}
-
function openSettings() {
var config = {
script_id: scriptId,
title: 'Review Clock Settings',
@@ -319,40 +279,12 @@
statHtmlElems.updateVisibility();
rateShowDelay = parseFloat(wkof.settings[scriptId].rateShowDelay)*60;
},
content: {
- general: {
- type: 'page',
- label: 'General',
- content: {
- units: {
- type: 'dropdown',
- label: 'Units for Speed',
- default: defaultSettings.units,
- hover_tip: 'What units the review rate of completion should be displayed in.',
- content: {
- rph: 'reviews/hr',
- rpm: 'reviews/min',
- mp100r: 'min/100 reviews',
- }
- },
- }
- },
reviewPage: {
type: 'page',
label: 'Review Page',
content: {
- location: {
- type: 'dropdown',
- label: 'Display Location',
- default: defaultSettings.location,
- hover_tip: 'Where to show the below items (if checked) during reviews.',
- content: {
- toprightright: 'top right (right of other stats)',
- toprightleft: 'top right (left of other stats)',
- bottom: 'bottom in gray font',
- }
- },
showTimer: {
type: 'checkbox',
label: 'Show elapsed time',
default: defaultSettings.showTimer,
@@ -452,14 +384,8 @@
console.warn('WaniKani Review Clock: Wanikani Open FrameWork required for adjusting settings. '
+ 'Installation instructions can be found here: https://community.wanikani.com/t/installing-wanikani-open-framework/28549');
}
- const style = document.createElement('style');
- style.textContent = '.wkrc_bottom i { margin-right: 0.5em; margin-left: 0.8em; }' +
- '.wkrc_bottom span { margin-right: 0.5em; }' +
- '.wkrc_bottom { color:#BBB; letter-spacing: initial; display: block; text-align: center; }';
- document.head.append(style);
-
if(/session$/.exec(window.location.href)) { // review page
await generateStatHtmlElems();
startReviewTimer();
} else { // review summary page