// ==UserScript==
// @name MZ - WL Weird Matches
// @namespace douglaskampl
// @version 2.2
// @description Checks world leagues rounds for unusual pairs of results
// @author Douglas
// @match https://www.managerzone.com/?p=match&sub=livescores_overview
// @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com
// @grant GM_addStyle
// @grant GM_getResourceText
// @resource weirdMatchesStyles https://u18mz.vercel.app/mz/userscript/other/weirdMatches.css
// @run-at document-idle
// @license MIT
// @downloadURL none
// ==/UserScript==
(function () {
'use strict';
GM_addStyle(GM_getResourceText('weirdMatchesStyles'));
const CONSTANTS = {
LEAGUE_TYPES: ['senior', 'u18_world', 'u21_world', 'u23_world'],
LEAGUE_DISPLAY_NAMES: {
'senior': 'Senior',
'u18_world': 'U18',
'u21_world': 'U21',
'u23_world': 'U23'
},
LEAGUE_LIMITS: {
div1: 1,
div2: 13,
div3: 40,
div4: 121,
div5: 291
},
ROUND_PAIRS: [
{ first: '11', second: '12', display: '11/12' },
{ first: '10', second: '13', display: '10/13' },
{ first: '9', second: '14', display: '9/14' },
{ first: '8', second: '15', display: '8/15' },
{ first: '7', second: '16', display: '7/16' },
{ first: '6', second: '17', display: '6/17' },
{ first: '5', second: '18', display: '5/18' },
{ first: '4', second: '19', display: '4/19' },
{ first: '3', second: '20', display: '3/20' },
{ first: '2', second: '21', display: '2/21' },
{ first: '1', second: '22', display: '1/22' }
],
ERROR_MESSAGES: {
FETCH_ERROR: 'Error fetching data for league',
NO_DISCREPANCIES: 'No weird matches found!',
INVALID_INPUT: 'Please enter a number between 1 and 10',
UNPLAYED_MATCHES: 'Warning: Some matches show X - X scores and may not have been played yet'
},
DOM: {
HEADER_ID: '#header-next-game',
BUTTON_CLASS: 'wl-check-button',
BUTTON_TEXT: 'WL',
BUTTON_TITLE: 'Check World League Rounds'
},
REGEX: {
GAMES: /
[^<]*]+>[^<]*<\/td>[^<]* | ]+>[^<]*]+>[^<]+<\/a>[^<]*<\/td>[^<]* | ]+>[^<]*<\/td>[^<]*<\/tr>/g,
SCORE: /]*>([^<]+)<\/a>/,
LINK: /= 2 && sid <= 4) return `1.${sid - 1}`;
if (sid >= 5 && sid <= CONSTANTS.LEAGUE_LIMITS.div2) return `2.${sid - 4}`;
if (sid >= 14 && sid <= CONSTANTS.LEAGUE_LIMITS.div3) return `3.${sid - 13}`;
return `4.${sid - 40}`;
}
async function fetchLeagueData(leagueType, worldLeagueId) {
const url = `/ajax.php?p=league&type=${leagueType}&sid=${worldLeagueId}&tid=1&sport=soccer&sub=schedule`;
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return await response.text();
} catch (error) {
console.error(`${CONSTANTS.ERROR_MESSAGES.FETCH_ERROR} ${worldLeagueId}:`, error.message);
return null;
}
}
function extractMatches(round, roundNumbers) {
const roundParts = round.split("");
const currentRound = roundParts[0].trim();
const matchesHTML = roundParts[1].split("")[0];
return {
currentRound,
games: matchesHTML.match(CONSTANTS.REGEX.GAMES) || []
};
}
function parseGameData(game) {
const teams = game.match(/ | ]*>[^<]*<\/td>/g).map(td => td.replace(/<[^>]+>/g, "").trim());
const score = CONSTANTS.REGEX.SCORE.exec(game)[1].trim();
const link = CONSTANTS.REGEX.LINK.exec(game)[1];
return { teams, score, link };
}
function checkDiscrepancy(homeScore, awayScore) {
const homeDiff = homeScore[0] - homeScore[1];
const awayDiff = awayScore[1] - awayScore[0];
const getWinner = diff => diff > 0 ? 0 : diff < 0 ? 1 : 2;
const homeWinner = getWinner(homeDiff);
const awayWinner = getWinner(awayDiff);
return {
totalDiff: Math.abs(homeDiff) + Math.abs(awayDiff),
isDiscrepancy: homeWinner !== 2 && awayWinner !== 2 && homeWinner !== awayWinner
};
}
async function processLeague(leagueType, worldLeagueId, minTotalDiff, roundNumbers) {
const html = await fetchLeagueData(leagueType, worldLeagueId);
if (!html) return { discrepancies: [], hasUnplayedMatches: false };
const rounds = html.split(/ |