您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Mortal牌谱解析增强脚本
当前为
// ==UserScript== // @name Mortal 显示恶手率 // @namespace https://viayoo.com/ // @version 2.0 // @description Mortal牌谱解析增强脚本 // @author mcube-12139 // @author modify by Miku39 // @run-at document-idle // @include /^https?:\/\/mjai.ekyu.moe\/report\/[A-Za-z0-9-_]+.html$/ // @include /^https?:\/\/mjai.ekyu.moe\/?([A-Za-z0-9-_]+.html)?$/ // @grant none // ==/UserScript== { if(window.location.pathname.startsWith("/report/")) { document.getElementsByClassName("collapse")[1].toggleAttribute("open", true); //打开 元数据 选项卡 //保留n位小数 function roundFun(value, n) { return Math.round(value*Math.pow(10,n))/Math.pow(10,n); } const badMoveUpperLimit = 5; const badMoveUpperLimitCustom = 10; let badChooseNum = 0; let badChooseNumCustom = 0; const lang = document.documentElement.lang; const i18nText = {}; if (lang == "zh-CN") { i18nText.badMove = "恶手"; i18nText.badMoveRatio = "恶手率"; } else { i18nText.badMove = "Bad move"; i18nText.badMoveRatio = "bad moves/total"; } i18nText.badMoveUp = " (严重鸡打 权重<=5%)"; i18nText.badMoveDown = " (普通错误 权重5~10%)"; i18nText.badMoveNull = " "; i18nText.badMoveSymbol = "%"; i18nText.badMoveDiffer = "差值: "; // i18nText.badMoveDiffer1 = "微差(0~5): "; i18nText.badMoveDiffer2 = "小幅差距(5~10): "; i18nText.badMoveDiffer3 = "低等差距(10~20): "; i18nText.badMoveDiffer4 = "中等差距(20~40): "; i18nText.badMoveDiffer5 = "高等差距(40~60): "; i18nText.badMoveDiffer6 = "大幅度差距(60~80): "; i18nText.badMoveDiffer7 = "压倒性差距(80~100): "; // i18nText.badMoveSum = " (总计)"; const orderLosses = document.getElementsByClassName("order-loss"); for (let i = 0, length = orderLosses.length; i != length; ++i) { const orderLoss = orderLosses[i]; const chosenIndex = parseInt(orderLoss.innerText.substring(2)); const turnInfo = orderLoss.parentElement; const summary = turnInfo.parentElement; const collapseEntry = summary.parentElement; const details = collapseEntry.lastChild; const table = details.firstChild; const tbody = table.lastChild; const chosenTr = tbody.childNodes[chosenIndex - 1]; const weightTd = chosenTr.lastChild; const intSpan = weightTd.firstChild; const chosenWeight = parseInt(intSpan.textContent); if (chosenWeight <= badMoveUpperLimit) { //严重恶手 const badChooseNode = document.createElement("span"); badChooseNode.innerHTML = ` \u00A0\u00A0\u00A0${i18nText.badMove}${i18nText.badMoveUp}`; badChooseNode.style.color = "#f00"; badChooseNode.style.fontWeight = 900; badChooseNode.style.fontSize = "20px"; turnInfo.appendChild(badChooseNode); collapseEntry.style.border = "2px solid #f00"; badChooseNum++; }else if (chosenWeight <= badMoveUpperLimitCustom) { //普通恶手 const badChooseNode = document.createElement("span"); badChooseNode.innerHTML = ` \u00A0\u00A0\u00A0${i18nText.badMove}${i18nText.badMoveDown}`; badChooseNode.style.color = "#6600FF"; badChooseNode.style.fontWeight = 700; badChooseNode.style.fontSize = "20px"; turnInfo.appendChild(badChooseNode); collapseEntry.style.border = "2px solid #6600FF"; badChooseNumCustom++; } } //for //const metaData = document.body.childNodes[4]; const metaData = document.getElementsByClassName("collapse")[1]; const metaDataDl = metaData.lastChild; const version = metaDataDl.childNodes[16]; const sameRatioDd = metaDataDl.childNodes[15]; const sameRatioText = sameRatioDd.textContent; const chooseNumStr = sameRatioText.substring(sameRatioText.indexOf("/") + 1); const chooseNum = parseInt(chooseNumStr); metaDataDl.childNodes[14].style.color = "#6600FF"; //rating metaDataDl.childNodes[15].style.color = "#6600FF"; metaDataDl.childNodes[16].style.color = "#6600FF"; //AI 一致率 metaDataDl.childNodes[17].style.color = "#6600FF"; const badChooseRatioDt = document.createElement("dt"); badChooseRatioDt.style.color = "#f00"; badChooseRatioDt.innerHTML = i18nText.badMoveRatio + i18nText.badMoveNull + badMoveUpperLimit + i18nText.badMoveSymbol; const badChooseRatioDd = document.createElement("dd"); badChooseRatioDd.style.color = "#f00"; badChooseRatioDd.innerHTML = `${badChooseNum}/${chooseNum} = ${(100 * badChooseNum / chooseNum).toFixed(3)}%`; metaDataDl.insertBefore(badChooseRatioDd, version); metaDataDl.insertBefore(badChooseRatioDt, badChooseRatioDd); /* 新增 计算总恶手数 */ badChooseNumCustom += badChooseNum; //计算总恶手数 const badChooseRatioDt2 = document.createElement("dt"); badChooseRatioDt2.style.color = "#f00"; badChooseRatioDt2.innerText = i18nText.badMoveRatio + i18nText.badMoveNull + badMoveUpperLimitCustom + i18nText.badMoveSymbol; const badChooseRatioDd2 = document.createElement("dd"); badChooseRatioDd2.style.color = "#f00"; badChooseRatioDd2.innerHTML = `${badChooseNumCustom}/${chooseNum} = ${(100 * badChooseNumCustom / chooseNum).toFixed(3)}%`; metaDataDl.insertBefore(badChooseRatioDd2, version); metaDataDl.insertBefore(badChooseRatioDt2, badChooseRatioDd2); /* 列出选择权重 */ const entry = document.getElementsByClassName("collapse entry"); for (let i = 0, length = entry.length; i != length; ++i) { const roleEle = entry[i].getElementsByClassName("role"); let selfPai = roleEle[0].parentElement; let mortalPai = roleEle[1].nextElementSibling; if(mortalPai.tagName.toLocaleLowerCase() == 'details') { mortalPai = roleEle[1].nextSibling; } if (Object.prototype.toString.call(selfPai.childNodes[selfPai.childNodes.length -2]) == '[object SVGSVGElement]') { if(selfPai.childNodes[selfPai.childNodes.length -2].tagName.toLocaleLowerCase() == 'svg') { //如果有多张牌图片,就使用最后一张牌图片 selfPai = selfPai.childNodes[selfPai.childNodes.length -2]; } } if(mortalPai.nextElementSibling.tagName.toLocaleLowerCase() == 'svg') { //如果有多张牌图片,就使用最后一张牌图片 mortalPai = mortalPai.nextElementSibling; } const dataEle = entry[i].getElementsByTagName("tbody")[0].childNodes; var selfPaiData = 0; var mortalPaiData = 0; var map = new Map(); //使用map保证重置循坏后的唯一性 let j = 0, size = dataEle.length; while (j != size) { let selfPaiStr = null; let mortalPaiStr = null; let isResetLoop = false; //是否重置循坏 if(selfPai != null){ if(Object.prototype.toString.call(selfPai) == '[object Text]') { selfPaiStr = selfPai.data; }else{ let obj = selfPai.getElementsByClassName("face"); if(obj[0] != null){ selfPaiStr = obj[0].href.baseVal; }else{ //选择跳过的情况 selfPaiStr = selfPai.childNodes[selfPai.childNodes.length -1].data; } } } if(mortalPai != null){ if(Object.prototype.toString.call(mortalPai) == '[object Text]') { mortalPaiStr = mortalPai.data; }else{ let obj = mortalPai.getElementsByClassName("face"); if(obj[0] != null){ mortalPaiStr = obj[0].href.baseVal; }else{ //选择跳过的情况 mortalPaiStr = mortalPai.childNodes[mortalPai.childNodes.length -1].data; } } } let data = dataEle[j].childNodes[2].innerHTML.replace(/<.*?>/g, ""); //过滤html标签, 只保留文字内容 let obj1 = dataEle[j].childNodes[0].getElementsByClassName("face"); let dataPaiStr; if(obj1[obj1.length - 1] != null) { // 如果有多张牌, 则选择最后一张牌作为对比牌 (主要用于吃的情况、碰杠这些牌都是一样的) dataPaiStr = obj1[obj1.length - 1].href.baseVal; }else{ dataPaiStr = dataEle[j].childNodes[0].innerHTML; if(map.has(j) == false) { map.set(j, true); //保存当前j的值,防止重复开始循坏 j = 0; //如果 有 选择跳过的情况, 则重新开始循坏, 以找到正确的数据 isResetLoop = true; } } if(selfPaiStr == dataPaiStr) { //如果目标操作是自己的操作 selfPaiData = data; const span = document.createElement("span"); span.innerText = ` \u00A0\u00A0\u00A0` + data; entry[i].insertBefore(span, entry[i].childNodes[3].nextSibling); selfPai = null; //置null, 防止继续计算 }else if(mortalPaiStr == dataPaiStr) { //如果目标操作是Mortal的操作 mortalPaiData = data; const span = document.createElement("span"); span.innerText = ` \u00A0\u00A0\u00A0` + data; span.style.marginLeft = "5px"; if(Object.prototype.toString.call(mortalPai.nextSibling) == '[object Text]') { //如果有多张牌图片,就使用最后一张牌图片后面的文字的位置 mortalPai = mortalPai.nextSibling; } entry[i].insertBefore(span, mortalPai.nextSibling); mortalPai = null; //置null, 防止继续计算 } if(selfPaiStr == mortalPaiStr) { //如果自己选择打出的牌与mortal选择打出的牌相同 if(map.has(j) == false) { map.set(j, true); //保存当前j的值,防止重复开始循坏 j = 0; //如果 有 选择跳过的情况, 则重新开始循坏, 以找到正确的数据 isResetLoop = true; } } if(selfPai == null && mortalPai == null) { //是否处理完毕 break; //跳出循坏 } if(isResetLoop == false){ ++j; } }//for /* 计算自己的选择与mortal选择的差值 */ var differData = roundFun(Math.abs(mortalPaiData - selfPaiData), 5); //保留5位小数 if (differData != 0) { //忽略自己和mortal打出的牌一样的结果 var turnInfo = roleEle[0].parentElement.parentElement.childNodes[0]; let newNode = document.createElement("span"); if (differData < 5) { //微差 newNode.style.color = "#000"; //黑色 newNode.innerHTML = ` \u00A0\u00A0\u00A0` + i18nText.badMoveDiffer1 + differData; }else if (differData < 10) { //小幅差距 newNode.style.color = "#996633"; //褐色 newNode.innerHTML = ` \u00A0\u00A0\u00A0` + i18nText.badMoveDiffer2 + differData; }else if (differData < 20) { //低等差距 newNode.style.color = "#009966"; //淡绿 newNode.innerHTML = ` \u00A0\u00A0\u00A0` + i18nText.badMoveDiffer3 + differData; }else if (differData < 40) { //中等差距 newNode.style.color = "#3399FF"; //淡蓝 newNode.innerHTML = ` \u00A0\u00A0\u00A0` + i18nText.badMoveDiffer4 + differData; }else if (differData < 60) { //高等差距 newNode.style.color = "#3333CC"; //深蓝 newNode.innerHTML = ` \u00A0\u00A0\u00A0` + i18nText.badMoveDiffer5 + differData; }else if (differData < 80) { //大幅度差距 newNode.style.color = "#CC0099"; //淡红 newNode.innerHTML = ` \u00A0\u00A0\u00A0` + i18nText.badMoveDiffer6 + differData; }else{ //压倒性差距 newNode.style.color = "#f00"; //红色 newNode.innerHTML = ` \u00A0\u00A0\u00A0` + i18nText.badMoveDiffer7 + differData; } newNode.style.fontWeight = 400; turnInfo.appendChild(newNode); } }//for }else { document.getElementsByName("show-rating")[0].checked = true; //默认勾选 显示Rating } }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址