pad.skyozora.com-Multiplay-Helper

show stamina and fast add stage

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        pad.skyozora.com-Multiplay-Helper
// @name:zh-CN	智龙迷城战友系统及资讯网协力页面辅助器 
// @namespace   http://www.mapaler.com/
// @description show stamina and fast add stage
// @description:zh-CN 智龙迷城战友系统及资讯网,协力页面,显示体力,登陆页面可快速添加今日地图
// @include     http://pad.skyozora.com/multiplay/register/
// @include     http://pad.skyozora.com/multiplay/
// @resource    style     https://raw.githubusercontent.com/Mapaler/pad.skyozora.com-Multiplay-Helper/master/style.css?v6
// @version     1.2.25
// @copyright	2017+, Mapaler <[email protected]>
// @grant       GM_getResourceText
// ==/UserScript==


//仿GM_xmlhttpRequest函数v1.3
if (typeof(GM_xmlhttpRequest) == "undefined")
{
    var GM_xmlhttpRequest = function(GM_param) {

        var xhr = new XMLHttpRequest(); //创建XMLHttpRequest对象
        xhr.open(GM_param.method, GM_param.url, true);
        if (GM_param.responseType) xhr.responseType = GM_param.responseType;
        if (GM_param.overrideMimeType) xhr.overrideMimeType(GM_param.overrideMimeType);
        xhr.onreadystatechange = function() //设置回调函数
            {
                if (xhr.readyState === xhr.DONE) {
                    if (xhr.status === 200 && GM_param.onload)
                        GM_param.onload(xhr);
                    if (xhr.status !== 200 && GM_param.onerror)
                        GM_param.onerror(xhr);
                }
            }

        for (var header in GM_param.headers) {
            xhr.setRequestHeader(header, GM_param.headers[header]);
        }

        xhr.send(GM_param.data ? GM_param.data : null);
    }
}
//仿GM_getValue函数v1.0
if(typeof(GM_getValue) == "undefined")
{
	var GM_getValue = function(name, type){
		var value = localStorage.getItem(name);
		if (value == undefined) return value;
		if ((/^(?:true|false)$/i.test(value) && type == undefined) || type == "boolean")
		{
			if (/^true$/i.test(value))
				return true;
			else if (/^false$/i.test(value))
				return false;
			else
				return Boolean(value);
		}
		else if((/^\-?[\d\.]+$/i.test(value) && type == undefined) || type == "number")
			return Number(value);
		else
			return value;
	}
}
//仿GM_setValue函数v1.0
if(typeof(GM_setValue) == "undefined")
{
	var GM_setValue = function(name, value){
		localStorage.setItem(name, value);
	}
}
//仿GM_deleteValue函数v1.0
if(typeof(GM_deleteValue) == "undefined")
{
	var GM_deleteValue = function(name){
		localStorage.removeItem(name);
	}
}
//仿GM_listValues函数v1.0
if(typeof(GM_listValues) == "undefined")
{
	var GM_listValues = function(){
		var keys = [];
		for (var ki=0, kilen=localStorage.length; ki<kilen; ki++)
		{
			keys.push(localStorage.key(ki));
		}
		return keys;
	}
}
//创建带Label的Input类
var LabelInput = function(text, classname, name, type, value, title = "", beforeText = true) {
	var label = document.createElement("label");
	if (text != undefined) label.appendChild(document.createTextNode(text));
	label.className = classname;
	if (typeof(title) != "undefined")
		label.title = title;

	var ipt = document.createElement("input");
	ipt.name = name;
	ipt.id = ipt.name;
	ipt.type = type;
	ipt.value = value;

	label.input = ipt;
	if (beforeText)
		label.insertBefore(ipt, label.firstChild);
	else
		label.appendChild(ipt);
	return label;
};
function log(str) //在信息框显示内容的
{
	var infoBox = document.querySelector("#info-box");
	for (var ci = infoBox.childNodes.length-1;ci>=0;ci--) //清空主图列表
	{
		infoBox.childNodes[ci].remove();
	}
	infoBox.appendChild(document.createTextNode(str));
}
//得到标准时区的时间的函数
function getLocalTime(i)
{
	//参数i为时区值数字,比如北京为东八区则输进8,西5输入-5
	if (typeof i !== 'number') return;
	var d = new Date();
	//得到1970年一月一日到现在的秒数
	var len = d.getTime();
	//本地时间与GMT时间的时间偏移差
	var offset = d.getTimezoneOffset() * 60000;
	//得到现在的格林尼治时间
	var utcTime = len + offset;
	return new Date(utcTime + 3600000 * i);
}

