// ==UserScript==
// @name FMP Rating
// @name:en FMP Rating
// @namespace http://tampermonkey.net/
// @version 0.10
// @description Show Rating
// @description:en Show Rating
// @match https://footballmanagerproject.com/Team/Player?id=*
// @match https://footballmanagerproject.com/Team/Player/?id=*
// @match https://www.footballmanagerproject.com/Team/Player?id=*
// @match https://www.footballmanagerproject.com/Team/Player/?id=*
// @grant none
// @license MIT
// ==/UserScript==
const RatingRate={
// Han,One,Ref,Aer,Jum,Ele,Kic,Thr,Pos,Sta,Pac
0: [1.0,0.8,1.0,0.6,0.6,0.5,0.5,0.5,0.7,0.5,0.6],//GK
// Mar,Tak,Tec,Pas,Cro,Fin,Hea,Lon,Pos,Sta,Pac
4: [1.0,1.0,0.5,0.5,0.3,0.2,1.0,0.6,0.9,0.8,0.5],//DC
5: [0.6,1.0,0.6,0.6,1.0,0.4,0.6,0.6,0.6,0.8,0.5],//DL
6: [0.6,1.0,0.6,0.6,1.0,0.4,0.6,0.6,0.6,0.8,0.5],//DR
8: [0.7,0.9,0.6,0.7,0.3,0.4,0.9,0.7,0.8,0.8,0.5],//DMC
9: [0.5,1.0,0.6,0.7,1.0,0.4,0.6,0.6,0.6,0.8,0.5],//DML
10:[0.8,0.5,0.5,1.0,0.6,0.6,0.6,1.0,0.6,0.4,0.6],//DMR
16:[0.5,0.7,0.8,1.0,0.4,0.5,0.6,0.7,0.8,0.8,0.5],//MC
17:[0.4,0.6,0.6,0.8,1.0,0.6,0.6,0.7,0.7,0.8,0.5],//ML
18:[0.4,0.6,0.6,0.8,1.0,0.6,0.6,0.7,0.7,0.8,0.5],//MR
32:[0.3,0.3,0.7,1.0,0.4,0.9,0.7,1.0,0.7,0.8,0.5],//AMC
33:[0.3,0.5,0.7,0.8,1.0,0.6,0.6,0.7,0.8,0.8,0.5],//AML
34:[0.3,0.5,0.7,0.8,1.0,0.6,0.6,0.7,0.8,0.8,0.5],//AMR
64:[0.2,0.5,0.7,0.7,0.4,1.0,1.0,0.8,0.7,0.8,0.5],//FC
};
const currentUrl = window.location.href;
const urlObj = new URL(currentUrl);
const id = urlObj.searchParams.get('id');
function getId(id){
const idDIv = document.createElement('tr');
idDIv.innerHTML = '<th>ID</th><td>'+id+'</td>';
return idDIv
}
function getRating(rating) {
const ratingDiv = document.createElement('tr');
ratingDiv.innerHTML = '<th>Rating</th><td>'+rating/10+'</td>';
let infoTable = document.getElementsByClassName("infotable");
infoTable[0].appendChild(ratingDiv);
}
function getBirthday(birthday) {
const birthtime = new Date(FMP.Day0)
birthtime.setDate(birthtime.getDate() + birthday);
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const birthdayDiv = document.createElement('tr');
birthdayDiv.innerHTML = '<th>出生日</th><td><span title="' + weekdays[birthtime.getDay()] + '">' + birthday + '</span>\t<span>' + weekdays[birthtime.getDay()] + '</span></td>';
let infoTable = document.getElementsByClassName("infotable");
infoTable[0].appendChild(birthdayDiv);
console.log(birthtime);
}
function getRatingTable(skills, pos ,nowRating) {
const targerElement = document.querySelectorAll('.d-flex.flex-wrap.justify-content-around');
let postions = [4,5,8,9,16,17,32,33,64];
let index=0;
let table={};
if (pos === 0) {
return;
}
else {
switch (pos) {
case 4: index=4;break;
case 5: index=5;break;
case 6: index=5;break;
case 8: index=8;break;
case 9: index=9;break;
case 10: index=9;break;
case 16: index=16;break;
case 17: index=17;break;
case 18: index=17;break;
case 32: index=32;break;
case 33: index=33;break;
case 34: index=33;break;
case 64: index=64;break;
}
for (let i of postions) {
table[i] = getPosRating(skills,i);
}
}
let predTable=predictRating(table,index,nowRating);
let tableDiv = document.createElement('table');
tableDiv.className = 'skilltable';
tableDiv.style.marginLeft = 'auto';
tableDiv.style.marginRight = 'auto';
let header='<th>位置</th><th>DC</th><th>DLR</th><th>DMC</th><th>DMLR</th><th>MC</th><th>MLR</th><th>OMC</th><th>OMLR</th><th>FC</th>';
let rats='<td>Rating</td>';
// 找出最大值
const maxValue = Math.max(...Object.values(predTable));
// 找出对应的键
const maxKey = Object.keys(predTable).find(key => predTable[key] === maxValue);
console.log("最大值的键:", maxKey, "最大值:", maxValue);
for (let i of postions) {
if (i==maxKey && i!=index){
rats+='<td style="color:lightgreen">'+predTable[i].toFixed(1)+'</td>';
}
else if(i==index){
rats+='<td style="color:yellow">'+predTable[i].toFixed(1)+'</td>';
}
else{
rats+='<td>'+predTable[i].toFixed(1)+'</td>';
}
}
tableDiv.innerHTML='<tbody><tr>'+header+'</tr><tr>'+rats+'</tr></tbody>';
let textDiv = document.createElement('span');
textDiv.innerHTML='*仅供参考';
textDiv.style.color='yellow';
textDiv.style.fontSize = '12px';
targerElement[0].after(tableDiv);
targerElement[0].after(textDiv);
targerElement[0].after(document.createElement('br'));
}
function predictRating(ratingTable,index,posRating){
let predBouns=posRating/10/ratingTable[index];
return Object.entries(ratingTable).reduce((newTable, [key, value]) => {
newTable[key] = value * predBouns; // 修改值
return newTable;
}, {});;
}
function getPubTalent(pubTalent,pos) {
const talentsDiv = document.getElementsByClassName("talents");
const tdDiv = talentsDiv[0].getElementsByTagName("td");
if (pos === 0) {
tdDiv[0].textContent+=pubTalent.agi+1;
tdDiv[1].textContent+=pubTalent.set+1;
tdDiv[2].textContent+=pubTalent.str+1;
}
else {
tdDiv[0].textContent+=pubTalent.ada+1;
tdDiv[1].textContent+=pubTalent.agi+1;
tdDiv[2].textContent+=pubTalent.set+1;
tdDiv[3].textContent+=pubTalent.str+1;
}
}
function getPosRating(skills,pos){
let skillValue = [];
if(pos === 0) {
skillValue = [skills.Han,
skills.One,
skills.Ref,
skills.Aer,
skills.Jum,
skills.Ele,
skills.Kic,
skills.Thr,
skills.Pos,
skills.Sta,
skills.Pac];
}
else {
skillValue = [skills.Mar,
skills.Tak,
skills.Tec,
skills.Pas,
skills.Cro,
skills.Fin,
skills.Hea,
skills.Lon,
skills.Pos,
skills.Sta,
skills.Pac];
}
const rating = skillValue.reduce((total, currentSkill, index) => {
return total + currentSkill * RatingRate[pos][index];
}, 0);
const sum = RatingRate[pos].reduce((accumulator, currentValue) => accumulator + currentValue, 0);
return rating/sum;
//return rating/sum*(1+xpBonus(skills.Rou));//计算不准确
}
function getPlayers(pid,rating,ratingtable,pubtalents,birthdate){
$.getJSON({
"url": ("/Team/Player?handler=PlayerData&playerId=" + pid),
"datatype": "json",
"contentType": "application/json",
"type": "GET"
},
function (ajaxResults) {
rating(ajaxResults.player.marketInfo.rating);
ajaxResults.player.pos=fp2pos(ajaxResults.player.fp);
var skills=decode(ajaxResults.player.skills,ajaxResults.player.pos)
ratingtable(skills,ajaxResults.player.pos,ajaxResults.player.marketInfo.rating);
pubtalents(ajaxResults.player.pubTalents,ajaxResults.player.pos);
birthdate(ajaxResults.player.birthday);
}
);
}
function decode(binsk, pos) {
var skills = Uint8Array.from(atob(binsk), c => c.charCodeAt(0));
var sk = {};
if (pos === 0) {
sk.Han = skills[0] / 10;
sk.One = skills[1] / 10;
sk.Ref = skills[2] / 10;
sk.Aer = skills[3] / 10;
sk.Ele = skills[4] / 10;
sk.Jum = skills[5] / 10;
sk.Kic = skills[6] / 10;
sk.Thr = skills[7] / 10;
sk.Pos = skills[8] / 10;
sk.Sta = skills[9] / 10;
sk.Pac = skills[10] / 10;
sk.For = skills[11] / 10;
sk.Rou = (skills[12] * 256 + skills[13]) / 100;
}
else {
sk.Mar = skills[0] / 10;
sk.Tak = skills[1] / 10;
sk.Tec = skills[2] / 10;
sk.Pas = skills[3] / 10;
sk.Cro = skills[4] / 10;
sk.Fin = skills[5] / 10;
sk.Hea = skills[6] / 10;
sk.Lon = skills[7] / 10;
sk.Pos = skills[8] / 10;
sk.Sta = skills[9] / 10;
sk.Pac = skills[10] / 10;
sk.For = skills[11] / 10;
sk.Rou = (skills[12] * 256 + skills[13]) / 100;
}
return sk;
}
function fp2pos(fp) {
switch (fp) {
case "GK": return 0;
case "DC": return 4;
case "DL": return 5;
case "DR": return 6;
case "DMC": return 8;
case "DML": return 9;
case "DMR": return 10;
case "MC": return 16;
case "ML": return 17;
case "MR": return 18;
case "OMC": return 32;
case "OML": return 33;
case "OMR": return 34;
case "FC": return 64;
}
return -1;
}
function pos2fp(pos) {
switch (pos) {
case 0: return "GK";
case 4: return "DC";
case 5: return "DL";
case 6: return "DR";
case 8: return "DMC";
case 9: return "DML";
case 10: return "DMR";
case 16: return "MC";
case 17: return "ML";
case 18: return "MR";
case 32: return "OMC";
case 33: return "OML";
case 34: return "OMR";
case 64: return "FC";
}
return "";
}
function xpBonus(rou) {
return 5*rou/(rou+10)/100;
}
let observer = new MutationObserver((mutationsList, observer) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
let infoTable = document.getElementsByClassName("infotable");
if (infoTable[0].firstChild) {
infoTable[0].insertBefore(getId(id),infoTable[0].firstChild);
getPlayers(id,getRating,getRatingTable,getPubTalent,getBirthday);
observer.disconnect(); // 停止观察
break;
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });