// ==UserScript==
// @name TMVN Cup HOF
// @namespace https://trophymanager.com
// @version 3
// @description Trophymanager: hall of fame of tournament
// @match https://trophymanager.com/history/cup/*
// @grant none
// @downloadURL none
// ==/UserScript==
(function () {
/* --------------------------- STORE --------------------------- */
const championsBySeason = new Map(); // season -> {id, nth}
const championIdOfSeason = new Map(); // season -> clubId (raw, before nth calc)
const titleCounter = new Map(); // clubId -> running nth counter
const clubNameById = new Map(); // clubId -> latest name
const cupChampTotal = new Map(); // clubId -> #champion
const cupRunnerTotal = new Map(); // clubId -> #runner‑up
const lastSeasonAppear = new Map(); // clubId -> most recent season they reached final
/* --------------------------- HELPERS ------------------------- */
const inc = (map, key) => map.set(key, (map.get(key) || 0) + 1);
function ensureRightColumn() {
let column = document.querySelector('div.column3_a');
if (!column) {
const old = document.querySelector('div.column3');
if (old) old.parentNode.removeChild(old);
column = document.createElement('div');
column.className = 'column3_a';
const centers = document.querySelectorAll('div.main_center');
const target = centers[centers.length === 4 ? 3 : 2];
target.appendChild(column);
}
return column;
}
function renderTables() {
/* Champions by season table (desc) */
const seasonsDesc = Array.from(championsBySeason.keys()).sort((a,b)=>b-a);
let championsHTML = "
Season | Club | Nth |
";
seasonsDesc.forEach((season,idx) => {
const {id,nth} = championsBySeason.get(season);
const name = clubNameById.get(id);
const odd = (idx & 1) ? " class='odd'" : "";
championsHTML += `${season} | ${name} | ${nth} |
`;
});
championsHTML += "
";
/* Hall of Fame */
const allIds = new Set([...cupChampTotal.keys(), ...cupRunnerTotal.keys()]);
const hofList = Array.from(allIds).sort((a,b)=>{
const scoreB = (cupChampTotal.get(b)||0)*1000 + (cupRunnerTotal.get(b)||0);
const scoreA = (cupChampTotal.get(a)||0)*1000 + (cupRunnerTotal.get(a)||0);
if (scoreB !== scoreA) return scoreB - scoreA;
// tie‑break by most recent appearance (descending season)
return (lastSeasonAppear.get(b)||0) - (lastSeasonAppear.get(a)||0);
});
let hofHTML = "# | Club | #1 | #2 |
";
hofList.forEach((id,index)=>{
const name = clubNameById.get(id);
const c = cupChampTotal.get(id)||'';
const r = cupRunnerTotal.get(id)||'';
const odd = (index & 1) ? " class='odd'" : "";
hofHTML += `${index+1} | ${name} | ${c} | ${r} |
`;
});
hofHTML += "
";
/* inject */
const col = ensureRightColumn();
if (!document.getElementById('tmvn_cup_champions')) {
col.insertAdjacentHTML('beforeend', ``);
} else {
document.querySelector('#tmvn_cup_champions .box_body').innerHTML = `${championsHTML}`;
}
if (!document.getElementById('tmvn_cup_hof')) {
col.insertAdjacentHTML('beforeend', ``);
} else {
document.querySelector('#tmvn_cup_hof .box_body').innerHTML = `${hofHTML}`;
}
}
/* --------------------------- SCAN --------------------------- */
const currentSeason = parseInt(document.querySelector('#top_menu a.none.white.small').innerText.split(/(\s+)/)[2],10);
const country = location.href.split('/')[5];
let scanned = 0;
for (let season = 1; season < currentSeason; season++) {
$.ajax(`https://trophymanager.com/history/cup/${country}/${season}`, {
type: 'GET', dataType: 'html', crossDomain: true,
success: response => {
const final = $('.match_list.border_bottom li', response)[0];
if (final) {
const a = final.querySelectorAll('a');
const id1 = a[0].getAttribute('club_link');
const id2 = a[2].getAttribute('club_link');
const name1 = a[0].innerText;
const name2 = a[2].innerText;
clubNameById.set(id1, name1);
clubNameById.set(id2, name2);
const [s1,s2] = a[1].innerText.split('-').map(n=>parseInt(n,10));
const champId = s1 > s2 ? id1 : id2;
const runId = s1 > s2 ? id2 : id1;
championIdOfSeason.set(season, champId); // save raw champ -> compute nth later
inc(cupChampTotal, champId);
inc(cupRunnerTotal, runId);
lastSeasonAppear.set(champId, season);
lastSeasonAppear.set(runId, season);
}
if (++scanned === currentSeason-1) finalize();
},
error: () => { if (++scanned === currentSeason-1) finalize(); }
});
}
function finalize() {
/* compute nth titles in chronological order to avoid async issues */
const seasonsAsc = Array.from(championIdOfSeason.keys()).sort((a,b)=>a-b);
seasonsAsc.forEach(season=>{
const champId = championIdOfSeason.get(season);
if (!champId) return;
inc(titleCounter, champId);
const nth = titleCounter.get(champId);
championsBySeason.set(season, {id: champId, nth});
});
renderTables();
}
})();