var config={
	version:1, //储存当前设置结构版本
	updateDate:0, //储存今日开放地图上次更新时间
	todayStage:[
		{name:"每日降临",detail:"每天都会更换一次的降临神,保持24小时。",stages:[]},
		{name:"紧急降临",detail:"每天分组出现的紧急本,每个组一小时。",stages:[]},
		{name:"耀日本",detail:"每周分星期几固定出现的本",stages:[]},
		{name:"活动本",detail:"各种活动的本",stages:[]}
	], //储存当前开放的地图
	starStage:[], //储存收藏的地图
	message:[],
};
var stageList=[]; //储存全部地图的数据
var mobile = false; //是否为手机版
var stageTestReg = "^/?s(?:tage)?/"; //用来测试href是不是地下城的

if(typeof(GM_getResourceText) != "undefined") //用了GM插件
{
	var styleDom = document.createElement("style");
	styleDom.type = "text/css";
	styleDom.appendChild(document.createTextNode(GM_getResourceText('style')));
	document.head.appendChild(styleDom);
}

if (GM_getValue("helper-config") == undefined && location.pathname == "/multiplay/register/")
{
	saveConfig();
	alert("💗欢迎使用!\n请先导入地下城列表数据\n然后检查今日开放地下城。");
	console.log("配置不存在,储存默认配置");
}else
{
	loadConfig(GM_getValue("helper-config"),GM_getValue("helper-stage-list"));
	//console.log("配置存在",config);

	var now = getLocalTime(9);var last = new Date(config.updateDate);
	if (now > last && now.getDate() != last.getDate())
	{
		console.log("今天的开放地图还没检查");
		if(location.pathname == "/multiplay/register/") alert("💗又是新的一天了!\n请检查今天开放的地下城。");
		config.todayStage.length = 0; //清空昨天的
	}else
	{
		console.log("已经是今天的开放地图");
	}
}
function loadConfig(configStr,stageListStr,reset = false)
{
	var bk = [true,true];
	var saConfig = JSON.parse(configStr);
	console.log("设置",saConfig)
	var saStageList = JSON.parse(stageListStr);
	console.log("地图数据",saStageList)

	if (saConfig != null && typeof(saConfig) == "object")
	{
		if (reset)
		{
			config = saConfig;
		}
		else
			config = Object.assign(config, saConfig);
	}	
	else
	{
		console.error("配置损坏,使用默认配置");
		bk[0] = false;
	}
	if (saStageList != null && typeof(saStageList) == "object")
		stageList = saStageList.concat();
	else
	{
		console.error("完整地下城数据丢失,使用空配置");
		bk[1] = false;
	}
	return bk;
}
function saveConfig(type)
{
	if (type == undefined) type = 255;
	if (1 == (type & 1))
	{
		var configStr = JSON.stringify(config);
		GM_setValue("helper-config", configStr);
	}
	if (2 == (type & 2))
	{
		var stageListStr = JSON.stringify(stageList);
		GM_setValue("helper-stage-list", stageListStr);
	}
}


if(location.pathname == "/multiplay/register/") //注册页面
{
	registerPage();
}else if(location.pathname == "/multiplay/") //列表页面
{
	multiplayPage();
}

