swdb.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. //const fs = require('fs-extra');
  2. //const csv = require('fast-csv');
  3. const dateFormat = require('dateformat');
  4. //const path = require('path');
  5. //const sanitize = require('sanitize-filename');
  6. module.exports = {
  7. defaultConfig: {
  8. enabled: true,
  9. debug: true
  10. },
  11. pluginName: 'SWDB',
  12. pluginDescription: 'Saves runs to SWDB.',
  13. target_host: 'http://localhost',
  14. target_port: '80',
  15. target_url: '/API/v1/log-run',
  16. temp: {},
  17. proxy: null,
  18. config: null,
  19. /**
  20. * Initializes he plugin.
  21. *
  22. * @param proxy The proxy.
  23. * @param Global configurations.
  24. */
  25. init(proxy, config) {
  26. this.proxy = proxy;
  27. this.config = config;
  28. proxy.on('apiCommand', (req, resp) => {
  29. try {
  30. wizardID = '';
  31. command = '';
  32. if (config.Config.Plugins[this.pluginName].enabled) {
  33. //const { command, wizard_id: wizardID } = req;
  34. command = req["command"];
  35. wizardID = req["wizard_id"];
  36. }
  37. if (!this.temp[wizardID]) {
  38. this.temp[wizardID] = {};
  39. }
  40. if (command === 'BattleScenarioStart') {
  41. proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV RUN START: ${resp}` })
  42. //for (var key in req) {
  43. // proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV REQ: ${key}: ${req[key]}` })
  44. //}
  45. this.temp[wizardID].area = req.region_id;
  46. this.temp[wizardID].stage = req.stage_no;
  47. this.temp[wizardID].difficulty = req.difficulty;
  48. }
  49. if (command === 'BattleScenarioResult' || command === 'BattleDungeonResult' || command === 'BattleDimensionHoleDungeonResult') {
  50. //proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV RUN RESULT: ${resp}` })
  51. //for (var key in req) {
  52. // this.log("info", `IVV REQ: ${key}: ${req[key]}`);
  53. //}
  54. //for (var key in resp) {
  55. // this.log("info", `IVV RES: ${key}: ${resp[key]}`);
  56. //}
  57. this.parse_normal(req, resp);
  58. }
  59. if (command === 'BattleRiftOfWorldsRaidResult') {
  60. this.parse_raid_rift(req, resp);
  61. }
  62. if (command === 'BattleRiftDungeonResult') {
  63. this.parse_elemental_rift(req, resp);
  64. }
  65. }
  66. catch (e) {
  67. proxy.log({ type: 'error', source: 'plugin', name: this.pluginName, message: `An unexpected error occured: ${e.message}` });
  68. }
  69. });
  70. },
  71. /**
  72. * Parses a reward item (no runes!).
  73. *
  74. * @param crate The crate object.
  75. * @return array of {item, unit, pieces, quantity, shapeshifting}
  76. */
  77. getItem(crate) {
  78. item = 0;
  79. unit = 0;
  80. pieces = 0;
  81. quantity = 0;
  82. shapeshifting = 0;
  83. if (crate.random_scroll && (crate.random_scroll.item_master_id === 1 || crate.random_scroll.item_master_id === 8 || crate.random_scroll.item_master_id === 2)){
  84. // 1: Unknown scroll
  85. // 2: Mystical Scroll
  86. // 8: Summoning Stones
  87. item = crate.random_scroll.item_master_id;
  88. quantity = crate.random_scroll.item_quantity;
  89. }
  90. if (crate.costume_point) {
  91. shapeshifting = crate.costume_point;
  92. }
  93. if (crate.rune_upgrade_stone) {
  94. item = 'Power Stone'; // TODO: Do they exist?
  95. quantity = crate.rune_upgrade_stone.item_quantity;
  96. }
  97. if (crate.unit_info) {
  98. unit = crate.unit_info.unit_master_id;
  99. }
  100. if (crate.material) {
  101. item = crate.material.item_master_id;
  102. quantity = crate.material.item_quantity;
  103. }
  104. if (crate.summon_pieces) {
  105. pieces = crate.summon_pieces.item_master_id;
  106. quantity = crate.summon_pieces.item_quantity;
  107. }
  108. if (crate.craft_stuff) {
  109. item = crate.craft_stuff.item_master_id;
  110. quantity = crate.craft_stuff.item_quantity;
  111. }
  112. //this.log('DEBUG', `Item: ${item}, ${unit}, ${pieces}, ${quantity}, ${shapeshifting}`);
  113. drop = {item, unit, pieces, quantity, shapeshifting}
  114. return drop;
  115. },
  116. /**
  117. * TODO! Unaddapted.
  118. * Parses a rift reward item (no runes!).
  119. *
  120. * @param crate The crate object.
  121. * @return array of {item, unit, pieces, quantity}
  122. */
  123. getItemRift(item, entry) {
  124. if (item.type === 8) {
  125. const rune = item.info;
  126. entry.drop = 'Rune';
  127. entry.grade = `${rune.class}*`;
  128. entry.sell_value = rune.sell_value;
  129. entry.set = gMapping.rune.sets[rune.set_id];
  130. entry.slot = rune.slot_no;
  131. entry.efficiency = gMapping.getRuneEfficiency(rune).current;
  132. entry.rarity = gMapping.rune.class[rune.sec_eff.length];
  133. entry.main_stat = gMapping.getRuneEffect(rune.pri_eff);
  134. entry.prefix_stat = gMapping.getRuneEffect(rune.prefix_eff);
  135. rune.sec_eff.forEach((substat, i) => {
  136. entry[`sub${i + 1}`] = gMapping.getRuneEffect(substat);
  137. });
  138. }
  139. if (item.info.craft_type_id) {
  140. enhancement = this.getEnchantVals(item.info.craft_type_id, item.info.craft_type);
  141. entry.drop = enhancement.drop;
  142. entry.sell_value = item.sell_value;
  143. entry.set = enhancement.set;
  144. entry.main_stat = enhancement.type;
  145. entry.sub1 = enhancement.min;
  146. entry.sub2 = enhancement.max;
  147. }
  148. return entry;
  149. },
  150. /**
  151. * TODO! Will I need this.
  152. * Saves run data to a file in CSV format.
  153. *
  154. */
  155. saveToFile(entry, filename, headers, proxy) {
  156. const csvData = [];
  157. const self = this;
  158. fs.ensureFile(path.join(config.Config.App.filesPath, filename), err => {
  159. if (err) {
  160. return;
  161. }
  162. csv
  163. .fromPath(path.join(config.Config.App.filesPath, filename), { ignoreEmpty: true, headers, renameHeaders: true })
  164. .on('data', data => {
  165. csvData.push(data);
  166. })
  167. .on('end', () => {
  168. csvData.push(entry);
  169. csv.writeToPath(path.join(config.Config.App.filesPath, filename), csvData, { headers }).on('finish', () => {
  170. proxy.log({ type: 'success', source: 'plugin', name: self.pluginName, message: `Saved run data to ${filename}` });
  171. });
  172. });
  173. });
  174. },
  175. /**
  176. * Parses a battle data.
  177. * Valid for scenario, dungeons and Dimensional Hole.
  178. *
  179. * @param req The request
  180. * @param resp The response.
  181. */
  182. parse_normal(req, resp) {
  183. const { command } = req;
  184. const { wizard_id: wizardID, wizard_name: wizardName } = resp.wizard_info;
  185. const run = {};
  186. const run_party = {};
  187. const run_k_party = {};
  188. log = true;
  189. if (command === 'BattleDungeonResult') {
  190. if (req.dungeon_id > 10000){
  191. // Hall of Heroes or unknown
  192. log = false;
  193. }
  194. run.area = req.dungeon_id;
  195. run.stage = req.stage_id;
  196. run.difficulty = 0
  197. }
  198. if (command === 'BattleScenarioResult') {
  199. for (var key in this.temp[wizardID]) {
  200. this.log("DEBUG", `IVV TEMP: ${key}: ${this.temp[wizardID][key]}`);
  201. }
  202. run.area = this.temp[wizardID].area;
  203. run.stage = this.temp[wizardID].stage;
  204. run.difficulty = this.temp[wizardID].difficulty;
  205. }
  206. if (command === 'BattleDimensionHoleDungeonResult') {
  207. //if (gMapping.dungeon[resp.dungeon_id]) {
  208. // run.dungeon = `${gMapping.dungeon[resp.dungeon_id]} Level ${resp.difficulty}`;
  209. //}
  210. run.area = req.dungeon_id;
  211. run.stage = req.stage_id;
  212. run.difficulty = 0
  213. }
  214. run.uid = wizardID;
  215. run.win = resp.win_lose; // 1/0 2 is lost in scenario
  216. run.dtime = dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss');
  217. const reward = resp.reward ? resp.reward : {};
  218. run.time = req.clear_time ? req.clear_time : 0;
  219. run.mana = reward.mana ? reward.mana : 0;
  220. run.energy = reward.energy ? reward.energy : 0;
  221. run.crystal = reward.crystal ? reward.crystal : 0;
  222. // TODO: GET
  223. run.helper = 0;
  224. run.rune = {};
  225. run.unit = 0;
  226. run.unit_pieces = {};
  227. run.sd = 0;
  228. run.item = {};
  229. run.shapeshifting = 0;
  230. if (reward.crate) {
  231. run.mana = reward.crate.mana ? run.mana + reward.crate.mana : run.mana;
  232. run.energy = reward.crate.energy ? run.energy + reward.crate.energy : run.energy;
  233. run.crystal = reward.crate.crystal ? run.crystal + reward.crate.crystal : run.crystal;
  234. if (reward.crate.rune) {
  235. const rune = reward.crate.rune;
  236. //for (var key in rune) {
  237. // this.proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV RUNE: ${key}: ${rune[key]}` })
  238. //}
  239. run.rune.id = rune.rune_id;
  240. run.rune.grade = rune.class;
  241. run.rune.value = rune.sell_value;
  242. run.rune.set = rune.set_id;
  243. run.rune.slot = rune.slot_no;
  244. run.rune.efficiency = gMapping.getRuneEfficiency(rune).current;
  245. run.rune.quality = rune.rank;
  246. run.rune.main = rune.pri_eff[0];
  247. run.rune.main_value = rune.pri_eff[1];
  248. if (rune.prefix_eff){
  249. run.rune.innate = rune.prefix_eff[0];
  250. run.rune.innate_value = rune.prefix_eff[1];
  251. }
  252. rune.sec_eff.forEach((substat, i) => {
  253. run.rune[`substat_${i + 1}`] = substat[0];
  254. run.rune[`substat_${i + 1}_value`] = substat[1];
  255. });
  256. }
  257. else {
  258. drop = this.getItem(reward.crate);
  259. if (drop.unit){
  260. run.unit.id = drop.unit;
  261. }
  262. if (drop.pieces){
  263. run.unit_pieces.id = drop.pieces;
  264. run.unit_pieces.quantity = drop.quantity;
  265. }
  266. if (drop.item){
  267. run.item.id = drop.item;
  268. run.item.quantity = drop.quantity;
  269. }
  270. run.shapeshifting = drop.shapeshifting;
  271. }
  272. }
  273. if (resp.instance_info) {
  274. run.sd = resp.instance_info;
  275. }
  276. if (resp.unit_list && resp.unit_list.length > 0) {
  277. resp.unit_list.forEach((unit, i) => {
  278. run_party[i] = unit.unit_master_id;
  279. run_k_party[i] = unit.unit_id;
  280. });
  281. }
  282. json_rune = '[';
  283. if (run.rune.length > 0){
  284. json_rune += `"id": "${run.rune.id}", `;
  285. json_rune += `"grade": "${run.rune.grade}", `;
  286. json_rune += `"set": "${run.rune.set}", `;
  287. json_rune += `"slot": "${run.rune.slot}", `;
  288. json_rune += `"efficiency": "${run.rune.efficiency}", `;
  289. json_rune += `"quality": "${run.rune.quality}", `;
  290. json_rune += `"value": "${run.rune.value}", `;
  291. json_rune += `"main_stat": "${run.rune.main}", `;
  292. json_rune += `"main_stat_value": "${run.rune.main_value}", `;
  293. json_rune += `"innate_stat": "${run.rune.innate}", `;
  294. json_rune += `"innate_stat_value": "${run.rune.innate_value}", `;
  295. json_rune += `"substat_1": "${run.rune.substat_1}", `;
  296. json_rune += `"substat_1_value": "${run.rune.substat_1_value}", `;
  297. json_rune += `"substat_2": "${run.rune.substat_2}", `;
  298. json_rune += `"substat_2_value": "${run.rune.substat_2_value}", `;
  299. json_rune += `"substat_3": "${run.rune.substat_3}", `;
  300. json_rune += `"substat_4_value": "${run.rune.substat_3_value}", `;
  301. json_rune += `"substat_4": "${run.rune.substat_4}", `;
  302. json_rune += `"substat_4_value": "${run.rune.substat_4_value}"`;
  303. }
  304. json_rune = json_rune + "]";
  305. json_item = '[';
  306. if (run.item.length > 0){
  307. json_item += `"id": "${run.item.id}", `;
  308. json_item += `"quantity": "${run.item.quantity}"`;
  309. }
  310. json_item = json_item + "]";
  311. json_unit_pieces = '[';
  312. if (run.unit_pieces.length > 0){
  313. json_unit_pieces += `"id": "${run.unit_pieces.id}", `;
  314. json_unit_pieces += `"quantity": "${run.unit_pieces.quantity}" `;
  315. }
  316. json_unit_pieces = json_unit_pieces + "]";
  317. json_party = '[';
  318. resp.unit_list.forEach((unit, i) => {
  319. json_party = json_party + '{"unit_id": ' + run_party[i] + ', "unit_master_id": ' + run_k_party[i] + '},';
  320. });
  321. json_party = json_party.slice(0, -1) + "]";
  322. //this.log('DEBUG', `IVV json_party: ${json_party}`)
  323. json = `{`;
  324. json += `"uid": "${run.uid}", `;
  325. json += `"dtime": "${run.dtime}", `;
  326. json += `"area": "${run.area}", `;
  327. json += `"stage": "${run.stage}", `;
  328. json += `"difficulty": "${run.difficulty}", `;
  329. json += `"win": "${run.win}", `;
  330. json += `"time": "${run.time}", `;
  331. json += `"mana": "${run.mana}", `;
  332. json += `"energy": "${run.energy}", `;
  333. json += `"crystal": "${run.crystal}", `;
  334. json += `"rune": ${json_rune}, `;
  335. json += `"sd": ${run.sd}, `;
  336. json += `"item": ${json_item}, `;
  337. json += `"unit": ${run.unit}, `;
  338. json += `"unit_pieces": ${json_unit_pieces}, `;
  339. json += `"shapeshifting": ${run.shapeshifting}, `;
  340. json += `"party": ${json_party}`, ;
  341. json += `"helper": "${run.helper}", `;
  342. json += `}`;
  343. this.log('DEBUG', `json: ${json}`)
  344. //const filename = sanitize(`${wizardName}-${wizardID}-runs.csv`);
  345. //const filename = sanitize(`IVV-${wizardName}-${wizardID}-runs.csv`);
  346. //this.saveToFile(entry, filename, headers, proxy);
  347. // Make the request
  348. //var inspect = require('eyespect').inspector();
  349. var request = require('request')
  350. var postData = {
  351. name: 'data',
  352. value: json
  353. }
  354. // npm install -S request eyespect
  355. /*var url = this.target_host + ':' + this.target_port + '/' + this.target_url;
  356. var options = {
  357. method: 'post',
  358. body: postData,
  359. json: false, //json: true,
  360. url: url
  361. }
  362. request(options, function (err, res, body) {
  363. if (err) {
  364. this.log('ERROR', `REQUEST ERROR ${err}, `)
  365. //return
  366. }
  367. //var headers = res.headers
  368. //var statusCode = res.statusCode
  369. //inspect(headers, 'headers')
  370. //inspect(statusCode, 'statusCode')
  371. //inspect(body, 'body')
  372. })*/
  373. /*const req_options = setRequestAuth(
  374. {
  375. json: true,
  376. body: { data: { request: req, response: resp, __version: acceptedCommands.__version } }
  377. },
  378. wizard_id
  379. );*/
  380. // Send it
  381. /*var url = this.target_host + ':' + this.target_port + '/' + this.target_url;
  382. request.post(url, postData, (error, response, body) => {
  383. if (error) {
  384. this.log('error',`Error: ${error.message}`);
  385. //return;
  386. }
  387. // Log message to proxy window
  388. if (response.statusCode === 200) {
  389. this.log('success',`${command} logged successfully`);
  390. }
  391. else {
  392. if (response.statusCode == 401) {
  393. this.log('error',`SWARFARM Authentication failure: ${body.detail}`);
  394. } else {
  395. this.log('error',`Error ${response.statusCode}: ${body.detail}`);
  396. }
  397. }
  398. });*/
  399. var querystring = require('querystring');
  400. var http = require('http');
  401. var fs = require('fs');
  402. var post_data = querystring.stringify({
  403. 'data' : json
  404. });
  405. // An object of options to indicate where to post to
  406. var post_options = {
  407. host: '192.168.1.101',//this.target_host,
  408. port: this.target_port,
  409. path: this.target_url,
  410. method: 'POST',
  411. headers: {
  412. 'Content-Type': 'application/x-www-form-urlencoded',
  413. 'Content-Length': Buffer.byteLength(post_data)
  414. }
  415. };
  416. // Set up the request
  417. var post_req = http.request(post_options, function(res) {
  418. res.setEncoding('utf8');
  419. res.on('data', function (chunk) {
  420. this.log("DEBUG", 'Response: ' + chunk);
  421. });
  422. });
  423. // post the data
  424. post_req.write(post_data);
  425. post_req.end();
  426. },
  427. /**
  428. * TODO Unaddapted.
  429. * Parses a battle data.
  430. * Valid for Rift Raids.
  431. *
  432. * @param req The request
  433. * @param resp The response.
  434. */
  435. parse_raid_rift(req, resp) {
  436. const { wizard_id: wizardID, wizard_name: wizardName } = resp.wizard_info;
  437. let run = {};
  438. if (gMapping.dungeon[req.dungeon_id]) {
  439. run.dungeon = `${gMapping.elemental_rift_dungeon[req.dungeon_id]}`;
  440. isElemental = true;
  441. }
  442. //const winLost = resp.win_lose === 1 ? 'Win' : 'Did not kill';
  443. run.dtime = dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss');
  444. //run.result = winLost;
  445. run.win = resp.win_lose;
  446. run.rune = {};
  447. run.unit = 0;
  448. run.unit_pieces = {};
  449. run.sd = 0;
  450. run.item = {};
  451. run.shapeshifting = 0;
  452. run.time = req.clear_time ? req.clear_time : 0;
  453. const reward = resp.reward ? resp.reward : {};
  454. if (resp.win_lose === 1) {
  455. // No crate: Mana of shapeshifting stones
  456. if (!reward.crate) {
  457. const reward = resp.battle_reward_list.find(value => value.wizard_id === resp.wizard_info.wizard_id).reward_list[0];
  458. if (reward.item_master_id === 6) {
  459. run.shapeshifting = reward.item_quantity;
  460. }
  461. else {
  462. run.mana = reward.item_quantity;
  463. }
  464. }
  465. // Rune craft item
  466. else if (reward.crate.changestones) {
  467. const item = {
  468. info: {
  469. craft_type: reward.crate.changestones[0].craft_type,
  470. craft_type_id: reward.crate.changestones[0].craft_type_id
  471. },
  472. sell_value: reward.crate.changestones[0].sell_value
  473. };
  474. run.drop= this.getItemRift(item, run);
  475. }
  476. // Rune
  477. else if (reward.crate.rune) {
  478. const rune = reward.crate.rune;
  479. //for (var key in rune) {
  480. // this.proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV RUNE: ${key}: ${rune[key]}` })
  481. //}
  482. run.rune.id = rune.rune_id;
  483. run.rune.grade = rune.class;
  484. run.rune.value = rune.sell_value;
  485. run.rune.set = rune.set_id;
  486. run.rune.slot = rune.slot_no;
  487. run.rune.efficiency = gMapping.getRuneEfficiency(rune).current;
  488. run.rune.quality = rune.rank;
  489. run.rune.main = rune.pri_eff[0];
  490. run.rune.main_value = rune.pri_eff[1];
  491. if (rune.prefix_eff){
  492. run.rune.innate = rune.prefix_eff[0];
  493. run.rune.innate_value = rune.prefix_eff[1];
  494. }
  495. rune.sec_eff.forEach((substat, i) => {
  496. run.rune[`substat_${i + 1}`] = substat[0];
  497. run.rune[`substat_${i + 1}_value`] = substat[1];
  498. });
  499. }
  500. // Unit (Rainbowmon)
  501. else if (reward.crate.unit_info && reward.crate.unit_info.unit_master_id > 0) {
  502. run.unit.id = reward.crate.unit_info.unit_master_id;
  503. }
  504. // Item
  505. else if (!run.drop && resp.reward.crate) {
  506. //run.drop = this.getItem(reward.resp.reward.crate);
  507. if (resp.reward.crate.random_scroll && (resp.reward.crate.random_scroll.item_master_id === 1 || resp.reward.crate.random_scroll.item_master_id === 8 || resp.reward.crate.random_scroll.item_master_id === 2)){
  508. // 1: Unknown scroll
  509. // 2: Mystical Scroll
  510. // 8: Summoning Stones
  511. run.item.id = resp.reward.crate.random_scroll.item_master_id;
  512. run.item.quantity = resp.reward.crate.random_scroll.item_quantity;
  513. }
  514. //if (resp.reward.crate.costume_point) {
  515. // shapeshifting = resp.reward.crate.costume_point;
  516. //}
  517. //if (resp.reward.crate.rune_upgrade_stone) {
  518. // item = 'Power Stone'; // TODO: Do they exist?
  519. // quantity = resp.reward.crate.rune_upgrade_stone.item_quantity;
  520. //}
  521. //if (resp.reward.crate.unit_info) {
  522. // unit = resp.reward.crate.unit_info.unit_master_id;
  523. //}
  524. if (resp.reward.crate.material) {
  525. item = resp.reward.crate.material.item_master_id;
  526. quantity = resp.reward.crate.material.item_quantity;
  527. }
  528. //if (resp.reward.crate.summon_pieces) {
  529. // pieces = resp.reward.crate.summon_pieces.item_master_id;
  530. // quantity = resp.reward.crate.summon_pieces.item_quantity;
  531. //}
  532. if (resp.reward.crate.craft_stuff) {
  533. item = resp.reward.crate.craft_stuff.item_master_id;
  534. quantity = resp.reward.crate.craft_stuff.item_quantity;
  535. }
  536. }
  537. else {
  538. run.drop = 'unknown';
  539. }
  540. }
  541. if (resp.unit_list && resp.unit_list.length > 0) {
  542. resp.unit_list.forEach((unit, i) => {
  543. run_party[i] = unit.unit_master_id;
  544. run_k_party[i] = unit.unit_id;
  545. });
  546. }
  547. //const filename = sanitize(`${wizardName}-${wizardID}-raid-runs.csv`);
  548. //this.saveToFile(run. filename, headers, proxy);
  549. },
  550. /**
  551. * TODO Unaddapted.
  552. * Parses a battle data.
  553. * Valid for Rift Dungeons.
  554. *
  555. * @param req The request
  556. * @param resp The response.
  557. */
  558. parse_elemental_rift(req, resp) {
  559. const { wizard_id: wizardID, wizard_name: wizardName } = resp.wizard_info;
  560. let entry = {};
  561. if (gMapping.dungeon[req.dungeon_id]) {
  562. entry.dungeon = `${gMapping.elemental_rift_dungeon[req.dungeon_id]}`;
  563. isElemental = true;
  564. }
  565. const winLost = req.battle_result === 1 ? 'Win' : 'Did not kill';
  566. entry.date = dateFormat(new Date(), 'yyyy-mm-dd HH:MM');
  567. entry.result = winLost;
  568. if (resp.item_list && resp.item_list.length > 0) {
  569. resp.item_list.forEach((item, i) => {
  570. if (item.is_boxing !== 1 || item.id === 2001) {
  571. entry[`item${i + 1}`] = `${gMapping.craftMaterial[item.id]} x${item.quantity}`;
  572. } else {
  573. if (item.id === 2) {
  574. entry.drop = 'Mystical Scroll';
  575. }
  576. if (item.id === 8) {
  577. entry.drop = `Summoning Stones x${item.item_quantity}`;
  578. }
  579. if (item.info && item.info.unit_master_id > 0) {
  580. entry.drop = `${gMapping.getMonsterName(item.info.unit_master_id)} ${item.class}`;
  581. }
  582. if ((item.info && item.info.craft_type_id) || item.type === 8) {
  583. entry = this.getItemRift(item, entry);
  584. }
  585. }
  586. });
  587. }
  588. if (resp.unit_list && resp.unit_list.length > 0) {
  589. resp.unit_list.forEach((unit, i) => {
  590. entry[`team${i + 1}`] = gMapping.getMonsterName(unit.unit_master_id);
  591. });
  592. }
  593. json_rune = '[';
  594. if (run.rune.length() > 0){
  595. json_rune += `"id": "${run.rune.id}", `;
  596. json_rune += `"grade": "${run.rune.grade}", `;
  597. json_rune += `"set": "${run.rune.set}", `;
  598. json_rune += `"slot": "${run.rune.slot}", `;
  599. json_rune += `"efficiency": "${run.rune.efficiency}", `;
  600. json_rune += `"quality": "${run.rune.quality}", `;
  601. json_rune += `"value": "${run.rune.value}", `;
  602. json_rune += `"main_stat": "${run.rune.main}", `;
  603. json_rune += `"main_stat_value": "${run.rune.main_value}", `;
  604. json_rune += `"innate_stat": "${run.rune.innate}", `;
  605. json_rune += `"innate_stat_value": "${run.rune.innate_value}", `;
  606. json_rune += `"substat_1": "${run.rune.substat_1}", `;
  607. json_rune += `"substat_1_value": "${run.rune.substat_1_value}", `;
  608. json_rune += `"substat_2": "${run.rune.substat_2}", `;
  609. json_rune += `"substat_2_value": "${run.rune.substat_2_value}", `;
  610. json_rune += `"substat_3": "${run.rune.substat_3}", `;
  611. json_rune += `"substat_4_value": "${run.rune.substat_3_value}", `;
  612. json_rune += `"substat_4": "${run.rune.substat_4}", `;
  613. json_rune += `"substat_4_value": "${run.rune.substat_4_value}", `;
  614. }
  615. json_rune = json_party.slice(0, -1) + "]";
  616. json_item = '[';
  617. if (run.item.length() > 0){
  618. json_item += `"id": "${run.item.id}", `;
  619. json_item += `"quantity": "${run.item.quantity}", `;
  620. }
  621. json_item = json_party.slice(0, -1) + "]";
  622. json_unit_pieces = '[';
  623. if (run.unit_pieces.length() > 0){
  624. json_unit_pieces += `"id": "${run.unit_pieces.id}", `;
  625. json_unit_pieces += `"quantity": "${run.unit_pieces.quantity}", `;
  626. }
  627. json_unit_pieces = json_party.slice(0, -1) + "]";
  628. json_party = '[';
  629. resp.unit_list.forEach((unit, i) => {
  630. json_party = json_party + '{"unit_id": ' + run_party[i] + ', "unit_master_id": ' + run_k_party[i] + '},';
  631. });
  632. json_party = json_party.slice(0, -1) + "]";
  633. //this.log('DEBUG', `IVV json_party: ${json_party}`)
  634. json = `{`;
  635. json += `"dtime": "${run.dtime}", `;
  636. json += `"area": "${run.dungeon}", `;
  637. json += `"stage": "${run.stage}", `;
  638. json += `"difficulty": "${run.difficulty}", `;
  639. json += `"win": "${run.win}", `;
  640. json += `"time": "${run.time}", `;
  641. json += `"mana": "${run.mana}", `;
  642. json += `"energy": "${run.energy}", `;
  643. json += `"crystal": "${run.crystal}", `;
  644. json += `"rune": ${json_rune}, `;
  645. json += `"sd": ${run.sd}, `;
  646. json += `"item": ${json_item}, `;
  647. json += `"unit": ${run.unit}, `;
  648. json += `"unit_pieces": ${json_unit_pieces}, `;
  649. json += `"sapeshifting": ${run.sapeshifting}, `;
  650. json += `"party": ${json_party}`;
  651. json += `}`;
  652. this.log('DEBUG', `json: ${json}`)
  653. },
  654. /**
  655. * TODO ???
  656. */
  657. getEnchantVals(craftID, craftType) {
  658. const map = {};
  659. const typeNumber = Number(craftID.toString().slice(-4, -2));
  660. map.set = gMapping.rune.sets[Number(craftID.toString().slice(0, -4))];
  661. map.grade = gMapping.rune.quality[Number(craftID.toString().slice(-1))];
  662. map.type = gMapping.rune.effectTypes[typeNumber];
  663. if (craftType === 2) {
  664. map.min = gMapping.grindstone[typeNumber].range[Number(craftID.toString().slice(-1))].min;
  665. map.max = gMapping.grindstone[typeNumber].range[Number(craftID.toString().slice(-1))].max;
  666. map.drop = 'Grindstone';
  667. } else {
  668. map.min = gMapping.enchanted_gem[typeNumber].range[Number(craftID.toString().slice(-1))].min;
  669. map.max = gMapping.enchanted_gem[typeNumber].range[Number(craftID.toString().slice(-1))].max;
  670. map.drop = 'Enchanted Gem';
  671. }
  672. return map;
  673. },
  674. /**
  675. * Prints a messageto the SWEX output.
  676. *
  677. * @param type Log type. Debug type will be printed depending on config.
  678. * @param msg The message to log.
  679. */
  680. log(type, msg){
  681. //if (type != "debug" || this.config.Config.Plugins[this.pluginName].debug == true){
  682. this.proxy.log({ type: type, source: 'plugin', name: this.pluginName, message: msg });
  683. //}
  684. }
  685. };