POST.php 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. <?php
  2. /**
  3. * Run logger script.
  4. *
  5. * Exposes an API to log a run.
  6. *
  7. * Mandatory PUT parameters are:
  8. * - result_response: JSON received from game server on run end.
  9. * - key: User API key.
  10. *
  11. * Optional POST parameters are:
  12. * - result_request: JSON sent to game server on run end.
  13. * - start_response: JSON received from game server on run start.
  14. * - start_request: JSON sent to game server on run start.
  15. *
  16. * @category API
  17. */
  18. /**
  19. * Calculates the currrent efficiency of a rune.
  20. *
  21. * @param JSON $rune JSON fragment of the rune.
  22. * @return int Efficiency (0-100)
  23. */
  24. function calculate_efficiency($rune){
  25. $efficiency = 0.0;
  26. $max_efficiency = 0.0;
  27. $substats = [];
  28. $level = $rune->{"upgrade_curr"};
  29. $stars = $rune->{"class"};
  30. // Ancient stars are + 10
  31. if ($stars > 10){
  32. $stars -= 10;
  33. }
  34. $list = null;
  35. // Main stat
  36. $main_stat = $rune->{"pri_eff"}[0];
  37. switch ($main_stat){
  38. case RUNE_STAT_ID::HP:
  39. $list = RUNE_STAT_VALUES::HP;
  40. break;
  41. case RUNE_STAT_ID::HP_P:
  42. $list = RUNE_STAT_VALUES::HP_P;
  43. break;
  44. case RUNE_STAT_ID::ATK:
  45. $list = RUNE_STAT_VALUES::ATK;
  46. break;
  47. case RUNE_STAT_ID::ATK_P:
  48. $list = RUNE_STAT_VALUES::ATK_P;
  49. break;
  50. case RUNE_STAT_ID::DEF:
  51. $list = RUNE_STAT_VALUES::DEF;
  52. break;
  53. case RUNE_STAT_ID::DEF_P:
  54. $list = RUNE_STAT_VALUES::DEF_P;
  55. break;
  56. case RUNE_STAT_ID::SPD:
  57. $list = RUNE_STAT_VALUES::SPD;
  58. break;
  59. case RUNE_STAT_ID::CRR:
  60. $list = RUNE_STAT_VALUES::CRR;
  61. break;
  62. case RUNE_STAT_ID::CRD:
  63. $list = RUNE_STAT_VALUES::CRD;
  64. break;
  65. case RUNE_STAT_ID::ACC:
  66. $list = RUNE_STAT_VALUES::ACC;
  67. break;
  68. case RUNE_STAT_ID::RES:
  69. $list = RUNE_STAT_VALUES::RES;
  70. break;
  71. }
  72. $efficiency += floatval($list[$stars][$level]) / floatval($list[6][15]);
  73. // Innate stat
  74. if ($rune->{"prefix_eff"}[0] > 0){
  75. $innate_stat = $rune->{"pri_eff"}[0];
  76. $innate_stat_value = $rune->{"pri_eff"}[1];
  77. $efficiency += floatval($innate_stat_value) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$innate_stat][6]));
  78. }
  79. // Substats
  80. for ($i = 0; $i <= 3; $i ++){
  81. if (sizeof($rune->{"sec_eff"}) > $i){
  82. $substat = $rune->{"sec_eff"}[$i][0];
  83. $substat_value = $rune->{"sec_eff"}[$i][1];
  84. $efficiency += floatval($substat_value) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$substat][6]));
  85. }
  86. }
  87. $efficiency = $efficiency / 2.8 * 100;
  88. if ($efficiency > 100){
  89. $efficiency = 100;
  90. }
  91. return $efficiency;
  92. }
  93. /**
  94. * Calculates the maximum efficiency of a rune.
  95. *
  96. * @param JSON $rune JSON fragment of the rune.
  97. * @return int Maximum efficiency (0-100)
  98. */
  99. function calculate_maximum_efficiency($rune){
  100. $efficiency = 0.0;
  101. $max_efficiency = 0.0;
  102. $substats = [];
  103. $stars = $rune->{"class"};
  104. // Ancient stars are + 10
  105. if ($stars > 10){
  106. $stars -= 10;
  107. }
  108. $list = null;
  109. // Main stat
  110. $main_stat = $rune->{"pri_eff"}[0];
  111. switch ($main_stat){
  112. case RUNE_STAT_ID::HP:
  113. $list = RUNE_STAT_VALUES::HP;
  114. break;
  115. case RUNE_STAT_ID::HP_P:
  116. $list = RUNE_STAT_VALUES::HP_P;
  117. break;
  118. case RUNE_STAT_ID::ATK:
  119. $list = RUNE_STAT_VALUES::ATK;
  120. break;
  121. case RUNE_STAT_ID::ATK_P:
  122. $list = RUNE_STAT_VALUES::ATK_P;
  123. break;
  124. case RUNE_STAT_ID::DEF:
  125. $list = RUNE_STAT_VALUES::DEF;
  126. break;
  127. case RUNE_STAT_ID::DEF_P:
  128. $list = RUNE_STAT_VALUES::DEF_P;
  129. break;
  130. case RUNE_STAT_ID::SPD:
  131. $list = RUNE_STAT_VALUES::SPD;
  132. break;
  133. case RUNE_STAT_ID::CRR:
  134. $list = RUNE_STAT_VALUES::CRR;
  135. break;
  136. case RUNE_STAT_ID::CRD:
  137. $list = RUNE_STAT_VALUES::CRD;
  138. break;
  139. case RUNE_STAT_ID::ACC:
  140. $list = RUNE_STAT_VALUES::ACC;
  141. break;
  142. case RUNE_STAT_ID::RES:
  143. $list = RUNE_STAT_VALUES::RES;
  144. break;
  145. }
  146. $efficiency += floatval($list[$stars][15]) / floatval($list[6][15]);
  147. // Innate stat
  148. if ($rune->{"prefix_eff"}[0] > 0){
  149. $innate_stat = $rune->{"pri_eff"}[0];
  150. $innate_stat_value = $rune->{"pri_eff"}[1];
  151. $efficiency += floatval($innate_stat_value) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$innate_stat][6]));
  152. }
  153. // Substats
  154. for ($i = 0; $i <= 3; $i ++){
  155. if (sizeof($rune->{"sec_eff"}) > $i){
  156. $substat = $rune->{"sec_eff"}[$i][0];
  157. $efficiency += floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$substat][$stars]) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$substat][6]));
  158. }
  159. }
  160. $efficiency = $efficiency / 2.8 * 100;
  161. if ($efficiency > 100){
  162. $efficiency = 100;
  163. }
  164. return $efficiency;
  165. }
  166. /**
  167. * Parses the JSONs relateds to a cairos run and saves the data.
  168. *
  169. * @param SQLiteConn $db Database connection.
  170. * @param int $uid Player UID.
  171. * @param int $id Run ID.
  172. * @param JSON[] $json List of received JSONs.
  173. */
  174. function log_rift_raid_run($db, $id, $uid, $json){
  175. // Only the start and result requests JSONs are needed:
  176. $result = $json["result_res"];
  177. if ($json["start_res"] === null){
  178. return ("400 Start response is required to parse Rift Raid runs.");
  179. }
  180. $start = $json["start_res"];
  181. // Prepare the "run" insert.
  182. $statement = $db->prepare("
  183. INSERT INTO run (
  184. uid,
  185. id,
  186. dtime,
  187. area_type,
  188. area,
  189. stage,
  190. difficulty,
  191. win,
  192. time,
  193. mana,
  194. energy,
  195. crystal,
  196. guild_points,
  197. helper,
  198. score,
  199. rank
  200. ) VALUES (
  201. :uid,
  202. :id,
  203. :dtime,
  204. :area_type,
  205. :area,
  206. :stage,
  207. :difficulty,
  208. :win,
  209. :time,
  210. :mana,
  211. :energy,
  212. :crystal,
  213. :guild_points,
  214. :helper,
  215. :score,
  216. :rank
  217. );
  218. ");
  219. // Bind data and insert
  220. $statement->bindValue(":uid", $uid);
  221. $statement->bindValue(":id", $id);
  222. $statement->bindValue(":dtime", $result->{"tvaluelocal"});
  223. $statement->bindValue(":area_type", AREA_TYPE_ID::RIFT_RAID);
  224. $statement->bindValue(":area", AREA_TYPE_ID::RIFT_RAID);
  225. $statement->bindValue(":stage", $start->{"battle_info"}->{"stage_id"});
  226. $statement->bindValue(":difficulty", null);
  227. $statement->bindValue(":win", $result->{"win_lose"});
  228. if ($result->{"win_lose"} == 1){
  229. $statement->bindValue(":time", $result->{"clear_time"}->{"current_time"});
  230. }
  231. else{
  232. $statement->bindValue(":time", 1);
  233. }
  234. $statement->bindValue(":mana", 0); // If reward is mana, i will be updated later
  235. $statement->bindValue(":energy", 0);
  236. $statement->bindValue(":crystal", 0);
  237. $statement->bindValue(":guild_points", 0);
  238. $statement->bindValue(":helper", 0);
  239. $statement->bindValue(":score", null);
  240. $statement->bindValue(":rank", null);
  241. $statement->execute();
  242. // Parse various types of reward
  243. if ($result->{"win_lose"} == 1 && array_key_exists("battle_reward_list", $result)){
  244. foreach ($result->{"battle_reward_list"} as $reward_list){
  245. if ($reward_list->{"wizard_id"} == $uid){
  246. $reward = $reward_list->{"reward_list"}[0];
  247. $reward_type = $reward->{"item_master_type"};
  248. switch ($reward_type){
  249. case INVENTORY_TYPE_ID::MONSTER: // Unit
  250. $statement = $db->prepare("INSERT INTO run_drop_unit (run, unit) VALUES (:run, :unit);");
  251. $statement->bindValue(":run", $id);
  252. $statement->bindValue(":unit", $reward->{"item_master_id"});
  253. $statement->execute();
  254. break;
  255. case INVENTORY_TYPE_ID::SCROLL:
  256. case INVENTORY_TYPE_ID::ESSENCES:
  257. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  258. $statement->bindValue(":run", $id);
  259. $statement->bindValue(":item", $reward->{"item_master_id"});
  260. $statement->bindValue(":amount", $reward->{"item_quantity"});
  261. $statement->execute();
  262. break;
  263. case INVENTORY_TYPE_ID::ENCHANTMENT:
  264. $statement = $db->prepare("
  265. INSERT INTO run_drop_enchantment (run, id, type, quality, rune, stat, value)
  266. VALUES (:run, :id, :type, :quality, :rune, :stat, :value);
  267. ");
  268. $statement->bindValue(":run", $id);
  269. $statement->bindValue(":id", $reward->{"runecraft_item_id"});
  270. $statement->bindValue(":type", $reward->{"runecraft_type"});
  271. $statement->bindValue(":quality", $reward->{"runecraft_rank"});
  272. $statement->bindValue(":rune", $reward->{"runecraft_set_id"});
  273. $statement->bindValue(":stat", $reward->{"runecraft_effect_id"});
  274. $statement->bindValue(":value", 0);
  275. $statement->execute();
  276. break;
  277. case 102: //: Mana
  278. $statement = $db->prepare("UPDATE run SET mana = :mana WHERE run = :run;");
  279. $statement->bindValue(":run", $id);
  280. $statement->bindValue(":id", $reward->{"runecraft_item_id"});
  281. $statement->execute();
  282. break;
  283. }
  284. }
  285. }
  286. }
  287. // Parse party
  288. foreach ($start->{"battle_info"}->{"user_list"} as $user){
  289. if ($user->{"wizard_id"} == $uid){
  290. foreach ($user->{"deck_list"} as $unit){
  291. $statement = $db->prepare("
  292. INSERT INTO run_party
  293. (run, unit, k_unit, leader, front)
  294. VALUES
  295. (:run, :unit, :k_unit, :leader, :front);"
  296. );
  297. $statement->bindValue(":run", $id);
  298. $statement->bindValue(":unit", $unit->{"unit_info"}->{"unit_id"});
  299. $statement->bindValue(":k_unit", $unit->{"unit_info"}->{"unit_master_id"});
  300. $statement->bindValue(":leader", $unit->{"leader"});
  301. if (intval($unit->{"index"}) <= 4){
  302. $statement->bindValue(":front", 1);
  303. }
  304. else{
  305. $statement->bindValue(":front", 0);
  306. }
  307. $statement->execute();
  308. }
  309. }
  310. }
  311. // Return success
  312. return "201 Created.";
  313. }
  314. /**
  315. * Parses the JSONs relateds to a cairos run and saves the data.
  316. *
  317. * @param SQLiteConn $db Database connection.
  318. * @param int $uid Player UID.
  319. * @param int $id Run ID.
  320. * @param JSON[] $json List of received JSONs.
  321. */
  322. function log_cairos_run($db, $id, $uid, $json){
  323. // Only the result request and response JSONs are needed:
  324. $response = $json["result_res"];
  325. if ($json["result_req"] === null){
  326. return ("400 Result request is required to parse Cairos runs.");
  327. }
  328. $request = $json["result_req"];
  329. // Prepare the "run" insert.
  330. $statement = $db->prepare("
  331. INSERT INTO run (
  332. uid,
  333. id,
  334. dtime,
  335. area_type,
  336. area,
  337. stage,
  338. difficulty,
  339. win,
  340. time,
  341. mana,
  342. energy,
  343. crystal,
  344. guild_points,
  345. helper,
  346. score,
  347. rank
  348. ) VALUES (
  349. :uid,
  350. :id,
  351. :dtime,
  352. :area_type,
  353. :area,
  354. :stage,
  355. :difficulty,
  356. :win,
  357. :time,
  358. :mana,
  359. :energy,
  360. :crystal,
  361. :guild_points,
  362. :helper,
  363. :score,
  364. :rank
  365. );
  366. ");
  367. // Bind data and insert
  368. $statement->bindValue(":uid", $uid);
  369. $statement->bindValue(":id", $id);
  370. $statement->bindValue(":dtime", $response->{"tvaluelocal"});
  371. $statement->bindValue(":area_type", AREA_TYPE_ID::CAIROS_DUNGEON);
  372. $statement->bindValue(":area", $request->{"dungeon_id"});
  373. $statement->bindValue(":stage", $request->{"stage_id"});
  374. $statement->bindValue(":difficulty", null);
  375. $statement->bindValue(":win", $response->{"win_lose"});
  376. $statement->bindValue(":time", $response->{"clear_time"}->{"current_time"});
  377. if (array_key_exists("mana", $response->{"reward"})){
  378. $statement->bindValue(":mana", $response->{"reward"}->{"mana"});
  379. }
  380. else{
  381. $statement->bindValue(":mana", 0);
  382. }
  383. if (array_key_exists("energy", $response->{"reward"})){
  384. $statement->bindValue(":energy", $response->{"reward"}->{"energy"});
  385. }
  386. else{
  387. $statement->bindValue(":energy", 0);
  388. }
  389. if (array_key_exists("crystal", $response->{"reward"})){
  390. $statement->bindValue(":crystal", $response->{"reward"}->{"crystal"});
  391. }
  392. else{
  393. $statement->bindValue(":crystal", 0);
  394. }
  395. $statement->bindValue(":guild_points", 0);
  396. $statement->bindValue(":helper", 0); // TODO Where is this information??
  397. $statement->bindValue(":score", null);
  398. $statement->bindValue(":rank", null);
  399. $statement->execute();
  400. // Parse various types of reward
  401. if (array_key_exists("changed_item_list", $response)){
  402. $reward_type = $response->{"changed_item_list"}[0]->{"type"};
  403. switch ($reward_type){
  404. case INVENTORY_TYPE_ID::MONSTER: // Unit
  405. $statement = $db->prepare("INSERT INTO run_drop_unit (run, unit) VALUES (:run, :unit);");
  406. $statement->bindValue(":run", $id);
  407. $statement->bindValue(":unit", $response->{"changed_item_list"}[0]->{"view"}->{"item_master_id"});
  408. $statement->execute();
  409. break;
  410. case INVENTORY_TYPE_ID::SCROLL:
  411. case INVENTORY_TYPE_ID::ESSENCES:
  412. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  413. $statement->bindValue(":run", $id);
  414. $statement->bindValue(":item", $response->{"changed_item_list"}[0]->{"view"}->{"item_master_id"});
  415. $statement->bindValue(":amount", $response->{"changed_item_list"}[0]->{"view"}->{"item_quantity"});
  416. $statement->execute();
  417. break;
  418. case INVENTORY_TYPE_ID::RUNE:
  419. $rune = $response->{"changed_item_list"}[0]->{"info"};
  420. $statement = $db->prepare("
  421. INSERT INTO run_drop_rune (
  422. run,
  423. id,
  424. type,
  425. slot,
  426. stars,
  427. ancient,
  428. quality,
  429. value,
  430. efficiency,
  431. max_efficiency,
  432. main_stat,
  433. main_stat_value,
  434. innate_stat,
  435. innate_stat_value,
  436. substat_1,
  437. substat_1_value,
  438. substat_2,
  439. substat_2_value,
  440. substat_3,
  441. substat_3_value,
  442. substat_4,
  443. substat_4_value
  444. ) VALUES (
  445. :run,
  446. :id,
  447. :type,
  448. :slot,
  449. :stars,
  450. :ancient,
  451. :quality,
  452. :value,
  453. :efficiency,
  454. :max_efficiency,
  455. :main_stat,
  456. :main_stat_value,
  457. :innate_stat,
  458. :innate_stat_value,
  459. :substat_1,
  460. :substat_1_value,
  461. :substat_2,
  462. :substat_2_value,
  463. :substat_3,
  464. :substat_3_value,
  465. :substat_4,
  466. :substat_4_value
  467. );
  468. ");
  469. $statement->bindValue(":run", $id);
  470. $statement->bindValue(":id", $rune->{"rune_id"});
  471. $statement->bindValue(":type", $rune->{"set_id"});
  472. $statement->bindValue(":slot", $rune->{"slot_no"});
  473. $statement->bindValue(":value", $rune->{"sell_value"});
  474. if ($rune->{"class"} > 10){
  475. // Ancient rune
  476. $statement->bindValue(":ancient", 1);
  477. $statement->bindValue(":stars", intval($rune->{"class"}) - 10);
  478. $statement->bindValue(":quality", intval($rune->{"rank"}) - 10);
  479. }
  480. else{
  481. // Non Ancient rune
  482. $statement->bindValue(":ancient", 0);
  483. $statement->bindValue(":stars", $rune->{"class"});
  484. $statement->bindValue(":quality", $rune->{"rank"});
  485. }
  486. $efficiency = calculate_efficiency($rune);
  487. $max_efficiency = calculate_maximum_efficiency($rune);
  488. $statement->bindValue(":efficiency", $efficiency);
  489. $statement->bindValue(":max_efficiency", $max_efficiency);
  490. $statement->bindValue(":main_stat", $rune->{"pri_eff"}[0]);
  491. $statement->bindValue(":main_stat_value", $rune->{"pri_eff"}[1]);
  492. if ($rune->{"prefix_eff"}[0] > 0){
  493. $statement->bindValue(":innate_stat", $rune->{"prefix_eff"}[0]);
  494. $statement->bindValue(":innate_stat_value", $rune->{"prefix_eff"}[1]);
  495. }
  496. else{
  497. $statement->bindValue(":innate_stat", null);
  498. $statement->bindValue(":innate_stat_value", 0);
  499. }
  500. if (sizeof($rune->{"sec_eff"}) > 0){
  501. $statement->bindValue(":substat_1", $rune->{"sec_eff"}[0][0]);
  502. $statement->bindValue(":substat_1_value", $rune->{"sec_eff"}[0][1]);
  503. }
  504. else{
  505. $statement->bindValue(":substat_1", null);
  506. $statement->bindValue(":substat_1_value", 0);
  507. }
  508. if (sizeof($rune->{"sec_eff"}) > 1){
  509. $statement->bindValue(":substat_2", $rune->{"sec_eff"}[1][0]);
  510. $statement->bindValue(":substat_2_value", $rune->{"sec_eff"}[1][1]);
  511. }
  512. else{
  513. $statement->bindValue(":substat_2", null);
  514. $statement->bindValue(":substat_2_value", 0);
  515. }
  516. if (sizeof($rune->{"sec_eff"}) > 2){
  517. $statement->bindValue(":substat_3", $rune->{"sec_eff"}[2][0]);
  518. $statement->bindValue(":substat_3_value", $rune->{"sec_eff"}[2][1]);
  519. }
  520. else{
  521. $statement->bindValue(":substat_3", null);
  522. $statement->bindValue(":substat_3_value", 0);
  523. }
  524. if (sizeof($rune->{"sec_eff"}) > 3){
  525. $statement->bindValue(":substat_4", $rune->{"sec_eff"}[3][0]);
  526. $statement->bindValue(":substat_4_value", $rune->{"sec_eff"}[3][1]);
  527. }
  528. else{
  529. $statement->bindValue(":substat_4", null);
  530. $statement->bindValue(":substat_4_value", 0);
  531. }
  532. $statement->execute();
  533. break;
  534. }
  535. }
  536. // Parse party
  537. $leader = 1;
  538. foreach ($response->{"unit_list"} as $unit){
  539. $statement = $db->prepare("
  540. INSERT INTO run_party
  541. (run, unit, k_unit, leader, front)
  542. VALUES
  543. (:run, :unit, :k_unit, :leader, :front);"
  544. );
  545. $statement->bindValue(":run", $id);
  546. $statement->bindValue(":unit", $unit->{"unit_id"});
  547. $statement->bindValue(":k_unit", $unit->{"unit_master_id"});
  548. $statement->bindValue(":leader", $leader);
  549. $leader = 0;
  550. $statement->bindValue(":front", 0);
  551. $statement->execute();
  552. }
  553. // Return success
  554. return "201 Created.";
  555. }
  556. /**
  557. * Parses the JSONs relateds to a Dimension Hole run and saves the data.
  558. *
  559. * @param SQLiteConn $db Database connection.
  560. * @param int $uid Player UID.
  561. * @param int $id Run ID.
  562. * @param JSON[] $json List of received JSONs.
  563. */
  564. function log_dimension_hole_run($db, $id, $uid, $json){
  565. // Only the result request and response JSONs are needed:
  566. $response = $json["result_res"];
  567. if ($json["result_req"] === null){
  568. return ("400 Result request is required to parse Cairos runs.");
  569. }
  570. $request = $json["result_req"];
  571. // Prepare the "run" insert.
  572. $statement = $db->prepare("
  573. INSERT INTO run (
  574. uid,
  575. id,
  576. dtime,
  577. area_type,
  578. area,
  579. stage,
  580. difficulty,
  581. win,
  582. time,
  583. mana,
  584. energy,
  585. crystal,
  586. guild_points,
  587. helper,
  588. score,
  589. rank
  590. ) VALUES (
  591. :uid,
  592. :id,
  593. :dtime,
  594. :area_type,
  595. :area,
  596. :stage,
  597. :difficulty,
  598. :win,
  599. :time,
  600. :mana,
  601. :energy,
  602. :crystal,
  603. :guild_points,
  604. :helper,
  605. :score,
  606. :rank
  607. );
  608. ");
  609. // Bind data and insert
  610. $statement->bindValue(":uid", $uid);
  611. $statement->bindValue(":id", $id);
  612. $statement->bindValue(":dtime", $response->{"tvaluelocal"});
  613. $statement->bindValue(":area_type", AREA_TYPE_ID::DIMENSIONAL_HOLE);
  614. $statement->bindValue(":area", $response->{"dungeon_id"});
  615. $statement->bindValue(":stage", $response->{"difficulty"}); // Difficulty is stage
  616. $statement->bindValue(":difficulty", null);
  617. $statement->bindValue(":win", $response->{"win_lose"});
  618. $statement->bindValue(":time", $response->{"clear_time"}->{"current_time"});
  619. if (array_key_exists("mana", $response->{"reward"})){
  620. $statement->bindValue(":mana", $response->{"reward"}->{"mana"});
  621. }
  622. else{
  623. $statement->bindValue(":mana", 0);
  624. }
  625. if (array_key_exists("energy", $response->{"reward"})){
  626. $statement->bindValue(":energy", $response->{"reward"}->{"energy"});
  627. }
  628. $statement->bindValue(":energy", 0);
  629. if (array_key_exists("crystal", $response->{"reward"})){
  630. $statement->bindValue(":crystal", $response->{"reward"}->{"crystal"});
  631. }
  632. else{
  633. $statement->bindValue(":crystal", 0);
  634. }
  635. $statement->bindValue(":guild_points", 0);
  636. $statement->bindValue(":helper", 0); // TODO Where is this information??
  637. $statement->bindValue(":score", null);
  638. $statement->bindValue(":rank", null);
  639. $statement->execute();
  640. // Parse various types of reward
  641. if (array_key_exists("changed_item_list", $response)){
  642. foreach ($response->{"changed_item_list"} as $drop){
  643. $reward_type = $drop->{"type"};
  644. switch ($reward_type){
  645. case INVENTORY_TYPE_ID::CRAFT_STUFF:
  646. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  647. $statement->bindValue(":run", $id);
  648. $statement->bindValue(":item", $drop->{"view"}->{"item_master_id"});
  649. $statement->bindValue(":amount", $drop->{"view"}->{"item_quantity"});
  650. $statement->execute();
  651. break;
  652. case INVENTORY_TYPE_ID::RUNE:
  653. // TODO: Investigate with no awaken dungeons
  654. /*$rune = $response->{"changed_item_list"}[0]->{"info"};
  655. $statement = $db->prepare("
  656. INSERT INTO run_drop_rune (
  657. run,
  658. id,
  659. type,
  660. slot,
  661. stars,
  662. ancient,
  663. quality,
  664. value,
  665. efficiency,
  666. max_efficiency,
  667. main_stat,
  668. main_stat_value,
  669. innate_stat,
  670. innate_stat_value,
  671. substat_1,
  672. substat_1_value,
  673. substat_2,
  674. substat_2_value,
  675. substat_3,
  676. substat_3_value,
  677. substat_4,
  678. substat_4_value
  679. ) VALUES (
  680. :run,
  681. :id,
  682. :type,
  683. :slot,
  684. :stars,
  685. :ancient,
  686. :quality,
  687. :value,
  688. :efficiency,
  689. :max_efficiency,
  690. :main_stat,
  691. :main_stat_value,
  692. :innate_stat,
  693. :innate_stat_value,
  694. :substat_1,
  695. :substat_1_value,
  696. :substat_2,
  697. :substat_2_value,
  698. :substat_3,
  699. :substat_3_value,
  700. :substat_4,
  701. :substat_4_value
  702. );
  703. ");
  704. $statement->bindValue(":run", $id);
  705. $statement->bindValue(":id", $rune->{"rune_id"});
  706. $statement->bindValue(":type", $rune->{"set_id"});
  707. $statement->bindValue(":slot", $rune->{"slot_no"});
  708. $statement->bindValue(":value", $rune->{"sell_value"});
  709. if ($rune->{"class"} > 10){
  710. // Ancient rune
  711. $statement->bindValue(":ancient", 1);
  712. $statement->bindValue(":stars", intval($rune->{"class"}) - 10);
  713. $statement->bindValue(":quality", intval($rune->{"rank"}) - 10);
  714. }
  715. else{
  716. // Non Ancient rune
  717. $statement->bindValue(":ancient", 0);
  718. $statement->bindValue(":stars", $rune->{"class"});
  719. $statement->bindValue(":quality", $rune->{"rank"});
  720. }
  721. $efficiency = calculate_efficiency($rune);
  722. $max_efficiency = calculate_maximum_efficiency($rune);
  723. $statement->bindValue(":efficiency", $efficiency);
  724. $statement->bindValue(":max_efficiency", $max_efficiency);
  725. $statement->bindValue(":main_stat", $rune->{"pri_eff"}[0]);
  726. $statement->bindValue(":main_stat_value", $rune->{"pri_eff"}[1]);
  727. if ($rune->{"prefix_eff"}[0] > 0){
  728. $statement->bindValue(":innate_stat", $rune->{"prefix_eff"}[0]);
  729. $statement->bindValue(":innate_stat_value", $rune->{"prefix_eff"}[1]);
  730. }
  731. else{
  732. $statement->bindValue(":innate_stat", null);
  733. $statement->bindValue(":innate_stat_value", 0);
  734. }
  735. if (sizeof($rune->{"sec_eff"}) > 0){
  736. $statement->bindValue(":substat_1", $rune->{"sec_eff"}[0][0]);
  737. $statement->bindValue(":substat_1_value", $rune->{"sec_eff"}[0][1]);
  738. }
  739. else{
  740. $statement->bindValue(":substat_1", null);
  741. $statement->bindValue(":substat_1_value", 0);
  742. }
  743. if (sizeof($rune->{"sec_eff"}) > 1){
  744. $statement->bindValue(":substat_2", $rune->{"sec_eff"}[1][0]);
  745. $statement->bindValue(":substat_2_value", $rune->{"sec_eff"}[1][1]);
  746. }
  747. else{
  748. $statement->bindValue(":substat_2", null);
  749. $statement->bindValue(":substat_2_value", 0);
  750. }
  751. if (sizeof($rune->{"sec_eff"}) > 2){
  752. $statement->bindValue(":substat_3", $rune->{"sec_eff"}[2][0]);
  753. $statement->bindValue(":substat_3_value", $rune->{"sec_eff"}[2][1]);
  754. }
  755. else{
  756. $statement->bindValue(":substat_3", null);
  757. $statement->bindValue(":substat_3_value", 0);
  758. }
  759. if (sizeof($rune->{"sec_eff"}) > 3){
  760. $statement->bindValue(":substat_4", $rune->{"sec_eff"}[3][0]);
  761. $statement->bindValue(":substat_4_value", $rune->{"sec_eff"}[3][1]);
  762. }
  763. else{
  764. $statement->bindValue(":substat_4", null);
  765. $statement->bindValue(":substat_4_value", 0);
  766. }
  767. $statement->execute();*/
  768. break;
  769. }
  770. }
  771. }
  772. // Parse party
  773. $leader = 1;
  774. foreach ($response->{"unit_list"} as $unit){
  775. $statement = $db->prepare("
  776. INSERT INTO run_party
  777. (run, unit, k_unit, leader, front)
  778. VALUES
  779. (:run, :unit, :k_unit, :leader, :front);"
  780. );
  781. $statement->bindValue(":run", $id);
  782. $statement->bindValue(":unit", $unit->{"unit_id"});
  783. $statement->bindValue(":k_unit", $unit->{"unit_master_id"});
  784. $statement->bindValue(":leader", $leader);
  785. $leader = 0;
  786. $statement->bindValue(":front", 0);
  787. $statement->execute();
  788. }
  789. // Return success
  790. return "201 Created.";
  791. }
  792. global $db;
  793. try{
  794. header("Content-type: application/json; charset=utf-8");
  795. // Get put data
  796. parse_str(file_get_contents("php://input"), $_POST);
  797. // Check API key.
  798. if (!array_key_exists("key", $_POST)){
  799. header("HTTP/1.1 400 API key not received.");
  800. syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 API key not received.");
  801. return 400;
  802. }
  803. $key = $_POST["key"];
  804. // Get all JSON files
  805. $json = [
  806. "start_req" => null,
  807. "start_res" => null,
  808. "result_req" => null,
  809. "result_res" => null,
  810. ];
  811. // Result response - mandatory
  812. if (!array_key_exists("result_response", $_POST)){
  813. header("HTTP/1.1 400 No result response data received.");
  814. syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 No result response data received.");
  815. return 400;
  816. }
  817. $data_json = json_decode($_POST["result_response"]);
  818. if ($data_json === null){
  819. header("HTTP/1.1 400 Result response data is no valid JSON.");
  820. syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 Result response data is no valid JSON.");
  821. return 400;
  822. }
  823. $json["result_res"] = $data_json;
  824. // Result request - optional
  825. if (array_key_exists("result_request", $_POST)){
  826. $data_raw = $_POST["result_request"];
  827. if ($data_raw != null && $data_raw != false){
  828. $data_json = json_decode($data_raw);
  829. if ($data_json != null){
  830. $json["result_req"] = $data_json;
  831. }
  832. }
  833. }
  834. // Start result - optional
  835. if (array_key_exists("start_response", $_POST)){
  836. $data_raw = $_POST["start_response"];
  837. if ($data_raw != null && $data_raw != false){
  838. $data_json = json_decode($data_raw);
  839. if ($data_json != null){
  840. $json["start_res"] = $data_json;
  841. }
  842. }
  843. }
  844. // Start result - optional
  845. if (array_key_exists("start_request", $_POST)){
  846. $data_raw = $_POST["start_request"];
  847. if ($data_raw != null && $data_raw != false){
  848. $data_json = json_decode($data_raw);
  849. if ($data_json != null){
  850. $json["start_req"] = $data_json;
  851. }
  852. }
  853. }
  854. // Extract basic data
  855. $uid = $json["result_res"]->{"wizard_info"}->{"wizard_id"};
  856. $command = $json["result_res"]->{"command"};
  857. // Authenticate
  858. $statement = $db->prepare("SELECT COUNT(uid) AS c FROM player WHERE uid = :uid AND api_key = :api_key;");
  859. $statement->bindValue(":uid", $uid);
  860. $statement->bindValue(":api_key", $key);
  861. if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
  862. header("HTTP/1.1 401 Invalid credentials.");
  863. syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
  864. return 401;
  865. }
  866. // Check for implemented command
  867. $accepted_commands = [
  868. "BattleDungeonResult_V2", // Dungeon Run
  869. "BattleDimensionHoleDungeonResult_v2", // Dimension Hole Run
  870. "BattleRiftOfWorldsRaidResult" // Rift Raid Run
  871. ];
  872. if (!in_array($command, $accepted_commands)){
  873. header("HTTP/1.1 405 Command not implemented.");
  874. syslog(LOG_INFO, "[APIv3] HTTP/1.1 405 Command not implemented.");
  875. return 405;
  876. }
  877. // Check if already in DB
  878. $dtime = $json["result_res"]->{"tvaluelocal"};
  879. $statement = $db->prepare("SELECT count(id) AS c FROM run WHERE uid = :uid AND dtime = :dtime;");
  880. $statement->bindValue(":uid", $uid);
  881. $statement->bindValue(":dtime", $dtime);
  882. if (0 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
  883. header("HTTP/1.1 409 Run already in database.");
  884. syslog(LOG_INFO, "[APIv3] HTTP/1.1 409 Run already in database.");
  885. return 409;
  886. }
  887. // Get new ID
  888. $q = $db->query("SELECT max(id) + 1 AS id FROM run;");
  889. $r = $q->fetchArray(SQLITE3_ASSOC);
  890. if ($r){
  891. $id = $r["id"];
  892. }
  893. else{
  894. $id = 1;
  895. }
  896. // Run parsing function
  897. $result = "500 Unknown Error";
  898. switch($command){
  899. case "BattleDungeonResult_V2":
  900. $result = log_cairos_run($db, $id, $uid, $json);
  901. break;
  902. case "BattleDimensionHoleDungeonResult_v2":
  903. $result = log_dimension_hole_run($db, $id, $uid, $json);
  904. break;
  905. case "BattleRiftOfWorldsRaidResult":
  906. $result = log_rift_raid_run($db, $id, $uid, $json);
  907. break;
  908. }
  909. // Process result
  910. $status_code = intval(substr($result, 0, 3));
  911. $status_message = substr($result, 4);
  912. if ($status_code == 0 || $status_code < 100 || $status_code > 599){
  913. header("HTTP/1.1 500 Unknown error.");
  914. syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unknown error.");
  915. return 500;
  916. }
  917. else{
  918. header("HTTP/1.1 $status_code $status_message");
  919. syslog(LOG_INFO, "[APIv3] HTTP/1.1 $status_code $status_message");
  920. return $status_code;
  921. }
  922. }
  923. catch(Exception $e) {
  924. header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
  925. syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
  926. return 500;
  927. }
  928. ?>