// ==UserScript==
// @name route assistant
// @namespace myhead
// @description 金书红颜录路线武功规划脚本,需配合相关维基页面使用
// @version 1
// @grant none
// @include
// ==/UserScript==
/*
oResult={
'拳':[aRegExpSearchResult1{[0](matched content),[1](captured content in parenthesis),[2],index,input},aRegExpSearchResult2...],
'剑':[],
'兵':[],
'特':[],
'暗':[],
'内':[],
'轻':[],
'余':[]
}
Pos= aC1[i] ={
__Con: {
sName: route position name,
sCon: RegExp context of the position,
nStart: start index in sCon,
nEnd: end index in sCon
},
next: []
//next is deeper list of route option object
}
*/
var aC1= [],
//aC1 correspond to the list of route root object
aRoute=[],
oResult={},
sOrigin='',
sResult='',
t;
var mainDiv=document.createElement('div'),
navi=document.createElement('div'),
div1=document.createElement('div'),
div2=document.createElement('div'),
div2p=document.createElement('code'),
div2f=document.createElement('div'),
round=document.createElement('select'),
speci=document.createElement('span'),
toggle= document.createElement('button'),
oTarget= {};
toggle.innerHTML="打开路线武功规划器"
toggle.onclick=function(){
if(sOrigin== '') main();
mainDiv.style.display='';
};
window.onload=function(){
oTarget= document.getElementById('bodyContent');
oTarget.insertBefore(toggle,oTarget.firstChild);
};
function main(){
//search route and set UI;
if(!oTarget){
alert('找不到源数据');
return;
};
sOrigin=oTarget.textContent;
var rP1= /#(.+)/g;
for(var i=0,aTemp;i<100;i++) {
aTemp=rP1.exec(sOrigin);
//aTemp contains [0] [1] .index .input
if (aTemp== null) break;
aC1[i]={
//aC1[i] is route option object
__Con: {
sPath: aTemp[0],
sName: aTemp[1],
sCon: aTemp.input,
nStart: aTemp.index,
nEnd: undefined
},
next: []
//next is deeper list of route option object
};
//initialise the route result array
aRoute[i]= aC1[i];
if(i>0)
aC1[i-1].__Con.nEnd= aTemp.index-1;
};
//create UI and set up initial option list
mainDiv.setAttribute('style','position: absolute; left: 200px; top: 100px; width: 800px; height: 600px; background: white; border: solid #E0E0E0; overflow: auto;resize: both;');
//
navi.innerHTML=
"<button onclick='div1.style.display=\"\";div2.style.display=\"none\";'>路线选择</button>"+
"<button onclick='div2.style.display=\"\";div1.style.display=\"none\";'>武功统计</button>"+
"<button onclick='mainDiv.style.display=\"none\";' style='float: right;'>隐藏</button>";
navi.setAttribute('style','border-bottom: solid #F0F0F0; background: #F0F0F0');navi.setAttribute('style','border-bottom: solid #F0F0F0;background: #F0F0F0');
div2.style.display='none';
div2.innerHTML+= '请选择周目:';
for(var i=1;i<7;i++)
round.innerHTML+='<option value='+i+'>'+i+'周</option>';
div2.appendChild(round);
button= document.createElement('button');
button.innerHTML='开始统计';
button.onclick= analyse;
div2.appendChild(button);
//create filter option bar div2f
div2f.innerHTML+= '结果过滤器:';
speci.innerHTML+=
'名称显示<select><option value=1 selected>简名</option><option value=2>全名</option></select> '+
'类别<select><option value=0 selected> </option><option value="拳">拳</option><option value="剑">剑</option><option value="兵">兵</option><option value="特">特</option><option value="暗">暗</option><option value="内">内</option><option value="轻">轻</option><option value="[^拳剑兵特暗内轻]">其他</option></select>'+
'阴阳<select><option value=0 selected> </option><option value="阴">阴</option><option value="阳">阳</option></select>'+
'最低数值<select><option value=0 selected> </option><option value=2 >2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option></select>';
div2f.appendChild(speci);
button= document.createElement('button');
button.innerHTML='过滤结果';
button.onclick=filter;
div2f.appendChild(button);
div2.appendChild(div2f);
div2.appendChild(div2p);
var tarList=document.createElement('ol');
for(var i=0,li,doList;i<aC1.length;i++){
//set up the root group
li= document.createElement('li');
li.innerHTML=aC1[i].__Con.sName;
doList= dive(aC1[i],1);
//set up the first layer option
if(doList.length>0){
var select=document.createElement('select');
select.onchange=routeQuery;
select.innerHTML+="<option value='"+i+"' selected ></option>"
for(var j=0;j<doList.length;j++){
//add drop-down list for each option
select.innerHTML+=
"<option value='"+i+"."+j+"' >"+doList[j].__Con.sName+"</option>"
};
li.appendChild(select);
};
tarList.appendChild(li);
};
div1.innerHTML='<button onclick="checkBinding();">检查路线冲突</button>';
div1.appendChild(tarList);
mainDiv.appendChild(navi);
mainDiv.appendChild(div1);
mainDiv.appendChild(div2);
document.body.appendChild(mainDiv);
}
function dive(Pos,nSym){
//dive into route chain,group represents the number of option root
var rP= new RegExp('\\s'+nSym+'(.*)','g'),
sContext= Pos.__Con.sCon.substring(Pos.__Con.nStart,Pos.__Con.nEnd);
for(var i=0,aTemp;i<100;i++) {
aTemp= rP.exec(sContext);
if(aTemp== null) break;
Pos.next[i]={
__Con: {
sPath: Pos.__Con.sPath+'-'+aTemp[1],
sName: aTemp[1],
sCon: aTemp.input,
nStart: aTemp.index,
nEnd: undefined
},
next: []
};
if(i>0) Pos.next[i-1].__Con.nEnd= aTemp.index-1;
}
return Pos.next;
//the newly matched route to create drop-down of
}
function sort(aEntry,aTarget){
var i,nIndi;
if(!aTarget[0]){
aTarget[0]=aEntry;
return;
}
if(!aEntry[1]) nIndi=0;
else nIndi=parseInt(aEntry[1].match(/\d/)[0]);
for(i=0;i<aTarget.length;i++){
if(nIndi< aTarget[i][1]){
for(var j=aTarget.length-1;j>= i;j--){
aTarget[j+1]= aTarget[j];
}
break;
}
}
aTarget[i]= aEntry;
}
//following fuctions are event handle
function routeQuery(){
//connecting with selcet.onchange, the event handle to search option of drop-down list,whose value corresponds to the index of content array.Then create relevant drop-down list.
while(this.nextSibling)
this.parentNode.removeChild(this.nextSibling);
if(this.value== this.firstChild.value) return;
var aValue=this.value.match(/\d+/g),
//[this] is the node elements triggering the event.[this.value] has form like'1.2.3'
Pos=aC1[aValue[0]],
//Pos is route option object
nSym= 0;
//nSym is the current route layer of Pos
for(var i=1;i<aValue.length;i++){
//convert string path in select's value to virtual array path
Pos=Pos.next[aValue[i]];
nSym++;
};
var list= dive(Pos,nSym+1);
if (list.length>0) {
var select=document.createElement('select');
select.onchange=routeQuery;
select.innerHTML+="<option value='"+this.value+"' selected ></option>";
for(var j=0;j<list.length;j++){
select.innerHTML+=
"<option value='"+this.value+"."+j+"' >"+list[j].__Con.sName+"</option>";
};
this.parentNode.appendChild(select);
}
//if there is no sub option in deeper layer,log the result
aRoute[aValue[0]]= Pos;
}
//connect with the button '开始统计'
function analyse(){
oResult={};
for(var i=0,oT;i<aRoute.length;i++){
var rP2=/\S+?(\+[1-9][阴阳]?)?(\-\S)?(\?[1-6])?(?=\s|$)/gm;
oT=aRoute[i].__Con;
sResult=oT.sCon.substring(oT.nStart,oT.nEnd);
t=sResult.match(/@.*/);
if(!t) continue;
else sResult=t[0].substring(1);
for(var j=0,aT=[];j<200;j++){
aT=rP2.exec(sResult);
//at[0]-- content; at[1]-- +[rank][yinyang]; at[2]-- -[type]; at[3]-- ?[round]
if(!aT) break;
if(aT[3] && parseInt(aT[3].substring(1))> round.value) continue;
if(!aT[2]) aT[2]='未分类';
else aT[2]=aT[2].substring(1);
if(!oResult[aT[2]]) oResult[aT[2]]=[];
sort(aT,oResult[aT[2]]);
}
}
sResult='';
//output
for(var x in oResult){
sResult+= '类别——'+x+':<br /> ';
var rTp= /[^-?\s]+/;
for(var i=0;i<oResult[x].length;i++){
sResult+= oResult[x][i][0]+' ';
};
sResult+='<br /><br />';
}
div2p.innerHTML= sResult;
}
//connect with button in filter bar
function filter(){
var aOut= speci.children,
rTp= /[^-?\s]+/;
sResult= '';
//aOut[1]-- string representing type; aOut[2]-- string representing yin yang; aOut[3]-- number representing value rank
for(var x in oResult){
if(aOut[1].value!= '0'){
var rP=new RegExp(aOut[1].value);
if(!rP.test(x)) continue;
}
sResult+= '类别——'+x+':<br /> ';
if(aOut[0].value== 1){
for(var i= 0,aTemp;i<oResult[x].length;i++){
aTemp=oResult[x][i];
if(aOut[2].value!= '0')
if(aTemp[1])
if(t= aTemp[1].match(/[阴阳]/))
if(t[0]!= aOut[2].value)
continue;
if(aOut[3].value== '0' || parseInt(aTemp[1].match(/\d/)[0])>= aOut[3].value)
sResult+= aTemp[0].match(rTp)[0]+' ';
};
}
else{
for(var i= 0,aTemp;i<oResult[x].length;i++){
aTemp=oResult[x][i];
if(aOut[2].value!= '0')
if(aTemp[1])
if(!(new RegExp(aOut[2].value).test(aTemp[1])))
continue;
if(aOut[3].value== '0' || parseInt(aTemp[1].match(/\d/)[0])> aOut[3].value)
sResult+= aTemp[0]+' ';
}
}
sResult+='<br /><br />';
}
div2p.innerHTML= sResult;
}
//connect with button to confirm proper binding
function checkBinding(){
var aBind=[],Compare={},sCollision='';
for(var i=0;i<aRoute.length;i++){
t= aRoute[i];
t=t.__Con;
var aT= t.sPath.split(/-/);
for(var j=0;j<aT.length;j++){
Compare[aT[j].match(/[^ ]+/)[0]]= 1;
};
var rP= /[^ \-\n]*bind\s*([^ \-\n]+)/g;
for(var j=0,aT1;j<100;j++){
aT1= rP.exec(t.sPath);
if(aT1) aBind.push(aT1);
else break;
}
}
for(var i=0,aT;i<aBind.length;i++){
if(!Compare[aBind[i][1]]) sCollision+= aBind[i].input+"\n";
}
if(sCollision!= '')
alert ('路线冲突:\n'+sCollision.replace(/bind/g,'绑定'));
else
alert ('无冲突');
}