Report_Rune_Enchantment_Page.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /**
  3. * Upgradeable runes report page file.
  4. *
  5. * Provides a class with all the properties and methods to display the page.
  6. *
  7. * @author Iñigo Valentin <i@inigovalentin.com>
  8. * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
  9. * @package SWDB
  10. */
  11. require_once(PATH::PAGE . "Page.php");
  12. require_once(PATH::ENTITY . "Unit.php");
  13. require_once(PATH::ENTITY . "Rune.php");
  14. require_once(PATH::ENTITY . "Enchantment.php");
  15. /**
  16. * Upgradeable runes report page model.
  17. *
  18. * @category Page
  19. * @todo Some filters are not implemented (enchantment type, teams...)
  20. */
  21. class Report_Rune_Enchantment_Page extends Page{
  22. /**
  23. * @var mixed[] List of available upgrades.
  24. */
  25. private $upgrades = [];
  26. /**
  27. * @var mixed[] Default filter values.
  28. */
  29. private $filters = [
  30. "MONSTER_NAME" => "",
  31. "MONSTER_MIN_STARS" => 5,
  32. "MONSTER_MAX_STARS" => 6,
  33. "MONSTER_IN_STORAGE" => false,
  34. "TEAM" => false,
  35. "RUNE_MIN_STARS" => 5,
  36. "RUNE_MAX_STARS" => 6,
  37. "RUNE_MIN_LEVEL" => 0,
  38. "RUNE_MAX_LEVEL" => 15,
  39. "RUNE_MIN_QUALITY" => QUALITY_ID::HERO,
  40. "RUNE_MAX_QUALITY" => QUALITY_ID::LEGEND,
  41. "RUNE_MIN_ORIGINAL_QUALITY" => QUALITY_ID::HERO,
  42. "RUNE_MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
  43. "RUNE_MIN_EFFICIENCY" => 0,
  44. "RUNE_MAX_EFFICIENCY" => 100,
  45. "RUNE_MIN_MAX_EFFICIENCY" => 0,
  46. "RUNE_MAX_MAX_EFFICIENCY" => 100,
  47. "RUNE_SLOT" => [],
  48. "GRIND" => 1,
  49. "GRIND_MIN_QUALITY" => QUALITY_ID::RARE,
  50. "GRIND_STAT" => [
  51. RUNE_STAT_ID::HP_P,
  52. RUNE_STAT_ID::ATK_P,
  53. RUNE_STAT_ID::DEF_P,
  54. RUNE_STAT_ID::SPD,
  55. RUNE_STAT_ID::CRD,
  56. RUNE_STAT_ID::CRR,
  57. RUNE_STAT_ID::ACC
  58. ],
  59. "GEM" => 1,
  60. "GEM_MIN_QUALITY" => QUALITY_ID::RARE,
  61. "GEM_STAT_FROM" => [
  62. RUNE_STAT_ID::HP,
  63. RUNE_STAT_ID::ATK,
  64. RUNE_STAT_ID::DEF,
  65. RUNE_STAT_ID::RES
  66. ],
  67. "GEM_STAT_TO" => [
  68. RUNE_STAT_ID::HP_P,
  69. RUNE_STAT_ID::ATK_P,
  70. RUNE_STAT_ID::DEF_P,
  71. RUNE_STAT_ID::SPD,
  72. RUNE_STAT_ID::CRD,
  73. RUNE_STAT_ID::CRR,
  74. RUNE_STAT_ID::ACC
  75. ]
  76. ];
  77. /**
  78. * Constructor.
  79. *
  80. * Retrieves the data and initializes the variables.
  81. */
  82. public function __construct(){
  83. parent::__construct();
  84. $this->set_public(true);
  85. $this->set_view("report_rune_enchantment.php");
  86. $this->set_title("Rune enchantment");
  87. $this->set_description("Find runes that can be upgraded via enchantments");
  88. $this->set_canonical(get_context()->get_player()->get_id() . "/report/rune_enchantment//");
  89. $this->add_css("report_rune_enchantment.css");
  90. $prev_monster = "";
  91. $prev_rune = "";
  92. $upgrade = null;
  93. $rupgrade = null;
  94. $this->parse_filters();
  95. $result_set = $this->prepare_statement()->execute();
  96. while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
  97. if ($result["unit"] != $prev_monster){
  98. if ($prev_rune != ""){
  99. array_push($upgrade["upgrade"], $rupgrade);
  100. }
  101. if ($prev_monster != ""){
  102. array_push($this->upgrades, $upgrade);
  103. }
  104. $prev_monster = $result["unit"];
  105. $prev_rune = "";
  106. $upgrade = [
  107. "unit" => new Unit($result["unit"]),
  108. "upgrade" => [],
  109. ];
  110. $rupgrade = [
  111. "rune" => new Rune($result["rune"]),
  112. "enchantment" => [],
  113. ];
  114. }
  115. if ($result["rune"] != $prev_rune){
  116. if ($prev_rune != ""){
  117. array_push($upgrade["upgrade"], $rupgrade);
  118. }
  119. $prev_rune = $result["rune"];
  120. $rupgrade = [
  121. "rune" => new Rune($result["rune"]),
  122. "enchantment" => [],
  123. ];
  124. }
  125. $enchantment= new Enchantment($result["enchantment"]);
  126. array_push($rupgrade["enchantment"], $enchantment);
  127. }
  128. // Last entries
  129. array_push($upgrade["upgrade"], $rupgrade);
  130. array_push($this->upgrades, $upgrade);
  131. $this->set_code(200);
  132. $this->set_message("OK");
  133. }
  134. /**
  135. * Parses the filters passed in the request and sets $filters.
  136. * Filters must be in $_GET, nd the available ones are max_stars (1-6),
  137. * min_stars (1-6) and in_storage (on/off).
  138. */
  139. private function parse_filters(){
  140. // Monster
  141. if (isset($_GET["monster_min_stars"]) && intval($_GET["monster_min_stars"]) > 0 && intval($_GET["monster_min_stars"]) < 7){
  142. $this->filters["MONSTER_MIN_STARS"] = $_GET["monster_min_stars"];
  143. }
  144. if (isset($_GET["monster_max_stars"]) && intval($_GET["monster_max_stars"]) > 0 && intval($_GET["monster_max_stars"]) < 7){
  145. $this->filters["MONSTER_MAX_STARS"] = $_GET["monster_max_stars"];
  146. }
  147. if (isset($_GET["monster_in_storage"]) && $_GET["monster_in_storage"] == "on"){
  148. $this->filters["MONSTER_IN_STORAGE"] = true;
  149. }
  150. else{
  151. $this->filters["MONSTER_IN_STORAGE"] = false;
  152. }
  153. if (isset($_GET["monster_name"]) && strlen($_GET["monster_name"]) > 0){
  154. $this->filters["MONSTER_NAME"] = SQLite3::escapeString($_GET["monster_name"]);
  155. }
  156. // Runes
  157. if (isset($_GET["rune_min_stars"]) && intval($_GET["rune_min_stars"]) > 0 && intval($_GET["rune_min_stars"]) < 7){
  158. $this->filters["RUNE_MIN_STARS"] = $_GET["rune_min_stars"];
  159. }
  160. if (isset($_GET["rune_max_stars"]) && intval($_GET["rune_max_stars"]) > 0 && intval($_GET["rune_max_stars"]) < 7){
  161. $this->filters["RUNE_MAX_STARS"] = $_GET["rune_max_stars"];
  162. }
  163. if (isset($_GET["rune_min_level"]) && intval($_GET["rune_min_level"]) >= 0 && intval($_GET["rune_min_level"]) <= 15){
  164. $this->filters["RUNE_MIN_LEVEL"] = $_GET["rune_min_level"];
  165. }
  166. if (isset($_GET["rune_max_level"]) && intval($_GET["rune_max_level"]) >= 0 && intval($_GET["rune_max_level"]) <= 15){
  167. $this->filters["RUNE_MAX_LEVEL"] = $_GET["rune_max_level"];
  168. }
  169. if (isset($_GET["rune_min_quality"]) && intval($_GET["rune_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_min_quality"]) <= QUALITY_ID::LEGEND){
  170. $this->filters["RUNE_MIN_QUALITY"] = $_GET["rune_min_quality"];
  171. }
  172. if (isset($_GET["rune_max_quality"]) && intval($_GET["rune_max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_max_quality"]) <= QUALITY_ID::LEGEND){
  173. $this->filters["RUNE_MAX_QUALITY"] = $_GET["rune_max_quality"];
  174. }
  175. if (isset($_GET["rune_min_original_quality"]) && intval($_GET["rune_min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_min_original_quality"]) <= QUALITY_ID::LEGEND){
  176. $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] = $_GET["rune_min_original_quality"];
  177. }
  178. if (isset($_GET["rune_max_original_quality"]) && intval($_GET["rune_max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_max_original_quality"]) <= QUALITY_ID::LEGEND){
  179. $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] = $_GET["rune_max_original_quality"];
  180. }
  181. if (isset($_GET["rune_min_efficiency"]) && intval($_GET["rune_min_efficiency"]) >= 0 && intval($_GET["rune_min_efficiency"]) <= 100){
  182. $this->filters["RUNE_MIN_EFFICIENCY"] = $_GET["rune_min_efficiency"];
  183. }
  184. if (isset($_GET["rune_max_efficiency"]) && intval($_GET["rune_max_efficiency"]) >= 0 && intval($_GET["rune_max_efficiency"]) <= 100){
  185. $this->filters["RUNE_MAX_EFFICIENCY"] = $_GET["rune_max_efficiency"];
  186. }
  187. if (isset($_GET["rune_min_max_efficiency"]) && intval($_GET["rune_min_max_efficiency"]) >= 0 && intval($_GET["rune_min_max_efficiency"]) <= 100){
  188. $this->filters["RUNE_MIN_MAX_EFFICIENCY"] = $_GET["rune_min_max_efficiency"];
  189. }
  190. if (isset($_GET["rune_max_max_efficiency"]) && intval($_GET["rune_max_max_efficiency"]) >= 0 && intval($_GET["rune_max_max_efficiency"]) <= 100){
  191. $this->filters["RUNE_MAX_MAX_EFFICIENCY"] = $_GET["rune_max_max_efficiency"];
  192. }
  193. if (isset($_GET["rune_slot"])){
  194. $slots = $_GET["rune_slot"];
  195. foreach ($slots as $slot){
  196. if (intval($slot) >= 1 && intval($slot) < 7){
  197. array_push($this->filters["RUNE_SLOT"], intval($slot));
  198. }
  199. }
  200. }
  201. // Grindstones
  202. if (isset($_GET["grind_min_quality"]) && intval($_GET["grind_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["grind_min_quality"]) < QUALITY_ID::LEGEND){
  203. $this->filters["GRIND_MIN_QUALITY"] = $_GET["grind_min_quality"];
  204. }
  205. if (isset($_GET["grind_stat"])){
  206. $stats = $_GET["grind_stat"];
  207. $this->filters["GRIND_STAT"] = [];
  208. foreach ($stats as $stat){
  209. array_push($this->filters["GRIND_STAT"], intval($stat));
  210. }
  211. }
  212. if (isset($_GET["gem_stat_from"])){
  213. $stats = $_GET["gem_stat_from"];
  214. $this->filters["GEM_STAT_FROM"] = [];
  215. foreach ($stats as $stat){
  216. array_push($this->filters["GEM_STAT_FROM"], intval($stat));
  217. }
  218. }
  219. if (isset($_GET["gem_stat_to"])){
  220. $stats = $_GET["gem_stat_to"];
  221. $this->filters["GEM_STAT_TO"] = [];
  222. foreach ($stats as $stat){
  223. array_push($this->filters["GEM_STAT_TO"], intval($stat));
  224. }
  225. }
  226. return;
  227. }
  228. /**
  229. * Prepares the statement to execute against the database using the filter values.
  230. *
  231. * @return SQLite3Stmt prepared statement.
  232. */
  233. private function prepare_statement(){
  234. // Common items
  235. $query = "
  236. SELECT DISTINCT
  237. unit.id AS unit,
  238. rune.id AS rune,
  239. enchantment.id AS enchantment
  240. FROM
  241. unit,
  242. monster,
  243. rune,
  244. unit_rune,
  245. enchantment,
  246. enchantment_type
  247. WHERE
  248. unit.player = :player AND
  249. rune.player = unit.player AND
  250. enchantment.player = unit.player AND
  251. unit.id = unit_rune.unit AND
  252. rune.id = unit_rune.rune AND
  253. unit_rune.rta = :rta AND
  254. unit.monster = monster.id AND
  255. enchantment.type = enchantment_type.id AND
  256. -- RUNE FILTERS
  257. rune.stars BETWEEN :rune_min_stars AND :rune_max_stars AND
  258. rune.quality BETWEEN :rune_min_quality AND :rune_max_quality AND
  259. rune.original_quality BETWEEN :rune_min_original_quality AND :rune_max_original_quality AND
  260. rune.level BETWEEN :rune_min_level AND :rune_max_level AND
  261. rune.efficiency BETWEEN :rune_min_efficiency AND :rune_max_efficiency AND
  262. rune.max_efficiency BETWEEN :rune_min_max_efficiency AND :rune_max_max_efficiency AND
  263. (rune.type = enchantment.rune OR enchantment_type.inmemorial = 1) AND
  264. enchantment_type.ancient = rune.ancient AND
  265. -- No enchantments with the same sat as the runes main or innate
  266. enchantment.stat NOT IN (
  267. SELECT stat
  268. FROM rune_stat
  269. WHERE
  270. rune_stat.rune = rune.id AND
  271. (
  272. rune_stat.slot = :stat_main OR
  273. rune_stat.slot = :stat_innate
  274. )
  275. ) AND
  276. ( -- TYPE SWITCH
  277. ( -- BEGIN GRINDSTONE BLOCK
  278. enchantment_type.gem = 0 AND
  279. enchantment.stat IN (SELECT stat FROM rune_stat WHERE rune_stat.rune = rune.id) AND
  280. enchantment.quality >= :grind_min_quality
  281. ";
  282. // GRindstone stats
  283. if (count($this->filters["GRIND_STAT"]) > 0){
  284. $query .= " AND enchantment.stat IN (";
  285. for ($i = 0; $i < sizeof($this->filters["GRIND_STAT"]); $i ++){
  286. $query .= ":grind_stat_$i, ";
  287. }
  288. $query = rtrim($query, ", ") . ") ";
  289. }
  290. $query .= "
  291. ) -- END GRINDSTONE BLOCK
  292. OR
  293. ( -- BEGIN GEM BLOCK
  294. enchantment_type.gem = 1 AND
  295. enchantment.stat NOT IN (SELECT stat FROM rune_stat WHERE rune_stat.rune = rune.id) AND
  296. enchantment.quality >= :gem_min_quality
  297. ";
  298. // Gem stats from
  299. if (count($this->filters["GEM_STAT_TO"]) > 0){
  300. $query .= " AND enchantment.stat IN (";
  301. for ($i = 0; $i < sizeof($this->filters["GEM_STAT_TO"]); $i ++){
  302. $query .= ":gem_stat_to_$i, ";
  303. }
  304. $query = rtrim($query, ", ") . ") ";
  305. }
  306. //Gem stats from
  307. if (count($this->filters["GEM_STAT_FROM"]) > 0){
  308. //$query .= " AND enchantment.stat IN (";
  309. $query .= "
  310. AND rune.id IN (
  311. SELECT DISTINCT rune
  312. FROM rune_stat
  313. WHERE
  314. rune_stat.rune = rune.id AND
  315. stat IN (
  316. ";
  317. for ($i = 0; $i < sizeof($this->filters["GEM_STAT_FROM"]); $i ++){
  318. $query .= ":gem_stat_from_$i, ";
  319. }
  320. $query = rtrim($query, ", ") . ")) ";
  321. }
  322. $query .= "
  323. ) -- END GEM BLOCK
  324. ) -- END SWITCH
  325. ";
  326. // Monster name
  327. if ($this->filters["MONSTER_NAME"] != ""){
  328. $query .= " AND upper(monster.name) LIKE upper(:monster_name) " ;
  329. }
  330. // Monsters in storage
  331. if (! $this->filters["MONSTER_IN_STORAGE"]){
  332. $query .= "AND unit.building <> :storage_building ";
  333. }
  334. // Rune slot
  335. if (count($this->filters["RUNE_SLOT"]) > 0){
  336. $query .= " AND rune.slot IN (";
  337. for ($i = 0; $i < sizeof($this->filters["RUNE_SLOT"]); $i ++){
  338. $query .= ":rune_slot_$i, ";
  339. }
  340. $query = rtrim($query, ", ") . ") ";
  341. }
  342. $statement = get_context()->get_db()->prepare($query);
  343. $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
  344. $statement->bindValue(":rta", get_context()->get_game_mode(), SQLITE3_TEXT);
  345. $statement->bindValue(":rune_min_stars", $this->filters["RUNE_MIN_STARS"], SQLITE3_INTEGER);
  346. $statement->bindValue(":rune_max_stars", $this->filters["RUNE_MAX_STARS"], SQLITE3_INTEGER);
  347. $statement->bindValue(":rune_min_quality", $this->filters["RUNE_MIN_QUALITY"], SQLITE3_INTEGER);
  348. $statement->bindValue(":rune_max_quality", $this->filters["RUNE_MAX_QUALITY"], SQLITE3_INTEGER);
  349. $statement->bindValue(":rune_min_original_quality", $this->filters["RUNE_MIN_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
  350. $statement->bindValue(":rune_max_original_quality", $this->filters["RUNE_MAX_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
  351. $statement->bindValue(":rune_min_level", $this->filters["RUNE_MIN_LEVEL"], SQLITE3_INTEGER);
  352. $statement->bindValue(":rune_max_level", $this->filters["RUNE_MAX_LEVEL"], SQLITE3_INTEGER);
  353. $statement->bindValue(":rune_min_efficiency", $this->filters["RUNE_MIN_EFFICIENCY"], SQLITE3_FLOAT);
  354. $statement->bindValue(":rune_max_efficiency", $this->filters["RUNE_MAX_EFFICIENCY"], SQLITE3_FLOAT);
  355. $statement->bindValue(":rune_min_max_efficiency", $this->filters["RUNE_MIN_MAX_EFFICIENCY"], SQLITE3_FLOAT);
  356. $statement->bindValue(":rune_max_max_efficiency", $this->filters["RUNE_MAX_MAX_EFFICIENCY"], SQLITE3_FLOAT);
  357. $statement->bindValue(":monster_name", "%" . $this->filters["MONSTER_NAME"] . "%", SQLITE3_TEXT);
  358. $statement->bindValue(":storage_building", BUILDING_ID::MONSTER_STORAGE, SQLITE3_INTEGER);
  359. for ($i = 0; $i < sizeof($this->filters["RUNE_SLOT"]); $i ++){
  360. $statement->bindValue(":rune_slot_$i", $this->filters["RUNE_SLOT"][$i], SQLITE3_INTEGER);
  361. }
  362. $statement->bindValue(":stat_main", RUNE_STAT_SLOT_ID::MAIN, SQLITE3_INTEGER);
  363. $statement->bindValue(":stat_innate", RUNE_STAT_SLOT_ID::INNATE, SQLITE3_INTEGER);
  364. $statement->bindValue(":grind_min_quality", $this->filters["GRIND_MIN_QUALITY"], SQLITE3_INTEGER);
  365. for ($i = 0; $i < sizeof($this->filters["GRIND_STAT"]); $i ++){
  366. $statement->bindValue(":grind_stat_$i", $this->filters["GRIND_STAT"][$i], SQLITE3_INTEGER);
  367. }
  368. $statement->bindValue(":gem_min_quality", $this->filters["GEM_MIN_QUALITY"], SQLITE3_INTEGER);
  369. for ($i = 0; $i < sizeof($this->filters["GEM_STAT_TO"]); $i ++){
  370. $statement->bindValue(":gem_stat_to_$i", $this->filters["GEM_STAT_TO"][$i], SQLITE3_INTEGER);
  371. }
  372. for ($i = 0; $i < sizeof($this->filters["GEM_STAT_FROM"]); $i ++){
  373. $statement->bindValue(":gem_stat_from_$i", $this->filters["GEM_STAT_FROM"][$i], SQLITE3_INTEGER);
  374. }
  375. return $statement;
  376. }
  377. /**
  378. * Retrieves the computed upgrades.
  379. *
  380. * Can be described as:
  381. * $upgrades = [
  382. * [
  383. * unit (Unit),
  384. * upgrade = [
  385. * [
  386. * rune (Rune),
  387. * enchant = [(Enchantment)]
  388. * ]
  389. * ]
  390. * ]
  391. * ]
  392. *
  393. * @return mixed[] Upgrades to show.
  394. */
  395. public function get_upgrades(){
  396. return $this->upgrades;
  397. }
  398. /**
  399. * Retrieves the page filters.
  400. *
  401. * @return mixed[] Page filtes
  402. */
  403. public function get_filters(){
  404. return $this->filters;
  405. }
  406. /**
  407. * Retrieves one filter.
  408. *
  409. * @param string $key
  410. * @return mixed Filter value, null if if doesn't exist.
  411. */
  412. public function get_filter($key){
  413. if (array_key_exists($key, $this->filters)){
  414. return $this->filters[$key];
  415. }
  416. else{
  417. return null;
  418. }
  419. }
  420. }