MAL extra stats

Adds favorite/dropped % and unweighted score to myanimelist stats page

当前为 2023-07-06 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==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>"


})();