GET.php 16 KB

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