POST.php 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
  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 mixed[] $rune JSON fragment of the rune.
  22. * @return int Efficiency (0-100)
  23. */
  24. function calculate_efficiency($rune){
  25. $efficiency = 0.0;
  26. $level = $rune->{"upgrade_curr"};
  27. $stars = $rune->{"class"};
  28. // Ancient stars are + 10
  29. if ($stars > 10){
  30. $stars -= 10;
  31. }
  32. $list = null;
  33. // Main stat
  34. $main_stat = $rune->{"pri_eff"}[0];
  35. switch ($main_stat){
  36. case RUNE_STAT_ID::HP:
  37. $list = RUNE_STAT_VALUES::HP;
  38. break;
  39. case RUNE_STAT_ID::HP_P:
  40. $list = RUNE_STAT_VALUES::HP_P;
  41. break;
  42. case RUNE_STAT_ID::ATK:
  43. $list = RUNE_STAT_VALUES::ATK;
  44. break;
  45. case RUNE_STAT_ID::ATK_P:
  46. $list = RUNE_STAT_VALUES::ATK_P;
  47. break;
  48. case RUNE_STAT_ID::DEF:
  49. $list = RUNE_STAT_VALUES::DEF;
  50. break;
  51. case RUNE_STAT_ID::DEF_P:
  52. $list = RUNE_STAT_VALUES::DEF_P;
  53. break;
  54. case RUNE_STAT_ID::SPD:
  55. $list = RUNE_STAT_VALUES::SPD;
  56. break;
  57. case RUNE_STAT_ID::CRR:
  58. $list = RUNE_STAT_VALUES::CRR;
  59. break;
  60. case RUNE_STAT_ID::CRD:
  61. $list = RUNE_STAT_VALUES::CRD;
  62. break;
  63. case RUNE_STAT_ID::ACC:
  64. $list = RUNE_STAT_VALUES::ACC;
  65. break;
  66. case RUNE_STAT_ID::RES:
  67. $list = RUNE_STAT_VALUES::RES;
  68. break;
  69. }
  70. $efficiency += floatval($list[$stars][$level]) / floatval($list[6][15]);
  71. // Innate stat
  72. if ($rune->{"prefix_eff"}[0] > 0){
  73. $innate_stat = $rune->{"pri_eff"}[0];
  74. $innate_stat_value = $rune->{"pri_eff"}[1];
  75. $efficiency += floatval($innate_stat_value) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$innate_stat][6]));
  76. }
  77. // Substats
  78. for ($i = 0; $i <= 3; $i ++){
  79. if (sizeof($rune->{"sec_eff"}) > $i){
  80. $substat = $rune->{"sec_eff"}[$i][0];
  81. $substat_value = $rune->{"sec_eff"}[$i][1];
  82. $efficiency += floatval($substat_value) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$substat][6]));
  83. }
  84. }
  85. $efficiency = $efficiency / 2.8 * 100;
  86. if ($efficiency > 100){
  87. $efficiency = 100;
  88. }
  89. return $efficiency;
  90. }
  91. /**
  92. * Calculates the maximum efficiency of a rune.
  93. *
  94. * @param mixed[] $rune JSON fragment of the rune.
  95. * @return int Maximum efficiency (0-100)
  96. */
  97. function calculate_maximum_efficiency($rune){
  98. $efficiency = 0.0;
  99. $stars = $rune->{"class"};
  100. // Ancient stars are + 10
  101. if ($stars > 10){
  102. $stars -= 10;
  103. }
  104. $list = null;
  105. // Main stat
  106. $main_stat = $rune->{"pri_eff"}[0];
  107. switch ($main_stat){
  108. case RUNE_STAT_ID::HP:
  109. $list = RUNE_STAT_VALUES::HP;
  110. break;
  111. case RUNE_STAT_ID::HP_P:
  112. $list = RUNE_STAT_VALUES::HP_P;
  113. break;
  114. case RUNE_STAT_ID::ATK:
  115. $list = RUNE_STAT_VALUES::ATK;
  116. break;
  117. case RUNE_STAT_ID::ATK_P:
  118. $list = RUNE_STAT_VALUES::ATK_P;
  119. break;
  120. case RUNE_STAT_ID::DEF:
  121. $list = RUNE_STAT_VALUES::DEF;
  122. break;
  123. case RUNE_STAT_ID::DEF_P:
  124. $list = RUNE_STAT_VALUES::DEF_P;
  125. break;
  126. case RUNE_STAT_ID::SPD:
  127. $list = RUNE_STAT_VALUES::SPD;
  128. break;
  129. case RUNE_STAT_ID::CRR:
  130. $list = RUNE_STAT_VALUES::CRR;
  131. break;
  132. case RUNE_STAT_ID::CRD:
  133. $list = RUNE_STAT_VALUES::CRD;
  134. break;
  135. case RUNE_STAT_ID::ACC:
  136. $list = RUNE_STAT_VALUES::ACC;
  137. break;
  138. case RUNE_STAT_ID::RES:
  139. $list = RUNE_STAT_VALUES::RES;
  140. break;
  141. }
  142. $efficiency += floatval($list[$stars][15]) / floatval($list[6][15]);
  143. // Innate stat
  144. if ($rune->{"prefix_eff"}[0] > 0){
  145. $innate_stat = $rune->{"pri_eff"}[0];
  146. $innate_stat_value = $rune->{"pri_eff"}[1];
  147. $efficiency += floatval($innate_stat_value) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$innate_stat][6]));
  148. }
  149. // Substats
  150. for ($i = 0; $i <= 3; $i ++){
  151. if (sizeof($rune->{"sec_eff"}) > $i){
  152. $substat = $rune->{"sec_eff"}[$i][0];
  153. $efficiency += floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$substat][$stars]) / (5 * floatval(RUNE_SUBSTAT_MAX_VALUES::SUBSTAT[$substat][6]));
  154. }
  155. }
  156. $efficiency = $efficiency / 2.8 * 100;
  157. if ($efficiency > 100){
  158. $efficiency = 100;
  159. }
  160. return $efficiency;
  161. }
  162. /**
  163. * Parses the JSONs relateds to an Arena run and saves the data.
  164. *
  165. * @param resource $db Database connection.
  166. * @param int $player_id Player ID.
  167. * @param int $id Run ID.
  168. * @param mixed[] $json List of received JSONs.
  169. */
  170. function log_arena_run($db, $id, $player_id, $json){
  171. // Only the result request and response JSONs are needed:
  172. $response = $json["result_res"];
  173. // Prepare the "run" insert.
  174. $statement = $db->prepare("
  175. INSERT INTO run (
  176. player,
  177. id,
  178. dtime,
  179. area_type,
  180. area,
  181. stage,
  182. difficulty,
  183. win,
  184. time,
  185. mana,
  186. energy,
  187. crystal,
  188. guild_points,
  189. honor_points,
  190. helper,
  191. score,
  192. rank
  193. ) VALUES (
  194. :player,
  195. :id,
  196. :dtime,
  197. :area_type,
  198. :area,
  199. :stage,
  200. :difficulty,
  201. :win,
  202. :time,
  203. :mana,
  204. :energy,
  205. :crystal,
  206. :guild_points,
  207. :honor_points,
  208. :helper,
  209. :score,
  210. :rank
  211. );
  212. ");
  213. // Bind data and insert
  214. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  215. $statement->bindValue(":id", $id, SQLITE3_INTEGER);
  216. $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
  217. $statement->bindValue(":area_type", AREA_TYPE_ID::ARENA, SQLITE3_INTEGER);
  218. $statement->bindValue(":area", AREA_TYPE_ID::ARENA, SQLITE3_INTEGER);
  219. $statement->bindValue(":stage", null, SQLITE3_INTEGER);
  220. $statement->bindValue(":difficulty", null, SQLITE3_INTEGER);
  221. $statement->bindValue(":win", $response->{"win_lose"}, SQLITE3_INTEGER);
  222. $statement->bindValue(":time", 1, SQLITE3_INTEGER);
  223. if (array_key_exists("mana", $response->{"reward"})){
  224. $statement->bindValue(":mana", $response->{"reward"}->{"mana"}, SQLITE3_INTEGER);
  225. }
  226. else{
  227. $statement->bindValue(":mana", 0, SQLITE3_INTEGER);
  228. }
  229. if (array_key_exists("energy", $response->{"reward"})){
  230. $statement->bindValue(":energy", $response->{"reward"}->{"energy"}, SQLITE3_INTEGER);
  231. }
  232. else{
  233. $statement->bindValue(":energy", 0, SQLITE3_INTEGER);
  234. }
  235. if (array_key_exists("crystal", $response->{"reward"})){
  236. $statement->bindValue(":crystal", $response->{"reward"}->{"crystal"}, SQLITE3_INTEGER);
  237. }
  238. else{
  239. $statement->bindValue(":crystal", 0, SQLITE3_INTEGER);
  240. }
  241. $statement->bindValue(":guild_points", 0, SQLITE3_INTEGER);
  242. if (array_key_exists("honor_point", $response->{"reward"})){
  243. $statement->bindValue(":honor_points", $response->{"reward"}->{"honor_point"}, SQLITE3_INTEGER);
  244. }
  245. else{
  246. $statement->bindValue(":honor_points", 0, SQLITE3_INTEGER);
  247. }
  248. $statement->bindValue(":helper", 0, SQLITE3_INTEGER);
  249. $statement->bindValue(":score", null, SQLITE3_INTEGER);
  250. $statement->bindValue(":rank", null, SQLITE3_TEXT);
  251. $statement->execute();
  252. // Parse party
  253. $leader = 1;
  254. foreach ($response->{"unit_list"} as $unit){
  255. $statement = $db->prepare("
  256. INSERT INTO run_party
  257. (run, unit, k_unit, leader, front)
  258. VALUES
  259. (:run, :unit, :k_unit, :leader, :front);"
  260. );
  261. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  262. $statement->bindValue(":unit", $unit->{"unit_id"}, SQLITE3_INTEGER);
  263. $statement->bindValue(":k_unit", $unit->{"unit_master_id"}, SQLITE3_INTEGER);
  264. $statement->bindValue(":leader", $leader, SQLITE3_INTEGER);
  265. $leader = 0;
  266. $statement->bindValue(":front", 0, SQLITE3_INTEGER);
  267. $statement->execute();
  268. }
  269. // Return success
  270. return "201 Created.";
  271. }
  272. /**
  273. * Parses the JSONs relateds to a Dimensional Rift run and saves the data.
  274. *
  275. * @param resource $db Database connection.
  276. * @param int $player_id Player ID.
  277. * @param int $id Run ID.
  278. * @param mixed[] $json List of received JSONs.
  279. */
  280. function log_dark_portal_run($db, $id, $player_id, $json){
  281. // Only the result request and response JSONs are needed:
  282. $response = $json["result_res"];
  283. // Prepare the "run" insert.
  284. $statement = $db->prepare("
  285. INSERT INTO run (
  286. player,
  287. id,
  288. dtime,
  289. area_type,
  290. area,
  291. stage,
  292. difficulty,
  293. win,
  294. time,
  295. mana,
  296. energy,
  297. crystal,
  298. guild_points,
  299. honor_points,
  300. helper,
  301. score,
  302. rank
  303. ) VALUES (
  304. :player,
  305. :id,
  306. :dtime,
  307. :area_type,
  308. :area,
  309. :stage,
  310. :difficulty,
  311. :win,
  312. :time,
  313. :mana,
  314. :energy,
  315. :crystal,
  316. :guild_points,
  317. :honor_points,
  318. :helper,
  319. :score,
  320. :rank
  321. );
  322. ");
  323. // Bind data and insert
  324. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  325. $statement->bindValue(":id", $id, SQLITE3_INTEGER);
  326. $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_INTEGER);
  327. $statement->bindValue(":area_type", AREA_TYPE_ID::DIMENSIONAL_RIFT, SQLITE3_INTEGER);
  328. // The area is the region the portal is open in.
  329. $statement->bindValue(":area", $response->{"region_id"}, SQLITE3_INTEGER);
  330. $statement->bindValue(":stage", null, SQLITE3_INTEGER);
  331. $statement->bindValue(":difficulty", $response->{"difficulty"}, SQLITE3_INTEGER);
  332. $statement->bindValue(":win", $response->{"win_lose"}, SQLITE3_INTEGER);
  333. $statement->bindValue(":time", 1, SQLITE3_INTEGER);
  334. if (array_key_exists("mana", $response->{"reward"})){
  335. $statement->bindValue(":mana", $response->{"reward"}->{"mana"}, SQLITE3_INTEGER);
  336. }
  337. else{
  338. $statement->bindValue(":mana", 0, SQLITE3_INTEGER);
  339. }
  340. if (array_key_exists("energy", $response->{"reward"})){
  341. $statement->bindValue(":energy", $response->{"reward"}->{"energy"});
  342. }
  343. else{
  344. $statement->bindValue(":energy", 0);
  345. }
  346. if (array_key_exists("crystal", $response->{"reward"})){
  347. $statement->bindValue(":crystal", $response->{"reward"}->{"crystal"}, SQLITE3_INTEGER);
  348. }
  349. else{
  350. $statement->bindValue(":crystal", 0, SQLITE3_INTEGER);
  351. }
  352. $statement->bindValue(":guild_points", 0, SQLITE3_INTEGER);
  353. $statement->bindValue(":honor_points", 0, SQLITE3_INTEGER);
  354. $statement->bindValue(":helper", 0, SQLITE3_INTEGER);
  355. $statement->bindValue(":score", null, SQLITE3_INTEGER);
  356. $statement->bindValue(":rank", null, SQLITE3_TEXT);
  357. $statement->execute();
  358. // Parse party
  359. $leader = 1;
  360. foreach ($response->{"unit_list"} as $unit){
  361. $statement = $db->prepare("
  362. INSERT INTO run_party
  363. (run, unit, k_unit, leader, front)
  364. VALUES
  365. (:run, :unit, :k_unit, :leader, :front);"
  366. );
  367. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  368. $statement->bindValue(":unit", $unit->{"unit_id"}, SQLITE3_INTEGER);
  369. $statement->bindValue(":k_unit", $unit->{"unit_master_id"}, SQLITE3_INTEGER);
  370. $statement->bindValue(":leader", $leader, SQLITE3_INTEGER);
  371. $leader = 0;
  372. $statement->bindValue(":front", 0, SQLITE3_INTEGER);
  373. $statement->execute();
  374. }
  375. // Return success
  376. return "201 Created.";
  377. }
  378. /**
  379. * Parses the JSONs relateds to a scenario run and saves the data.
  380. *
  381. * @param resource $db Database connection.
  382. * @param int $player_id Player ID.
  383. * @param int $id Run ID.
  384. * @param mixed[] $json List of received JSONs.
  385. */
  386. function log_scenario_run($db, $id, $player_id, $json){
  387. // Only the result request and response JSONs are needed:
  388. $response = $json["result_res"];
  389. if ($json["start_res"] === null){
  390. return ("400 Start response is required to parse scenario runs.");
  391. }
  392. $request = $json["start_res"];
  393. // Prepare the "run" insert.
  394. $statement = $db->prepare("
  395. INSERT INTO run (
  396. player,
  397. id,
  398. dtime,
  399. area_type,
  400. area,
  401. stage,
  402. difficulty,
  403. win,
  404. time,
  405. mana,
  406. energy,
  407. crystal,
  408. guild_points,
  409. honor_points,
  410. helper,
  411. score,
  412. rank
  413. ) VALUES (
  414. :player,
  415. :id,
  416. :dtime,
  417. :area_type,
  418. :area,
  419. :stage,
  420. :difficulty,
  421. :win,
  422. :time,
  423. :mana,
  424. :energy,
  425. :crystal,
  426. :guild_points,
  427. :honor_points,
  428. :helper,
  429. :score,
  430. :rank
  431. );
  432. ");
  433. // Bind data and insert
  434. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  435. $statement->bindValue(":id", $id, SQLITE3_INTEGER);
  436. $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
  437. $statement->bindValue(":area_type", AREA_TYPE_ID::SCENARIO, SQLITE3_INTEGER);
  438. $statement->bindValue(":area", $response->{"scenario_info"}->{"region_id"}, SQLITE3_INTEGER);
  439. $statement->bindValue(":stage", $response->{"scenario_info"}->{"stage_no"}, SQLITE3_INTEGER);
  440. $statement->bindValue(":difficulty", $response->{"scenario_info"}->{"difficulty"}, SQLITE3_INTEGER);
  441. $statement->bindValue(":win", $response->{"win_lose"}, SQLITE3_INTEGER);
  442. $statement->bindValue(":time", $response->{"clear_time"}->{"current_time"}, SQLITE3_INTEGER);
  443. if (array_key_exists("mana", $response->{"reward"})){
  444. $statement->bindValue(":mana", $response->{"reward"}->{"mana"}, SQLITE3_INTEGER);
  445. }
  446. else{
  447. $statement->bindValue(":mana", 0, SQLITE3_INTEGER);
  448. }
  449. if (array_key_exists("energy", $response->{"reward"})){
  450. $statement->bindValue(":energy", $response->{"reward"}->{"energy"}, SQLITE3_INTEGER);
  451. }
  452. else{
  453. $statement->bindValue(":energy", 0, SQLITE3_INTEGER);
  454. }
  455. if (array_key_exists("crystal", $response->{"reward"})){
  456. $statement->bindValue(":crystal", $response->{"reward"}->{"crystal"}, SQLITE3_INTEGER);
  457. }
  458. else{
  459. $statement->bindValue(":crystal", 0, SQLITE3_INTEGER);
  460. }
  461. $statement->bindValue(":guild_points", 0, SQLITE3_INTEGER);
  462. $statement->bindValue(":honor_points", 0, SQLITE3_INTEGER);
  463. if (array_key_exists("helper_unit_list", $request) && sizeof($request->{"helper_unit_list"}) > 0){
  464. $statement->bindValue(":helper", 1, SQLITE3_INTEGER);
  465. }
  466. else{
  467. $statement->bindValue(":helper", 0, SQLITE3_INTEGER);
  468. }
  469. $statement->bindValue(":score", null, SQLITE3_INTEGER);
  470. $statement->bindValue(":rank", null, SQLITE3_TEXT);
  471. $statement->execute();
  472. // Parse various types of reward
  473. if (array_key_exists("crate", $response->{"reward"})){
  474. $crate = $response->{"reward"}->{"crate"};
  475. if (array_key_exists("unit_info", $crate)){
  476. $unit = $crate->{"unit_info"};
  477. $statement = $db->prepare("INSERT INTO run_drop_unit (run, unit) VALUES (:run, :unit);");
  478. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  479. $statement->bindValue(":unit", $unit->{"unit_master_id"}, SQLITE3_INTEGER);
  480. $statement->execute();
  481. }
  482. if (array_key_exists("craft_stuff", $crate)){
  483. $item = $crate->{"craft_stuff"};
  484. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  485. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  486. $statement->bindValue(":item", $item->{"item_master_id"}, SQLITE3_INTEGER);
  487. $statement->bindValue(":amount", $item->{"item_quantity"}, SQLITE3_INTEGER);
  488. $statement->execute();
  489. }
  490. if (array_key_exists("random_scroll", $crate)){
  491. $item = $crate->{"random_scroll"};
  492. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  493. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  494. $statement->bindValue(":item", $item->{"item_master_id"}, SQLITE3_INTEGER);
  495. $statement->bindValue(":amount", $item->{"item_quantity"}, SQLITE3_INTEGER);
  496. $statement->execute();
  497. }
  498. if (array_key_exists("rune", $crate)){
  499. $rune = $crate->{"rune"};
  500. $statement = $db->prepare("
  501. INSERT INTO run_drop_rune (
  502. run,
  503. id,
  504. type,
  505. slot,
  506. stars,
  507. ancient,
  508. quality,
  509. value,
  510. efficiency,
  511. max_efficiency,
  512. main_stat,
  513. main_stat_value,
  514. innate_stat,
  515. innate_stat_value,
  516. substat_1,
  517. substat_1_value,
  518. substat_2,
  519. substat_2_value,
  520. substat_3,
  521. substat_3_value,
  522. substat_4,
  523. substat_4_value
  524. ) VALUES (
  525. :run,
  526. :id,
  527. :type,
  528. :slot,
  529. :stars,
  530. :ancient,
  531. :quality,
  532. :value,
  533. :efficiency,
  534. :max_efficiency,
  535. :main_stat,
  536. :main_stat_value,
  537. :innate_stat,
  538. :innate_stat_value,
  539. :substat_1,
  540. :substat_1_value,
  541. :substat_2,
  542. :substat_2_value,
  543. :substat_3,
  544. :substat_3_value,
  545. :substat_4,
  546. :substat_4_value
  547. );
  548. ");
  549. $statement->bindValue(":run", $id);
  550. $statement->bindValue(":id", $rune->{"rune_id"});
  551. $statement->bindValue(":type", $rune->{"set_id"});
  552. $statement->bindValue(":slot", $rune->{"slot_no"});
  553. $statement->bindValue(":value", $rune->{"sell_value"});
  554. if ($rune->{"class"} > 10){
  555. // Ancient rune
  556. $statement->bindValue(":ancient", 1, SQLITE3_INTEGER);
  557. $statement->bindValue(":stars", intval($rune->{"class"}) - 10, SQLITE3_INTEGER);
  558. $statement->bindValue(":quality", intval($rune->{"rank"}) - 10, SQLITE3_INTEGER);
  559. }
  560. else{
  561. // Non Ancient rune
  562. $statement->bindValue(":ancient", 0, SQLITE3_INTEGER);
  563. $statement->bindValue(":stars", $rune->{"class"}, SQLITE3_INTEGER);
  564. $statement->bindValue(":quality", $rune->{"rank"}, SQLITE3_INTEGER);
  565. }
  566. $efficiency = calculate_efficiency($rune);
  567. $max_efficiency = calculate_maximum_efficiency($rune);
  568. $statement->bindValue(":efficiency", $efficiency, SQLITE3_FLOAT);
  569. $statement->bindValue(":max_efficiency", $max_efficiency, SQLITE3_FLOAT);
  570. $statement->bindValue(":main_stat", $rune->{"pri_eff"}[0], SQLITE3_INTEGER);
  571. $statement->bindValue(":main_stat_value", $rune->{"pri_eff"}[1], SQLITE3_INTEGER);
  572. if ($rune->{"prefix_eff"}[0] > 0){
  573. $statement->bindValue(":innate_stat", $rune->{"prefix_eff"}[0], SQLITE3_INTEGER);
  574. $statement->bindValue(":innate_stat_value", $rune->{"prefix_eff"}[1], SQLITE3_INTEGER);
  575. }
  576. else{
  577. $statement->bindValue(":innate_stat", null, SQLITE3_INTEGER);
  578. $statement->bindValue(":innate_stat_value", 0, SQLITE3_INTEGER);
  579. }
  580. if (sizeof($rune->{"sec_eff"}) > 0){
  581. $statement->bindValue(":substat_1", $rune->{"sec_eff"}[0][0], SQLITE3_INTEGER);
  582. $statement->bindValue(":substat_1_value", $rune->{"sec_eff"}[0][1], SQLITE3_INTEGER);
  583. }
  584. else{
  585. $statement->bindValue(":substat_1", null, SQLITE3_INTEGER);
  586. $statement->bindValue(":substat_1_value", 0, SQLITE3_INTEGER);
  587. }
  588. if (sizeof($rune->{"sec_eff"}) > 1){
  589. $statement->bindValue(":substat_2", $rune->{"sec_eff"}[1][0], SQLITE3_INTEGER);
  590. $statement->bindValue(":substat_2_value", $rune->{"sec_eff"}[1][1], SQLITE3_INTEGER);
  591. }
  592. else{
  593. $statement->bindValue(":substat_2", null, SQLITE3_INTEGER);
  594. $statement->bindValue(":substat_2_value", 0, SQLITE3_INTEGER);
  595. }
  596. if (sizeof($rune->{"sec_eff"}) > 2){
  597. $statement->bindValue(":substat_3", $rune->{"sec_eff"}[2][0], SQLITE3_INTEGER);
  598. $statement->bindValue(":substat_3_value", $rune->{"sec_eff"}[2][1], SQLITE3_INTEGER);
  599. }
  600. else{
  601. $statement->bindValue(":substat_3", null, SQLITE3_INTEGER);
  602. $statement->bindValue(":substat_3_value", 0, SQLITE3_INTEGER);
  603. }
  604. if (sizeof($rune->{"sec_eff"}) > 3){
  605. $statement->bindValue(":substat_4", $rune->{"sec_eff"}[3][0], SQLITE3_INTEGER);
  606. $statement->bindValue(":substat_4_value", $rune->{"sec_eff"}[3][1], SQLITE3_INTEGER);
  607. }
  608. else{
  609. $statement->bindValue(":substat_4", null, SQLITE3_INTEGER);
  610. $statement->bindValue(":substat_4_value", 0, SQLITE3_INTEGER);
  611. }
  612. $statement->execute();
  613. }
  614. }
  615. // Parse party
  616. $leader = 1;
  617. foreach ($response->{"unit_list"} as $unit){
  618. $statement = $db->prepare("
  619. INSERT INTO run_party
  620. (run, unit, k_unit, leader, front)
  621. VALUES
  622. (:run, :unit, :k_unit, :leader, :front);"
  623. );
  624. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  625. $statement->bindValue(":unit", $unit->{"unit_id"}, SQLITE3_INTEGER);
  626. $statement->bindValue(":k_unit", $unit->{"unit_master_id"}, SQLITE3_INTEGER);
  627. $statement->bindValue(":leader", $leader, SQLITE3_INTEGER);
  628. $leader = 0;
  629. $statement->bindValue(":front", 0, SQLITE3_INTEGER);
  630. $statement->execute();
  631. }
  632. // Return success
  633. return "201 Created.";
  634. }
  635. /**
  636. * Parses the JSONs relateds to a cairos run and saves the data.
  637. *
  638. * @param resource $db Database connection.
  639. * @param int $player_id Player ID.
  640. * @param int $id Run ID.
  641. * @param mixed[] $json List of received JSONs.
  642. */
  643. function log_rift_raid_run($db, $id, $player_id, $json){
  644. // Only the start and result requests JSONs are needed:
  645. $result = $json["result_res"];
  646. if ($json["start_res"] === null){
  647. return ("400 Start response is required to parse Rift Raid runs.");
  648. }
  649. $start = $json["start_res"];
  650. // Prepare the "run" insert.
  651. $statement = $db->prepare("
  652. INSERT INTO run (
  653. player,
  654. id,
  655. dtime,
  656. area_type,
  657. area,
  658. stage,
  659. difficulty,
  660. win,
  661. time,
  662. mana,
  663. energy,
  664. crystal,
  665. guild_points,
  666. honor_points,
  667. helper,
  668. score,
  669. rank
  670. ) VALUES (
  671. :player,
  672. :id,
  673. :dtime,
  674. :area_type,
  675. :area,
  676. :stage,
  677. :difficulty,
  678. :win,
  679. :time,
  680. :mana,
  681. :energy,
  682. :crystal,
  683. :guild_points,
  684. :honor_points,
  685. :helper,
  686. :score,
  687. :rank
  688. );
  689. ");
  690. // Bind data and insert
  691. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  692. $statement->bindValue(":id", $id, SQLITE3_INTEGER);
  693. $statement->bindValue(":dtime", $result->{"tvaluelocal"}, SQLITE3_TEXT);
  694. $statement->bindValue(":area_type", AREA_TYPE_ID::RIFT_RAID, SQLITE3_INTEGER);
  695. $statement->bindValue(":area", AREA_TYPE_ID::RIFT_RAID, SQLITE3_INTEGER);
  696. $statement->bindValue(":stage", $start->{"battle_info"}->{"stage_id"}, SQLITE3_INTEGER);
  697. $statement->bindValue(":difficulty", null, SQLITE3_INTEGER);
  698. $statement->bindValue(":win", $result->{"win_lose"}, SQLITE3_INTEGER);
  699. if ($result->{"win_lose"} == 1){
  700. $statement->bindValue(":time", $result->{"clear_time"}->{"current_time"}, SQLITE3_TEXT);
  701. }
  702. else{
  703. $statement->bindValue(":time", 1, SQLITE3_INTEGER);
  704. }
  705. $statement->bindValue(":mana", 0, SQLITE3_INTEGER); // If reward is mana, i will be updated later
  706. $statement->bindValue(":energy", 0, SQLITE3_INTEGER);
  707. $statement->bindValue(":crystal", 0, SQLITE3_INTEGER);
  708. $statement->bindValue(":guild_points", 0, SQLITE3_INTEGER);
  709. $statement->bindValue(":honor_points", 0, SQLITE3_INTEGER);
  710. $statement->bindValue(":helper", 0, SQLITE3_INTEGER);
  711. $statement->bindValue(":score", null, SQLITE3_INTEGER);
  712. $statement->bindValue(":rank", null, SQLITE3_TEXT);
  713. $statement->execute();
  714. // Parse various types of reward
  715. if ($result->{"win_lose"} == 1 && array_key_exists("battle_reward_list", $result)){
  716. foreach ($result->{"battle_reward_list"} as $reward_list){
  717. if ($reward_list->{"wizard_id"} == $player_id){
  718. $reward = $reward_list->{"reward_list"}[0];
  719. $reward_type = $reward->{"item_master_type"};
  720. switch ($reward_type){
  721. case INVENTORY_TYPE_ID::MONSTER: // Unit
  722. $statement = $db->prepare("INSERT INTO run_drop_unit (run, unit) VALUES (:run, :unit);");
  723. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  724. $statement->bindValue(":unit", $reward->{"item_master_id"}, SQLITE3_INTEGER);
  725. $statement->execute();
  726. break;
  727. case INVENTORY_TYPE_ID::SCROLL:
  728. case INVENTORY_TYPE_ID::ESSENCES:
  729. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  730. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  731. $statement->bindValue(":item", $reward->{"item_master_id"}, SQLITE3_INTEGER);
  732. $statement->bindValue(":amount", $reward->{"item_quantity"}, SQLITE3_INTEGER);
  733. $statement->execute();
  734. break;
  735. case INVENTORY_TYPE_ID::ENCHANTMENT:
  736. $statement = $db->prepare("
  737. INSERT INTO run_drop_enchantment (run, id, type, quality, rune, stat, value)
  738. VALUES (:run, :id, :type, :quality, :rune, :stat, :value);
  739. ");
  740. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  741. $statement->bindValue(":id", $reward->{"runecraft_item_id"}, SQLITE3_INTEGER);
  742. $statement->bindValue(":type", $reward->{"runecraft_type"}, SQLITE3_INTEGER);
  743. $statement->bindValue(":quality", $reward->{"runecraft_rank"}, SQLITE3_INTEGER);
  744. $statement->bindValue(":rune", $reward->{"runecraft_set_id"}, SQLITE3_INTEGER);
  745. $statement->bindValue(":stat", $reward->{"runecraft_effect_id"}, SQLITE3_INTEGER);
  746. $statement->bindValue(":value", 0, SQLITE3_INTEGER);
  747. $statement->execute();
  748. break;
  749. case 102: //: Mana
  750. $statement = $db->prepare("UPDATE run SET mana = :mana WHERE run = :run;");
  751. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  752. $statement->bindValue(":id", $reward->{"runecraft_item_id"}, SQLITE3_INTEGER);
  753. $statement->execute();
  754. break;
  755. }
  756. }
  757. }
  758. }
  759. // Parse party
  760. foreach ($start->{"battle_info"}->{"user_list"} as $user){
  761. if ($user->{"wizard_id"} == $player_id){
  762. foreach ($user->{"deck_list"} as $unit){
  763. $statement = $db->prepare("
  764. INSERT INTO run_party
  765. (run, unit, k_unit, leader, front)
  766. VALUES
  767. (:run, :unit, :k_unit, :leader, :front);"
  768. );
  769. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  770. $statement->bindValue(":unit", $unit->{"unit_info"}->{"unit_id"}, SQLITE3_INTEGER);
  771. $statement->bindValue(":k_unit", $unit->{"unit_info"}->{"unit_master_id"}, SQLITE3_INTEGER);
  772. $statement->bindValue(":leader", $unit->{"leader"}, SQLITE3_INTEGER);
  773. if (intval($unit->{"index"}) <= 4){
  774. $statement->bindValue(":front", 1, SQLITE3_INTEGER);
  775. }
  776. else{
  777. $statement->bindValue(":front", 0, SQLITE3_INTEGER);
  778. }
  779. $statement->execute();
  780. }
  781. }
  782. }
  783. // Return success
  784. return "201 Created.";
  785. }
  786. /**
  787. * Parses the JSONs relateds to a cairos run and saves the data.
  788. *
  789. * @param resource $db Database connection.
  790. * @param int $player_id Player ID.
  791. * @param int $id Run ID.
  792. * @param mixed[] $json List of received JSONs.
  793. */
  794. function log_cairos_run($db, $id, $player_id, $json){
  795. // Only the result request and response JSONs are needed:
  796. $response = $json["result_res"];
  797. if ($json["result_req"] === null){
  798. return ("400 Result request is required to parse Cairos runs.");
  799. }
  800. $request = $json["result_req"];
  801. // Prepare the "run" insert.
  802. $statement = $db->prepare("
  803. INSERT INTO run (
  804. player,
  805. id,
  806. dtime,
  807. area_type,
  808. area,
  809. stage,
  810. difficulty,
  811. win,
  812. time,
  813. mana,
  814. energy,
  815. crystal,
  816. guild_points,
  817. honor_points,
  818. helper,
  819. score,
  820. rank
  821. ) VALUES (
  822. :player,
  823. :id,
  824. :dtime,
  825. :area_type,
  826. :area,
  827. :stage,
  828. :difficulty,
  829. :win,
  830. :time,
  831. :mana,
  832. :energy,
  833. :crystal,
  834. :guild_points,
  835. :honor_points,
  836. :helper,
  837. :score,
  838. :rank
  839. );
  840. ");
  841. // Bind data and insert
  842. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  843. $statement->bindValue(":id", $id, SQLITE3_INTEGER);
  844. $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
  845. $statement->bindValue(":area_type", AREA_TYPE_ID::CAIROS_DUNGEON, SQLITE3_INTEGER);
  846. $statement->bindValue(":area", $request->{"dungeon_id"}, SQLITE3_INTEGER);
  847. $statement->bindValue(":stage", $request->{"stage_id"}, SQLITE3_INTEGER);
  848. $statement->bindValue(":difficulty", null, SQLITE3_INTEGER);
  849. $statement->bindValue(":win", $response->{"win_lose"}, SQLITE3_INTEGER);
  850. $statement->bindValue(":time", $response->{"clear_time"}->{"current_time"}, SQLITE3_INTEGER);
  851. if (array_key_exists("mana", $response->{"reward"})){
  852. $statement->bindValue(":mana", $response->{"reward"}->{"mana"}, SQLITE3_INTEGER);
  853. }
  854. else{
  855. $statement->bindValue(":mana", 0, SQLITE3_INTEGER);
  856. }
  857. if (array_key_exists("energy", $response->{"reward"})){
  858. $statement->bindValue(":energy", $response->{"reward"}->{"energy"}, SQLITE3_INTEGER);
  859. }
  860. else{
  861. $statement->bindValue(":energy", 0, SQLITE3_INTEGER);
  862. }
  863. if (array_key_exists("crystal", $response->{"reward"})){
  864. $statement->bindValue(":crystal", $response->{"reward"}->{"crystal"}, SQLITE3_INTEGER);
  865. }
  866. else{
  867. $statement->bindValue(":crystal", 0, SQLITE3_INTEGER);
  868. }
  869. $statement->bindValue(":guild_points", 0, SQLITE3_INTEGER);
  870. $statement->bindValue(":honor_points", 0, SQLITE3_INTEGER);
  871. $statement->bindValue(":helper", 0, SQLITE3_INTEGER); // TODO Where is this information??
  872. $statement->bindValue(":score", null, SQLITE3_INTEGER);
  873. $statement->bindValue(":rank", null, SQLITE3_TEXT);
  874. $statement->execute();
  875. // Parse various types of reward
  876. if (array_key_exists("changed_item_list", $response)){
  877. $reward_type = $response->{"changed_item_list"}[0]->{"type"};
  878. switch ($reward_type){
  879. case INVENTORY_TYPE_ID::MONSTER: // Unit
  880. $statement = $db->prepare("INSERT INTO run_drop_unit (run, unit) VALUES (:run, :unit);");
  881. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  882. $statement->bindValue(":unit", $response->{"changed_item_list"}[0]->{"view"}->{"item_master_id"}, SQLITE3_INTEGER);
  883. $statement->execute();
  884. break;
  885. case INVENTORY_TYPE_ID::SCROLL:
  886. case INVENTORY_TYPE_ID::ESSENCES:
  887. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  888. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  889. $statement->bindValue(":item", $response->{"changed_item_list"}[0]->{"view"}->{"item_master_id"}, SQLITE3_INTEGER);
  890. $statement->bindValue(":amount", $response->{"changed_item_list"}[0]->{"view"}->{"item_quantity"}, SQLITE3_INTEGER);
  891. $statement->execute();
  892. break;
  893. case INVENTORY_TYPE_ID::RUNE:
  894. $rune = $response->{"changed_item_list"}[0]->{"info"};
  895. $statement = $db->prepare("
  896. INSERT INTO run_drop_rune (
  897. run,
  898. id,
  899. type,
  900. slot,
  901. stars,
  902. ancient,
  903. quality,
  904. value,
  905. efficiency,
  906. max_efficiency,
  907. main_stat,
  908. main_stat_value,
  909. innate_stat,
  910. innate_stat_value,
  911. substat_1,
  912. substat_1_value,
  913. substat_2,
  914. substat_2_value,
  915. substat_3,
  916. substat_3_value,
  917. substat_4,
  918. substat_4_value
  919. ) VALUES (
  920. :run,
  921. :id,
  922. :type,
  923. :slot,
  924. :stars,
  925. :ancient,
  926. :quality,
  927. :value,
  928. :efficiency,
  929. :max_efficiency,
  930. :main_stat,
  931. :main_stat_value,
  932. :innate_stat,
  933. :innate_stat_value,
  934. :substat_1,
  935. :substat_1_value,
  936. :substat_2,
  937. :substat_2_value,
  938. :substat_3,
  939. :substat_3_value,
  940. :substat_4,
  941. :substat_4_value
  942. );
  943. ");
  944. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  945. $statement->bindValue(":id", $rune->{"rune_id"}, SQLITE3_INTEGER);
  946. $statement->bindValue(":type", $rune->{"set_id"}, SQLITE3_INTEGER);
  947. $statement->bindValue(":slot", $rune->{"slot_no"}, SQLITE3_INTEGER);
  948. $statement->bindValue(":value", $rune->{"sell_value"}, SQLITE3_INTEGER);
  949. if ($rune->{"class"} > 10){
  950. // Ancient rune
  951. $statement->bindValue(":ancient", 1, SQLITE3_INTEGER);
  952. $statement->bindValue(":stars", intval($rune->{"class"}) - 10, SQLITE3_INTEGER);
  953. $statement->bindValue(":quality", intval($rune->{"rank"}) - 10, SQLITE3_INTEGER);
  954. }
  955. else{
  956. // Non Ancient rune
  957. $statement->bindValue(":ancient", 0, SQLITE3_INTEGER);
  958. $statement->bindValue(":stars", $rune->{"class"}, SQLITE3_INTEGER);
  959. $statement->bindValue(":quality", $rune->{"rank"}, SQLITE3_INTEGER);
  960. }
  961. $efficiency = calculate_efficiency($rune);
  962. $max_efficiency = calculate_maximum_efficiency($rune);
  963. $statement->bindValue(":efficiency", $efficiency, SQLITE3_FLOAT);
  964. $statement->bindValue(":max_efficiency", $max_efficiency, SQLITE3_FLOAT);
  965. $statement->bindValue(":main_stat", $rune->{"pri_eff"}[0], SQLITE3_INTEGER);
  966. $statement->bindValue(":main_stat_value", $rune->{"pri_eff"}[1], SQLITE3_INTEGER);
  967. if ($rune->{"prefix_eff"}[0] > 0){
  968. $statement->bindValue(":innate_stat", $rune->{"prefix_eff"}[0], SQLITE3_INTEGER);
  969. $statement->bindValue(":innate_stat_value", $rune->{"prefix_eff"}[1], SQLITE3_INTEGER);
  970. }
  971. else{
  972. $statement->bindValue(":innate_stat", null, SQLITE3_INTEGER);
  973. $statement->bindValue(":innate_stat_value", 0, SQLITE3_INTEGER);
  974. }
  975. if (sizeof($rune->{"sec_eff"}) > 0){
  976. $statement->bindValue(":substat_1", $rune->{"sec_eff"}[0][0], SQLITE3_INTEGER);
  977. $statement->bindValue(":substat_1_value", $rune->{"sec_eff"}[0][1], SQLITE3_INTEGER);
  978. }
  979. else{
  980. $statement->bindValue(":substat_1", null, SQLITE3_INTEGER);
  981. $statement->bindValue(":substat_1_value", 0, SQLITE3_INTEGER);
  982. }
  983. if (sizeof($rune->{"sec_eff"}) > 1){
  984. $statement->bindValue(":substat_2", $rune->{"sec_eff"}[1][0]);
  985. $statement->bindValue(":substat_2_value", $rune->{"sec_eff"}[1][1]);
  986. }
  987. else{
  988. $statement->bindValue(":substat_2", null, SQLITE3_INTEGER);
  989. $statement->bindValue(":substat_2_value", 0, SQLITE3_INTEGER);
  990. }
  991. if (sizeof($rune->{"sec_eff"}) > 2){
  992. $statement->bindValue(":substat_3", $rune->{"sec_eff"}[2][0], SQLITE3_INTEGER);
  993. $statement->bindValue(":substat_3_value", $rune->{"sec_eff"}[2][1], SQLITE3_INTEGER);
  994. }
  995. else{
  996. $statement->bindValue(":substat_3", null, SQLITE3_INTEGER);
  997. $statement->bindValue(":substat_3_value", 0, SQLITE3_INTEGER);
  998. }
  999. if (sizeof($rune->{"sec_eff"}) > 3){
  1000. $statement->bindValue(":substat_4", $rune->{"sec_eff"}[3][0], SQLITE3_INTEGER);
  1001. $statement->bindValue(":substat_4_value", $rune->{"sec_eff"}[3][1], SQLITE3_INTEGER);
  1002. }
  1003. else{
  1004. $statement->bindValue(":substat_4", null, SQLITE3_INTEGER);
  1005. $statement->bindValue(":substat_4_value", 0, SQLITE3_INTEGER);
  1006. }
  1007. $statement->execute();
  1008. break;
  1009. }
  1010. }
  1011. // Parse party
  1012. $leader = 1;
  1013. foreach ($response->{"unit_list"} as $unit){
  1014. $statement = $db->prepare("
  1015. INSERT INTO run_party
  1016. (run, unit, k_unit, leader, front)
  1017. VALUES
  1018. (:run, :unit, :k_unit, :leader, :front);"
  1019. );
  1020. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  1021. $statement->bindValue(":unit", $unit->{"unit_id"}, SQLITE3_INTEGER);
  1022. $statement->bindValue(":k_unit", $unit->{"unit_master_id"}, SQLITE3_INTEGER);
  1023. $statement->bindValue(":leader", $leader, SQLITE3_INTEGER);
  1024. $leader = 0;
  1025. $statement->bindValue(":front", 0, SQLITE3_INTEGER);
  1026. $statement->execute();
  1027. }
  1028. // Return success
  1029. return "201 Created.";
  1030. }
  1031. /**
  1032. * Parses the JSONs relateds to a Dimension Hole run and saves the data.
  1033. *
  1034. * @param resource $db Database connection.
  1035. * @param int $player_id Player ID.
  1036. * @param int $id Run ID.
  1037. * @param mixed[] $json List of received JSONs.
  1038. */
  1039. function log_dimension_hole_run($db, $id, $player_id, $json){
  1040. // Only the result request and response JSONs are needed:
  1041. $response = $json["result_res"];
  1042. if ($json["result_req"] === null){
  1043. return ("400 Result request is required to parse Dimension Hole runs.");
  1044. }
  1045. // Prepare the "run" insert.
  1046. $statement = $db->prepare("
  1047. INSERT INTO run (
  1048. player,
  1049. id,
  1050. dtime,
  1051. area_type,
  1052. area,
  1053. stage,
  1054. difficulty,
  1055. win,
  1056. time,
  1057. mana,
  1058. energy,
  1059. crystal,
  1060. guild_points,
  1061. honor_points,
  1062. helper,
  1063. score,
  1064. rank
  1065. ) VALUES (
  1066. :player,
  1067. :id,
  1068. :dtime,
  1069. :area_type,
  1070. :area,
  1071. :stage,
  1072. :difficulty,
  1073. :win,
  1074. :time,
  1075. :mana,
  1076. :energy,
  1077. :crystal,
  1078. :guild_points,
  1079. :honor_points,
  1080. :helper,
  1081. :score,
  1082. :rank
  1083. );
  1084. ");
  1085. // Bind data and insert
  1086. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  1087. $statement->bindValue(":id", $id, SQLITE3_INTEGER);
  1088. $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
  1089. $statement->bindValue(":area_type", AREA_TYPE_ID::DIMENSIONAL_HOLE, SQLITE3_INTEGER);
  1090. $statement->bindValue(":area", $response->{"dungeon_id"}, SQLITE3_INTEGER);
  1091. $statement->bindValue(":stage", $response->{"difficulty"}, SQLITE3_INTEGER); // Difficulty is stage
  1092. $statement->bindValue(":difficulty", null, SQLITE3_INTEGER);
  1093. $statement->bindValue(":win", $response->{"win_lose"}, SQLITE3_INTEGER);
  1094. $statement->bindValue(":time", $response->{"clear_time"}->{"current_time"}, SQLITE3_INTEGER);
  1095. if (array_key_exists("mana", $response->{"reward"})){
  1096. $statement->bindValue(":mana", $response->{"reward"}->{"mana"}, SQLITE3_INTEGER);
  1097. }
  1098. else{
  1099. $statement->bindValue(":mana", 0, SQLITE3_INTEGER);
  1100. }
  1101. if (array_key_exists("energy", $response->{"reward"})){
  1102. $statement->bindValue(":energy", $response->{"reward"}->{"energy"}, SQLITE3_INTEGER);
  1103. }
  1104. $statement->bindValue(":energy", 0, SQLITE3_INTEGER);
  1105. if (array_key_exists("crystal", $response->{"reward"})){
  1106. $statement->bindValue(":crystal", $response->{"reward"}->{"crystal"}, SQLITE3_INTEGER);
  1107. }
  1108. else{
  1109. $statement->bindValue(":crystal", 0, SQLITE3_INTEGER);
  1110. }
  1111. $statement->bindValue(":guild_points", 0, SQLITE3_INTEGER);
  1112. $statement->bindValue(":honor_points", 0, SQLITE3_INTEGER);
  1113. $statement->bindValue(":helper", 0, SQLITE3_INTEGER); // TODO Where is this information??
  1114. $statement->bindValue(":score", null, SQLITE3_INTEGER);
  1115. $statement->bindValue(":rank", null, SQLITE3_TEXT);
  1116. $statement->execute();
  1117. // Parse various types of reward
  1118. if (array_key_exists("changed_item_list", $response)){
  1119. foreach ($response->{"changed_item_list"} as $drop){
  1120. $reward_type = $drop->{"type"};
  1121. switch ($reward_type){
  1122. case INVENTORY_TYPE_ID::CRAFT_STUFF:
  1123. $statement = $db->prepare("INSERT INTO run_drop_item (run, item, amount) VALUES (:run, :item, :amount);");
  1124. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  1125. $statement->bindValue(":item", $drop->{"view"}->{"item_master_id"}, SQLITE3_INTEGER);
  1126. $statement->bindValue(":amount", $drop->{"view"}->{"item_quantity"}, SQLITE3_INTEGER);
  1127. $statement->execute();
  1128. break;
  1129. case INVENTORY_TYPE_ID::RUNE:
  1130. // TODO: Investigate with no awaken dungeons
  1131. /*$rune = $response->{"changed_item_list"}[0]->{"info"};
  1132. $statement = $db->prepare("
  1133. INSERT INTO run_drop_rune (
  1134. run,
  1135. id,
  1136. type,
  1137. slot,
  1138. stars,
  1139. ancient,
  1140. quality,
  1141. value,
  1142. efficiency,
  1143. max_efficiency,
  1144. main_stat,
  1145. main_stat_value,
  1146. innate_stat,
  1147. innate_stat_value,
  1148. substat_1,
  1149. substat_1_value,
  1150. substat_2,
  1151. substat_2_value,
  1152. substat_3,
  1153. substat_3_value,
  1154. substat_4,
  1155. substat_4_value
  1156. ) VALUES (
  1157. :run,
  1158. :id,
  1159. :type,
  1160. :slot,
  1161. :stars,
  1162. :ancient,
  1163. :quality,
  1164. :value,
  1165. :efficiency,
  1166. :max_efficiency,
  1167. :main_stat,
  1168. :main_stat_value,
  1169. :innate_stat,
  1170. :innate_stat_value,
  1171. :substat_1,
  1172. :substat_1_value,
  1173. :substat_2,
  1174. :substat_2_value,
  1175. :substat_3,
  1176. :substat_3_value,
  1177. :substat_4,
  1178. :substat_4_value
  1179. );
  1180. ");
  1181. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  1182. $statement->bindValue(":id", $rune->{"rune_id"}, SQLITE3_INTEGER);
  1183. $statement->bindValue(":type", $rune->{"set_id"}, SQLITE3_INTEGER);
  1184. $statement->bindValue(":slot", $rune->{"slot_no"}, SQLITE3_INTEGER);
  1185. $statement->bindValue(":value", $rune->{"sell_value"}, SQLITE3_INTEGER);
  1186. if ($rune->{"class"} > 10){
  1187. // Ancient rune
  1188. $statement->bindValue(":ancient", 1, SQLITE3_INTEGER);
  1189. $statement->bindValue(":stars", intval($rune->{"class"}) - 10, SQLITE3_INTEGER);
  1190. $statement->bindValue(":quality", intval($rune->{"rank"}) - 10, SQLITE3_INTEGER);
  1191. }
  1192. else{
  1193. // Non Ancient rune
  1194. $statement->bindValue(":ancient", 0, SQLITE3_INTEGER);
  1195. $statement->bindValue(":stars", $rune->{"class"}, SQLITE3_INTEGER);
  1196. $statement->bindValue(":quality", $rune->{"rank"}, SQLITE3_INTEGER);
  1197. }
  1198. $efficiency = calculate_efficiency($rune);
  1199. $max_efficiency = calculate_maximum_efficiency($rune);
  1200. $statement->bindValue(":efficiency", $efficiency, SQLITE3_FLOAT);
  1201. $statement->bindValue(":max_efficiency", $max_efficiency, SQLITE3_FLOAT);
  1202. $statement->bindValue(":main_stat", $rune->{"pri_eff"}[0], SQLITE3_INTEGER);
  1203. $statement->bindValue(":main_stat_value", $rune->{"pri_eff"}[1], SQLITE3_INTEGER);
  1204. if ($rune->{"prefix_eff"}[0] > 0){
  1205. $statement->bindValue(":innate_stat", $rune->{"prefix_eff"}[0], SQLITE3_INTEGER);
  1206. $statement->bindValue(":innate_stat_value", $rune->{"prefix_eff"}[1], SQLITE3_INTEGER);
  1207. }
  1208. else{
  1209. $statement->bindValue(":innate_stat", null, SQLITE3_INTEGER);
  1210. $statement->bindValue(":innate_stat_value", 0, SQLITE3_INTEGER);
  1211. }
  1212. if (sizeof($rune->{"sec_eff"}) > 0){
  1213. $statement->bindValue(":substat_1", $rune->{"sec_eff"}[0][0], SQLITE3_INTEGER);
  1214. $statement->bindValue(":substat_1_value", $rune->{"sec_eff"}[0][1], SQLITE3_INTEGER);
  1215. }
  1216. else{
  1217. $statement->bindValue(":substat_1", null, SQLITE3_INTEGER);
  1218. $statement->bindValue(":substat_1_value", 0, SQLITE3_INTEGER);
  1219. }
  1220. if (sizeof($rune->{"sec_eff"}) > 1){
  1221. $statement->bindValue(":substat_2", $rune->{"sec_eff"}[1][0], SQLITE3_INTEGER);
  1222. $statement->bindValue(":substat_2_value", $rune->{"sec_eff"}[1][1], SQLITE3_INTEGER);
  1223. }
  1224. else{
  1225. $statement->bindValue(":substat_2", null, SQLITE3_INTEGER);
  1226. $statement->bindValue(":substat_2_value", 0, SQLITE3_INTEGER);
  1227. }
  1228. if (sizeof($rune->{"sec_eff"}) > 2){
  1229. $statement->bindValue(":substat_3", $rune->{"sec_eff"}[2][0], SQLITE3_INTEGER);
  1230. $statement->bindValue(":substat_3_value", $rune->{"sec_eff"}[2][1], SQLITE3_INTEGER);
  1231. }
  1232. else{
  1233. $statement->bindValue(":substat_3", null, SQLITE3_INTEGER);
  1234. $statement->bindValue(":substat_3_value", 0, SQLITE3_INTEGER);
  1235. }
  1236. if (sizeof($rune->{"sec_eff"}) > 3){
  1237. $statement->bindValue(":substat_4", $rune->{"sec_eff"}[3][0], SQLITE3_INTEGER);
  1238. $statement->bindValue(":substat_4_value", $rune->{"sec_eff"}[3][1], SQLITE3_INTEGER);
  1239. }
  1240. else{
  1241. $statement->bindValue(":substat_4", null, SQLITE3_INTEGER);
  1242. $statement->bindValue(":substat_4_value", 0, SQLITE3_INTEGER);
  1243. }
  1244. $statement->execute();*/
  1245. break;
  1246. }
  1247. }
  1248. }
  1249. // Parse party
  1250. $leader = 1;
  1251. foreach ($response->{"unit_list"} as $unit){
  1252. $statement = $db->prepare("
  1253. INSERT INTO run_party
  1254. (run, unit, k_unit, leader, front)
  1255. VALUES
  1256. (:run, :unit, :k_unit, :leader, :front);"
  1257. );
  1258. $statement->bindValue(":run", $id, SQLITE3_INTEGER);
  1259. $statement->bindValue(":unit", $unit->{"unit_id"}, SQLITE3_INTEGER);
  1260. $statement->bindValue(":k_unit", $unit->{"unit_master_id"}, SQLITE3_INTEGER);
  1261. $statement->bindValue(":leader", $leader, SQLITE3_INTEGER);
  1262. $leader = 0;
  1263. $statement->bindValue(":front", 0, SQLITE3_INTEGER);
  1264. $statement->execute();
  1265. }
  1266. // Return success
  1267. return "201 Created.";
  1268. }
  1269. global $db;
  1270. try{
  1271. header("Content-type: application/json; charset=utf-8");
  1272. // Get put data
  1273. parse_str(file_get_contents("php://input"), $_POST);
  1274. // Check API key.
  1275. if (!array_key_exists("key", $_POST)){
  1276. header("HTTP/1.1 400 API key not received.");
  1277. syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
  1278. return 400;
  1279. }
  1280. $key = $_POST["key"];
  1281. // Get all JSON files
  1282. $json = [
  1283. "start_req" => null,
  1284. "start_res" => null,
  1285. "result_req" => null,
  1286. "result_res" => null,
  1287. ];
  1288. // Result response - mandatory
  1289. if (!array_key_exists("result_response", $_POST)){
  1290. header("HTTP/1.1 400 No result response data received.");
  1291. syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 No result response data received.");
  1292. return 400;
  1293. }
  1294. $data_json = json_decode($_POST["result_response"]);
  1295. if ($data_json === null){
  1296. header("HTTP/1.1 400 Result response data is no valid JSON.");
  1297. syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Result response data is no valid JSON.");
  1298. return 400;
  1299. }
  1300. $json["result_res"] = $data_json;
  1301. // Result request - optional
  1302. if (array_key_exists("result_request", $_POST)){
  1303. $data_raw = $_POST["result_request"];
  1304. if ($data_raw != null && $data_raw != false){
  1305. $data_json = json_decode($data_raw);
  1306. if ($data_json != null){
  1307. $json["result_req"] = $data_json;
  1308. }
  1309. }
  1310. }
  1311. // Start result - optional
  1312. if (array_key_exists("start_response", $_POST)){
  1313. $data_raw = $_POST["start_response"];
  1314. if ($data_raw != null && $data_raw != false){
  1315. $data_json = json_decode($data_raw);
  1316. if ($data_json != null){
  1317. $json["start_res"] = $data_json;
  1318. }
  1319. }
  1320. }
  1321. // Start result - optional
  1322. if (array_key_exists("start_request", $_POST)){
  1323. $data_raw = $_POST["start_request"];
  1324. if ($data_raw != null && $data_raw != false){
  1325. $data_json = json_decode($data_raw);
  1326. if ($data_json != null){
  1327. $json["start_req"] = $data_json;
  1328. }
  1329. }
  1330. }
  1331. // Extract basic data
  1332. $player_id = $json["result_res"]->{"wizard_info"}->{"wizard_id"};
  1333. $command = $json["result_res"]->{"command"};
  1334. // Authenticate
  1335. // TODO: Table user
  1336. $statement = $db->prepare("SELECT COUNT(id) AS c FROM data.player WHERE id = :player AND api_key = :api_key;");
  1337. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  1338. $statement->bindValue(":api_key", $key, SQLITE3_TEXT);
  1339. if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
  1340. header("HTTP/1.1 401 Invalid credentials.");
  1341. syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
  1342. return 401;
  1343. }
  1344. // Check for implemented command
  1345. $accepted_commands = [
  1346. "BattleDungeonResult_V2", // Dungeon Run
  1347. "BattleDimensionHoleDungeonResult_v2", // Dimension Hole Run
  1348. "BattleRiftOfWorldsRaidResult", // Rift Raid Run
  1349. "BattleScenarioResult", // Scenario Run
  1350. "BattleArenaResult", // Arena Run
  1351. "BattleDarkPortalResult" // Dimensinal Rift Run
  1352. ];
  1353. if (!in_array($command, $accepted_commands)){
  1354. header("HTTP/1.1 405 Command not implemented.");
  1355. syslog(LOG_INFO, "[APIv1] HTTP/1.1 405 Command not implemented.");
  1356. return 405;
  1357. }
  1358. // Check if already in DB
  1359. $dtime = $json["result_res"]->{"tvaluelocal"};
  1360. $statement = $db->prepare("SELECT count(id) AS c FROM run WHERE player = :player AND dtime = :dtime;");
  1361. $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
  1362. $statement->bindValue(":dtime", $dtime, SQLITE3_TEXT);
  1363. if (0 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
  1364. header("HTTP/1.1 409 Run already in database.");
  1365. syslog(LOG_INFO, "[APIv1] HTTP/1.1 409 Run already in database.");
  1366. return 409;
  1367. }
  1368. // Get new ID
  1369. $q = $db->query("SELECT max(id) + 1 AS id FROM run;");
  1370. $r = $q->fetchArray(SQLITE3_ASSOC);
  1371. if ($r){
  1372. $id = $r["id"];
  1373. }
  1374. else{
  1375. $id = 1;
  1376. }
  1377. // Run parsing function
  1378. $result = "500 Unknown Error";
  1379. switch($command){
  1380. case "BattleDungeonResult_V2":
  1381. $result = log_cairos_run($db, $id, $player_id, $json);
  1382. break;
  1383. case "BattleDimensionHoleDungeonResult_v2":
  1384. $result = log_dimension_hole_run($db, $id, $player_id, $json);
  1385. break;
  1386. case "BattleRiftOfWorldsRaidResult":
  1387. $result = log_rift_raid_run($db, $id, $player_id, $json);
  1388. break;
  1389. case "BattleScenarioResult":
  1390. $result = log_scenario_run($db, $id, $player_id, $json);
  1391. break;
  1392. case "BattleArenaResult":
  1393. $result = log_arena_run($db, $id, $player_id, $json);
  1394. break;
  1395. case "BattleDarkPortalResult":
  1396. $result = log_dark_portal_run($db, $id, $player_id, $json);
  1397. break;
  1398. }
  1399. // Process result
  1400. $status_code = intval(substr($result, 0, 3));
  1401. $status_message = substr($result, 4);
  1402. if ($status_code == 0 || $status_code < 100 || $status_code > 599){
  1403. header("HTTP/1.1 500 Unknown error.");
  1404. syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unknown error.");
  1405. return 500;
  1406. }
  1407. else{
  1408. header("HTTP/1.1 $status_code $status_message");
  1409. syslog(LOG_INFO, "[APIv1] HTTP/1.1 $status_code $status_message");
  1410. return $status_code;
  1411. }
  1412. }
  1413. catch(Exception $e) {
  1414. header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
  1415. syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
  1416. return 500;
  1417. }
  1418. ?>