Advertisement
Guest User

Untitled

a guest
Aug 22nd, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.67 KB | None | 0 0
  1. const fs = require('fs');
  2. const path = require('path');
  3. const jsdom = require('jsdom');
  4. const { JSDOM } = jsdom;
  5.  
  6. const dataDir = path.join('ktst');
  7. const ws = fs.createWriteStream('ktst-passive.tsv', 'utf-8');
  8. let pk = 0;
  9.  
  10. ws.on('error', function (err) {
  11. console.error(err);
  12. process.exit(1);
  13. });
  14.  
  15. ws.write([
  16. 'pk',
  17. 'logID',
  18. 'turn',
  19. 'action',
  20. 'parent',
  21. 'target',
  22. 'effect',
  23. 'type',
  24. 'direction',
  25. 'cycle',
  26. 'actual',
  27. 'cycle * actual',
  28. 'passive'].join('\t') + '\n');
  29.  
  30. const list = fs.readdirSync(dataDir);
  31. console.log(list.length + ' files');
  32.  
  33. for (let i = 0; i < list.length; i++) {
  34. readLog(path.join(dataDir, list[i]));
  35. }
  36.  
  37. function readLog(fullpath) {
  38. fs.stat(fullpath, (err, stats) => {
  39. if (err) {
  40. return;
  41. }
  42.  
  43. let m = fullpath.match(/([0-9]+)\.html$/);
  44.  
  45. if (!stats.isFile() || !m) {
  46. return;
  47. }
  48.  
  49. if (m[1] != 12648) {
  50. //return;
  51. }
  52.  
  53. _readLog(fullpath, m[1])
  54. .then(result => console.log(result.fullpath));
  55. });
  56. }
  57.  
  58. function _readLog(fullpath, battleId) {
  59. return new Promise((resolve, reject) => {
  60. fs.readFile(fullpath, 'utf8', function(err, data) {
  61. if (err) {
  62. reject(err);
  63. return;
  64. }
  65.  
  66. const result = parse(data, battleId);
  67. result.fullpath = fullpath;
  68. resolve(result);
  69. });
  70. });
  71. }
  72.  
  73. function parseFormation(mae, naka, usiro) {
  74. const line = [mae, naka, usiro];
  75.  
  76. return {
  77. line: line,
  78. zenTarget: line.reduce((pre, cur) => pre + cur),
  79. retuTarget: line.sort((pre, cur) => cur - pre)[0],
  80. kanTarget: line.filter(cur => cur).length,
  81. }
  82. }
  83.  
  84. function parse(data, battleId) {
  85. const result = {};
  86. const formation = {};
  87. const document = new JSDOM(data).window.document;
  88. const contents = document.querySelector('body > .AL > div[style]');
  89.  
  90. if (!contents) {
  91. return result;
  92. }
  93.  
  94. let cursor = contents.firstElementChild;
  95. let m;
  96.  
  97. const state = {
  98. battleId: battleId,
  99. turn: 0,
  100. formation: {
  101. }
  102. };
  103.  
  104. while (cursor) {
  105. if (cursor.tagName == 'TABLE' && cursor.className == 'FRB1') {
  106. const title = cursor.querySelector('.B7i');
  107.  
  108. if (title && (m = title.textContent.match(/(\d+)/))) {
  109. state.turn = ~~ m[1];
  110. }
  111.  
  112. const left = cursor.querySelector('td[width = "490"] > .SE > table > tbody');
  113. const right = cursor.querySelector('td[width = "490"] > .SE2 > table > tbody');
  114.  
  115. if (left && right) {
  116. state.formation.left = parseFormation(
  117. left.querySelectorAll('td[width = "100"][align = "right"]').length,
  118. left.querySelectorAll('td[width = "100"][align = "center"]').length,
  119. left.querySelectorAll('td[width = "100"]:not([align])').length
  120. );
  121.  
  122. state.formation.right = parseFormation(
  123. right.querySelectorAll('td[width = "100"]:not([align])').length,
  124. right.querySelectorAll('td[width = "100"][align = "center"]').length,
  125. right.querySelectorAll('td[width = "100"][align = "right"]').length
  126. );
  127. }
  128.  
  129. cursor
  130. .querySelectorAll('.FRB2 > div[align = LEFT]')
  131. .forEach(e => parseBA2(state, e, 'root', '', ''));
  132. }
  133. else if (cursor.tagName == 'DIV') {
  134. cursor
  135. .querySelectorAll('.FRS2 > .BA2')
  136. .forEach(e => parseBA2(state, e, 'root', '', ''));
  137. }
  138.  
  139. cursor = cursor.nextElementSibling;
  140. }
  141.  
  142. return result;
  143. }
  144.  
  145. function parseBA2(state, cursor, parent, currentTarget, currentEffect) {
  146. let m;
  147. const regPassiveName = /の([^!]+)/,
  148. regActiveName = /^([^!]+)/,
  149. regSkillEffect = /^(.+?):([^!]+?)!$/;
  150.  
  151. if (!cursor) {
  152. return;
  153. }
  154.  
  155. cursor = cursor.firstElementChild;
  156.  
  157. while (cursor) {
  158. if (cursor.nodeType == 1) {
  159. /*
  160. () は走査のルート要素
  161.  
  162. 行動前
  163. (.FRS2 > b.BA2) > b.BA2
  164.  
  165. アクティブ
  166. (.FRS2 > b.BA2) > dl. > dl.BA2
  167. パッシブ
  168. > dl.BA2
  169.  
  170. 通常攻撃
  171. (.FRS2 > b.BA2) > dl. > dl.BA2
  172. パッシブ
  173. 通常攻撃の兄弟要素 dl.BA2
  174.  
  175. ターン開始
  176. (.FRB2 > div[align = LEFT]) > b.BA2
  177. */
  178.  
  179. if (cursor.textContent == '通常攻撃!' && cursor.className == 'HK2') {
  180. parent = '通常攻撃';
  181. currentTarget = '敵';
  182. currentEffect = '攻撃';
  183. }
  184. else if (cursor.className == 'F7') {
  185. m = cursor.textContent.match(regActiveName);
  186. parent = m[1];
  187. }
  188. else if (cursor.tagName == 'B' && cursor.className == 'HK2') {
  189. m = cursor.textContent.match(regPassiveName);
  190.  
  191. if (m[1] == "' Θ '") {
  192. logger(state, 'action', parent, currentTarget, currentEffect, m[1]);
  193. }
  194.  
  195. parent = m[1];
  196. }
  197. else if (cursor.className == 'P2') {
  198. m = cursor.textContent.match(regSkillEffect);
  199. currentTarget = m[1];
  200. currentEffect = m[2];
  201. }
  202. else if (cursor.className == 'BA2') {
  203. parseBA2(state, cursor, parent, currentTarget, currentEffect);
  204. }
  205. else if (cursor.tagName == 'DL') {
  206. parseBA2(state, cursor, parent, currentTarget, currentEffect);
  207. }
  208. }
  209. else if (cursor.nodeType == 3) {
  210. if (cursor.textContent.match(/のダメージ!$/)) {
  211. logger(state, 'hit', parent, currentTarget, currentEffect, '');
  212. }
  213. }
  214.  
  215. cursor = cursor.nextSibling;
  216. }
  217. }
  218.  
  219. function logger(state, action, parent, target, effect, skill) {
  220. if (!state.formation) {
  221. return;
  222. }
  223.  
  224. pk++;
  225.  
  226. const foe = state.formation.left;
  227. const ally = state.formation.right;
  228.  
  229. let actual = 1;
  230. let type = '単';
  231. let cycle = 1;
  232. let direction = '';
  233. let m;
  234.  
  235. if (m = target.match(/(\d+)/)) {
  236. cycle = ~~ m[1];
  237. }
  238.  
  239. if (m = target.match(/敵/)) {
  240. direction = '敵';
  241. }
  242. else if (m = target.match(/味/)) {
  243. direction = '味';
  244. }
  245. else if (m = target.match(/他/)) {
  246. direction = '他';
  247. }
  248.  
  249. if (target.match(/貫/)) {
  250. actual = (direction == '敵') ? foe.kanTarget : ally.kanTarget;
  251. type = '貫';
  252. }
  253. if (target.match(/列/)) {
  254. actual = (direction == '敵') ? foe.retuTarget : ally.retuTarget;
  255. type = '列';
  256. }
  257. else if (m = effect.match(/(\d+)連鎖/)) {
  258. actual = ~~ m[1];
  259. type = '連鎖';
  260. }
  261. else if (m = effect.match(/(\d+)連撃/)) {
  262. actual = ~~ m[1];
  263. type = '連撃';
  264. }
  265. else if (m = target.match(/全/)) {
  266. type = '全';
  267.  
  268. if (direction == '敵') {
  269. actual = foe.zenTarget;
  270. }
  271. else if (direction == '味') {
  272. actual = ally.zenTarget;
  273. }
  274. else if (direction == '他') {
  275. actual = -1 + foe.zenTarget + ally.zenTarget;
  276. }
  277. }
  278.  
  279. ws.write([
  280. pk,
  281. state.battleId,
  282. state.turn,
  283. action,
  284. "'" + parent,
  285. target,
  286. effect,
  287. type,
  288. direction,
  289. cycle,
  290. actual,
  291. cycle * actual,
  292. "'" + skill].join('\t') + '\n');
  293. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement