MAL extra stats

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

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

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

You will need to install an extension such as Tampermonkey to install this script.

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         MAL extra stats 
// @namespace    http://tampermonkey.net/
// @version      0.6
// @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) {
        return Math.round(num / 0.005) * 0.005;
    }
    function roundNearest0001(num) {
        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.querySelectorAll('#content h2')[7].innerHTML = 'Score Stats <div style="padding-top:3px;">bots '+(arr.mean(scores)).toFixed(2)+ " | real "+ UnweightedWithoutBots + " | mal "+ mal_rating+"</div>"


})();