// ==UserScript==
// @name WoD 竞技场增强
// @icon http://info.world-of-dungeons.org/wod/css/WOD.gif
// @namespace http://tampermonkey.net/
// @description 竞技场管理员辅助工具合集
// @author Christophero
// @version 2023.06.04.3
// @match http*://*.world-of-dungeons.org/*
// @require https://code.jquery.com/jquery-3.3.1.min.js
// @require https://code.jquery.com/ui/1.13.2/jquery-ui.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js
// @grant none
// ==/UserScript==
(function () {
("use strict");
main();
/**
* 插件主入口
*/
function main() {
initStyle();
initJQUIStyle();
addOptBtn();
addExportLeagueBtn();
addBatchInvite();
addBatchAccept();
addBatchLeague();
addBatchChangeLeagueCat();
}
/**
* 插入Css样式
* @param {*} select
* @param {*} styles
*/
function insertCss(select, styles) {
if (document.styleSheets.length === 0) {
//如果没有style标签,则创建一个style标签
var style = document.createElement("style");
document.head.appendChild(style);
}
var styleSheet = document.styleSheets[document.styleSheets.length - 1]; //如果有style 标签.则插入到最后一个style标签中
var str = select + " {"; //插入的内容必须是字符串,所以得把obj转化为字符串
for (var prop in styles) {
str +=
prop.replace(/([A-Z])/g, function (item) {
//使用正则把大写字母替换成 '-小写字母'
return "-" + item.toLowerCase();
}) +
":" +
styles[prop] +
";";
}
str += "}";
styleSheet.insertRule(str, styleSheet.cssRules.length); //插入样式到最后一个style标签中的最后面
}
/**
* 初始化样式表
*/
function initStyle() {
insertCss(".bp-wrapper", {
display: "flex",
});
insertCss(".bp-container", {
margin: "5px",
});
insertCss(".bp-container input", {
width: "100%",
paddingRight: "0",
});
}
/**
* 初始化JqueryUI的样式表
*/
function initJQUIStyle() {
let $toolbarCss = $("<link>");
$("head").prepend($toolbarCss);
$toolbarCss.attr({
rel: "stylesheet",
type: "text/css",
href: "https://code.jquery.com/ui/1.13.2/themes/humanity/jquery-ui.css",
});
document.querySelector("style").textContent +=
".ui-dialog { height: 600px !important; } " +
".ui-dialog .ui-dialog-content { height: 90% !important; } " +
"@media (min-width:1px) { .ui-dialog { width: 95% !important; } } " +
"@media (min-width: 768px) { .ui-dialog { max-width:900px !important; width:95% !important; } }";
}
const getHeroInfo = async (heroName) => {
const response = await fetch(
`${location.origin}/wod/spiel/hero/profile.php?name=${encodeURIComponent(
heroName
)}&IS_POPUP=1&is_popup=1`
);
const text = await response.text();
const jq = $(text);
$("#heroCurrent").text(parseInt($("#heroCurrent").text()) + 1);
if (jq.find('h1:contains("没有找到")').length) {
// 没有找到英雄
return { hero: heroName, exist: false };
}
const $groupTd = jq.find("td:contains('团队:')");
const $clanTd = jq.find("td:contains('联盟:')");
const group = $groupTd.next().text().trim();
const clan = $clanTd.next().text().trim();
// console.log(group);
// console.log(clan);
return { hero: heroName, group, clan, exist: true };
};
/**
* 添加操作按钮
*/
function addOptBtn() {
const $analysisBtn = $(
'<input type="button" name="analysisBtn" value="进行英雄团队分析" class="button clickable">'
);
const $baseInput = $(".gadget.hero.lang-cn");
$baseInput.after($analysisBtn);
$analysisBtn.click(showAnalysisDialog);
}
function length(str) {
return str.replace(/[^\x00-\xff]/g, "aa").length;
}
function getHeroList(str) {
return str
.split("\n")
.map((name) => name.trim())
.filter((name) => name);
}
function addPointMap(pointMap, index) {
const p = $("#bonusPoints" + index).val();
const t = $("#bpTextarea" + index).val();
for (let s of getHeroList(t)) {
pointMap[s] = p;
}
}
function showAnalysisDialog() {
let $analysisForm = $("div#analysisForm");
if (!$analysisForm.length) {
let $container = $(
`<div style="visibility: hidden;">
<div id="analysisForm">
<div>
<label for="heroTextarea">输入要分析的英雄列表,每行一个英雄名称</label>
<textarea id="heroTextarea" name="heroTextarea" style="width: 100%;" rows="10" />
</div>
<div><span id="heroTotal">0</span>/<span id="heroCurrent">0</span></div>
<div class="bp-wrapper">
</div>
</div>
</div>`
);
const $bpWrapper = $container.find(".bp-wrapper");
for (let i = 1; i <= 7; i++) {
$bpWrapper.append(
$(`<div class="bp-container">
<div>
<label for="bonusPoints${i}">分组${i}</label>
<input type="number" name="bonusPoints${i}" id="bonusPoints${i}" value="100" placeholder="number" />
</div>
<div>
<textarea id="bpTextarea${i}" name="bpTextarea${i}" style="width: 100%;" rows="10" />
</div>
</div>`)
);
}
$("body:first").append($container);
$analysisForm = $("div#analysisForm");
}
$analysisForm.dialog({
autoOpen: true, // 是否自动弹出窗口
modal: true, // 设置为模态对话框
resizable: true,
width: 540, //弹出框宽度
height: 620, //弹出框高度
title: "输入", //弹出框标题
position: { my: "center", at: "center", of: window }, //窗口显示的位置
buttons: {
关闭: function () {
$(this).dialog("close");
},
分析: function () {
const text = $("#heroTextarea").val();
let arr = text.split("\n").filter((name) => name.trim());
$("#heroTotal").text(arr.length);
$("#heroCurrent").text(0);
let list = [];
for (let name of arr) {
if (!name) continue;
list.push(getHeroInfo(name.trim()));
}
const pointMap = {};
for (let i = 1; i <= 7; i++) {
addPointMap(pointMap, i);
}
Promise.all(list)
.then((result) => {
console.log(result); //['成功了', 'success']
let notExistArr = result.filter((obj) => !obj.exist);
let aloneArr = result.filter(
(obj) => obj.exist && !obj.clan && !obj.group
);
let groupArr = result.filter(
(obj) => obj.exist && !obj.clan && obj.group
);
let clanArr = result.filter(
(obj) => obj.exist && obj.clan && obj.group
);
console.log("不存在的角色");
console.log(notExistArr);
console.log("独行的角色");
console.log(aloneArr);
console.log("仅有团队的角色");
console.log(groupArr);
console.log("存在联盟的角色");
console.log(clanArr);
let data = "";
let clanMap = {};
for (let obj of clanArr) {
clanMap[obj.clan] = clanMap[obj.clan] || [];
clanMap[obj.clan].push(obj.hero);
}
data += "=====================================================\n";
data += `按联盟分角色(${Object.keys(clanMap).length})\n`;
for (let clanName of Object.keys(clanMap)) {
data +=
clanName.padEnd(20) +
`(${clanMap[clanName].length})` +
":" +
clanMap[clanName].join(",") +
"\n";
}
data += "\n\n";
let groupMap = {};
for (let obj of groupArr) {
groupMap[obj.group] = groupMap[obj.group] || [];
groupMap[obj.group].push(obj.hero);
}
for (let obj of clanArr) {
groupMap[obj.group] = groupMap[obj.group] || [];
groupMap[obj.group].push(obj.hero);
}
data += "=====================================================\n";
data += `按团队分角色(${Object.keys(groupMap).length})\n`;
for (let groupName of Object.keys(groupMap)) {
const heroArr = groupMap[groupName];
const len = length(groupName);
const padSpace = len ? " ".repeat(50 - len) : "";
const numStr = "人数:" + heroArr.length;
const pointArr = heroArr.map((hero) => pointMap[hero]);
const totalPoint = pointArr.reduce(
(prev, cur) => prev + parseInt(cur) || 0
);
const pointStr =
"积分:" +
heroArr.map((hero) => pointMap[hero]).join("+") +
"=" +
totalPoint;
const gname = groupName.padEnd(20);
const heroes = heroArr.join(",");
data += `${gname}(${numStr})「${pointStr}」:${heroes}\n`;
}
data += "\n\n";
data += "=====================================================\n";
data += "以下角色不存在\n";
data += notExistArr.map((obj) => obj.hero).join("\n");
data += "\n\n";
// data += "以下角色是独行角色(没有团队)\n";
// data += aloneArr.map((obj) => obj.hero).join("\n");
// data += "\n\n";
data += "=====================================================\n";
data += "以下角色仅有团队,没有联盟\n";
data += groupArr.map((obj) => obj.hero).join("\n");
data += "\n\n";
data += "=====================================================\n";
data += "以下角色存在联盟\n";
data += clanArr.map((obj) => obj.hero).join("\n");
data += "\n\n";
exportFile(data);
})
.catch((error) => {
console.log(error);
});
},
},
});
}
/**
* 导出文件的方法,导出并直接进行下载
*
* @param {String} 传入导出文件的数据, 格式为字符串
* @param {String} 导出文件的文件名称
*/
const exportFile = (
text = "",
filename = "分析内容.txt",
exportCsv = false
) => {
let blob;
// 导出数据
if (exportCsv) {
blob = new Blob(["\ufeff" + text], {
type: "text/csv;charset=utf-8;",
});
} else {
blob = new Blob([text]);
}
const e = new MouseEvent("click");
const a = document.createElement("a");
a.download = filename;
a.href = window.URL.createObjectURL(blob);
a.dispatchEvent(e);
};
function addExportLeagueBtn() {
if (!["/wod/spiel/arena/index.php"].includes(location.pathname)) return;
const $btn = $(
'<button type="button" class="button clickable">导出参与者</button>'
).click(function () {
const $activeSubTab = $(
'.label.selected:visible:contains("联赛排行榜"), .label.selected:visible:contains("参加者")'
);
if (!$activeSubTab.length) {
alert("请先切换到联赛排行榜或参加者分页再执行导出操作");
return;
}
const subTabTitle = $activeSubTab.text().trim();
let reservedCnt = parseInt(prompt("请输出每组提取前多少(默认全部)", "0"));
if (isNaN(reservedCnt)) {
return;
}
const leagueName = $(
'[id^="smarttabs__league_"]:not([id$="inner"]):visible ul li.selected'
)
.text()
.trim();
// 追加子联赛逻辑
const $matchTables = $(
'[id^="arena_league_details"][id$="_inner"]:visible .content_table'
);
let result = [];
$matchTables.each((i, e) => {
const $table = $(e);
let subMatchName = $table.prevAll("h3:first").text();
if (!subMatchName) {
subMatchName = $table.prevAll("h2:first")[0].firstChild.textContent;
}
const $heroes = $table.find(
'a[href^="/wod/spiel/hero/profile.php?"],a[href^="/wod/spiel/dungeon/group.php?"]'
);
const lines = [];
$heroes.each((i, e) => {
if (reservedCnt != 0 && i >= reservedCnt) return;
const points = $(e).parents("td:first").next("td").text().trim();
const line = `${subMatchName ? subMatchName + "," : ""}${
i + 1
},${e.textContent.trim()},${'"' + points + '"'}`;
lines.push(line + "\n");
});
result.push(lines.join(""));
});
exportFile(result.join(",,\n"), leagueName + ".csv", true);
});
const $tabs = $('[id^="smarttabs__league_"]:not([id$="inner"]) ul');
$tabs.append($btn);
}
/**
* 批量邀请
*/
function addBatchInvite() {
if (!["/wod/spiel/tournament/duell.php"].includes(location.pathname))
return;
// 1. 添加批量邀请防御方和批量邀请挑战方
const $batchAddChallenger = $(
'<button id="inviteChallenger" type="button" class="button">批量挑战方</button>'
);
const $batchAddDefender = $(
'<button id="inviteDefender" type="button" class="button">批量防御方</button>'
);
$batchAddChallenger.click(function () {
createInviteHeroesDialog(false);
});
$batchAddDefender.click(function () {
createInviteHeroesDialog(true);
});
$('input[value="发出邀请"]').after($batchAddChallenger, $batchAddDefender);
}
function getTargetsDialog() {
return $(
`<div>
<div id="inviteForm">
<div>
<label for="targetTextarea">输入要邀请的目标列表,每行一个名称</label>
<textarea id="targetTextarea" name="targetTextarea" style="width: 100%;" rows="20" />
</div>
<div style="font-size: 20px; margin-top: 5px;">
<span>当前进度:</span><span id="targetTotal">0</span>/<span id="targetCurrent">0</span>
</div>
</div>
</div>`
);
}
function createInviteHeroesDialog(isInviteDefender) {
getTargetsDialog().dialog({
autoOpen: true, // 是否自动弹出窗口
modal: true, // 设置为模态对话框
resizable: true,
closeOnEscape: true,
width: 540, //弹出框宽度
height: 540, //弹出框高度
title: `批量邀请${isInviteDefender ? "防御方" : "进攻方"}`, //弹出框标题
position: { my: "center", at: "center", of: window }, //窗口显示的位置
close: function (event, ui) {
$(this).dialog("destroy");
},
buttons: {
关闭: function () {
$(this).dialog("close");
},
邀请: function () {
//扩展jquery的格式化方法
$.fn.parseForm = function () {
const serializeObj = {};
const array = this.serializeArray();
let str = this.serialize();
$(array).each(function () {
if (serializeObj[this.name]) {
if ($.isArray(serializeObj[this.name])) {
serializeObj[this.name].push(this.value);
} else {
serializeObj[this.name] = [
serializeObj[this.name],
this.value,
];
}
} else {
serializeObj[this.name] = this.value;
}
});
return serializeObj;
};
const targetsText = $("#targetTextarea").val();
const targets = targetsText.split("\n").filter((name) => name.trim());
const $inviteForm = $(
'form[action^="/wod/spiel/tournament/duell.php"]'
);
const duellUrl = $inviteForm.attr("action");
const params = $inviteForm.parseForm();
const inviteFetchList = [];
let completeFetch = 0;
for (const hero of targets) {
const inviteParam = Object.assign({}, params);
if (isInviteDefender) {
inviteParam["search[rk_verteidiger]"] = hero;
inviteParam["invite[rk_verteidiger]"] = "选择";
} else {
inviteParam["search[rk_angreifer]"] = hero;
inviteParam["invite[rk_angreifer]"] = "选择";
}
inviteFetchList.push(
fetch(
`${location.origin}/wod/spiel/tournament/duell.php?DuellId=${inviteParam["DuellId"]}&is_popup=1`,
{
headers: {
accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"content-type": "application/x-www-form-urlencoded",
},
method: "POST",
body: new URLSearchParams(
Object.entries(inviteParam)
).toString(),
}
).then((response) => {
completeFetch++;
$("#targetCurrent").text(completeFetch);
return new Promise((resolve, reject) => {
resolve(response);
});
})
);
}
$("#targetTotal").text(targets.length);
Promise.all(inviteFetchList).then((responseArr) => {
fetch(
`${location.origin}/wod/spiel/tournament/duell.php?DuellId=${params["DuellId"]}&is_popup=1`,
{
headers: {
accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"content-type": "application/x-www-form-urlencoded",
},
method: "POST",
body: new URLSearchParams(Object.entries(params)).toString(),
}
)
.then((response) => {
return response.text();
})
.then((text) => {
// 统计哪些目标未能成功添加进挑战列表
const jq = $(text);
const $currentTargets = jq
.find(`.content_table:eq(${isInviteDefender ? 1 : 0})`)
.find(
'a[href^="/wod/spiel/hero/profile.php?"], a[href^="/wod/spiel/dungeon/group.php?"]'
);
const currentTargets = $currentTargets
.map((i, e) => e.textContent)
.get();
const unprocessedHeroes = targets.filter(
(h) => !currentTargets.includes(h)
);
if (unprocessedHeroes.length) {
exportFile(
unprocessedHeroes.join("\n"),
"未能成功操作的目标请手工确认.txt"
);
}
})
.finally(() => {
$inviteForm.submit();
});
});
},
},
});
}
function batchAcceptOrReject(isAccept) {
let $btns;
if (isAccept) {
$btns = $('input[name^="accept["]');
if (!$btns.length) {
alert("没有可以接受的决斗!");
return;
}
} else {
$btns = $('input[name^="reject["]');
if (!$btns.length) {
alert("没有可以拒绝的决斗!");
return;
}
}
const opts = $btns.map((i, e) => e.name).get();
const $duellForm = $('form[action^="/wod/spiel/tournament/duell.php"]');
const actionUrl = $duellForm.attr("action");
const duellParams = new URLSearchParams("?" + $duellForm.serialize());
for (let opt of opts) {
duellParams.set(opt, isAccept ? "开始" : "拒绝");
}
console.log(duellParams.toString());
fetch(actionUrl, {
headers: {
accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"content-type": "application/x-www-form-urlencoded",
},
method: "POST",
body: duellParams.toString(),
}).then((resp) => {
alert("已处理,刷新页面");
location.reload();
});
}
function addBatchAccept() {
if (!["/wod/spiel/tournament/duell.php"].includes(location.pathname))
return;
// 1. 添加批量接受和批量拒绝
const $batchAccept = $(
'<button id="batchAccept" type="button" class="button">全部接受</button>'
);
const $batchReject = $(
'<button id="batchReject" type="button" class="button">全部拒绝</button>'
);
$batchAccept.click(function () {
batchAcceptOrReject(true);
});
$batchReject.click(function () {
batchAcceptOrReject(false);
});
$('a.button:contains("配置决斗选项")').after($batchAccept, $batchReject);
}
/**
* 批量添加比赛(Bo3/Bo5)
*/
function addBatchLeague() {
if (!["/wod/spiel/arena/index.php"].includes(location.pathname)) return;
const $createLeagueBtn = $('a:contains("创建联赛/比赛")');
let $batchLeagueBtn = $(
'<a href="#" class="clickanchor">批量联赛/比赛</a>'
);
$batchLeagueBtn.insertAfter($createLeagueBtn).click(function () {
fetchLeagueBaseInfo();
});
}
function getAllHiddenParams() {
const searchParams = new URLSearchParams();
$("input:hidden").each(function () {
const $this = $(this);
searchParams.set($this.attr("name"), $this.val());
});
return searchParams;
}
function getBaseLeagueParams() {
const allParams = getAllHiddenParams().toString();
const searchParams = new URLSearchParams();
searchParams.set("wod_post_id", params.get("wod_post_id"));
searchParams.set("session_hero_id", params.get("session_hero_id"));
searchParams.set("session_player_id", params.get("session_player_id"));
return searchParams;
}
async function getNameCheckPromise(params, name) {
const nameCheckParam = new URLSearchParams();
nameCheckParam.set("wod_post_id", params.get("wod_post_id"));
nameCheckParam.set("session_hero_id", params.get("session_hero_id"));
nameCheckParam.set("session_player_id", params.get("session_player_id"));
nameCheckParam.set("spieler_id", params.get("spieler_id"));
nameCheckParam.set("table", "arena_league");
nameCheckParam.set("postname", "league_name");
nameCheckParam.set("league_name", name);
nameCheckParam.set("ajax", "1");
return await fetch(`${location.origin}/wod/ajax/validateName.php`, {
headers: {
accept: "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-requested-with": "XMLHttpRequest",
},
body: nameCheckParam.toString(),
method: "POST",
mode: "cors",
credentials: "include",
});
}
async function batchCheckLeagueName(params, namePrev, cnt) {
const $nameErrSpan = $('input[name="league_name"]~#NameInputDiv');
$nameErrSpan.html('<img src="wod/css/img/ajax-loader.gif"');
let nameCheckPromiseArr = [];
let nameArr = [];
if (cnt == 1) {
nameCheckPromiseArr.push(getNameCheckPromise(params, namePrev));
nameArr.push(namePrev);
} else {
for (let i = 1; i <= cnt; i++) {
const leagueName = namePrev + "bo" + i;
nameCheckPromiseArr.push(
getNameCheckPromise(params, namePrev + "bo" + i)
);
nameArr.push(leagueName);
}
}
let responseArr = await Promise.all(nameCheckPromiseArr);
for (let response of responseArr) {
const ret = await response.text();
if (ret.includes("名称不可用或已被使用,请重新输入")) {
$nameErrSpan.html(
'<span class="message_error">名称不可用或已被使用,请重新输入!</span>'
);
_ajaxStopWaiting("ajax_editor");
return;
}
}
$nameErrSpan.html("正在创建联赛,请稍候...");
return nameArr;
}
async function createLeague(params, name) {
let createLeagueParam = new URLSearchParams(params.toString());
createLeagueParam.set("league_name", name);
return await fetch(
`${location.origin}/wod/spiel/arena/league_edit_ajax.php`,
{
headers: {
accept: "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-requested-with": "XMLHttpRequest",
},
body: createLeagueParam.toString(),
method: "POST",
mode: "cors",
credentials: "include",
}
);
}
async function fetchLeagueId(leagueNameArr, leagueCatId, sessionHeroId) {
const response = await fetch(
`${location.origin}/wod/spiel/arena/index.php?menukey=arena&is_popup=1&session_hero_id=${sessionHeroId}`,
{ method: "GET" }
);
const html = await response.text();
const $leagueDoc = $(html);
const $leagueList = $leagueDoc.find(
`#div_league_list_${leagueCatId} a[href^="/wod/spiel/arena/index.php?"]`
);
return $leagueList
.filter((i, e) => leagueNameArr.includes($(e).text()))
.map((i, e) =>
new URLSearchParams(e.href.split("?")[1]).get("show_league_id")
)
.get();
}
async function addHeroes(params) {
const addHeroParams = new URLSearchParams();
addHeroParams.set("wod_post_id", params.get("wod_post_id"));
addHeroParams.set("session_hero_id", params.get("session_hero_id"));
addHeroParams.set("session_player_id", params.get("session_player_id"));
addHeroParams.set("ajax_class_name", "ArenaLeagueMembers");
addHeroParams.set("ajax_object_id", params.get("ajax_object_id"));
addHeroParams.set("add_members", params.get("add_members"));
addHeroParams.set("ajax", 1);
const response = await fetch(`${location.origin}/wod/ajax/render.php`, {
headers: {
accept: "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-requested-with": "XMLHttpRequest",
},
body: addHeroParams.toString(),
method: "POST",
mode: "cors",
credentials: "include",
});
return response.text();
}
async function autoLeagueGroup(params) {
const response = await fetch(`${location.origin}/wod/ajax/render.php`, {
headers: {
accept: "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-requested-with": "XMLHttpRequest",
},
body: params.toString(),
method: "POST",
mode: "cors",
credentials: "include",
});
return response.text();
}
async function fetchLeagueBaseInfo() {
const targetId = "ajax_editor";
_ajaxCreateDialogDirect(
targetId,
null,
"批量联赛/比赛",
true,
async function (event) {
if (event == "ok") {
console.log("提交");
ajaxAlert("开始批处理...");
const params = getAllHiddenParams();
const league_name = $('input[name="league_name"]').val();
const league_owner_id = $('input[name="league_owner_id"]').val();
const league_cat_id = $('select[name="league_cat_id"]').val();
const league_engine = $('select[name="league_engine"]').val();
const league_start_season = $(
'input[name="league_start_season"]'
).val();
const league_round_length_seconds = $(
'select[name="league_round_length_seconds"]'
).val();
const league_start_hour = $('select[name="league_start_hour"]').val();
const league_reward_type = $(
'select[name="league_reward_type"]'
).val();
const league_ref_type = $('select[name="league_ref_type"]').val();
const league_is_only_one_member_per_player =
$('input[name="league_is_only_one_member_per_player"]').prop(
"checked"
) + 0;
const league_hero_class_id = $(
'input[name="league_hero_class_id"]'
).val();
const league_duels_for_ranking = $(
'input[name="league_duels_for_ranking"]:checked'
).val();
const league_closed = $('input[name="league_closed"]:checked').val();
const league_list_position = $(
'input[name="league_list_position"]'
).val();
const league_description = $(
'textarea[name="league_description"]'
).val();
const league_comment = $('textarea[name="league_comment"]').val();
const bo_count = $('input[name="bo_count"]').val();
const attack_group = $('textarea[name="attack_group"]').val();
const defense_group = $('textarea[name="defense_group"]').val();
const wod_post_id = params.get("wod_post_id");
const session_hero_id = params.get("session_hero_id");
const session_player_id = params.get("session_player_id");
const attackHeroArr = attack_group.split("\n").filter((hero) => hero);
const defenseHeroArr = defense_group
.split("\n")
.filter((hero) => hero);
if (attackHeroArr.length != defenseHeroArr.length) {
ajaxAlert("攻击方与防守方人数不一致,请检查!");
_ajaxStopWaiting(targetId);
return false;
}
ajaxAlert("1/4 进行名称检查...");
// 检查比赛名称
const leagueNameArr = await batchCheckLeagueName(
params,
league_name,
bo_count
);
ajaxAlert("2/4 开始创建比赛...");
// 开始创建比赛
const createLeagueParam = new URLSearchParams();
createLeagueParam.set("league_owner_id", league_owner_id);
createLeagueParam.set("league_cat_id", league_cat_id);
createLeagueParam.set("league_engine", league_engine);
createLeagueParam.set("league_start_season", league_start_season);
createLeagueParam.set(
"league_round_length_seconds",
league_round_length_seconds
);
createLeagueParam.set("league_start_hour", league_start_hour);
createLeagueParam.set("league_reward_type", league_reward_type);
createLeagueParam.set("league_ref_type", league_ref_type);
createLeagueParam.set(
"league_is_only_one_member_per_player",
league_is_only_one_member_per_player
);
createLeagueParam.set("league_hero_class_id", league_hero_class_id);
createLeagueParam.set(
"league_duels_for_ranking",
league_duels_for_ranking
);
createLeagueParam.set("league_closed", league_closed);
createLeagueParam.set("league_list_position", league_list_position);
createLeagueParam.set("league_description", league_description);
createLeagueParam.set("league_comment", league_comment);
createLeagueParam.set("wod_post_id", wod_post_id);
createLeagueParam.set("session_hero_id", session_hero_id);
createLeagueParam.set("session_player_id", session_player_id);
createLeagueParam.set("id", "new");
createLeagueParam.set("event", "save");
const promiseArr = [];
for (let leagueName of leagueNameArr) {
promiseArr.push(createLeague(createLeagueParam, leagueName));
}
await Promise.all(promiseArr);
// 获取比赛列表,找到新创建的比赛,获得leagueId
let ajaxObjIdArr = await fetchLeagueId(
leagueNameArr,
league_cat_id,
session_hero_id
);
ajaxAlert("3/4 添加参赛人员...");
// 添加人员
const addHeroParams = new URLSearchParams(params.toString());
const addMembers = [...attackHeroArr, ...defenseHeroArr]
.filter((hero) => hero)
.join("\n");
addHeroParams.set("add_members", addMembers);
const addHeroesPromiseArr = [];
for (let objId of ajaxObjIdArr) {
addHeroParams.set("ajax_object_id", objId);
addHeroesPromiseArr.push(addHeroes(addHeroParams));
}
const respArr = await Promise.all(addHeroesPromiseArr);
console.log(respArr);
ajaxAlert("4/4 自动对决分组...");
// 自动对决分组
const text = respArr[0];
const $jq = $("<div></div>").append($(`<div>${text}</div>`));
const $heroes = $jq.find(
'.content_table_mainline a[href^="/wod/spiel/hero/profile.php?"]'
);
const autoLeagueGroupParam = new URLSearchParams();
autoLeagueGroupParam.set("wod_post_id", wod_post_id);
autoLeagueGroupParam.set("session_hero_id", session_hero_id);
autoLeagueGroupParam.set("session_player_id", session_player_id);
autoLeagueGroupParam.set("ajax_class_name", "ArenaLeagueMembers");
autoLeagueGroupParam.set("LeagueMember_league_save", "1");
$heroes.each((i, e) => {
const $hero = $(e);
const hero = $hero.text();
const selectId = $hero
.parents("tr:first")
.find('select[name^="LeagueMember_league"]')
.attr("name");
const attackIndex = attackHeroArr.indexOf(hero);
const defenseIndex = defenseHeroArr.indexOf(hero);
const leagueIndex =
(attackIndex >= 0 ? attackIndex : defenseIndex) + 1;
autoLeagueGroupParam.set(selectId, leagueIndex);
});
const autoLeagueGroupPromiseArr = [];
for (let objId of ajaxObjIdArr) {
autoLeagueGroupParam.set("ajax_object_id", objId);
autoLeagueGroupPromiseArr.push(
autoLeagueGroup(autoLeagueGroupParam)
);
}
await Promise.all(autoLeagueGroupPromiseArr);
ajaxAlert("批量创建比赛已完成!");
updateLeagueList(league_cat_id);
_ajaxStopWaiting(targetId);
return true;
} else {
console.log("取消");
_ajaxStopWaiting(targetId);
_ajaxCloseModalDialog("ajax_editor");
return true;
}
},
function () {
console.log("init");
}
);
_ajaxStartWaiting(targetId);
// ajaxMsgBox("批量联赛/比赛", "", true, "console.log(111)");
let params = getAllHiddenParams();
let response = await fetch(
`${location.origin}/wod/spiel/arena/league_edit_ajax.php?is_popup=1`,
{
body: `wod_post_id=${params.get(
"wod_post_id"
)}&session_hero_id=${params.get(
"session_hero_id"
)}&session_player_id=${params.get("session_player_id")}&id=new&ajax=1`,
method: "POST",
mode: "cors",
}
);
const text = await response.text();
const $jq = $("<div></div>").append($(`<div>${text}</div>`));
const $table = $jq.find("table");
$table
.find('input[name="league_name"]')
.removeAttr("onkeyup")
.removeAttr("onchange")
.parent()
.prev()
.text("联赛名称(前缀):");
$table.append(
$(
'<tr><td>比赛轮次:</td><td><input name="bo_count" value="1" type="number" min="1" max="5"><button class="button" id="btn_bo3">Bo3</button></td></tr>'
)
);
$table.append(
$(
'<tr><td>进攻方:</td><td><div class="resizeable default"><textarea onmouseover="attachResizer(this)" name="attack_group" cols="40" rows="4" placeholder="每行一个"></textarea></div></td></tr>'
)
);
$table.append(
$(
'<tr><td>防守方:</td><td><div class="resizeable default"><textarea onmouseover="attachResizer(this)" name="defense_group" cols="40" rows="4" placeholder="每行一个,与进攻方一一对应"></textarea></div><button class="button" id="btn_shuffle">乱序</button></td></tr>'
)
);
$("#ajax_editor_content").append($table);
$("#btn_bo3").click(function () {
$('input[name="bo_count"]').val(3);
});
$("#btn_shuffle").click(function () {
const $attackTa = $('textarea[name="attack_group"]');
const $defenseTa = $('textarea[name="defense_group"]');
let attackHeroArr = $('textarea[name="attack_group"]')
.val()
.split("\n")
.filter((hero) => hero);
let defenseHeroArr = $('textarea[name="defense_group"]')
.val()
.split("\n")
.filter((hero) => hero);
defenseHeroArr = _.shuffle(defenseHeroArr);
if (!attackHeroArr.length) {
[attackHeroArr, defenseHeroArr] = _.chunk(
defenseHeroArr,
Math.ceil(defenseHeroArr.length / 2)
);
$attackTa.val(attackHeroArr.join("\n"));
}
$defenseTa.val(defenseHeroArr.join("\n"));
});
_ajaxStopWaiting(targetId);
}
function addBatchChangeLeagueCat() {
if (!["/wod/spiel/arena/index.php"].includes(location.pathname)) return;
const $btn = $(
'<button type="button" class="button clickable">批量修改标签</button>'
).click(async function () {
// 获得所有分组内联赛
const leagueList = [];
$(
'[id^="div_league_list"]:visible:first a[href^="/wod/spiel/arena/index.php?"]:visible'
).each((i, e) => {
const params = new URLSearchParams(e.href.split("?")[1]);
leagueList.push({
id: params.get("show_league_id"),
name: $(e).text(),
});
});
if (!leagueList.length) {
ajaxAlert("页面内没有比赛/联赛!");
return;
}
// 打开处理页面
const $container = $(
'<div><input type="hidden" id="leagueCkProcess"><table><tbody></tbody></table></div>'
);
const targetId = "ajax_editor";
_ajaxCreateDialogDirect(
targetId,
null,
"批量修改显示标签",
true,
async function (event) {
if (event == "ok") {
console.log("提交");
ajaxAlert("开始批处理...");
const leagueIds = $container
.find('input:checkbox[id^="leagueCk"]:checked')
.map((i, e) => e.id.replace("leagueCk", ""))
.get();
const leagueCatId = $container
.find('select[name="league_cat_id"]')
.val();
await batchChangeLeagueCat(leagueIds, leagueCatId);
_ajaxStopWaiting(targetId);
return true;
} else {
console.log("取消");
_ajaxStopWaiting(targetId);
_ajaxCloseModalDialog("ajax_editor");
return true;
}
},
function () {
console.log("init");
}
);
_ajaxStartWaiting(targetId);
// 获得所有分组名称
let params = getAllHiddenParams();
const wod_post_id = params.get("wod_post_id");
const session_hero_id = params.get("session_hero_id");
const session_player_id = params.get("session_player_id");
let response = await fetch(
`${location.origin}/wod/spiel/arena/league_edit_ajax.php?is_popup=1`,
{
headers: {
accept: "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-requested-with": "XMLHttpRequest",
},
body: `wod_post_id=${wod_post_id}&session_hero_id=${session_hero_id}&session_player_id=${session_player_id}&id=${leagueList[0].id}&ajax=1`,
method: "POST",
mode: "cors",
credentials: "include",
}
);
const text = await response.text();
const $jq = $("<div></div>").append($(`<div>${text}</div>`));
const $select = $jq.find('select[name="league_cat_id"]');
const $tbody = $container.find("tbody");
const $leagueListRow = $(
'<tr><td colspan="2">显示标签:</td><td></td></tr>'
);
$leagueListRow.find("td:last").append($select);
$tbody.append($leagueListRow);
for (let i = 1; i <= leagueList.length; i++) {
const league = leagueList[i - 1];
$tbody.append(
`<tr><td style="text-align: right;">${i}</td><td style="text-align: center;"><input id="leagueCk${league.id}" type="checkbox"></td><td><label for="leagueCk${league.id}">${league.name}</label></td></tr>`
);
}
$("#ajax_editor_content").append($container);
_ajaxStopWaiting(targetId);
});
const $tabs = $('[id^="smarttabs__league_"]:not([id$="inner"]) ul');
$tabs.append($btn);
}
async function changeLeagueCat(updateParams, total) {
let response = await fetch(
`${location.origin}/wod/spiel/arena/league_edit_ajax.php?is_popup=1`,
{
headers: {
accept: "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-requested-with": "XMLHttpRequest",
},
body: updateParams.toString(),
method: "POST",
mode: "cors",
credentials: "include",
}
);
const $leagueCkProcess = $("#leagueCkProcess");
$leagueCkProcess.val(parseInt($leagueCkProcess.val()) + 1);
ajaxAlert(`目前进度:${$leagueCkProcess.val()}/${total}`);
return response.text();
}
async function batchChangeLeagueCat(leagueIds, leagueCatId) {
let params = getAllHiddenParams();
const wod_post_id = params.get("wod_post_id");
const session_hero_id = params.get("session_hero_id");
const session_player_id = params.get("session_player_id");
const updateParams = new URLSearchParams();
updateParams.set("wod_post_id", wod_post_id);
updateParams.set("session_hero_id", session_hero_id);
updateParams.set("session_player_id", session_player_id);
updateParams.set("event", "save");
updateParams.set("ajax", "1");
updateParams.set("league_cat_id", leagueCatId);
$("#leagueCkProcess").val(0);
let promiseArr = [];
for (let leagueId of leagueIds) {
updateParams.set("id", leagueId);
promiseArr.push(changeLeagueCat(updateParams, leagueIds.length));
}
const respArr = await Promise.all(promiseArr);
const currentCatId = $('[id^="div_league_list_"]:visible:first')[0]
.id.replace("div_league_list_", "")
.replace("_container", "");
updateLeagueList(currentCatId);
updateLeagueList(leagueCatId);
ajaxAlert("处理完成!");
console.log(respArr);
}
})();