PersonPageStats

show avg ratings and rankings on a person's page on bangumi

// ==UserScript==
// @name         PersonPageStats
// @namespace    https://jirehlov.com
// @version      0.1
// @description  show avg ratings and rankings on a person's page on bangumi
// @author       Jirehlov
// @include      /^https?:\/\/(bgm\.tv|bangumi\.tv|chii\.in)\/person\/\d+(?!\/works\/voice)\/works/
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
	'use strict';
	let totalSum = 0;
	let totalCount = 0;
	let totalRank = 0;
	let rankCount = 0;
	function calculateAverage() {
		const browserFullElements = document.querySelectorAll('.browserFull');
		totalSum = 0;
		totalCount = 0;
		const rankElements = document.querySelectorAll('.rank');
		totalRank = 0;
		rankCount = 0;
		browserFullElements.forEach(browserFullElement => {
			const liElements = browserFullElement.querySelectorAll('li');
			liElements.forEach(liElement => {
				const rateInfoElement = liElement.querySelector('.rateInfo');
				if (rateInfoElement) {
					const fadeElement = rateInfoElement.querySelector('.fade');
					if (fadeElement) {
						const value = parseFloat(fadeElement.textContent);
						if (!isNaN(value)) {
							totalSum += value;
							totalCount++;
						}
					}
				}
			});
		});
		rankElements.forEach(rankElement => {
			const smallElement = rankElement.querySelector('small');
			if (smallElement) {
				const rankText = rankElement.textContent.replace('Rank ', '').trim();
				const rankValue = parseInt(rankText);
				if (!isNaN(rankValue)) {
					totalRank += rankValue;
					rankCount++;
				}
			}
		});
		return {
			avgRating: totalCount === 0 ? 0 : totalSum / totalCount,
			avgRank: rankCount === 0 ? 0 : totalRank / rankCount
		};
	}
	function updateDisplay() {
		const {avgRating, avgRank} = calculateAverage();
		const averageLi = document.querySelector('#averageValue');
		const rankAverageLi = document.querySelector('#rankAverage');
		const totalCountSpan = document.querySelector('#totalCount');
		const rankCountSpan = document.querySelector('#rankCount');
		if (averageLi) {
			averageLi.textContent = avgRating.toFixed(4);
		}
		if (rankAverageLi) {
			rankAverageLi.textContent = avgRank.toFixed(4);
		}
		if (totalCountSpan) {
			totalCountSpan.textContent = totalCount;
		}
		if (rankCountSpan) {
			rankCountSpan.textContent = rankCount;
		}
	}
	function createFilterButtons() {
		const subjectFilterElement = document.querySelector('.subjectFilter');
		if (subjectFilterElement) {
			const groupedUL = document.createElement('ul');
			groupedUL.className = 'grouped clearit';
			const titleLi = document.createElement('li');
			titleLi.classList.add('title');
			titleLi.innerHTML = '<span>当前页面统计信息</span>';
			const averageLi = document.createElement('li');
			averageLi.innerHTML = `<span>评分平均值: <span id="averageValue">${ calculateAverage().avgRating.toFixed(4) }</span></span>`;
			const rankAverageLi = document.createElement('li');
			rankAverageLi.innerHTML = `<span>排名平均值: <span id="rankAverage">${ calculateAverage().avgRank.toFixed(4) }</span></span>`;
			const totalCountLi = document.createElement('li');
			totalCountLi.innerHTML = `<span>评分条目数: <span id="totalCount">${ totalCount }</span></span>`;
			const rankCountLi = document.createElement('li');
			rankCountLi.innerHTML = `<span>排名条目数: <span id="rankCount">${ rankCount }</span></span>`;
			groupedUL.appendChild(titleLi);
			groupedUL.appendChild(averageLi);
			groupedUL.appendChild(totalCountLi);
			groupedUL.appendChild(rankAverageLi);
			groupedUL.appendChild(rankCountLi);
			subjectFilterElement.appendChild(groupedUL);
		}
	}
	createFilterButtons();
	const observer = new MutationObserver(updateDisplay);
	observer.observe(document.body, {
		subtree: true,
		childList: true,
		attributes: true,
		attributeFilter: ['class']
	});
}());