您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays player ratings on transfer page
当前为
// ==UserScript== // @name MZ - Player Ratings on Transfer Page // @namespace douglaskampl // @version 1.0 // @description Displays player ratings on transfer page // @author Douglas // @match https://www.managerzone.com/?p=transfer* // @match https://www.managerzone.com/?p=players* // @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com // @grant GM_addStyle // @license MIT // @run-at document-idle // ==/UserScript== (function () { 'use strict'; const ratings = { "SPEED": { "K": 0.09, "D": 0.25, "A": 0.25, "M": 0.15, "W": 0.25, "F": 0.23 }, "STAMINA": { "K": 0.09, "D": 0.16, "A": 0.18, "M": 0.15, "W": 0.20, "F": 0.15 }, "PLAYINT": { "K": 0.09, "D": 0.07, "A": 0.05, "M": 0.10, "W": 0.06, "F": 0.05 }, "PASSING": { "K": 0.02, "D": 0.02, "A": 0.05, "M": 0.15, "W": 0.04, "F": 0.04 }, "SHOOTING": { "K": 0.00, "D": 0.00, "A": 0.00, "M": 0.00, "W": 0.05, "F": 0.28 }, "HEADING": { "K": 0.00, "D": 0.00, "A": 0.02, "M": 0.00, "W": 0.00, "F": 0.03 }, "GOALKEEPING": { "K": 0.55, "D": 0.00, "A": 0.00, "M": 0.00, "W": 0.00, "F": 0.00 }, "BALLCONTROL": { "K": 0.09, "D": 0.08, "A": 0.10, "M": 0.12, "W": 0.15, "F": 0.15 }, "TACKLING": { "K": 0.00, "D": 0.30, "A": 0.25, "M": 0.20, "W": 0.05, "F": 0.02 }, "CROSSING": { "K": 0.02, "D": 0.07, "A": 0.05, "M": 0.08, "W": 0.15, "F": 0.00 }, "SETPLAYS": { "K": 0.00, "D": 0.00, "A": 0.00, "M": 0.00, "W": 0.00, "F": 0.00 }, "EXPERIENCE": { "K": 0.05, "D": 0.05, "A": 0.05, "M": 0.05, "W": 0.05, "F": 0.05 } }; const skillPositionMap = [ "SPEED", "STAMINA", "PLAYINT", "PASSING", "SHOOTING", "HEADING", "GOALKEEPING", "BALLCONTROL", "TACKLING", "CROSSING", "SETPLAYS", "EXPERIENCE" ]; function calculateRatings(skills) { const player = { K: 0, D: 0, A: 0, M: 0, W: 0, F: 0, B: 0, top: 0 }; Object.entries(skills).forEach(([skill, value]) => { if (!ratings[skill]) return; const num = parseInt(value, 10); if (isNaN(num)) return; if (skill !== "EXPERIENCE") { player.B += num; } player.K += num * ratings[skill]["K"]; if (player.K > player.top) player.top = player.K; player.D += num * ratings[skill]["D"]; if (player.D > player.top) player.top = player.D; player.A += num * ratings[skill]["A"]; if (player.A > player.top) player.top = player.A; player.M += num * ratings[skill]["M"]; if (player.M > player.top) player.top = player.M; player.W += num * ratings[skill]["W"]; if (player.W > player.top) player.top = player.W; player.F += num * ratings[skill]["F"]; if (player.F > player.top) player.top = player.F; }); return { K: player.K.toFixed(2), D: player.D.toFixed(2), A: player.A.toFixed(2), M: player.M.toFixed(2), W: player.W.toFixed(2), F: player.F.toFixed(2), B: player.B, top: player.top.toFixed(2) }; } function extractPlayerSkills(playerElement) { const skills = {}; const skillRows = playerElement.querySelectorAll('.player_skills tr'); skillRows.forEach((row, index) => { if (index >= skillPositionMap.length) return; const valueElem = row.querySelector('.skillval span'); if (valueElem) { const skillType = skillPositionMap[index]; const value = valueElem.textContent.trim(); skills[skillType] = value; } }); return skills; } function createRatingDisplay(ratings) { const positions = [ { code: 'K', name: 'Goalkeeper', value: ratings.K }, { code: 'D', name: 'Defender', value: ratings.D }, { code: 'A', name: 'Anchorman', value: ratings.A }, { code: 'M', name: 'Midfielder', value: ratings.M }, { code: 'W', name: 'Winger', value: ratings.W }, { code: 'F', name: 'Forward', value: ratings.F } ]; const container = document.createElement('div'); container.className = 'mz-rating-container'; const ratingsList = document.createElement('div'); ratingsList.className = 'mz-rating-list'; positions.forEach(pos => { const row = document.createElement('div'); row.className = 'mz-rating-row'; const isTop = pos.value === ratings.top; const posName = document.createElement('span'); posName.className = 'mz-pos-name' + (isTop ? ' mz-pos-top' : ''); posName.textContent = pos.name + ':'; const posValue = document.createElement('span'); posValue.className = 'mz-pos-value' + (isTop ? ' mz-pos-top' : ''); posValue.textContent = pos.value; row.appendChild(posName); row.appendChild(posValue); ratingsList.appendChild(row); }); container.appendChild(ratingsList); return container; } function addRatingButton(playerElement) { const idElement = playerElement.querySelector('.player_id_span'); if (!idElement) return; if (idElement.nextElementSibling && idElement.nextElementSibling.classList.contains('mz-rating-btn')) { return; } const btn = document.createElement('button'); btn.className = 'mz-rating-btn'; btn.innerHTML = '<i class="fa-solid fa-calculator"></i>'; btn.title = 'Show player ratings'; let ratingContainer = null; let isVisible = false; btn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); if (isVisible && ratingContainer) { ratingContainer.classList.remove('mz-rating-visible'); setTimeout(() => { if (ratingContainer && ratingContainer.parentNode) { ratingContainer.parentNode.removeChild(ratingContainer); } ratingContainer = null; }, 300); isVisible = false; btn.innerHTML = '<i class="fa-solid fa-calculator"></i>'; return; } const skills = extractPlayerSkills(playerElement); const ratings = calculateRatings(skills); ratingContainer = createRatingDisplay(ratings); const playerHeader = playerElement.querySelector('.subheader'); if (playerHeader) { playerHeader.parentNode.insertBefore(ratingContainer, playerHeader.nextSibling); } else { playerElement.appendChild(ratingContainer); } setTimeout(() => { ratingContainer.classList.add('mz-rating-visible'); }, 10); isVisible = true; btn.innerHTML = '<i class="fa-solid fa-xmark"></i>'; }); idElement.parentNode.insertBefore(btn, idElement.nextSibling); } function processPlayerElements() { const playerContainers = document.querySelectorAll('div[id^="thePlayers_"]'); playerContainers.forEach(addRatingButton); } function setupObserver() { const playerContainer = document.getElementById('players_container') || document.body; const observer = new MutationObserver((mutations) => { let shouldProcess = false; mutations.forEach(mutation => { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { for (const node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE && (node.id && node.id.startsWith('thePlayers_') || node.querySelector && node.querySelector('div[id^="thePlayers_"]'))) { shouldProcess = true; break; } } } }); if (shouldProcess) { processPlayerElements(); } }); observer.observe(playerContainer, { childList: true, subtree: true }); return observer; } function addStyles() { GM_addStyle(` .mz-rating-btn { display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; width: 24px; height: 24px; border: none; border-radius: 50%; background: #1a73e8; color: white; cursor: pointer; font-size: 12px; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .mz-rating-btn:hover { background: #0d5bbb; transform: translateY(-1px); box-shadow: 0 3px 6px rgba(0, 0, 0, 0.25); } .mz-rating-container { margin: 10px 0; padding: 12px; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); max-width: 300px; opacity: 0; transform: translateY(-10px); transition: all 0.3s ease; } .mz-rating-visible { opacity: 1; transform: translateY(0); } .mz-rating-header { font-weight: bold; margin-bottom: 8px; padding-bottom: 5px; border-bottom: 1px solid #eee; color: #333; font-size: 14px; } .mz-rating-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-bottom: 10px; } .mz-rating-row { display: flex; justify-content: space-between; align-items: center; padding: 3px 5px; } .mz-pos-name { font-size: 13px; color: #555; } .mz-pos-value { font-weight: bold; font-size: 13px; color: #333; } .mz-pos-top { color: #1a73e8; } .mz-total-row { margin-top: 5px; padding-top: 8px; border-top: 1px solid #eee; } `); } function init() { addStyles(); processPlayerElements(); setupObserver(); } if (document.readyState === 'complete' || document.readyState === 'interactive') { setTimeout(init, 500); } else { window.addEventListener('DOMContentLoaded', () => setTimeout(init, 500)); } })();