function registerPage()
{
	var form = document.querySelector("#wrapper>table:nth-last-of-type(2) form"); //主要版面的表单
	if (form == undefined) //如果没找到,试试手机版
	{
		form = document.querySelector(".content>form");
		if (form!=undefined)
		{
			mobile = true;
		}else
		{
			alert("😰未找到协力登陆窗口");
		}
	}
	if (!mobile) form.querySelector("p:nth-last-of-type(1)").remove() //去除最后面那个无用的东西
	var box = document.createElement("div");form.parentElement.appendChild(box);
	box.id = box.className = "mlt-helper";


	function typeClick(){refreshStageList1(this.value)};

	var stgBox = document.createElement("div");box.appendChild(stgBox);
	stgBox.className = "main-stg-box";

	var stg1Box = document.createElement("div");stgBox.appendChild(stg1Box);
	stg1Box.className = "stg-box stg-box-1";
	var stg1Ul = document.createElement("ul");stg1Box.appendChild(stg1Ul);
	
	function refresTypeList()
	{
		for (var ci = stg1Ul.childNodes.length-1;ci>=0;ci--) //清空主图列表
		{
			stg1Ul.childNodes[ci].remove();
		}
		//添加每日类型
		config.todayStage.forEach(function(stgs,index){
			var stg1UlLi1 = document.createElement("li");stg1Ul.appendChild(stg1UlLi1);
			if (typeof(stgs) != "object") return;
			var stgType1 = new LabelInput(stgs.name, "stg-type","stg-type","radio",index,stgs.detail);
			//if (index == 0) stgType1.input.checked = true;
			stgType1.input.onclick = typeClick;
			stg1UlLi1.appendChild(stgType1);
		})

		//添加收藏类型
		var stg1UlLi2 = document.createElement("li");stg1Ul.appendChild(stg1UlLi2);
		var stgType2 = new LabelInput("我的收藏", "stg-type","stg-type","radio",100,"我收藏的地下城");
		stgType2.input.onclick = typeClick;
		stg1UlLi2.appendChild(stgType2);
	}


	var stg2Box = document.createElement("div");stgBox.appendChild(stg2Box);
	stg2Box.className = "stg-box stg-box-2";
	var stg2Ul = document.createElement("ul");stg2Box.appendChild(stg2Ul);

	//征求文本信息
	var req = form.querySelector("[name=req]");
	var msgBox = document.createElement("select");stgBox.appendChild(msgBox);
	msgBox.size = 5;
	msgBox.className = "stg-box msg-box";
	msgBox.onclick = function(){
		var msg = config.message[this.value];
		if (msg !== undefined)
			insertText(req,msg);
			//req.value += msg;
	}

	function refreshMessageList()
	{
		while(msgBox.options.length>0) //清空原来的短语列表
		{
			msgBox.remove(0);
		}
		config.message.forEach(function(item,index){
			var opt = new Option(item, index);
			msgBox.add(opt);
		})
	}
	function insertText(obj,str) {
		if (document.selection) {
			var sel = document.selection.createRange();
			sel.text = str;
		} else if (typeof obj.selectionStart === 'number' && typeof obj.selectionEnd === 'number') {
			var startPos = obj.selectionStart,
			endPos = obj.selectionEnd,
			cursorPos = startPos,
			tmpStr = obj.value;
			obj.value = tmpStr.substring(0, startPos) + str + tmpStr.substring(endPos, tmpStr.length);
			cursorPos += str.length;
			obj.selectionStart = obj.selectionEnd = cursorPos;
		} else {
			obj.value += str;
		}
	}

	var msgBoxCtl = document.createElement("div");stgBox.appendChild(msgBoxCtl);
	msgBoxCtl.className = "msg-box-control";
	var msgAdd = document.createElement("input");msgBoxCtl.appendChild(msgAdd);
	msgAdd.type = "button";
	msgAdd.id = msgAdd.className = "message-add";
	msgAdd.value = "+";
	msgAdd.onclick = function(){
		var str = prompt("请输入需要保存的短语");
		if (str == null) return;
		config.message.push(str);
		saveConfig(1);
		refreshMessageList();
	};
	var msgRmv = document.createElement("input");msgBoxCtl.appendChild(msgRmv);
	msgRmv.type = "button";
	msgRmv.id = msgRmv.className = "message-remove";
	msgRmv.value = "-";
	msgRmv.onclick = function(){
		config.message.splice(msgBox.selectedIndex,1);
		saveConfig(1);
		refreshMessageList();
	};

	//刷新地下城列表类型
	function refreshStageList1(type)
	{
		if (type == undefined)type = 0;
		for (var ci = stg2Ul.childNodes.length-1;ci>=0;ci--) //清空主图列表
		{
			stg2Ul.childNodes[ci].remove();
		}
		var stages; //需要处理的数组
		if (type == 100)
		{
			stages = config.starStage;
		}else if (type >=0 )
		{
			if (config.todayStage[type] == undefined) return;
			stages = config.todayStage[type].stages;
		}else
		{
			console.error("未知的地下城类型",type,stages);
			return;
		}

		if (typeof(stages) != "object") return;
		stages.forEach(function(stgName)
		{
			var _stgName = stgName;
			var li = document.createElement("li");stg2Ul.appendChild(li);
			var stgLbl = new LabelInput(null, "stg-list","stg-list","radio",_stgName,"地下城大关卡:" + _stgName);
			li.appendChild(stgLbl);
			stgLbl.input.onclick = refreshStageList2;

			var icon = document.createElement("div"); stgLbl.appendChild(icon);
			icon.className = "stage-icon";
			var thisStage = stageList.filter(function(stg){return stg.name == _stgName;})[0]
			if (thisStage) icon.style.backgroundImage = "url(" + thisStage.iconUrl + ")";
			
			var detail =  document.createElement("div"); stgLbl.appendChild(detail);
			detail.className = "stage-detail";
			detail.appendChild(document.createTextNode(_stgName));
			
		})
	}

	function refreshStageList2()
	{
		if (!this.checked) return; //如果并不是自身被选中,那么就没反应
		var _stgName = this.value;
		var thisStage = stageList.filter(function(stg){return stg.name == _stgName;})[0]
		if (thisStage == undefined)
		{
			alert("😱数据库里没有这个地下城");
			return;
		}

		stage0.selectedIndex = stage0.options.length - 1; //选中“上次登录的关卡”

		while(stage1.options.length>0) //清空原来的主地下城列表
		{
			stage1.remove(0);
		}
		while(stage2.options.length>0) //清空原来的子地下城列表
		{
			stage2.remove(0);
		}

		var opt = new Option(thisStage.name, thisStage.name);
		stage1.add(opt);
		stage1.selectedIndex = stage1.options.length - 1;

		thisStage.subStage.forEach(function(stg){
			var opt = new Option(stg.name, stg.name);
			stage2.add(opt);
		})
		stage2.selectedIndex = 0;
	}

	function addStarStage(name)
	{
		if (config.starStage.indexOf(name)<0)
		{
			if (!stageList.some(function(item){ //查找以前有没有这个地图
				return item.name == name;
			}))
				alert("😱数据库里没有这个地下城");
			else{
				config.starStage.push(name);
				saveConfig(1);
				stg1Ul.querySelector("input[value='100']").click(); //点击刷新
				//alert("💗“"+ name +"”收藏成功");
			}
		}else
		{
			alert("😅“"+ name +"”已经收藏过了");
		}
	}
	function removeStarStage(name)
	{
		if (name == undefined)
		{
			config.starStage.length = 0; //如果没有输入,直接清空
			saveConfig(1);
			stg1Ul.querySelector("input[value='100']").click(); //点击刷新
			//alert("收藏清空了");
			return;
		}
		var index = config.starStage.indexOf(name);
		if (index<0)
		{
			alert("😅你并没有收藏过“"+ name +"”");
		}else
		{
			config.starStage.splice(index,1)
			saveConfig(1);
			stg1Ul.querySelector("input[value='100']").click(); //点击刷新
			//alert("“"+ name +"”被删掉了");
		}
	}
	var btnBox1 = document.createElement("div");box.appendChild(btnBox1);
	var btnAddStg = document.createElement("input");btnBox1.appendChild(btnAddStg);
	btnAddStg.type = "button";
	btnAddStg.id = btnAddStg.className = "add-stage-string";
	btnAddStg.value = "直接输入名称添加收藏";
	btnAddStg.onclick = function(){
		addStarStage(prompt("请输入地下城名称"));
	};
	var btnRemoveStg = document.createElement("input");btnBox1.appendChild(btnRemoveStg);
	btnRemoveStg.type = "button";
	btnRemoveStg.id = btnRemoveStg.className = "remove-stage";
	btnRemoveStg.value = "删除选中地下城收藏";
	btnRemoveStg.onclick = function(){
		var radios = document.getElementsByName("stg-list");
		for (var ri=0;ri<radios.length;ri++)
		{
			if (radios[ri].checked)
			{
				removeStarStage(radios[ri].value);
			}
		}
	};
	var btnRemoveAllStg = document.createElement("input");btnBox1.appendChild(btnRemoveAllStg);
	btnRemoveAllStg.type = "button";
	btnRemoveAllStg.id = btnRemoveAllStg.className = "remove-stage";
	btnRemoveAllStg.value = "清空我的收藏";
	btnRemoveAllStg.onclick = function(){
		removeStarStage();
	};

	var btnBox2 = document.createElement("div");box.appendChild(btnBox2);
	var chkUpt = document.createElement("input");btnBox2.appendChild(chkUpt);
	chkUpt.type = "button";
	chkUpt.id = chkUpt.className = "checkUpdate";
	chkUpt.value = "检查今日开放地下城";
	chkUpt.onclick = function(){
		checkTodayUpdate(function(){
			refresTypeList();
			saveConfig(1);
			refreshStageList1(0);
		})
	}

	var chkStgLst = document.createElement("input");btnBox2.appendChild(chkStgLst);
	chkStgLst.type = "button";
	chkStgLst.id = chkUpt.className = "check-stage-list";
	chkStgLst.value = "获取完整地下城数据";
	chkStgLst.onclick = function(){
		checkAllStageList();
	}

	var ioCfg = document.createElement("input");btnBox2.appendChild(ioCfg);
	ioCfg.type = "button";
	ioCfg.id = chkUpt.className = "input-output-config";
	ioCfg.value = "导入/导出设置&地下城列表";
	ioCfg.onclick = function(){
		var dlg = ioConfigDialog();
		form.parentElement.appendChild(dlg);
		dlg.classList.remove("display-none");
		dlg.configText.value = JSON.stringify(config);
		dlg.stageListText.value = JSON.stringify(stageList);
	};

	//收藏按钮
	var stage0 = form.querySelector("[name=column1]");
	var stage1 = form.querySelector("#stage");
	var stage2 = form.querySelector("#stage2"); stage2.onchange = null;
	var starStg = document.createElement("input");form.insertBefore(starStg,stage2.nextSibling);
	starStg.type = "button";
	starStg.id = starStg.className = "star-stage";
	starStg.value = "⭐️";
	starStg.onclick = function(){
		addStarStage(stage1.value);
	};

	var infoBox = document.createElement("div");box.appendChild(infoBox);
	infoBox.id = infoBox.className = "info-box";
	refresTypeList();
	refreshStageList1(0); //先刷新地下城吧
	refreshMessageList(); //刷新文本列表
}
function checkTodayUpdate(callback)
{
	log("开始检查今日地下城");
	GM_xmlhttpRequest({
		method: "GET",
		url: "desktop/", //主页
		onload: dealMainPage,
		onerror: function(response) {
			log("获取主页地下城活动失败");
			console.error("获取主页地下城活动失败",response);
		}
	});

	function dealMainPage(response)
	{
		var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
		//紧急活动地下城表格
		var JinJiEvent = PageDOM.querySelector("#container>.item:nth-of-type(1)>table:nth-of-type(2)");
		//今天的降临
		if (JinJiEvent.rows[2] == undefined || JinJiEvent.rows[2].cells[1] == undefined) {alert("😅未发现今日数据,是不是主页格式有问题?"); return;}
		
		config.todayStage.length = 0; //先清空

		var JiangLin = JinJiEvent.rows[2].cells[1].getElementsByTagName("a");
		var stgs1 = {name:"每日降临",detail:"每天都会更换一次的降临神,保持24小时。",stages:[]};
		for (var ai=0;ai<JiangLin.length;ai++)
		{
			var link = JiangLin[ai];
			if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) && stgs1.stages.indexOf(link.title)<0)
			{
				stgs1.stages.push(link.title);
			}
		}
		config.todayStage.push(stgs1);
		//今天的紧急
		var stgs2 = {name:"紧急降临",detail:"每天分组出现的紧急本,每个组一小时。",stages:[]};
		for (var ri=1;ri<JinJiEvent.rows[2].cells[0].rowSpan;ri++)
		{
			var link = JinJiEvent.rows[2+ri].cells[0].querySelector("a");
			if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) && stgs2.stages.indexOf(link.title)<0)
			{
				stgs2.stages.push(link.title);
			}
		}
		config.todayStage.push(stgs2);
	
		//长期活动地下城表格
		//第一行周回本
		var ChangQiEvent = PageDOM.querySelector("#container>.item:nth-of-type(2)>table:nth-last-of-type(1)");
		var stgs3 = {name:"耀日本",detail:"每周分星期几固定出现的本",stages:[]};
		var imgsArr = [ChangQiEvent.rows[1].getElementsByTagName("img"),ChangQiEvent.rows[3].getElementsByTagName("img")];
		for (var iAi=0;iAi<imgsArr.length;iAi++)
		{
			var imgs = imgsArr[iAi];
			for (var ii=0;ii<imgs.length;ii++)
			{
				var link = imgs[ii].parentElement;
				if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) //是场景
					&& stgs3.stages.indexOf(link.title)<0
				)
				{
					stgs3.stages.push(link.title);
				}
			}
		}
		config.todayStage.push(stgs3);

		//后面的活动
		var stgs4 = {name:"长期活动",detail:"各种活动的本",stages:[]};
		for (var ri=4;ri<ChangQiEvent.rows.length;ri++)
		{
			var imgs = ChangQiEvent.rows[ri].getElementsByTagName("img");
			var typeStr = ""; //储存地下城类型说明
			var typeSpan = ChangQiEvent.rows[ri].cells[2].querySelector("span"); //获取文字型类别
			if (typeSpan != undefined)
			{
				typeStr = typeSpan.textContent;
			}
			var typeImg = ChangQiEvent.rows[ri].cells[2].querySelector("img"); //获取图片型类别
			if (typeImg != undefined)
			{
				typeStr = typeImg.alt;
			}
			var endTime = "";
			var endTimeTd = ChangQiEvent.rows[ri].cells[3]; //获取开始时间
			if (endTimeTd != undefined)
			{
				endTime = endTimeTd.childNodes[1].nodeValue;
			}
			for (var ii=0;ii<imgs.length;ii++)
			{
				var link = imgs[ii].parentElement;
				var href = link.getAttribute("href");
				if (new RegExp(stageTestReg,"igm").test(href) //是场景
					&& !/coin\.png/igm.test(imgs[ii].getAttribute("src")) //不是金币地下城
					&& !/後開始/igm.test(endTime) //不是还没有开始的
					&& !/一次通關限定/igm.test(typeStr) //不是一次通关限定
					&& !/排名地下城/igm.test(typeStr) //不是排名地下城
					&& !/每天一場/igm.test(typeStr) //不是每天一场限定
					&& !/單人限定/igm.test(typeStr) //不是单人限定
					&& stgs4.stages.indexOf(link.title)<0
				)
				{
					var realName = link.title.replace(/【.*】/igm,"");
					if (href.indexOf(link.title)>=0)
					{
						stgs4.stages.push(link.title);
					}else if (href.indexOf(realName)>=0)
					{
						stgs4.stages.push(realName);
					}else //那些活动title和场景stage名字不符
					{
						var realName = link.title.replace(/【.*】/igm,"");
						var subStageReg = "^/?s(?:tage)?/([^/]+)/[^/]+"; //用来测试href是不是有子地下城的
						if (new RegExp(subStageReg,"igm").test(href))
						{
							var stgV = new RegExp(subStageReg,"igm").exec(href);
							stgs4.stages.push(stgV[1]);
						}
					}
				}
			}
		}
		config.todayStage.push(stgs4);

		config.updateDate = getLocalTime(9).getTime();
		log("今日有" + config.todayStage.reduce(function(previous, current){return previous + current.stages.length},0) + "个地下城");
		//console.log("今日地下城获取完毕",config);
		callback();
	}
}
//关卡大家都有的部分,类
function minStage(name,iconUrl)
{
	this.name = name;
	this.iconUrl = iconUrl;
}
//单个难度地下城关卡,类
function Stage(name,iconUrl,stamina,battles)
{
	var obj = new minStage(name,iconUrl);
	obj.stamina = stamina; //体力
	obj.battles = battles; //层数
	return obj;
}
//多个难度的地下城关卡,类
function mainStage(name,iconUrl)
{
	var obj = new minStage(name,iconUrl);
	obj.name = name;
	obj.iconUrl = iconUrl;
	obj.subStage = [];
	obj.checkSubStage = function(callback)
	{
		GM_xmlhttpRequest({
			method: "GET",
			url: "stage/" + this.name,
			onload: function(response){ //获取成功
				var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
				var subStageList = PageDOM.querySelector("#wrapper>table:nth-last-of-type(2) ul"); //子关卡的列表ul
				if (subStageList == undefined) //如果没找到,试试手机版
				{
					subStageList = PageDOM.querySelector(".content>ul");
					if (subStageList!=undefined)
					{
						mobile = true;
					}else
					{
						alert("😰 " + name + " 页面未找到關卡資料");
					}
				}

				var subStage = subStageList.getElementsByTagName("li"); //所有的li

				obj.subStage.length = 0; //去掉所有的旧数据
				for (var si=0;si<subStage.length;si++)
				{
					var link = subStage[si].querySelector("div a"); //图标链接
					var iconUrl = link.querySelector("img").getAttribute("data-original");
					var detailTd = subStage[si].querySelector("div:nth-of-type(2)"); //介绍格
					if (detailTd == undefined)
					{ //目前不知道到底是谁错了
						console.error("没有介绍格",subStage[si]);
					}
					var name = detailTd.querySelector("a").textContent.replace(/\s*關卡資料.*$/igm,"");
					var stamina = 0;var battles = 0;
					for (var ci=0;ci<detailTd.childNodes.length;ci++)
					{
						var cld = detailTd.childNodes[ci];
						if (cld.nodeName == "SPAN" && /體力/igm.test(cld.previousSibling.nodeValue))
							var stamina = parseInt(cld.textContent);
						if (cld.nodeName == "SPAN" && /層數/igm.test(cld.previousSibling.nodeValue))
							var battles = parseInt(cld.textContent);
					}
					var stage = new Stage(name,iconUrl,stamina,battles);
					obj.subStage.push(stage);
				}
				callback();
			},
			onerror: function(response) {
				log("获取 " + obj.name + " 详情失败");
				console.error("获取 " + obj.name + " 详情失败",response);
			},
		});
	}
	return obj;
}
function checkAllStageList(resetAll = false)
{
	GM_xmlhttpRequest({
		method: "GET",
		url: "stage",
		onload: dealStageList,
		onerror: function(response) {
			log("获取全部地下城列表失败");
			console.error("获取全部地下城列表失败",response);
		},
	});

	function dealStageList(response)
	{
		var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
		if (resetAll) stageList.length = 0; //先清空
		//所有地下城表格
		var stageTd = PageDOM.querySelector("#wrapper>table:nth-last-of-type(2) td");
		if (stageTd == undefined) //如果没找到,试试手机版
		{
			stageTd = PageDOM.querySelector(".content");
			if (stageTd!=undefined)
			{
				mobile = true;
			}else
			{
				alert("😰未找到地下城列表");
			}
		}
		var stages = stageTd.getElementsByClassName("tooltip"); //获取所有的链接
		if(mobile)
		{
			stages = stageTd.getElementsByTagName("a"); //获取所有的链接
		}
		stages = Array.prototype.slice.call(stages); //将类数组转换为数组
		stages = stages.filter(function(item){ //清除没有图标的链接和不是地下城的链接
			return new RegExp(stageTestReg,"igm").test(item.getAttribute("href")) //是地下城链接
					&& item.querySelector("img") != undefined; //有图标
		})

		//检查是否已经存在,否则添加新的
		function checkExistAdd(newStage,resetAll = false)
		{
			var oldStage = stageList.filter(function(item){ //查找以前有没有这个地图
				return item.name == newStage.name;
			})[0];
			if (resetAll || oldStage == undefined)
			{ //没有就添加新的
				newStages.push(newStage);
			}else
			{ //有的话就什么也不改变
				//oldStage.name = newStage.name;
				//oldStage.iconUrl = newStage.iconUrl;
			}
		}

		var newStages = [];
		//所有地下城
		stages.forEach(function(item) {
			var img= item.querySelector("img");
			imgUrl = img.getAttribute("data-original");
			checkExistAdd(new mainStage(mobile?img.alt:item.title,imgUrl),resetAll);
		});
		//▼添加暂时没有的特殊图
		//checkExistAdd(new mainStage("闇の戦武龍","http://i1296.photobucket.com/albums/ag18/skyozora/pets_icon/3839_zpsinupxf0j.png"),resetAll);
		//▲添加暂时没有的特殊图

		//var stageArr = stageList.slice(398,400); //debug用
		getStageDetail(newStages,newStages.length,function(){
			stageList = stageList.concat(newStages);
			log("所有地下城获取完毕");
			//console.log("所有地下城获取完毕",config);
			saveConfig(2);
		});
	}
	function getStageDetail(stgArr,max,callback)
	{
		if (stgArr.length < 1)
		{
			callback();
			return;
		}
		var newStgArr = stgArr.concat();
		var thisStg = newStgArr.shift(); //删除新数组的第一个元素

		thisStg.checkSubStage(function(){
			log("已获取" + (max-newStgArr.length) + "/" + max);
			console.log("已获取" + (max-newStgArr.length) + "/" + max);
			getStageDetail(newStgArr,max,callback);
		});
	}
}

