Commit d1bc3354 authored by nanahira's avatar nanahira

playerlist

parent 14a74aae
......@@ -10,7 +10,7 @@ class Tx3Fetcher {
responseType: "document"
})).data;
const parsedContent = parseHTML(content);
return new User(id, content);
return new User(id, content, null);
/*} catch(e) {
console.error(`Errored fetching role data from ${id}: ${e.toString()}`);
return null;
......
import HTML from "posthtml-parser";
import _, { first } from "underscore";
import {getDepthOfTree, getNumber, findNodeIndex, findNodeIndexByAttribute, findNodeIndexByContent, findNodeIndexByTag, findAllNodeIndex, getContinuousData, getContinuousNodes, getString} from "./utility";
export interface PlayerRow {
url: string;
rank: number;
name: string;
category: string;
serverArea: string;
server: string;
level: number;
region: string;
score: number;
equip: number;
totalScore: number;
}
function getPlayerRowFromTree(tree: HTML.Tree): PlayerRow {
const nodes = getContinuousNodes(tree, [1], 0, 2, 10);
return {
url: (nodes[1] as HTML.NodeTag).attrs.href as string,
rank: getNumber(nodes[0]),
name: getString(nodes[1]),
serverArea: getString(nodes[2]),
server: getString(nodes[3]),
level: getNumber(nodes[4]),
category: getString(nodes[5]),
region: getString(nodes[6]),
score: getNumber(nodes[7]),
equip: getNumber(nodes[8]),
totalScore: getNumber(nodes[9])
}
}
export class PlayerList {
rows: PlayerRow[];
private parseRows(content: string) {
this.rows = [];
const parsedContent = HTML(content);
const tablePos = findNodeIndexByTag(parsedContent, "table", []);
const tableTree = getDepthOfTree(parsedContent, tablePos);
const playerPoses = findAllNodeIndex(tableTree, (node) => {
return typeof (node) !== "string" && node.tag === "tr" && node.attrs.class !== "trTop2";
}, []);
this.rows = playerPoses.map(pos => {
const tree = getDepthOfTree(tableTree, pos);
return getPlayerRowFromTree(tree);
})
}
constructor(content: string) {
this.parseRows(content);
}
}
import HTML from "posthtml-parser";
import _, { first } from "underscore";
import {getDepthOfTree, getNumber, findNodeIndex, findNodeIndexByAttribute, findNodeIndexByContent, findNodeIndexByTag, getContinuousNumber} from "./utility";
function getDepthOfTree(tree: HTML.Tree, indexList: number[]): HTML.Tree {
if (indexList.length) {
const _indexList = _.clone(indexList);
const index = _indexList.splice(0, 1)[0];
const node = tree[index];
if (typeof (node) === "string" || !node.content) {
return [node];
}
return getDepthOfTree(node.content, _indexList);
} else {
return tree;
}
}
function findNodeIndex(baseTree: HTML.Tree, condition: (node: HTML.Node) => boolean, offset: number[]): number[] {
let queue = [offset];
while (queue.length) {
const indexList = queue.splice(0, 1)[0];
const tree = getDepthOfTree(baseTree, indexList);
for (let i = 0; i < tree.length; ++i) {
const node = tree[i];
const newList = indexList.concat([i]);
if (condition(node)) {
//console.log(newList);
return newList;
} else if (typeof (node) !== "string") {
queue.push(newList);
}
}
}
return null;
}
function findNodeIndexByContent(baseTree: HTML.Tree, label: string, offset: number[]): number[] {
return findNodeIndex(baseTree, (node) => {
return node === label;
}, offset);
}
function findNodeIndexByAttribute(baseTree: HTML.Tree, key: string, value: string, offset: number[]): number[] {
return findNodeIndex(baseTree, (node) => {
return typeof (node) !== "string" && node.attrs && node.attrs[key] === value;
}, offset);
}
function findNodeIndexByTag(baseTree: HTML.Tree, tag: string, offset: number[]): number[] {
return findNodeIndex(baseTree, (node) => {
return typeof (node) !== "string" && node.tag === tag;
}, offset);
}
const chineseCapitalNumbers = ["", "", "", "", "", "", "", "", "", ""]
function getNumber(node: HTML.Node) {
let numberStr: string;
if (typeof (node) === "string") {
numberStr = node;
} else {
const subTree = node.content;
if (!subTree) {
return null;
}
numberStr = subTree[0] as string;
}
numberStr = numberStr.trim();
let stringMatch: RegExpMatchArray;
if (numberStr === "没有上榜") {
return null;
} else if (stringMatch = numberStr.match(/^([天地])魂$/)) {
return stringMatch[1] === "" ? 2 : 1;
} else if (stringMatch = numberStr.match(/^(.+)(.+)境界$/)) {
return (_.findIndex(chineseCapitalNumbers, (m) => m === stringMatch[1]) << 8) | _.findIndex(chineseCapitalNumbers, (m) => m === stringMatch[2]);
} else if (stringMatch = numberStr.match(/^(\d+)-(\d+)$/)) {
const minValue = parseInt(stringMatch[1]);
const maxValue = parseInt(stringMatch[2]);
return (minValue << 16) | maxValue;
} else {
return parseInt(numberStr);
}
}
interface AttackAttribute {
export interface AttackAttribute {
'攻力': number, //大攻取前2字节int16,小攻取后2字节int16,法力也是这样
'命中': number,
'法力': number,
......@@ -91,7 +12,7 @@ interface AttackAttribute {
'附加伤害': number
}
interface DefenseAttribute {
export interface DefenseAttribute {
'防御': number,
'回避': number,
'法防': number,
......@@ -100,7 +21,7 @@ interface DefenseAttribute {
'知彼': number
}
interface SpecialAttribute {
export interface SpecialAttribute {
'身法': number,
'坚韧': number,
'定力': number,
......@@ -110,12 +31,13 @@ interface SpecialAttribute {
'铁壁': number
}
interface AdvancedAttribute { '追电': number, '骤雨': number, '疾语': number, '明思': number, '扰心': number, '人祸': number }
export interface AdvancedAttribute { '追电': number, '骤雨': number, '疾语': number, '明思': number, '扰心': number, '人祸': number }
export class User {
id: string;
content: HTML.Tree;
name: string;
region: string;
category: string;
serverArea: string;
server: string;
......@@ -145,17 +67,8 @@ export class User {
specialAttributes: SpecialAttribute;
advancedAttributes: AdvancedAttribute;
yhz: string[];
getContinuousData(_pos: number[], moveOffset: number, step: number, dataCount: number): number[] {
const pos = _.clone(_pos);
const datas: number[] = [];
for (let i = 0; i < dataCount; ++i) {
const node = getDepthOfTree(this.content, pos)[0];
datas.push(getNumber(node))
pos[pos.length - (moveOffset + 1)] += step;
}
return datas;
}
parseMetadata() {
private parseMetadata() {
let namePos = findNodeIndexByAttribute(this.content, "class", "sTitle", []);
this.name = getDepthOfTree(this.content, namePos.concat([0]))[0] as string;
namePos[namePos.length - 1] += 2;
......@@ -168,11 +81,11 @@ export class User {
levelPos[levelPos.length - 1]++;
this.level = getNumber(getDepthOfTree(this.content, levelPos)[0]);
}
parseEquipmentData() {
private parseEquipmentData() {
let ValuePos = findNodeIndexByContent(this.content, "装备评价:", []);
ValuePos.pop();
ValuePos[ValuePos.length - 1]++;
let datas = this.getContinuousData(ValuePos, 1, 2, 4);
let datas = getContinuousNumber(this.content, ValuePos, 1, 2, 4);
this.equipValue = datas[0];
this.equipRank = datas[1];
this.equipLocalRank = datas[2];
......@@ -181,7 +94,7 @@ export class User {
ValuePos = findNodeIndexByContent(this.content, "人物修为:", []);
ValuePos.pop();
ValuePos[ValuePos.length - 1]++;
datas = this.getContinuousData(ValuePos, 1, 2, 8);
datas = getContinuousNumber(this.content, ValuePos, 1, 2, 8);
this.scoreValue = datas[0];
this.scoreRank = datas[1];
this.scoreLocalRank = datas[2];
......@@ -191,7 +104,7 @@ export class User {
this.qhLevel = datas[6];
this.tlPoints = datas[7];
}
parseAttributeTable(_pos: number[]): any {
private parseAttributeTable(_pos: number[]): any {
const ret = {};
const pos = _.clone(_pos);
const tree = getDepthOfTree(this.content, pos);
......@@ -204,11 +117,11 @@ export class User {
}
return ret;
}
parseBasicAttributes() {
private parseBasicAttributes() {
let ValuePos = findNodeIndexByContent(this.content, "", []);
ValuePos.pop();
ValuePos[ValuePos.length - 1] += 2;
const datas = this.getContinuousData(ValuePos, 0, 4, 8);
const datas = getContinuousNumber(this.content, ValuePos, 0, 4, 8);
this.hp = datas[0];
this.mp = datas[1];
this.li = datas[2];
......@@ -229,7 +142,7 @@ export class User {
ValuePos[ValuePos.length - 1] += 2;
this.advancedAttributes = this.parseAttributeTable(ValuePos) as AdvancedAttribute;
}
parseYHZ() {
private parseYHZ() {
let ValuePos = findNodeIndexByAttribute(this.content, "id", "tableYHZ", []);
ValuePos.push(1);
const tree = getDepthOfTree(this.content, ValuePos);
......@@ -239,14 +152,15 @@ export class User {
this.yhz.push(node.content[0] as string);
}
}
parse() {
private parse() {
this.parseMetadata();
this.parseEquipmentData();
this.parseBasicAttributes();
this.parseYHZ();
}
constructor(id: string, content: string) {
constructor(id: string, content: string, region: string) {
this.id = id;
this.region = region;
this.content = HTML(content);
this.parse();
this.content = null;
......
import HTML from "posthtml-parser";
import _ from "underscore";
export function getDepthOfTree(tree: HTML.Tree, indexList: number[]): HTML.Tree {
if (indexList.length) {
const _indexList = _.clone(indexList);
const index = _indexList.splice(0, 1)[0];
const node = tree[index];
if (typeof (node) === "string" || !node.content) {
return [node];
}
return getDepthOfTree(node.content, _indexList);
} else {
return tree;
}
}
export function findNodeIndex(baseTree: HTML.Tree, condition: (node: HTML.Node) => boolean, offset: number[]): number[] {
const queue = [offset];
while (queue.length) {
const indexList = queue.splice(0, 1)[0];
const tree = getDepthOfTree(baseTree, indexList);
for (let i = 0; i < tree.length; ++i) {
const node = tree[i];
const newList = indexList.concat([i]);
if (condition(node)) {
return newList;
} else if (typeof (node) !== "string") {
queue.push(newList);
}
}
}
return null;
}
export function findAllNodeIndex(baseTree: HTML.Tree, condition: (node: HTML.Node) => boolean, offset: number[]): number[][] {
const queue = [offset];
const res: number[][] = [];
while (queue.length) {
const indexList = queue.splice(0, 1)[0];
const tree = getDepthOfTree(baseTree, indexList);
for (let i = 0; i < tree.length; ++i) {
const node = tree[i];
const newList = indexList.concat([i]);
if (condition(node)) {
//console.log(newList);
res.push(newList);
} else if (typeof (node) !== "string") {
queue.push(newList);
}
}
}
return res;
}
export function findNodeIndexByContent(baseTree: HTML.Tree, label: string, offset: number[]): number[] {
return findNodeIndex(baseTree, (node) => {
return node === label;
}, offset);
}
export function findNodeIndexByAttribute(baseTree: HTML.Tree, key: string, value: string, offset: number[]): number[] {
return findNodeIndex(baseTree, (node) => {
return typeof (node) !== "string" && node.attrs && node.attrs[key] === value;
}, offset);
}
export function findNodeIndexByTag(baseTree: HTML.Tree, tag: string, offset: number[]): number[] {
return findNodeIndex(baseTree, (node) => {
return typeof (node) !== "string" && node.tag === tag;
}, offset);
}
export function findAllNodeIndexByContent(baseTree: HTML.Tree, label: string, offset: number[]): number[][] {
return findAllNodeIndex(baseTree, (node) => {
return node === label;
}, offset);
}
export function findAllNodeIndexByAttribute(baseTree: HTML.Tree, key: string, value: string, offset: number[]): number[][] {
return findAllNodeIndex(baseTree, (node) => {
return typeof (node) !== "string" && node.attrs && node.attrs[key] === value;
}, offset);
}
export function findAllNodeIndexByTag(baseTree: HTML.Tree, tag: string, offset: number[]): number[][] {
return findAllNodeIndex(baseTree, (node) => {
return typeof (node) !== "string" && node.tag === tag;
}, offset);
}
const chineseCapitalNumbers = ["", "", "", "", "", "", "", "", "", ""]
export function getString(node: HTML.Node) {
let resultStr: string;
if (typeof (node) === "string") {
resultStr = node;
} else {
const subTree = node.content;
if (!subTree) {
return null;
}
const subNode = subTree[0];
if (typeof (subNode) === "string") {
resultStr = subTree[0] as string;
} else {
resultStr = getString(subTree[0]) as string;
}
}
resultStr = resultStr.trim();
return resultStr;
}
export function getNumber(node: HTML.Node) {
const numberStr = getString(node);
let stringMatch: RegExpMatchArray;
if (numberStr === "没有上榜") {
return null;
} else if (stringMatch = numberStr.match(/^([天地])魂$/)) {
return stringMatch[1] === "" ? 2 : 1;
} else if (stringMatch = numberStr.match(/^(.+)(.+)境界$/)) {
return (_.findIndex(chineseCapitalNumbers, (m) => m === stringMatch[1]) << 8) | _.findIndex(chineseCapitalNumbers, (m) => m === stringMatch[2]);
} else if (stringMatch = numberStr.match(/^(\d+)-(\d+)$/)) {
const minValue = parseInt(stringMatch[1]);
const maxValue = parseInt(stringMatch[2]);
return (minValue << 16) | maxValue;
} else {
return parseInt(numberStr);
}
}
export function getContinuousNodes(tree: HTML.Tree, _pos: number[], moveOffset: number, step: number, dataCount: number): HTML.Node[] {
const pos = _.clone(_pos);
const datas: HTML.Node[] = [];
for (let i = 0; i < dataCount; ++i) {
const node = getDepthOfTree(tree, pos)[0];
datas.push(node);
pos[pos.length - (moveOffset + 1)] += step;
}
return datas;
}
export function getContinuousData(tree: HTML.Tree, _pos: number[], moveOffset: number, step: number, dataCount: number): string[] {
return getContinuousNodes(tree, _pos, moveOffset, step, dataCount).map(getString);
}
export function getContinuousNumber(tree: HTML.Tree, _pos: number[], moveOffset: number, step: number, dataCount: number): number[] {
return getContinuousNodes(tree, _pos, moveOffset, step, dataCount).map(getNumber);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment