MazyarTools

Mazyar Tools & Utilities

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/513041/1504558/MazyarTools.js

  1. // ==UserScript==
  2. // @name MazyarTools
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.1
  5. // @description Mazyar Tools & Utilities
  6. // @copyright z7z from managerzone.com
  7. // @author z7z from managerzone.com
  8. // @license MIT
  9. // @grant GM_xmlhttpRequest
  10. // @match https://www.managerzone.com/*
  11. // @match https://test.managerzone.com/*
  12. // @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com
  13. // @supportURL https://github.com/mz-ir/mazyar
  14. // ==/UserScript==
  15.  
  16. // --------------------------------------- Formatter -----------------------------
  17.  
  18. function mazyarFormatBigNumber(n, sep = " ") {
  19. if (n) {
  20. const numberString = n.toString();
  21. let formattedParts = [];
  22. for (let i = numberString.length - 1; i >= 0; i -= 3) {
  23. let part = numberString.substring(Math.max(i - 2, 0), i + 1);
  24. formattedParts.unshift(part);
  25. }
  26. return formattedParts.join(sep);
  27. }
  28. return "0";
  29. }
  30.  
  31. function mazyarFormatAverageAge(age, fractionDigits = 1) {
  32. if (age) {
  33. return age.toFixed(fractionDigits);
  34. }
  35. return "0.0";
  36. }
  37.  
  38. function mazyarFormatFileSize(b) {
  39. const s = 1024;
  40. let u = 0;
  41. while (b >= s || -b >= s) {
  42. b /= s;
  43. u++;
  44. }
  45. return (u ? b.toFixed(1) + " " : b) + " KMGTPEZY"[u] + "B";
  46. }
  47.  
  48. // -------------------------------- Parser -------------------------------------
  49.  
  50. function mazyarParseMzDate(dateString) {
  51. const [day, month, year] = dateString.split('-').map(Number);
  52. return new Date(year, month - 1, day);
  53. }
  54.  
  55. function mazyarParseMzDateTime(dateTimeString) {
  56. const [date, time] = dateTimeString.split(' ');
  57. const [day, month, year] = date.split('-').map(Number);
  58. const [hours, minutes] = time.split(':').map(Number);
  59. return new Date(year, month - 1, day, hours, minutes);
  60. }
  61.  
  62. function mazyarGenerateUuidV4() {
  63. return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
  64. const r = (Math.random() * 16) | 0,
  65. v = c == "x" ? r : (r & 0x3) | 0x8;
  66. return v.toString(16);
  67. });
  68. }
  69.  
  70. function mazyarIsFilterHitsValid(hits) {
  71. return typeof hits === "number" && hits >= 0;
  72. }
  73.  
  74. function mazyarHasDuplicates(array) {
  75. return new Set(array).size !== array.length;
  76. }
  77.  
  78. function mazyarExtractSportType(doc = document) {
  79. const zone = doc.querySelector("a#shortcut_link_thezone");
  80. if (zone) {
  81. return zone.href.indexOf("hockey") > -1 ? "hockey" : "soccer";
  82. }
  83. return "soccer";
  84. }
  85.  
  86. function mazyarExtractClubCurrency(doc) {
  87. const players = doc.getElementById("playerAltViewTable")?.querySelectorAll("tbody tr");
  88. if (players && players.length > 0) {
  89. const parts = players[0].querySelector("td:nth-child(3)")?.innerText.split(" ");
  90. return parts[parts.length - 1].trim();
  91. }
  92. return "";
  93. }
  94.  
  95. function mazyarExtractNationalCurrency(doc) {
  96. // works for both domestic and foreign countries
  97. const playerNode = doc.getElementById("thePlayers_0")?.querySelector("table tbody tr:nth-child(6)");
  98. if (playerNode) {
  99. const parts = playerNode.innerText.split(" ");
  100. return parts[parts.length - 1].trim();
  101. }
  102. return "";
  103. }
  104.  
  105. function mazyarExtractTeamId(link) {
  106. const regex = /tid=(\d+)/;
  107. const match = regex.exec(link);
  108. return match ? match[1] : null;
  109. }
  110.  
  111. function mazyarExtractPlayerIdFromProfileLink(link) {
  112. const regex = /pid=(\d+)/;
  113. const match = regex.exec(link);
  114. return match ? match[1] : null;
  115. }
  116.  
  117. function mazyarExtractMatchId(link) {
  118. const regex = /mid=(\d+)/;
  119. const match = regex.exec(link);
  120. return match ? match[1] : null;
  121. }
  122.  
  123. function mazyarExtractPlayerIdFromTransferMonitor(link) {
  124. const regex = /u=(\d+)/;
  125. const match = regex.exec(link);
  126. return match ? match[1] : null;
  127. }
  128.  
  129. function mazyarExtractPlayerIdFromContainer(player) {
  130. return player?.querySelector("h2 span.player_id_span")?.innerText;
  131. }
  132.  
  133. function mazyarIsMatchInProgress(resultText) {
  134. const scoreRegex = /\b(X|0|[1-9]\d*) - (X|0|[1-9]\d*)\b/;
  135. return !scoreRegex.test(resultText);
  136. }
  137.  
  138. function mazyarIsPlayerSentToCamp(doc) {
  139. return !!doc.querySelector(`#thePlayers_0 span.player_icon_wrapper i.fa-traffic-cone.tc-status-icon:not(.tc-status-icon--disabled)`);
  140. }
  141.  
  142. function mazyarExtractSkillNamesFromPlayerInfo(player) {
  143. const skills = player?.querySelectorAll("table.player_skills > tbody > tr > td > span.clippable");
  144. return [...skills].map((el) => el.innerText);
  145. }
  146.  
  147. function mazyarExtractSkillsFromScoutReport(section, skillList) {
  148. const skills = section.querySelectorAll("div.flex-grow-1 ul li.blurred span");
  149. return [...skills].map((el) => skillList.indexOf(el.innerText));
  150. }
  151.  
  152. function mazyarExtractStarsFromScoutReport(section) {
  153. return section.querySelectorAll(".stars i.lit")?.length;
  154. }
  155.  
  156. function mazyarExtractResidencyDaysAndPrice(doc = document) {
  157. if (!doc) {
  158. return { days: 0, price: '' };
  159. }
  160. const transfers = doc?.querySelector("div.baz > div > div.win_back > table.hitlist");
  161. const history = transfers?.querySelector("tbody");
  162. if (history?.children.length > 1) {
  163. const arrived = history?.lastChild?.querySelector("td")?.innerText;
  164. const days = Math.floor((new Date() - mazyarParseMzDate(arrived)) / 86_400_000);
  165. const price = history.lastChild?.querySelector("td:last-child")?.innerText;
  166. const currency = transfers?.querySelector("thead tr td:last-child")?.innerText?.match(/.*\((.*)\)/)?.[1];
  167. return { days, price: price + ' ' + currency };
  168. }
  169. return { days: -1, price: '' };
  170. }
  171.  
  172. async function mazyarExtractPlayerProfile(playerId) {
  173. const url = `https://${location.hostname}/?p=players&pid=${playerId}`;
  174. const doc = await mazyarFetchHtml(url);
  175. if (doc) {
  176. const { days, price } = mazyarExtractResidencyDaysAndPrice(doc);
  177. const camp = mazyarIsPlayerSentToCamp(doc);
  178. const skills = doc.querySelectorAll("#thePlayers_0 table.player_skills tbody tr");
  179. let i = 0;
  180. const maxed = [];
  181. for (const skill of skills) {
  182. if (skill.querySelector(".maxed")) {
  183. maxed.push(i);
  184. }
  185. i++;
  186. }
  187. return {
  188. pid: playerId,
  189. maxed,
  190. days,
  191. price,
  192. camp,
  193. };
  194. }
  195. return null;
  196. }
  197.  
  198. async function mazyarExtractPlayerScoutReport(pid, skills, sport = "soccer") {
  199. const url = `https://${location.hostname}/ajax.php?p=players&sub=scout_report&pid=${pid}&sport=${sport}`;
  200. const doc = await mazyarFetchHtml(url);
  201. if (doc) {
  202. const report = doc.querySelectorAll(".paper-content.clearfix dl dd");
  203. if (report.length == 3) {
  204. const high = mazyarExtractStarsFromScoutReport(report[0]);
  205. const highSkills = mazyarExtractSkillsFromScoutReport(report[0], skills);
  206. const low = mazyarExtractStarsFromScoutReport(report[1]);
  207. const lowSkills = mazyarExtractSkillsFromScoutReport(report[1], skills);
  208. const trainingSpeed = mazyarExtractStarsFromScoutReport(report[2]);
  209. return {
  210. pid,
  211. H: high,
  212. HS: highSkills,
  213. L: low,
  214. LS: lowSkills,
  215. S: trainingSpeed,
  216. };
  217. }
  218. }
  219. return null;
  220. }
  221.  
  222. function mazyarExtractClubPlayersDetails(doc, currency) {
  223. const players = [];
  224. const playerNodes = doc.querySelectorAll("table#playerAltViewTable tr");
  225. for (const playerNode of playerNodes) {
  226. const age = playerNode.querySelector("td:nth-child(5)")?.innerText.replace(/\s/g, "");
  227. if (age) {
  228. const value = playerNode.querySelector("td:nth-child(3)")?.innerText.replaceAll(currency, "").replace(/\s/g, "");
  229. const shirtNumber = playerNode.querySelector("td:nth-child(0)")?.innerText.replace(/\s/g, "");
  230. const pid = playerNode.querySelector("a")?.href;
  231. players.push({
  232. shirtNumber,
  233. age: parseInt(age, 10),
  234. value: parseInt(value, 10),
  235. id: mazyarExtractPlayerIdFromProfileLink(pid),
  236. });
  237. }
  238. }
  239. return players;
  240. }
  241.  
  242. function mazyarExtractNumberOfFlags(infoTable) {
  243. const images = infoTable.getElementsByTagName("img");
  244. return images ? [...images].filter((img) => img.src.indexOf("/flags/") > -1).length : 0;
  245. }
  246.  
  247. function mazyarIsPlayerDomestic(infoTable) {
  248. return mazyarExtractNumberOfFlags(infoTable) === 1;
  249. }
  250.  
  251. function mazyarExtractNationalPlayersDetails(doc, currency) {
  252. const players = [];
  253. const playerNodes = doc.querySelectorAll("div.playerContainer");
  254. for (const playerNode of playerNodes) {
  255. const id = mazyarExtractPlayerIdFromProfileLink(playerNode.querySelector("h2 a")?.href);
  256. const infoTable = playerNode.querySelector("div.dg_playerview_info table");
  257. const age = infoTable.querySelector("tbody tr:nth-child(1) td strong").innerText;
  258. const selector = mazyarIsPlayerDomestic(infoTable) ? "tbody tr:nth-child(5) td span" : "tbody tr:nth-child(6) td span";
  259. const value = infoTable.querySelector(selector)?.innerText.replaceAll(currency, "").replace(/\s/g, "");
  260. players.push({
  261. age: parseInt(age, 10),
  262. value: parseInt(value, 10),
  263. id,
  264. });
  265. }
  266. return players;
  267. }
  268.  
  269. function mazyarGetNumberOfPlayers(players, ageLow = 0, ageHigh = 99) {
  270. return players.filter((player) => player.age <= ageHigh && player.age >= ageLow).length;
  271. }
  272.  
  273. // ----------------------------------- Fetch ---------------------------------
  274.  
  275. async function mazyarFetchHtmlWithGM(url, timeout = 10) {
  276. try {
  277. const response = await new Promise((resolve, reject) => {
  278. GM_xmlhttpRequest({
  279. url,
  280. // timeout: timeout * 1000,
  281. onload: (resp) => resolve(resp),
  282. onerror: reject
  283. });
  284. });
  285. const parser = new DOMParser();
  286. return parser.parseFromString(response.responseText, "text/html");
  287. } catch (error) {
  288. console.warn(error);
  289. return null;
  290. }
  291. }
  292.  
  293. async function mazyarFetchHtml(url) {
  294. return await fetch(url)
  295. .then((resp) => resp.text())
  296. .then((content) => {
  297. const parser = new DOMParser();
  298. return parser.parseFromString(content, "text/html");
  299. })
  300. .catch((error) => {
  301. console.warn(error);
  302. return null;
  303. });
  304. }
  305.  
  306. async function mazyarFetchXml(url) {
  307. return await fetch(url)
  308. .then((resp) => resp.text())
  309. .then((content) => {
  310. const parser = new DOMParser();
  311. return parser.parseFromString(content, "text/xml");
  312. })
  313. .catch((error) => {
  314. console.warn(error);
  315. return null;
  316. });
  317. }
  318.  
  319. async function mazyarFetchJson(url) {
  320. return await fetch(url)
  321. .then((resp) => resp.json())
  322. .catch((error) => {
  323. console.warn(error);
  324. return null;
  325. });
  326. }
  327.  
  328. function mazyarGetSquadSummaryUrl(tid) {
  329. return `https://${location.hostname}/?p=players&sub=alt&tid=${tid}`;
  330. }
  331.  
  332. function mazyarExtractSquadSummaryDetails(players, sport = "soccer") {
  333. if (!players) {
  334. return [];
  335. }
  336. const rows = [];
  337. if (sport === "hockey") {
  338. {
  339. const all = mazyarFilterPlayers(players);
  340. const top21 = mazyarFilterPlayers(players, 21);
  341. rows.push({
  342. title: "All",
  343. count: players.length,
  344. all: all.values,
  345. allAge: all.avgAge,
  346. top21: top21.values,
  347. top21Age: top21.avgAge,
  348. });
  349. }
  350. {
  351. const all = mazyarFilterPlayers(players, 0, 0, 23);
  352. const top21 = mazyarFilterPlayers(players, 21, 0, 23);
  353. rows.push({
  354. title: "U23",
  355. count: mazyarGetNumberOfPlayers(players, 0, 23),
  356. all: all.values,
  357. allAge: all.avgAge,
  358. top21: top21.values,
  359. top21Age: top21.avgAge,
  360. });
  361. }
  362. {
  363. const all = mazyarFilterPlayers(players, 0, 0, 21);
  364. const top21 = mazyarFilterPlayers(players, 21, 0, 21);
  365. rows.push({
  366. title: "U21",
  367. count: mazyarGetNumberOfPlayers(players, 0, 21),
  368. all: all.values,
  369. allAge: all.avgAge,
  370. top21: top21.values,
  371. top21Age: top21.avgAge,
  372. });
  373. }
  374. {
  375. const all = mazyarFilterPlayers(players, 0, 0, 18);
  376. const top21 = mazyarFilterPlayers(players, 21, 0, 18);
  377. rows.push({
  378. title: "U18",
  379. count: mazyarGetNumberOfPlayers(players, 0, 18),
  380. all: all.values,
  381. allAge: all.avgAge,
  382. top21: top21.values,
  383. top21Age: top21.avgAge,
  384. });
  385. }
  386. } else {
  387. {
  388. const all = mazyarFilterPlayers(players);
  389. const top16 = mazyarFilterPlayers(players, 16);
  390. const top11 = mazyarFilterPlayers(players, 11);
  391. rows.push({
  392. title: "All",
  393. count: players.length,
  394. all: all.values,
  395. allAge: all.avgAge,
  396. top16: top16.values,
  397. top16Age: top16.avgAge,
  398. top11: top11.values,
  399. top11Age: top11.avgAge,
  400. });
  401. }
  402. {
  403. const all = mazyarFilterPlayers(players, 0, 0, 23);
  404. const top16 = mazyarFilterPlayers(players, 16, 0, 23);
  405. const top11 = mazyarFilterPlayers(players, 11, 0, 23);
  406. rows.push({
  407. title: "U23",
  408. count: mazyarGetNumberOfPlayers(players, 0, 23),
  409. all: all.values,
  410. allAge: all.avgAge,
  411. top16: top16.values,
  412. top16Age: top16.avgAge,
  413. top11: top11.values,
  414. top11Age: top11.avgAge,
  415. });
  416. }
  417. {
  418. const all = mazyarFilterPlayers(players, 0, 0, 21);
  419. const top16 = mazyarFilterPlayers(players, 16, 0, 21);
  420. const top11 = mazyarFilterPlayers(players, 11, 0, 21);
  421. rows.push({
  422. title: "U21",
  423. count: mazyarGetNumberOfPlayers(players, 0, 21),
  424. all: all.values,
  425. allAge: all.avgAge,
  426. top16: top16.values,
  427. top16Age: top16.avgAge,
  428. top11: top11.values,
  429. top11Age: top11.avgAge,
  430. });
  431. }
  432. {
  433. const all = mazyarFilterPlayers(players, 0, 0, 18);
  434. const top16 = mazyarFilterPlayers(players, 16, 0, 18);
  435. const top11 = mazyarFilterPlayers(players, 11, 0, 18);
  436. rows.push({
  437. title: "U18",
  438. count: mazyarGetNumberOfPlayers(players, 0, 18),
  439. all: all.values,
  440. allAge: all.avgAge,
  441. top16: top16.values,
  442. top16Age: top16.avgAge,
  443. top11: top11.values,
  444. top11Age: top11.avgAge,
  445. });
  446. }
  447. }
  448. return rows;
  449. }
  450.  
  451. function mazyarFilterPlayers(players, count = 0, ageLow = 0, ageHigh = 99) {
  452. if (players.length === 0) {
  453. return { values: 0, avgAge: 0.0 };
  454. }
  455.  
  456. const n = count === 0 ? players.length : count;
  457. const filtered = players
  458. .filter((player) => player.age <= ageHigh && player.age >= ageLow)
  459. .sort((a, b) => b.value - a.value)
  460. .slice(0, n);
  461. if (filtered.length === 0) {
  462. return { values: 0, avgAge: 0.0 };
  463. }
  464. const values = filtered.map((player) => player.value).reduce((a, b) => a + b, 0);
  465. const avgAge = filtered.map((player) => player.age).reduce((a, b) => a + b, 0) / filtered.length;
  466. return { values, avgAge };
  467. }
  468.  
  469. async function mazyarFetchNationalPlayersAndCurrency(tid, sport) {
  470. const url = `https://${location.hostname}/ajax.php?p=nationalTeams&sub=players&ntid=${tid}&sport=${sport}`;
  471. const doc = await mazyarFetchHtml(url);
  472. if (doc) {
  473. const currency = mazyarExtractNationalCurrency(doc);
  474. const players = mazyarExtractNationalPlayersDetails(doc, currency);
  475. return { players, currency };
  476. }
  477. return { players: [], currency: '' };
  478. }
  479.  
  480. async function mazyarFetchClubPlayersAndCurrency(tid) {
  481. const url = mazyarGetSquadSummaryUrl(tid);
  482. const doc = await mazyarFetchHtml(url);
  483. if (doc) {
  484. const currency = mazyarExtractClubCurrency(doc);
  485. const players = mazyarExtractClubPlayersDetails(doc, currency);
  486. return { players, currency };
  487. }
  488. return { players: [], currency: '' };
  489. }
  490.  
  491. async function mazyarFetchPlayersAndCurrency(tid, sport) {
  492. const url = mazyarGetSquadSummaryUrl(tid);
  493. const isNational = await fetch(url, { method: "HEAD" })
  494. .then((resp) => (resp.url.search("p=national_teams") > -1));
  495. return isNational ? await mazyarFetchNationalPlayersAndCurrency(tid, sport) : await mazyarFetchClubPlayersAndCurrency(tid);
  496. }
  497.  
  498. function mazyarExtractClubTopPlyers(doc) {
  499. const currency = mazyarExtractClubCurrency(doc);
  500. const players = mazyarExtractClubPlayersDetails(doc, currency);
  501. const sport = mazyarExtractSportType(doc);
  502. const count = sport === "soccer" ? 11 : 21;
  503. return players ? mazyarFilterPlayers(players, count) : { values: 0, avgAge: 0 };
  504. }
  505.  
  506. async function mazyarExtractPlayersProfileDetails(teamId) {
  507. if (!teamId) {
  508. return null;
  509. }
  510. const url = `https://${location.hostname}/?p=players&tid=${teamId}`;
  511. const doc = await mazyarFetchHtml(url);
  512. if (doc) {
  513. const players = doc.getElementById("players_container")?.querySelectorAll("div.playerContainer");
  514. const info = {};
  515. for (const player of players) {
  516. const playerId = player.querySelector("span.player_id_span")?.innerText;
  517. const inMarket = [...player.querySelectorAll("a")].find((el) => el.href?.indexOf("p=transfer&sub") > -1);
  518. info[playerId] = {
  519. detail: player,
  520. shared: !!player.querySelector("i.special_player.fa-share-alt"),
  521. market: !!inMarket,
  522. marketLink: inMarket?.href,
  523. name: player.querySelector("span.player_name")?.innerText,
  524. age: player.querySelector(".dg_playerview_info tbody tr:nth-child(1) td:nth-child(1) strong")?.innerText,
  525. }
  526. }
  527. return info;
  528. }
  529. return null;
  530. }
  531.  
  532. // -------------------------------------------- Icons ------------------------------------------
  533.  
  534. function mazyarStartSpinning(element) {
  535. element.classList.add("fa-spin");
  536. }
  537.  
  538. function mazyarStopSpinning(element) {
  539. element.classList.remove("fa-spin");
  540. }
  541.  
  542. function mazyarCreateIconFromFontAwesomeClass(classes = [], title = "") {
  543. const icon = document.createElement("i");
  544. icon.classList.add(...classes);
  545. icon.setAttribute("aria-hidden", "true");
  546. icon.style.cursor = "pointer";
  547. if (title) {
  548. icon.title = title;
  549. }
  550. return icon;
  551. }
  552.  
  553. function mazyarCreateMoveIcon(title) {
  554. return mazyarCreateIconFromFontAwesomeClass(["fa-solid", "fa-up-down-left-right"], title);
  555. }
  556.  
  557. function mazyarCreateSharedIcon(title) {
  558. return mazyarCreateIconFromFontAwesomeClass(["fa", "fa-share-alt"], title);
  559. }
  560.  
  561. function mazyarCreateMarketIcon(title) {
  562. return mazyarCreateIconFromFontAwesomeClass(["fa", "fa-legal"], title);
  563. }
  564.  
  565. function mazyarCreateCogIcon(title = "") {
  566. return mazyarCreateIconFromFontAwesomeClass(["fa", "fa-cog"], title);
  567. }
  568.  
  569. function mazyarCreateCommentIcon(title = "") {
  570. return mazyarCreateIconFromFontAwesomeClass(["fa-solid", "fa-comment"], title);
  571. }
  572.  
  573. function mazyarCreateSearchIcon(title = "") {
  574. return mazyarCreateIconFromFontAwesomeClass(["fa", "fa-search"], title);
  575. }
  576.  
  577. function mazyarCreateNoteIcon(title = "") {
  578. return mazyarCreateIconFromFontAwesomeClass(["fa-solid", "fa-note-sticky"], title);
  579. }
  580.  
  581. function mazyarCreateRefreshIcon(title = "") {
  582. return mazyarCreateIconFromFontAwesomeClass(["fa", "fa-refresh"], title);
  583. }
  584.  
  585. function mazyarCreateLegalIcon(title = "") {
  586. return mazyarCreateIconFromFontAwesomeClass(["fa", "fa-legal"], title);
  587. }
  588.  
  589. function mazyarCreateSignalIcon(title = "") {
  590. return mazyarCreateIconFromFontAwesomeClass(["fa-solid", "fa-signal-stream"], title);
  591. }
  592.  
  593. function mazyarCreateLoadingIcon(title = "") {
  594. const icon = mazyarCreateIconFromFontAwesomeClass(["fa", "fa-spinner", "fa-spin"], title);
  595. icon.style.cursor = "unset";
  596. return icon;
  597. }
  598.  
  599. function mazyarCreateLoadingIcon2(title = "") {
  600. const icon = mazyarCreateIconFromFontAwesomeClass(["fa-solid", "fa-loader", "fa-pulse", "fa-fw"], title);
  601. icon.style.cursor = "unset";
  602. return icon;
  603. }
  604.  
  605. function mazyarCreateTrashIcon(title = "", style = { fontSize: "1rem", margin: "unset" }) {
  606. const icon = mazyarCreateIconFromFontAwesomeClass(["fa-solid", "fa-trash", "discard-icon"], title);
  607. icon.style.cursor = "pointer";
  608. if (style?.fontSize) {
  609. icon.style.fontSize = style.fontSize;
  610. }
  611. if (style?.margin) {
  612. icon.style.margin = style.margin;
  613. }
  614. return icon;
  615. }
  616.  
  617. function mazyarCreateAddToDeadlineIcon(title, color) {
  618. const icon = mazyarCreateLegalIcon();
  619. icon.style.verticalAlign = "unset";
  620. icon.style.borderRadius = "50%";
  621. icon.style.border = "solid 1px";
  622. icon.style.padding = "3px";
  623.  
  624. const span = document.createElement("span");
  625. span.style.color = color;
  626. span.classList.add("floatRight");
  627. if (title) {
  628. span.title = title;
  629. }
  630. span.appendChild(icon);
  631. return span;
  632. }
  633.  
  634. function mazyarCreateHideFromTransferIcon(title) {
  635. const icon = mazyarCreateTrashIcon(title, { fontSize: "0.9rem" });
  636. icon.style.verticalAlign = "unset";
  637. icon.style.padding = "3px";
  638.  
  639. const span = document.createElement("span");
  640. span.classList.add("floatRight");
  641. if (title) {
  642. span.title = title;
  643. }
  644. span.appendChild(icon);
  645. return span;
  646. }
  647.  
  648. // -------------------------------- DOM Utils ------------------------------
  649.  
  650. async function mazyarGetTransferHistory(url) {
  651. const doc = await mazyarFetchHtml(url);
  652. if (doc) {
  653. const table = doc.querySelector("#transfer-history");
  654. const tbody = table.querySelector("tbody");
  655. tbody.querySelectorAll("tr:not(.bought, .sold)")?.forEach((child) => {
  656. tbody.removeChild(child);
  657. });
  658. return table;
  659. }
  660. return null;
  661. }
  662.  
  663. async function mazyarGetTableTransferHistories(table) {
  664. const teams = table.querySelectorAll("tbody tr.responsive-hide");
  665. const jobs = [];
  666. for (const team of teams) {
  667. const teamLink = team.querySelector("td:nth-child(2) a:last-child");
  668. const tid = mazyarExtractTeamId(teamLink?.href);
  669. const url = `https://${location.hostname}/?p=transfer_history&tid=${tid}`;
  670. jobs.push(mazyarGetTransferHistory(url).then((history) => {
  671. if (history) {
  672. const name = document.createElement("td");
  673. name.innerHTML = `For Team: <a style="text-decoration: none !important;" href="${url}">${teamLink?.innerText}</a>`;
  674. name.colSpan = 5;
  675. // name.style.backgroundColor = "khaki";
  676. name.style.fontWeight = "bold";
  677. name.style.padding = "10px 5px 5px";
  678. const tr = document.createElement("tr");
  679. tr.classList.add("mazyar-history-name", "hitlist-compact-list-column");
  680. tr.style.border = "2px solid darkgray";
  681. tr.appendChild(name);
  682. history.querySelector("tbody").prepend(tr);
  683. return history;
  684. }
  685. return null;
  686. }));
  687. }
  688. return (await Promise.all(jobs)).filter((h) => !!h);
  689. }
  690.  
  691. function mazyarFilterTransferHistory(history, weeks = 2) {
  692. history.filterResults = 0;
  693. const players = history?.querySelectorAll("tbody tr:not(.mazyar-history-name)");
  694. players?.forEach((child) => {
  695. const date = child.querySelector("td.hitlist-compact-list-column")?.firstChild?.nodeValue?.trim();
  696. if (Date.now() - mazyarParseMzDate(date) >= weeks * 7 * 24 * 60 * 60 * 1000) {
  697. child.style.display = 'none';
  698. } else {
  699. child.style.display = "table-row";
  700. history.filterResults += 1;
  701. }
  702. });
  703. }
  704.  
  705. function mazyarRemoveOldTransferHistory(history, weeks = 4) {
  706. const players = history?.querySelectorAll("tbody tr:not(.mazyar-history-name)");
  707. players?.forEach((child) => {
  708. const date = child.querySelector("td.hitlist-compact-list-column")?.firstChild?.nodeValue?.trim();
  709. if (Date.now() - mazyarParseMzDate(date) >= weeks * 7 * 24 * 60 * 60 * 1000) {
  710. child.parentNode.removeChild(child);
  711. }
  712. });
  713. }
  714.  
  715. function mazyarMakeElementDraggable(element, dragHandleElement, dragEndCallback = null) {
  716. let deltaX = 0, deltaY = 0, lastX = 0, lastY = 0;
  717.  
  718. dragHandleElement.style.cursor = "move";
  719. dragHandleElement.onmousedown = dragMouseDown;
  720.  
  721. function dragMouseDown(e) {
  722. e = e || window.event;
  723. e.preventDefault();
  724. // get the mouse cursor position at startup:
  725. lastX = e.clientX;
  726. lastY = e.clientY;
  727. document.onmouseup = closeDragElement;
  728. // call a function whenever the cursor moves:
  729. document.onmousemove = elementDrag;
  730. }
  731.  
  732. function elementDrag(e) {
  733. e = e || window.event;
  734. e.preventDefault();
  735.  
  736. // calculate the new cursor position:
  737. deltaX = lastX - e.clientX;
  738. deltaY = lastY - e.clientY;
  739. lastX = e.clientX;
  740. lastY = e.clientY;
  741.  
  742. // set the element's new position:
  743. let newTop = Math.max(0, element.offsetTop - deltaY);
  744. let newLeft = Math.max(0, element.offsetLeft - deltaX);
  745.  
  746. const { right, bottom, width, height } = element.getBoundingClientRect();
  747. if (right > window.innerWidth) {
  748. newLeft = window.innerWidth - width;
  749. }
  750. if (bottom > window.innerHeight) {
  751. newTop = window.innerHeight - height;
  752. }
  753.  
  754. element.style.top = newTop + "px";
  755. element.style.left = newLeft + "px";
  756. }
  757.  
  758. function closeDragElement() {
  759. // stop moving when mouse button is released:
  760. document.onmouseup = null;
  761. document.onmousemove = null;
  762. if (dragEndCallback) {
  763. dragEndCallback();
  764. }
  765. }
  766. }
  767.  
  768. function mazyarColorizeMaxedSkills(player, maxed = []) {
  769. if (maxed) {
  770. const playerSkills = player.querySelectorAll("table.player_skills tr td.skillval span");
  771. for (const skill of maxed) {
  772. playerSkills[skill]?.classList.add("maxed");
  773. }
  774. }
  775. }
  776.  
  777. function mazyarColorizeSkills(player, report = { H: 4, L: 2, HS: [0, 1], LS: [2, 3] }) {
  778. if (report) {
  779. const playerSkills = player?.querySelectorAll("table.player_skills tr td:nth-child(1)");
  780. playerSkills[report.HS[0]]?.classList.add("mazyar-scout-h", `mazyar-scout-${report.H}`);
  781. playerSkills[report.HS[1]]?.classList.add("mazyar-scout-h", `mazyar-scout-${report.H}`);
  782. playerSkills[report.LS[0]]?.classList.add(`mazyar-scout-${report.L}`);
  783. playerSkills[report.LS[1]]?.classList.add(`mazyar-scout-${report.L}`);
  784. }
  785. }
  786.  
  787. function mazyarGetMzButtonColorClass(color) {
  788. if (color) {
  789. if (color === "red") {
  790. return "button_red";
  791. } else if (color === "blue") {
  792. return "button_blue";
  793. } else if (color === "grey") {
  794. return "buttondiv_disabled";
  795. }
  796. }
  797. // green or other values
  798. return "button_account";
  799. }
  800.  
  801. function mazyarCreateMzStyledButton(title, color = "", floatDirection = null) {
  802. const div = document.createElement("div");
  803. div.style.margin = "auto 0.3rem";
  804. if (floatDirection) {
  805. // floatDirection: floatRight, floatLeft
  806. div.classList.add(floatDirection);
  807. }
  808.  
  809. const button = document.createElement("div");
  810. button.classList.add("mzbtn", "buttondiv", mazyarGetMzButtonColorClass(color));
  811. button.innerHTML = `<span class="buttonClassMiddle"><span style="white-space: nowrap">${title}</span></span><span class="buttonClassRight">&nbsp;</span>`;
  812.  
  813. div.appendChild(button);
  814. return div;
  815. }
  816.  
  817. function mazyarCreateSettingsSectionButton(html = "", style = { backgroundColor: null }) {
  818. const button = document.createElement("button");
  819. button.innerHTML = html;
  820. button.classList.add("mazyar-settings-section-button");
  821. if (style?.backgroundColor) {
  822. button.style.backgroundColor = style.backgroundColor;
  823. }
  824. return button;
  825. }
  826.  
  827. function mazyarCreateUpdateTip(version, url) {
  828. const div = document.createElement("div");
  829. div.classList.add("mazyar-update-tip");
  830. div.innerHTML = `
  831. <span><b>Update Available!</b></span><br />
  832. <button><a href="${url}" target="_blank">Install v${version}</a></button>`;
  833. return div;
  834. }
  835.  
  836. function mazyarCreateMzStyledCloseButton(closeCallback) {
  837. const close = document.createElement("div");
  838. close.classList.add("mazyar-cross-close-button");
  839.  
  840. close.innerHTML = `
  841. <span class="fa-stack fa-lg">
  842. <i class="fa fa-circle fa-stack-2x fa-inverse"></i>
  843. <i class="fa fa-close fa-stack-1x"></i>
  844. </span>`;
  845. if (closeCallback) {
  846. close.addEventListener("click", closeCallback);
  847. }
  848. return close;
  849. }
  850.  
  851. function mazyarCreateMzStyledModalHeader(text = "", closeCallback = null) {
  852. const header = document.createElement("div");
  853. header.classList.add("mazyar-flexbox-row", "mazyar-modal-header");
  854.  
  855. const title = document.createElement("span");
  856. title.innerText = text;
  857. title.style.flexGrow = "1";
  858. title.style.fontWeight = "bold";
  859. title.style.fontSize = "larger";
  860. title.style.padding = "5px";
  861.  
  862. header.appendChild(title);
  863.  
  864. if (closeCallback) {
  865. const close = mazyarCreateMzStyledCloseButton(closeCallback);
  866. header.appendChild(close);
  867. }
  868. return header;
  869. }
  870.  
  871. function mazyarCreateSuggestionList(items) {
  872. const datalist = document.createElement("datalist");
  873. datalist.id = mazyarGenerateUuidV4();
  874. for (const item of items) {
  875. const option = document.createElement("option");
  876. option.value = item.toString();
  877. datalist.appendChild(option);
  878. }
  879. return datalist;
  880. }
  881.  
  882. function mazyarCreateMenuTextInput(title = "input", placeholder = "example", datalistId = "") {
  883. const div = document.createElement("div");
  884. div.classList.add("mazyar-flexbox-row");
  885. div.style.justifyItems = "space-between";
  886. div.innerHTML = `
  887. <label style="margin: 0.5rem; font-weight: bold;">${title}: </label>
  888. <input list="${datalistId}" style="margin: 0.5rem;" type="text" value="" placeholder="${placeholder}">`;
  889. return div;
  890. }
  891.  
  892. function mazyarCreateSubMenuTextInput(title = "input", placeholder = "example", initialValue = 0, style = {
  893. margin: "0.1rem 2.2rem",
  894. inputSize: "5px"
  895. }) {
  896. const div = document.createElement("div");
  897. div.classList.add("mazyar-flexbox-row");
  898. div.style.justifyItems = "space-between";
  899. div.style.margin = style?.margin ?? "0.1rem 2.2rem";
  900. div.innerHTML = `
  901. <label style="margin-left: 0.5rem;">${title}: </label>
  902. <input style="margin-left: 0.5rem;" type="text" size="${style?.inputSize ?? "5px"}" placeholder="${placeholder}", value="${initialValue}">`;
  903. return div;
  904. }
  905.  
  906. function mazyarCreateMenuCheckBox(
  907. label,
  908. initialValue = true,
  909. style = {
  910. alignSelf: "flex-start",
  911. margin: "0.3rem 0.7rem",
  912. }
  913. ) {
  914. const id = mazyarGenerateUuidV4();
  915.  
  916. const div = document.createElement("div");
  917. div.style.alignSelf = style?.alignSelf ?? "flex-start";
  918. div.style.margin = style?.margin ?? "0.3rem 0.7rem";
  919.  
  920. const checkbox = document.createElement("input");
  921. checkbox.id = id;
  922. checkbox.type = "checkbox";
  923. checkbox.checked = initialValue;
  924.  
  925. const labelElement = document.createElement("label");
  926. labelElement.htmlFor = id;
  927. labelElement.innerHTML = label;
  928.  
  929. div.appendChild(checkbox);
  930. div.appendChild(labelElement);
  931. return div;
  932. }
  933.  
  934. function mazyarCreateMenuGroup(title = "") {
  935. const group = document.createElement("div");
  936. group.classList.add("mazyar-flexbox-column");
  937. group.style.alignSelf = "flex-start";
  938. group.style.alignItems = "flex-start";
  939. group.style.margin = "0.2rem 0.6rem";
  940. const header = document.createElement("h4");
  941. header.innerText = title;
  942. header.style.margin = "0.3rem 0rem";
  943. group.appendChild(header);
  944. return group;
  945. }
  946.  
  947. function mazyarAppendOptionList(parent, options, selected) {
  948. // options = a object full of 'key: {value, label}'
  949. for (const key in options) {
  950. if (options.hasOwnProperty(key)) {
  951. const child = document.createElement("option");
  952. child.value = options[key].value;
  953. child.innerText = options[key].label;
  954. if (child.value === selected) {
  955. child.selected = true;
  956. }
  957. parent.appendChild(child);
  958. }
  959. }
  960. }
  961.  
  962. function mazyarCreateDropDownMenu(label, options, initialValue) {
  963. // options = a object full of 'key: {value, label}'
  964. // initialValue = one of the options.value
  965.  
  966. const div = document.createElement("div");
  967. const labelElement = document.createElement("label");
  968. const dropdown = document.createElement("select");
  969.  
  970. div.style.alignSelf = "flex-start";
  971. div.style.margin = "0.3rem 0.7rem";
  972.  
  973. labelElement.innerText = label;
  974. labelElement.style.paddingRight = "0.5rem";
  975.  
  976. mazyarAppendOptionList(dropdown, options, initialValue);
  977.  
  978. div.appendChild(labelElement);
  979. div.appendChild(dropdown);
  980. return div;
  981. }
  982.  
  983. function mazyarCreateDeleteAllFiltersButton(title = "Delete", clickCallback = null) {
  984. const div = document.createElement("div");
  985. div.classList.add("mazyar-flexbox-row");
  986. div.style.width = "100%";
  987. const button = document.createElement("button");
  988. button.classList.add("mazyar-button");
  989. const icon = mazyarCreateTrashIcon(null, { fontSize: "0.9rem", margin: "1px 3px" });
  990. const text = document.createElement("span");
  991. text.innerText = title;
  992. text.style.fontWeight = "bold";
  993. button.appendChild(icon);
  994. button.appendChild(text);
  995. div.append(button);
  996.  
  997. button.style.margin = "4px";
  998. button.style.padding = "3px";
  999.  
  1000. if (clickCallback) {
  1001. button.addEventListener("click", clickCallback);
  1002. }
  1003.  
  1004. return div;
  1005. }
  1006.  
  1007. function mazyarCreateTableHeaderForFiltersView() {
  1008. const tr = document.createElement("tr");
  1009.  
  1010. const name = document.createElement("th");
  1011. name.classList.add("header");
  1012. name.innerText = "Name";
  1013. name.title = "Filter' name";
  1014. name.style.textAlign = "left";
  1015. name.style.textDecoration = "none";
  1016. name.style.width = "11rem";
  1017.  
  1018. const totalHits = document.createElement("th");
  1019. totalHits.classList.add("header");
  1020. totalHits.innerText = "Total";
  1021. totalHits.title = "Total hits founds for this filter";
  1022. totalHits.style.textAlign = "center";
  1023. totalHits.style.textDecoration = "none";
  1024.  
  1025. const scoutHits = document.createElement("th");
  1026. scoutHits.classList.add("header");
  1027. scoutHits.innerText = "Scout";
  1028. scoutHits.title = "Hits found after applying scout filters";
  1029. scoutHits.style.textAlign = "center";
  1030. scoutHits.style.textDecoration = "none";
  1031.  
  1032. const tools = document.createElement("th");
  1033. tools.classList.add("header");
  1034. tools.innerHTML = " ";
  1035. tools.style.textAlign = "center";
  1036. tools.style.textDecoration = "none";
  1037.  
  1038. tr.appendChild(tools);
  1039. tr.appendChild(name);
  1040. tr.appendChild(totalHits);
  1041. tr.appendChild(scoutHits);
  1042.  
  1043. const thead = document.createElement("thead");
  1044. thead.appendChild(tr);
  1045. return thead;
  1046. }
  1047.  
  1048. function mazyarCreateToolbar() {
  1049. const toolbar = document.createElement("div");
  1050. const logo = document.createElement("span");
  1051. const menu = mazyarCreateCogIcon("Settings");
  1052. const note = mazyarCreateNoteIcon("Notebook");
  1053. const live = mazyarCreateSignalIcon("In Progress Results");
  1054. const separator = document.createElement("span");
  1055. const transfer = document.createElement("div");
  1056. const transferIcon = mazyarCreateSearchIcon("Transfer");
  1057. const transferCount = document.createElement("span");
  1058.  
  1059. toolbar.id = "mazyar-toolbar-overlay";
  1060. toolbar.classList.add("mazyar-flexbox-column");
  1061.  
  1062. logo.innerText = "MZY";
  1063. logo.style.fontSize = "0.6rem";
  1064. logo.style.fontWeight = "bold";
  1065. logo.style.margin = "2px";
  1066. logo.style.padding = "1px";
  1067.  
  1068. menu.style.fontSize = "large";
  1069.  
  1070. note.style.fontSize = "large";
  1071. note.style.marginTop = "5px";
  1072.  
  1073. live.style.fontSize = "large";
  1074. live.style.marginTop = "5px";
  1075. live.id = "mazyar-in-progress-icon";
  1076.  
  1077. transferIcon.style.fontSize = "large";
  1078.  
  1079. separator.innerText = "-------";
  1080. separator.style.textAlign = "center";
  1081. separator.style.fontSize = "0.6rem";
  1082. separator.style.fontWeight = "bolder";
  1083. separator.style.margin = "0";
  1084. separator.style.padding = "0";
  1085.  
  1086. transfer.classList.add("mazyar-flexbox-column");
  1087. transfer.style.cursor = "pointer";
  1088.  
  1089. transferCount.id = "mazyar-transfer-filter-hits";
  1090. transferCount.innerText = "0";
  1091. transferCount.style.fontSize = "0.6rem";
  1092. transferCount.style.fontWeight = "bold";
  1093. transferCount.style.margin = "1px 0";
  1094. transferCount.style.padding = "1px";
  1095.  
  1096. transfer.appendChild(transferIcon);
  1097. transfer.appendChild(transferCount);
  1098.  
  1099. toolbar.appendChild(logo);
  1100. toolbar.appendChild(menu);
  1101. toolbar.appendChild(note);
  1102. toolbar.appendChild(live);
  1103. toolbar.appendChild(separator);
  1104. toolbar.appendChild(transfer);
  1105.  
  1106. return { toolbar, menu, transfer, note, live };
  1107. }
  1108.  
  1109. function mazyarCreateFiltersOverview(filters, label, labelColor = "black") {
  1110. const div = document.createElement("div");
  1111. div.classList.add("mazyar-flexbox-column");
  1112. div.style.minWidth = "250px";
  1113. div.style.marginBottom = "20px";
  1114. div.style.alignItems = "flex-start";
  1115.  
  1116. const header = document.createElement("div");
  1117. header.innerText = label;
  1118. header.style.color = labelColor;
  1119. header.style.fontWeight = "bolder";
  1120. header.style.padding = "5px";
  1121. header.style.alignSelf = "center";
  1122. div.appendChild(header);
  1123.  
  1124. const rows = document.createElement("div");
  1125. rows.classList.add("mazyar-flexbox-column");
  1126. rows.style.justifyContent = "left";
  1127. rows.style.margin = "8px";
  1128. div.appendChild(rows);
  1129.  
  1130. if (filters.soccer.length > 0 || filters.hockey.length > 0) {
  1131. if (filters.soccer.length > 0) {
  1132. const title = document.createElement("div");
  1133. title.classList.add("mazyar-import-sport-title");
  1134. title.innerHTML = "<b>Soccer:</b>";
  1135. rows.appendChild(title);
  1136. for (const filter of filters.soccer) {
  1137. const row = document.createElement("div");
  1138. row.classList.add("mazyar-import-filter-row");
  1139. row.innerHTML = `
  1140. <span>
  1141. name: <b style="color: ${labelColor}">${filter.name}</b>
  1142. </span>`;
  1143. rows.appendChild(row);
  1144. }
  1145. }
  1146. if (filters.hockey.length > 0) {
  1147. const title = document.createElement("div");
  1148. title.classList.add("mazyar-import-sport-title");
  1149. title.innerHTML = "<b>Hockey:</b>";
  1150. rows.appendChild(title);
  1151. for (const filter of filters.hockey) {
  1152. const row = document.createElement("div");
  1153. row.classList.add("mazyar-import-filter-row");
  1154. row.innerHTML = `
  1155. <span>
  1156. name: <b style="color: ${labelColor}">${filter.name}</b>
  1157. </span>`;
  1158. rows.appendChild(row);
  1159. }
  1160. }
  1161. } else {
  1162. rows.appendChild(document.createTextNode("No Filters"));
  1163. }
  1164.  
  1165. return div;
  1166. }
  1167.  
  1168. // -------------------------------- Monitor ------------------------------
  1169.  
  1170. function mazyarCreateSectionSeparatorForMonitor() {
  1171. const tr = document.createElement("tr");
  1172. tr.style.height = "10px";
  1173. tr.innerHTML = '<td></td>';
  1174. return tr;
  1175. }
  1176.  
  1177. function mazyarCreateRowSeparatorForMonitor(color) {
  1178. const tr = document.createElement("tr");
  1179. tr.classList.add("mazyar-monitor-player-row");
  1180. tr.style.height = "1px";
  1181. tr.style.backgroundColor = color;
  1182. tr.innerHTML = '<td></td>';
  1183. return tr;
  1184. }
  1185.  
  1186. function monitorAddRowSeparator() {
  1187. return [
  1188. mazyarCreateRowSeparatorForMonitor("#999999"),
  1189. mazyarCreateRowSeparatorForMonitor("#FFFFFF")
  1190. ];
  1191. }
  1192.  
  1193. function mazyarCreateSectionForMonitor(title, id) {
  1194. const tr = document.createElement("tr");
  1195. tr.innerHTML = `
  1196. <td>
  1197. <div id="${id}">
  1198. <table width="100%" cellpadding="0" cellspacing="0">
  1199. <tbody>
  1200. <tr>
  1201. <td style="background-image: url(img/subheader_right.gif);">
  1202. <table border="0" cellpadding="0" cellspacing="0" width="100%">
  1203. <tbody>
  1204. <tr>
  1205. <td class="subheader" valign="bottom">${title}</td>
  1206. </tr>
  1207. </tbody>
  1208. </table>
  1209. </td>
  1210. </tr>
  1211. </tbody>
  1212. </table>
  1213. </div>
  1214. </td>`;
  1215. return tr;
  1216. }
  1217.  
  1218. function mazyarClearPlayerRowsInMonitor(tbody) {
  1219. const players = tbody.querySelectorAll(".mazyar-monitor-player-row");
  1220. for (const player of players) {
  1221. tbody.removeChild(player);
  1222. }
  1223. }
  1224.  
  1225. async function mazyarFetchPlayerMarketDetail(pid, sport = "soccer") {
  1226. const url = `https://${location.hostname}/ajax.php?p=transfer&sub=transfer-search&sport=${sport}&u=${pid}`;
  1227. const result = await mazyarFetchJson(url);
  1228. if (result) {
  1229. if (result.totalHits > 0) {
  1230. const parser = new DOMParser();
  1231. const playerDiv = parser.parseFromString(result?.players, "text/html").body.firstChild;
  1232. const deadline = playerDiv.querySelector(".transfer-control-area div.box_dark:nth-child(1) table:nth-child(1) tr:nth-child(3) strong")?.innerText;
  1233. const fee = playerDiv.querySelector(".transfer-control-area > div > div:nth-child(1) > table > tbody > tr:last-child strong")?.innerText;
  1234. const latestBid = playerDiv.querySelector(".transfer-control-area > div > div:nth-child(2) > table > tbody > tr:last-child strong")?.innerText;
  1235. const flag = playerDiv.querySelector(`img[src*="/flags/"]`)?.src;
  1236. const player = {
  1237. name: playerDiv.querySelector(".player_name")?.innerText,
  1238. pid,
  1239. deadline: 1 + Math.ceil((mazyarParseMzDateTime(deadline.trim()) - new Date()) / 60_000),
  1240. deadlineFull: deadline.trim(),
  1241. latestBid,
  1242. fee,
  1243. source: "mzy",
  1244. flag,
  1245. };
  1246. return { player, remove: false };
  1247. }
  1248. return { player: null, remove: true };
  1249. }
  1250. return { player: null, remove: false };
  1251. }
  1252.  
  1253. async function mazyarFetchTrainingCampDetail() {
  1254. const url = `https://${location.hostname}/?p=training_camp`;
  1255. const doc = await mazyarFetchHtml(url);
  1256. if (doc) {
  1257. const players = doc.querySelectorAll("#training_camp_players_container div.tc_table_container");
  1258. const detail = {};
  1259. for (const player of players) {
  1260. const pid = mazyarExtractPlayerIdFromProfileLink(player.querySelector(".player_link")?.href);
  1261. const daysFull = player.querySelector(".tc_table_duration > div:nth-child(2)")?.innerText;
  1262. detail[pid] = {
  1263. days: daysFull?.split(": ")?.[1],
  1264. }
  1265. }
  1266. return detail;
  1267. }
  1268. return null;
  1269. }
  1270.  
  1271. function mazyarCreatePlayerRowForMonitor(
  1272. player = { pid: "", name: "", deadline: 0, deadlineFull: "", latestBid: "", flag: "" },
  1273. timeout = 0) {
  1274. const tr = document.createElement("tr");
  1275. tr.classList.add("mazyar-monitor-player-row");
  1276. if (player.deadline <= timeout) {
  1277. tr.classList.add("mazyar-deadline-monitor-throb");
  1278. }
  1279. tr.innerHTML = `
  1280. <td valign="top" style="" width="100%">
  1281. <table width="100%" border="0">
  1282. <tbody>
  1283. <tr style="height: 25px;">
  1284. <td colspan="2">
  1285. <table cellpadding="0" cellspacing="0" width="100%" border="0">
  1286. <tbody>
  1287. <tr>
  1288. <td width="220">
  1289. <table>
  1290. <tbody>
  1291. <tr>
  1292. <td><img src="${player.flag}"></td>
  1293. <td><a target="_blank", href="/?p=transfer&sub=players&u=${player.pid}">${player.name}</a></td>
  1294. <td></td>
  1295. </tr>
  1296. </tbody>
  1297. </table>
  1298. </td>
  1299. <td>
  1300. <table class="deadline-table">
  1301. <tbody>
  1302. <tr>
  1303. <td><img src="img/icon_deadline.gif" width="13" height="15"></td>
  1304. <td>${player.deadlineFull}</td>
  1305. </tr>
  1306. </tbody>
  1307. </table>
  1308. </td>
  1309. <td align="right">
  1310. <table border="0">
  1311. <tbody>
  1312. <tr>
  1313. <td>Latest bid:</td>
  1314. <td align="right" style="font-size: 11px; font-weight: bold;">${player.latestBid}</td>
  1315. <td>&nbsp;</td>
  1316. </tr>
  1317. </tbody>
  1318. </table>
  1319. </td>
  1320. </tr>
  1321. </tbody>
  1322. </table>
  1323. </td>
  1324. </tr>
  1325. </tbody>
  1326. </table>
  1327. </td>`;
  1328. return tr;
  1329. }
  1330.  
  1331. // -------------------------------- Tools ------------------------------
  1332.  
  1333. function mazyarConvertFilterArrayToFilterObject(filters) {
  1334. return filters?.reduce((filter, { id, name, params, scout, interval }) => {
  1335. filter[name] = { id, name, params, scout, interval };
  1336. return filter;
  1337. }, {});
  1338. }
  1339.  
  1340. function mazyarMergeFilters(a = [], b = []) {
  1341. // 'b' members could replace 'a' members
  1342. const aObj = mazyarConvertFilterArrayToFilterObject(a);
  1343. const bObj = mazyarConvertFilterArrayToFilterObject(b);
  1344. return Object.values({ ...aObj, ...bObj });
  1345. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址