MZ Axis

Based on the Murder script, add copy-paste functions and move the coordinate axis to the center field.

目前為 2024-03-13 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name MZ Axis
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Based on the Murder script, add copy-paste functions and move the coordinate axis to the center field.
  6. // @author jrcl
  7. // @match https://www.managerzone.com/?p=tactics*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. var coordsContainerAux = document.getElementById('formation-container');
  16. var input = '<input id=\"**id**\" type=\"text\" style=\"width: 20px\" value=\"**val**\">';
  17. var _x = '--';
  18. var _y = '--';
  19.  
  20. var formation = [];
  21.  
  22. if(allowed()) {
  23. var coordsContainer = document.getElementById('formation-container');
  24. var m = "<div><span style=\"font-weight: 600\">" + allowed() + "</span></div>";
  25. wrapCoordinates();
  26. var node = createElementFromHTML(m);
  27. coordsContainer.appendChild(node);
  28. }
  29. else if(isSoccer()) {
  30. var murder = 'murder';
  31. var test = window.btoa(murder);
  32. var test2 = window.atob(test);
  33. enableActionsForAllTabs();
  34. enableActionForAltTactics();
  35. addEventsToPlayers();
  36. drawCoordinates();
  37. document.addEventListener("keydown", setKeys);
  38. document.addEventListener("click", clickEvent);
  39. }
  40.  
  41. function addEventsToPlayers() {
  42. var checkExist = setInterval(function() {
  43. if (document.getElementsByClassName('fieldpos fieldpos-ok ui-draggable').length) {
  44. var players = document.getElementsByClassName('fieldpos fieldpos-ok ui-draggable');
  45. for (var i = 0; i < players.length; ++i) {
  46. players[i].addEventListener('click', setCoordsLabel, false);
  47. players[i].addEventListener('keydown', setCoordsLabel, false);
  48. }
  49. clearInterval(checkExist);
  50. }
  51. }, 1000);
  52.  
  53. }
  54.  
  55. function setCoordsLabel(player) {
  56. getOffset(player.path[1]);
  57. drawCoordinates();
  58. }
  59.  
  60. function getOffset( el ) {
  61. _y = 101 - (el.offsetTop - 54);
  62. _x = el.offsetLeft - 97;
  63. }
  64.  
  65. function drawCoordinates() {
  66. let coord = document.getElementById('divCoords');
  67. if(coord) {
  68. coord.parentElement.removeChild(coord);
  69. }
  70.  
  71. var coordsContainer = document.getElementById('formation-container');
  72. var divCoords = "<div id=\"divCoords\"><span style=\"font-weight: 600\">Player position: **coords**</span>"+
  73. //"<span><input id=\"copyBtn\" type=\"button\" value=\"Copy\" onclick=\"copyFormation();\"/></span>" +
  74. "&nbsp;<span><button id=\"copyBtn\" onclick=\"copyFormation()\">Copy</button></span>" +
  75. "&nbsp;<span><button id=\"pasteBtn\" onclick=\"pasteFormation()\">Paste</button></span>" +
  76. // "<span><textarea id=\"txtFormation\" name=\"textarea\"></textarea></span>" +
  77. "</div>";
  78. wrapCoordinates();
  79. var node = createElementFromHTML(divCoords.replace('**coords**', _x + _y));
  80. coordsContainer.appendChild(node);
  81. applyCoordinates();
  82.  
  83. document.getElementById("copyBtn").onclick = copyFormation;
  84. document.getElementById("pasteBtn").onclick = pasteFormation;
  85.  
  86. }
  87.  
  88. function copyFormation() {
  89. formation = [];
  90. var player = document.querySelectorAll('.fieldpos.fieldpos-ok.ui-draggable:not(.substitute):not(.goalkeeper)');
  91. for (let i = 0; i < player.length; i++) {
  92. formation.push([Number((player[i].style.left).slice(0,-2)), Number((player[i].style.top).slice(0,-2))]);
  93. }
  94.  
  95. // order by top desc and left asc
  96. formation = formation.sort(function(a,b) { if (b[1] == a[1]) return a[0] - b[0]; else return b[1] - a[1]; })
  97.  
  98. let txtCoord = "";
  99. for (let coord of formation) {
  100. txtCoord += (coord[0] - 97) + "," + (155 - coord[1]) + '\n';
  101. }
  102.  
  103. navigator.clipboard.writeText(txtCoord)
  104. .then(() => {
  105. console.log('Formation copied to the clipboard');
  106. alert('Formation copied to the clipboard');
  107. })
  108. .catch(err => {
  109. console.error('Error copying to the clipboard:', err);
  110. })
  111. console.log(txtCoord);
  112. }
  113.  
  114. function pasteFormation() {
  115. navigator.clipboard.readText()
  116. .then(text => {
  117. console.log('Clipboard text:', text)
  118. // is xml content?
  119. if (text.search("xml") != -1) {
  120. // parse clipboard to xml file
  121. console.log('Cartesian coordinate system from XML file');
  122. let parser = new DOMParser();
  123. let xmlDoc = parser.parseFromString(text,"text/xml");
  124. formation = [];
  125. let pos = xmlDoc.getElementsByTagName("Pos")
  126. for (var i = 1; i < pos.length; i++) {
  127. formation.push([Number(pos[i].getAttribute("x")) - 7, Number(pos[i].getAttribute("y")) - 9]);
  128. }
  129.  
  130. formation = formation.sort(function(a,b) { if (b[1] == a[1]) return a[0] - b[0]; else return b[1] - a[1]; })
  131. setFormation();
  132. } else if (text.trim().split('\n').length == 10) { // is there 10 coord?
  133. console.log('Cartesian coordinate system from Clipboard');
  134. let coorXY = text.trim().split('\n')
  135.  
  136. formation = [];
  137. for (let pair of coorXY) {
  138. let [xAxis,yAxis] = pair.split(',');
  139. formation.push([Number(xAxis) + 97, 155 - Number(yAxis)]);
  140. }
  141.  
  142. formation = formation.sort(function(a,b) { if (b[1] == a[1]) return a[0] - b[0]; else return b[1] - a[1]; })
  143. setFormation();
  144. } else if (formation.length == 10) {
  145. console.log('Cartesian coordinate system from internal var');
  146. setFormation();
  147. } else {
  148. console.log("Nothing to do");
  149. }
  150.  
  151.  
  152. })
  153. .catch(err => {
  154. console.error('Error reading from the clipboard:', err)
  155. })
  156. }
  157.  
  158. function setFormation() {
  159. let player = document.querySelectorAll('.fieldpos.fieldpos-ok.ui-draggable:not(.substitute):not(.goalkeeper)');
  160.  
  161. if (formation.length == player.length) {
  162. // get an order
  163. let oldFormation = [];
  164. for (let i = 0; i < player.length; i++) {
  165. oldFormation.push([Number((player[i].style.left).slice(0,-2)), Number((player[i].style.top).slice(0,-2)), i]);
  166. }
  167.  
  168. oldFormation = oldFormation.sort(function(a,b) { if (b[1] == a[1]) return a[0] - b[0]; else return b[1] - a[1]; })
  169.  
  170. for (let i = 0; i < formation.length; i++) {
  171. player[oldFormation[i][2]].style.left = formation[i][0] + 'px';
  172. player[oldFormation[i][2]].style.top = formation[i][1] + 'px';
  173. }
  174. alert('Formation successfully copied');
  175. formation = []; // empty formation
  176. }
  177. }
  178.  
  179. function createElementFromHTML(htmlString) {
  180. var div = document.createElement('div');
  181. div.innerHTML = htmlString.trim();
  182.  
  183. // Change this to div.childNodes to support multiple top-level nodes
  184. return div.firstChild;
  185. }
  186.  
  187. function applyCoordinates() {
  188. var inpX = document.getElementById('inputX');
  189. var inpY = document.getElementById('inputY');
  190.  
  191. inpX.addEventListener('keyup', setPlayerPosition, false);
  192. inpY.addEventListener('keyup', setPlayerPosition, false);
  193. }
  194.  
  195. function setPlayerPosition(input) {
  196. var c = input.currentTarget.id === 'inputX' ? 'x' : 'y';
  197. let selectedInput = c === 'x' ? document.getElementById('inputX') : document.getElementById('inputY');
  198. //get selected player
  199. var players = document.getElementsByClassName('fieldpos fieldpos-ok ui-draggable ui-selected');
  200. var playerCollision = document.getElementsByClassName('fieldpos ui-selected fieldpos-collision');
  201. if(players.length) {
  202. let xVal = c === 'x' ? input.currentTarget.value : document.getElementById('inputX').value;
  203. let yVal = c === 'y' ? input.currentTarget.value : document.getElementById('inputY').value;
  204.  
  205. if(isInRange(c == 'x' ? xVal : yVal, c)) {
  206. removeBorder(selectedInput);
  207. players[0].style.left = (parseInt(xVal) + 97) + "px";
  208. players[0].style.top = (101 - parseInt(yVal) + 54) + "px";
  209. }
  210. else {
  211. addBorder(selectedInput);
  212. }
  213. }
  214. else if(playerCollision.length) {
  215. let xVal = c === 'x' ? input.currentTarget.value : document.getElementById('inputX').value;
  216. let yVal = c === 'y' ? input.currentTarget.value : document.getElementById('inputY').value;
  217.  
  218. if(isInRange(c == 'x' ? xVal : yVal, c)) {
  219. removeBorder(selectedInput);
  220. playerCollision[0].style.left = (parseInt(xVal) + 97) + "px";
  221. playerCollision[0].style.top = (101 - parseInt(yVal) + 54) + "px";
  222. }
  223. else {
  224. addBorder(selectedInput);
  225. }
  226. }
  227. }
  228.  
  229. function wrapCoordinates() {
  230. var inpX = input.replace('**id**','inputX').replace('**val**', _x);
  231. var inpY = input.replace('**id**','inputY').replace('**val**', _y);
  232. _x = '<span style=\"color: green\"> X: </span>' + inpX;
  233. _y = '<span style=\"color: blue\"> Y: </span>' + inpY;
  234. }
  235.  
  236. function isInRange(number, coordinate) {
  237. if(!isNaN(number)) {
  238. var integer = parseInt(number);
  239. if(coordinate == 'x') {
  240. return integer <= 96 && integer >= -96;
  241. }
  242. else if(coordinate == 'y') {
  243. return integer <= 101 && integer >= -157;
  244. }
  245. else {
  246. return false;
  247. }
  248. }
  249. else {
  250. return false;
  251. }
  252. }
  253.  
  254. function setKeys(key) {
  255. if((key.keyCode === 37 || key.keyCode === 38 || key.keyCode === 39 || key.keyCode === 40)
  256. && (key.currentTarget.activeElement.localName != 'input')) {
  257.  
  258. var players = document.getElementsByClassName('fieldpos fieldpos-ok ui-draggable ui-selected');
  259. var playerCollision = document.getElementsByClassName('fieldpos ui-selected fieldpos-collision');
  260. //player selected with or without collision
  261. if(players.length) {
  262. _y = 101 - (players[0].offsetTop - 54);
  263. _x = players[0].offsetLeft - 97;
  264. }
  265. else if (playerCollision.length) {
  266. _y = 101 - (playerCollision[0].offsetTop - 54);
  267. _x = playerCollision[0].offsetLeft - 97;
  268. }
  269. else {
  270. _y = '--';
  271. _x = '--';
  272. }
  273.  
  274. drawCoordinates();
  275. }
  276. }
  277.  
  278. function clickEvent(ev) {
  279. if(ev.currentTarget.activeElement.localName === 'select') {
  280. return false;
  281. }
  282. var players = document.getElementsByClassName('fieldpos fieldpos-ok ui-draggable ui-selected');
  283. var playerCollision = document.getElementsByClassName('fieldpos ui-selected fieldpos-collision');
  284. if(!players.length && !playerCollision.length) {
  285. _y = '--';
  286. _x = '--';
  287. drawCoordinates();
  288. }
  289. }
  290.  
  291. function enableActionsForAllTabs() {
  292. var tabs = document.getElementsByClassName('ui-state-default ui-corner-top');
  293. let ttta = document.getElementById('ttta');
  294. let tttb = document.getElementById('tttb');
  295. ttta.addEventListener('click',restart);
  296. tttb.addEventListener('click',restart);
  297.  
  298. for (var i = 0; i < tabs.length; ++i) {
  299. tabs[i].addEventListener("click", function() {
  300. addEventsToPlayers();
  301. enableActionForAltTactics();
  302. });
  303. }
  304. }
  305.  
  306. function enableActionForAltTactics() {
  307. var altTactics = document.getElementById('formation_select');
  308. altTactics.addEventListener('change',tacticChange);
  309. }
  310.  
  311. function tacticChange() {
  312. let resetBtn = document.getElementById('reset_formation');
  313. let copyBtn = document.getElementById('replace_starting_formation');
  314.  
  315. resetBtn.addEventListener('click',restart);
  316. copyBtn.addEventListener('click',restart);
  317.  
  318. restart();
  319. }
  320.  
  321. function restart() {
  322. _y = '--';
  323. _x = '--';
  324. addEventsToPlayers();
  325. drawCoordinates();
  326. }
  327.  
  328. function addBorder(input) {
  329. input.style.border = 'solid 4px red';
  330. }
  331. function allowed(){let G=!1,b=[{u:"ZGllZ29jYXBhbm8=",m:"VXN0ZWQgbm8gdGllbmUgcGVybWl0aWRvIHVzYXIgbGEgaGVycmFtaWVudGEgZGFkbyBxdWUgcG9zZWUgbeFzIGRlIHVuYSBjdWVudGEu"},{u:"bWF4d2VsbHNtYXJ0ODE=",m:"RWwgc2lzdGVtYSBoYSBkZXRlY3RhZG8gcXVlIHVzdGVkIGVzIGRlbWFzaWFkbyB0cmFtcG9zbyBwYXJhIHVzYXIgZXN0YSBoZXJyYW1pZW50YS4="},{u:"bHVra2s0MQ==",m:"VXN0ZWQgZXMgdW4gdHJhbXBvc28geSBubyB0aWVuZSBwZXJtaXRpZG8gdXNhciBsYSBoZXJyYW1pZW50YS4="},{u:"ZGFya2xpbmU=",m:"RWwgc2lzdGVtYSBoYSBkZXRlY3RhZG8gcXVlIHVzdGVkIGVzIHVuIHBlbG90dWRvIHkgbm8gdGllbmUgcGVybWl0aWRvIHVzYXIgbGEgaGVycmFtaWVudGEu"},{u:"a2luZXNpbzEw",m:"TG9zIHBlbG90dWRvcyBjb21vIHZvcyBubyB0aWVuZW4gcGVybWl0aWRvIHVzYXIgbGEgaGVycmFtaWVudGEgcG9yIGhhYmVyIGFycnVpbmFkbyBlbCBmb3JvLg=="},{u:"bXVyZGVy",m:"TG9zIHBlbG90dWRvcyBjb21vIHZvcyBubyB0aWVuZW4gcGVybWl0aWRvIHVzYXIgbGEgaGVycmFtaWVudGEgcG9yIGhhYmVyIGFycnVpbmFkbyBlbCBmb3JvLg=="}],V=document.getElementById("header-username").textContent;for(var g=0;g<b.length;++g)window.atob(b[g].u)===V&&(G=window.atob(b[g].m));return G}
  332. function removeBorder(input) {
  333. input.style.border = null;
  334. }
  335.  
  336. function isSoccer() {
  337. let response = false;
  338. let sport = document.getElementById('tactics_box');
  339. for(var i = 0; i < sport.classList.length; ++i) {
  340. if(sport.classList[i] == 'soccer') {
  341. response = true;
  342. }
  343. }
  344. return response;
  345. }
  346.  
  347. })();