/*
 * 协力列表页面
 * 
 */
function multiplayPage()
{
	var table = document.querySelector("#wrapper>table:nth-last-of-type(2) table"); //协力请求表格
	if (table == undefined) //如果没找到,试试手机版
	{
		table = document.querySelector(".content>table");
		if (table!=undefined)
		{
			mobile = true;
		}else
		{
			alert("😰未找到协力列表");
		}
	}
	var cellMaxLength = 0;
	for (var ci=0;ci<table.rows[0].cells.length;ci++)
	{
		cellMaxLength += table.rows[0].cells[ci].colSpan; //计算宽度
	}
	for (var ri=table.rows.length-1;ri>0;ri--)
	{
		if (table.rows[ri].cells[0].colSpan >= cellMaxLength)
		{
			table.rows[ri].remove(); //去除广告
		}
	}
	if (!mobile) table.rows[0].cells[0].colSpan += 1; //标题添加一格合并
	for (var ri=(mobile?0:1);ri<table.rows.length;(mobile?ri+=nextRow+1:ri++))
	{
		var stageNameCell = table.rows[ri].cells[1]; //获取名字的格
		if (mobile)
		{
			var nextRow = table.rows[ri].cells[0].rowSpan++; //增加一跨行
			var newRow = table.insertRow(ri+nextRow);
			newRow.bgColor = table.rows[ri].bgColor;
			var newCell = newRow.insertCell(0); //添加新格
		}else
		{
			var newCell = table.rows[ri].insertCell(2); //添加新格
		}

		var link1 = stageNameCell.querySelector("a");
		var link2 = stageNameCell.querySelector("a:nth-of-type(2)");
		var stage1 = stageList.filter(function(item){
			return item.name == link1.textContent;
		})[0];
		if (stage1 == undefined) //如果发现没有数据的图,跳过
		{
			console.error("没有主关卡数据",link1.textContent)
			continue;
		}
		var stage2 = stage1.subStage.filter(function(item){
			return item.name == link2.textContent;
		})[0];
		if (stage2 == undefined) //如果发现没有数据的图,跳过
		{
			console.error("没有子关卡数据",link2.textContent)
			continue;
		}
		//newCell.appendChild(document.createTextNode(stage2.stamina + "体"));
		//newCell.appendChild(document.createElement("br"));
		newCell.appendChild(document.createTextNode("协力" + Math.round(stage2.stamina/2) + "体"));
		if (!mobile) newCell.appendChild(document.createElement("br")); else newCell.appendChild(document.createTextNode(","));
		newCell.appendChild(document.createTextNode(stage2.battles + "层"));
	}
}


