您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Lets you manage your tactics in ManagerZone
当前为
- // ==UserScript==
- // @name MZ Tactics Manager
- // @namespace douglaskampl
- // @version 10.1.0
- // @description Lets you manage your tactics in ManagerZone
- // @author Douglas Vieira
- // @match https://www.managerzone.com/?p=tactics
- // @match https://www.managerzone.com/?p=national_teams&sub=tactics&type=*
- // @icon https://yt3.googleusercontent.com/ytc/AIdro_mDHaJkwjCgyINFM7cdUV2dWPPnL9Q58vUsrhOmRqkatg=s160-c-k-c0x00ffffff-no-rj
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_addStyle
- // @require https://cdnjs.cloudflare.com/ajax/libs/jsSHA/3.3.1/sha256.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/i18next/23.7.16/i18next.min.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.10.2/sweetalert2.min.js
- // @license MIT
- // ==/UserScript==
- (function () {
- 'use strict';
- GM_addStyle(`@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Dancing+Script:wght@500&display=swap"); #mz_tactics_panel {font-family: "Space Grotesk", -apple-system, sans-serif; background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 20px; margin: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); border: 1px solid #1e293b; transition: opacity 0.3s ease, max-height 0.3s ease; max-height: 1000px; opacity: 1; color: #f8fafc; } .mz-group {background: linear-gradient(135deg, #334155 0%, #1e293b 100%); border-radius: 8px; padding: 16px; margin: 8px; border: 1px solid #334155; position: relative; } .mz-group-main-title {color: #f8fafc; font-size: 16px; font-weight: 500; margin: -4px 0 12px 0; padding-bottom: 8px; border-bottom: 1px solid rgba(248, 250, 252, 0.1); } .mz-main-title {color: #f8fafc; font-family: "Space Grotesk", sans-serif; font-size: 18px; font-weight: 500; margin: 0; padding: 0; text-align: center; letter-spacing: 0.2px; } .mz-version-text {color: #ff9933; font-family: "Dancing Script", cursive; font-size: 0.9em; font-weight: 500; margin-left: 4px; } .mz-divider {width: 40px; height: 2px; background: #64748b; margin: 8px auto 0; opacity: 0.3; } #mz_tactics_panel .mzbtn {display: inline-flex; align-items: center; padding: 8px 14px; margin: 4px; font-family: "Space Grotesk", sans-serif; font-size: 13px; font-weight: 500; color: #f8fafc; background: #334155; border: none; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; } #mz_tactics_panel .mzbtn:hover {background: #475569; transform: translateY(-1px); } #mz_tactics_panel .mzbtn:focus {outline: 2px solid #94a3b8; outline-offset: 1px; } #mz_tactics_panel select {font-family: "Space Grotesk", sans-serif; font-size: 13px; color: #f8fafc; padding: 8px 14px; border: 1px solid #334155; border-radius: 6px; background-color: #1e293b; cursor: pointer; margin: 4px; transition: all 0.2s ease; } #mz_tactics_panel select:focus {outline: none; border-color: #64748b; box-shadow: 0 0 0 2px rgba(100, 116, 139, 0.1); } #language_flag {height: 15px; width: 25px; margin: 6px 0 6px 6px; border: 1px solid #e2e8f0; border-radius: 22px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } #info_modal, #useful_links_modal {background: #1e293b; padding: 20px; border-radius: 12px; color: #f8fafc; width: 90%; max-width: 500px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); } #info_modal a, #useful_links_modal a {color: #60a5fa; } #info_modal ul, #useful_links_modal ul {list-style: none; padding: 0; } #info_modal ul li, #useful_links_modal ul li {margin: 10px 0; } .swal2-popup.swal-mz-popup {font-family: "Space Grotesk", sans-serif; border-radius: 8px; background: #1e293b; color: #f8fafc; } .swal2-popup.swal-mz-popup .swal2-title {font-size: 18px; color: #f8fafc; } .swal2-popup.swal-mz-popup .swal2-html-container {font-size: 14px; color: #f8fafc; } .swal2-popup.swal-mz-popup .swal2-input {font-size: 14px; border: 1px solid #334155; border-radius: 6px; background: #0f172a; color: #f8fafc; } .swal2-popup.swal-mz-popup .swal2-textarea {background: #0f172a; color: #f8fafc; border: 1px solid #334155; } .swal2-popup.swal-mz-popup .swal2-confirm {background: #475569 !important; } .swal2-popup.swal-mz-popup .swal2-cancel {background: #64748b !important; } .swal2-container.swal2-backdrop-show {background: rgba(0, 0, 0, 0.6); } #hidden_trigger_button {position: absolute; visibility: hidden; pointer-events: none; }`);
- const OUTFIELD_PLAYERS_SELECTOR = ".fieldpos.fieldpos-ok.ui-draggable:not(.substitute):not(.goalkeeper):not(.substitute.goalkeeper), .fieldpos.fieldpos-collision.ui-draggable:not(.substitute):not(.goalkeeper):not(.substitute.goalkeeper)";
- const GOALKEEPER_SELECTOR = ".fieldpos.fieldpos-ok.goalkeeper.ui-draggable";
- const FORMATION_TEXT_SELECTOR = "#formation_text";
- const TACTIC_SLOT_SELECTOR = ".ui-state-default.ui-corner-top.ui-tabs-selected.ui-state-active.invalid";
- const MIN_OUTFIELD_PLAYERS = 10;
- const MAX_TACTIC_NAME_LENGTH = 50;
- const DEFAULT_TACTICS_DATA_URL = "https://pub-02de1c06eac643f992bb26daeae5c7a0.r2.dev/json/defaultTactics.json";
- const LANG_DATA_BASE_URL = "https://pub-02de1c06eac643f992bb26daeae5c7a0.r2.dev/json/lang/";
- const BASE_FLAG_URL = "https://flagcdn.com/w320/";
- const LANGUAGES = [
- { code: "en", name: "English", flag: BASE_FLAG_URL + "gb.png" },
- { code: "pt", name: "Português", flag: BASE_FLAG_URL + "br.png" },
- { code: "zh", name: "中文", flag: BASE_FLAG_URL + "cn.png" },
- { code: "sv", name: "Svenska", flag: BASE_FLAG_URL + "se.png" },
- { code: "no", name: "Norsk", flag: BASE_FLAG_URL + "no.png" },
- { code: "da", name: "Dansk", flag: BASE_FLAG_URL + "dk.png" },
- { code: "es", name: "Español", flag: BASE_FLAG_URL + "ar.png" },
- { code: "pl", name: "Polski", flag: BASE_FLAG_URL + "pl.png" },
- { code: "nl", name: "Nederlands", flag: BASE_FLAG_URL + "nl.png" },
- { code: "id", name: "Bahasa Indonesia", flag: BASE_FLAG_URL + "id.png" },
- { code: "de", name: "Deutsch", flag: BASE_FLAG_URL + "de.png" },
- { code: "it", name: "Italiano", flag: BASE_FLAG_URL + "it.png" },
- { code: "fr", name: "Français", flag: BASE_FLAG_URL + "fr.png" },
- { code: "ro", name: "Română", flag: BASE_FLAG_URL + "ro.png" },
- { code: "tr", name: "Türkçe", flag: BASE_FLAG_URL + "tr.png" },
- { code: "ko", name: "한국어", flag: BASE_FLAG_URL + "kr.png" },
- { code: "ru", name: "Русский", flag: BASE_FLAG_URL + "ru.png" },
- { code: "ar", name: "العربية", flag: BASE_FLAG_URL + "sa.png" },
- { code: "jp", name: "日本語", flag: BASE_FLAG_URL + "jp.png" }
- ];
- const VERSION = "10.1.0";
- const VERSION_KEY = "mz_tactics_version";
- const SWAL_CONSTANTS = {
- ICONS: {
- SUCCESS: 'success',
- ERROR: 'error',
- WARNING: 'warning'
- }
- };
- const SWAL_CUSTOM_CLASS = {
- popup: 'swal-mz-popup',
- title: 'swal-mz-title',
- htmlContainer: 'swal-mz-html-container',
- input: 'swal-mz-input',
- validationMessage: 'swal-mz-validation',
- actions: 'swal-mz-actions',
- confirmButton: 'swal-mz-confirm',
- cancelButton: 'swal-mz-cancel',
- closeButton: 'swal-mz-close'
- };
- const USERSCRIPT_STRINGS = {
- addButton: "Add Tactic",
- addWithXmlButton: "Add Tactic via XML",
- deleteButton: "Delete Tactic",
- renameButton: "Rename Tactic",
- updateButton: "Update Tactic",
- clearButton: "Clear Tactics",
- resetButton: "Reset Tactics",
- importButton: "Import Tactics",
- exportButton: "Export Tactics",
- usefulLinksButton: "Useful Links",
- aboutButton: "About",
- tacticNamePrompt: "Tactic Name:",
- addAlert: "Tactic {} added successfully.",
- deleteAlert: "Tactic {} deleted successfully.",
- renameAlert: "Tactic {} renamed to {} successfully.",
- updateAlert: "Tactic {} updated successfully.",
- clearAlert: "Tactics cleared successfully.",
- resetAlert: "Tactics reset successfully.",
- importAlert: "Tactics imported successfully.",
- exportAlert: "Tactics exported successfully.",
- deleteConfirmation: "Do you really want to delete {}?",
- updateConfirmation: "Do you really want to update {}?",
- clearConfirmation: "Do you really want to clear tactics?",
- resetConfirmation: "Do you really want to reset tactics?",
- invalidTacticError: "Invalid tactic.",
- noTacticNameProvidedError: "No tactic name provided.",
- alreadyExistingTacticNameError: "Tactic name already exists.",
- tacticNameMaxLengthError: "Tactic name is too long.",
- noTacticSelectedError: "No tactic selected.",
- duplicateTacticError: "Duplicate tactic.",
- noChangesMadeError: "No changes made.",
- invalidImportError: "Invalid import file.",
- modalContentInfoText: "This is the tactic selector.",
- modalContentFeedbackText: "Send your feedback.",
- usefulContent: "Some useful resources:",
- tacticsDropdownMenuLabel: "Tactics:",
- languageDropdownMenuLabel: "Language:",
- errorTitle: "Error",
- doneTitle: "Done",
- confirmationTitle: "Confirmation",
- deleteTacticConfirmButton: "Delete",
- cancelConfirmButton: "Cancel",
- updateConfirmButton: "Update",
- clearTacticsConfirmButton: "Clear",
- resetTacticsConfirmButton: "Reset",
- addConfirmButton: "Add",
- xmlValidationError: "Invalid XML.",
- xmlParsingError: "Error parsing XML.",
- xmlPlaceholder: "Paste XML here",
- tacticNamePlaceholder: "Name",
- managerTitle: "MZ Tactics Manager",
- tacticActionsTitle: "Actions",
- otherActionsTitle: "Other",
- welcomeMessage: "Welcome to MZ Tactics Manager! Enjoy using it!<br><br>If you got any questions or suggestions, feel free to message douglaskampl via chat or guestbook.",
- welcomeGotIt: "Got it!"
- };
- const ELEMENT_STRING_KEYS = {
- add_tactic_button: "addButton",
- add_tactic_with_xml_button: "addWithXmlButton",
- delete_tactic_button: "deleteButton",
- rename_tactic_button: "renameButton",
- update_tactic_button: "updateButton",
- clear_tactics_button: "clearButton",
- reset_tactics_button: "resetButton",
- import_tactics_button: "importButton",
- export_tactics_button: "exportButton",
- about_button: "aboutButton",
- tactics_dropdown_menu_label: "tacticsDropdownMenuLabel",
- language_dropdown_menu_label: "languageDropdownMenuLabel",
- info_modal_info_text: "modalContentInfoText",
- info_modal_feedback_text: "modalContentFeedbackText",
- useful_links_button: "usefulLinksButton",
- };
- let dropdownMenuTactics = [];
- let activeLanguage;
- let infoModal;
- let usefulLinksModal;
- function isFootball() {
- const element = document.querySelector("div#tactics_box.soccer.clearfix");
- return !!element;
- }
- function sha256Hash(str) {
- const shaObj = new jsSHA("SHA-256", "TEXT");
- shaObj.update(str);
- return shaObj.getHash("HEX");
- }
- function showAlert(options) {
- const defaultOptions = {
- customClass: SWAL_CUSTOM_CLASS,
- buttonsStyling: true,
- showClass: {
- popup: 'swal-mz-popup modalFadeIn'
- },
- hideClass: {
- popup: 'modalFadeOut'
- },
- allowOutsideClick: true,
- allowEscapeKey: true,
- width: options.html?.includes('swal-xml-input') ? '600px' : '300px',
- padding: '20px'
- };
- if (options.customClass) {
- options.customClass = { ...SWAL_CUSTOM_CLASS, ...options.customClass };
- }
- return Swal.fire({
- ...defaultOptions,
- ...options
- });
- }
- function showSuccessMessage(title, text) {
- return showAlert({
- title,
- text,
- icon: SWAL_CONSTANTS.ICONS.SUCCESS
- });
- }
- function showErrorMessage(title, text) {
- return showAlert({
- title,
- text,
- icon: SWAL_CONSTANTS.ICONS.ERROR
- });
- }
- async function fetchTacticsFromGMStorage() {
- const storedTactics = GM_getValue("ls_tactics");
- if (storedTactics) {
- return storedTactics;
- } else {
- const jsonTactics = await fetchTacticsFromJson();
- storeTacticsInGMStorage(jsonTactics);
- return jsonTactics;
- }
- }
- async function fetchTacticsFromJson() {
- const response = await fetch(DEFAULT_TACTICS_DATA_URL);
- return await response.json();
- }
- function storeTacticsInGMStorage(data) {
- GM_setValue("ls_tactics", data);
- }
- async function validateDuplicateTactic(id) {
- const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
- return tacticsData.tactics.some((tactic) => tactic.id === id);
- }
- async function saveTacticToStorage(tactic) {
- const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
- tacticsData.tactics.push(tactic);
- await GM_setValue("ls_tactics", tacticsData);
- }
- async function validateDuplicateTacticWithUpdatedCoord(newId, selectedTac, tacticsData) {
- if (newId === selectedTac.id) {
- return "unchanged";
- } else if (tacticsData.tactics.some((tac) => tac.id === newId)) {
- return "duplicate";
- } else {
- return "unique";
- }
- }
- function handleTacticsSelection(tactic) {
- const outfieldPlayers = Array.from(document.querySelectorAll(OUTFIELD_PLAYERS_SELECTOR));
- const selectedTactic = dropdownMenuTactics.find((tacticData) => tacticData.name === tactic);
- if (selectedTactic) {
- if (outfieldPlayers.length < MIN_OUTFIELD_PLAYERS) {
- const hiddenTriggerButton = document.getElementById("hidden_trigger_button");
- hiddenTriggerButton.click();
- setTimeout(() => rearrangePlayers(selectedTactic.coordinates), 1);
- } else {
- rearrangePlayers(selectedTactic.coordinates);
- }
- }
- }
- function rearrangePlayers(coordinates) {
- const outfieldPlayers = Array.from(document.querySelectorAll(OUTFIELD_PLAYERS_SELECTOR));
- findBestPositions(outfieldPlayers, coordinates);
- for (let i = 0; i < outfieldPlayers.length; ++i) {
- outfieldPlayers[i].style.left = coordinates[i][0] + "px";
- outfieldPlayers[i].style.top = coordinates[i][1] + "px";
- removeCollision(outfieldPlayers[i]);
- }
- removeTacticSlotInvalidStatus();
- updateFormationText(getFormation(coordinates));
- }
- function findBestPositions(players, coordinates) {
- players.sort((a, b) => parseInt(a.style.top) - parseInt(b.style.top));
- coordinates.sort((a, b) => a[1] - b[1]);
- }
- function removeCollision(player) {
- if (player.classList.contains("fieldpos-collision")) {
- player.classList.remove("fieldpos-collision");
- player.classList.add("fieldpos-ok");
- }
- }
- function removeTacticSlotInvalidStatus() {
- const slot = document.querySelector(TACTIC_SLOT_SELECTOR);
- if (slot) {
- slot.classList.remove("invalid");
- }
- }
- function updateFormationText(formation) {
- const formationTextElement = document.querySelector(FORMATION_TEXT_SELECTOR);
- formationTextElement.querySelector(".defs").textContent = formation.defenders;
- formationTextElement.querySelector(".mids").textContent = formation.midfielders;
- formationTextElement.querySelector(".atts").textContent = formation.strikers;
- }
- function getFormation(coordinates) {
- let strikers = 0;
- let midfielders = 0;
- let defenders = 0;
- for (const coo of coordinates) {
- const y = coo[1];
- if (y < 103) {
- strikers++;
- } else if (y <= 204) {
- midfielders++;
- } else {
- defenders++;
- }
- }
- return { strikers, midfielders, defenders };
- }
- function validateTacticPlayerCount(outfieldPlayers) {
- const isGoalkeeper = document.querySelector(GOALKEEPER_SELECTOR);
- outfieldPlayers = outfieldPlayers.filter((player) => !player.classList.contains("fieldpos-collision"));
- if (outfieldPlayers.length < MIN_OUTFIELD_PLAYERS || !isGoalkeeper) {
- showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.invalidTacticError);
- return false;
- }
- return true;
- }
- async function addNewTactic() {
- const outfieldPlayers = Array.from(document.querySelectorAll(OUTFIELD_PLAYERS_SELECTOR));
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- const tacticCoordinates = outfieldPlayers.map((player) => [parseInt(player.style.left), parseInt(player.style.top)]);
- if (!validateTacticPlayerCount(outfieldPlayers)) {
- return;
- }
- const tacticId = generateUniqueId(tacticCoordinates);
- const isDuplicate = await validateDuplicateTactic(tacticId);
- if (isDuplicate) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.duplicateTacticError);
- return;
- }
- const result = await showAlert({
- title: USERSCRIPT_STRINGS.tacticNamePrompt,
- input: 'text',
- inputValue: '',
- inputValidator: (value) => {
- if (!value) {
- return USERSCRIPT_STRINGS.noTacticNameProvidedError;
- }
- if (value.length > MAX_TACTIC_NAME_LENGTH) {
- return USERSCRIPT_STRINGS.tacticNameMaxLengthError;
- }
- if (dropdownMenuTactics.some((t) => t.name === value)) {
- return USERSCRIPT_STRINGS.alreadyExistingTacticNameError;
- }
- },
- showCancelButton: true,
- confirmButtonText: USERSCRIPT_STRINGS.addConfirmButton,
- cancelButtonText: USERSCRIPT_STRINGS.cancelConfirmButton
- });
- const tacticName = result.value;
- if (!tacticName) {
- return;
- }
- const tactic = {
- name: tacticName,
- coordinates: tacticCoordinates,
- id: tacticId
- };
- await saveTacticToStorage(tactic);
- addTacticsToDropdownMenu(tacticsDropdownMenu, [tactic]);
- dropdownMenuTactics.push(tactic);
- const placeholderOption = tacticsDropdownMenu.querySelector('option[value=""]');
- if (placeholderOption) {
- placeholderOption.remove();
- }
- if (tacticsDropdownMenu.disabled) {
- tacticsDropdownMenu.disabled = false;
- }
- tacticsDropdownMenu.value = tactic.name;
- const changeEvent = new Event('change', { bubbles: true });
- tacticsDropdownMenu.dispatchEvent(changeEvent);
- handleTacticsSelection(tactic.name);
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.addAlert.replace("{}", tactic.name));
- }
- async function addNewTacticWithXml() {
- const result = await showAlert({
- title: USERSCRIPT_STRINGS.addWithXmlButton,
- html:
- `<textarea id="swal-xml-input" class="swal2-textarea swal-mz-input" placeholder="${USERSCRIPT_STRINGS.xmlPlaceholder}" style="height: 200px;"></textarea>` +
- `<input id="swal-name-input" class="swal2-input swal-mz-input" placeholder="${USERSCRIPT_STRINGS.tacticNamePlaceholder}">`,
- focusConfirm: false,
- showCancelButton: true,
- confirmButtonText: USERSCRIPT_STRINGS.addConfirmButton,
- cancelButtonText: USERSCRIPT_STRINGS.cancelConfirmButton,
- preConfirm: () => {
- const xml = document.getElementById('swal-xml-input').value;
- const name = document.getElementById('swal-name-input').value;
- if (!xml) {
- Swal.showValidationMessage(USERSCRIPT_STRINGS.xmlValidationError);
- return false;
- }
- if (!name) {
- Swal.showValidationMessage(USERSCRIPT_STRINGS.noTacticNameProvidedError);
- return false;
- }
- if (name.length > MAX_TACTIC_NAME_LENGTH) {
- Swal.showValidationMessage(USERSCRIPT_STRINGS.tacticNameMaxLengthError);
- return false;
- }
- if (dropdownMenuTactics.some((t) => t.name === name)) {
- Swal.showValidationMessage(USERSCRIPT_STRINGS.alreadyExistingTacticNameError);
- return false;
- }
- return { xml, name };
- }
- });
- if (!result.value) {
- return;
- }
- try {
- const { xml, name } = result.value;
- const newTactic = await convertXmlToTacticJson(xml, name);
- const tacticId = generateUniqueId(newTactic.coordinates);
- const isDuplicate = await validateDuplicateTactic(tacticId);
- if (isDuplicate) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.duplicateTacticError);
- return;
- }
- newTactic.id = tacticId;
- await saveTacticToStorage(newTactic);
- const tacticsDropdownMenu = document.getElementById('tactics_dropdown_menu');
- addTacticsToDropdownMenu(tacticsDropdownMenu, [newTactic]);
- dropdownMenuTactics.push(newTactic);
- tacticsDropdownMenu.value = newTactic.name;
- handleTacticsSelection(newTactic.name);
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.addAlert.replace('{}', newTactic.name));
- } catch (e) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.xmlParsingError);
- }
- }
- async function deleteTactic() {
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- const selectedTactic = dropdownMenuTactics.find((tactic) => tactic.name === tacticsDropdownMenu.value);
- if (!selectedTactic) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.noTacticSelectedError);
- return;
- }
- const result = await showAlert({
- text: USERSCRIPT_STRINGS.deleteConfirmation.replace("{}", selectedTactic.name),
- icon: SWAL_CONSTANTS.ICONS.WARNING,
- showCancelButton: true,
- confirmButtonText: USERSCRIPT_STRINGS.deleteTacticConfirmButton,
- cancelButtonText: USERSCRIPT_STRINGS.cancelConfirmButton
- });
- if (!result.isConfirmed) {
- return;
- }
- const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
- tacticsData.tactics = tacticsData.tactics.filter((tactic) => tactic.id !== selectedTactic.id);
- await GM_setValue("ls_tactics", tacticsData);
- dropdownMenuTactics = dropdownMenuTactics.filter((tactic) => tactic.id !== selectedTactic.id);
- const selectedOption = Array.from(tacticsDropdownMenu.options).find((option) => option.value === selectedTactic.name);
- tacticsDropdownMenu.remove(selectedOption.index);
- if (tacticsDropdownMenu.options[0]?.disabled) {
- tacticsDropdownMenu.selectedIndex = 0;
- }
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.deleteAlert.replace("{}", selectedTactic.name));
- }
- async function renameTactic() {
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- const selectedTactic = dropdownMenuTactics.find((tactic) => tactic.name === tacticsDropdownMenu.value);
- if (!selectedTactic) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.noTacticSelectedError);
- return;
- }
- const oldName = selectedTactic.name;
- const result = await showAlert({
- title: USERSCRIPT_STRINGS.tacticNamePrompt,
- input: 'text',
- inputValue: oldName,
- inputValidator: (value) => {
- if (!value) {
- return USERSCRIPT_STRINGS.noTacticNameProvidedError;
- }
- if (value.length > MAX_TACTIC_NAME_LENGTH) {
- return USERSCRIPT_STRINGS.tacticNameMaxLengthError;
- }
- if (value !== oldName && dropdownMenuTactics.some((t) => t.name === value)) {
- return USERSCRIPT_STRINGS.alreadyExistingTacticNameError;
- }
- },
- showCancelButton: true,
- confirmButtonText: USERSCRIPT_STRINGS.updateConfirmButton,
- cancelButtonText: USERSCRIPT_STRINGS.cancelConfirmButton
- });
- const newName = result.value;
- if (!newName) {
- return;
- }
- const selectedOption = Array.from(tacticsDropdownMenu.options).find((option) => option.value === selectedTactic.name);
- const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
- tacticsData.tactics = tacticsData.tactics.map((tactic) => {
- if (tactic.id === selectedTactic.id) {
- tactic.name = newName;
- }
- return tactic;
- });
- await GM_setValue("ls_tactics", tacticsData);
- dropdownMenuTactics = dropdownMenuTactics.map((tactic) => {
- if (tactic.id === selectedTactic.id) {
- tactic.name = newName;
- }
- return tactic;
- });
- selectedOption.value = newName;
- selectedOption.textContent = newName;
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.renameAlert.replace("{}", oldName).replace("{}", newName));
- }
- async function updateTactic() {
- const outfieldPlayers = Array.from(document.querySelectorAll(OUTFIELD_PLAYERS_SELECTOR));
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- const selectedTactic = dropdownMenuTactics.find((tactic) => tactic.name === tacticsDropdownMenu.value);
- if (!selectedTactic) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.noTacticSelectedError);
- return;
- }
- const updatedCoordinates = outfieldPlayers.map((player) => [parseInt(player.style.left), parseInt(player.style.top)]);
- const newId = generateUniqueId(updatedCoordinates);
- const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
- const validationOutcome = await validateDuplicateTacticWithUpdatedCoord(newId, selectedTactic, tacticsData);
- if (validationOutcome === "unchanged") {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.noChangesMadeError);
- return;
- } else if (validationOutcome === "duplicate") {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.duplicateTacticError);
- return;
- }
- const result = await showAlert({
- text: USERSCRIPT_STRINGS.updateConfirmation.replace("{}", selectedTactic.name),
- icon: SWAL_CONSTANTS.ICONS.WARNING,
- showCancelButton: true,
- confirmButtonText: USERSCRIPT_STRINGS.updateConfirmButton,
- cancelButtonText: USERSCRIPT_STRINGS.cancelConfirmButton
- });
- if (!result.isConfirmed) {
- return;
- }
- for (const tactic of tacticsData.tactics) {
- if (tactic.id === selectedTactic.id) {
- tactic.coordinates = updatedCoordinates;
- tactic.id = newId;
- }
- }
- for (const tactic of dropdownMenuTactics) {
- if (tactic.id === selectedTactic.id) {
- tactic.coordinates = updatedCoordinates;
- tactic.id = newId;
- }
- }
- await GM_setValue("ls_tactics", tacticsData);
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.updateAlert.replace("{}", selectedTactic.name));
- }
- async function clearTactics() {
- const result = await showAlert({
- text: USERSCRIPT_STRINGS.clearConfirmation,
- icon: SWAL_CONSTANTS.ICONS.WARNING,
- showCancelButton: true,
- confirmButtonText: USERSCRIPT_STRINGS.clearTacticsConfirmButton,
- cancelButtonText: USERSCRIPT_STRINGS.cancelConfirmButton
- });
- if (!result.isConfirmed) {
- return;
- }
- await GM_setValue("ls_tactics", { tactics: [] });
- dropdownMenuTactics = [];
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- tacticsDropdownMenu.innerHTML = "";
- tacticsDropdownMenu.disabled = true;
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.clearAlert);
- }
- async function resetTactics() {
- const result = await showAlert({
- text: USERSCRIPT_STRINGS.resetConfirmation,
- icon: SWAL_CONSTANTS.ICONS.WARNING,
- showCancelButton: true,
- confirmButtonText: USERSCRIPT_STRINGS.resetTacticsConfirmButton,
- cancelButtonText: USERSCRIPT_STRINGS.cancelConfirmButton
- });
- if (!result.isConfirmed) {
- return;
- }
- const response = await fetch(DEFAULT_TACTICS_DATA_URL);
- const data = await response.json();
- const defaultTactics = data.tactics;
- await GM_setValue("ls_tactics", { tactics: defaultTactics });
- dropdownMenuTactics = defaultTactics;
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- tacticsDropdownMenu.innerHTML = "";
- tacticsDropdownMenu.appendChild(createPlaceholderOption());
- addTacticsToDropdownMenu(tacticsDropdownMenu, dropdownMenuTactics);
- tacticsDropdownMenu.disabled = false;
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.resetAlert);
- }
- async function importTactics() {
- const input = document.createElement("input");
- input.type = "file";
- input.accept = ".json";
- input.onchange = async function (event) {
- const file = event.target.files[0];
- const reader = new FileReader();
- reader.onload = async function (event) {
- let importedData;
- try {
- importedData = JSON.parse(event.target.result);
- } catch (e) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.invalidImportError);
- return;
- }
- if (!importedData || !Array.isArray(importedData.tactics)) {
- await showErrorMessage(USERSCRIPT_STRINGS.errorTitle, USERSCRIPT_STRINGS.invalidImportError);
- return;
- }
- const importedTactics = importedData.tactics;
- let existingTactics = await GM_getValue("ls_tactics", { tactics: [] });
- existingTactics = existingTactics.tactics;
- const mergedTactics = [...existingTactics];
- for (const importedTactic of importedTactics) {
- if (!existingTactics.some((tactic) => tactic.id === importedTactic.id)) {
- mergedTactics.push(importedTactic);
- }
- }
- await GM_setValue("ls_tactics", { tactics: mergedTactics });
- mergedTactics.sort((a, b) => a.name.localeCompare(b.name));
- dropdownMenuTactics = mergedTactics;
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- tacticsDropdownMenu.innerHTML = "";
- tacticsDropdownMenu.append(createPlaceholderOption());
- addTacticsToDropdownMenu(tacticsDropdownMenu, dropdownMenuTactics);
- tacticsDropdownMenu.disabled = false;
- await showSuccessMessage(USERSCRIPT_STRINGS.doneTitle, USERSCRIPT_STRINGS.importAlert);
- };
- reader.readAsText(file);
- };
- input.click();
- }
- function exportTactics() {
- const tactics = GM_getValue("ls_tactics", { tactics: [] });
- const tacticsJson = JSON.stringify(tactics);
- const blob = new Blob([tacticsJson], { type: "application/json" });
- const url = URL.createObjectURL(blob);
- const link = document.createElement("a");
- link.href = url;
- link.download = "tactics.json";
- const onFocus = () => {
- window.removeEventListener('focus', onFocus);
- URL.revokeObjectURL(url);
- };
- window.addEventListener('focus', onFocus, { once: true });
- link.click();
- }
- async function convertXmlToTacticJson(xmlString, tacticName) {
- const parser = new DOMParser();
- const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
- const parserError = xmlDoc.getElementsByTagName('parsererror');
- if (parserError.length > 0) {
- throw new Error('Invalid XML');
- }
- const posElements = Array.from(xmlDoc.getElementsByTagName('Pos'));
- const normalPosElements = posElements.filter(el => el.getAttribute('pos') === 'normal');
- const coordinates = normalPosElements.map(el => {
- const x = parseInt(el.getAttribute('x'));
- const y = parseInt(el.getAttribute('y'));
- const htmlLeft = x - 7;
- const htmlTop = y - 9;
- return [htmlLeft, htmlTop];
- });
- return {
- name: tacticName,
- coordinates: coordinates
- };
- }
- function createAddNewTacticButton() {
- const button = document.createElement("button");
- setUpButton(button, "add_tactic_button", USERSCRIPT_STRINGS.addButton);
- button.addEventListener("click", function () {
- addNewTactic().catch((_) => { });
- });
- return button;
- }
- function createAddNewTacticWithXmlButton() {
- const button = document.createElement("button");
- setUpButton(button, "add_tactic_with_xml_button", USERSCRIPT_STRINGS.addWithXmlButton);
- button.addEventListener("click", function () {
- addNewTacticWithXml().catch((_) => { });
- });
- return button;
- }
- function createDeleteTacticButton() {
- const button = document.createElement("button");
- setUpButton(button, "delete_tactic_button", USERSCRIPT_STRINGS.deleteButton);
- button.addEventListener("click", function () {
- deleteTactic().catch((_) => { });
- });
- return button;
- }
- function createRenameTacticButton() {
- const button = document.createElement("button");
- setUpButton(button, "rename_tactic_button", USERSCRIPT_STRINGS.renameButton);
- button.addEventListener("click", function () {
- renameTactic().catch((_) => { });
- });
- return button;
- }
- function createUpdateTacticButton() {
- const button = document.createElement("button");
- setUpButton(button, "update_tactic_button", USERSCRIPT_STRINGS.updateButton);
- button.addEventListener("click", function () {
- updateTactic().catch((_) => { });
- });
- return button;
- }
- function createClearTacticsButton() {
- const button = document.createElement("button");
- setUpButton(button, "clear_tactics_button", USERSCRIPT_STRINGS.clearButton);
- button.addEventListener("click", function () {
- clearTactics().catch((_) => { });
- });
- return button;
- }
- function createResetTacticsButton() {
- const button = document.createElement("button");
- setUpButton(button, "reset_tactics_button", USERSCRIPT_STRINGS.resetButton);
- button.addEventListener("click", function () {
- resetTactics().catch((_) => { });
- });
- return button;
- }
- function createImportTacticsButton() {
- const button = document.createElement("button");
- setUpButton(button, "import_tactics_button", USERSCRIPT_STRINGS.importButton);
- button.addEventListener("click", function () {
- importTactics().catch((_) => { });
- });
- return button;
- }
- function createExportTacticsButton() {
- const button = document.createElement("button");
- setUpButton(button, "export_tactics_button", USERSCRIPT_STRINGS.exportButton);
- button.addEventListener("click", function () {
- exportTactics();
- });
- return button;
- }
- async function checkVersion() {
- const storedVersion = GM_getValue(VERSION_KEY, null);
- if (!storedVersion || storedVersion !== VERSION) {
- await showWelcomeMessage();
- GM_setValue(VERSION_KEY, VERSION);
- }
- }
- async function showWelcomeMessage() {
- await showAlert({
- html: `
- <div style="text-align: left; margin: 1em 0;">
- <p>${USERSCRIPT_STRINGS.welcomeMessage}</p>
- </div>
- `,
- icon: 'info',
- confirmButtonText: USERSCRIPT_STRINGS.welcomeGotIt,
- customClass: {
- popup: 'swal-mz-popup',
- confirmButton: 'swal-mz-confirm'
- },
- showClass: {
- popup: 'swal-mz-popup modalFadeIn'
- },
- hideClass: {
- popup: 'modalFadeOut'
- }
- });
- }
- function playRandomAudio(audios) {
- if (audios.length === 0) {
- return;
- }
- const randomIdx = Math.floor(Math.random() * audios.length);
- const activeAudio = audios.splice(randomIdx, 1)[0];
- playAudio(activeAudio, audios);
- return activeAudio;
- }
- function playAudio(currAudio, audios) {
- currAudio.play();
- currAudio.onended = function () {
- playRandomAudio(audios);
- };
- }
- function pauseAudio(audio) {
- if (audio) {
- audio.pause();
- audio.currentTime = 0;
- }
- }
- function updateAudioIcon(button, isPlaying) {
- button.textContent = isPlaying ? "⏸️" : "🔊";
- }
- function createAudioButton() {
- const button = document.createElement("button");
- setUpButton(button, "audio_button", "🔊");
- const audioUrls = [
- "https://ia801901.us.archive.org/31/items/corp.-palm-mall-01-palm-mall/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20Palm%20Mall%20-%2003%20Special%20Discount.mp3",
- "https://ia801901.us.archive.org/31/items/corp.-palm-mall-01-palm-mall/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20Palm%20Mall%20-%2004%20First%20Floor.mp3",
- "https://ia801901.us.archive.org/31/items/corp.-palm-mall-01-palm-mall/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20Palm%20Mall%20-%2006%20Second%20Floor.mp3",
- "https://ia801901.us.archive.org/7/items/palm-mall-mars-remastered/%E7%8C%AB%20%E3%82%B7%20Corp.%20%26%20SEPHORA%E8%84%B3%E3%83%90%E3%82%A4%E3%83%96%E3%82%B9%20-%20Palm%20Mall%20Mars%20%28remastered%29%20-%2006%20Second%20floor-%20%ED%99%98%EB%8C%80%20%26%20%EC%9D%8C%EC%95%85.mp3",
- "https://ia801901.us.archive.org/7/items/palm-mall-mars-remastered/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20Palm%20Mall%20Mars%20%28remastered%29%20-%2001%20%E3%82%B9%E3%82%AD%E3%83%9D%E3%83%BC%E3%83%AB%E7%A9%BA%E6%B8%AFPlaza.mp3",
- "https://ia801901.us.archive.org/7/items/palm-mall-mars-remastered/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20Palm%20Mall%20Mars%20%28remastered%29%20-%2009%20Sembikiya%20Restaurant.mp3",
- "https://ia804504.us.archive.org/20/items/5-wn9896/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97%20%40%20%E3%83%98%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%20-%2001%20FORUM%20%E6%B6%88%E8%B2%BB%E8%80%85-kuluttaja-.mp3",
- "https://ia904504.us.archive.org/20/items/5-wn9896/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97%20%40%20%E3%83%98%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%20-%2002%20Pelican%20Self%20Storage%20-Tilaa%20Kaikelle-.mp3",
- "https://ia904504.us.archive.org/20/items/5-wn9896/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97%20%40%20%E3%83%98%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%20-%2003%20%E8%B2%B7%E3%81%86%40JUMBO%20-Kauppakeskus-.mp3",
- "https://ia904504.us.archive.org/20/items/5-wn9896/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97%20%40%20%E3%83%98%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%20-%2005%20Hesburger%20%E6%98%A0%E7%94%BB%E9%A4%A8%20-hampurilainen-.mp3",
- "https://ia804504.us.archive.org/20/items/5-wn9896/%E7%8C%AB%20%E3%82%B7%20Corp.%20-%20%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97%20%40%20%E3%83%98%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%20-%2006%20%E9%83%BD%E5%B8%82%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9%E3%83%A0%20Consumer%20-kahvi-.mp3"
- ];
- const audios = audioUrls.map(url => new Audio(url));
- let isPlaying = false;
- let currentAudio = null;
- button.addEventListener("click", function () {
- if (!isPlaying) {
- currentAudio = playRandomAudio(audios);
- isPlaying = true;
- } else {
- pauseAudio(currentAudio);
- isPlaying = false;
- }
- updateAudioIcon(button, isPlaying);
- });
- return button;
- }
- function createMainContainer() {
- const container = document.createElement("div");
- container.id = "mz_tactics_panel";
- container.classList.add("mz-panel");
- const tacticGroup = document.createElement("div");
- tacticGroup.classList.add("mz-group");
- const mainTitle = document.createElement("h2");
- mainTitle.classList.add("mz-group-main-title");
- const titleText = document.createElement("span");
- titleText.textContent = "MZ Tactics Manager ";
- mainTitle.appendChild(titleText);
- const authorText = document.createElement("span");
- authorText.textContent = "v10.1.0";
- authorText.classList.add("mz-version-text");
- mainTitle.appendChild(authorText);
- const dropdownSection = document.createElement("div");
- const tacticsDropdownMenuLabel = createDropdownMenuLabel("tactics_dropdown_menu_label");
- const tacticsDropdownMenu = createTacticsDropdownMenu();
- const tacticsDropdownGroup = createLabelDropdownMenuGroup(tacticsDropdownMenuLabel, tacticsDropdownMenu);
- dropdownSection.appendChild(tacticsDropdownGroup);
- const buttonsSection = document.createElement("div");
- buttonsSection.style.marginTop = "10px";
- const addNewTacticBtn = createAddNewTacticButton();
- const addNewTacticWithXmlBtn = createAddNewTacticWithXmlButton();
- const deleteTacticBtn = createDeleteTacticButton();
- const renameTacticBtn = createRenameTacticButton();
- const updateTacticBtn = createUpdateTacticButton();
- const clearTacticsBtn = createClearTacticsButton();
- const resetTacticsBtn = createResetTacticsButton();
- const importTacticsBtn = createImportTacticsButton();
- const exportTacticsBtn = createExportTacticsButton();
- appendChildren(buttonsSection, [
- addNewTacticBtn,
- addNewTacticWithXmlBtn,
- deleteTacticBtn,
- renameTacticBtn,
- updateTacticBtn,
- clearTacticsBtn,
- resetTacticsBtn,
- importTacticsBtn,
- exportTacticsBtn
- ]);
- appendChildren(tacticGroup, [
- mainTitle,
- dropdownSection,
- buttonsSection,
- createHiddenTriggerButton()
- ]);
- const otherGroup = document.createElement("div");
- otherGroup.classList.add("mz-group");
- const otherContainer = document.createElement("div");
- otherContainer.style.display = "flex";
- otherContainer.style.justifyContent = "space-between";
- otherContainer.style.alignItems = "center";
- otherContainer.style.width = "100%";
- const otherLeftGroup = document.createElement("div");
- otherLeftGroup.style.display = "flex";
- otherLeftGroup.style.alignItems = "center";
- const usefulLinksBtn = createUsefulLinksButton();
- const aboutBtn = createAboutButton();
- const audioBtn = createAudioButton();
- appendChildren(otherLeftGroup, [usefulLinksBtn, aboutBtn, audioBtn]);
- const otherRightGroup = document.createElement("div");
- otherRightGroup.style.display = "flex";
- otherRightGroup.style.alignItems = "center";
- const languageDropdownMenuLabel = createDropdownMenuLabel("language_dropdown_menu_label");
- const languageDropdownMenu = createLanguageDropdownMenu();
- const languageDropdownGroup = createLabelDropdownMenuGroup(languageDropdownMenuLabel, languageDropdownMenu);
- const flagImage = createFlagImage();
- appendChildren(otherRightGroup, [languageDropdownGroup, flagImage]);
- appendChildren(otherContainer, [otherLeftGroup, otherRightGroup]);
- appendChildren(otherGroup, [otherContainer]);
- appendChildren(container, [tacticGroup, otherGroup]);
- return container;
- }
- function createHiddenTriggerButton() {
- const button = document.createElement("button");
- button.id = "hidden_trigger_button";
- button.textContent = "";
- button.style.visibility = "hidden";
- button.addEventListener("click", function () {
- const tacticsPresetInfo = {
- elem: document.getElementById("tactics_preset"),
- resetValue: "5-3-2"
- }
- tacticsPresetInfo.elem.value = tacticsPresetInfo.resetValue;
- tacticsPresetInfo.elem.dispatchEvent(new Event("change"));
- });
- return button;
- }
- function insertAfterElement(something, element) {
- element.parentNode.insertBefore(something, element.nextSibling);
- }
- function appendChildren(parent, children) {
- children.forEach((ch) => {
- parent.appendChild(ch);
- });
- }
- function setUpButton(button, id, textContent) {
- button.id = id;
- button.classList.add('mzbtn');
- button.textContent = textContent;
- }
- function createTacticsDropdownMenu() {
- const dropdown = document.createElement("select");
- setUpDropdownMenu(dropdown, "tactics_dropdown_menu");
- appendChildren(dropdown, [createPlaceholderOption()]);
- return dropdown;
- }
- function createDropdownMenuLabel(labelId) {
- const label = document.createElement("span");
- setUpDropdownMenuLabel(label, labelId, USERSCRIPT_STRINGS.languageDropdownMenuLabel);
- return label;
- }
- function createLabelDropdownMenuGroup(label, dropdown) {
- const group = document.createElement("div");
- group.classList.add('dropdown-group');
- group.appendChild(label);
- group.appendChild(dropdown);
- return group;
- }
- function setUpDropdownMenu(dropdown, id) {
- dropdown.id = id;
- }
- function createPlaceholderOption() {
- const placeholderOption = document.createElement("option");
- placeholderOption.value = "";
- placeholderOption.text = "";
- placeholderOption.disabled = true;
- placeholderOption.selected = true;
- return placeholderOption;
- }
- function addTacticsToDropdownMenu(dropdown, tactics) {
- for (const tactic of tactics) {
- const option = document.createElement("option");
- option.value = tactic.name;
- option.text = tactic.name;
- dropdown.appendChild(option);
- }
- }
- function setUpDropdownMenuLabel(description, id, textContent) {
- description.id = id;
- description.textContent = textContent;
- }
- function createLanguageDropdownMenu() {
- const dropdown = document.createElement("select");
- setUpDropdownMenu(dropdown, "language_dropdown_menu");
- for (const lang of LANGUAGES) {
- const option = document.createElement("option");
- option.value = lang.code;
- option.textContent = lang.name;
- if (lang.code === activeLanguage) {
- option.selected = true;
- }
- dropdown.appendChild(option);
- }
- dropdown.addEventListener("change", function () {
- changeLanguage(this.value).catch((_) => { });
- });
- return dropdown;
- }
- function createFlagImage() {
- const img = document.createElement("img");
- img.id = "language_flag";
- const activeLang = LANGUAGES.find((lang) => lang.code === activeLanguage);
- if (activeLang) {
- img.src = activeLang.flag;
- }
- return img;
- }
- function getActiveLanguage() {
- let language = GM_getValue("language");
- if (!language) {
- let browserLanguage = navigator.language || "en";
- browserLanguage = browserLanguage.split("-")[0];
- const languageExists = LANGUAGES.some((lang) => lang.code === browserLanguage);
- language = languageExists ? browserLanguage : "en";
- }
- return language;
- }
- function updateTranslation() {
- for (const key in USERSCRIPT_STRINGS) {
- USERSCRIPT_STRINGS[key] = i18next.t(key);
- }
- for (const id in ELEMENT_STRING_KEYS) {
- const element = document.getElementById(id);
- if (id === "info_modal_info_text" || id === "info_modal_feedback_text") {
- if (element) element.innerHTML = USERSCRIPT_STRINGS[ELEMENT_STRING_KEYS[id]];
- } else if (element) {
- element.textContent = USERSCRIPT_STRINGS[ELEMENT_STRING_KEYS[id]];
- }
- }
- }
- async function changeLanguage(languageCode) {
- try {
- const translationDataUrl = LANG_DATA_BASE_URL + languageCode + ".json";
- const translations = await (await fetch(translationDataUrl)).json();
- i18next.changeLanguage(languageCode);
- i18next.addResourceBundle(languageCode, "translation", translations);
- GM_setValue("language", languageCode);
- updateTranslation();
- const language = LANGUAGES.find((lang) => lang.code === languageCode);
- if (language) {
- const flagImage = document.getElementById("language_flag");
- if (flagImage) flagImage.src = language.flag;
- }
- } catch (_e) { }
- }
- function generateUniqueId(coordinates) {
- const sortedCoordinates = coordinates.sort((a, b) => a[1] - b[1] || a[0] - b[0]);
- const coordString = sortedCoordinates.map((coord) => coord[1] + "_" + coord[0]).join("_");
- return sha256Hash(coordString);
- }
- function createUsefulLinksModal() {
- const modal = document.createElement("div");
- setUpModal(modal, "useful_links_modal");
- const modalContent = createUsefulLinksModalContent();
- modal.appendChild(modalContent);
- return modal;
- }
- function createUsefulLinksModalContent() {
- const modalContent = document.createElement("div");
- styleModalContent(modalContent);
- const usefulContent = createUsefulContent();
- const resources = new Map([
- ["gewlaht - BoooM", "https://www.managerzone.com/?p=forum&sub=topic&topic_id=11415137&forum_id=49&sport=soccer"],
- ["taktikskola by honken91", "https://www.managerzone.com/?p=forum&sub=topic&topic_id=12653892&forum_id=4&sport=soccer"],
- ["peto - mix de dibujos", "https://www.managerzone.com/?p=forum&sub=topic&topic_id=12196312&forum_id=255&sport=soccer"],
- ["The Zone Chile", "https://www.managerzone.com/thezone/paper.php?paper_id=18036&page=9&sport=soccer"],
- ["Tactics guide by lukasz87o/filipek4", "https://www.managerzone.com/?p=forum&sub=topic&topic_id=12766444&forum_id=12&sport=soccer&share_sport=soccer"],
- ["MZExtension/van.mz.playerAdvanced by vanjoge", "https://greasyfork.org/pt-BR/scripts/373382-van-mz-playeradvanced"],
- ["Mazyar Userscript", "https://greasyfork.org/pt-BR/scripts/476290-mazyar"],
- ["Stats Xente Userscript", "https://greasyfork.org/pt-BR/scripts/491442-stats-xente-script"],
- ["More userscripts", "https://greasyfork.org/pt-BR/users/1088808-douglasdotv"]
- ]);
- const usefulLinksList = createLinksList(resources);
- modalContent.appendChild(usefulContent);
- modalContent.appendChild(usefulLinksList);
- return modalContent;
- }
- function createUsefulContent() {
- const usefulContent = document.createElement("p");
- usefulContent.id = "useful_content";
- usefulContent.textContent = "";
- return usefulContent;
- }
- function createLinksList(hrefs) {
- const list = document.createElement("ul");
- hrefs.forEach((href, title) => {
- const listItem = document.createElement("li");
- const link = document.createElement("a");
- link.href = href;
- link.textContent = title;
- listItem.appendChild(link);
- list.appendChild(listItem);
- });
- return list;
- }
- function setUsefulLinksModal() {
- usefulLinksModal = createUsefulLinksModal();
- document.body.appendChild(usefulLinksModal);
- }
- function createInfoModal() {
- const modal = document.createElement("div");
- setUpModal(modal, "info_modal");
- const modalContent = createModalContent();
- modal.appendChild(modalContent);
- return modal;
- }
- function createModalContent() {
- const modalContent = document.createElement("div");
- styleModalContent(modalContent);
- const title = createTitle();
- const infoText = createInfoText();
- const feedbackText = createFeedbackText();
- modalContent.appendChild(title);
- modalContent.appendChild(infoText);
- modalContent.appendChild(feedbackText);
- return modalContent;
- }
- function createTitle() {
- const title = document.createElement("h2");
- title.id = "info_modal_title";
- title.textContent = "";
- title.style.fontSize = "24px";
- title.style.fontWeight = "bold";
- title.style.marginBottom = "20px";
- return title;
- }
- function createInfoText() {
- const infoText = document.createElement("p");
- infoText.id = "info_modal_info_text";
- infoText.innerHTML = USERSCRIPT_STRINGS.modalContentInfoText;
- return infoText;
- }
- function createFeedbackText() {
- const feedbackText = document.createElement("p");
- feedbackText.id = "info_modal_feedback_text";
- feedbackText.innerHTML = USERSCRIPT_STRINGS.modalContentFeedbackText;
- return feedbackText;
- }
- function setInfoModal() {
- infoModal = createInfoModal();
- document.body.appendChild(infoModal);
- }
- function setUpModal(modal, id) {
- modal.id = id;
- modal.style.display = "none";
- modal.style.position = "fixed";
- modal.style.zIndex = "1";
- modal.style.left = "50%";
- modal.style.top = "50%";
- modal.style.transform = "translate(-50%, -50%)";
- modal.style.opacity = "0";
- modal.style.transition = "opacity 0.5s ease-in-out";
- }
- function styleModalContent(content) {
- content.classList.add('swal-mz-content');
- }
- function toggleModal(modal) {
- if (modal.style.display === "none" || modal.style.opacity === "0") {
- showModal(modal);
- } else {
- hideModal(modal);
- }
- }
- function showModal(modal) {
- modal.style.display = "block";
- setTimeout(function () {
- modal.style.opacity = "1";
- }, 0);
- }
- function hideModal(modal) {
- modal.style.opacity = "0";
- setTimeout(function () {
- modal.style.display = "none";
- }, 500);
- }
- function setUpModalsWindowClickListener() {
- window.addEventListener("click", function (event) {
- if (usefulLinksModal.style.display === "block" && !usefulLinksModal.contains(event.target)) {
- hideModal(usefulLinksModal);
- }
- if (infoModal.style.display === "block" && !infoModal.contains(event.target)) {
- hideModal(infoModal);
- }
- });
- }
- function createUsefulLinksButton() {
- const button = document.createElement("button");
- setUpButton(button, "useful_links_button", USERSCRIPT_STRINGS.usefulLinksButton);
- button.addEventListener("click", function (event) {
- event.stopPropagation();
- toggleModal(usefulLinksModal);
- });
- return button;
- }
- function createAboutButton() {
- const button = document.createElement("button");
- setUpButton(button, "about_button", USERSCRIPT_STRINGS.aboutButton);
- button.addEventListener("click", function (event) {
- event.stopPropagation();
- toggleModal(infoModal);
- });
- return button;
- }
- function initialize() {
- const tacticsBox = document.getElementById("tactics_box");
- if (tacticsBox) {
- activeLanguage = getActiveLanguage();
- i18next.init({
- lng: activeLanguage,
- resources: {
- [activeLanguage]: {
- translation: {}
- }
- }
- }).then(async () => {
- const res = await fetch(LANG_DATA_BASE_URL + activeLanguage + ".json");
- const json = await res.json();
- i18next.addResourceBundle(activeLanguage, "translation", json);
- await checkVersion();
- const mainContainer = createMainContainer();
- if (isFootball()) {
- insertAfterElement(mainContainer, tacticsBox);
- }
- fetchTacticsFromGMStorage().then((data) => {
- const tacticsDropdownMenu = document.getElementById("tactics_dropdown_menu");
- tacticsDropdownMenu.addEventListener('click', function () {
- if (this.value) {
- handleTacticsSelection(this.value);
- }
- });
- dropdownMenuTactics = data.tactics;
- dropdownMenuTactics.sort((a, b) => a.name.localeCompare(b.name));
- addTacticsToDropdownMenu(tacticsDropdownMenu, dropdownMenuTactics);
- tacticsDropdownMenu.addEventListener("change", function () {
- handleTacticsSelection(this.value);
- });
- }).catch((_) => { });
- setInfoModal();
- setUsefulLinksModal();
- setUpModalsWindowClickListener();
- updateTranslation();
- });
- }
- }
- window.addEventListener("load", function () {
- initialize();
- });
- })();