//-----------------------------------------------------------------------------
// [WoD] Extra Statistics
// Copyright (c) Fenghou, Tomy, DotIN13, ShakeSS
// This script can generate additional statistical data in the dungeon and duel report pages.
// When you entered the details or statistics page of reports, a new button will appear beside
// the details button. At the details page, the new button is "Extra Stat", which will show
// the statistics of the current level when you click it. At the statistics page, the new
// button is "Entire Extra Stat", which will show the statistics of entire dungeon.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// If you want to add a new Stat table, you should create a new sub class of CInfoList,
// and use CStat::RegInfoList() to register your new info list.
// A detailed example is CILItemDamage.
//-----------------------------------------------------------------------------
// 此版本的依赖项替换为gitee以保证国内访问
// ==UserScript==
// @name WoD 战报额外统计信息与导出
// @namespace fenghou
// @description Generate additional statistical data in the dungeon and duel report pages
// @icon http://info.world-of-dungeons.org/wod/css/WOD.gif
// @include http*://*.world-of-dungeons.*/wod/spiel/*dungeon/report.php*
// @include http*://*.world-of-dungeons.*/wod/spiel/tournament/*duell.php*
// @include http*://*.wannaexpresso.*/wod/spiel/*dungeon/report.php*
// @include http*://*.wannaexpresso.*/wod/spiel/tournament/*duell.php*
// @require https://code.jquery.com/jquery-3.3.1.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/Blob.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.form.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/dayjs.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/plugin/customParseFormat.js
// @require https://code.jquery.com/ui/1.13.2/jquery-ui.min.js
// @modifier Christophero
// @version 2023.03.14.1
// ==/UserScript==
(function () {
// COMMON FUNCTIONS ///////////////////////////////////////////////////////////
// Choose contents of the corresponding language
// Contents: {Name1 : [lang1, lang2, ...], Name2 : [lang1, lang2, ...], ...}
// return: Local contents, or null
// It will edit the input contents directly, so the returned object is not necessary
function GetLocalContents(Contents) {
function GetLanguageId() {
var langText = null;
var allMetas = document.getElementsByTagName("meta");
for (var i = 0; i < allMetas.length; ++i) {
if (allMetas[i].httpEquiv == "Content-Language") {
langText = allMetas[i].content;
break;
}
}
if (langText === null)
return false;
switch (langText) {
case "en":
return 0;
case "cn":
return 1;
default:
return null;
}
}
var nLangId = GetLanguageId();
if (nLangId === null)
return null;
if (Contents instanceof Object) {
for (var name in Contents)
Contents[name] = Contents[name][nLangId];
return Contents;
} else
return null;
}
function CompareString(a, b) {
a = a || "";
b = b || "";
return a.toLowerCase().localeCompare(b.toLowerCase(), "zh-CN-u-co-pinyin");
}
function CreateElementHTML(Name, Content /* , [AttrName1, AttrValue1], [AttrName2, AttrValue2], ... */) {
var HTML = '<' + Name;
for (var i = 2; i < arguments.length; ++i)
HTML += ' ' + arguments[i][0] + '="' + arguments[i][1] + '"';
HTML += (Content != null && Content !== "") ? ('>' + Content + '</' + Name + '>') : (' />');
return HTML;
}
function DbgMsg(Text) {
if (DEBUG) alert(Text);
}
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (needle) {
for (var i = 0; i < this.length; i++) {
if (this[i] === needle) {
return i;
}
}
return -1;
};
}
initJQUIStyle();
/**
* 初始化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-progressbar .ui-progressbar-value {transition: width 0.7s ease 0s;} " +
"#progressbar .progress-label {position: absolute; left: 48%; font-weight: bold; text-shadow: 1px 1px 0 #fff; height: 31px; display: flex; justify-content: enter; align-items: center;}" +
"@media (min-width:1px) { .ui-dialog { width: 95% !important; } } " +
"@media (min-width: 768px) { .ui-dialog { max-width:900px !important; width:95% !important; } }";
}
// COMMON STAT FUNCTIONS ///////////////////////////////////////////////////////////
function getSum(numArr) {
var nTotal = 0;
for (var i = 0; i < numArr.length; i++) {
nTotal = nTotal + Number(numArr[i]);
}
return nTotal;
}
function getAverage(numArr) {
return getSum(numArr) / numArr.length;
}
// see http://www.johndcook.com/blog/2008/09/26/comparing-three-methods-of-computing-standard-deviation/
// for discussion on choice of algorithm
function getVariance(numArr) {
if (numArr.length <= 1) {
return 0;
}
var nAvg = getAverage(numArr);
var nTempSum = 0;
for (var i = 0; i < numArr.length; i++) {
nTempSum = nTempSum + Math.pow(Number(numArr[i]) - nAvg, 2);
}
return nTempSum / (numArr.length - 1);
}
// sample standard deviation
function getSTD(numArr) {
return Number(Math.sqrt(getVariance(numArr)).toFixed(2));
}
function getMax(numArr) {
return Math.max.apply(null, numArr);
}
function getMin(numArr) {
return Math.min.apply(null, numArr);
}
// EXTERN FUNCTIONS ///////////////////////////////////////////////////////////
/**
* A utility function for defining JavaScript classes.
*
* This function expects a single object as its only argument. It defines
* a new JavaScript class based on the data in that object and returns the
* constructor function of the new class. This function handles the repetitive
* tasks of defining classes: setting up the prototype object for correct
* inheritance, copying methods from other types, and so on.
*
* The object passed as an argument should have some or all of the
* following properties:
*
* name: The name of the class being defined.
* If specified, this value will be stored in the classname
* property of the prototype object.
*
* extend: The constructor of the class to be extended. If omitted,
* the Object( ) constructor will be used. This value will
* be stored in the superclass property of the prototype object.
*
* construct: The constructor function for the class. If omitted, a new
* empty function will be used. This value becomes the return
* value of the function, and is also stored in the constructor
* property of the prototype object.
*
* methods: An object that specifies the instance methods (and other shared
* properties) for the class. The properties of this object are
* copied into the prototype object of the class. If omitted,
* an empty object is used instead. Properties named
* "classname", "superclass", and "constructor" are reserved
* and should not be used in this object.
*
* statics: An object that specifies the static methods (and other static
* properties) for the class. The properties of this object become
* properties of the constructor function. If omitted, an empty
* object is used instead.
*
* borrows: A constructor function or array of constructor functions.
* The instance methods of each of the specified classes are copied
* into the prototype object of this new class so that the
* new class borrows the methods of each specified class.
* Constructors are processed in the order they are specified,
* so the methods of a class listed at the end of the array may
* overwrite the methods of those specified earlier. Note that
* borrowed methods are stored in the prototype object before
* the properties of the methods object above. Therefore,
* methods specified in the methods object can overwrite borrowed
* methods. If this property is not specified, no methods are
* borrowed.
*
* provides: A constructor function or array of constructor functions.
* After the prototype object is fully initialized, this function
* verifies that the prototype includes methods whose names and
* number of arguments match the instance methods defined by each
* of these classes. No methods are copied; this is simply an
* assertion that this class "provides" the functionality of the
* specified classes. If the assertion fails, this method will
* throw an exception. If no exception is thrown, any
* instance of the new class can also be considered (using "duck
* typing") to be an instance of these other types. If this
* property is not specified, no such verification is performed.
**/
function DefineClass(data) {
// Extract the fields we'll use from the argument object.
// Set up default values.
var classname = data.name;
var superclass = data.extend || Object;
var constructor = data.construct || function () {};
var methods = data.methods || {};
var statics = data.statics || {};
var borrows;
var provides;
// Borrows may be a single constructor or an array of them.
if (!data.borrows) borrows = [];
else if (data.borrows instanceof Array) borrows = data.borrows;
else borrows = [data.borrows];
// Ditto for the provides property.
if (!data.provides) provides = [];
else if (data.provides instanceof Array) provides = data.provides;
else provides = [data.provides];
// Create the object that will become the prototype for our class.
var proto = new superclass();
// Delete any noninherited properties of this new prototype object.
for (var p in proto) if (proto.hasOwnProperty(p)) delete proto[p];
// Borrow methods from "mixin" classes by copying to our prototype.
for (var i = 0; i < borrows.length; i++) {
var c = data.borrows[i];
borrows[i] = c;
// Copy method properties from prototype of c to our prototype
for (var p in c.prototype) {
if (typeof c.prototype[p] != "function") continue;
proto[p] = c.prototype[p];
}
}
// Copy instance methods to the prototype object
// This may overwrite methods of the mixin classes
for (var p in methods) proto[p] = methods[p];
// Set up the reserved "constructor", "superclass", and "classname"
// properties of the prototype.
proto.constructor = constructor;
proto.superclass = superclass;
// classname is set only if a name was actually specified.
if (classname) proto.classname = classname;
// Verify that our prototype provides all of the methods it is supposed to.
for (var i = 0; i < provides.length; i++) {
// for each class
var c = provides[i];
for (var p in c.prototype) {
// for each property
if (typeof c.prototype[p] != "function") continue; // methods only
if (p == "constructor" || p == "superclass") continue;
// Check that we have a method with the same name and that
// it has the same number of declared arguments. If so, move on
if (
p in proto &&
typeof proto[p] == "function" &&
proto[p].length == c.prototype[p].length
)
continue;
// Otherwise, throw an exception
throw new Error(
"Class " +
classname +
" does not provide method " +
c.classname +
"." +
p
);
}
}
// Associate the prototype object with the constructor function
constructor.prototype = proto;
// Copy static properties to the constructor
for (var p in statics) constructor[p] = statics[p];
// Finally, return the constructor function
return constructor;
}
/**
* Throughout, whitespace is defined as one of the characters
* "\t" TAB \u0009
* "\n" LF \u000A
* "\r" CR \u000D
* " " SPC \u0020
*
* This does not use Javascript's "\s" because that includes non-breaking
* spaces (and also some other characters).
*/
/**
* Determine whether a node's text content is entirely whitespace.
*
* @param nod A node implementing the |CharacterData| interface (i.e.,
* a |Text|, |Comment|, or |CDATASection| node
* @return True if all of the text content of |nod| is whitespace,
* otherwise false.
*/
function is_all_ws(nod) {
// Use ECMA-262 Edition 3 String and RegExp features
return !/[^\t\n\r ]/.test(nod.data);
}
/**
* Determine if a node should be ignored by the iterator functions.
*
* @param nod An object implementing the DOM1 |Node| interface.
* @return true if the node is:
* 1) A |Text| node that is all whitespace
* 2) A |Comment| node
* and otherwise false.
*/
function is_ignorable(nod) {
return (
nod.nodeType == Node.COMMENT_NODE || // A comment node
(nod.nodeType == Node.TEXT_NODE && is_all_ws(nod))
); // a text node, all ws
}
/**
* Version of |previousSibling| that skips nodes that are entirely
* whitespace or comments. (Normally |previousSibling| is a property
* of all DOM nodes that gives the sibling node, the node that is
* a child of the same parent, that occurs immediately before the
* reference node.)
*
* @param sib The reference node.
* @return Either:
* 1) The closest previous sibling to |sib| that is not
* ignorable according to |is_ignorable|, or
* 2) null if no such node exists.
*/
function node_before(sib) {
while ((sib = sib.previousSibling)) {
if (!is_ignorable(sib)) return sib;
}
return null;
}
/**
* Version of |nextSibling| that skips nodes that are entirely
* whitespace or comments.
*
* @param sib The reference node.
* @return Either:
* 1) The closest next sibling to |sib| that is not
* ignorable according to |is_ignorable|, or
* 2) null if no such node exists.
*/
function node_after(sib) {
while ((sib = sib.nextSibling)) {
if (!is_ignorable(sib)) return sib;
}
return null;
}
/**
* Version of |lastChild| that skips nodes that are entirely
* whitespace or comments. (Normally |lastChild| is a property
* of all DOM nodes that gives the last of the nodes contained
* directly in the reference node.)
*
* @param par The reference node.
* @return Either:
* 1) The last child of |sib| that is not
* ignorable according to |is_ignorable|, or
* 2) null if no such node exists.
*/
function last_child(par) {
var res = par.lastChild;
while (res) {
if (!is_ignorable(res)) return res;
res = res.previousSibling;
}
return null;
}
/**
* Version of |firstChild| that skips nodes that are entirely
* whitespace and comments.
*
* @param par The reference node.
* @return Either:
* 1) The first child of |sib| that is not
* ignorable according to |is_ignorable|, or
* 2) null if no such node exists.
*/
function first_child(par) {
var res = par.firstChild;
while (res) {
if (!is_ignorable(res)) return res;
res = res.nextSibling;
}
return null;
}
/**
* Version of |data| that doesn't include whitespace at the beginning
* and end and normalizes all whitespace to a single space. (Normally
* |data| is a property of text nodes that gives the text of the node.)
*
* @param txt The text node whose data should be returned
* @return A string giving the contents of the text node with
* whitespace collapsed.
*/
function data_of(txt) {
var data = txt.data;
// Use ECMA-262 Edition 3 String and RegExp features
data = data.replace(/[\t\n\r ]+/g, " ");
if (data.charAt(0) == " ") data = data.substring(1, data.length);
if (data.charAt(data.length - 1) == " ")
data = data.substring(0, data.length - 1);
return data;
}
function split_id(id) {
const segs = id.split("_");
let obj = { a: 0, b: 0, c: 0, d: 0 };
if (segs[1]) obj.a = parseInt(segs[1]);
if (segs[2]) obj.a = parseInt(segs[1]);
if (segs[3]) obj.a = parseInt(segs[1]);
if (segs[4]) obj.a = parseInt(segs[1]);
return obj;
}
function compare_id(id1, id2) {
let obj1 = split_id(id1);
let obj2 = split_id(id2);
return obj1.a - obj2.a
? obj1.a - obj2.a
: obj1.b - obj2.b
? obj1.b - obj2.b
: obj1.c - obj2.c
? obj1.c - obj2.c
: obj1.d - obj2.d;
}
// CLASSES ////////////////////////////////////////////////////////////////////
// NextNode: the node next to the statistics node when it is created
function CStat(NextNode, InfoDiv) {
this._HTML = '';
this._reportInfoDiv = InfoDiv;
this._gInfoList = [];
this.iscurrentPage = true;
this.nTotalPages = 0;
this.nReadPages = 0;
this.nReadRows = 0;
this.nTotalRows = 0;
this.setNode = function (newNode) {
if (newNode.id == "stat_all") {
this._Node = newNode;
this._Node.innerHTML = '';
}
else {
if (this._Node) {
var divs = newNode.parentNode.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
if (divs[i].id == "stat_all") {
newNode.parentNode.removeChild(divs[i]);
break;
}
}
}
var NewSection = document.createElement("div");
NewSection.id = "stat_all";
NewSection.className = "stat_all tab";
if (newNode.parentNode)
this._Node = newNode.parentNode.insertBefore(NewSection, newNode);
else {
this._Node = NewSection;
newNode.appendChild(NewSection);
}
}
this._HTML = '';
};
this.setNode(NextNode);
this._reportInfoDiv.appendChild(document.createElement('table'));
}
CStat.prototype._Write = function (Text) {
this._HTML += Text;
};
CStat.prototype._Flush = function () {
this._Node.innerHTML = this._HTML;
};
CStat.prototype.RegInfoList = function (InfoList) {
if (InfoList instanceof CInfoList) {
this._gInfoList.push(InfoList);
return true;
}
return false;
};
CStat.prototype.SaveInfo = function (Info) {
for (var i = 0; i < this._gInfoList.length; ++i)
this._gInfoList[i].SaveInfo(Info);
};
CStat.prototype.getTab = function (isExport, showhide) {
function FactoryTabClick(Id) {
return function () {
CStat.OnTabClick(Id);
};
}
var tab = document.createElement('li');
tab.className = 'not_selected';
var title = Local.Text_Button_ShowAll;
var id = 'showall';
if (showhide === true) {
title = Local.Text_Button_ShowAll;
id = 'showall';
}
else {
tab.id = 'tab_hideall';
title = Local.Text_Button_HideAll;
id = 'hideall';
}
tab.id = 'tab_' + id;
var a = document.createElement('A');
a.id = 'show_all_a';
var name = document.createTextNode(title);
a.appendChild(name);
a.href = '#';
if (isExport)
a.setAttribute("onclick", "st('" + id + "');");
else
a.addEventListener("click", FactoryTabClick(id), false);
tab.appendChild(a);
return tab;
};
CStat.prototype.Show = function (isExport) {
this._Node.innerHTML = '';
var tabs = document.createElement("ul");
this._Node.appendChild(tabs);
var bar = document.createElement('div');
bar.id = 'stat_bar';
bar.className = 'bar';
this._Node.appendChild(bar);
var tabDivs = [];
var isFirst = true;
for (var i = 0; i < this._gInfoList.length; ++i) {
var infoNode = this._gInfoList[i].Show(isExport);
var tab = this._gInfoList[i].getTab(isExport);
if (tab && infoNode) {
tabs.appendChild(tab);
this._Node.appendChild(infoNode);
tabDivs.push(infoNode.id);
if (isFirst) {
tab.className = 'selected';
infoNode.style.display = '';
isFirst = false;
}
else {
tab.className = 'not_selected';
infoNode.style.display = 'none';
}
}
}
tabs.appendChild(this.getTab(isExport, true));
tabs.appendChild(this.getTab(isExport, false));
this._Node.setAttribute('tabs', tabDivs.join(','));
if (!isExport) {
this._Node.appendChild(document.createElement('hr'));
//this._Node.appendChild(this._reportInfoDiv);
this.ShowProgress();
}
if (!this.iscurrentPage) {
this._reportInfoDiv.style.display = 'none';
this._Node.appendChild(this._reportInfoDiv);
}
//this._reportInfoDiv.parentNode.removeChild(this._reportInfoDiv);
};
CStat.prototype.ShowProgress = function () {
var widthP = 1;
var currentP = 1;
if (reportInfoDiv) {
if (this.nReadPages < 1)
currentP = 1;
else
currentP = this.nReadPages
if (this.nTotalPages === 0 || this.nTotalRows === 0)
widthP = 1;
else
widthP = parseInt(((currentP - 1) / this.nTotalPages + this.nReadRows / (this.nTotalRows * this.nTotalPages)) * 100);
reportInfoDiv.style.width = widthP + '%';
}
};
CStat.prototype._AddEvents = function () {
function OnDelGMValues() {
try {
var ValueList = GM_listValues();
for (var name in ValueList) {
GM_deleteValue(ValueList[name]);
}
alert(Local.Text_DefaultMsg);
} catch (e) {
alert("OnDelGMValues(): " + e);
}
}
document.getElementById("stat_options_default").addEventListener("click", OnDelGMValues, false);
};
CStat.OnTabClick = function (id) {
var statdiv = document.getElementById('stat_all');
var tabs = statdiv.getAttribute('tabs').split(',');
var showall = false;
var lishowall = document.getElementById('tab_showall');
var lihideall = document.getElementById('tab_hideall');
lishowall.className = 'not_selected';
lihideall.className = 'not_selected';
for (var i = 0; i < tabs.length; i++) {
var tabid = tabs[i];
var tab = document.getElementById(tabid);
var li = document.getElementById('tab_' + tabid);
li.className = 'not_selected';
if (id == 'showall') {
lishowall.className = 'selected';
tab.style.display = '';
}
else if (id == 'hideall') {
lihideall.className = 'selected';
tab.style.display = 'none';
}
else {
if (tabid == id) {
tab.style.display = '';
li.className = 'selected';
}
else {
tab.style.display = 'none';
li.className = 'not_selected';
}
}
}
};
///////////////////////////////////////////////////////////////////////////////
function CTable(Title, Id, nColumns, isExport) {
this._Title = Title;
this._Id = Id;
this._filterId = "filter_" + Id;
this._nColumns = nColumns;
this._HeadCellContents = new Array(nColumns);
this._HeadCellLegends = new Array(nColumns);
this._BodyCellContentTypes = new Array(nColumns);
this._HeadCellContentFilters = [];
this._BodyCellContents = [];
this._HTML = '';
this._isExport = isExport;
this._bShow = true;
}
CTable._ContentAttrs = {
string: 'left',
number: 'right',
button: 'center'
};
CTable.prototype.SetHeadCellContentFilters = function ( /* Content1, Content2, ... */) {
for (var i = 0; i < arguments.length; ++i)
if (arguments[i] != null)
this._HeadCellContentFilters.push(arguments[i]);
};
CTable.prototype.SetHeadCellContents = function ( /* Content1, Content2, ... */) {
for (var i = 0; i < this._nColumns; ++i)
this._HeadCellContents[i] = arguments[i] != null ? arguments[i] : "";
};
CTable.prototype.SetHeadCellLegends = function ( /* Content1, Content2, ... */) {
for (var i = 0; i < this._nColumns; ++i)
this._HeadCellLegends[i] = arguments[i] != null ? arguments[i] : "";
};
// Type: a string that is the property name of CTable::ContentAttrs
CTable.prototype.SetBodyCellContentTypes = function ( /* Type1, Type2, ... */) {
for (var i = 0; i < this._nColumns; ++i)
this._BodyCellContentTypes[i] =
arguments[i] != null ? CTable._ContentAttrs[arguments[i]] : "";
};
CTable.prototype.SetBodyCellContents = function ( /* Content1, Content2, ... */) {
var Contents = new Array(this._nColumns);
for (var i = 0; i < this._nColumns; ++i)
Contents[i] = arguments[i] != null ? arguments[i] : "";
this._BodyCellContents.push(Contents);
};
CTable.prototype.CreateHTML = function () {
function Factory(Id) {
return function () {
CTable.OnClickTitle(Id);
};
}
function FactoryFilter(tableid, rowId) {
return function () {
CTable.OnChangeFilter(tableid, rowId);
};
}
function FactorySort(tableid, colId, numberId) {
return function () {
CTable.OnChangeOrder(tableid, colId, numberId);
};
}
function FactoryShowDetail(rowId, activeRows) {
return function () {
activeRows = activeRows.sort(compare_id)
CTable.OnShowDetail(rowId, activeRows);
};
}
var tableid = "table_" + this._Id;
var outputDiv = document.createElement('div');
outputDiv.id = this._Id;
outputDiv.className = 'content';
var headerDiv = document.createElement('div');
outputDiv.appendChild(headerDiv);
headerDiv.className = 'stat_header';
headerDiv.style.textAlign = 'center';
var spanTitle = document.createElement('span');
spanTitle.className = "stat_title clickable";
headerDiv.appendChild(spanTitle);
spanTitle.innerHTML = this._Title;
if (this._isExport)
spanTitle.setAttribute('onclick', "ct('" + tableid + "');");
else
spanTitle.addEventListener("click", Factory(tableid), false);
var table = document.createElement("table");
table.className = "content_table";
table.style.margin = '0px auto';
table.id = tableid;
if (!this._bShow)
table.setAttribute('hide', 'hide');
outputDiv.appendChild(table);
var trHeader = table.insertRow(0);
trHeader.className = "content_table_header";
for (var i = 0; i < this._nColumns; ++i) {
var th = document.createElement("th");
th.className = "content_table stat_order";
th.id = 'th_' + this._Id + i;
th.setAttribute('order', '-1');
var thSpan = document.createElement("span");
thSpan.id = this._Id + "_col" + i;
thSpan.innerHTML = this._HeadCellContents[i];
th.appendChild(thSpan);
var legend = this._HeadCellLegends[i];
var infospan = document.createElement("span");
infospan.id = tableid + '_orderInfo_' + i;
infospan.innerHTML = '<span></span><span></span>';
thSpan.appendChild(infospan);
if (legend) {
infospan.className = legend.className;
if (i > 0) {
thSpan.innerHTML = thSpan.innerHTML + '<br />';
thSpan.appendChild(legend);
var legends = legend.getElementsByTagName('span');
for (var li = 0; li < legends.length; li++) {
var l = legends[li];
l.className = "clickable";
if (this._isExport)
l.setAttribute('onclick', "co('" + tableid + "'," + i + "," + li + ");");
else
l.addEventListener("click", FactorySort(tableid, i, li), false);
}
}
else {
th.appendChild(legend);
var checkboxs = legend.getElementsByTagName('input');
for (var ti = 0; ti < checkboxs.length; ti++) {
var c = checkboxs[ti];
c.id = tableid + '_checkbox_' + i + '_' + ti;
if (this._isExport) {
c.setAttribute('onclick', "cf('" + tableid + "','" + this._filterId + "');");
c.setAttribute('checked', '');
}
else
c.addEventListener("click", FactoryFilter(tableid, this._filterId), false);
}
}
}
else {
thSpan.className = "clickable";
if (this._isExport)
thSpan.setAttribute('onclick', "co('" + tableid + "'," + i + ",0);");
else
thSpan.addEventListener("click", FactorySort(tableid, i, 0), false);
}
trHeader.appendChild(th);
}
if (useFilter) {
var trfilter = table.insertRow(-1);
trfilter.id = this._filterId;
trfilter.className = "content_table_filter_row";
for (var i = 0; i < this._nColumns - 1; ++i) {
var cell = trfilter.insertCell(-1);
if (this._HeadCellContentFilters != null) {
if (this._HeadCellContentFilters[i] != null) {
var filter = this._HeadCellContentFilters[i];
var comboboxid = this._filterId + "_combobox_" + i;
var combobox = document.createElement("select");
cell.appendChild(combobox);
combobox.id = comboboxid;
if (this._isExport)
combobox.setAttribute('onchange', "cf('" + tableid + "','" + this._filterId + "');");
else
combobox.addEventListener("change", FactoryFilter(tableid, this._filterId), false);
combobox.options.add(new Option(Local.Text_Table_AllData, i + '_' + 'all'));
for (var j = 0; j < filter.length; j++)
combobox.options.add(new Option(filter[j], i + '_' + j));
var comboboxOrg = combobox.cloneNode(true);
comboboxOrg.id = 'org_' + comboboxid;
comboboxOrg.style.display = 'none';
cell.appendChild(comboboxOrg);
}
else {
var input = document.createElement("input");
var textid = this._filterId + "_textbox_" + i;
input.type = "text";
input.size = 6;
input.id = textid;
cell.appendChild(input);
}
}
}
var searchButton = document.createElement("input");
searchButton.type = 'button';
searchButton.id = this._filterId + "_button";
searchButton.value = "查询";
searchButton.className = "button";
if (this._isExport)
searchButton.setAttribute('onclick', "cf('" + tableid + "','" + this._filterId + "');");
else
searchButton.addEventListener("click", FactoryFilter(tableid, this._filterId), false);
var buttonCell = trfilter.insertCell(-1);
buttonCell.appendChild(searchButton);
buttonCell.style.textAlign = 'center';
}
for (var i = 0; i < this._BodyCellContents.length; ++i) {
var row = table.insertRow(-1);
row.className = "row" + i % 2;
row.setAttribute('oriorder', i);
var rowId = [];
var infoRowid = tableid + '_' + i;
var infoNode;
for (var j = 0; j < this._nColumns; ++j) {
var rowspan = "";
var content = this._BodyCellContents[i][j];
if (content.show) {
var cell = row.insertCell(-1);
cell.className = "content_table";
cell.style.textAlign = this._BodyCellContentTypes[j];
if (content.rowspan > 1) {
cell.rowSpan = content.rowspan;
cell.style.verticalAlign = 'middle';
}
var valueNode = content.value;
cell.appendChild(valueNode);
if (j == this._nColumns - 1) {
if (this._isExport)
valueNode.setAttribute("onclick", "sd('" + infoRowid + "',['" + content.activeRows.join("','") + "']);");
else
valueNode.addEventListener("click", FactoryShowDetail(infoRowid, this._BodyCellContents[i][0].activeRows), false);
infoNode = valueNode.getAttribute('data');
valueNode.removeAttribute('data');
}
}
rowId.push(j + "_" + this._BodyCellContents[i][j].filterId);
}
row.id = rowId.join(",");
var infoRow = table.insertRow(-1);
infoRow.className = row.className;
infoRow.id = infoRowid;
infoRow.style.display = 'none';
var infoCell = infoRow.insertCell(-1);
infoCell.colSpan = this._nColumns;
if (infoNode) {
infoCell.innerHTML = infoNode;
}
}
return outputDiv;
//this._HTML = outputDiv.outerHTML;
//return this._HTML;
};
CTable.prototype.GetHTML = function () {
return this._HTML;
};
CTable.OnClickTitle = function (Id) {
try {
var Table = document.getElementById(Id);
if (Table.hasAttribute("hide")) {
Table.removeAttribute("hide");
} else {
Table.setAttribute("hide", "hide");
}
} catch (e) {
alert("CTable.OnClickTitle(): " + e);
}
};
CTable.GetNumber = function (cell) {
var numberPatten = /^\s?([\d]+\.?[\d]*)\s?_?\s?([\d]*\.?[\d]*)\s?$/;
var pairTable = cell.firstChild;
var numberString = cell.textContent;
var numbers;
if (pairTable && pairTable.nodeName == "TABLE") {
numberString = pairTable.id;
}
if (numberPatten.test(numberString)) {
numbers = [];
var numberres = numberPatten.exec(numberString);
if (numberres[1])
numbers.push(numberres[1]);
if (numberres[2])
numbers.push(numberres[2]);
}
return numbers;
};
CTable.OnChangeFilter = function (tableId, filterRowId) {
try {
var Table = document.getElementById(tableId);
var filterRow = document.getElementById(filterRowId);
var stringfilters = [];
var orgstringfilters = [];
var numberfilters = [];
var filterString = "";
var showIds = [];
var refilter = 0;
var showHero_0 = document.getElementById(tableId + "_checkbox_0_0");
var showHero_1 = document.getElementById(tableId + "_checkbox_0_1");
var showHero = [showHero_0.checked, showHero_1.checked];
for (var i = 0; i < filterRow.cells.length; i++) {
var cell = filterRow.cells[i];
var stringfilter = document.getElementById(filterRow.id + "_combobox_" + i);
var orgstringfilter = document.getElementById('org_' + filterRow.id + "_combobox_" + i);
var numberfilter = document.getElementById(filterRow.id + "_textbox_" + i);
if (stringfilter) {
stringfilters.push(stringfilter.value);
refilter += stringfilter.selectedIndex > 0 ? 1 : 0;
}
else
stringfilters.push(null);
if (orgstringfilter) {
for (var ii = 0, ij = orgstringfilter.options.length; ii < ij; ++ii) {
if (orgstringfilter.options[ii].value === stringfilter.value) {
orgstringfilter.selectedIndex = ii;
break;
}
}
orgstringfilters.push([stringfilter, orgstringfilter]);
showIds.push([]);
}
if (numberfilter)
numberfilters.push(numberfilter.value);
else
numberfilters.push(null);
}
var index = 0;
var patten = /([\(|\[|>|<|=|]*)\s*([\d]*\.?[\d]*)\s*-?\s*([\d]*\.?[\d]*)\s*([\)|\]|\s]?)/;
for (var i = 2; i < Table.rows.length; i = i + 2) {
var row = Table.rows[i];
var rowInfo = Table.rows[i + 1];
var rowIds = row.id.split(",");
var show = true;
var hero = row.cells[0].getElementsByTagName('a')[0];
var heroKind = hero.getAttribute("kind");
show = showHero[heroKind];
if (show) {
for (var fi = 0; fi < stringfilters.length; fi++) {
var sfilter = stringfilters[fi];
if (!sfilter)
continue;
if (sfilter != fi + "_all" && sfilter != rowIds[fi]) {
show = false;
break;
}
}
}
if (show) {
for (var fi = 0; fi < numberfilters.length; fi++) {
var nfilter = numberfilters[fi];
if (!nfilter)
continue;
else {
var numbers = CTable.GetNumber(row.cells[fi]);
var nfilters = nfilter.split(/\s*[,|,]\s*/);
for (ni = 0; ni < numbers.length; ni++) {
var theFilter = nfilters[ni];
var testString = "";
if (theFilter && patten.test(theFilter)) {
var op = "==";
var res = patten.exec(theFilter);
if (res[1]) {
op = res[1];
if (res[3]) {
if (op == "[") op = ">=";
if (op == "(") op = ">";
if (op == "=") op = "==";
}
}
else {
if (res[3])
op = ">=";
}
testString = numbers[ni] + op + res[2];
if (res[3]) {
op = "<=";
if (res[4]) {
op = res[4];
if (op == "]") op = "<=";
if (op == ")") op = "<";
}
testString += " && " + numbers[ni] + op + res[3];
}
show = eval(testString);
if (!show)
break;
}
}
}
if (!show)
break;
}
}
row.style.display = show ? '' : 'none';
rowInfo.style.display = show ? rowInfo.style.display : 'none';
if (show) {
row.className = "row" + index % 2;
rowInfo.className = row.className;
index++;
for (var fi = 0; fi < orgstringfilters.length; fi++) {
var id = rowIds[fi];
if (showIds[fi].indexOf(id) <= -1)
showIds[fi].push(id);
}
}
}
if (orgstringfilters.length - refilter > 1) {
for (var fi = 0; fi < orgstringfilters.length; fi++) {
var sfilter = orgstringfilters[fi][0];
var sfilterorg = orgstringfilters[fi][1];
if (!sfilter)
continue;
if (refilter == 1 && sfilter.selectedIndex > 0)
continue;
for (var i = sfilter.options.length - 1; i > 0; i--)
sfilter.remove(i);
for (var i = 0; i < sfilterorg.options.length; i++) {
var opt = sfilterorg.options[i];
if (showIds[fi].indexOf(opt.value) > -1) {
var newopt = new Option(opt.text, opt.value);
newopt.selected = opt.selected;
sfilter.add(newopt);
}
}
}
}
} catch (e) {
alert("CTable.OnChangeFilter(): " + e);
}
};
CTable.OnChangeOrder = function (tableId, columnIndex, numberIndex) {
var Table = document.getElementById(tableId);
var index = numberIndex;
var ths = Table.getElementsByTagName("th");
if (index === null)
index = 0;
var th = ths[columnIndex];
var order = th.getAttribute("order");
for (var i = 0; i < ths.length - 1; i++) {
var span = document.getElementById(tableId + '_orderInfo_' + i);
var spans = span.getElementsByTagName('span');
if (spans && spans.length == 2) {
spans[0].innerHTML = '';
spans[1].innerHTML = '';
if (i == columnIndex)
spans[numberIndex].innerHTML = order > 0 ? '▲' : '▼';
}
}
for (var i = 2; i < Table.rows.length - 2; i = i + 2) {
for (var j = i + 2; j < Table.rows.length; j = j + 2) {
var row_1 = Table.rows[i];
var row_1_info = Table.rows[i + 1];
var row_2 = Table.rows[j];
var row_2_info = Table.rows[j + 1];
var cell_1 = row_1.cells[columnIndex];
var cell_2 = row_2.cells[columnIndex];
n1 = CTable.GetNumber(cell_1);
n2 = CTable.GetNumber(cell_2);
var change = false;
if (columnIndex == ths.length - 1) {
var n11 = Number(row_1.getAttribute("oriorder"));
var n12 = Number(row_2.getAttribute("oriorder"));
change = n11 > n12;
}
else {
var c1 = row_1.cells[0].firstChild.className.replace("my", "");
var c2 = row_2.cells[0].firstChild.className.replace("my", "");
var s1 = cell_1.textContent;
var s2 = cell_2.textContent;
var cc = CompareString(c1, c2);
if (cc < 0)
change = false;
else if (cc > 0)
change = true;
else {
if (n1 && n2 && n1.length > 0 && n2.length > 0) {
var number_1 = n1[index] * order;
var number_2 = n2[index] * order;
change = number_1 > number_2;
}
else
change = (CompareString(s1, s2) == order);
}
}
if (change) {
row_2.parentNode.insertBefore(row_2, row_1);
row_2_info.parentNode.insertBefore(row_2_info, row_1);
}
}
Table.rows[i].className = "row" + (i / 2) % 2;
Table.rows[i + 1].className = Table.rows[i].className;
}
th.setAttribute("order", -1 * order);
};
CTable.OnShowDetail = function (rowid, activeRows) {
var row = document.getElementById(rowid);
var cell = row.cells[0];
var button = row.previousSibling.getElementsByTagName('input')[0];
activeRows = activeRows || [];
if (cell) {
if (row.style.display == '') {
button.value = '显示';
row.style.display = 'none';
}
else {
button.value = '隐藏';
row.style.display = '';
}
var table = cell.getElementsByTagName('table')[0];
if (table.rows.length <= 1) {
if (activeRows.length > 0) {
var ids = activeRows[0].split('_');
var level = Number(ids[1]);
var ac = table.insertRow(-1).insertCell(-1);
ac.colSpan = '3';
ac.innerHTML = '<hr/><br />层 ' + level + '<br /><hr/>';
for (var i = 0; i < activeRows.length; i++) {
ids = activeRows[i].split('_');
var newlevel = Number(ids[1]);
if (newlevel != level) {
ac = table.insertRow(-1).insertCell(-1);
ac.colSpan = '3';
ac.innerHTML = '<hr/><br />层 ' + newlevel + '<br /><hr/>';
level = newlevel;
}
var theRow = document.getElementById(activeRows[i]).cloneNode(true);
if (theRow) {
table.appendChild(theRow);
var c = table.insertRow(-1).insertCell(-1);
c.colSpan = '3';
c.innerHTML = '<hr/>';
}
}
}
}
}
};
///////////////////////////////////////////////////////////////////////////////
function CActiveInfo() {
this.nIniRoll;
this.nCurrAction;
this.nTotalActions;
this.Char = new CChar();
this.nCharId;
this.ActionType = new CActionType();
this.Skill = new CSkill();
this.gAttackRoll;
this.gPosition = new CKeyList();
this.nSkillMP;
this.nSkillHP;
this.gItem = new CKeyList();
}
function CPassiveInfo() {
this.Char = new CChar();
this.nCharId;
this.Skill = new CSkill();
this.nDefenceRoll;
this.nSkillMP;
this.gItem = new CKeyList();
this.HitType = new CHitType();
this.bStruckDown;
this.gDamage = [];
this.DamagedItem = new CItem();
this.nItemDamage;
this.nHealedHP;
this.nHealedMP;
}
function CNavi(nLevel, nRoom, nRound, nRow) {
this.nLevel = nLevel;
this.nRoom = nRoom;
this.nRound = nRound;
this.nRow = nRow;
this.toString = function () {
return this.nLevel + '_' + this.nRoom + '_' + this.nRound + '_' + this.nRow;
};
}
function CActionInfo(Navi) {
this.Navi = Navi;
this.Active = new CActiveInfo();
this.gPassive = [];
this.ActiveRow = 'activeRow_' + this.Navi.toString();
}
function CActiveValue(ActiveRow, Value) {
this.Value = Value;
this.ActiveRow = ActiveRow;
}
///////////////////////////////////////////////////////////////////////////////
// Class: Key
// Every key should have two function properties: compareTo() and toString(),
// and can work without initialization parameters
var CKey = DefineClass({
methods: {
compareTo: function (that) {
return this - that;
},
toString: function () {
var theNode = this.toHTMLNode();
return (theNode.nodeType == Node.COMMENT_NODE || theNode.nodeType == Node.TEXT_NODE) ? theNode.data : theNode.outerHTML;
},
toText: function () {
return this.toHTMLNode().textContent;
},
toHTMLNode: function () {
return document.createTextNode("");
}
}
});
CKey.UNKNOWN = -1;
var CKeyList = DefineClass({
extend: CKey,
construct: function () {
this._gKey = [];
},
methods: {
push: function (Key) {
return this._gKey.push(Key);
},
compareTo: function (that) {
var result = this._gKey.length - that._gKey.length;
if (result != 0)
return result;
var i = 0;
while (i < this._gKey.length && this._gKey[i].compareTo(that._gKey[i]) === 0)
++i;
if (i === this._gKey.length)
return 0;
else
return this._gKey[i].compareTo(that._gKey[i]);
},
toHTMLNode: function () {
var ret = document.createElement('span');
ret.innerHTML = this._gKey.join(", ");
return ret;
}
}
});
var CTypeKey = DefineClass({
extend: CKey,
construct: function (TypeText) {
this._sType;
this._nKind = CKey.UNKNOWN;
this._text;
if (TypeText != null) {
this._sType = TypeText;
this._text = TypeText;
this.Init();
}
},
methods: {
Init: function () { },
GetType: function () {
return this._sType;
},
GetKind: function () {
return this._nKind;
},
compareTo: function (that) {
return CompareString(this._sType, that._sType);
},
toText: function () {
return this._text;
},
setText: function (text) {
this._text = text;
},
setKind: function (kind) {
this._nKind = kind;
},
toHTMLNode: function () {
return document.createTextNode(this._text);
}
}
});
// Attack position
var CPositionType = DefineClass({
extend: CTypeKey,
construct: function (PositionText) {
CTypeKey.call(this, PositionText);
}
});
// Action type
var CActionType = DefineClass({
extend: CTypeKey,
construct: function (ActionText) {
CTypeKey.call(this, ActionText);
},
methods: {
Init: function () {
this._text = 'unknown';
if (Local.OrigTextList_AttackActionType.indexOf(this._sType) > -1) {
this._nKind = CActionType.ATTACK;
this.setText(Local.TextList_AttackType[Local.OrigTextList_AttackActionType.indexOf(this._sType)]);
}
else if (Local.OrigTextList_HealActionType.indexOf(this._sType) > -1) {
this._nKind = CActionType.HEAL;
this.setText(Local.TextList_HealType);
}
else if (Local.OrigTextList_BuffActionType.indexOf(this._sType) > -1) {
this._nKind = CActionType.BUFF;
this.setText(Local.TextList_BuffType);
}
else if (Local.OrigTextList_WaitActionType.indexOf(this._sType) > -1) {
this._nKind = CActionType.WAIT;
this.setText(Local.TextList_WaitType);
}
else if (this._sType.indexOf("(") > -1) {
this._nKind = CActionType.ATTACK2;
this.setText("其他");
}
}
}
});
CActionType.ATTACK = 0;
CActionType.HEAL = 1;
CActionType.BUFF = 2;
CActionType.WAIT = 3;
CActionType.ATTACK2 = 4;
// hit type
var CHitType = DefineClass({
extend: CTypeKey,
construct: function (HitClassText) {
CTypeKey.call(this, HitClassText);
},
methods: {
Init: function () {
switch (this._sType) {
case "rep_miss":
this._nKind = CHitType.MISS;
break;
case "rep_hit":
this._nKind = CHitType.HIT;
break;
case "rep_hit_good":
this._nKind = CHitType.GOOD;
break;
case "rep_hit_crit":
this._nKind = CHitType.CRIT;
break;
default:
this._nKind = CKey.UNKNOWN;
}
if (this._nKind != CKey.UNKNOWN)
this.setText(Local.TextList_HitType[this._nKind]);
else
this.setText('');
},
compareTo: function (that) {
return this._nKind - that._nKind;
}
}
});
CHitType.MISS = 0;
CHitType.HIT = 1;
CHitType.GOOD = 2;
CHitType.CRIT = 3;
// heal type
var CHealType = DefineClass({
extend: CTypeKey,
construct: function (HealText) {
CTypeKey.call(this, HealText);
},
methods: {
Init: function () {
switch (this._sType) {
case "HP":
this._nKind = CHealType.HP;
break;
case "MP":
this._nKind = CHealType.MP;
break;
default:
this._nKind = CKey.UNKNOWN;
}
}
}
});
CHealType.HP = 0;
CHealType.MP = 1;
// buff type
var CBuffType = DefineClass({
extend: CTypeKey,
construct: function (BuffText) {
CTypeKey.call(this, BuffText);
}
});
// Damage Type
var CDamageType = DefineClass({
extend: CTypeKey,
construct: function (DamageTypeText) {
CTypeKey.call(this, DamageTypeText);
},
methods: {
Init: function () {
this.setText(this._sType.replace('伤害', ''));
}
}
});
var CElementKey = DefineClass({
extend: CKey,
construct: function (HTMLElement) {
this._Name = '';
this._Href;
this._OnClick;
this._Class;
this._nKind = CKey.UNKNOWN;
if (HTMLElement != null) {
this._Name = HTMLElement.firstChild.data;
this._Href = HTMLElement.href;
this._OnClick = HTMLElement.getAttribute("onclick");
this._Class = HTMLElement.className;
this.Init();
}
},
methods: {
Init: function () { },
GetKind: function () {
return this._nKind;
},
compareTo: function (that) {
var result = this._nKind - that._nKind;
if (result !== 0)
return result;
return CompareString(this._Name, that._Name);
},
toHTMLNode: function () {
if (this._Name != null) {
var ret = document.createElement('A');
var name = document.createTextNode(this._Name);
ret.appendChild(name);
ret.href = this._Href;
ret.setAttribute("onclick", this._OnClick);
ret.setAttribute('kind', this._nKind);
if (this._Class)
ret.className = this._Class;
return ret;
}
else
return document.createTextNode('');
},
toText: function () {
return this._Name;
},
setText: function (name) {
this._Name = name;
}
}
});
var CChar = DefineClass({
extend: CElementKey,
construct: function (HTMLElement) {
CElementKey.call(this, HTMLElement);
},
methods: {
Init: function () {
switch (this._Class) {
case "rep_hero":
case "rep_myhero":
this._nKind = CChar.HERO;
break;
case "rep_monster":
case "rep_myhero_defender":
this._nKind = CChar.MONSTER;
break;
default:
this._nKind = CKey.UNKNOWN;
}
}
}
});
CChar.HERO = 0;
CChar.MONSTER = 1;
var CSkill = DefineClass({
extend: CElementKey,
construct: function (HTMLElement) {
CElementKey.call(this, HTMLElement);
}
});
var CItem = DefineClass({
extend: CElementKey,
construct: function (HTMLElement) {
CElementKey.call(this, HTMLElement);
}
});
var CDamage = DefineClass({
extend: CKey,
construct: function (HTMLElement) {
this._nBasicDmg;
this._nActualDmg;
this._nArmor;
this._sType;
this._cType;
if (HTMLElement != null) {
var Str;
if (HTMLElement.nodeType != Node.TEXT_NODE) {
Str = HTMLElement.getAttribute("onmouseover");
// \1 basic damage
var Patt_BasicDamage = Local.Pattern_BasicDamage;
var result = Patt_BasicDamage.exec(Str);
if (result == null)
throw "CDamage() :" + Str;
this._nBasicDmg = Number(result[1]);
Str = HTMLElement.firstChild.data;
} else
Str = HTMLElement.data;
// \1 actual damage
// \2 armor
// \3 damage type
var Patt_Damage = Local.Pattern_Damage;
var result = Patt_Damage.exec(Str);
if (result == null)
throw "CDamage() :" + Str;
this._nActualDmg = Number(result[1]);
this._nArmor = result[2] != null ? Number(result[2]) : 0;
this._sType = result[3] || "";
this._cType = new CDamageType(this._sType);
if (this._nBasicDmg == null)
this._nBasicDmg = this._nActualDmg + this._nArmor;
}
},
methods: {
GetType: function () {
return this._sType;
},
GetDamageType: function () {
return this._cType;
},
GetBasicDmg: function () {
return this._nBasicDmg;
},
GetArmor: function () {
return this._nArmor;
},
GetActualDmg: function () {
return this._nActualDmg;
},
IsHPDamage: function () {
return Local.OrigTextList_NoneHPDamageType.indexOf(this._sType) <= -1;
},
compareTo: function (that) {
return this._nBasicDmg - that._nBasicDmg;
},
toHTMLNode: function () {
var Str = '';
if (this._sType != null) {
Str = String(this._nBasicDmg);
if (this._nArmor > 0)
Str += " - " + this._nArmor + " -> " + this._nActualDmg;
else if (this._nBasicDmg !== this._nActualDmg)
Str += " -> " + this._nActualDmg;
Str += " " + this._sType;
}
document.createTextNode(Str);
}
}
});
///////////////////////////////////////////////////////////////////////////////
// Class: Value list
// Value list is a special key, it can contains any type of values, including keys
var CValueList = DefineClass({
extend: CKey,
construct: function () {
this._gValue = [];
this._nValue = [];
this._ActiveValue = [];
this._nAvgValue; // unsure type
this._nMaxValue; // unsure type
this._nMinValue; // unsure type
this._nSTDValue; // unsure type
this._nTotalValue; // unsure type
},
methods: {
GetLength: function () {
return document.createTextNode(this._gValue.length);
},
Calculate: function () { },
push: function (ActiveRow, Value) {
this._nValue.push(Value);
if (this._ActiveValue.indexOf(ActiveRow) <= -1)
this._ActiveValue.push(ActiveRow);
var activeValue = new CActiveValue(ActiveRow, Value);
return this._gValue.push(activeValue);
},
compareTo: function (that) {
return this._nAvgValue - that._nAvgValue;
},
AvgValue: function () {
return this.getNode(this._nAvgValue);
},
MaxValue: function () {
return this.getNode(this._nMaxValue);
},
MinValue: function () {
return this.getNode(this._nMinValue);
},
STDValue: function () {
return this.getNode(this._nSTDValue);
},
TotalValue: function () {
return this.getNode(this._nTotalValue);
},
ActiveValue: function () {
return this._ActiveValue;
},
toHTMLNode: function () {
var table = document.createElement('table');
table.style.width = '100%';
var cell = table.insertRow(-1).insertCell(-1);
cell.colSpan = "3";
cell.style.textAlign = 'center';
var ret = document.createElement("span");
var value = this.sortValue(this._nValue);
ret.innerHTML = value.join(", ");
cell.appendChild(ret);
return table;
},
sortValue: function (value) {
return value.sort();
},
getNode: function (data) {
return document.createTextNode(String(data));
},
Legend: function () {
return null;
}
}
});
var CVLString = DefineClass({
extend: CValueList,
construct: function () {
CValueList.call(this);
},
methods: {
Calculate: function () {
this._nAvgValue = "";
this._nMaxValue = "";
this._nMinValue = "";
this._nSTDValue = "";
this._nTotalValue = "";
},
compareTo: function (that) {
return 0;
},
toHTMLNode: function () {
var table = document.createElement('table');
table.style.width = '100%';
var cell = table.insertRow(-1).insertCell(-1);
cell.colSpan = "3";
cell.style.textAlign = 'center';
return table;
}
}
});
var CVLNumber = DefineClass({
extend: CValueList,
construct: function () {
CValueList.call(this);
},
methods: {
Calculate: function () {
this._nTotalValue = 0;
for (var i = 0; i < this._nValue.length; ++i)
this._nTotalValue += Number(this._nValue[i]);
this._nAvgValue = Number((this._nTotalValue / this._gValue.length)).toFixed(2);
this._nMaxValue = getMax(this._nValue);
this._nMinValue = getMin(this._nValue);
this._nSTDValue = getSTD(this._nValue);
},
sortValue: function (value) {
return value.sort(function (a, b) { return b - a; });
}
}
});
// value: [Number1, Number2]
var CVLPairNumber = DefineClass({
extend: CValueList,
construct: function () {
CValueList.call(this);
this._nTotalValue = [0, 0];
this.gValueZero = [];
this.gValueFirst = [];
this.nSorting = [];
},
methods: {
Calculate: function () {
this.setPair();
this.doCalculate();
},
setPair: function () {
for (var i = 0; i < this._nValue.length; ++i) {
var theValue = this._nValue[i];
this.gValueZero.push(theValue[0]);
this.gValueFirst.push(theValue[1]);
this._nTotalValue[0] += theValue[0];
this._nTotalValue[1] += theValue[1];
this.nSorting.push(theValue[0], theValue[1]);
};
},
doCalculate: function () {
this._nAvgValue = new Array(2);
this._nAvgValue[0] = Number((this._nTotalValue[0] / this._gValue.length).toFixed(2));
this._nAvgValue[1] = Number((this._nTotalValue[1] / this._gValue.length).toFixed(2));
this._nMaxValue = new Array(2);
this._nMaxValue[0] = getMax(this.gValueZero);
this._nMaxValue[1] = getMax(this.gValueFirst);
this._nMinValue = new Array(2);
this._nMinValue[0] = getMin(this.gValueZero);
this._nMinValue[1] = getMin(this.gValueFirst);
this._nSTDValue = new Array(2);
this._nSTDValue[0] = getSTD(this.gValueZero);
this._nSTDValue[1] = getSTD(this.gValueFirst);
},
compareTo: function (that) {
if (this._nAvgValue[0] !== 0 || that._nAvgValue[0] !== 0)
return this._nAvgValue[0] - that._nAvgValue[0];
else
return this._nAvgValue[1] - that._nAvgValue[1];
},
toHTMLNode: function () {
var table = document.createElement('table');
table.style.width = '100%';
var cell = table.insertRow(-1).insertCell(-1);
cell.style.textAlign = 'center';
cell.colSpan = "3";
this.nSorting.sort(function (a, b) { return b[0] - a[0]; });
for (var i = 0; i < this.nSorting.length; ++i) {
var ret = document.createElement("span");
ret.className = "pair_value";
var theValue = this.nSorting[i];
var s = document.createElement('span');
s.innerHTML = (theValue[0] != null) ? theValue[0] : 0;
ret.appendChild(s);
s = document.createElement('span');
s.innerHTML = ' [ ' + ((theValue[1] != null) ? theValue[1] : 0) + ' ]';
ret.appendChild(s);
if (i < this.nSorting.length - 1)
ret.appendChild(document.createTextNode(', '));
cell.appendChild(ret);
}
return table;
},
getNode: function (data) {
var table = document.createElement('table');
table.className = "pair_value";
table.id = data[0] + "_" + data[1];
var row = table.insertRow(0);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = String(data[0]);
cell2.innerHTML = String(data[1]);
return table;
},
Legend: function () {
var infospan = document.createElement("span");
infospan.className = "pair_value";
infospan.innerHTML = '<span>ROLL点</span><span>&bnsp;&bnsp;实际值</span>: ';
return infospan;
}
}
});
// value: An Array of CDamage
var CVLDamage = DefineClass({
extend: CVLPairNumber,
construct: function () {
CVLPairNumber.call(this);
},
methods: {
setPair: function () {
for (var i = 0; i < this._nValue.length; ++i) {
var nSumOneAtkValue = [0, 0];
var theActiveValue = this._nValue[i];
for (var j = 0; j < theActiveValue.length; ++j) {
var theValue = theActiveValue[j];
this._nTotalValue[0] += theValue.GetBasicDmg();
this._nTotalValue[1] += theValue.GetActualDmg();
nSumOneAtkValue[0] = nSumOneAtkValue[0] + theValue.GetBasicDmg();
nSumOneAtkValue[1] = nSumOneAtkValue[1] + theValue.GetActualDmg();
}
this.gValueZero.push(nSumOneAtkValue[0]);
this.gValueFirst.push(nSumOneAtkValue[1]);
this.nSorting.push(nSumOneAtkValue);
}
}
}
});
///////////////////////////////////////////////////////////////////////////////
// Class: Info list
function CCellContent(value, rowspan, show, filterId, activeRows) {
this.value = value;
this.rowspan = rowspan;
this.show = show;
this.filterId = filterId;
this.activeRows = activeRows || [];
}
function CKeyType(name, type, legend) {
this.Name = name;
this.Type = type;
this.legend = legend ? legend.cloneNode(true) : null;
this.getValue = function (info) {
var value = info.ValueList;
switch (this.Name) {
case Local.Text_Table_AvgRoll:
case Local.Text_Table_ItemDamagePoints:
return value.AvgValue();
case Local.Text_Table_Times:
return value.GetLength();
case Local.Text_Table_MaxRoll:
return value.MaxValue();
case Local.Text_Table_MinRoll:
return value.MinValue();
case Local.Text_Table_STDRoll:
return value.STDValue();
case Local.Text_Table_Total:
return value.TotalValue();
case Local.Text_Table_RollList:
case Local.Text_Table_DetailList:
var ret = document.createElement("input");
ret.type = "button";
ret.className = "button";
ret.value = Local.Text_Button_Show;
ret.setAttribute("data", value.toString());
return ret;
default:
return document.createTextNode(this.Name);
}
};
}
CKeyType.AvgRoll = function (legend) {
return new CKeyType(Local.Text_Table_AvgRoll, "number", legend);
};
CKeyType.Times = function (legend) {
return new CKeyType(Local.Text_Table_Times, "number", legend);
};
CKeyType.MaxRoll = function (legend) {
return new CKeyType(Local.Text_Table_MaxRoll, "number", legend);
};
CKeyType.MinRoll = function (legend) {
return new CKeyType(Local.Text_Table_MinRoll, "number", legend);
};
CKeyType.STDRoll = function (legend) {
return new CKeyType(Local.Text_Table_STDRoll, "number", legend);
};
CKeyType.TotalRoll = function (legend) {
return new CKeyType(Local.Text_Table_Total, "number", legend);
};
CKeyType.RollList = function (legend) {
return new CKeyType(Local.Text_Table_RollList, "button", legend);
};
CKeyType.DetailList = function (legend) {
return new CKeyType(Local.Text_Table_DetailList, "button", legend);
};
CKeyType.Char = function (legend) {
var _legend = legend;
if (!legend) {
var info = document.createElement("table");
info.className = 'pair_hero';
var hero = info.insertRow(-1).insertCell(-1);
var check = document.createElement("INPUT");
check.type = 'checkbox';
check.value = CChar.HERO;
check.checked = true;
hero.appendChild(check);
hero.appendChild(document.createTextNode('英雄'));
var npc = info.rows[0].insertCell(-1);
check = document.createElement("INPUT");
check.type = 'checkbox';
check.value = CChar.MONSTER;
check.checked = true;
npc.appendChild(check);
npc.appendChild(document.createTextNode('对手'));
_legend = info;
}
return new CKeyType(Local.Text_Table_Char, "string", _legend);
};
CKeyType.ProviderChar = function (legend) {
return new CKeyType(Local.Text_Table_Buffer, "string", legend);
};
CKeyType.ReceiverChar = function (legend) {
return new CKeyType(Local.Text_Table_BuffeReceiver, "string", legend);
};
CKeyType.AttackType = function (legend) {
return new CKeyType(Local.Text_Table_AttackType, "string", legend);
};
CKeyType.Skill = function (legend) {
return new CKeyType(Local.Text_Table_Skill, "string", legend);
};
CKeyType.Item = function (legend) {
return new CKeyType(Local.Text_Table_Item, "string", legend);
};
CKeyType.Position = function (legend) {
return new CKeyType(Local.Text_Table_Position, "string", legend);
};
CKeyType.HealType = function (legend) {
return new CKeyType(Local.Text_Table_HealType, "string", legend);
};
CKeyType.BuffType = function (legend) {
return new CKeyType(Local.Text_Table_BuffType, "string", legend);
};
CKeyType.DamageType = function (legend) {
return new CKeyType(Local.Text_Table_DamageType, "string", legend);
};
CKeyType.DefenceType = function (legend) {
return new CKeyType(Local.Text_Table_DefenceType, "string", legend);
};
CKeyType.ItemDamagePoints = function (legend) {
return new CKeyType(Local.Text_Table_ItemDamagePoints, "string", legend);
};
CKeyType.ValueName = function (legend) {
return [CKeyType.AvgRoll(legend), CKeyType.Times(), CKeyType.MaxRoll(legend), CKeyType.MinRoll(legend), CKeyType.STDRoll(legend), CKeyType.RollList()];
};
CKeyType.TotalValueName = function (legend) {
return [CKeyType.TotalRoll(legend), CKeyType.AvgRoll(legend), CKeyType.Times(), CKeyType.MaxRoll(legend), CKeyType.MinRoll(legend), CKeyType.STDRoll(legend), CKeyType.RollList()];
};
var CInfoList = DefineClass({
construct: function (CValueList, Title, Id, gKeyName, gValueName) {
this._gInfo = [];
this._gKeyName = gKeyName || [];
this._nKeys = this._gKeyName.length;
this._CValueList = CValueList || [];
this._Table = null;
this._Title = Title || "";
this._Id = Id || "";
this._gValueName = gValueName || [];
this._Allkey = this._gKeyName.concat(this._gValueName);
},
methods: {
_CompareKeys: function (gKeyA, gKeyB) {
for (var i = 0; i < this._nKeys; ++i) {
var result = gKeyA[i].compareTo(gKeyB[i]);
if (result !== 0)
return result;
}
return 0;
},
_SetTableBodyCellContents: function () {
if (this._gInfo.length <= 0)
return;
var tablecontent = [];
var keys = this._gInfo[0].gKey.length;
var filters = new Array(keys);
for (var i = 0; i < keys; i++) {
var filter = [];
filters[i] = filter;
}
for (var i = 0; i < this._gInfo.length; ++i) {
for (var j = 0; j < this._gInfo[i].gKey.length; ++j) {
var value = this._gInfo[i].gKey[j];
var filter = value.toText();
if (filters[j].indexOf(filter) <= -1)
filters[j].push(filter);
}
}
for (var i = 0; i < this._gInfo.length; ++i) {
var gBodyCellContent = [];
for (var j = 0; j < this._gInfo[i].gKey.length; ++j) {
if (j > 0)
filters[j].sort(CompareString);
var value = this._gInfo[i].gKey[j];
var filter = value.toText();
gBodyCellContent.push(new CCellContent(value.toHTMLNode(), 1, true, filters[j].indexOf(filter), this._gInfo[i].ValueList.ActiveValue()));
}
for (var j = 0; j < this._gValueName.length; ++j)
gBodyCellContent.push(new CCellContent(this._gValueName[j].getValue(this._gInfo[i]), 1, true, -1, this._gInfo[i].ValueList.ActiveValue()));
tablecontent.push(gBodyCellContent);
}
this._Table.SetHeadCellContentFilters.apply(this._Table, filters);
if (groupData) {
for (var i = tablecontent.length - 1; i > 0; i--) {
for (var j = 0; j < keys; j++) {
if (tablecontent[i][j].value.compareTo(tablecontent[i - 1][j].value) === 0) {
tablecontent[i][j].show = false;
tablecontent[i - 1][j].rowspan = tablecontent[i][j].rowspan + 1;
}
else
break;
}
}
}
for (var i = 0; i < tablecontent.length; i++)
this._Table.SetBodyCellContents.apply(this._Table, tablecontent[i]);
},
SaveInfo: function (Info) { },
Show: function (isExport) {
if (this._gInfo.length > 0) {
this.CalculateValue();
this.sort();
return this.CreateTable(isExport);
}
return "";
},
getTab: function (isExport) {
function FactoryTabClick(Id) {
return function () {
CStat.OnTabClick(Id);
};
}
var tab = document.createElement('li');
tab.id = 'tab_' + this._Id;
tab.className = 'not_selected';
var a = document.createElement('A');
var name = document.createTextNode(this._Title);
a.appendChild(name);
a.href = '#';
if (isExport)
a.setAttribute("onclick", "st('" + this._Id + "');");
else
a.addEventListener("click", FactoryTabClick(this._Id), false);
tab.appendChild(a);
return tab;
},
// Call this function when read all data, and before sort and export data
CalculateValue: function () {
for (var i = 0; i < this._gInfo.length; ++i)
this._gInfo[i].ValueList.Calculate();
},
CreateTable: function (isExport) {
// Key1, Key2, ..., AverageValue, Times, MaxValue, MinValue, STDValue, ValueList
this._Table = new CTable(this._Title, this._Id, this._Allkey.length, isExport);
var gHeadCellContent = new Array(this._Allkey.length);
var gHeadCellLegend = new Array(this._Allkey.length);
var gBodyCellContentType = new Array(this._Allkey.length);
for (var i = 0; i < this._Allkey.length; ++i) {
gHeadCellContent[i] = this._Allkey[i].Name;
gBodyCellContentType[i] = this._Allkey[i].Type;
gHeadCellLegend[i] = this._Allkey[i].legend;
}
this._Table.SetHeadCellContents.apply(this._Table, gHeadCellContent);
this._Table.SetHeadCellLegends.apply(this._Table, gHeadCellLegend);
this._Table.SetBodyCellContentTypes.apply(this._Table, gBodyCellContentType);
this._SetTableBodyCellContents();
return this._Table.CreateHTML();
},
// Call this function when edited the info list (for example, re-sorted it)
ReCreateTableHTML: function () {
this._SetTableBodyCellContents();
return this._Table.CreateHTML();
},
push: function (ActiveRow, gKey, Value) {
for (var i = 0; i < this._gInfo.length; ++i) {
if (this._CompareKeys(this._gInfo[i].gKey, gKey) === 0) {
this._gInfo[i].ValueList.push(ActiveRow, Value);
return this._gInfo.length;
}
}
var ValueList = new this._CValueList();
ValueList.push(ActiveRow, Value);
return this._gInfo.push(new CInfoList._CInfo(gKey, ValueList));
},
sort: function (gSortKeyId) {
function Factory(gId) {
return function (A, B) {
return CInfoList._CompareInfo(A, B, gId);
};
}
return this._gInfo.sort(Factory(gSortKeyId));
}
},
statics: {
_CInfo: function (gKey, ValueList) {
this.gKey = gKey;
this.ValueList = ValueList;
},
// SortKeyId: Id of keys, or null
// The list will be sorted in this way: sort them by the first key, if there are
// elements are still equal, then sort them by the second key, and so on.
// If SortKeyId is null, then sort the list by value
// If gSortKeyId is null, then sort the list by default order of keys
_CompareInfo: function (InfoA, InfoB, gSortKeyId) {
if (gSortKeyId == null) {
for (var i = 0; i < InfoA.gKey.length; ++i) {
var result = InfoA.gKey[i].compareTo(InfoB.gKey[i]);
if (result !== 0) return result;
}
return 0;
} else {
for (var i = 0; i < gSortKeyId.length; ++i) {
var KeyId = gSortKeyId[i];
var result = (KeyId != null) ?
InfoA.gKey[KeyId].compareTo(InfoB.gKey[KeyId]) :
InfoA.ValueList.compareTo(InfoB.ValueList);
if (result !== 0) return result;
}
return 0;
}
}
}
});
///////////////////////////////////////////////////////////////////////////////
// Sub classes of CInfoList
//
// var CIL_ = DefineClass({
// extend: CInfoList,
// construct: function(_nKeys, CValueList) {this.superclass(_nKeys, CValueList);},
// methods:
// {
// _SetTableBodyCellContents: function() {},
// SaveInfo: function(Info) {},
// Show: function() {},
// CreateTable: function(Title, Id, gKeyName) {}
// }
// });
var CILIni = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_Ini, "stat_ini", [CKeyType.Char()],
CKeyType.ValueName());
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.nCurrAction === 1)
this.push(Info.ActiveRow, [Info.Active.Char], Info.Active.nIniRoll);
}
}
});
var CILAttackRoll = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_Attack, "stat_attack", [CKeyType.Char(), CKeyType.AttackType(), CKeyType.Skill(), CKeyType.Item(), CKeyType.Position()],
CKeyType.ValueName());
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.ATTACK && Info.Active.gAttackRoll.length != 0) {
for (var i = 0; i < Info.Active.gAttackRoll.length; ++i) {
this.push(Info.ActiveRow, [Info.Active.Char, Info.Active.ActionType, Info.Active.Skill, Info.Active.gItem, Info.Active.gPosition._gKey[i]],
Info.Active.gAttackRoll[i]);
}
}
}
}
});
var CILDefenceRoll = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_Defence, "stat_defence", [CKeyType.Char(), CKeyType.DefenceType(), CKeyType.Skill(), CKeyType.Item()],
CKeyType.ValueName());
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.ATTACK) {
for (var i = 0; i < Info.gPassive.length; ++i) {
if (Info.gPassive[i].nDefenceRoll != null)
this.push(Info.ActiveRow, [Info.gPassive[i].Char, Info.Active.ActionType,
Info.gPassive[i].Skill, Info.gPassive[i].gItem], Info.gPassive[i].nDefenceRoll);
}
}
}
}
});
var CILDamage = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
var infospan = document.createElement("span");
infospan.className = "pair_value";
infospan.innerHTML = '<span>ROLL点</span> <span>实际值</span>';
this.superclass(CValueList, Local.Text_Table_Damage, "stat_damage", [CKeyType.Char(), CKeyType.AttackType(), CKeyType.Skill(), CKeyType.Item(), CKeyType.DamageType()],
CKeyType.TotalValueName(infospan));
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.ATTACK) {
for (var i = 0; i < Info.gPassive.length; ++i) {
if (Info.gPassive[i].gDamage.length > 0) {
//var damage = [];
//damage.push(Info.gPassive[i].gDamage);
for (var index = 0; index < Info.gPassive[i].gDamage.length; index++) {
this.push(Info.ActiveRow, [Info.Active.Char, Info.Active.ActionType, Info.Active.Skill, Info.Active.gItem, Info.gPassive[i].gDamage[index].GetDamageType()], [Info.gPassive[i].gDamage[index]]);
}
}
}
}
}
}
});
var CILDamaged = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
var infospan = document.createElement("span");
infospan.className = "pair_value";
infospan.innerHTML = '<span>ROLL点</span> <span>实际值</span>';
this.superclass(CValueList, Local.Text_Table_Damaged, "stat_damaged", [CKeyType.Char(), CKeyType.AttackType(), CKeyType.Skill(), CKeyType.Item(), CKeyType.DamageType()],
CKeyType.TotalValueName(infospan));
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.ATTACK) {
for (var i = 0; i < Info.gPassive.length; ++i) {
if (Info.gPassive[i].gDamage.length > 0) {
//var damage = [];
//damage.push(Info.gPassive[i].gDamage);
for (var index = 0; index < Info.gPassive[i].gDamage.length; index++) {
this.push(Info.ActiveRow, [Info.gPassive[i].Char, Info.Active.ActionType, Info.Active.Skill, Info.Active.gItem, Info.gPassive[i].gDamage[index].GetDamageType()], [Info.gPassive[i].gDamage[index]]);
}
}
}
}
}
}
});
var CILHeal = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_Heal, "stat_heal", [CKeyType.Char(), CKeyType.Skill(), CKeyType.Item(), CKeyType.HealType()],
CKeyType.TotalValueName());
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.HEAL) {
for (var i = 0; i < Info.gPassive.length; ++i) {
if (Info.gPassive[i].nHealedHP != null)
this.push(Info.ActiveRow, [Info.Active.Char, Info.Active.Skill, Info.Active.gItem, new CHealType('HP')], [Number(Info.gPassive[i].nHealedHP)]);
if (Info.gPassive[i].nHealedMP != null)
this.push(Info.ActiveRow, [Info.Active.Char, Info.Active.Skill, Info.Active.gItem, new CHealType('MP')], [Number(Info.gPassive[i].nHealedMP)]);
}
}
}
}
});
var CILHealed = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_Healed, "stat_healed", [CKeyType.Char(), CKeyType.HealType()],
CKeyType.TotalValueName());
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.HEAL) {
for (var i = 0; i < Info.gPassive.length; ++i) {
if (Info.gPassive[i].nHealedHP != null)
this.push(Info.ActiveRow, [Info.gPassive[i].Char, new CHealType('HP')], [Number(Info.gPassive[i].nHealedHP)]);
if (Info.gPassive[i].nHealedMP != null)
this.push(Info.ActiveRow, [Info.gPassive[i].Char, new CHealType('MP')], [Number(Info.gPassive[i].nHealedMP)]);
}
}
}
}
});
var CILBuff = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_Buff, "stat_buff", [CKeyType.Char(), CKeyType.Skill(), CKeyType.Item(), CKeyType.BuffType()],
[CKeyType.Times(), CKeyType.DetailList()]);
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.BUFF) {
this.push(Info.ActiveRow, [Info.Active.Char, Info.Active.Skill, Info.Active.gItem, new CBuffType(Info.Active.nIniRoll == null ? '回合前' : '回合中')], [0]);
}
}
}
});
var CILBuffed = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_Buffed, "stat_buffed", [CKeyType.Char(), CKeyType.Skill(), CKeyType.Item(), CKeyType.BuffType()],
[CKeyType.Times(), CKeyType.DetailList()]);
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.BUFF) {
for (var i = 0; i < Info.gPassive.length; ++i)
this.push(Info.ActiveRow, [Info.gPassive[i].Char, Info.Active.Skill, Info.Active.gItem, new CBuffType(Info.Active.nIniRoll == null ? '回合前' : '回合中')], [0]);
}
}
}
});
var CILItemDamage = DefineClass({
extend: CInfoList,
construct: function (CValueList) {
this.superclass(CValueList, Local.Text_Table_DamagedItems, "stat_item_damage", [CKeyType.Char(), CKeyType.Item()], [CKeyType.TotalRoll(), CKeyType.Times(), CKeyType.ItemDamagePoints(), CKeyType.RollList()]);
},
methods: {
SaveInfo: function (Info) {
if (Info.Active.ActionType.GetKind() === CActionType.ATTACK) {
for (var i = 0; i < Info.gPassive.length; ++i) {
if (Info.gPassive[i].nItemDamage != null)
this.push(Info.ActiveRow, [Info.gPassive[i].Char, Info.gPassive[i].DamagedItem],
Info.gPassive[i].nItemDamage);
}
}
}
}
});
// FUNCTIONS //////////////////////////////////////////////////////////////////
function CountStat(page, bLastSubPage, alsoSaveEntire) {
// Read the last round only when reading the last sub page
if (!bLastSubPage) RemoveLastRound(page);
var nLevel = GetHiddenInfo(page, "current_level", 1);
var ret = GetRepPageInfo(page, [1, 1]);
var nCurrRepPage = ret[0];
var Navi = new CNavi(nLevel, nCurrRepPage, 0, 0);
var allRows = page.getElementsByTagName("tr");
Stat.nTotalRows = allRows.length;
for (var i = 0; i < allRows.length; ++i) {
Stat.nReadRows = i + 1;
var Info = new CActionInfo(Navi);
var IniColumn = first_child(allRows[i]);
if (!GetIniInfo(IniColumn, Info))
continue;
Navi.nRow++;
allRows[i].setAttribute('id', Info.ActiveRow);
if (Stat.iscurrentPage == false) {
Stat._reportInfoDiv.firstChild.appendChild(allRows[i].cloneNode(true));
}
if (alsoSaveEntire && StatEntire.iscurrentPage == false) {
StatEntire._reportInfoDiv.firstChild.appendChild(allRows[i].cloneNode(true));
}
var ActiveColumn = node_after(IniColumn);
GetActiveInfo(ActiveColumn, Info);
switch (Info.Active.ActionType.GetKind()) {
case CActionType.ATTACK: // Attack
{
var PassiveColumn = node_after(ActiveColumn);
if (PassiveColumn)
GetAttackedInfo(PassiveColumn, Info);
break;
}
case CActionType.HEAL: // Heal
{
if (includeFilter.Healed) {
var PassiveColumn = node_after(ActiveColumn);
GetHealedBuffedInfo(PassiveColumn, Info);
break;
}
}
case CActionType.BUFF: // Buff
{
if (includeFilter.Buffed) {
var PassiveColumn = node_after(ActiveColumn);
GetHealedBuffedInfo(PassiveColumn, Info);
break;
}
}
case CActionType.WAIT: // Wait
default: // Unknown
;
}
Stat.SaveInfo(Info);
if (alsoSaveEntire)
StatEntire.SaveInfo(Info);
};
}
function RemoveLastRound(page) {
var allRows = page.getElementsByTagName("tr");
for (var i = 0; i < allRows.length; ++i) {
if (allRows[i].className != null &&
rValue.Pattern_logRow.test(allRows[i].className)) {
var allH1 = allRows[i].getElementsByTagName("h1");
if (allH1[0] != null &&
allH1[0].firstChild != null &&
allH1[0].firstChild.nodeType == Node.TEXT_NODE &&
allH1[0].firstChild.data == Local.OrigText_LastRound) {
allRows[i].parentNode.removeChild(allRows[i]);
break;
}
}
};
}
function GetIniInfo(Node, Info) {
if (Node == null || Node.className != "rep_initiative")
return false;
if (Node.innerHTML == " ")
return true;
if (includeFilter.Init) {
// \1 ini
// \2 current action
// \3 total actions
var Patt_Ini = Local.Pattern_Ini;
var result = Patt_Ini.exec(Node.innerHTML);
if (result == null) {
DbgMsgAction(Info, "IniInfo: " + Node.innerHTML);
return false;
}
var active = Info.Active;
active.nIniRoll = Number(result[1]);
active.nCurrAction = Number(result[2]);
active.nTotalActions = Number(result[3]);
return active.nIniRoll != null;
}
return false;
}
// return: whether the format is right
function GetActiveInfo(Node, Info) {
if (Node === null) {
DbgMsgAction(Info, "ActiveInfo: null");
return false;
}
var nStartNode = 0;
var Str = Node.innerHTML;
var active = Info.Active;
// \1 span node
// \2 npc Id
var Patt_Char = Local.Pattern_Active_Char;
var result = Patt_Char.exec(Str);
if (result === null) {
DbgMsgAction(Info, "ActiveInfo (Char): " + Node.innerHTML);
return true;
}
var CharNode = result[1] != null ? Node.childNodes[nStartNode].childNodes[0] :
Node.childNodes[nStartNode];
active.Char = new CChar(CharNode);
active.nCharId = result[2] != null ? Number(result[2]) : null;
nStartNode += result[1] != null ? 1 : (result[2] != null ? 2 : 1);
Str = Str.substring(result[0].length);
// \1 attack
// \2 heal or buff
// \3 left parenthesis
var Patt_Action1 = Local.Pattern_Active_Action1;
result = Patt_Action1.exec(Str);
if (result === null) {
// \1 other action
var Patt_Action2 = Local.Pattern_Active_Action2;
result = Patt_Action2.exec(Str);
if (result === null) {
DbgMsgAction(Info, "ActiveInfo (Action2): " + Node.innerHTML);
return false;
}
if (result[3] != null) {
active.ActionType.setKind(CActionType.ATTACK);
active.ActionType.setText("");
active.gAttackRoll = [];
active.gAttackRoll.push(Number(result[3]));
active.gPosition.push(new CPositionType(""));
active.Skill = new CSkill(null);
}
else
active.ActionType = new CActionType(result[1]);
return true;
}
if (result[1] != null) {
active.ActionType = new CActionType(result[1]);
if (active.ActionType.GetKind() !== CActionType.ATTACK) {
DbgMsgAction(Info, "ActiveInfo (Attack Type): " + result[1]);
return false;
}
nStartNode += 1;
Str = Str.substring(result[0].length);
} else {
active.ActionType = new CActionType(result[2]);
if (active.ActionType.GetKind() !== CActionType.HEAL && active.ActionType.GetKind() !== CActionType.BUFF) {
DbgMsgAction(Info, "ActiveInfo (Heal/Buff Type): " + result[2]);
return false;
}
active.Skill = new CSkill(Node.childNodes[nStartNode + 1]);
if (result[3] === null)
return true;
nStartNode += 3;
Str = Str.substring(result[0].length);
}
switch (active.ActionType.GetKind()) {
case CActionType.ATTACK: // attack
{
// \1 single roll
// \2 multiple positions and rolls
// \3 position n (only the last one)
// \4 multiple roll n (only the last one)
// \5 MP
// \6 item list
// \7 HP
if (includeFilter.Attack) {
var Patt_ActtackDetails = Local.Pattern_Active_AttackDetails;
result = Patt_ActtackDetails.exec(Str);
if (result === null) {
DbgMsgAction(Info, "ActiveInfo (ActtackDetails): " + Node.innerHTML);
return false;
}
active.Skill = new CSkill(Node.childNodes[nStartNode]);
active.gAttackRoll = [];
active.gPosition = new CKeyList();
if (result[1] != null) {
active.gAttackRoll.push(Number(result[1]));
active.gPosition.push(new CPositionType(''));
}
if (result[2] != null) {
var pattern_pos_atk = /^([^\u0000-\u007F]+): ([\d]+)$/;
var gPos_Atk = result[2].split('/');
for (var i = 1; i < gPos_Atk.length; ++i) {
var inner_result = pattern_pos_atk.exec(gPos_Atk[i]);
active.gAttackRoll.push(Number(inner_result[2]));
active.gPosition.push(new CPositionType(inner_result[1]));
}
}
active.nSkillMP = result[5] != null ? Number(result[5]) : null;
active.nSkillHP = result[7] != null ? Number(result[7]) : null;
if (result[6] != null) {
active.gItem = new CKeyList();
nStartNode += result[5] != null ? 4 : 2;
var ItemNode;
while ((ItemNode = Node.childNodes[nStartNode]) != null) {
if (ItemNode.tagName == 'A') {
active.gItem.push(new CItem(ItemNode));
nStartNode += 2;
}
else {
nStartNode++;
}
}
}
}
return true;
}
case CActionType.HEAL: // heal
case CActionType.BUFF: // buff
{
// \1 MP
// \2 normal item list
// \3 magical potion
if ((includeFilter.Heal && active.ActionType.GetKind() === CActionType.HEAL) || (includeFilter.Buff && active.ActionType.GetKind() === CActionType.BUFF)) {
var Patt_HealBuffDetails = Local.Pattern_Active_HealBuffDetails;
result = Patt_HealBuffDetails.exec(Str);
if (result === null) {
DbgMsgAction(Info, "ActiveInfo (HealBuffDetails): " + Node.innerHTML);
return false;
}
active.nSkillMP = result[1] != null ? Number(result[1]) : null;
if (result[2] != null) {
active.gItem = new CKeyList();
nStartNode += result[1] != null ? 2 : 0;
var ItemNode;
while ((ItemNode = Node.childNodes[nStartNode]) != null) {
if (ItemNode.tagName == 'A') {
active.gItem.push(new CItem(ItemNode));
nStartNode += 2;
}
else {
nStartNode++;
}
}
} else if (result[3] != null) {
active.gItem = new CKeyList();
nStartNode += result[1] != null ? 2 : 0;
active.gItem.push(new CItem(Node.childNodes[nStartNode]));
// nStartNode: determine by the number of reagents
}
}
return true;
}
default: // impossible, the value can only be 0, 1, or 2
return false;
}
}
// return: whether the format is right
function GetAttackedInfo(Node, Info) {
if (Node === null) {
DbgMsgAction(Info, "AttackedInfo: null");
return false;
}
var nStartNode = 0;
var Str = Node.innerHTML;
// \1 char span node
// \2 char Id
// \3 skill
// \4 defence roll
// \5 MP
// \6 item list
// \7 hit type
// \8 struck down
// \9 damage list
// \10 item damage
// \11 next flag
var Patt_Attacked = Local.Pattern_Passive_Attacked;
var bEnd = false;
while (!bEnd) {
var PassiveInfo = new CPassiveInfo();
var result = Patt_Attacked.exec(Str);
if (result === null) {
DbgMsgAction(Info, "AttackedInfo: " + Node.innerHTML);
return true;
}
var CharNode = result[1] != null ? Node.childNodes[nStartNode].childNodes[0] :
Node.childNodes[nStartNode];
PassiveInfo.Char = new CChar(CharNode);
PassiveInfo.nCharId = result[2] != null ? Number(result[2]) : null;
nStartNode += result[1] != null ? 1 : (result[2] != null ? 2 : 1);
if (result[3] != null) {
PassiveInfo.Skill = new CSkill(Node.childNodes[nStartNode + 1]);
nStartNode += 2;
}
PassiveInfo.nDefenceRoll = Number(result[4]);
if (result[5] != null) {
PassiveInfo.nSkillMP = Number(result[5]);
nStartNode += 2;
}
if (result[6] != null) {
PassiveInfo.gItem = new CKeyList();
nStartNode += 1;
var ItemNode = Node.childNodes[nStartNode];
while (ItemNode != null && ItemNode.nodeName == "A") {
PassiveInfo.gItem.push(new CItem(ItemNode));
nStartNode += 2;
ItemNode = Node.childNodes[nStartNode];
}
} else
nStartNode += 1;
PassiveInfo.HitType = new CHitType(result[7]);
PassiveInfo.bStruckDown = (result[8] != null);
nStartNode += result[8] != null ? 2 : 1;
if (result[9] != null) {
PassiveInfo.gDamage = [];
nStartNode += 1;
var DamageNode = Node.childNodes[nStartNode];
while (DamageNode != null && (DamageNode.nodeType == Node.TEXT_NODE ||
(DamageNode.nodeName == "SPAN" &&
DamageNode.firstChild != null && DamageNode.firstChild.nodeType == Node.TEXT_NODE))) {
PassiveInfo.gDamage.push(new CDamage(DamageNode));
nStartNode += 2;
DamageNode = Node.childNodes[nStartNode];
}
nStartNode -= 1;
}
if (result[10] != null) {
PassiveInfo.DamagedItem = new CItem(Node.childNodes[nStartNode + 1]);
PassiveInfo.nItemDamage = Number(result[10]);
nStartNode += 3;
}
if (result[11] != null)
nStartNode += 1;
else
bEnd = true;
Info.gPassive.push(PassiveInfo);
Str = Str.substring(result[0].length);
}
return true;
}
// return: whether the format is right
function GetHealedBuffedInfo(Node, Info) {
if (Node === null) {
DbgMsgAction(Info, "HealedBuffedInfo: null");
return false;
}
var nStartNode = 0;
var Str = Node.innerHTML;
// \1 span node
// \2 char Id
// \3 self
// \4 HP
// \5 MP
// \6 next flag
var Patt_HealedBuffed = Local.Pattern_Passive_Healed_Buffed;
var bEnd = false;
while (!bEnd) {
var PassiveInfo = new CPassiveInfo();
var result = Patt_HealedBuffed.exec(Str);
if (result === null) {
DbgMsgAction(Info, "HealedBuffedInfo: " + Node.innerHTML);
return true;
}
if (result[3] != null) {
PassiveInfo.Char = Info.Active.Char;
PassiveInfo.nCharId = Info.Active.nCharId;
} else {
var CharNode = result[1] != null ? Node.childNodes[nStartNode].childNodes[0] :
Node.childNodes[nStartNode];
PassiveInfo.Char = new CChar(CharNode);
PassiveInfo.nCharId = result[2] != null ? Number(result[2]) : null;
nStartNode += result[1] != null ? 1 : (result[2] != null ? 2 : 1);
}
PassiveInfo.nHealedHP = result[4] != null ? Number(result[4]) : null;
PassiveInfo.nHealedMP = result[5] != null ? Number(result[5]) : null;
nStartNode += 1;
if (result[6] != null)
nStartNode += 1;
else
bEnd = true;
Info.gPassive.push(PassiveInfo);
Str = Str.substring(result[0].length);
}
return true;
}
function DbgMsgAction(Info, Text) {
if (DEBUG)
alert("[" + Info.Navi.nLevel + "." + Info.Navi.nRoom + "." +
Info.Navi.nRound + "." + Info.Navi.nRow + "] " + Text);
}
// GLOBAL VARIABLES ///////////////////////////////////////////////////////////
var DEBUG = false;
var groupData = false;
var useFilter = true;
var Contents = {
OrigText_Button_DungeonDetails: ["details", "详细资料"],
OrigText_Button_DuelDetails: ["Details", "详细"],
OrigText_Button_DungeonStat: ["statistics", "统计表"],
OrigText_Level: ["Level", "层数"],
OrigText_LastRound: ["Last round:", "最后回合:"],
OrigTextList_AttackActionType: [
[
"attacks",
"ranged attacks",
"attacks with magic",
"socially attacks",
"cunningly attacks",
"activates on",
"works as a force of nature upon",
"infected",
"casts an explosion at",
"deactivated",
"magic projectile",
"curse",
"scare",
"other",
],
[
"近战攻击",
"远程攻击",
"魔法攻击",
"心理攻击",
"偷袭",
"触发",
"作为自然灾害",
"散布",
"制造爆炸",
"解除",
"魔法投射",
"诅咒",
"恐吓",
"冲击",
"魔法弹",
],
],
OrigTextList_HealActionType: [["heals with"], ["治疗"]],
OrigTextList_BuffActionType: [
["uses", "summons with"],
["使用", "召唤"],
],
OrigTextList_WaitActionType: [
["is unable to do anything.", "looks around in boredom and waits."],
["不能执行任何动作.", "无聊的打量四周,等待着."],
],
OrigTextList_NoneHPDamageType: [
["mana damage", "mana"],
["法力伤害", "法力"],
],
Pattern_Ini: [
/^Initiative ([\d]+)<br><span .*?>Action ([\d]+) of ([\d]+)<\/span>$/,
/^先攻([\d]+)<br><span .*?>第([\d]+)步行动 \/ 共([\d]+)步<\/span>$/,
],
Pattern_Active_Char: [
/^(<span .*?>)?<a .*?>.*?<\/a>(?:<span .*?>([\d]+)<\/span>)?(?:<img .*?><\/span>)?/,
/^(<span .*?>)?<a .*?>.*?<\/a>(?:<span .*?>([\d]+)<\/span>)?(?:<img .*?><\/span>)?/,
],
Pattern_Active_Action1: [
/^\s*(?:([A-Za-z][A-Za-z ]+[A-Za-z]) +\(|([A-Za-z][A-Za-z ]+[A-Za-z]) +<a .*?>.*?<\/a>(?:( \()|$| on $))/,
/^\s*(?:([^\u0000-\u007F]+) +\(|([^\u0000-\u007F]+)<a .*?>.*?<\/a>(?:( \()|$|给$))/,
],
Pattern_Active_Action2: [
/^\s*([\S][^/(^/)]*[\S])([/(]([\d]+)[/)])?\s*$/,
/^\s*([\S][^/(^/)]*[\S])([/(]([\d]+)[/)])?\s*$/,
],
Pattern_Active_AttackDetails: [
/^<a .*?>.*?<\/a>(?:\/([\d]+)|(?:\/([A-Za-z ]+): ([\d]+))+)(?:\/<span .*?>([\d]+) MP<\/span>)?(\/(?:<a .*?>.*?<\/a>,)*<a .*?>.*?<\/a>)?\)$/,
/^<a .*?>.*?<\/a>(?:\/([\d]+)|((?:\/([^\u0000-\u007F]+): ([\d]+))+))(?:\/<span .*?>([\d]+) (?:法力|神力|怒气|灵能|动力|魂能|动能|动能)<\/span>)?(\/(?:<a .*?>.*?<\/a>\s*(?:<img .*?>)*,)*<a .*?>.*?<\/a>\s*(?:<img .*?>)*)?(?:\/<span .*?>(?:<b>)?(?:-|\+)([\d]+) HP(?:<\/b>)?<\/span>)?(?:\/<span .*?>(?:<b>)?(?:-|\+)([\d]+) (?:法力|神力|怒气|灵能|动力|魂能|动能)(?:<\/b>)?<\/span>)?\)$/,
],
Pattern_Active_HealBuffDetails: [
/^(?:<span .*?>([\d]+) MP<\/span>)?(?:\/)?(?:((<a .*?>.*?<\/a>,)*<a .*?>.*?<\/a>)|(<a .*?>.*?<\/a>\s+(?:<img .*?>)+))?\)(?: on )?$/,
/^(?:<span .*?>(?:-|\+)?([\d]+) (?:法力|神力|怒气|灵能|动力|魂能|动能)<\/span>)?(?:\/)?(?:((<a .*?>.*?<\/a>\s*(?:<img .*?>)*,)*<a .*?>.*?<\/a>\s*(?:<img .*?>)*))?\)(?:给)?$/,
],
Pattern_Passive_Attacked: [
/^(<span .*?>)?<a .*?>.*?<\/a>(?:<span .*?>([\d]+)<\/span>)?(?:<img .*?><\/span>)?\s*\((<a .*?>.*?<\/a>\/)?([\d]+)(?:\/<span .*?>([\d]+) MP<\/span>)?(\/(?:<a .*?>.*?<\/a>,)*<a .*?>.*?<\/a>)?\): <span class="([A-Za-z_]+)">[A-Za-z ]+<\/span>( - [A-Za-z ]+)?(<br>(?:<span .*?>)?(?:-)?[\d]+ (?:\[(?:\+|-)[\d]+\] )?[A-Za-z ]+(?:<img .*?><\/span>)?)*(?:<br><a .*?>.*?<\/a> -([\d]+) HP)?(?:(<br>)|$)/,
/^(<span .*?>)?<a .*?>.*?<\/a>(?:<span .*?>([\d]+)<\/span>)?(?:<img .*?><\/span>)?\s*\((<a .*?>.*?<\/a>\/)?([\d]+)(?:\/<span .*?>([\d]+) (?:法力|神力|怒气|灵能|动力|魂能|动能)<\/span>)?(\/(?:<a .*?>.*?<\/a>\s*(?:<img .*?>)*,)*<a .*?>.*?<\/a>\s*(?:<img .*?>)*)?\): <span class="([A-Za-z_]+)">[^\u0000-\u007F]+<\/span>( - [^\u0000-\u007F]+ *)?(<br>(?:<span .*?>)?(?:-)?[\d]+ (?:\[(?:\+|-)[\d]+\] )?[^\u0000-\u007F]+(?:<img .*?><\/span>)?)*(?:<br><a .*?>.*?<\/a> (?:-|\+)([\d]+) HP)?(?:(<br>)|$)/,
],
Pattern_BasicDamage: [/causes: <b>([\d]+)<\/b>/, /造成: <b>([\d]+)<\/b>/],
Pattern_Damage: [
/^((?:-)?[\d]+) (?:\[((?:\+|-)[\d]+)\] )?([A-Za-z][A-Za-z ]+[A-Za-z])$/,
/^((?:-)?[\d]+) (?:\[((?:\+|-)[\d]+)\] )?([^\u0000-\u007F]+)$/,
],
Pattern_Passive_Healed_Buffed: [
/^(?:(<span .*?>)?<a .*?>.*?<\/a>(?:<span .*?>([\d]+)<\/span>)?(?:<img .*?><\/span>)?\s+|(themselves))(?: \+([\d]+) HP)?(?: \+([\d]+) MP)?(?:(<br>)|$)/,
/^(?:(<span .*?>)?<a .*?>.*?<\/a>(?:<span .*?>([\d]+)<\/span>)?(?:<img .*?><\/span>)?\s+|(自己|自身))(?: \+([\d]+) HP)?(?: \+([\d]+) (?:法力|神力|怒气|灵能|动力|魂能|动能))?(?:(<br>)|$)/,
],
Text_Button_ExtraStat: ["Extra Stat", "额外统计"],
Text_Button_EntireStat: ["Entire Extra Stat", "全城额外统计"],
Text_Button_Show: ["Show", "显示"],
Text_Button_Hide: ["Hide", "隐藏"],
Text_Button_ShowAll: ["Show All", "全部显示"],
Text_Button_HideAll: ["Hide All", "全部隐藏"],
Text_Button_Default: ["Default", "默认"],
TextList_AttackType: [
[
"melee",
"ranged",
"spell",
"social",
"ambush",
"trap",
"nature",
"disease",
"detonate",
"disarm trap",
"magic projectile",
"curse",
"scare",
"other",
],
[
"近战",
"远程",
"魔法",
"心理",
"偷袭",
"陷阱",
"自然",
"疾病",
"爆破",
"解除陷阱",
"魔法投射",
"诅咒",
"恐吓",
"冲击",
"魔法弹",
],
],
TextList_HealType: [["heal"], ["治疗"]],
TextList_BuffType: [["buff"], ["使用"]],
TextList_WaitType: [["wait"], ["等待"]],
TextList_HitType: [
["failed", "success", "good success", "critical success"],
["闪避", "普通", "重击", "致命一击"],
],
Text_Loading: ["Loading", "载入中"],
Text_Options: ["Options:", "选项:"],
Text_DefaultMsg: [
"All the data this script stored in your machine has been cleared.",
"此脚本储存在你的机器上的所有数据已被清除。",
],
Text_Table_Ini: ["Initiative", "先攻权"],
Text_Table_Attack: ["Attack", "攻击骰"],
Text_Table_Defence: ["Defence", "防御骰"],
Text_Table_Damage: ["Damage", "造成伤害"],
Text_Table_Damaged: ["Damage", "受到伤害"],
Text_Table_DamageType: ["Damage Type", "伤害类型"],
Text_Table_HealType: ["Heal Type", "治疗类型"],
Text_Table_BuffType: ["Buff Type", "增益类型"],
Text_Table_Heal: ["Healing By The Hero", "给予治疗"],
Text_Table_Healed: ["Healing On The Hero", "接受治疗"],
Text_Table_Buff: ["Buffing By The Hero", "给予增益"],
Text_Table_Buffed: ["Buffing On The Hero", "接受增益"],
Text_Table_Buffer: ["Buffing Provider", "提供者"],
Text_Table_BuffeReceiver: ["Buffing Receiver", "提供给"],
Text_Table_DamagedItems: ["Damaged Items", "物品损坏"],
Text_Table_Char: ["Character", "人物"],
Text_Table_AttackType: ["Attack type", "攻击类型"],
Text_Table_DefenceType: ["Defence type", "防御类型"],
Text_Table_Skill: ["Skill", "技能"],
Text_Table_Item: ["Item", "物品"],
Text_Table_Position: ["Pos", "位置"],
Text_Table_AvgRoll: ["Average roll", "平均值"],
Text_Table_MaxRoll: ["Max roll", "Max值"],
Text_Table_MinRoll: ["Min roll", "Min值"],
Text_Table_STDRoll: ["STD roll", "STD值"],
Text_Table_Total: ["Total", "总数"],
Text_Table_Times: ["Times", "次数"],
Text_Table_RollList: ["Roll list", "数值列表"],
Text_Table_DetailList: ["Detail list", "详细列表"],
Text_Table_ItemDamagePoints: ["Damage Points", "损坏点数"],
Text_Table_AllData: ["All", "全部"],
};
var Style = "div.stat_all {font-size:14px;} " +
"div.stat_header {margin:1em auto 0.5em auto;} " +
"span.stat_title {margin: auto 1em auto 0em; font-size:20px; font-weight:bold; color:#FFF;} span.clickable {cursor:pointer;} " +
"span.pair_value {width:100%; font-size:12px;} span.pair_value span {width:50%; min-width:3em; text-align:right; color:#F8A400;} span.pair_value span + span {color:#00CC00;} " +
"table.pair_hero {width:100%; font-size:12px;} table.pair_hero td {width:50%; min-width:3em; text-align:right; color:#00CC00;} table.pair_hero td + td {color:#F8A400;} " +
"table[hide] {display:none;} " +
"table.pair_value {width:100%;} table.pair_value td {width:50%; min-width:3em; text-align:right; color:#F8A400;} table.pair_value td + td {color:#00CC00;} " +
"#myProgress {position: relative; width: 100%; height: 3px; background-color: #ddd;} " +
"#myBar { position: absolute; width: 1%; height: 100%; background-color: #4CAF50;}";
var Local;
var Stat;
var includeFilter = {
Init: true,
Attack: true,
Defence: true,
Damage: true,
Damaged: true,
Heal: true,
Healed: true,
Buff: true,
Buffed: true,
DamagedItems: true
};
var localInfo = document;
var reportInfoDiv;
var progress;
var dataPage;
var heroes = [];
var heroLvMap = {};
if (typeof GM_addStyle == "undefined") {
function GM_addStyle(styles) {
var S = document.createElement("style");
S.type = "text/css";
var T = "" + styles + "";
T = document.createTextNode(T);
S.appendChild(T);
document.body.appendChild(S);
return;
}
}
var clickedButton;
// FUNCTIONS //////////////////////////////////////////////////////////////////
function CreateStat(node, infoNode, isExport) {
// Stat initialization
includeFilter.Init =
document.getElementById("chk_Text_Table_Ini").checked;
includeFilter.Attack = document.getElementById(
"chk_Text_Table_Attack"
).checked;
includeFilter.Defence = document.getElementById(
"chk_Text_Table_Defence"
).checked;
includeFilter.Damage = document.getElementById(
"chk_Text_Table_Damage"
).checked;
includeFilter.Damaged = document.getElementById(
"chk_Text_Table_Damaged"
).checked;
includeFilter.Heal = document.getElementById(
"chk_Text_Table_Heal"
).checked;
includeFilter.Healed = document.getElementById(
"chk_Text_Table_Healed"
).checked;
includeFilter.Buff = document.getElementById(
"chk_Text_Table_Buff"
).checked;
includeFilter.Buffed = document.getElementById(
"chk_Text_Table_Buffed"
).checked;
includeFilter.DamagedItems = document.getElementById(
"chk_Text_Table_DamagedItems"
).checked;
var theStat = new CStat(node, infoNode);
if (includeFilter.Init)
theStat.RegInfoList(new CILIni(CVLNumber, isExport));
if (includeFilter.Attack)
theStat.RegInfoList(new CILAttackRoll(CVLNumber, isExport));
if (includeFilter.Defence)
theStat.RegInfoList(new CILDefenceRoll(CVLNumber, isExport));
if (includeFilter.Damage)
theStat.RegInfoList(new CILDamage(CVLDamage, isExport));
if (includeFilter.Damaged)
theStat.RegInfoList(new CILDamaged(CVLDamage, isExport));
if (includeFilter.Heal)
theStat.RegInfoList(new CILHeal(CVLNumber, isExport));
if (includeFilter.Healed)
theStat.RegInfoList(new CILHealed(CVLNumber, isExport));
if (includeFilter.Buff)
theStat.RegInfoList(new CILBuff(CVLString, isExport));
if (includeFilter.Buffed)
theStat.RegInfoList(new CILBuffed(CVLString, isExport));
if (includeFilter.DamagedItems)
theStat.RegInfoList(new CILItemDamage(CVLNumber, isExport));
return theStat;
}
function Main() {
// Language selection
Local = GetLocalContents(Contents);
if (Local === null) return;
//GM_log(Local);
// Add CSS
GM_addStyle(Style);
// Add buttons
var KeyButton = AddButtonBesideDisabledButton(
[
Local.OrigText_Button_DungeonDetails,
Local.Text_Button_ExtraStat,
OnCountStat,
],
[
Local.OrigText_Button_DungeonStat,
Local.Text_Button_EntireStat,
OnCountEntireStat,
],
[
Local.OrigText_Button_DuelDetails,
Local.Text_Button_ExtraStat,
OnCountStat,
]
);
if (KeyButton === null) return;
KeyButton = addFilter(KeyButton);
addStatusBar(KeyButton);
dataPage = document.createElement("div");
dataPage.innerHTML = "";
}
function addStatusBar(node) {
var progressDiv = document.createElement("div");
progressDiv.id = "myProgress";
reportInfoDiv = document.createElement("div");
reportInfoDiv.id = "myBar";
progressDiv.appendChild(reportInfoDiv);
node.parentNode.insertBefore(progressDiv, node.nextSibling);
}
function hideFilter() {
// 隐藏复选项
var AllFilter = document.getElementsByName("ExtraFilter");
for (var i = 0, l = AllFilter.length; i < l; i++) {
AllFilter[i].style.display = "none";
}
}
function addFilter(KeyButton) {
if (isaddFilter) {
//首次执行插入复选项
var newLine = document.createElement("br");
newLine.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newLine,
KeyButton.nextSibling
);
var newSpan = document.createElement("span");
newSpan.innerHTML = "选择要统计的项目:";
newSpan.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//先攻
var newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
newCheckBox.setAttribute("name", "ExtraFilter");
if (includeFilter.Init) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Ini";
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Ini;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//攻击骰
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Attack) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Attack";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Attack;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//防御骰
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Defence) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Defence";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Defence;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//造成伤害
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Damage) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Damage";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Damage;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//受到伤害
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Damaged) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Damaged";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Damaged;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//给予治疗
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Heal) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Heal";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Heal;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//接受治疗
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Healed) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Healed";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Healed;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//给予增益
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Buff) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Buff";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Buff;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//接受增益
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.Buffed) newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_Buffed";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_Buffed;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
//物品损坏
newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "");
if (includeFilter.DamagedItems)
newCheckBox.setAttribute("checked", "true");
newCheckBox.id = "chk_Text_Table_DamagedItems";
newCheckBox.setAttribute("name", "ExtraFilter");
KeyButton = KeyButton.parentNode.insertBefore(
newCheckBox,
KeyButton.nextSibling
);
newSpan = document.createElement("label");
newSpan.innerHTML = Local.Text_Table_DamagedItems;
newSpan.setAttribute("name", "ExtraFilter");
newSpan.setAttribute("for", newCheckBox.id);
KeyButton = KeyButton.parentNode.insertBefore(
newSpan,
KeyButton.nextSibling
);
isaddFilter = false;
return KeyButton;
} else {
//多次执行重新显示复选项
var AllFilter = document.getElementsByName("ExtraFilter");
for (var i = 0, l = AllFilter.length; i < l; i++) {
AllFilter[i].style.display = "";
}
return KeyButton;
}
}
// It will only add the first eligible button
// return: the node of the first eligible disabled button, or null if didn't find anyone
function AddButtonBesideDisabledButton(/* [DisabledButtonText, ButtonText, ClickEvent], [...], ... */) {
var allInputs = document.getElementsByTagName("input");
for (var i = 0; i < allInputs.length; ++i) {
if (allInputs[i].className == "button_disabled") {
for (var j = 0; j < arguments.length; ++j) {
if (allInputs[i].getAttribute("value") == arguments[j][0]) {
return AddButton(allInputs[i], arguments[j][1], arguments[j][2]);
}
}
}
}
return null;
}
// Add a button to the end of the given node's parent node
function AddButton(SiblingNode, Value, OnClick) {
var newButton = document.createElement("input");
newButton.setAttribute("type", "button");
newButton.setAttribute("class", "button");
newButton.setAttribute("value", Value);
newButton.addEventListener("click", OnClick, false);
var newBlank = document.createTextNode(" ");
SiblingNode.parentNode.appendChild(newBlank);
SiblingNode.parentNode.appendChild(newButton);
return newButton;
}
function OnCountStat() {
try {
clickedButton = this;
if (this.className == "button_disabled") return;
else this.className = "button_disabled";
var InfoDiv = document.createElement("div");
InfoDiv.id = "report_info";
Stat = CreateStat(node_after(this.parentNode), InfoDiv, false);
reportInfoDiv.style.width = "1%";
Stat.nTotalPages = 1;
//Stat.nReadPages = 1;
Stat.iscurrentPage = true;
Stat.ShowProgress();
if (progress) clearInterval(progress);
progress = setInterval(Stat.ShowProgress.bind(Stat), 1);
ReadPage(document, true);
} catch (e) {
alert("OnCountStat(): " + e);
}
}
function OnCountEntireStat() {
try {
clickedButton = this;
if (this.className == "button_disabled") return;
else this.className = "button_disabled";
var InfoDiv = document.createElement("div");
InfoDiv.id = "report_Entire_info";
Stat = CreateStat(node_after(this.parentNode), InfoDiv, false);
reportInfoDiv.style.width = "1%";
CountEntireStat();
} catch (e) {
alert("OnCountEntireStat(): " + e);
}
}
function CountEntireStat() {
var nCurrRepId = GetHiddenInfo(document, "report_id[0]", "");
var nMaxLevel = (Stat.nTotalPages = GetStatPageMaxLevel(document, 1));
Stat.ShowProgress();
if (progress) clearInterval(progress);
progress = setInterval(Stat.ShowProgress.bind(Stat), 1);
for (var CurrLevel = 1; CurrLevel <= nMaxLevel; ++CurrLevel)
GetPage(nCurrRepId, CurrLevel, 1, true);
//Stat.ShowProgress();
}
function GetPage(nRepId, nLevel, nRepPage, bFirstRead) {
var XmlHttp = new XMLHttpRequest();
XmlHttp.onreadystatechange = function () {
try {
if (XmlHttp.readyState == 4 && XmlHttp.status == 200) {
dataPage.innerHTML = XmlHttp.responseText;
//Stat.nReadPages = nRepPage;
Stat.iscurrentPage = false;
ReadPage(dataPage, bFirstRead);
}
} catch (e) {
alert("XMLHttpRequest.onreadystatechange(): " + e);
}
};
var URL =
location.protocol +
"//" +
location.host +
"/wod/spiel/dungeon/report.php" +
"?cur_rep_id=" +
nRepId +
"&gruppe_id=¤t_level=" +
nLevel +
"&REPORT_PAGE=" +
nRepPage +
"&IS_POPUP=1";
Stat.ShowProgress();
XmlHttp.open("GET", URL, true);
XmlHttp.send(null);
}
function ReadPage(page, bFirstRead) {
var ret = GetRepPageInfo(page, [1, 1]);
var nCurrRepPage = ret[0];
var nMaxRepPage = ret[1];
if (bFirstRead && nMaxRepPage > 1) {
var nRepId = GetHiddenInfo(page, "report_id[0]", "");
var nLevel = GetHiddenInfo(page, "current_level", 1);
Stat.nTotalPages += nMaxRepPage - 1;
for (var i = 1; i <= nMaxRepPage; ++i) {
Stat.ShowProgress();
if (i !== nCurrRepPage) GetPage(nRepId, nLevel, i, false);
}
}
Stat.nReadPages++;
Stat.ShowProgress();
CountStat(page, nCurrRepPage === nMaxRepPage);
if (Stat.nReadPages >= Stat.nTotalPages) {
Stat.Show(false);
if (clickedButton) clickedButton.className = "button";
}
}
function GetHiddenInfo(page, InfoName, DefaultValue) {
var allInputs = page.getElementsByTagName("input");
for (var i = 0; i < allInputs.length; ++i) {
if (
allInputs[i].getAttribute("type") == "hidden" &&
allInputs[i].name == InfoName
)
return allInputs[i].value;
}
return DefaultValue;
}
function GetStatPageMaxLevel(page, DefaultValue) {
var allTds = page.getElementsByTagName("td");
for (var i = 0; i < allTds.length; ++i) {
if (first_child(allTds[i].parentNode) != allTds[i]) continue;
var LevelNode = first_child(allTds[i]);
if (
LevelNode != null &&
LevelNode.nodeType == Node.TEXT_NODE &&
LevelNode.data == Local.OrigText_Level
) {
var Patt_Level = /^(?:<span .*?>)?(?:[\d]+)\/([\d]+)(?:<\/span>)?$/;
var result = Patt_Level.exec(node_after(allTds[i]).innerHTML);
if (result === null) return DefaultValue;
return Number(result[1]);
}
}
return DefaultValue;
}
// return: an array, [0]: nCurrRepPage, [1]: nMaxRepPage
function GetRepPageInfo(page, DefaultValue) {
var ret = [DefaultValue[0], DefaultValue[1]];
var allInputs = page.getElementsByTagName("input");
var IndexPatt = /\D*([\d]+)\D*/;
var pages = [];
for (var i = 0; i < allInputs.length; ++i) {
var theInput = allInputs[i];
if (theInput.className == "paginator_selected clickable") {
var Result = IndexPatt.exec(theInput.value);
if (Result && Result[1]) {
pages.push(Number(Result[1]));
ret[0] = Number(Result[1]);
}
}
}
allInputs = page.getElementsByTagName("a");
for (var i = 0; i < allInputs.length; ++i) {
var theInput = allInputs[i];
if (theInput.className == "paginator") {
var Result = IndexPatt.exec(theInput.textContent);
if (Result && Result[1]) pages.push(Number(Result[1]));
}
}
if (pages.length > 0) ret[1] = Math.max.apply(Math, pages);
return ret;
}
//===============================================================================================
// code for save report only.
//===============================================================================================
var StatEntire;
var StatEntireDiv;
function es_addStyle(page, styles) {
var S = document.createElement("style");
S.type = "text/css";
var T = "" + styles + "";
T = document.createTextNode(T);
S.appendChild(T);
page.appendChild(S);
return;
}
function InsertButton(Node, Value, OnClick) {
var newButton = document.createElement("input");
newButton.setAttribute("type", "button");
newButton.setAttribute("class", "button");
newButton.setAttribute("value", Value);
newButton.addEventListener("click", OnClick, false);
Node.parentNode.insertBefore(newButton, Node.nextSibling);
}
function changeAllSelection(select) {
var allCheckbox = document.getElementsByTagName("input");
for (var i = 0; i < allCheckbox.length; ++i) {
var theCheckbox = allCheckbox[i];
if (
rValue.Pattern_checkboxName.test(theCheckbox.getAttribute("name"))
) {
theCheckbox.checked = select;
}
}
}
function selectAll() {
if (!gIsWorking) changeAllSelection(true);
}
function cleartAll() {
if (!gIsWorking) changeAllSelection(false);
}
function getTimeStrFromWodTimeStr(report) {
if (report == null) {
return;
}
let timestr = $(report.getAttribute("reporttime")).text();
const today = dayjs();
if (timestr.includes("昨天")) {
timestr = timestr.replace(
"昨天",
today.subtract(1, "d").format("YYYY年MM月DD日")
);
} else if (timestr.includes("今天")) {
timestr = timestr.replace("今天", today.format("YYYY年MM月DD日"));
} else if (timestr.includes("明天")) {
timestr = timestr.replace(
"明天",
today.add(1, "d").format("YYYY年MM月DD日")
);
}
return timestr;
}
function parseTime(timeStr) {
timeStr = timeStr.replace("年", "-").replace("月", "-").replace("日", "");
return dayjs(timeStr, "YYYY-MM-DD HH:mm");
}
function getTimeFromWodTimeStr(report) {
const timestr = getTimeStrFromWodTimeStr(report);
return parseTime(timestr);
}
function formatTime(date, format) {
return date.format(format);
}
function formatTime4report(report, format) {
return formatTime(getTimeFromWodTimeStr(report), format);
}
function getOverviewDiv() {
let $overviewDiv = $("div#overview");
if (!$overviewDiv.length) {
$("body:first").append(
$(
'<div style="visibility: hidden;"><div id="overview"><div id="progressbar"><div class="progress-label">初始化...</div></div><div id="detailMsg"></div></div></div>'
)
);
$overviewDiv = $("div#overview");
}
return $overviewDiv;
}
function exportLog() {
if (gIsWorking && !DEBUG) return;
gIsWorking = true;
// 获取前缀
var prefix = document.getElementById("prefix").value;
var timeFormatSuffix = document.getElementById("suffix").value;
var includeCheckbox = document.getElementById(rValue.Chk_includeData);
var singleCheckbox = document.getElementById(rValue.Chk_single);
var withLvCheckbox = document.getElementById(rValue.Chk_withLv);
var singleCheck = singleCheckbox.checked;
includeData = includeCheckbox.checked;
gWithLv = withLvCheckbox.checked;
var allCheckbox = document.getElementsByTagName("input");
// 单文件导出走特殊流程
if (singleCheck) {
gIsWorking = false;
let $overviewDiv = getOverviewDiv();
let $processbar = $overviewDiv.find("#progressbar");
let $processLabel = $overviewDiv.find("#progressbar .progress-label");
let $detailMsg = $overviewDiv.find("#detailMsg");
$overviewDiv.dialog({
autoOpen: true, // 是否自动弹出窗口
modal: true, // 设置为模态对话框
resizable: true,
width: 540, //弹出框宽度
height: 620, //弹出框高度
title: "导出进度", //弹出框标题
position: { my: "center", at: "center", of: window }, //窗口显示的位置
buttons: {
关闭: function () {
$(this).dialog("close");
},
},
});
$processbar.progressbar({
value: false,
change: function () {
$processLabel.text($processbar.progressbar("value") + "%");
},
complete: function () {
$processLabel.text("任务已全部完成!");
},
});
let total = 0;
let remain = 0;
// 设置定时任务,每秒检测导出进度
var interval = setInterval(function () {
$detailMsg.html($("#infoDiv").html());
if (!gIsWorking) {
allCheckbox = document.getElementsByTagName("input");
allCheckbox = Array.prototype.slice
.call(allCheckbox)
.filter(
(c) =>
rValue.Pattern_checkboxName.test(c.getAttribute("name")) &&
c.checked
);
if (allCheckbox.length) {
gIsWorking = true;
if (total < allCheckbox.length) total = allCheckbox.length;
remain = allCheckbox.length;
var report = allCheckbox[0];
gSelectedReport = [report];
heroes = [];
heroLvMap = {};
default_gTitle =
prefix +
(gWithLv ? rValue.Holder_Lv : "") +
report
.getAttribute("reportname")
.replace(/<[^>]+>/g, "")
.replace(/[ ]|[\r\n\t]/g, "");
if (timeFormatSuffix) {
var firstTimeStr = formatTime4report(report, timeFormatSuffix);
default_gTitle += firstTimeStr;
}
gTitle = default_gTitle;
// 更新进度
$processbar.progressbar(
"value",
parseFloat((((total - remain) * 100) / total).toFixed(0))
);
gZip = new JSZip();
headDiv = document
.getElementsByTagName("head")[0]
.cloneNode(true);
handleHead(headDiv);
gIndexDiv = gIndexTemplateDiv.cloneNode(true);
var table = document.createElement("div");
gCurrentReport = gSelectedReport[0];
if (includeData) {
StatEntireDiv = document.createElement("div");
var EntireInfoDiv = document.createElement("div");
EntireInfoDiv.id = "report_entire_info";
StatEntire = CreateStat(StatEntireDiv, EntireInfoDiv, true);
StatEntire.iscurrentPage = false;
}
if (!isDuel) GetLevelPage(1, 1);
else GetDuelPage();
} else {
clearInterval(interval);
$overviewDiv.dialog("close");
}
}
}, 1000);
return;
}
gSelectedReport = [];
for (var i = 0; i < allCheckbox.length; ++i) {
var theCheckbox = allCheckbox[i];
if (
rValue.Pattern_checkboxName.test(theCheckbox.getAttribute("name"))
) {
if (theCheckbox.checked) {
gSelectedReport.push(theCheckbox);
default_gTitle =
prefix +
(gWithLv ? rValue.Holder_Lv : "") +
theCheckbox
.getAttribute("reportname")
.replace(/<[^>]+>/g, "")
.replace(/[ ]|[\r\n\t]/g, "");
// 获取前缀和最下面勾选的战报名字作为默认,正则去除html标签,空格,换行,制表符
}
}
}
if (gSelectedReport.length > 0) {
heroes = [];
heroLvMap = {};
// 处理后缀
if (timeFormatSuffix) {
var firstReport = gSelectedReport[0];
var lastReport = gSelectedReport[gSelectedReport.length - 1];
var firstTimeStr = formatTime4report(firstReport, timeFormatSuffix);
var lastTimeStr = formatTime4report(lastReport, timeFormatSuffix);
default_gTitle += firstTimeStr;
if (firstReport != lastReport && firstTimeStr != lastTimeStr) {
default_gTitle += "-" + lastTimeStr;
}
}
gTitle = window.prompt("输入战报名称", default_gTitle);
if (gTitle != null) {
gZip = new JSZip();
headDiv = document.getElementsByTagName("head")[0].cloneNode(true);
handleHead(headDiv);
gIndexDiv = gIndexTemplateDiv.cloneNode(true);
var table = document.createElement("div");
gCurrentReport = gSelectedReport[0];
if (includeData) {
StatEntireDiv = document.createElement("div");
var EntireInfoDiv = document.createElement("div");
EntireInfoDiv.id = "report_entire_info";
StatEntire = CreateStat(StatEntireDiv, EntireInfoDiv, true);
StatEntire.iscurrentPage = false;
}
if (!isDuel) GetLevelPage(1, 1);
else GetDuelPage();
} else gIsWorking = false;
} else {
window.alert("没有选择任何战报");
gIsWorking = false;
}
}
function GetDuelPage() {
var XmlHttp = new XMLHttpRequest();
XmlHttp.onreadystatechange = function () {
try {
if (XmlHttp.readyState == 4 && XmlHttp.status == 200) {
gResponseDiv.innerHTML = XmlHttp.responseText;
ReadDuelPage();
}
} catch (e) {
alert("GetLevelPage XMLHttpRequest.onreadystatechange(): " + e);
}
};
XmlHttp.open(
"GET",
gCurrentReport.getAttribute("href") + "&IS_POPUP=1¤t_view[1]",
true
);
XmlHttp.send(null);
}
function ReadDuelPage() {
var rows = gIndexDiv.getElementsByTagName("tr");
var row = rows[rows.length - 1];
row.parentNode.appendChild(row.cloneNode(true));
row.setAttribute("class", gIndexRowclass);
if (gIndexRowclass == "row0") gIndexRowclass = "row1";
else gIndexRowclass = "row0";
row.cells[0].innerHTML = replaceDate(gCurrentReport.getAttribute("c0"));
row.cells[1].innerHTML = gCurrentReport.getAttribute("c1");
row.cells[2].innerHTML = gCurrentReport.getAttribute("reporttime");
var cell = row.cells[3];
cell.innerHTML = "";
addIndexNewButton(
cell,
"细节",
"document.location.href='" + gCurrentReport.value + "/detail.html';"
);
if (includeData) {
var EntireInfoDiv = document.createElement("div");
EntireInfoDiv.id = "report_entire_info";
Stat = CreateStat(
node_before(gResponseDiv.getElementsByTagName("h2")[0].nextSibling),
EntireInfoDiv,
true
);
Stat.nTotalPages = 1;
Stat.iscurrentPage = true;
}
multiPageDiv.push(gResponseDiv);
infodiv.innerHTML = "保存决斗: " + gTitle;
if (includeData) CountStat(gResponseDiv, true, true);
for (var i = 0; i < multiPageDiv.length; i++) {
var thepage = multiPageDiv[i];
var theFileName = gCurrentReport.value + "/detail.html";
if (i > 0) {
theFileName = gCurrentReport.value + "/detail_" + (i + 1) + ".html";
Stat.iscurrentPage = false;
}
if (includeData) {
Stat.setNode(
node_before(thepage.getElementsByTagName("h1")[0].nextSibling)
);
Stat.Show(true);
}
gZip.file(theFileName, handlePage(thepage, null));
}
multiPageDiv = [];
gCurrentReport.checked = false;
for (var i = 0; i < gSelectedReport.length; ++i) {
var theCheckbox = gSelectedReport[i];
if (theCheckbox.checked) {
gCurrentReport = theCheckbox;
if (includeData) {
StatEntireDiv = document.createElement("div");
var EntireInfoDiv = document.createElement("div");
EntireInfoDiv.id = "report_entire_info";
StatEntire = CreateStat(StatEntireDiv, EntireInfoDiv, true);
StatEntire.iscurrentPage = false;
}
GetDuelPage();
return;
}
}
handleIndexPage();
infodiv.innerHTML =
"保存决斗战报: " +
gTitle +
"<br/>" +
gCurrentReport.getAttribute("title");
var indexStr =
"<html>\n" +
headDiv.outerHTML +
"\n<body>\n<h1>" +
gTitle +
"</h1><br/>\n" +
gIndexDiv.innerHTML +
"\n</body>\n</html>";
gZip.file("index.html", indexStr);
gZip
.generateAsync({
type: "blob",
compression: "DEFLATE",
compressionOptions: { level: 7 },
})
.then(function (content) {
//saveAs(content, "wodlog" + '_' + Math.random().toString(36).substr(2, 9) + ".zip");
saveAs(content, "wodlog" + "_" + gTitle + ".zip");
});
// alert("zip文件生成完毕");
console.log("zip文件生成完毕");
infodiv.innerHTML = "";
gResponseDiv.innerHTML = "";
gIsWorking = false;
}
function GetLevelPage(nLevel, nRepPage) {
var XmlHttp = new XMLHttpRequest();
XmlHttp.onreadystatechange = function () {
try {
if (XmlHttp.readyState == 4 && XmlHttp.status == 200) {
gResponseDiv.innerHTML = XmlHttp.responseText;
ReadLevelPage(nLevel, nRepPage);
}
} catch (e) {
alert("GetLevelPage XMLHttpRequest.onreadystatechange(): " + e);
}
};
var URL =
location.protocol +
"//" +
location.host +
"/wod/spiel/dungeon/report.php" +
"?cur_rep_id=" +
gCurrentReport.value +
"&gruppe_id=¤t_level=" +
nLevel +
"&REPORT_PAGE=" +
nRepPage +
"&IS_POPUP=1";
XmlHttp.open("GET", URL, true);
XmlHttp.send(null);
}
function ReadLevelPage(nLevel, nRepPage) {
if (nLevel == 1) {
gCurrentReport.setAttribute("maxLevel", GetMaxLevel(gResponseDiv, 1));
var rows = gIndexDiv.getElementsByTagName("tr");
var row = rows[rows.length - 1];
row.parentNode.appendChild(row.cloneNode(true));
row.setAttribute("class", gIndexRowclass);
if (gIndexRowclass == "row0") gIndexRowclass = "row1";
else gIndexRowclass = "row0";
row.cells[0].innerHTML = replaceDate(
gCurrentReport.getAttribute("reporttime")
);
row.cells[1].innerHTML = gCurrentReport.getAttribute("reportname");
var cell = row.cells[2];
cell.innerHTML = "";
addIndexNewButton(
cell,
"统计表",
"document.location.href='" +
gCurrentReport.value +
"/statistics.html';"
);
addIndexNewButton(
cell,
"获得物品",
"document.location.href='" + gCurrentReport.value + "/items.html';"
);
for (var i = 1; i <= gCurrentReport.getAttribute("maxLevel"); i++) {
addIndexNewButton(
cell,
"层 " + i,
"document.location.href='" +
gCurrentReport.value +
"/level" +
i +
".html';"
);
}
}
var ret = GetRepPageInfo(gResponseDiv, [1, 1]);
var nCurrRepPage = ret[0];
var nMaxRepPage = ret[1];
if (includeData && nCurrRepPage == 1) {
var EntireInfoDiv = document.createElement("div");
EntireInfoDiv.id = "report_entire_info";
Stat = CreateStat(
node_before(gResponseDiv.getElementsByTagName("h2")[0].nextSibling),
EntireInfoDiv,
true
);
Stat.nTotalPages = nMaxRepPage;
Stat.iscurrentPage = true;
}
if (nMaxRepPage > 1) {
var copyDiv = document.createElement("div");
copyDiv.innerHTML = gResponseDiv.innerHTML;
multiPageDiv.push(copyDiv);
if (includeData) Stat.iscurrentPage = false;
} else multiPageDiv.push(gResponseDiv);
var maxLevel = gCurrentReport.getAttribute("maxLevel");
infodiv.innerHTML =
"保存战报: " +
gTitle +
"<br/>" +
gCurrentReport.getAttribute("title") +
" - 第 " +
nLevel +
"/" +
maxLevel +
" 层详细资料";
if (includeData)
CountStat(gResponseDiv, nCurrRepPage === nMaxRepPage, true);
if (nCurrRepPage === nMaxRepPage) {
for (var i = 0; i < multiPageDiv.length; i++) {
var thepage = multiPageDiv[i];
var theFileName = gCurrentReport.value + "/level" + nLevel + ".html";
if (i > 0) {
theFileName =
gCurrentReport.value +
"/level" +
nLevel +
"_" +
(i + 1) +
".html";
if (includeData) Stat.iscurrentPage = false;
}
if (includeData) {
Stat.setNode(
node_before(thepage.getElementsByTagName("h2")[0].nextSibling)
);
Stat.Show(true);
}
gZip.file(theFileName, handlePage(thepage, nLevel));
}
multiPageDiv = [];
}
if (nCurrRepPage < nMaxRepPage) GetLevelPage(nLevel, nCurrRepPage + 1);
else if (nLevel < maxLevel) GetLevelPage(nLevel + 1, 1);
else GetStatPage();
}
function GetStatPage() {
var queryString =
$("form[name='the_form']").formSerialize() +
"&IS_POPUP=1&" +
gCurrentReport.getAttribute(rValue.Text_Stat) +
"=" +
rValue.Text_Stat;
var XmlHttp = new XMLHttpRequest();
XmlHttp.onreadystatechange = function () {
try {
if (XmlHttp.readyState == 4 && XmlHttp.status == 200) {
gResponseDiv.innerHTML = XmlHttp.responseText;
infodiv.innerHTML =
"保存战报: " +
gTitle +
"<br/>" +
gCurrentReport.getAttribute("title") +
" - 统计表";
if (includeData) {
StatEntire.setNode(
node_before(
gResponseDiv.getElementsByTagName("h2")[0].nextSibling
)
);
StatEntire.Show(true);
}
gZip.file(
gCurrentReport.value + "/statistics.html",
handlePage(gResponseDiv)
);
GetItemPage();
}
} catch (e) {
alert("GetItemPage XMLHttpRequest.onreadystatechange(): " + e);
}
};
var URL =
location.protocol +
"//" +
location.host +
"/wod/spiel/dungeon/report.php";
XmlHttp.open("POST", URL, true);
XmlHttp.setRequestHeader(
"Content-type",
"application/x-www-form-urlencoded"
);
// XmlHttp.setRequestHeader("Content-length", queryString.length);
// XmlHttp.setRequestHeader("Connection", "close");
XmlHttp.send(queryString);
}
function getAvgLvTip() {
if (!heroes.length) {
return "";
}
let finalMap = {};
for (let heroName of heroes) {
heroLvMap[heroName] &&
(finalMap[heroName] = parseInt(heroLvMap[heroName]));
}
let avgLv =
Math.round(
(100 * Object.values(finalMap).reduce((a, b) => a + b)) /
Object.keys(finalMap).length
) / 100;
return "「" + avgLv.toFixed(2) + "级」";
}
function GetItemPage() {
var queryString =
$("form[name='the_form']").formSerialize() +
"&IS_POPUP=1&" +
gCurrentReport.getAttribute(rValue.Text_Item) +
"=" +
rValue.Text_Item;
var XmlHttp = new XMLHttpRequest();
XmlHttp.onreadystatechange = function () {
try {
if (XmlHttp.readyState == 4 && XmlHttp.status == 200) {
gResponseDiv.innerHTML = XmlHttp.responseText;
infodiv.innerHTML =
"保存战报: " +
gTitle +
"<br/>" +
gCurrentReport.getAttribute("title") +
" - 获得物品";
gZip.file(
gCurrentReport.value + "/items.html",
handlePage(gResponseDiv)
);
gCurrentReport.checked = false;
for (var i = 0; i < gSelectedReport.length; ++i) {
var theCheckbox = gSelectedReport[i];
if (theCheckbox.checked) {
gCurrentReport = theCheckbox;
if (includeData) {
StatEntireDiv = document.createElement("div");
var EntireInfoDiv = document.createElement("div");
EntireInfoDiv.id = "report_entire_info";
StatEntire = CreateStat(StatEntireDiv, EntireInfoDiv, true);
StatEntire.iscurrentPage = false;
}
GetLevelPage(1, 1);
return;
}
}
handleIndexPage();
// 导出前把平均等级替换上去
if (gWithLv) {
gTitle = gTitle.replace(rValue.Holder_Lv, getAvgLvTip());
}
infodiv.innerHTML =
"保存战报: " + gTitle + "<br/>" + "生成Zip文件";
var indexStr =
"<html>\n" +
headDiv.outerHTML +
"\n<body>\n<h1>" +
gTitle +
"</h1><br/>\n" +
gIndexDiv.innerHTML +
"\n</body>\n</html>";
gZip.file("index.html", indexStr);
gZip
.generateAsync({
type: "blob",
compression: "DEFLATE",
compressionOptions: { level: 7 },
})
.then(function (content) {
//saveAs(content, "wodlog" + '_' + Math.random().toString(36).substr(2, 9) + ".zip");
saveAs(content, "wodlog" + "_" + gTitle + ".zip");
gIsWorking = false;
});
// alert("zip文件生成完毕");
console.log("zip文件生成完毕");
infodiv.innerHTML = "";
gResponseDiv.innerHTML = "";
}
} catch (e) {
alert("GetItemPage XMLHttpRequest.onreadystatechange(): " + e);
}
};
var URL =
location.protocol +
"//" +
location.host +
"/wod/spiel/dungeon/report.php";
XmlHttp.open("POST", URL, true);
XmlHttp.setRequestHeader(
"Content-type",
"application/x-www-form-urlencoded"
);
// XmlHttp.setRequestHeader("Content-length", queryString.length);
// XmlHttp.setRequestHeader("Connection", "close");
XmlHttp.send(queryString);
}
function GetMaxLevel(page, DefaultValue) {
var ret = DefaultValue;
var allInputs = page.getElementsByTagName("input");
for (var i = 0; i < allInputs.length; ++i) {
var name = allInputs[i].getAttribute("name");
if (rValue.Pattern_level.test(name)) {
var levelnumber = Number(rValue.Pattern_idNumber.exec(name)[1]);
if (levelnumber > ret) ret = levelnumber;
}
}
return ret;
}
function handlePage(page, nLevel) {
if (gWithLv) {
let $page = $(page);
if ($page.find('h1:contains("战斗统计: ")').length) {
let $heroThs = $page.find(
"h2 ~ table.content_table table tr:first th:gt(0)"
);
heroes = [];
$heroThs.each(function (i, el) {
heroes.push($(el).text().trim());
});
console.log(heroes);
}
let $heroLvTrs = $page.find("table.rep_status_table tr:not(:first)");
if ($heroLvTrs.length) {
heroLvMap = {};
$heroLvTrs.each(function (i, el) {
let heroName = $(el).find("td:eq(1)").text().trim();
let heroLv = parseInt($(el).find("td:eq(2)").text().trim());
if (heroName && heroLv) {
heroLvMap[heroName] = parseInt(heroLv);
}
});
console.log(heroLvMap);
}
}
var thepage = page.getElementsByTagName("form")[0];
var h2 = thepage.getElementsByTagName("h2")[0];
if (h2) {
h2.innerHTML = replaceDate(h2.innerHTML);
}
//removePageInput(thepage);
replaceURL(thepage, "link", "href");
replaceURL(thepage, "script", "src");
replaceURL(thepage, "img", "src");
replaceURL(thepage, "a", "href", "#");
replaceButton(thepage);
if (nLevel) replaceLevelPage(thepage, nLevel);
return (
"<html>\n" +
headDiv.outerHTML +
"\n<body>\n" +
replaceOther(thepage.outerHTML) +
"\n</body>\n</html>"
);
}
function handleHead(head) {
if (gTitle == null) gTitle = default_gTitle;
head.getElementsByTagName("title")[0].innerHTML = gTitle.replace(
rValue.Holder_Lv,
""
);
replaceURL(head, "link", "href");
var bodyScript = document
.getElementsByTagName("body")[0]
.cloneNode(true)
.getElementsByTagName("script");
for (var i = 0; i < bodyScript.length; i++)
head.appendChild(bodyScript[i]);
var scripts = head.getElementsByTagName("script");
for (var i = scripts.length - 1; i >= 0; i--) {
script = scripts[i];
handleScript(script);
}
replaceURL(head, "script", "src");
var metas = head.getElementsByTagName("meta");
for (var i = metas.length - 1; i >= 0; i--) {
var meta = metas[i];
if (!meta.httpEquiv) meta.parentNode.removeChild(meta);
}
if (includeData) es_addStyle(head, Style);
head.innerHTML = head.innerHTML + "\n";
return head;
}
function handleScript(script) {
var patten = /wod_standard.js|wodtooltip.js/;
var scriptPatten = /(wodToolTipInit\(.*\);)\s*(wodInitialize\([^;]*\);)/;
if (script.src) {
if (!patten.test(script.src)) script.parentNode.removeChild(script);
} else if (script.firstChild) {
var scriptStr = script.firstChild.data;
var result = scriptPatten.exec(scriptStr);
if (result != null)
if (result[1] && result[2])
scriptStr =
"window.onload = function(e){" + result[1] + result[2] + "}";
scriptStr = scriptStr
.replace(
/wodInitialize\(''/g,
"wodInitialize('" + location.host + "'"
)
.replace("'0'", "'1'");
scriptStr +=
'\nfunction o(t,n){ \n var url="' +
location.origin +
'/wod/spiel/";\n';
scriptStr += 'if(t=="n"){url += "help/npc"}\n';
scriptStr += 'if(t=="s"){url += "hero/skill"}\n';
scriptStr += 'if(t=="i"){url += "hero/item"}\n';
scriptStr += 'return wo(url + ".php?name=" + n + "&IS_POPUP=1");}\n';
if (includeData) {
scriptStr += "var CTable=function(){};\n";
scriptStr +=
"CTable.GetNumber = " + CTable.GetNumber.toString() + "\n";
scriptStr += "CompareString = " + CompareString.toString() + "\n";
scriptStr += "ct = " + CTable.OnClickTitle.toString() + "\n";
scriptStr += "cf = " + CTable.OnChangeFilter.toString() + "\n";
scriptStr += "co = " + CTable.OnChangeOrder.toString() + "\n";
scriptStr += "sd = " + CTable.OnShowDetail.toString() + "\n";
scriptStr += "st = " + CStat.OnTabClick.toString() + "\n";
}
script.firstChild.data = scriptStr;
}
}
function removePageInput(page) {
var inputs = page.getElementsByTagName("input");
for (var i = inputs.length - 1; i >= 0; i--) {
var theInput = inputs[i];
if (theInput.type == "hidden") {
theInput.parentNode.removeChild(theInput);
break;
}
}
return page;
}
function replaceURL(page, tag, attr, value) {
var test_pattern = /^\//;
var test1_pattern = /^#/;
var onclick_pattern = /([^\/]*)\.php\?name=([^&]*)/;
var allLink = page.getElementsByTagName(tag);
var path = location.origin + location.pathname;
var m = path.match(/(.*)[\/\\]([^\/\\]+)\.\w+$/);
for (var i = 0; i < allLink.length; i++) {
var link = allLink[i];
if (link.hasAttribute(attr)) {
var uri = link.getAttribute(attr);
if (value) {
if (!test1_pattern.test(uri)) link.setAttribute(attr, value);
if (link.hasAttribute("onclick")) {
var result = onclick_pattern.exec(link.getAttribute("onclick"));
if (result && result[1] && result[2])
link.setAttribute(
"onclick",
"return o('" +
result[1].substr(0, 1) +
"','" +
result[2] +
"');"
);
}
} else {
if (!rValue.pattern_http.test(uri)) {
if (test_pattern.test(uri)) {
link.setAttribute(attr, location.origin + uri);
} else if (!test1_pattern.test(uri)) {
link.setAttribute(attr, m[1] + "/" + uri);
}
}
}
}
}
}
function replaceButton(page) {
var allInputs = page.getElementsByTagName("input");
for (var i = 0; i < allInputs.length; ++i) {
var name = allInputs[i].getAttribute("name");
if (rValue.Pattern_level.test(name)) {
var levelURL =
"document.location.href='level" +
rValue.Pattern_idNumber.exec(name)[1] +
".html';";
var button = allInputs[i];
button.setAttribute("type", "button");
button.setAttribute("onclick", levelURL);
}
if (rValue.Pattern_item.test(name)) {
var levelURL = "document.location.href='items.html';";
var button = allInputs[i];
button.setAttribute("type", "button");
button.setAttribute("onclick", levelURL);
}
if (rValue.Pattern_stat.test(name)) {
var levelURL = "document.location.href='statistics.html';";
var button = allInputs[i];
button.setAttribute("type", "button");
button.setAttribute("onclick", levelURL);
}
if (rValue.Pattern_detail.test(name)) {
var levelURL = "document.location.href='level1.html';";
var button = allInputs[i];
button.setAttribute("type", "button");
button.setAttribute("onclick", levelURL);
}
if (name == "overview" || name == "") {
var levelURL = "document.location.href='../index.html';";
var button = allInputs[i];
button.setAttribute("type", "button");
button.setAttribute("onclick", levelURL);
}
}
}
function replaceLevelPage(page, nLevel) {
var IndexPatt = /\D*([\d]+)\D*/;
allURL = page.getElementsByTagName("a");
for (var i = 0; i < allURL.length; ++i) {
var theURL = allURL[i];
if (theURL.className == "paginator") {
var Result = IndexPatt.exec(theURL.textContent);
var pageNum = Number(Result[1]);
theURL.href =
"level" + nLevel + (pageNum > 1 ? "_" + pageNum : "") + ".html";
}
}
}
function replaceDate(sDate) {
var today = new Date();
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
var ret = sDate.replace(
"今天",
today.getFullYear() +
"年" +
(today.getMonth() + 1) +
"月" +
today.getDate() +
"日"
);
ret = ret.replace(
"昨天",
yesterday.getFullYear() +
"年" +
(yesterday.getMonth() + 1) +
"月" +
yesterday.getDate() +
"日"
);
return ret;
}
function replaceOther(sHTML) {
var ret = sHTML.replace(
/wodInitialize\(''/g,
"wodInitialize('" + location.host + "'"
);
ret = ret.replace(/wo\('\/wod/g, "wo('" + location.origin + "/wod");
return ret;
}
function prepareIndexPageTemplate() {
var allRow = gIndexTemplateDiv.getElementsByTagName("tr");
for (var j = allRow.length - 1; j > 1; --j) {
var row = allRow[j];
if (rValue.Pattern_logRow.test(row.getAttribute("class"))) {
row.parentNode.removeChild(row);
}
}
}
function addIndexNewButton(cell, buttonText, url) {
var newButton = document.createElement("input");
newButton.setAttribute("type", "button");
newButton.setAttribute("class", "button clickable");
newButton.setAttribute("value", buttonText);
newButton.setAttribute("onclick", url);
cell.appendChild(newButton);
}
function handleIndexPage() {
var allRow = gIndexDiv.getElementsByTagName("tr");
var row = allRow[allRow.length - 1];
row.parentNode.removeChild(row);
}
function insertFilter() {
if (this.checked) addFilter(this.nextSibling);
else hideFilter();
}
var gIndexRowclass = "row0";
var gCurrentReport;
var gZip;
var rLocal;
var infodiv;
var gTitle;
var gSelectedReport = [];
var gIndexTemplateDiv;
var gResponseDiv;
var multiPageDiv = [];
var gIndexDiv;
var gIsWorking = false;
var includeData = false;
var gWithLv = false;
var headDiv;
var world = "";
var default_gTitle;
var isaddFilter = true;
var rContents = {
OrigText_H1_DungeonLog: ["Battle Report", "战报"],
OrigText_H1_DuelLog: ["Battle Report", "您的决斗"],
OrigText_Button_DungeonDetails: ["details", "详细资料"],
Text_Button_Exportlog: ["Export Log", "导出战报"],
Text_Button_SelectAll: ["Select All", "全选"],
Text_Button_ClearAll: ["Clear All", "清除"],
};
var rValue = {
Text_Item: "items",
Text_Stat: "stats",
Text_Checkbox: "chkLog",
Chk_includeData: "export_with_data",
Chk_single: "single_export",
Chk_withLv: "withLv_export",
Holder_Lv: "「等级」",
Pattern_level: /^level\[[\d]+\]/,
Pattern_stat: /^stats\[[\d]+\]/,
Pattern_item: /^items\[[\d]+\]/,
Pattern_detail: /^details\[[\d]+\]/,
Pattern_checkboxName: /^chkLog/,
Pattern_logRow: /^row\d/,
Pattern_idNumber: /([\d]+)/,
pattern_http: /^http/i,
};
var isDuel = false;
//-----------------------------------------------------------------------------
// "main"
//-----------------------------------------------------------------------------
function ReprotMain() {
rLocal = GetLocalContents(rContents);
if (rLocal === null) return;
var allH1 = document.getElementsByTagName("h1");
var i = 0;
var h1;
var shouldContinue = false;
if (allH1 === "undefined") return;
for (i = 0; i < allH1.length; ++i) {
h1 = allH1[i];
if (
h1.innerHTML == rLocal.OrigText_H1_DungeonLog ||
h1.innerHTML == rLocal.OrigText_H1_DuelLog
) {
infodiv = document.createElement("div");
infodiv.innerHTML = "";
infodiv.id = "infoDiv";
h1.parentNode.insertBefore(infodiv, h1.nextSibling);
var newLabel = document.createElement("label");
newLabel.innerHTML = "同时保存统计信息";
h1.parentNode.insertBefore(newLabel, h1.nextSibling);
var newCheckBox = document.createElement("input");
newCheckBox.setAttribute("type", "checkbox");
newCheckBox.setAttribute("class", "checkbox");
newCheckBox.setAttribute("value", "同时保存统计信息");
newCheckBox.addEventListener("change", insertFilter, false);
newCheckBox.id = rValue.Chk_includeData;
newLabel.setAttribute("for", newCheckBox.id);
h1.parentNode.insertBefore(newCheckBox, h1.nextSibling);
// 插入单文件导出复选框
var singleCheckLabel = document.createElement("label");
singleCheckLabel.innerHTML = "单文件导出";
h1.parentNode.insertBefore(singleCheckLabel, h1.nextSibling);
var singleCheckBox = document.createElement("input");
singleCheckBox.setAttribute("type", "checkbox");
singleCheckBox.setAttribute("class", "checkbox");
singleCheckBox.setAttribute("value", "单文件导出");
singleCheckBox.id = rValue.Chk_single;
singleCheckLabel.setAttribute("for", singleCheckBox.id);
h1.parentNode.insertBefore(singleCheckBox, h1.nextSibling);
// 插入文件名包含平均等级复选框
var withLvLabel = document.createElement("label");
withLvLabel.innerHTML = "平均等级";
h1.parentNode.insertBefore(withLvLabel, h1.nextSibling);
var withLvCheckBox = document.createElement("input");
withLvCheckBox.setAttribute("type", "checkbox");
withLvCheckBox.setAttribute("class", "checkbox");
withLvCheckBox.setAttribute("value", "平均等级");
withLvCheckBox.setAttribute("checked", true);
withLvCheckBox.id = rValue.Chk_withLv;
withLvLabel.setAttribute("for", withLvCheckBox.id);
h1.parentNode.insertBefore(withLvCheckBox, h1.nextSibling);
// 插入日期后缀框
var suffixBox = document.createElement("input");
suffixBox.setAttribute("id", "suffix");
suffixBox.setAttribute("size", "14");
suffixBox.setAttribute("type", "text");
suffixBox.setAttribute("placeholder", "日期后缀");
// 默认使用年月日时分为后缀
suffixBox.setAttribute("value", "YYYYMMDDHHmm");
suffixBox.innerHTML = "YYYYMMDDHHmm";
h1.parentNode.insertBefore(suffixBox, h1.nextSibling);
var suffixSpan = document.createElement("span");
suffixSpan.innerHTML = "日期后缀:";
h1.parentNode.insertBefore(suffixSpan, h1.nextSibling);
// 插入前缀框
var prefixBox = document.createElement("input");
prefixBox.setAttribute("id", "prefix");
prefixBox.setAttribute("size", "14");
prefixBox.setAttribute("type", "text");
prefixBox.setAttribute("placeholder", "战报导出命名前缀");
// 默认使用团队名作为前缀
prefixBox.setAttribute(
"value",
"[" + document.getElementsByName("gruppe_name")[0].value + "]"
);
prefixBox.innerHTML =
"[" + document.getElementsByName("gruppe_name")[0].value + "]";
h1.parentNode.insertBefore(prefixBox, h1.nextSibling);
var newLabel = document.createElement("span");
newLabel.innerHTML = "战报导出命名前缀:";
h1.parentNode.insertBefore(newLabel, h1.nextSibling);
InsertButton(h1, rLocal.Text_Button_Exportlog, exportLog);
InsertButton(h1, rLocal.Text_Button_ClearAll, cleartAll);
InsertButton(h1, rLocal.Text_Button_SelectAll, selectAll);
gResponseDiv = document.createElement("div");
gResponseDiv.innerHTML = "";
gIndexTemplateDiv = document.createElement("div");
gIndexTemplateDiv.innerHTML = "";
shouldContinue = true;
break;
}
}
if (!shouldContinue) return;
var allTable = document.getElementsByTagName("table");
for (i = 0; i < allTable.length; ++i) {
var theTable = allTable[i];
if (theTable.getAttribute("class") == "content_table") {
gIndexTemplateDiv.innerHTML = theTable.outerHTML;
prepareIndexPageTemplate();
var allRow = theTable.getElementsByTagName("tr");
for (var j = 0; j < allRow.length; ++j) {
var row = allRow[j];
var newCheckbox = document.createElement("input");
newCheckbox.setAttribute("type", "checkbox");
if (rValue.Pattern_logRow.test(row.getAttribute("class"))) {
if (isDuel) {
var reportName =
"<span>" +
row.cells[0].innerHTML.replace("<hr>", " <b>对战</b> ") +
" " +
row.cells[1].innerText +
"</span>";
var reportTime = "<span>" + row.cells[2].innerText + "</span>";
var title = reportName + " - " + reportTime;
var allduel = row.cells[3].getElementsByTagName("a");
var href = allduel[0].href;
var onclick_pattern = /\?DuellId=([^&]*)/;
var result = onclick_pattern.exec(href);
newCheckbox.setAttribute(
"name",
rValue.Text_Checkbox + "[" + j + "]"
);
newCheckbox.setAttribute(
"id",
rValue.Text_Checkbox + "[" + j + "]"
);
newCheckbox.setAttribute("value", result[1]);
newCheckbox.setAttribute("href", href);
newCheckbox.setAttribute("title", title);
newCheckbox.setAttribute("reportname", reportName);
newCheckbox.setAttribute("reporttime", reportTime);
newCheckbox.setAttribute(
"c0",
row.cells[0].innerHTML.replace("<hr>", " <b>对战</b> ")
);
newCheckbox.setAttribute("c1", row.cells[1].innerHTML);
newCheckbox.setAttribute("maxLevel", 1);
row.cells[0].insertBefore(newCheckbox, row.cells[0].firstChild);
} else {
var reportName =
"<span>" + row.cells[1].firstChild.innerHTML + "</span>";
var reportTime =
"<span>" + row.cells[0].firstChild.innerHTML + "</span>";
var title = reportName + " - " + reportTime;
var allInput = row.cells[2].getElementsByTagName("input");
var id = "";
var index = "";
for (var k = 0; k < allInput.length; ++k) {
var input = allInput[k];
var name = input.getAttribute("name");
var value = input.getAttribute("value");
if (name.indexOf("report_id") != -1) {
var Result = rValue.Pattern_idNumber.exec(name);
index = Number(Result[1]);
id = value;
break;
}
}
newCheckbox.setAttribute(
"name",
rValue.Text_Checkbox + "[" + index + "]"
);
newCheckbox.setAttribute(
"id",
rValue.Text_Checkbox + "[" + index + "]"
);
newCheckbox.setAttribute("value", id);
newCheckbox.setAttribute("title", title);
newCheckbox.setAttribute("reportname", reportName);
newCheckbox.setAttribute("reporttime", reportTime);
newCheckbox.setAttribute("maxLevel", 1);
newCheckbox.setAttribute(
rValue.Text_Item,
rValue.Text_Item + "%5B" + index + "%5D"
);
newCheckbox.setAttribute(
rValue.Text_Stat,
rValue.Text_Stat + "%5B" + index + "%5D"
);
row.cells[0].insertBefore(newCheckbox, row.cells[0].firstChild);
}
}
}
break;
}
}
var allInput = document.getElementsByTagName("input");
for (var i = 0; i < allInput.length; i++) {
var input = allInput[i];
if (input.name && input.name == "wod_post_world") {
world = input.value;
break;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
function test(o) {
alert('test');
}
function filterMain() {
function Factoryfilter(o) {
return function () {
filterReport(o);
};
}
var tables = document.getElementsByTagName("table");
for (var i = 0; i < tables.length; i++) {
var table = tables[i];
if (table.className == "rep_status_table") {
for (var j = 0; j < table.rows.length; j++) {
var row = table.rows[j];
for (var k = 0; k < row.cells.length; k++) {
var cell = row.cells[k];
if (cell.className == "hero") {
var newCheckbox = document.createElement("input");
newCheckbox.setAttribute("type", "checkbox");
newCheckbox.setAttribute("class", "filter");
newCheckbox.value = cell.firstChild.textContent;
cell.insertBefore(newCheckbox, cell.firstChild);
//newCheckbox.setAttribute("onclick", "test(this);");
newCheckbox.addEventListener("click", Factoryfilter(newCheckbox), false);
break;
}
}
}
}
}
}
filterReport = function (o) {
var checkboxlist = document.getElementsByTagName("input");
var selectedheros = [];
var classNamepattern = /^[rep_monster|rep_hero|rep_myhero]/;
for (var i = 0; i < checkboxlist.length; i++) {
var checkbox = checkboxlist[i];
if (checkbox.getAttribute("type") == "checkbox" && checkbox.getAttribute("class") == "filter") {
if (checkbox.value == o.value)
checkbox.checked = o.checked;
if (checkbox.checked && selectedheros.indexOf(checkbox.value) <= -1)
selectedheros.push(checkbox.value);
}
}
var tables = document.getElementsByTagName("table");
for (var i = 0; i < tables.length; i++) {
var table = tables[i];
if (table.className != "rep_status_table") {
var istheTable = false;
for (var j = 0; j < table.rows.length; j++) {
var row = table.rows[j];
var show = false;
if (row.cells.length <= 0 || row.cells[0].colSpan > 1)
continue;
if (istheTable || row.cells[0].className == "rep_initiative") {
istheTable = true;
for (var k = 0; k < row.cells.length; k++) {
var cell = row.cells[k];
var links = cell.getElementsByTagName("a");
for (var index = 0; index < links.length; index++) {
var link = links[index];
if (classNamepattern.test(link.className)) {
var name = link.textContent;
if (selectedheros.length <= 0 || selectedheros.indexOf(name) > -1) {
show = true;
break;
}
}
}
if (show)
break;
}
row.style.display = show ? '' : 'none';
}
}
}
}
};
try {
isDuel = (window.location.href.indexOf("duell.php") > 0);
Main();
ReprotMain();
//filterMain();
} catch (e) {
alert("Main(): " + e);
}
})();