Adds favorite/dropped % and unweighted score to myanimelist stats page
当前为
// ==UserScript==
// @name MAL extra stats
// @namespace http://tampermonkey.net/
// @version 0.6.1
// @description Adds favorite/dropped % and unweighted score to myanimelist stats page
// @author pepe
// @match https://myanimelist.net/*/stats*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
//https://stackoverflow.com/questions/32229667/have-max-2-decimal-places
function roundNearest05(num) { // round drops
return Math.round(num / 0.005) * 0.005;
}
function roundNearest0001(num) { // round favs
return Math.round(num / 0.0001) * 0.0001;
}
setTimeout(function(){
// drop %
let watching = document.querySelectorAll('[valign="top"]:nth-child(2) .spaceit_pad')[0].textContent.split(" ")[1].replace(/,/g,"");
let completed = document.querySelectorAll('[valign="top"]:nth-child(2) .spaceit_pad')[1].textContent.split(" ")[1].replace(/,/g,"");
let dropped = document.querySelectorAll('[valign="top"]:nth-child(2) .spaceit_pad')[3].textContent.split(" ")[1].replace(/,/g,"");
let total_viewers = parseInt(watching) + parseInt(completed) + parseInt(dropped);
let dropPercent = +parseFloat(roundNearest05((dropped/total_viewers).toFixed(3))*100).toFixed(2); console.log(`${dropped}/${total_viewers}=${(dropped/total_viewers).toFixed(3)}`)
document.querySelectorAll('[valign="top"]:nth-child(2) .spaceit_pad')[3].innerHTML += " ("+dropPercent+"%)"
// fav %
let favEL = document.querySelectorAll('[valign="top"]:nth-child(1) .spaceit_pad');
let totalEL = document.querySelectorAll('[valign="top"]:nth-child(2) .spaceit_pad')[5];
let regex = /,| |\n/g;
let fav = favEL[favEL.length-1].textContent.split(":")[1].replaceAll(regex,""); console.log(fav)
let favPercent = +parseFloat(roundNearest0001((fav/(total_viewers-parseInt(dropped))).toFixed(3))*100).toFixed(2);
let newFavEL = `<div class="spaceit_pad"><span class="dark_text" style="color: #0088ff!important;">Favorites:</span> ${fav} (${favPercent}%)</div>`
let favDOM = new DOMParser().parseFromString(newFavEL, "text/xml");
totalEL.parentNode.insertBefore(favDOM.documentElement, totalEL.nextSibling);
}, 500);
var arr = {
max: function(array) {
return Math.max.apply(null, array);
},
min: function(array) {
return Math.min.apply(null, array);
},
range: function(array) {
return arr.max(array) - arr.min(array);
},
midrange: function(array) {
return arr.range(array) / 2;
},
sum: function(array) {
var num = 0;
for (var i = 0, l = array.length; i < l; i++) num += array[i];
return num;
},
mean: function(array) {
return arr.sum(array) / array.length;
},
median: function(array) {
array.sort(function(a, b) {
return a - b;
});
var mid = array.length / 2;
return mid % 1 ? array[mid - 0.5] : (array[mid - 1] + array[mid]) / 2;
},
modes: function(array) {
if (!array.length) return [];
var modeMap = {},
maxCount = 0,
modes = [];
array.forEach(function(val) {
if (!modeMap[val]) modeMap[val] = 1;
else modeMap[val]++;
if (modeMap[val] > maxCount) {
modes = [val];
maxCount = modeMap[val];
}
else if (modeMap[val] === maxCount) {
modes.push(val);
maxCount = modeMap[val];
}
});
return modes;
},
variance: function(array) {
// var mean = arr.mean(array);
var t = array.length;
for(var m, s = 0, l = t; l--; s += array[l]);
for(m = s / t, l = t, s = 0; l--; s += Math.pow(array[l] - m, 2));
return s / (t-1);
},
standardDeviation: function(array) {
return Math.sqrt(arr.variance(array));
},
meanAbsoluteDeviation: function(array) {
var mean = arr.mean(array);
return arr.mean(array.map(function(num) {
return Math.abs(num - mean);
}));
},
zScores: function(array) {
var mean = arr.mean(array);
var standardDeviation = arr.standardDeviation(array);
return array.map(function(num) {
return (num - mean) / standardDeviation;
});
}
};
// score deviation and unweighted score (includes bots)
var scores = [];
var score_bars = document.getElementsByClassName("updatesBar");
var c = 10000000;
var score_count = '1,', mal_rating = 0;
try {score_count = document.querySelector('[itemprop=ratingCount]').textContent;}catch(e){} // catch for null
try {mal_rating = document.querySelector('[itemprop=ratingValue]').textContent;}catch(e){}
var le = score_count;
le = (le.replace(/\s/g , "")).length; // thousand/million separator to empty
var count = c.toString().substring(0,le-Math.floor(le/2));
count = parseInt(count);
for(let i = 0; i < score_bars.length; i++){
var votes_by_score = score_bars[i].nextElementSibling.getElementsByTagName("small")[0].innerHTML;
votes_by_score = votes_by_score.substring(votes_by_score.lastIndexOf("(")+1,votes_by_score.lastIndexOf(" "));
for(let j = 0; j < (votes_by_score/count).toFixed(0); j++){
scores.push(10-i);
}
}
// inverse calculation of Weighted MAL Score
let currentScore = Number(mal_rating)
score_count = Number(score_count.replace(/,/g, ''))
let UnweightedWithoutBots = ((currentScore/(score_count/(100+score_count)))-((100/(score_count+100))/(score_count/(100+score_count)))*6.37)
UnweightedWithoutBots = (UnweightedWithoutBots + (UnweightedWithoutBots-currentScore)).toFixed(2) // above calculation is slightly wrong? but this fixes it..
//document.getElementsByClassName("border_top")[0].innerHTML = " bots "+(arr.mean(scores)).toFixed(2)+ " | real "+ UnweightedWithoutBots + " | mal "+ mal_rating
//+ " | sdev "+(arr.standardDeviation(scores)).toFixed(2) +" | variance " + (arr.variance(scores)).toFixed(2)
document.querySelector("#content > table > tbody > tr > td:nth-child(2) > div > h2:nth-child(13)").innerHTML = 'Score Stats <div style="padding-top:3px;">bots '+(arr.mean(scores)).toFixed(2)+ " | est "+ UnweightedWithoutBots + " | mal "+ mal_rating+"</div>"
})();