GET.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <?php
  2. /**
  3. * Unit getter script.
  4. *
  5. * Exposes an API to rerieve unit info.
  6. *
  7. * Optional query parameters are:
  8. * - id: Unit ID.
  9. *
  10. * @category API
  11. */
  12. global $db;
  13. /**
  14. * Gets info on a unit.
  15. *
  16. * @param resource $db Database connection.
  17. * @param int $id Unit identifier
  18. * @return mixed[] Content.
  19. */
  20. function get_unit($db, $id){
  21. $result = [
  22. "status" => 404,
  23. "message" => "Unit not found",
  24. "content" => ""
  25. ];
  26. $statement = $db->prepare("
  27. SELECT
  28. monster.id AS id,
  29. monster.name AS name,
  30. monster.family AS family,
  31. monster.element AS element,
  32. element.name AS element_name,
  33. monster.archetype AS archetype,
  34. archetype.name AS archetype_name,
  35. monster.base_stars AS base_stars,
  36. monster.natural_stars AS natural_stars,
  37. monster.obtainable AS obtainable,
  38. monster.awakens_from AS awakens_from,
  39. monster.awakens_to AS awakens_to,
  40. monster.homunculus AS homunculus,
  41. monster.hp AS hp,
  42. monster.attack AS attack,
  43. monster.defense AS defense,
  44. monster.speed AS speed,
  45. monster.crit_rate AS crit_rate,
  46. monster.crit_damage AS crit_damage,
  47. monster.accuracy AS accuracy,
  48. monster.resistance AS resistance,
  49. monster.leader_skill AS leader_skill
  50. FROM
  51. monster,
  52. element,
  53. archetype
  54. WHERE
  55. monster.element = element.id AND
  56. monster.archetype = archetype.id AND
  57. monster.id = :id ;
  58. ");
  59. $statement->bindValue(":id", $id, SQLITE3_TEXT);
  60. $q = $statement->execute();
  61. $r = $q->fetchArray(SQLITE3_ASSOC);
  62. if ($r){
  63. $unit = [
  64. "id" => $r["id"],
  65. "url" => URL::BASE . "API/v1/units/" . $r["id"] . "/",
  66. "name" => $r["name"],
  67. "family" => $r["family"],
  68. "image" => APPLICATION::img("UNIT", $r["id"]),
  69. "element" => $r["element"],
  70. "element_name" => $r["element_name"],
  71. "archetype" => $r["archetype"],
  72. "archetype_name" => $r["archetype_name"],
  73. "stars" => $r["base_stars"],
  74. "natural_stars" => $r["natural_stars"],
  75. "obtainable" => (($r["obtainable"] == 1) ? (true) : (false)),
  76. "awakens_from" => $r["awakens_from"],
  77. "awakens_to" => $r["awakens_to"],
  78. "homunculus" => (($r["homunculus"] == 1) ? (true) : (false)),
  79. "hp" => $r["hp"],
  80. "attack" => $r["attack"],
  81. "defense" => $r["defense"],
  82. "speed" => $r["speed"],
  83. "critical_rate" => $r["crit_rate"],
  84. "critical_damage" => $r["crit_damage"],
  85. "accuracy" => $r["accuracy"],
  86. "resistance" => $r["resistance"],
  87. "leader_skill" => null,
  88. "skills" => [],
  89. ];
  90. // Leader_skill
  91. if ($r["leader_skill"] != null){
  92. $statement_leader = $db->prepare("
  93. SELECT
  94. leader_skill.id AS id,
  95. leader_skill.stat AS stat,
  96. stat.name AS stat_name,
  97. leader_skill.amount AS amount,
  98. leader_skill.area AS area,
  99. effect_area.name AS area_name,
  100. leader_skill.element AS element,
  101. element.name AS element_name
  102. FROM
  103. leader_skill,
  104. stat,
  105. effect_area,
  106. element
  107. WHERE
  108. leader_skill.id = :id AND
  109. leader_skill.stat = stat.id AND
  110. leader_skill.area = effect_area.id AND
  111. leader_skill.element = element.id;
  112. ");
  113. $statement_leader->bindValue(":id", $r["leader_skill"], SQLITE3_INTEGER);
  114. $q_leader = $statement_leader->execute();
  115. $r_leader = $q_leader->fetchArray(SQLITE3_ASSOC);
  116. if ($r_leader){
  117. $description = "Increases the ";
  118. switch ($r_leader["stat"]){
  119. case STAT_ID::ATK:
  120. $description .= "attack power";
  121. break;
  122. case STAT_ID::DEF:
  123. $description .= "defense";
  124. break;
  125. case STAT_ID::HP:
  126. $description .= "HP";
  127. break;
  128. case STAT_ID::SPD:
  129. $description .= "attack speed";
  130. break;
  131. case STAT_ID::CRIT_RATE:
  132. $description .= "critical rate";
  133. break;
  134. case STAT_ID::CRIT_DMG:
  135. $description .= "critical damage";
  136. break;
  137. case STAT_ID::ACCURACY:
  138. $description .= "accuracy";
  139. break;
  140. case STAT_ID::RESIST:
  141. $description .= "resistance";
  142. break;
  143. }
  144. $description .= " of ally monsters ";
  145. switch ($r_leader["element"]){
  146. case ELEMENT_ID::WATER:
  147. $description .= " with Water attribute ";
  148. break;
  149. case ELEMENT_ID::FIRE:
  150. $description .= " with Fire attribute ";
  151. break;
  152. case ELEMENT_ID::WIND:
  153. $description .= " with Wind attribute ";
  154. break;
  155. case ELEMENT_ID::LIGHT:
  156. $description .= " with Light attribute ";
  157. break;
  158. case ELEMENT_ID::DARK:
  159. $description .= " with Dark attribute ";
  160. break;
  161. }
  162. $description = $description . "by " . $r_leader["amount"] . "%";
  163. switch ($r_leader["area"]){
  164. case EFFECT_AREA_ID::DUNGEON:
  165. $description .= " in the Dungeons";
  166. break;
  167. case EFFECT_AREA_ID::ARENA:
  168. $description .= " in the Arena";
  169. break;
  170. case EFFECT_AREA_ID::GUILD:
  171. $description .= " in Guild content";
  172. break;
  173. }
  174. $description = str_replace(" ", " ", $description) . ".";
  175. $unit["leader_skill"] = [
  176. "id" => $r_leader["id"],
  177. "stat" => $r_leader["stat"],
  178. "stat_name" => $r_leader["stat_name"],
  179. "increase" => $r_leader["amount"],
  180. "area" => $r_leader["area"],
  181. "area_name" => $r_leader["area_name"],
  182. "element" => $r_leader["element"],
  183. "element_name" => $r_leader["element_name"],
  184. "description" => $description
  185. ];
  186. }
  187. }
  188. // Skill
  189. $statement_skills = $db->prepare("
  190. SELECT
  191. skill.id AS id,
  192. skill.slot AS slot,
  193. skill.name AS name,
  194. skill.description AS description,
  195. skill.passive AS passive,
  196. skill.cooltime AS cooltime,
  197. skill.hits AS hits,
  198. skill.aoe AS aoe,
  199. skill.multiplier_formula AS multiplier_formula,
  200. skill.max_level AS max_level
  201. FROM
  202. skill,
  203. monster_skill
  204. WHERE
  205. skill.id = monster_skill.skill AND
  206. monster_skill.unit = :id
  207. ORDER BY slot;
  208. ");
  209. $statement_skills->bindValue(":id", $id, SQLITE3_TEXT);
  210. $q_skills = $statement_skills->execute();
  211. while ($r_skills = $q_skills->fetchArray(SQLITE3_ASSOC)){
  212. $skill = [
  213. "id" => $r_skills["id"],
  214. "slot" => $r_skills["slot"],
  215. "name" => $r_skills["name"],
  216. "description" => $r_skills["description"],
  217. "image" => APPLICATION::img("SKILL", $r_skills["id"]),
  218. "passive" => (($r_skills["passive"] == 1) ? (true) : (false)),
  219. "cooltime" => $r_skills["cooltime"],
  220. "hits" => $r_skills["hits"],
  221. "aoe" => (($r_skills["aoe"] == 1) ? (true) : (false)),
  222. "effects" => [],
  223. "max_level" => $r_skills["max_level"],
  224. "upgrades" => [],
  225. "formula" => $r_skills["multiplier_formula"]
  226. ];
  227. // Skill levels
  228. $statement_skill_levels = $db->prepare("
  229. SELECT
  230. level,
  231. description
  232. FROM skill_level
  233. WHERE
  234. level > 1 AND
  235. skill = :id
  236. ORDER BY level;
  237. ");
  238. $statement_skill_levels->bindValue(":id", $r_skills["id"], SQLITE3_INTEGER);
  239. $q_skill_levels = $statement_skill_levels->execute();
  240. while ($r_skill_levels = $q_skill_levels->fetchArray(SQLITE3_ASSOC)){
  241. $level = [
  242. "level" => $r_skill_levels["level"],
  243. "description" => $r_skill_levels["description"]
  244. ];
  245. array_push($skill["upgrades"], $level);
  246. }
  247. // Skill efffects
  248. $statement_skill_effects = $db->prepare("
  249. SELECT
  250. effect.id AS id,
  251. effect.is_buff AS is_buff,
  252. effect.name AS name,
  253. effect.description AS description
  254. FROM
  255. effect,
  256. skill_effect
  257. WHERE
  258. skill_effect.skill = :id AND
  259. skill_effect.effect = effect.id
  260. ");
  261. $statement_skill_effects->bindValue(":id", $r_skills["id"], SQLITE3_INTEGER);
  262. $q_skill_effects = $statement_skill_effects->execute();
  263. while ($r_skill_effects = $q_skill_effects->fetchArray(SQLITE3_ASSOC)){
  264. $effect = [
  265. "id" => $r_skill_effects["id"],
  266. "buff" => (($r_skill_effects["is_buff"] == 1) ? (true) : (false)),
  267. "name" => $r_skill_effects["name"],
  268. "description" => $r_skill_effects["description"],
  269. "image" => APPLICATION::img("EFFECT", $r_skill_effects["id"]),
  270. ];
  271. array_push($skill["effects"], $effect);
  272. }
  273. array_push($unit["skills"], $skill);
  274. }
  275. // Add to array
  276. $result["content"] = $unit;
  277. $result["status"] = 200;
  278. $result["message"] = "Success.";
  279. }
  280. return $result;
  281. }
  282. /**
  283. * Gets a list of units, paginated.
  284. *
  285. * @param resource $db Database connection.
  286. * @return mixed[] Content.
  287. */
  288. function get_unit_list($db){
  289. $result = [
  290. "status" => 200,
  291. "message" => "Success.",
  292. "content" => ""
  293. ];
  294. // Get filters
  295. $parameters = "";
  296. $filters = [
  297. "page" => 1,
  298. "per_page" => 30,
  299. "name" => "",
  300. "element" => "",
  301. "archetype" => "",
  302. "stars" => "",
  303. "stars_lte" => "",
  304. "stars_gte" => "",
  305. ];
  306. foreach (array_keys($filters) as $filter_key){
  307. $filter = filter_input(INPUT_GET, $filter_key);
  308. if ($filter != null && $filter !== false){
  309. $filters[$filter_key] = $filter;
  310. // Also, build the new url parameters
  311. if ($filter_key != "page"){
  312. $parameters .= ("&" . $filter_key . "=" . $filter);
  313. }
  314. }
  315. }
  316. // Fix some filters
  317. if (intval($filters["page"]) < 1){
  318. $filters["page"] = 1;
  319. }
  320. if (intval($filters["per_page"]) < 1){
  321. $filters["per_page"] = 1;
  322. }
  323. elseif (intval($filters["per_page"]) > 100){
  324. $filters["per_page"] = 100;
  325. }
  326. // Build the where clause
  327. $where = "
  328. monster.element = element.id AND
  329. monster.archetype = archetype.id
  330. ";
  331. if (strlen($filters["name"]) > 0){
  332. $where .= " AND upper(monster.name) LIKE upper(:name) ";
  333. }
  334. if (strlen($filters["element"]) > 0){
  335. $where .= " AND (element.id = :element OR upper(element.name) = upper(:element)) ";
  336. }
  337. if (strlen($filters["archetype"]) > 0){
  338. $where .= " AND (archetype.id = :archetype OR upper(archetype.name) = upper(:archetype)) ";
  339. }
  340. if (strlen($filters["stars"]) > 0){
  341. $where .= " AND monster.base_stars = :stars ";
  342. }
  343. if (strlen($filters["stars_lte"]) > 0){
  344. $where .= " AND monster.base_stars <= :stars_lte ";
  345. }
  346. if (strlen($filters["stars_gte"]) > 0){
  347. $where .= " AND monster.base_stars >= :stars_gte ";
  348. }
  349. // Get total
  350. $statement = $db->prepare("
  351. SELECT count(monster.id) AS c
  352. FROM
  353. monster,
  354. element,
  355. archetype
  356. WHERE $where ;
  357. ");
  358. $statement->bindValue(":name", "%" . $filters["name"] . "%", SQLITE3_TEXT);
  359. $statement->bindValue(":element", $filters["element"], SQLITE3_TEXT);
  360. $statement->bindValue(":archetype", $filters["archetype"], SQLITE3_TEXT);
  361. $statement->bindValue(":stars", $filters["stars"], SQLITE3_INTEGER);
  362. $statement->bindValue(":stars_gte", $filters["stars_gte"], SQLITE3_INTEGER);
  363. $statement->bindValue(":stars_lte", $filters["stars_lte"], SQLITE3_INTEGER);
  364. $total = $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"];
  365. // Selet all units
  366. $statement = $db->prepare("
  367. SELECT monster.id AS id
  368. FROM
  369. monster,
  370. element,
  371. archetype
  372. WHERE $where
  373. LIMIT :limit
  374. OFFSET :offset ;
  375. ");
  376. $statement->bindValue(":name", "%" . $filters["name"] . "%", SQLITE3_TEXT);
  377. $statement->bindValue(":element", $filters["element"], SQLITE3_TEXT);
  378. $statement->bindValue(":archetype", $filters["archetype"], SQLITE3_TEXT);
  379. $statement->bindValue(":stars", $filters["stars"], SQLITE3_INTEGER);
  380. $statement->bindValue(":stars_gte", $filters["stars_gte"], SQLITE3_INTEGER);
  381. $statement->bindValue(":stars_lte", $filters["stars_lte"], SQLITE3_INTEGER);
  382. $statement->bindValue(":limit", $filters["per_page"], SQLITE3_INTEGER);
  383. $statement->bindValue(":offset", $filters["per_page"] * ($filters["page"] - 1), SQLITE3_INTEGER);
  384. $q = $statement->execute();
  385. $units = [];
  386. // Loop and get unit info
  387. while ($r = $q->fetchArray(SQLITE3_ASSOC)){
  388. $unit = get_unit($db, $r["id"]);
  389. if ($unit["status"] == 200){
  390. array_push($units, $unit["content"]);
  391. }
  392. };
  393. // Calculate previous and next pages
  394. if ($filters["page"] == 1){
  395. $url_prev = null;
  396. }
  397. else{
  398. $url_prev = URL::BASE . "API/v1/units/?page=" . ($filters["page"] - 1) . $parameters;
  399. }
  400. if ($filters["page"] < ceil($total / $filters["per_page"])){
  401. $url_next = URL::BASE . "API/v1/units/?page=" . ($filters["page"] + 1) . $parameters;
  402. }
  403. else{
  404. $url_next = null;
  405. }
  406. $content = [
  407. "count" => $total,
  408. "next" => $url_next,
  409. "previous" => $url_prev,
  410. "results" => $units
  411. ];
  412. $result["content"] = $content;
  413. return $result;
  414. }
  415. try{
  416. header("Content-type: application/json; charset=utf-8");
  417. $result = [
  418. "status" => 200,
  419. "message" => "Success.",
  420. "content" => ""
  421. ];
  422. // Get profile ID
  423. /** @var mixed $query Request parameters, from API_CONTROLLER*/
  424. if (strlen($query[0]) > 0){
  425. $id = $query[0];
  426. $result = get_unit($db, $id);
  427. }
  428. else{
  429. $result = get_unit_list($db);
  430. }
  431. header("HTTP/1.1 " . $result["status"] . " " . $result["message"]);
  432. echo(json_encode($result["content"]));
  433. syslog(LOG_ERR, "HTTP/1.1 " . $result["status"] . " " . $result["message"]);
  434. return $result["status"];
  435. }
  436. catch(Exception $e) {
  437. header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
  438. syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
  439. return 500;
  440. }