POST.php 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469
  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 $uid Player UID.
  167. * @param int $id Run ID.
  168. * @param mixed[] $json List of received JSONs.
  169. */
  170. function log_arena_run($db, $id, $uid, $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. uid,
  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. :uid,
  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(":uid", $uid, 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 $uid Player UID.
  277. * @param int $id Run ID.
  278. * @param mixed[] $json List of received JSONs.
  279. */
  280. function log_dark_portal_run($db, $id, $uid, $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. uid,
  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. :uid,
  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(":uid", $uid, 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 $uid Player UID.
  383. * @param int $id Run ID.
  384. * @param mixed[] $json List of received JSONs.
  385. */
  386. function log_scenario_run($db, $id, $uid, $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. uid,
  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. :uid,
  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(":uid", $uid, 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 $uid Player UID.
  640. * @param int $id Run ID.
  641. * @param mixed[] $json List of received JSONs.
  642. */
  643. function log_rift_raid_run($db, $id, $uid, $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. uid,
  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. :uid,
  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(":uid", $uid, 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"} == $uid){
  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"} == $uid){
  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 $uid Player UID.
  791. * @param int $id Run ID.
  792. * @param mixed[] $json List of received JSONs.
  793. */
  794. function log_cairos_run($db, $id, $uid, $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. uid,
  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. :uid,
  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(":uid", $uid, 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 $uid Player UID.
  1036. * @param int $id Run ID.
  1037. * @param mixed[] $json List of received JSONs.
  1038. */
  1039. function log_dimension_hole_run($db, $id, $uid, $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. uid,
  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. :uid,
  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(":uid", $uid, 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, "[APIv3] 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, "[APIv3] 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, "[APIv3] 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. $uid = $json["result_res"]->{"wizard_info"}->{"wizard_id"};
  1333. $command = $json["result_res"]->{"command"};
  1334. // Authenticate
  1335. $statement = $db->prepare("SELECT COUNT(uid) AS c FROM player WHERE uid = :uid AND api_key = :api_key;");
  1336. $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
  1337. $statement->bindValue(":api_key", $key, SQLITE3_TEXT);
  1338. if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
  1339. header("HTTP/1.1 401 Invalid credentials.");
  1340. syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
  1341. return 401;
  1342. }
  1343. // Check for implemented command
  1344. $accepted_commands = [
  1345. "BattleDungeonResult_V2", // Dungeon Run
  1346. "BattleDimensionHoleDungeonResult_v2", // Dimension Hole Run
  1347. "BattleRiftOfWorldsRaidResult", // Rift Raid Run
  1348. "BattleScenarioResult", // Scenario Run
  1349. "BattleArenaResult", // Arena Run
  1350. "BattleDarkPortalResult" // Dimensinal Rift Run
  1351. ];
  1352. if (!in_array($command, $accepted_commands)){
  1353. header("HTTP/1.1 405 Command not implemented.");
  1354. syslog(LOG_INFO, "[APIv3] HTTP/1.1 405 Command not implemented.");
  1355. return 405;
  1356. }
  1357. // Check if already in DB
  1358. $dtime = $json["result_res"]->{"tvaluelocal"};
  1359. $statement = $db->prepare("SELECT count(id) AS c FROM run WHERE uid = :uid AND dtime = :dtime;");
  1360. $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
  1361. $statement->bindValue(":dtime", $dtime, SQLITE3_TEXT);
  1362. if (0 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
  1363. header("HTTP/1.1 409 Run already in database.");
  1364. syslog(LOG_INFO, "[APIv3] HTTP/1.1 409 Run already in database.");
  1365. return 409;
  1366. }
  1367. // Get new ID
  1368. $q = $db->query("SELECT max(id) + 1 AS id FROM run;");
  1369. $r = $q->fetchArray(SQLITE3_ASSOC);
  1370. if ($r){
  1371. $id = $r["id"];
  1372. }
  1373. else{
  1374. $id = 1;
  1375. }
  1376. // Run parsing function
  1377. $result = "500 Unknown Error";
  1378. switch($command){
  1379. case "BattleDungeonResult_V2":
  1380. $result = log_cairos_run($db, $id, $uid, $json);
  1381. break;
  1382. case "BattleDimensionHoleDungeonResult_v2":
  1383. $result = log_dimension_hole_run($db, $id, $uid, $json);
  1384. break;
  1385. case "BattleRiftOfWorldsRaidResult":
  1386. $result = log_rift_raid_run($db, $id, $uid, $json);
  1387. break;
  1388. case "BattleScenarioResult":
  1389. $result = log_scenario_run($db, $id, $uid, $json);
  1390. break;
  1391. case "BattleArenaResult":
  1392. $result = log_arena_run($db, $id, $uid, $json);
  1393. break;
  1394. case "BattleDarkPortalResult":
  1395. $result = log_dark_portal_run($db, $id, $uid, $json);
  1396. break;
  1397. }
  1398. // Process result
  1399. $status_code = intval(substr($result, 0, 3));
  1400. $status_message = substr($result, 4);
  1401. if ($status_code == 0 || $status_code < 100 || $status_code > 599){
  1402. header("HTTP/1.1 500 Unknown error.");
  1403. syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unknown error.");
  1404. return 500;
  1405. }
  1406. else{
  1407. header("HTTP/1.1 $status_code $status_message");
  1408. syslog(LOG_INFO, "[APIv3] HTTP/1.1 $status_code $status_message");
  1409. return $status_code;
  1410. }
  1411. }
  1412. catch(Exception $e) {
  1413. header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
  1414. syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
  1415. return 500;
  1416. }
  1417. ?>