function ioConfigDialog()
{
	var box = document.querySelector("#io-config-dialog");
	if (box != undefined) return box;

	var box = document.createElement("div");
	box.id = box.className = "io-config-dialog";
	box.className = "display-none";

	var txtBox = document.createElement("div");box.appendChild(txtBox);
	txtBox.className = "text-box";
	var divConfig = document.createElement("div");txtBox.appendChild(divConfig);
	divConfig.className = "text-lbl-box";
	var lblConfig = document.createElement("label");divConfig.appendChild(lblConfig);
	lblConfig.appendChild(document.createTextNode("设置:"));
	lblConfig.appendChild(document.createElement("br"));
	var txtConfig = document.createElement("textarea");lblConfig.appendChild(txtConfig);
	txtConfig.id = txtConfig.className = "text-config";
	txtConfig.value = "";
	box.configText = txtConfig;

	var divStageList = document.createElement("div");txtBox.appendChild(divStageList);
	divStageList.className = "text-lbl-box";
	var lblStageList = document.createElement("label");divStageList.appendChild(lblStageList);
	lblStageList.appendChild(document.createTextNode("地下城列表:"));
	lblStageList.appendChild(document.createElement("br"));
	var txtStageList = document.createElement("textarea");lblStageList.appendChild(txtStageList);
	txtStageList.id = txtStageList.className = "text-stage-list";
	txtStageList.value = "";
	box.stageListText = txtStageList;

	var btnBox = document.createElement("div");box.appendChild(btnBox);
	btnBox.className = "botton-box";
	var btnIpt = document.createElement("input");btnBox.appendChild(btnIpt);
	btnIpt.type = "button";
	btnIpt.id = btnIpt.className = "input-config";
	btnIpt.value = "导入设置";
	btnIpt.onclick = function(){
		var bk = loadConfig(txtConfig.value,txtStageList.value,true);
		if (bk[0] && bk[1])
		{
			saveConfig();
			alert("😄导入成功");
		}else
		{
			if(!bk[0])alert("😰该设置信息格式不正确");
			if(!bk[1])alert("😰该地下城列表信息格式不正确");
		}
	}

	var btnCls = document.createElement("input");btnBox.appendChild(btnCls);
	btnCls.type = "button";
	btnCls.id = btnCls.className = "close-dialog";
	btnCls.value = "关闭";
	btnCls.onclick = function(){box.classList.add("display-none");}

	return box;
}