// ==UserScript==
// @name TMVN League HOF
// @namespace https://trophymanager.com
// @version 5
// @description Trophymanager: hall of fame of tournament
// @match https://trophymanager.com/history/league/*/*/*/standings*
// @grant none
// @downloadURL none
// ==/UserScript==
(function () {
"use strict";
/* --------------------------- STORAGE --------------------------- */
const champOfSeason = new Map(); // season -> clubId (filled later with nth)
const titleCounter = new Map(); // clubId -> cumulative #titles during scan
const countChampions = new Map(); // clubId -> #1 titles
const countRunnerUp = new Map(); // clubId -> #2 titles
const countThird = new Map(); // clubId -> #3 titles
const latestName = new Map(); // clubId -> {name, season}
/* --------------------------- FETCH ----------------------------- */
const currentSeason = (window.SESSION && SESSION.season) ? SESSION.season : '';
function getLeagueInfo() {
let country,
division,
group;
if (window.feed_nat && window.feed_div && window.feed_gro) {
country = String(feed_nat);
division = String(feed_div);
group = String(feed_gro);
} else {
const m = location.pathname.match(/\/league\/([^\/]+)\/(\d+)\/(\d+)/);
if (m)
[, country, division, group] = m;
}
return {
country,
division,
group
};
}
const info = getLeagueInfo();
let baseUrl = `https://trophymanager.com/history/league/${info.country}/${info.division}/${info.group}/standings/`;
let fetched = 0;
const total = currentSeason - 1;
for (let season = currentSeason - 1; season > 0; season--) {
$.ajax({
url: baseUrl + season,
type: "GET",
dataType: "html",
crossDomain: true,
success: (html) => {
const rows = $(".box_body .border_bottom tr", html);
if (rows.length >= 4) {
for (let j = 1; j <= 3; j++) { // ranks 1‑3
const $row = rows.eq(j);
const rank = +$row.children().eq(0).text();
const $link = $row.find("[club_link]");
const clubId = $link.attr("club_link");
const clubName = $link.text();
// save latest club name (largest season number wins)
if (!latestName.has(clubId) || season > latestName.get(clubId).season) {
latestName.set(clubId, {
name: clubName,
season
});
}
if (rank === 1) {
champOfSeason.set(season, clubId);
increase(countChampions, clubId);
} else if (rank === 2) {
increase(countRunnerUp, clubId);
} else if (rank === 3) {
increase(countThird, clubId);
}
}
}
fetched++;
},
error: () => fetched++
});
}
const waiter = setInterval(() => {
if (fetched < total)
return;
clearInterval(waiter);
computeNthTitlesAndBuild();
}, 500);
/* --------------------------- HELPERS --------------------------- */
function increase(map, key) {
map.set(key, (map.get(key) || 0) + 1);
}
function ensureRightColumn() {
let $col = $(".column3_a");
if (!$col.length) {
$col = $("
");
if ($('#bteam_reminder').length === 1) {
$(".main_center").eq(3).append($col);
} else {
$(".main_center").eq(2).append($col);
}
$(".column3").first().remove();
}
return $col;
}
/* -------------------------- BUILD UI -------------------------- */
function computeNthTitlesAndBuild() {
// scan seasons ascending to compute nth title
for (let season = 1; season < currentSeason; season++) {
if (!champOfSeason.has(season))
continue;
const clubId = champOfSeason.get(season);
const nth = (titleCounter.get(clubId) || 0) + 1;
titleCounter.set(clubId, nth);
champOfSeason.set(season, {
clubId,
nth
});
}
const $column = ensureRightColumn();
buildChampionsBox($column);
buildHofBox($column);
}
/* -------------- BOX 1: Champions by season -------------- */
function buildChampionsBox($column) {
const boxId = "tmvn_champions_box";
if (document.getElementById(boxId))
return;
const $box = $(
``);
$column.append($box);
let html = `Season | Club | nth |
`;
let row = 0;
for (let season = currentSeason - 1; season > 0; season--) {
const entry = champOfSeason.get(season);
if (!entry)
continue;
const {
clubId,
nth
} = entry;
const clubName = latestName.get(clubId).name;
row++;
const odd = row % 2 ? "class='odd'" : "";
html += `
${season} |
${clubName} |
${nth} |
`;
}
html += `
`;
$("#" + boxId).append(html);
}
/* -------------- BOX 2: Hall of Fame -------------- */
function buildHofBox($column) {
const boxId = "tmvn_hof_box";
if (document.getElementById(boxId))
return;
const $box = $(
``);
$column.append($box);
// build sortable array of clubs with score champion*1000 + runner*100 + third
const clubScores = [];
const allClubIds = new Set([...countChampions.keys(), ...countRunnerUp.keys(), ...countThird.keys()]);
allClubIds.forEach(clubId => {
const champ = countChampions.get(clubId) || 0;
const run = countRunnerUp.get(clubId) || 0;
const third = countThird.get(clubId) || 0;
const score = champ * 1000 + run * 100 + third;
if (score > 0)
clubScores.push({
clubId,
champ,
run,
third,
score
});
});
clubScores.sort((a, b) => b.score - a.score);
let html = `# | Club | #1 | #2 | #3 |
`;
clubScores.forEach((c, idx) => {
const odd = (idx + 1) % 2 ? "class='odd'" : "";
const clubName = latestName.get(c.clubId).name;
html += `
${idx + 1} |
${clubName} |
${c.champ || ""} |
${c.run || ""} |
${c.third || ""} |
`;
});
html += `
`;
$("#" + boxId).append(html);
}
})();