// ==UserScript==
// @name Ban成績がRPG風に見やすくなるスクリプト
// @namespace http://t...content-available-to-author-only...y.net/
// @version 0.1
// @description 規約違反はBanしよう
// @author 名無し216
// @match https://w...content-available-to-author-only...e.com/reporthistory
// @grant none
// ==/UserScript==
// ライセンスはWTFPL(何でもOK)だから自由に使ってください
(function () {
// for debug
const pp = function(obj) {
// hoge = obj;
console.log(Object.prototype.toString.apply(obj))
console.log(JSON.stringify(obj, null, 2))
}
// 報告履歴の背景色
const colours = {
逃亡: 'cyan', // 投稿者が削除した時
制限: 'yellow', // 制限された時
削除: 'red', // 削除された時
生存: 'white' // 生き延びてる時
}
const data = window.ytInitialData.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[1].reportHistorySectionRenderer.reportHistorySectionRenderers;
// 計算結果を表示する要素の親
const parent = document.getElementById('container');
// スコアボードはドラッグで移動可能なdiv要素
const scoreBoard = getScoreBoard();
// 戦績
const record = {total: 0, hetare: 0, limited: 0, deleted: 0, alive: 0 };
// 動的に履歴が読み込まれたときの処理
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((element) => {
element.getNodes("items").forEach((node) => {
calculateBanScore(node, record);
drawBanScoreTable(scoreBoard, record);
setColour(node);
});
});
});
})
// 報告履歴の背景を状態によって色付け
function setColour(elm){
elm.setAttribute('style', `background: ${ colours[getState(elm)]};`);
}
// 要素から報告後の状態を取得
function getState(elm){
const _state = elm.getElementsByClassName("report-state")[0];
if(!_state){
return '逃亡';
}
switch(_state.textContent){
case '動画は制限されています。':
return '制限';
case '動画が削除されました。':
return '削除';
case '動画は現在アクティブです。':
return '生存';
}
}
// Ban成績を計算
function calculateBanScore(elm, record){
let state = getState(elm);
++record.total;
switch(state){
case '逃亡':
++record.hetare;
break;
case '制限':
++record.limited;
break;
case '削除':
++record.deleted;
break;
case '生存':
++record.alive;
break;
}
}
// スコアボードの作成
function getScoreBoard(){
const scoreBoard = document.createElement('div');
scoreBoard.setAttribute('id', 'score-board');
scoreBoard.setAttribute('style', 'font-size: 2em; opacity: 0.9 ; display: inline-block; color: white; line-height: 100%; position: absolute; left: 50px; top: 50px; width: 10em; height: 16em; background-color: black; cursor: move;');
scoreBoard.innerHTML = "計算中……"
let isMoving = false;
let XBeforeDrag = 0;
let YBeforeDrag = 0;
// ドラッグ始め
window.onmousedown = function(e) {
isMoving = true;
XBeforeDrag = e.clientX - parseInt(document.getElementById('score-board').style.left);
YBeforeDrag = e.clientY - parseInt(document.getElementById('score-board').style.top);
}
// ドラッグ終わり
window.onmouseup = function(e) {
isMoving = false;
}
// ドラッグ中
window.onmousemove = function(e) {
if(isMoving) {
document.getElementById('score-board').style.left = `${e.clientX - XBeforeDrag}px`;
document.getElementById('score-board').style.top = `${e.clientY - YBeforeDrag}px`;
}
}
return scoreBoard;
}
// ステータスの表示
function drawBanScoreTable(elm, record){
elm.innerHTML = `<table width="97%" style="text-align: right;"><tr><td colspan="2" style="text-align: center;"><div style="margin: 10px 0 1em 0;">つよさ</div></td></tr><tr><td>レベル:</td><td>${getLevel(record)}</td></tr><tr><td>ごうけい:</td><td>${record.total}</td></tr><tr><td>さくじょ:</td><td>${record.deleted}</td></tr><tr><td>せいげん:</td><td>${record.limited}</td></tr><tr><td>とうぼう:</td><td>${record.hetare}</td></tr><tr><td>せいぞん:</td><td>${record.alive}</td></tr><tr><td>だりつ:</td><td>${getBattingAverage(record).toFixed(1)}%</td></tr><tr><td>削除率:</td><td>${getRemovingAverage(record).toFixed(1)}%</td></tr><tr><td>経験値:</td><td>${getExp(record)}</td></tr><tr><td>次のレベ <br>ルまで:</td><td>${getRestExp(record)}</td></tr></table>`;
}
function expTable(level){
return level * (level - 1) / 2;
}
function getLevel(record){
return Math.floor((Math.sqrt(8 * getExp(record) + 1) + 1) / 2);
}
function getRestExp(record){
return expTable(getLevel(record) + 1) - getExp(record);
}
function getExp(record){
return record.deleted*3 + record.hetare + record.limited;
}
function getRemovingAverage(record){
return 100*record.deleted/record.total;
}
function getBattingAverage(record){
return 100*(1 - record.alive/record.total);
}
// スコアボードを追加
parent.insertBefore(scoreBoard, parent.firstChild);
// 報告結果がリストされるノード(の親?)
const target = document.getElementById('contents');
// 最初に表示される履歴を処理
const nodes = document.getElementsByTagName('ytd-video-report-renderer');
for(let i = 0; i < nodes.length; i++){
let node = nodes[i];
calculateBanScore(node, record);
drawBanScoreTable(scoreBoard, record);
setColour(node);
}
// 報告履歴の監視開始
observer.observe(target, {childList: true});
})();