Kaynağa Gözat

Code optimizations in pages and views. Proper encapsulation and documentation across all files.

Iñigo Valentin 5 yıl önce
ebeveyn
işleme
8f1d5cdc07
74 değiştirilmiş dosya ile 8515 ekleme ve 7205 silme
  1. 56 56
      application/API/v1/API_Controller.php
  2. 417 408
      application/API/v1/help/api.php
  3. 8 8
      application/API/v1/help/index.php
  4. 25 16
      application/API/v1/main.php
  5. 123 121
      application/API/v1/profile/DELETE.php
  6. 79 77
      application/API/v1/profile/GET.php
  7. 235 233
      application/API/v1/profile/POST.php
  8. 517 486
      application/API/v1/profile/PUT.php
  9. 887 477
      application/API/v1/run/POST.php
  10. 425 422
      application/API/v1/units/GET.php
  11. 10 115
      application/Constant.php
  12. 4 7
      application/Controller.php
  13. 1 1
      application/action/change_game_mode.php
  14. 1 1
      application/action/delete_team.php
  15. 1 1
      application/action/edit_profile.php
  16. 1 1
      application/action/login.php
  17. 1 1
      application/action/new_team.php
  18. 1 1
      application/action/optimize_get_options.php
  19. 1 1
      application/action/optimize_get_rune_list.php
  20. 1 1
      application/action/rate_team.php
  21. 1 1
      application/action/save_run_team.php
  22. 1 1
      application/entity/Run.php
  23. 1 1
      application/entity/Unit.php
  24. 88 90
      application/helper/APPLICATION_Helper.php
  25. 36 38
      application/helper/DB_Helper.php
  26. 651 654
      application/helper/HTML_Helper.php
  27. 18 17
      application/helper/Helper.php
  28. 49 51
      application/helper/NET_Helper.php
  29. 92 96
      application/helper/TEXT_Helper.php
  30. 249 163
      application/page/Artifacts_Page.php
  31. 203 200
      application/page/Enchantments_Page.php
  32. 67 47
      application/page/Error_Page.php
  33. 86 57
      application/page/Guild_Page.php
  34. 26 34
      application/page/Home_Page.php
  35. 55 32
      application/page/Landing_Page.php
  36. 138 71
      application/page/Monster_Page.php
  37. 157 108
      application/page/Monsters_Page.php
  38. 48 59
      application/page/Optimizer_Page.php
  39. 40 32
      application/page/Optimizer_Unit_Page.php
  40. 131 65
      application/page/Page.php
  41. 26 56
      application/page/Profile_Page.php
  42. 27 34
      application/page/Report_Page.php
  43. 393 373
      application/page/Report_Rune_Enchantment_Page.php
  44. 303 254
      application/page/Report_Skillup_Page.php
  45. 306 229
      application/page/Runes_Page.php
  46. 167 112
      application/page/Runs_Page.php
  47. 239 229
      application/page/Stats_Page.php
  48. 136 82
      application/page/Teams_Page.php
  49. 40 33
      application/page/Unit_Page.php
  50. 225 167
      application/page/Units_Page.php
  51. 38 36
      application/view/artifacts.php
  52. 40 45
      application/view/enchantments.php
  53. 15 12
      application/view/error.php
  54. 30 27
      application/view/guild.php
  55. 15 15
      application/view/help.php
  56. 52 30
      application/view/home.php
  57. 28 24
      application/view/landing.php
  58. 52 48
      application/view/monster.php
  59. 37 35
      application/view/monsters.php
  60. 30 28
      application/view/optimizer.php
  61. 130 128
      application/view/optimizer_unit.php
  62. 36 34
      application/view/profile.php
  63. 27 25
      application/view/report.php
  64. 54 52
      application/view/report_rune_enchantment.php
  65. 45 43
      application/view/report_skillup.php
  66. 48 45
      application/view/runes.php
  67. 34 32
      application/view/runs.php
  68. 27 25
      application/view/stats.php
  69. 66 40
      application/view/teams.php
  70. 97 95
      application/view/unit.php
  71. 28 28
      application/view/units.php
  72. 773 517
      parser/swarfarm_parser
  73. 1 0
      public/css/report_skillup.css
  74. 19 21
      public/index.php

+ 56 - 56
application/API/v1/API_Controller.php

@@ -1,69 +1,69 @@
 <?php
+/**
+ * v1 API Controller file.
+ *
+ * Provides a class to handle all posible API requests.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * v1 API Controller file.
-     *
-     * Provides a class to handle all posible API requests.
-     *
-     * @category Constroller
-     */
+/**
+ * v1 API controller.
+ *
+ * Handles every API request.
+ *
+ * @category API
+ */
+class API_Controller {
 
     /**
-     * v1 API controller.
+     * Constructor.
      *
-     * Handles every API request.
+     * Handles every request, creating the required models and selecting the
+     * view.
      *
-     * @category Controller
+     * @param string[] $query GET parameters of the request.
      */
-    class API_Controller {
-
-        /**
-         * Constructor.
-         *
-         * Handles every request, creating the required models and selecting the
-         * view.
-         *
-         * @param string[] $query GET parameters of the request.
-         */
-        public function __construct($query){
+    public function __construct($query){
 
-            // Remove /API/
-            array_shift($query);
-            // Remove /v1/
+        // Remove /API/
+        array_shift($query);
+        // Remove /v1/
+        array_shift($query);
+        // API call: Use API controller
+        $method = $_SERVER["REQUEST_METHOD"];
+        if (!in_array($method, ["GET", "POST", "PUT", "DELETE"])){
+            $method = "GET";
+        }
+        if (count($query) == 0 || $query[0] == null || $query[0] == ""){
+            require_once(__DIR__ . "/main.php");
+        }
+        else{
+            $command = strtolower($query[0]);
+            // Remove /<command>/
             array_shift($query);
-            // API call: Use API controller
-            $method = $_SERVER["REQUEST_METHOD"];
-            if (!in_array($method, ["GET", "POST", "PUT", "DELETE"])){
-                $method = "GET";
-            }
-            if (count($query) == 0 || $query[0] == null || $query[0] == ""){
-                require_once(__DIR__ . "/main.php");
-            }
-            else{
-                $command = strtolower($query[0]);
-                // Remove /<command>/
-                array_shift($query);
-                switch ($command){
-                    case "help":
-                        require_once(__DIR__ . "/help/index.php");
-                        break;
-                    case "profile":
-                    case "run":
-                    case "logbook":
-                    case "collection":
-                    case "run":
-                    case "units":
-                        if (file_exists(__DIR__ . "/$command/$method.php")){
-                            require_once(__DIR__ . "/$command/$method.php");
-                        }
-                        else{
-                            header("HTTP/1.1 404");
-                        }
-                        break;
-                    default:
+            switch ($command){
+                case "help":
+                    require_once(__DIR__ . "/help/index.php");
+                    break;
+                case "profile":
+                case "run":
+                case "logbook":
+                case "collection":
+                case "run":
+                case "units":
+                    if (file_exists(__DIR__ . "/$command/$method.php")){
+                        require_once(__DIR__ . "/$command/$method.php");
+                    }
+                    else{
                         header("HTTP/1.1 404");
-                }
+                    }
+                    break;
+                default:
+                    header("HTTP/1.1 404");
             }
         }
     }
-?>
+}

+ 417 - 408
application/API/v1/help/api.php

@@ -1,425 +1,434 @@
 <?php
+/**
+ * API structure definition.
+ *
+ * Provides the API structure to define the help page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category API
+ */
 
-    /**
-     * @var mixed[] $API API help structure.
-     */
-    $API = [
-        "version" => 1,
-        "category" => [
-            [ // BEGIN CATEGORY Units
-                "name" => "Units",
-                "command" => [
-                    [ // BEGIN COMMAND Units
-                        "name" => "units",
-                        "method" => [
-                            [
-                                "id" => "GET",
-                                "url" => "/units/",
-                                "description" => "Retrieves units.",
-                                "parameters" => [
-                                    [
-                                        "key" => "page",
-                                        "via" => "request",
-                                        "type" => "int",
-                                        "description" => "Page to fetch. Deaults to 1.",
-                                        "optional" => true
-                                    ],
-                                    [
-                                        "key" => "per_page",
-                                        "via" => "request",
-                                        "type" => "int",
-                                        "description" => "number of results per page. Defaults to 30, maximum is 100.",
-                                        "optional" => true
-                                    ],
-                                    [
-                                        "key" => "name",
-                                        "via" => "request",
-                                        "type" => "string",
-                                        "description" => "Filter units with this in their name. Case insensitive.",
-                                        "optional" => true
-                                    ]
-                                ],
-                                "responses" => [
-                                    [
-                                        "status" => "200",
-                                        "message" => "Success.",
-                                        "description" => null,
-                                        "example" => null,
-                                    ],
+/**
+ * @var mixed[] $API API help structure.
+ */
+$API = [
+    "version" => 1,
+    "category" => [
+        [ // BEGIN CATEGORY Units
+            "name" => "Units",
+            "command" => [
+                [ // BEGIN COMMAND Units
+                    "name" => "units",
+                    "method" => [
+                        [
+                            "id" => "GET",
+                            "url" => "/units/",
+                            "description" => "Retrieves units.",
+                            "parameters" => [
+                                [
+                                    "key" => "page",
+                                    "via" => "request",
+                                    "type" => "int",
+                                    "description" => "Page to fetch. Deaults to 1.",
+                                    "optional" => true
+                                ],
+                                [
+                                    "key" => "per_page",
+                                    "via" => "request",
+                                    "type" => "int",
+                                    "description" => "number of results per page. Defaults to 30, maximum is 100.",
+                                    "optional" => true
+                                ],
+                                [
+                                    "key" => "name",
+                                    "via" => "request",
+                                    "type" => "string",
+                                    "description" => "Filter units with this in their name. Case insensitive.",
+                                    "optional" => true
                                 ]
                             ],
-                            [
-                                "id" => "GET",
-                                "url" => "/units/{id}/",
-                                "description" => "Retrieves a unit info.",
-                                "parameters" => [
-                                    [
-                                        "key" => "{id}",
-                                        "via" => "query",
-                                        "type" => "string",
-                                        "description" => "Unit ID.",
-                                        "optional" => false
-                                    ],
-                                ],
-                                "responses" => [
-                                    [
-                                        "status" => "200",
-                                        "message" => "Success.",
-                                        "description" => null,
-                                        "example" => null,
-                                    ],
-                                    [
-                                        "status" => "404",
-                                        "message" => "Unit not found.",
-                                        "description" => "The requested unit does not exist.",
-                                        "example" => null
-                                    ]
-                                ]
+                            "responses" => [
+                                [
+                                    "status" => "200",
+                                    "message" => "Success.",
+                                    "description" => null,
+                                    "example" => null,
+                                ],
+                            ]
+                        ],
+                        [
+                            "id" => "GET",
+                            "url" => "/units/{id}/",
+                            "description" => "Retrieves a unit info.",
+                            "parameters" => [
+                                [
+                                    "key" => "{id}",
+                                    "via" => "query",
+                                    "type" => "string",
+                                    "description" => "Unit ID.",
+                                    "optional" => false
+                                ],
                             ],
+                            "responses" => [
+                                [
+                                    "status" => "200",
+                                    "message" => "Success.",
+                                    "description" => null,
+                                    "example" => null,
+                                ],
+                                [
+                                    "status" => "404",
+                                    "message" => "Unit not found.",
+                                    "description" => "The requested unit does not exist.",
+                                    "example" => null
+                                ]
+                            ]
                         ],
-                    ] // END COMMAND profile
-                ]
-            ], // END CATEGORY Units
-            [ // BEGIN CATEGORY Profile
-                "name" => "Profile",
-                "command" => [
-                    [ // BEGIN COMMAND UploadProfile
-                        "name" => "profile",
-                        "method" => [
-                            [
-                                "id" => "GET",
-                                "url" => "/profile/{id}/",
-                                "description" => "Retrieves player profile.",
-                                "parameters" => [
-                                    [
-                                        "key" => "{id}",
-                                        "via" => "query",
-                                        "type" => "string",
-                                        "description" => "Player ID or name.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "key",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "API key. Required for private profiles.",
-                                        "optional" => true
-                                    ]
-                                ],
-                                "responses" => [
-                                    [
-                                        "status" => "200",
-                                        "message" => "Success.",
-                                        "description" => null,
-                                        "example" => json_encode('{"username":"IValentin","level":50,"public":"1"}', JSON_PRETTY_PRINT),
-                                    ],
-                                    [
-                                        "status" => "403",
-                                        "message" => "A list of profiles cant be retrieved. Please specify a profile ID or player name.",
-                                        "description" => "No player ID or name has been supplied. A full list of profiles is not available.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "403",
-                                        "message" => "The profile is not public.",
-                                        "description" => "The requestd player profile is private, and the API key has not been sent or it's invalid.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "404",
-                                        "message" => "Player not found.",
-                                        "description" => "The requestd player is not registered in SWDB.",
-                                        "example" => null
-                                    ]
+                    ],
+                ] // END COMMAND profile
+            ]
+        ], // END CATEGORY Units
+        [ // BEGIN CATEGORY Profile
+            "name" => "Profile",
+            "command" => [
+                [ // BEGIN COMMAND UploadProfile
+                    "name" => "profile",
+                    "method" => [
+                        [
+                            "id" => "GET",
+                            "url" => "/profile/{id}/",
+                            "description" => "Retrieves player profile.",
+                            "parameters" => [
+                                [
+                                    "key" => "{id}",
+                                    "via" => "query",
+                                    "type" => "string",
+                                    "description" => "Player ID or name.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "key",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "API key. Required for private profiles.",
+                                    "optional" => true
                                 ]
                             ],
-                            [
-                                "id" => "POST",
-                                "url" => "/profile/{id}/",
-                                "description" => "Creates a new player profile.",
-                                "parameters" => [
-                                    [
-                                        "key" => "{id}",
-                                        "via" => "query",
-                                        "type" => "string",
-                                        "description" => "Player ID.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "email",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "User email. Must be a valid address.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "password",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "New user password.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "name",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "New username. If not supplied, it will default to 'player_[id]'. Will be overriden on the next PUT request.",
-                                        "optional" => true
-                                    ],
-                                    [
-                                        "key" => "public",
-                                        "via" => "body",
-                                        "type" => "int",
-                                        "description" => "1 to make the profile public, 0 to keep it private. Default to 0.",
-                                        "optional" => true
-                                    ],
-                                ],
-                                "responses" => [
-                                    [
-                                        "status" => "201",
-                                        "message" => "Created.",
-                                        "description" => null,
-                                        "example" => json_encode('{"username":"IValentin","email":example@example.com,"api_key":"0123456789012345","public":"0"}', JSON_PRETTY_PRINT),
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "User ID not received.",
-                                        "description" => "The ID of the player to create is not in the query.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "User email not received.",
-                                        "description" => "The email of the player to create has not ben passed in the request.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "Invalid email.",
-                                        "description" => "The 'mail' parameter must be a valid email address.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "User password not received.",
-                                        "description" => "The password of the player to create has not ben passed in the request.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "Existing user.",
-                                        "description" => "A player with the same ID is already registered in SWDB.",
-                                        "example" => null
-                                    ]
+                            "responses" => [
+                                [
+                                    "status" => "200",
+                                    "message" => "Success.",
+                                    "description" => null,
+                                    "example" => json_encode('{"username":"IValentin","level":50,"public":"1"}', JSON_PRETTY_PRINT),
+                                ],
+                                [
+                                    "status" => "403",
+                                    "message" => "A list of profiles cant be retrieved. Please specify a profile ID or player name.",
+                                    "description" => "No player ID or name has been supplied. A full list of profiles is not available.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "403",
+                                    "message" => "The profile is not public.",
+                                    "description" => "The requestd player profile is private, and the API key has not been sent or it's invalid.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "404",
+                                    "message" => "Player not found.",
+                                    "description" => "The requestd player is not registered in SWDB.",
+                                    "example" => null
                                 ]
+                            ]
+                        ],
+                        [
+                            "id" => "POST",
+                            "url" => "/profile/{id}/",
+                            "description" => "Creates a new player profile.",
+                            "parameters" => [
+                                [
+                                    "key" => "{id}",
+                                    "via" => "query",
+                                    "type" => "string",
+                                    "description" => "Player ID.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "email",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "User email. Must be a valid address.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "password",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "New user password.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "name",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "New username. If not supplied, it will default to 'player_[id]'. Will be overriden on the next PUT request.",
+                                    "optional" => true
+                                ],
+                                [
+                                    "key" => "public",
+                                    "via" => "body",
+                                    "type" => "int",
+                                    "description" => "1 to make the profile public, 0 to keep it private. Default to 0.",
+                                    "optional" => true
+                                ],
                             ],
-                            [
-                                "id" => "PUT",
-                                "url" => "/profile/{id}/",
-                                "description" => "Updates a player profile with data received from the game.",
-                                "parameters" => [
-                                    [
-                                        "key" => "{id}",
-                                        "via" => "query",
-                                        "type" => "string",
-                                        "description" => "Player ID.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "key",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "API key.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "response",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "JSON received from game server on HubUserLogin command.",
-                                        "optional" => false
-                                    ]
-                                ],
-                                "responses" => [
-                                    [
-                                        "status" => "204",
-                                        "message" => "Profile imported.",
-                                        "description" => null,
-                                        "example" => null,
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "API key not received.",
-                                        "description" => "No API key was suplied in the request.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "No data received.",
-                                        "description" => "Game JSON response not received from request",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "Data is no valid JSON.",
-                                        "description" => "The parameter 'response' contains information, but it's not valid JSON data.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "401",
-                                        "message" => "Invalid credentials",
-                                        "description" => "The API key is not valid for the profile being updated.",
-                                        "example" => null
-                                    ]
+                            "responses" => [
+                                [
+                                    "status" => "201",
+                                    "message" => "Created.",
+                                    "description" => null,
+                                    "example" => json_encode('{"username":"IValentin","email":example@example.com,"api_key":"0123456789012345","public":"0"}', JSON_PRETTY_PRINT),
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "User ID not received.",
+                                    "description" => "The ID of the player to create is not in the query.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "User email not received.",
+                                    "description" => "The email of the player to create has not ben passed in the request.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "Invalid email.",
+                                    "description" => "The 'mail' parameter must be a valid email address.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "User password not received.",
+                                    "description" => "The password of the player to create has not ben passed in the request.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "Existing user.",
+                                    "description" => "A player with the same ID is already registered in SWDB.",
+                                    "example" => null
                                 ]
-                            ],
-                            [
-                                "id" => "DELETE",
-                                "url" => "/profile/{id}/",
-                                "description" => "Deletes a player profile.",
-                                "parameters" => [
-                                    [
-                                        "key" => "{id}",
-                                        "via" => "query",
-                                        "type" => "string",
-                                        "description" => "Player ID.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "key",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "API key.",
-                                        "optional" => false
-                                    ]
-                                ],
-                                "responses" => [
-                                    [
-                                        "status" => "204",
-                                        "message" => "Profile deleted.",
-                                        "description" => null,
-                                        "example" => null,
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "User ID not received.",
-                                        "description" => "The ID of the player to create is not in the query.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "API key not received.",
-                                        "description" => "No API key was suplied in the request.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "401",
-                                        "message" => "Invalid credentials",
-                                        "description" => "The API key is not valid for the profile being updated.",
-                                        "example" => null
-                                    ]
+                            ]
+                        ],
+                        [
+                            "id" => "PUT",
+                            "url" => "/profile/{id}/",
+                            "description" => "Updates a player profile with data received from the game.",
+                            "parameters" => [
+                                [
+                                    "key" => "{id}",
+                                    "via" => "query",
+                                    "type" => "string",
+                                    "description" => "Player ID.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "key",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "API key.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "response",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "JSON received from game server on HubUserLogin command.",
+                                    "optional" => false
                                 ]
                             ],
+                            "responses" => [
+                                [
+                                    "status" => "204",
+                                    "message" => "Profile imported.",
+                                    "description" => null,
+                                    "example" => null,
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "API key not received.",
+                                    "description" => "No API key was suplied in the request.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "No data received.",
+                                    "description" => "Game JSON response not received from request",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "Data is no valid JSON.",
+                                    "description" => "The parameter 'response' contains information, but it's not valid JSON data.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "401",
+                                    "message" => "Invalid credentials",
+                                    "description" => "The API key is not valid for the profile being updated.",
+                                    "example" => null
+                                ]
+                            ]
                         ],
-                    ] // END COMMAND profile
-                ]
-            ], // END CATEGORY Profile
-            [ // BEGIN CATEGORY Run
-                "name" => "Run",
-                "command" => [
-                    [ // BEGIN COMMAND run
-                        "name" => "run",
-                        "method" => [
-                            [
-                                "id" => "POST",
-                                "url" => "/run/",
-                                "description" => "Logs a game run using JSON files intercepted from the game.",
-                                "parameters" => [
-                                    [
-                                        "key" => "key",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "API key.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "result_response",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "JSON received from game server on run result.",
-                                        "optional" => false
-                                    ],
-                                    [
-                                        "key" => "result_request",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "JSON sent to game server on run result. Required for commands: BattleDungeonResult_V2, BattleDimensionHoleDungeonResult_v2",
-                                        "optional" => true
-                                    ],
-                                    [
-                                        "key" => "start_response",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "JSON received from game server on run start. Required for commands: BattleRiftOfWorldsRaidResult, BattleScenarioResult",
-                                        "optional" => true
-                                    ],
-                                    [
-                                        "key" => "start_request",
-                                        "via" => "body",
-                                        "type" => "string",
-                                        "description" => "JSON sent to game server on run start. Required for commands: ",
-                                        "optional" => true
-                                    ],
-                                ],
-                                "responses" => [
-                                    [
-                                        "status" => "201",
-                                        "message" => "Created.",
-                                        "description" => null,
-                                        "example" => null,
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "API key not received.",
-                                        "description" => "No API key was suplied in the request.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "No result response data received.",
-                                        "description" => "JSON received from game server on run result wast receiven on the request.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "400",
-                                        "message" => "Result response data is no valid JSON.",
-                                        "description" => "The parameter 'result_response' contains information, but it's not valid JSON data.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "401",
-                                        "message" => "Invalid credentials",
-                                        "description" => "The API key is not valid for the profile being updated.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "405",
-                                        "message" => "Command not implemented.",
-                                        "description" => "The command referenced in the JSON file is not implemented.",
-                                        "example" => null
-                                    ],
-                                    [
-                                        "status" => "409",
-                                        "message" => "Run already in database.",
-                                        "description" => "The run is already in the database for the user.",
-                                        "example" => null
-                                    ]
+                        [
+                            "id" => "DELETE",
+                            "url" => "/profile/{id}/",
+                            "description" => "Deletes a player profile.",
+                            "parameters" => [
+                                [
+                                    "key" => "{id}",
+                                    "via" => "query",
+                                    "type" => "string",
+                                    "description" => "Player ID.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "key",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "API key.",
+                                    "optional" => false
                                 ]
                             ],
+                            "responses" => [
+                                [
+                                    "status" => "204",
+                                    "message" => "Profile deleted.",
+                                    "description" => null,
+                                    "example" => null,
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "User ID not received.",
+                                    "description" => "The ID of the player to create is not in the query.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "API key not received.",
+                                    "description" => "No API key was suplied in the request.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "401",
+                                    "message" => "Invalid credentials",
+                                    "description" => "The API key is not valid for the profile being updated.",
+                                    "example" => null
+                                ]
+                            ]
+                        ],
+                    ],
+                ] // END COMMAND profile
+            ]
+        ], // END CATEGORY Profile
+        [ // BEGIN CATEGORY Run
+            "name" => "Run",
+            "command" => [
+                [ // BEGIN COMMAND run
+                    "name" => "run",
+                    "method" => [
+                        [
+                            "id" => "POST",
+                            "url" => "/run/",
+                            "description" => "Logs a game run using JSON files intercepted from the game.",
+                            "parameters" => [
+                                [
+                                    "key" => "key",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "API key.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "result_response",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "JSON received from game server on run result.",
+                                    "optional" => false
+                                ],
+                                [
+                                    "key" => "result_request",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "JSON sent to game server on run result. Required for commands: BattleDungeonResult_V2, BattleDimensionHoleDungeonResult_v2",
+                                    "optional" => true
+                                ],
+                                [
+                                    "key" => "start_response",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "JSON received from game server on run start. Required for commands: BattleRiftOfWorldsRaidResult, BattleScenarioResult",
+                                    "optional" => true
+                                ],
+                                [
+                                    "key" => "start_request",
+                                    "via" => "body",
+                                    "type" => "string",
+                                    "description" => "JSON sent to game server on run start. Required for commands: ",
+                                    "optional" => true
+                                ],
+                            ],
+                            "responses" => [
+                                [
+                                    "status" => "201",
+                                    "message" => "Created.",
+                                    "description" => null,
+                                    "example" => null,
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "API key not received.",
+                                    "description" => "No API key was suplied in the request.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "No result response data received.",
+                                    "description" => "JSON received from game server on run result wast receiven on the request.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "400",
+                                    "message" => "Result response data is no valid JSON.",
+                                    "description" => "The parameter 'result_response' contains information, but it's not valid JSON data.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "401",
+                                    "message" => "Invalid credentials",
+                                    "description" => "The API key is not valid for the profile being updated.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "405",
+                                    "message" => "Command not implemented.",
+                                    "description" => "The command referenced in the JSON file is not implemented.",
+                                    "example" => null
+                                ],
+                                [
+                                    "status" => "409",
+                                    "message" => "Run already in database.",
+                                    "description" => "The run is already in the database for the user.",
+                                    "example" => null
+                                ]
+                            ]
                         ],
-                    ] // END COMMAND Run
-                ]
-            ], // END CATEGORY Run
-        ],
-    ];
-?>
+                    ],
+                ] // END COMMAND Run
+            ]
+        ], // END CATEGORY Run
+    ],
+];

+ 8 - 8
application/API/v1/help/index.php

@@ -1,12 +1,12 @@
 <?php
-    /**
-     * API Help view.
-     *
-     * Shows API documentation.
-     *
-     * @category View
-     * @var mixed[] $API API help structure.
-     */
+/**
+ * API Help view.
+ *
+ * Shows API documentation.
+ *
+ * @category API
+ * @var mixed[] $API API help structure.
+ */
 ?>
 <?php
     include __DIR__ . "/api.php";

+ 25 - 16
application/API/v1/main.php

@@ -1,17 +1,26 @@
 <?php
-    header("Content-Type:application/json");
-    $links = [
-        "Archetypes" => URL::BASE . "/API/v1/archetypes",
-        "Area types" => URL::BASE . "/API/v1/area_types",
-        "Areas types" => URL::BASE . "/API/v1/areas",
-        "Buildings" => URL::BASE . "/API/v1/buildings",
-        "Decorations" => URL::BASE . "/API/v1/decorations",
-        "Areas types" => URL::BASE . "/API/v1/areas",
-        "Units" => URL::BASE . "/API/v1/units",
-        "Skills" => URL::BASE . "/API/v1/skills",
-        "Skill effects" => URL::BASE . "/API/v1/skill_efects",
-    ];
-    header("HTTP/1.1 200");
-    $json_response = json_encode($links);
-    echo $json_response;
-?>
+/**
+ * v1 API main view.
+ *
+ * Linkks to all API commands.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category API
+ */
+header("Content-Type:application/json");
+$links = [
+    "Archetypes" => URL::BASE . "/API/v1/archetypes",
+    "Area types" => URL::BASE . "/API/v1/area_types",
+    "Areas types" => URL::BASE . "/API/v1/areas",
+    "Buildings" => URL::BASE . "/API/v1/buildings",
+    "Decorations" => URL::BASE . "/API/v1/decorations",
+    "Areas types" => URL::BASE . "/API/v1/areas",
+    "Units" => URL::BASE . "/API/v1/units",
+    "Skills" => URL::BASE . "/API/v1/skills",
+    "Skill effects" => URL::BASE . "/API/v1/skill_efects",
+];
+header("HTTP/1.1 200");
+$json_response = json_encode($links);
+echo $json_response;

+ 123 - 121
application/API/v1/profile/DELETE.php

@@ -1,133 +1,135 @@
 <?php
-    /**
-     * Profile deleter script.
-     *
-     * Exposes an API to update an existing profile.
-     *
-     * It also saves the data to a JSON file in the data directory.
-     *
-     * Mandatory query parameters are:
-     *  - id: Player ID.
-     *
-     * Mandatory DELETE parameters are:
-     *  - key: User API key.
-     *
-     * @category API
-     */
+/**
+ * Profile deleter script.
+ *
+ * Exposes an API to update an existing profile.
+ *
+ * It also saves the data to a JSON file in the data directory.
+ *
+ * Mandatory query parameters are:
+ *  - id: Player ID.
+ *
+ * Mandatory DELETE parameters are:
+ *  - key: User API key.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category API
+ */
 
-    try{
+try{
 
-        header("Content-type: application/json; charset=utf-8");
+    header("Content-type: application/json; charset=utf-8");
 
-        // Get put data
-        $_DELETE = [];
-        parse_str(file_get_contents("php://input"), $_DELETE);
+    // Get put data
+    $_DELETE = [];
+    parse_str(file_get_contents("php://input"), $_DELETE);
 
-        // Get profile ID
-        /** @var mixed $query Request parameters, from API_CONTROLLER*/
-        if (count($query) > 0){
-            $player_id = $query[0];
-        }
-        else{
-            // ID is mandatory
-            header("HTTP/1.1 400 User ID not received.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User ID not received.");
-            return 400;
-        }
+    // Get profile ID
+    /** @var mixed $query Request parameters, from API_CONTROLLER*/
+    if (count($query) > 0){
+        $player_id = $query[0];
+    }
+    else{
+        // ID is mandatory
+        header("HTTP/1.1 400 User ID not received.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User ID not received.");
+        return 400;
+    }
 
-        // Check API key.
-        $api_key = $_DELETE["key"];
-        if ($api_key == null || $api_key == false){
-            header("HTTP/1.1 400 API key not received.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
-            return 400;
-        }
+    // Check API key.
+    $api_key = $_DELETE["key"];
+    if ($api_key == null || $api_key == false){
+        header("HTTP/1.1 400 API key not received.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
+        return 400;
+    }
 
-        $db = get_context()->get_db();
+    $db = get_context()->get_db();
 
-        // Authenticate
-        $statement = $db->prepare("
-          SELECT COUNT(player.id) AS c 
-          FROM
-            user,
-            player
-          WHERE
-            user.id = player.user AND
-            player.id = :id AND
-            user.api_key = :api_key;
-        ");
-        $statement->bindValue(":id", $player_id, SQLITE3_INTEGER);
-        $statement->bindValue(":api_key", $api_key, SQLITE3_TEXT);
-        if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
-            header("HTTP/1.1 401 Invalid credentials.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
-            return 401;
-        }
+    // Authenticate
+    $statement = $db->prepare("
+      SELECT COUNT(player.id) AS c 
+      FROM
+        user,
+        player
+      WHERE
+        user.id = player.user AND
+        player.id = :id AND
+        user.api_key = :api_key;
+    ");
+    $statement->bindValue(":id", $player_id, SQLITE3_INTEGER);
+    $statement->bindValue(":api_key", $api_key, SQLITE3_TEXT);
+    if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
+        header("HTTP/1.1 401 Invalid credentials.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
+        return 401;
+    }
 
-        // Delete all player data
-        $db->query("PRAGMA foreign_keys = OFF;");
-        $statement = $db->prepare(
-          "DELETE FROM unit_skill
-          WHERE unit IN (SELECT id FROM unit WHERE player = :player);
-        ");
-        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
-        $statement->execute();
-        $statement = $db->prepare("
-          DELETE FROM unit_rune 
-          WHERE unit IN (SELECT id FROM unit WHERE player = :player);
-        ");
-        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
-        $statement->execute();
-        $statement = $db->prepare("
-          DELETE FROM rune_stat
-          WHERE rune IN (SELECT id FROM rune WHERE player = :player);
-        ");
-        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
-        $statement->execute();
-        $statement = $db->prepare("
-          DELETE FROM unit_artifact
-          WHERE unit IN (SELECT id FROM unit WHERE player = :player);n        ");
-        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
-        $statement->execute();
-        $statement = $db->prepare("
-          DELETE FROM artifact_stat
-          WHERE artifact IN (SELECT id FROM artifact WHERE player = :player);n        ");
-        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
-        $statement->execute();
-        $statement = $db->prepare("
-          DELETE FROM artifact_effect
-          WHERE artifact IN (SELECT id FROM artifact WHERE player = :player);n        ");
+    // Delete all player data
+    $db->query("PRAGMA foreign_keys = OFF;");
+    $statement = $db->prepare(
+      "DELETE FROM unit_skill
+      WHERE unit IN (SELECT id FROM unit WHERE player = :player);
+    ");
+    $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
+    $statement->execute();
+    $statement = $db->prepare("
+      DELETE FROM unit_rune 
+      WHERE unit IN (SELECT id FROM unit WHERE player = :player);
+    ");
+    $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
+    $statement->execute();
+    $statement = $db->prepare("
+      DELETE FROM rune_stat
+      WHERE rune IN (SELECT id FROM rune WHERE player = :player);
+    ");
+    $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
+    $statement->execute();
+    $statement = $db->prepare("
+      DELETE FROM unit_artifact
+      WHERE unit IN (SELECT id FROM unit WHERE player = :player);n        ");
+    $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
+    $statement->execute();
+    $statement = $db->prepare("
+      DELETE FROM artifact_stat
+      WHERE artifact IN (SELECT id FROM artifact WHERE player = :player);n        ");
+    $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
+    $statement->execute();
+    $statement = $db->prepare("
+      DELETE FROM artifact_effect
+      WHERE artifact IN (SELECT id FROM artifact WHERE player = :player);n        ");
+    $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
+    $statement->execute();
+    $tables_to_clear = [
+        "defense",
+        "unit",
+        "rune",
+        "artifact",
+        "building",
+        "decoration",
+        "item",
+        "enchantment"
+    ];
+    foreach ($tables_to_clear as $table){
+        $statement = $db->prepare("DELETE FROM $table WHERE player = :player;");
         $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->execute();
-        $tables_to_clear = [
-            "defense",
-            "unit",
-            "rune",
-            "artifact",
-            "building",
-            "decoration",
-            "item",
-            "enchantment"
-        ];
-        foreach ($tables_to_clear as $table){
-            $statement = $db->prepare("DELETE FROM $table WHERE player = :player;");
-            $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
-            $statement->execute();
-        }
-        $statement = $db->prepare("
-          DELETE FROM player
-          WHERE id = :id
-        ");
-        $statement->bindValue(":id", $player_id, SQLITE3_INTEGER);
-        $statement->execute();
-
-        header("HTTP/1.1 204 Profile deleted.");
-        syslog(LOG_INFO, "[APIv1] HTTP/1.1 204 Profile deleted.");
-        return 204;
     }
-    catch(Exception $e) {
-        header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
-        return 500;
-    }
-?>
+    $statement = $db->prepare("
+      DELETE FROM player
+      WHERE id = :id
+    ");
+    $statement->bindValue(":id", $player_id, SQLITE3_INTEGER);
+    $statement->execute();
+
+    header("HTTP/1.1 204 Profile deleted.");
+    syslog(LOG_INFO, "[APIv1] HTTP/1.1 204 Profile deleted.");
+    return 204;
+}
+catch(Exception $e) {
+    header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
+    syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+    return 500;
+}

+ 79 - 77
application/API/v1/profile/GET.php

@@ -1,84 +1,86 @@
 <?php
-    /**
-     * Profile getter script.
-     *
-     * Exposes an API to rerieve a user profile.
-     *
-     * A lst of profiles can't be retrieved.
-     *
-     * Mandatory query parameters are:
-     *  - id: Player ID.
-     *
-     * Optional GET parameters are.
-     *  - key: User API key to retrieve a private profile.
-     *
-     * @category API
-     */
+/**
+ * Profile getter script.
+ *
+ * Exposes an API to rerieve a user profile.
+ *
+ * A lst of profiles can't be retrieved.
+ *
+ * Mandatory query parameters are:
+ *  - id: Player ID.
+ *
+ * Optional GET parameters are.
+ *  - key: User API key to retrieve a private profile.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category API
+ */
 
-    try{
-        header("Content-type: application/json; charset=utf-8");
+try{
+    header("Content-type: application/json; charset=utf-8");
 
-        // Get profile ID
-        /** @var mixed $query Request parameters, from API_CONTROLLER*/
-        if (count($query) > 1){
-            $id = $query[0];
-        }
-        else{
-            // Id is mandatory, a list can be retrieved
-            header("HTTP/1.1 403 A list of profiles cant be retrieved. Please specify a profile ID or player name.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 403 A list of profiles cant be retrieved. Please specify a profile ID or player name.");
-            return 403;
-        }
-
-        $db = get_context()->get_db();
-
-        // Get player
-        $statement = $db->prepare("
-          SELECT
-            user.api_key AS api_key,
-            player.id AS id,
-            player.public AS public
-          FROM
-            user,
-            player
-          WHERE
-            user.id = player.user AND
-            player.id = :id AND
-            user.api_key = :api_key;
-        ");
-        $statement->bindValue(":id", $id, SQLITE3_INTEGER);
-        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-        if ($r == null){
-            // No player found
-            header("HTTP/1.1 404 Player not found.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 404 Player not found.");
-            return 403;
-        }
-        if ($r["public"] != 1 && $r["key"] != filter_input(INPUT_GET, "key")){
-            header("HTTP/1.1 403 The profile is not public.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 403 The profile is not public.");
-            return 403;
-        }
+    // Get profile ID
+    /** @var mixed $query Request parameters, from API_CONTROLLER*/
+    if (count($query) > 1){
+        $id = $query[0];
+    }
+    else{
+        // Id is mandatory, a list can be retrieved
+        header("HTTP/1.1 403 A list of profiles cant be retrieved. Please specify a profile ID or player name.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 403 A list of profiles cant be retrieved. Please specify a profile ID or player name.");
+        return 403;
+    }
 
-        // Permission granted, get player data.
-        $player_id = $r["player_id"];
-        $player = new Player($player_id);
+    $db = get_context()->get_db();
 
-        // Build array
-        // TODO: Add way more data
-        $player = [
-            "username" => $player->get_name(),
-            "level" => $player->get_level(),
-            "public" => $player->is_public()
-        ];
-        echo(json_encode($player));
-        header("HTTP/1.1 200 Success.");
-        syslog(LOG_INFO, "[APIv1] HTTP/1.1 200 Success.");
-        return 200;
+    // Get player
+    $statement = $db->prepare("
+      SELECT
+        user.api_key AS api_key,
+        player.id AS id,
+        player.public AS public
+      FROM
+        user,
+        player
+      WHERE
+        user.id = player.user AND
+        player.id = :id AND
+        user.api_key = :api_key;
+    ");
+    $statement->bindValue(":id", $id, SQLITE3_INTEGER);
+    $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+    if ($r == null){
+        // No player found
+        header("HTTP/1.1 404 Player not found.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 404 Player not found.");
+        return 403;
     }
-    catch(Exception $e) {
-        header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
-        return 500;
+    if ($r["public"] != 1 && $r["key"] != filter_input(INPUT_GET, "key")){
+        header("HTTP/1.1 403 The profile is not public.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 403 The profile is not public.");
+        return 403;
     }
-?>
+
+    // Permission granted, get player data.
+    $player_id = $r["player_id"];
+    $player = new Player($player_id);
+
+    // Build array
+    // TODO: Add way more data
+    $player = [
+        "username" => $player->get_name(),
+        "level" => $player->get_level(),
+        "public" => $player->is_public()
+    ];
+    echo(json_encode($player));
+    header("HTTP/1.1 200 Success.");
+    syslog(LOG_INFO, "[APIv1] HTTP/1.1 200 Success.");
+    return 200;
+}
+catch(Exception $e) {
+    header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
+    syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+    return 500;
+}

+ 235 - 233
application/API/v1/profile/POST.php

@@ -1,244 +1,246 @@
 <?php
-    /**
-     * Profile creator script.
-     *
-     * Exposes an API to create a new profile.
-     *
-     * Mandatory query parameters are:
-     *  - id: Player ID.
-     *
-     * Mandatory POST parameters are:
-     *  - key: User API key.
-     *
-     * Optional POST parameters are:
-     *  - name: User name.
-     *  - public: 1 To make the profile public, 0 for private.
-     *
-     * @category API
-     */
+/**
+ * Profile creator script.
+ *
+ * Exposes an API to create a new profile.
+ *
+ * Mandatory query parameters are:
+ *  - id: Player ID.
+ *
+ * Mandatory POST parameters are:
+ *  - key: User API key.
+ *
+ * Optional POST parameters are:
+ *  - name: User name.
+ *  - public: 1 To make the profile public, 0 for private.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category API
+ */
 
-    try{
+try{
 
-        header("Content-type: application/json; charset=utf-8");
+    header("Content-type: application/json; charset=utf-8");
 
-        // Get put data
-        parse_str(file_get_contents("php://input"), $_POST);
+    // Get put data
+    parse_str(file_get_contents("php://input"), $_POST);
 
-        // Get profile ID
-        /** @var mixed $query Request parameters, from API_CONTROLLER*/
-        if (count($query) > 0){
-            $id = $query[0];
-        }
-        else{
-            // ID is mandatory
-            header("HTTP/1.1 400 User ID not received.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User ID not received.");
-            return 400;
-        }
-
-        // Check user mail.
-        $mail = $_POST["email"];
-        if ($mail == null || $mail == false){
-            header("HTTP/1.1 400 User email not received.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User email not received.");
-            return 400;
-        }
-        if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) {
-            header("HTTP/1.1 400 Invalid email.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Invalid email.");
-            return 400;
-        }
-        // Check user password.
-        $password = $_POST["password"];
-        if ($password == null || $password == false){
-            header("HTTP/1.1 400 User password not received.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User password not received.");
-            return 400;
-        }
-        // Check user name.
-        $name = $_POST["name"];
-        if ($name == null || $name == false){
-            $name = "player_" . $id;
-        }
-        // Check user name.
-        $public = intval($_POST["public"]);
-        if ($public != 1){
-            $public = 0;
-        }
-
-        $db = get_context()->get_db();
+    // Get profile ID
+    /** @var mixed $query Request parameters, from API_CONTROLLER*/
+    if (count($query) > 0){
+        $id = $query[0];
+    }
+    else{
+        // ID is mandatory
+        header("HTTP/1.1 400 User ID not received.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User ID not received.");
+        return 400;
+    }
 
-        // Check if player exists
-        $statement = $db->prepare("SELECT COUNT(id) AS c FROM data.player WHERE id = :id;");
-        $statement->bindValue(":id", $id, SQLITE3_INTEGER);
-        if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
-            header("HTTP/1.1 400 Existing user.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Existing user.");
-            return 400;
-        }
+    // Check user mail.
+    $mail = $_POST["email"];
+    if ($mail == null || $mail == false){
+        header("HTTP/1.1 400 User email not received.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User email not received.");
+        return 400;
+    }
+    if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) {
+        header("HTTP/1.1 400 Invalid email.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Invalid email.");
+        return 400;
+    }
+    // Check user password.
+    $password = $_POST["password"];
+    if ($password == null || $password == false){
+        header("HTTP/1.1 400 User password not received.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User password not received.");
+        return 400;
+    }
+    // Check user name.
+    $name = $_POST["name"];
+    if ($name == null || $name == false){
+        $name = "player_" . $id;
+    }
+    // Check user name.
+    $public = intval($_POST["public"]);
+    if ($public != 1){
+        $public = 0;
+    }
 
-        // Get and validate API key
-        $api_key = $_POST["key"];
-        if ($api_key == null || $api_key == false){
-            header("HTTP/1.1 400 API key not received.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
-            return 400;
-        }
-        $statement = $db->prepare("
-          SELECT id
-          FROM user
-          WHERE api_key = :api_key;
-        ");
-        $statement->bindValue(":api_key", $api_key, SQLITE3_TEXT);
-        $statement->execute();
-        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-        if ($r == null){
-            // No valid API key found
-            header("HTTP/1.1 404 Player not found.");
-            syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid API key.");
-            return 403;
-        }
-        $user_id = $r["id"];
+    $db = get_context()->get_db();
 
-        // Insert
-        // TODO: Get user ID, check fields
-        $statement = $db->prepare("
-          INSERT INTO data.player (
-            id,
-            user,
-            server,
-            country,
-            lang,
-            name,
-            mana,
-            crystal,
-            level,
-            experience,
-            energy,
-            energy_max,
-            energy_per_min,
-            arena_energy,
-            rep,
-            social_point,
-            honor_point,
-            guild_point,
-            darkportal_energy,
-            dimension_energy,
-            costume_point,
-            honor_medal,
-            honor_mark,
-            event_coin,
-            storage_slots,
-            island,
-            joined,
-            top_rank_arena,
-            top_rank_world_arena,
-            top_rank_special_league,
-            top_rank_gw,
-            top_rank_siege,
-            top_rank_wboss,
-            top_rank_toan,
-            top_rank_toah,
-            top_rank_toal,
-            public,
-            mode,
-            last_access
-          ) VALUES (
-            :id,
-            :user,
-            :server,
-            :country,
-            :lang,
-            :name,
-            :mana,
-            :crystal,
-            :level,
-            :experience,
-            :energy,
-            :energy_max,
-            :energy_per_min,
-            :arena_energy,
-            :rep,
-            :social_point,
-            :honor_point,
-            :guild_point,
-            :darkportal_energy,
-            :dimension_energy,
-            :costume_point,
-            :honor_medal,
-            :honor_mark,
-            :event_coin,
-            :storage_slots,
-            :island,
-            :joined,
-            :top_rank_arena,
-            :top_rank_world_arena,
-            :top_rank_special_league,
-            :top_rank_gw,
-            :top_rank_siege,
-            :top_rank_wboss,
-            :top_rank_toan,
-            :top_rank_toah,
-            :top_rank_toal,
-            :public,
-            :mode,
-            :last_access
-          );
-        ");
-        $statement->bindValue(":id", $id, SQLITE3_INTEGER);
-        $statement->bindValue(":user", $user_id, SQLITE3_INTEGER);
-        $statement->bindValue(":server", null, SQLITE3_INTEGER);
-        $statement->bindValue(":country", null, SQLITE3_INTEGER);
-        $statement->bindValue(":lang", null, SQLITE3_INTEGER);
-        $statement->bindValue(":name", $name, SQLITE3_INTEGER);
-        $statement->bindValue(":mana", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":crystal", 0, SQLIE3_INTTE3_INTEGER);
-        $statement->bindValue(":level", 1, SQLITEGER);
-        $statement->bindValue(":experience", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":energy", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":energy_max", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":energy_per_min", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":arena_energy", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":rep", null, SQLITE3_INTEGER);
-        $statement->bindValue(":social_point", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":honor_point", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":guild_point", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":darkportal_energy", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":dimension_energy", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":costume_point", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":honor_medal", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":honor_mark", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":event_coin", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":storage_slots", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":island", 1, SQLITE3_INTEGER);
-        $statement->bindValue(":joined", null, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_arena", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_world_arena", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_special_league", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_gw", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_siege", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_wboss", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_toan", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_toah", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":top_rank_toal", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":public", $public, SQLITE3_INTEGER);
-        $statement->bindValue(":mode", 0, SQLITE3_INTEGER);
-        $statement->bindValue(":last_access", null, SQLITE3_INTEGER);
-        $statement->execute();
+    // Check if player exists
+    $statement = $db->prepare("SELECT COUNT(id) AS c FROM data.player WHERE id = :id;");
+    $statement->bindValue(":id", $id, SQLITE3_INTEGER);
+    if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
+        header("HTTP/1.1 400 Existing user.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Existing user.");
+        return 400;
+    }
 
-        // Build array
-        $player = [
-            "username" => $name,
-            "public" => "1"
-        ];
-        echo(json_encode($player));
-        header("HTTP/1.1 201 Created.");
-        syslog(LOG_INFO, "[APIv1] HTTP/1.1 201 Created.");
-        return 201;
+    // Get and validate API key
+    $api_key = $_POST["key"];
+    if ($api_key == null || $api_key == false){
+        header("HTTP/1.1 400 API key not received.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
+        return 400;
     }
-    catch(Exception $e) {
-        header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
-        return 500;
+    $statement = $db->prepare("
+      SELECT id
+      FROM user
+      WHERE api_key = :api_key;
+    ");
+    $statement->bindValue(":api_key", $api_key, SQLITE3_TEXT);
+    $statement->execute();
+    $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+    if ($r == null){
+        // No valid API key found
+        header("HTTP/1.1 404 Player not found.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid API key.");
+        return 403;
     }
-?>
+    $user_id = $r["id"];
+
+    // Insert
+    // TODO: Get user ID, check fields
+    $statement = $db->prepare("
+      INSERT INTO data.player (
+        id,
+        user,
+        server,
+        country,
+        lang,
+        name,
+        mana,
+        crystal,
+        level,
+        experience,
+        energy,
+        energy_max,
+        energy_per_min,
+        arena_energy,
+        rep,
+        social_point,
+        honor_point,
+        guild_point,
+        darkportal_energy,
+        dimension_energy,
+        costume_point,
+        honor_medal,
+        honor_mark,
+        event_coin,
+        storage_slots,
+        island,
+        joined,
+        top_rank_arena,
+        top_rank_world_arena,
+        top_rank_special_league,
+        top_rank_gw,
+        top_rank_siege,
+        top_rank_wboss,
+        top_rank_toan,
+        top_rank_toah,
+        top_rank_toal,
+        public,
+        mode,
+        last_access
+      ) VALUES (
+        :id,
+        :user,
+        :server,
+        :country,
+        :lang,
+        :name,
+        :mana,
+        :crystal,
+        :level,
+        :experience,
+        :energy,
+        :energy_max,
+        :energy_per_min,
+        :arena_energy,
+        :rep,
+        :social_point,
+        :honor_point,
+        :guild_point,
+        :darkportal_energy,
+        :dimension_energy,
+        :costume_point,
+        :honor_medal,
+        :honor_mark,
+        :event_coin,
+        :storage_slots,
+        :island,
+        :joined,
+        :top_rank_arena,
+        :top_rank_world_arena,
+        :top_rank_special_league,
+        :top_rank_gw,
+        :top_rank_siege,
+        :top_rank_wboss,
+        :top_rank_toan,
+        :top_rank_toah,
+        :top_rank_toal,
+        :public,
+        :mode,
+        :last_access
+      );
+    ");
+    $statement->bindValue(":id", $id, SQLITE3_INTEGER);
+    $statement->bindValue(":user", $user_id, SQLITE3_INTEGER);
+    $statement->bindValue(":server", null, SQLITE3_INTEGER);
+    $statement->bindValue(":country", null, SQLITE3_INTEGER);
+    $statement->bindValue(":lang", null, SQLITE3_INTEGER);
+    $statement->bindValue(":name", $name, SQLITE3_INTEGER);
+    $statement->bindValue(":mana", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":crystal", 0, SQLIE3_INTTE3_INTEGER);
+    $statement->bindValue(":level", 1, SQLITEGER);
+    $statement->bindValue(":experience", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":energy", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":energy_max", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":energy_per_min", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":arena_energy", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":rep", null, SQLITE3_INTEGER);
+    $statement->bindValue(":social_point", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":honor_point", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":guild_point", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":darkportal_energy", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":dimension_energy", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":costume_point", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":honor_medal", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":honor_mark", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":event_coin", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":storage_slots", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":island", 1, SQLITE3_INTEGER);
+    $statement->bindValue(":joined", null, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_arena", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_world_arena", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_special_league", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_gw", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_siege", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_wboss", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_toan", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_toah", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":top_rank_toal", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":public", $public, SQLITE3_INTEGER);
+    $statement->bindValue(":mode", 0, SQLITE3_INTEGER);
+    $statement->bindValue(":last_access", null, SQLITE3_INTEGER);
+    $statement->execute();
+
+    // Build array
+    $player = [
+        "username" => $name,
+        "public" => "1"
+    ];
+    echo(json_encode($player));
+    header("HTTP/1.1 201 Created.");
+    syslog(LOG_INFO, "[APIv1] HTTP/1.1 201 Created.");
+    return 201;
+}
+catch(Exception $e) {
+    header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
+    syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+    return 500;
+}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 517 - 486
application/API/v1/profile/PUT.php


Dosya farkı çok büyük olduğundan ihmal edildi
+ 887 - 477
application/API/v1/run/POST.php


+ 425 - 422
application/API/v1/units/GET.php

@@ -1,454 +1,457 @@
 <?php
-    /**
-     * Unit getter script.
-     *
-     * Exposes an API to rerieve unit info.
-     *
-     * Optional query parameters are:
-     *  - id: Unit ID.
-     *
-     * @category API
-     */
+/**
+ * Unit getter script.
+ *
+ * Exposes an API to rerieve unit info.
+ *
+ * Optional query parameters are:
+ *  - id: Unit ID.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category API
+ */
 
-    /**
-     * Gets info on a unit.
-     *
-     * @param resource $db Database connection.
-     * @param int $id Unit identifier
-     * @return mixed[] Content.
-     */
-    function get_unit($id){
-        $result = [
-            "status" => 404,
-            "message" => "Unit not found",
-            "content" => ""
+/**
+ * Gets info on a unit.
+ *
+ * @param resource $db Database connection.
+ * @param int $id Unit identifier
+ * @return mixed[] Content.
+ */
+function get_unit($id){
+    $result = [
+        "status" => 404,
+        "message" => "Unit not found",
+        "content" => ""
+    ];
+    $db = get_context()->get_db();
+    $statement = $db->prepare("
+      SELECT
+        monster.id AS id,
+        monster.name AS name,
+        monster.family AS family,
+        monster.element AS element,
+        element.name AS element_name,
+        monster.archetype AS archetype,
+        archetype.name AS archetype_name,
+        monster.base_stars AS base_stars,
+        monster.natural_stars AS natural_stars,
+        monster.obtainable AS obtainable,
+        monster.awakens_from AS awakens_from,
+        monster.awakens_to AS awakens_to,
+        monster.homunculus AS homunculus,
+        monster.hp AS hp,
+        monster.attack AS attack,
+        monster.defense AS defense,
+        monster.speed AS speed,
+        monster.crit_rate AS crit_rate,
+        monster.crit_damage AS crit_damage,
+        monster.accuracy AS accuracy,
+        monster.resistance AS resistance,
+        monster.leader_skill AS leader_skill
+      FROM
+        monster,
+        element,
+        archetype
+      WHERE
+        monster.element = element.id AND
+        monster.archetype = archetype.id AND
+        monster.id = :id ;
+    ");
+    $statement->bindValue(":id", $id, SQLITE3_TEXT);
+    $q = $statement->execute();
+    $r = $q->fetchArray(SQLITE3_ASSOC);
+    if ($r){
+        $unit = [
+            "id" => $r["id"],
+            "url" => URL::BASE . "API/v1/units/" . $r["id"] . "/",
+            "name" => $r["name"],
+            "family" => $r["family"],
+            "image" => APPLICATION::img("UNIT", $r["id"]),
+            "element" => $r["element"],
+            "element_name" => $r["element_name"],
+            "archetype" => $r["archetype"],
+            "archetype_name" => $r["archetype_name"],
+            "stars" => $r["base_stars"],
+            "natural_stars" => $r["natural_stars"],
+            "obtainable" => (($r["obtainable"] == 1) ? (true) : (false)),
+            "awakens_from" => $r["awakens_from"],
+            "awakens_to" => $r["awakens_to"],
+            "homunculus" => (($r["homunculus"] == 1) ? (true) : (false)),
+            "hp" => $r["hp"],
+            "attack" => $r["attack"],
+            "defense" => $r["defense"],
+            "speed" => $r["speed"],
+            "critical_rate" => $r["crit_rate"],
+            "critical_damage" => $r["crit_damage"],
+            "accuracy" => $r["accuracy"],
+            "resistance" => $r["resistance"],
+            "leader_skill" => null,
+            "skills" => [],
         ];
-        $db = get_context()->get_db();
-        $statement = $db->prepare("
+
+        // Leader_skill
+        if ($r["leader_skill"] != null){
+            $statement_leader = $db->prepare("
+            SELECT
+                leader_skill.id AS id,
+                leader_skill.stat AS stat,
+                stat.name AS stat_name,
+                leader_skill.amount AS amount,
+                leader_skill.area AS area,
+                effect_area.name AS area_name,
+                leader_skill.element AS element,
+                element.name AS element_name
+            FROM
+                leader_skill,
+                stat,
+                effect_area,
+                element
+            WHERE
+                leader_skill.id = :id AND
+                leader_skill.stat = stat.id AND
+                leader_skill.area = effect_area.id AND
+                leader_skill.element = element.id;
+            ");
+            $statement_leader->bindValue(":id", $r["leader_skill"], SQLITE3_INTEGER);
+            $q_leader = $statement_leader->execute();
+            $r_leader = $q_leader->fetchArray(SQLITE3_ASSOC);
+            if ($r_leader){
+                $description = "Increases the ";
+                switch ($r_leader["stat"]){
+                    case STAT_ID::ATK:
+                        $description .= "attack power";
+                        break;
+                    case STAT_ID::DEF:
+                        $description .= "defense";
+                        break;
+                    case STAT_ID::HP:
+                        $description .= "HP";
+                        break;
+                    case STAT_ID::SPD:
+                        $description .= "attack speed";
+                        break;
+                    case STAT_ID::CRIT_RATE:
+                        $description .= "critical rate";
+                        break;
+                    case STAT_ID::CRIT_DMG:
+                        $description .= "critical damage";
+                        break;
+                    case STAT_ID::ACCURACY:
+                        $description .= "accuracy";
+                        break;
+                    case STAT_ID::RESIST:
+                        $description .= "resistance";
+                        break;
+                }
+                $description .= " of ally monsters ";
+                switch ($r_leader["element"]){
+                    case ELEMENT_ID::WATER:
+                        $description .= " with Water attribute ";
+                        break;
+                    case ELEMENT_ID::FIRE:
+                        $description .= " with Fire attribute ";
+                        break;
+                    case ELEMENT_ID::WIND:
+                        $description .= " with Wind attribute ";
+                        break;
+                    case ELEMENT_ID::LIGHT:
+                        $description .= " with Light attribute ";
+                        break;
+                    case ELEMENT_ID::DARK:
+                        $description .= " with Dark attribute ";
+                        break;
+                }
+                $description = $description . "by " . $r_leader["amount"] . "%";
+                switch ($r_leader["area"]){
+                    case EFFECT_AREA_ID::DUNGEON:
+                        $description .= " in the Dungeons";
+                        break;
+                    case EFFECT_AREA_ID::ARENA:
+                        $description .= " in the Arena";
+                        break;
+                    case EFFECT_AREA_ID::GUILD:
+                        $description .= " in Guild content";
+                        break;
+                }
+                $description = str_replace("  ", " ", $description) . ".";
+                $unit["leader_skill"] = [
+                    "id" => $r_leader["id"],
+                    "stat" => $r_leader["stat"],
+                    "stat_name" => $r_leader["stat_name"],
+                    "increase" => $r_leader["amount"],
+                    "area" => $r_leader["area"],
+                    "area_name" => $r_leader["area_name"],
+                    "element" => $r_leader["element"],
+                    "element_name" => $r_leader["element_name"],
+                    "description" => $description
+                ];
+            }
+        }
+
+        // Skill
+        $statement_skills = $db->prepare("
           SELECT
-            monster.id AS id,
-            monster.name AS name,
-            monster.family AS family,
-            monster.element AS element,
-            element.name AS element_name,
-            monster.archetype AS archetype,
-            archetype.name AS archetype_name,
-            monster.base_stars AS base_stars,
-            monster.natural_stars AS natural_stars,
-            monster.obtainable AS obtainable,
-            monster.awakens_from AS awakens_from,
-            monster.awakens_to AS awakens_to,
-            monster.homunculus AS homunculus,
-            monster.hp AS hp,
-            monster.attack AS attack,
-            monster.defense AS defense,
-            monster.speed AS speed,
-            monster.crit_rate AS crit_rate,
-            monster.crit_damage AS crit_damage,
-            monster.accuracy AS accuracy,
-            monster.resistance AS resistance,
-            monster.leader_skill AS leader_skill
+            skill.id AS id,
+            skill.slot AS slot,
+            skill.name AS name,
+            skill.description AS description,
+            skill.passive AS passive,
+            skill.cooltime AS cooltime,
+            skill.hits AS hits,
+            skill.aoe AS aoe,
+            skill.multiplier_formula AS multiplier_formula,
+            skill.max_level AS max_level
           FROM
-            monster,
-            element,
-            archetype
+            skill,
+            monster_skill
           WHERE
-            monster.element = element.id AND
-            monster.archetype = archetype.id AND
-            monster.id = :id ;
+            skill.id = monster_skill.skill AND
+            monster_skill.unit = :id 
+          ORDER BY slot;
         ");
-        $statement->bindValue(":id", $id, SQLITE3_TEXT);
-        $q = $statement->execute();
-        $r = $q->fetchArray(SQLITE3_ASSOC);
-        if ($r){
-            $unit = [
-                "id" => $r["id"],
-                "url" => URL::BASE . "API/v1/units/" . $r["id"] . "/",
-                "name" => $r["name"],
-                "family" => $r["family"],
-                "image" => APPLICATION::img("UNIT", $r["id"]),
-                "element" => $r["element"],
-                "element_name" => $r["element_name"],
-                "archetype" => $r["archetype"],
-                "archetype_name" => $r["archetype_name"],
-                "stars" => $r["base_stars"],
-                "natural_stars" => $r["natural_stars"],
-                "obtainable" => (($r["obtainable"] == 1) ? (true) : (false)),
-                "awakens_from" => $r["awakens_from"],
-                "awakens_to" => $r["awakens_to"],
-                "homunculus" => (($r["homunculus"] == 1) ? (true) : (false)),
-                "hp" => $r["hp"],
-                "attack" => $r["attack"],
-                "defense" => $r["defense"],
-                "speed" => $r["speed"],
-                "critical_rate" => $r["crit_rate"],
-                "critical_damage" => $r["crit_damage"],
-                "accuracy" => $r["accuracy"],
-                "resistance" => $r["resistance"],
-                "leader_skill" => null,
-                "skills" => [],
+        $statement_skills->bindValue(":id", $id, SQLITE3_TEXT);
+        $q_skills = $statement_skills->execute();
+        while ($r_skills = $q_skills->fetchArray(SQLITE3_ASSOC)){
+            $skill = [
+                "id" => $r_skills["id"],
+                "slot" => $r_skills["slot"],
+                "name" => $r_skills["name"],
+                "description" => $r_skills["description"],
+                "image" => APPLICATION::img("SKILL", $r_skills["id"]),
+                "passive" => (($r_skills["passive"] == 1) ? (true) : (false)),
+                "cooltime" => $r_skills["cooltime"],
+                "hits" => $r_skills["hits"],
+                "aoe" => (($r_skills["aoe"] == 1) ? (true) : (false)),
+                "effects" => [],
+                "max_level" => $r_skills["max_level"],
+                "upgrades" => [],
+                "formula" => $r_skills["multiplier_formula"]
             ];
-
-            // Leader_skill
-            if ($r["leader_skill"] != null){
-                $statement_leader = $db->prepare("
-                SELECT
-                    leader_skill.id AS id,
-                    leader_skill.stat AS stat,
-                    stat.name AS stat_name,
-                    leader_skill.amount AS amount,
-                    leader_skill.area AS area,
-                    effect_area.name AS area_name,
-                    leader_skill.element AS element,
-                    element.name AS element_name
-                FROM
-                    leader_skill,
-                    stat,
-                    effect_area,
-                    element
-                WHERE
-                    leader_skill.id = :id AND
-                    leader_skill.stat = stat.id AND
-                    leader_skill.area = effect_area.id AND
-                    leader_skill.element = element.id;
-                ");
-                $statement_leader->bindValue(":id", $r["leader_skill"], SQLITE3_INTEGER);
-                $q_leader = $statement_leader->execute();
-                $r_leader = $q_leader->fetchArray(SQLITE3_ASSOC);
-                if ($r_leader){
-                    $description = "Increases the ";
-                    switch ($r_leader["stat"]){
-                        case STAT_ID::ATK:
-                            $description .= "attack power";
-                            break;
-                        case STAT_ID::DEF:
-                            $description .= "defense";
-                            break;
-                        case STAT_ID::HP:
-                            $description .= "HP";
-                            break;
-                        case STAT_ID::SPD:
-                            $description .= "attack speed";
-                            break;
-                        case STAT_ID::CRIT_RATE:
-                            $description .= "critical rate";
-                            break;
-                        case STAT_ID::CRIT_DMG:
-                            $description .= "critical damage";
-                            break;
-                        case STAT_ID::ACCURACY:
-                            $description .= "accuracy";
-                            break;
-                        case STAT_ID::RESIST:
-                            $description .= "resistance";
-                            break;
-                    }
-                    $description .= " of ally monsters ";
-                    switch ($r_leader["element"]){
-                        case ELEMENT_ID::WATER:
-                            $description .= " with Water attribute ";
-                            break;
-                        case ELEMENT_ID::FIRE:
-                            $description .= " with Fire attribute ";
-                            break;
-                        case ELEMENT_ID::WIND:
-                            $description .= " with Wind attribute ";
-                            break;
-                        case ELEMENT_ID::LIGHT:
-                            $description .= " with Light attribute ";
-                            break;
-                        case ELEMENT_ID::DARK:
-                            $description .= " with Dark attribute ";
-                            break;
-                    }
-                    $description = $description . "by " . $r_leader["amount"] . "%";
-                    switch ($r_leader["area"]){
-                        case EFFECT_AREA_ID::DUNGEON:
-                            $description .= " in the Dungeons";
-                            break;
-                        case EFFECT_AREA_ID::ARENA:
-                            $description .= " in the Arena";
-                            break;
-                        case EFFECT_AREA_ID::GUILD:
-                            $description .= " in Guild content";
-                            break;
-                    }
-                    $description = str_replace("  ", " ", $description) . ".";
-                    $unit["leader_skill"] = [
-                        "id" => $r_leader["id"],
-                        "stat" => $r_leader["stat"],
-                        "stat_name" => $r_leader["stat_name"],
-                        "increase" => $r_leader["amount"],
-                        "area" => $r_leader["area"],
-                        "area_name" => $r_leader["area_name"],
-                        "element" => $r_leader["element"],
-                        "element_name" => $r_leader["element_name"],
-                        "description" => $description
-                    ];
-                }
+            // Skill levels
+            $statement_skill_levels = $db->prepare("
+              SELECT
+                level,
+                description
+              FROM skill_level
+              WHERE
+                level > 1 AND
+                skill = :id
+              ORDER BY level;
+            ");
+            $statement_skill_levels->bindValue(":id", $r_skills["id"], SQLITE3_INTEGER);
+            $q_skill_levels = $statement_skill_levels->execute();
+            while ($r_skill_levels = $q_skill_levels->fetchArray(SQLITE3_ASSOC)){
+                $level = [
+                    "level" => $r_skill_levels["level"],
+                    "description" => $r_skill_levels["description"]
+                ];
+                array_push($skill["upgrades"], $level);
             }
-
-            // Skill
-            $statement_skills = $db->prepare("
+            // Skill efffects
+            $statement_skill_effects = $db->prepare("
               SELECT
-                skill.id AS id,
-                skill.slot AS slot,
-                skill.name AS name,
-                skill.description AS description,
-                skill.passive AS passive,
-                skill.cooltime AS cooltime,
-                skill.hits AS hits,
-                skill.aoe AS aoe,
-                skill.multiplier_formula AS multiplier_formula,
-                skill.max_level AS max_level
+                effect.id AS id,
+                effect.is_buff AS is_buff,
+                effect.name AS name,
+                effect.description AS description
               FROM
-                skill,
-                monster_skill
+                effect,
+                skill_effect
               WHERE
-                skill.id = monster_skill.skill AND
-                monster_skill.unit = :id 
-              ORDER BY slot;
+                skill_effect.skill = :id AND
+                skill_effect.effect = effect.id
             ");
-            $statement_skills->bindValue(":id", $id, SQLITE3_TEXT);
-            $q_skills = $statement_skills->execute();
-            while ($r_skills = $q_skills->fetchArray(SQLITE3_ASSOC)){
-                $skill = [
-                    "id" => $r_skills["id"],
-                    "slot" => $r_skills["slot"],
-                    "name" => $r_skills["name"],
-                    "description" => $r_skills["description"],
-                    "image" => APPLICATION::img("SKILL", $r_skills["id"]),
-                    "passive" => (($r_skills["passive"] == 1) ? (true) : (false)),
-                    "cooltime" => $r_skills["cooltime"],
-                    "hits" => $r_skills["hits"],
-                    "aoe" => (($r_skills["aoe"] == 1) ? (true) : (false)),
-                    "effects" => [],
-                    "max_level" => $r_skills["max_level"],
-                    "upgrades" => [],
-                    "formula" => $r_skills["multiplier_formula"]
+            $statement_skill_effects->bindValue(":id", $r_skills["id"], SQLITE3_INTEGER);
+            $q_skill_effects = $statement_skill_effects->execute();
+            while ($r_skill_effects = $q_skill_effects->fetchArray(SQLITE3_ASSOC)){
+                $effect = [
+                    "id" => $r_skill_effects["id"],
+                    "buff" => (($r_skill_effects["is_buff"] == 1) ? (true) : (false)),
+                    "name" => $r_skill_effects["name"],
+                    "description" => $r_skill_effects["description"],
+                    "image" => APPLICATION::img("EFFECT", $r_skill_effects["id"]),
                 ];
-                // Skill levels
-                $statement_skill_levels = $db->prepare("
-                  SELECT
-                    level,
-                    description
-                  FROM skill_level
-                  WHERE
-                    level > 1 AND
-                    skill = :id
-                  ORDER BY level;
-                ");
-                $statement_skill_levels->bindValue(":id", $r_skills["id"], SQLITE3_INTEGER);
-                $q_skill_levels = $statement_skill_levels->execute();
-                while ($r_skill_levels = $q_skill_levels->fetchArray(SQLITE3_ASSOC)){
-                    $level = [
-                        "level" => $r_skill_levels["level"],
-                        "description" => $r_skill_levels["description"]
-                    ];
-                    array_push($skill["upgrades"], $level);
-                }
-                // Skill efffects
-                $statement_skill_effects = $db->prepare("
-                  SELECT
-                    effect.id AS id,
-                    effect.is_buff AS is_buff,
-                    effect.name AS name,
-                    effect.description AS description
-                  FROM
-                    effect,
-                    skill_effect
-                  WHERE
-                    skill_effect.skill = :id AND
-                    skill_effect.effect = effect.id
-                ");
-                $statement_skill_effects->bindValue(":id", $r_skills["id"], SQLITE3_INTEGER);
-                $q_skill_effects = $statement_skill_effects->execute();
-                while ($r_skill_effects = $q_skill_effects->fetchArray(SQLITE3_ASSOC)){
-                    $effect = [
-                        "id" => $r_skill_effects["id"],
-                        "buff" => (($r_skill_effects["is_buff"] == 1) ? (true) : (false)),
-                        "name" => $r_skill_effects["name"],
-                        "description" => $r_skill_effects["description"],
-                        "image" => APPLICATION::img("EFFECT", $r_skill_effects["id"]),
-                    ];
-                    array_push($skill["effects"], $effect);
-                }
-                array_push($unit["skills"], $skill);
+                array_push($skill["effects"], $effect);
             }
-
-            // Add to array
-            $result["content"] = $unit;
-            $result["status"] = 200;
-            $result["message"] = "Success.";
+            array_push($unit["skills"], $skill);
         }
-        return $result;
+
+        // Add to array
+        $result["content"] = $unit;
+        $result["status"] = 200;
+        $result["message"] = "Success.";
     }
+    return $result;
+}
 
-    /**
-     * Gets a list of units, paginated.
-     *
-     * @return mixed[] Content.
-     */
-    function get_unit_list(){
-        $db = get_context()->get_db();
-        $result = [
-            "status" => 200,
-            "message" => "Success.",
-            "content" => ""
-        ];
+/**
+ * Gets a list of units, paginated.
+ *
+ * @return mixed[] Content.
+ */
+function get_unit_list(){
+    $db = get_context()->get_db();
+    $result = [
+        "status" => 200,
+        "message" => "Success.",
+        "content" => ""
+    ];
 
-        // Get filters
-        $parameters = "";
-        $filters = [
-            "page" => 1,
-            "per_page" => 30,
-            "name" => "",
-            "element" => "",
-            "archetype" => "",
-            "stars" => "",
-            "stars_lte" => "",
-            "stars_gte" => "",
-        ];
+    // Get filters
+    $parameters = "";
+    $filters = [
+        "page" => 1,
+        "per_page" => 30,
+        "name" => "",
+        "element" => "",
+        "archetype" => "",
+        "stars" => "",
+        "stars_lte" => "",
+        "stars_gte" => "",
+    ];
 
-        foreach (array_keys($filters) as $filter_key){
-            $filter = filter_input(INPUT_GET, $filter_key);
-            if ($filter != null && $filter !== false){
-                $filters[$filter_key] = $filter;
-                // Also, build the new url parameters
-                if ($filter_key != "page"){
-                    $parameters .= ("&" . $filter_key . "=" . $filter);
-                }
+    foreach (array_keys($filters) as $filter_key){
+        $filter = filter_input(INPUT_GET, $filter_key);
+        if ($filter != null && $filter !== false){
+            $filters[$filter_key] = $filter;
+            // Also, build the new url parameters
+            if ($filter_key != "page"){
+                $parameters .= ("&" . $filter_key . "=" . $filter);
             }
         }
+    }
 
-        // Fix some filters
-        if (intval($filters["page"]) < 1){
-            $filters["page"] = 1;
-        }
-        if (intval($filters["per_page"]) < 1){
-            $filters["per_page"] = 1;
-        }
-        elseif (intval($filters["per_page"]) > 100){
-            $filters["per_page"] = 100;
-        }
-
-        // Build the where clause
-        $where = "
-          monster.element = element.id AND
-          monster.archetype = archetype.id
-        ";
-        if (strlen($filters["name"]) > 0){
-            $where .= " AND upper(monster.name) LIKE upper(:name) ";
-        }
-        if (strlen($filters["element"]) > 0){
-            $where .= " AND (element.id = :element OR upper(element.name) = upper(:element)) ";
-        }
-        if (strlen($filters["archetype"]) > 0){
-            $where .= " AND (archetype.id = :archetype OR upper(archetype.name) = upper(:archetype)) ";
-        }
-        if (strlen($filters["stars"]) > 0){
-            $where .= " AND monster.base_stars = :stars ";
-        }
-        if (strlen($filters["stars_lte"]) > 0){
-            $where .= " AND monster.base_stars <= :stars_lte ";
-        }
-        if (strlen($filters["stars_gte"]) > 0){
-            $where .= " AND monster.base_stars >= :stars_gte ";
-        }
+    // Fix some filters
+    if (intval($filters["page"]) < 1){
+        $filters["page"] = 1;
+    }
+    if (intval($filters["per_page"]) < 1){
+        $filters["per_page"] = 1;
+    }
+    elseif (intval($filters["per_page"]) > 100){
+        $filters["per_page"] = 100;
+    }
 
-        // Get total
-        $statement = $db->prepare("
-          SELECT count(monster.id) AS c
-          FROM
-            monster,
-            element,
-            archetype
-          WHERE $where ;
-        ");
-        $statement->bindValue(":name", "%" . $filters["name"] . "%", SQLITE3_TEXT);
-        $statement->bindValue(":element", $filters["element"], SQLITE3_TEXT);
-        $statement->bindValue(":archetype", $filters["archetype"], SQLITE3_TEXT);
-        $statement->bindValue(":stars", $filters["stars"], SQLITE3_INTEGER);
-        $statement->bindValue(":stars_gte", $filters["stars_gte"], SQLITE3_INTEGER);
-        $statement->bindValue(":stars_lte", $filters["stars_lte"], SQLITE3_INTEGER);
-        $total = $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"];
+    // Build the where clause
+    $where = "
+      monster.element = element.id AND
+      monster.archetype = archetype.id
+    ";
+    if (strlen($filters["name"]) > 0){
+        $where .= " AND upper(monster.name) LIKE upper(:name) ";
+    }
+    if (strlen($filters["element"]) > 0){
+        $where .= " AND (element.id = :element OR upper(element.name) = upper(:element)) ";
+    }
+    if (strlen($filters["archetype"]) > 0){
+        $where .= " AND (archetype.id = :archetype OR upper(archetype.name) = upper(:archetype)) ";
+    }
+    if (strlen($filters["stars"]) > 0){
+        $where .= " AND monster.base_stars = :stars ";
+    }
+    if (strlen($filters["stars_lte"]) > 0){
+        $where .= " AND monster.base_stars <= :stars_lte ";
+    }
+    if (strlen($filters["stars_gte"]) > 0){
+        $where .= " AND monster.base_stars >= :stars_gte ";
+    }
 
-        // Selet all units
-        $statement = $db->prepare("
-          SELECT monster.id AS id
-          FROM
-            monster,
-            element,
-            archetype
-          WHERE $where
-          LIMIT :limit
-          OFFSET :offset ;
-        ");
-        $statement->bindValue(":name", "%" . $filters["name"] . "%", SQLITE3_TEXT);
-        $statement->bindValue(":element", $filters["element"], SQLITE3_TEXT);
-        $statement->bindValue(":archetype", $filters["archetype"], SQLITE3_TEXT);
-        $statement->bindValue(":stars", $filters["stars"], SQLITE3_INTEGER);
-        $statement->bindValue(":stars_gte", $filters["stars_gte"], SQLITE3_INTEGER);
-        $statement->bindValue(":stars_lte", $filters["stars_lte"], SQLITE3_INTEGER);
-        $statement->bindValue(":limit", $filters["per_page"], SQLITE3_INTEGER);
-        $statement->bindValue(":offset", $filters["per_page"] * ($filters["page"] - 1), SQLITE3_INTEGER);
-        $q = $statement->execute();
-        $units = [];
+    // Get total
+    $statement = $db->prepare("
+      SELECT count(monster.id) AS c
+      FROM
+        monster,
+        element,
+        archetype
+      WHERE $where ;
+    ");
+    $statement->bindValue(":name", "%" . $filters["name"] . "%", SQLITE3_TEXT);
+    $statement->bindValue(":element", $filters["element"], SQLITE3_TEXT);
+    $statement->bindValue(":archetype", $filters["archetype"], SQLITE3_TEXT);
+    $statement->bindValue(":stars", $filters["stars"], SQLITE3_INTEGER);
+    $statement->bindValue(":stars_gte", $filters["stars_gte"], SQLITE3_INTEGER);
+    $statement->bindValue(":stars_lte", $filters["stars_lte"], SQLITE3_INTEGER);
+    $total = $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"];
 
-        // Loop and get unit info
-        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-            $unit = get_unit($db, $r["id"]);
-            if ($unit["status"] == 200){
-                array_push($units, $unit["content"]);
-            }
-        };
+    // Selet all units
+    $statement = $db->prepare("
+      SELECT monster.id AS id
+      FROM
+        monster,
+        element,
+        archetype
+      WHERE $where
+      LIMIT :limit
+      OFFSET :offset ;
+    ");
+    $statement->bindValue(":name", "%" . $filters["name"] . "%", SQLITE3_TEXT);
+    $statement->bindValue(":element", $filters["element"], SQLITE3_TEXT);
+    $statement->bindValue(":archetype", $filters["archetype"], SQLITE3_TEXT);
+    $statement->bindValue(":stars", $filters["stars"], SQLITE3_INTEGER);
+    $statement->bindValue(":stars_gte", $filters["stars_gte"], SQLITE3_INTEGER);
+    $statement->bindValue(":stars_lte", $filters["stars_lte"], SQLITE3_INTEGER);
+    $statement->bindValue(":limit", $filters["per_page"], SQLITE3_INTEGER);
+    $statement->bindValue(":offset", $filters["per_page"] * ($filters["page"] - 1), SQLITE3_INTEGER);
+    $q = $statement->execute();
+    $units = [];
 
-        // Calculate previous and next pages
-        if ($filters["page"] == 1){
-            $url_prev = null;
-        }
-        else{
-            $url_prev = URL::BASE . "API/v1/units/?page=" . ($filters["page"] - 1) . $parameters;
+    // Loop and get unit info
+    while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+        $unit = get_unit($db, $r["id"]);
+        if ($unit["status"] == 200){
+            array_push($units, $unit["content"]);
         }
-        if ($filters["page"] < ceil($total / $filters["per_page"])){
-            $url_next = URL::BASE . "API/v1/units/?page=" . ($filters["page"] + 1) . $parameters;
-        }
-        else{
-            $url_next = null;
-        }
-        $content = [
-            "count" => $total,
-            "next" => $url_next,
-            "previous" => $url_prev,
-            "results" => $units
-        ];
-        $result["content"] = $content;
-        return $result;
+    };
+
+    // Calculate previous and next pages
+    if ($filters["page"] == 1){
+        $url_prev = null;
+    }
+    else{
+        $url_prev = URL::BASE . "API/v1/units/?page=" . ($filters["page"] - 1) . $parameters;
+    }
+    if ($filters["page"] < ceil($total / $filters["per_page"])){
+        $url_next = URL::BASE . "API/v1/units/?page=" . ($filters["page"] + 1) . $parameters;
+    }
+    else{
+        $url_next = null;
     }
+    $content = [
+        "count" => $total,
+        "next" => $url_next,
+        "previous" => $url_prev,
+        "results" => $units
+    ];
+    $result["content"] = $content;
+    return $result;
+}
 
-    try{
-        header("Content-type: application/json; charset=utf-8");
-        $result = [
-            "status" => 200,
-            "message" => "Success.",
-            "content" => ""
-        ];
-        // Get profile ID
-        /** @var mixed $query Request parameters, from API_CONTROLLER*/
-        if (strlen($query[0]) > 0){
-            $id = $query[0];
-            $result = get_unit($id);
-        }
-        else{
-            $result = get_unit_list();
-        }
-        header("HTTP/1.1 " . $result["status"] . " " . $result["message"]);
-        echo(json_encode($result["content"]));
-        syslog(LOG_ERR, "HTTP/1.1 " . $result["status"] . " " . $result["message"]);
-        return $result["status"];
+try{
+    header("Content-type: application/json; charset=utf-8");
+    $result = [
+        "status" => 200,
+        "message" => "Success.",
+        "content" => ""
+    ];
+    // Get profile ID
+    /** @var mixed $query Request parameters, from API_CONTROLLER*/
+    if (strlen($query[0]) > 0){
+        $id = $query[0];
+        $result = get_unit($id);
     }
-    catch(Exception $e) {
-        header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
-        return 500;
+    else{
+        $result = get_unit_list();
     }
+    header("HTTP/1.1 " . $result["status"] . " " . $result["message"]);
+    echo(json_encode($result["content"]));
+    syslog(LOG_ERR, "HTTP/1.1 " . $result["status"] . " " . $result["message"]);
+    return $result["status"];
+}
+catch(Exception $e) {
+    header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
+    syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+    return 500;
+}

+ 10 - 115
application/Constant.php

@@ -4222,12 +4222,12 @@ final class ARTIFACT_TYPE{
     /**
      * Elemental attribute.
      */
-    const ELEMENT = 0;
+    const ELEMENT = 1;
 
     /**
      * Type artifact.
      */
-    const ARCHETYPE = 1;
+    const ARCHETYPE = 2;
  }
 
 /**
@@ -4289,16 +4289,16 @@ final class QUALITY_ID{
 };
 
 /**
- * Craft items constants.
+ * Enchantment type constants.
  *
  * @category Data
  */
-final class CRAFT_ID{
+final class ENCHANTMENT_TYPE_ID{
 
     /**
      * Enchant Gem.
      */
-    const ENCHANT_GEM = 1;
+    const GEM = 1;
 
     /**
      * Grindstone.
@@ -4306,14 +4306,14 @@ final class CRAFT_ID{
     const GRINDSTONE = 2;
 
     /**
-     * Immemorial Gem.
+     * Inmemorial Gem.
      */
-    const IMMEMORIAL_GEM = 3;
+    const INMEMORIAL_GEM = 3;
 
     /**
-     * Immemorial Grindstone.
+     * Inmemorial Grindstone.
      */
-    const IMMEMORIAL_GRINDSTONE = 4;
+    const INMEMORIAL_GRINDSTONE = 4;
 };
 
 /**
@@ -4605,109 +4605,4 @@ final class WORLD_BOSS_RANK_ID{
         11 => "SSS"
     ];
 
-}
-
-/**
- * Default filter values;
- * 
- * @category Data
- */
-final class FILTER{
-
-    /**
-     * Default values for the fusion filters.
-     */
-    const FUSION = [
-        "PRODUCT" => 0
-    ];
-
-    /**
-     * Default values for the rune filters.
-     */
-    const RUNE = [
-        "TYPE" => [],
-        "MAIN" => [],
-        "SUB" => [],
-        "SLOT" => [],
-        "MIN_QUALITY" => QUALITY_ID::NORMAL,
-        "MAX_QUALITY" => QUALITY_ID::LEGEND,
-        "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
-        "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
-        "MIN_STARS" => 1,
-        "MAX_STARS" => 6,
-        "MIN_LEVEL" => 0,
-        "MAX_LEVEL" => 15,
-        "MIN_EFFICIENCY" => 0,
-        "MAX_EFFICIENCY" => 100,
-        "MIN_MAX_EFFICIENCY" => 0,
-        "MAX_MAX_EFFICIENCY" => 100,
-        "ASSIGNED" => 1,
-        "GROUP" => "SLOT"
-    ];
-
-    /**
-     * Default values for the artifact filters.
-     */
-    const ARTIFACT = [
-        "TYPE" => 0,
-        "ELEMENT" => [],
-        "ARCHETYPE" => [],
-        "MAIN" => [],
-        "MIN_QUALITY" => QUALITY_ID::NORMAL,
-        "MAX_QUALITY" => QUALITY_ID::LEGEND,
-        "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
-        "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
-        "MIN_LEVEL" => 0,
-        "MAX_LEVEL" => 15,
-        "MIN_EFFICIENCY" => 0,
-        "MAX_EFFICIENCY" => 100,
-        "MIN_MAX_EFFICIENCY" => 0,
-        "MAX_MAX_EFFICIENCY" => 100,
-        "ASSIGNED" => 1
-    ];
-
-    /**
-     * Default values for the enchantment filters.
-     */
-    const ENCHANTMENT = [
-        "TYPE" => [],
-        "RUNE" => [],
-        "STAT" => [],
-        "MIN_QUALITY" => QUALITY_ID::NORMAL,
-        "MAX_QUALITY" => QUALITY_ID::LEGEND,
-    ];
-
-    /**
-     * Default values for the run filters.
-     */
-    const RUN = [
-        "AREA_TYPE" => 0,
-        "AREA" => 0,
-        "STAGE" => 0,
-        "DIFFICULTY" => 0,
-        "DATE_MIN" => null,
-        "DATE_MAX" => null,
-        "DEFEAT" => false,
-        "HELPER" => false,
-        "NUMBER" => 20,
-    ];
-
-    /**
-     * Default values for the rune team filters.
-     */
-    const TEAM = [
-        "NAME" => "",
-        "AREA" => null
-    ];
-
-    /**
-     * Default values for the rune team filters.
-     */
-    const STATS = [
-        "AREA_TYPE" => null,
-        "AREA" => null,
-        "STAGE" => null,
-        "DIFFICULTY" => null,
-        "INCLUDE_HELPER" => false
-    ];
-};
+}

+ 4 - 7
application/Controller.php

@@ -1,5 +1,4 @@
 <?php
-
 /**
  * Controller file.
  *
@@ -10,9 +9,6 @@
  * @package SWDB
  */
 
-/**
- * Include some required files.
- */
 require_once(__DIR__ . "/config.php");
 require_once(PATH::HELPER . "DB_Helper.php");
 require_once(PATH::HELPER . "TEXT_Helper.php");
@@ -167,7 +163,7 @@ class Controller extends Context{
                 // ... and no user logged in. Go to the landing page.
                 require_once(PATH::PAGE . "Landing_Page.php");
                 $page = new Landing_Page();
-                require_once($page->view);
+                require_once($page->get_view());
                 return;
             }
             else{
@@ -187,7 +183,7 @@ class Controller extends Context{
                 else{
                     require_once(PATH::PAGE . "Landing_Page.php");
                     $page = new Landing_Page();
-                    require_once($page->view);
+                    require_once($page->get_view());
                     return;
                 }
             }
@@ -400,12 +396,13 @@ class Controller extends Context{
 
         // Load the view, or set an error code.
         if (isset($page)){
-            require_once($page->view);
+            require_once($page->get_view());
             return 200;
         }
         else{
             require_once(PATH::PAGE . "Error_Page.php");
             $page = new Error_Page(404);
+            require_once($page->get_view());
             http_response_code(404);
             return 404;
         }

+ 1 - 1
application/action/change_game_mode.php

@@ -17,7 +17,7 @@
  *  score
  * Validates the data and sets the score.
  *
-      * @return int 201 on success, HTTP error codes on failure.
+ * @return int 201 on success, HTTP error codes on failure.
  * @category Action
  */
 function action(){

+ 1 - 1
application/action/delete_team.php

@@ -16,7 +16,7 @@
  *  player: the team owner's player id.
  *  id: the team id.
  * 
-      * @return int 201 on success, HTTP error status codes on failure.
+ * @return int 201 on success, HTTP error status codes on failure.
  * @category Action
  */
 function action(){

+ 1 - 1
application/action/edit_profile.php

@@ -20,7 +20,7 @@
  * Then it updates the selected info with the prameter vlue. Multiple itemss can be updated at the
  * same time.
  * 
-     * @return int|string 201 on success, HTTP error codes on failure. If the API key has been updated,
+ * @return int|string 201 on success, HTTP error codes on failure. If the API key has been updated,
  * the new key is returned instead.
  * @category Action
  */

+ 1 - 1
application/action/login.php

@@ -18,7 +18,7 @@
  * If there is a match, it generates a token and sets cookies and session variablesand
  * redirects to the user homepage.
  *
-      * @return int 201 on success, HTTP error codes on failure.
+ * @return int 201 on success, HTTP error codes on failure.
  * @category Action
  */
 function action(){

+ 1 - 1
application/action/new_team.php

@@ -23,7 +23,7 @@
  *  description: Optional, team description.
  * Validates the data and creates the team in the database.
  * 
-      * @return int 201 on success, HTTP error status codes on failure.
+ * @return int 201 on success, HTTP error status codes on failure.
  * @category Action
  */
 function action(){

+ 1 - 1
application/action/optimize_get_options.php

@@ -18,7 +18,7 @@
  *  tuning: {@todo Documentproperly}.
  *  options: JSON with rune sets.
  *
-     * @return int|string a JSON with the runes on success, negative integers on error. 0 if no errors
+ * @return int|string a JSON with the runes on success, negative integers on error. 0 if no errors
  * ocurred, but no results were found.
  * @category Action
  */

+ 1 - 1
application/action/optimize_get_rune_list.php

@@ -23,7 +23,7 @@
  *  
  * Then it selects all the runes matching the cryteria.
  * 
-     * @return int|string a JSON with the runes on success, negative integers on error. 0 if no errors
+ * @return int|string a JSON with the runes on success, negative integers on error. 0 if no errors
  * ocurred, but no results were found.
  * @category Action
  */

+ 1 - 1
application/action/rate_team.php

@@ -19,7 +19,7 @@
  * Validates the data and sets the score.
  *
  * @todo: Check that the user can rate this team.
-      * @return int 201 on success, HTTP erro status codes on error.
+ * @return int 201 on success, HTTP erro status codes on error.
  * @category Action
  */
 function action(){

+ 1 - 1
application/action/save_run_team.php

@@ -20,7 +20,7 @@
  *  score: New team score {@todo implement}.
  * Validates the data and creates the team in the database.
  * 
-      * @return int 201 on success, HTTP erro status codes on error.
+ * @return int 201 on success, HTTP erro status codes on error.
  * @category Action
  */
 function action(){

+ 1 - 1
application/entity/Run.php

@@ -429,7 +429,7 @@ class Run extends Entity{
                 $enchantment = new Enchantment($r["id"]);
                 if (!isset($enchantment->id)){
                     $enchantment->id = $r["id"];
-                    if ($r["type"] == CRAFT_ID::ENCHANT_GEM || $r["type"] == CRAFT_ID::IMMEMORIAL_GEM){
+                    if ($r["type"] == ENCHANTMENT_TYPE_ID::ENCHANT_GEM || $r["type"] == ENCHANTMENT_TYPE_ID::INMEMORIAL_GEM){
                             $enchantment->gem = 1;
                     }
                     else{

+ 1 - 1
application/entity/Unit.php

@@ -972,7 +972,7 @@ class Unit extends Entity{
      */
     public function get_skill_levels(){
         if (! $this->flag_skills){
-            $this->load_skill();
+            $this->load_skills();
         }
         return $this->skill_levels;
     }

+ 88 - 90
application/helper/APPLICATION_Helper.php

@@ -1,107 +1,105 @@
 <?php
+/**
+ * App helper file.
+ *
+ * Provides a helper to perform app related operations.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::HELPER . "Helper.php");
+
+/**
+ * Application helper.
+ *
+ * Contains app-related utilities.
+ *
+ * @category Helper.
+ */
+final class APPLICATION extends Helper{
+
     /**
-     * App helper file.
+     * Checks if a value is a valid one in a constant class.
      *
-     * Provides a helper to perform app related operations.
+     * It will intentionally fail when used for a non constant class.
      *
-     * @category Helper.
+     * @param string $class Name of the class.
+     * @param int $value Value to check.
+     * @return bool True if the value is defined, false otherwise.
      */
+    public static function valid_id($class, $value){
+        if (strtoupper($class) != $class){
+            return false;
+        }
+        if (!class_exists($class, false)){
+            return false;
+        }
+        $reflect = new ReflectionClass($class);
+        if (in_array($value, $reflect->getConstants())){
+            return true;
+        }
+        else{
+            return false;
+        }
+    }
 
     /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::HELPER . "Helper.php");
-
-    /**
-     * Application helper.
+     * Forms an image URL.
      *
-     * Contains app-related utilities.
+     * It will intentionally fail when used for a non constant class.
      *
-     * @category Helper.
+     * @param string $type Image type. valid values are:
+     *   ICON,    LOGO,         CURRENCY,    UNIT,
+     *   AREA,    SKILL,        ESSENCE,     RUNE,
+     *   GRIND,   ELEMENT,      SKILL_GUILD, DECORATION,
+     *   SOURCE,  SKILL_LEADER, INVENTORY,   EFFECT,
+     *   BUILDING
+     * @param string|int $name Filename, with no path or extension. It can also
+     * skip the padding. An id can be used.
+     * @return string URL if found. If not, the URL to an 'unknown' icon.
      */
-    final class APPLICATION extends Helper{
-
-        /**
-         * Checks if a value is a valid one in a constant class.
-         *
-         * It will intentionally fail when used for a non constant class.
-         *
-         * @param string $class Name of the class.
-         * @param int $value Value to check.
-         * @return bool True if the value is defined, false otherwise.
-         */
-        public static function valid_id($class, $value){
-            if (strtoupper($class) != $class){
-                return false;
-            }
-            if (!class_exists($class, false)){
-                return false;
-            }
-            $reflect = new ReflectionClass($class);
-            if (in_array($value, $reflect->getConstants())){
-                return true;
-            }
-            else{
-                return false;
+    public static function img($type, $name){
+        $pad = 1;
+        $url = URL::IMG["UNKNOWN"];
+        while ($pad < 10){
+            if (isset(PATH::IMG[$type]) && file_exists(PATH::IMG[$type] . str_pad($name, $pad, '0', STR_PAD_LEFT) . ".png")){
+                $url = URL::IMG[$type] . str_pad($name, $pad, '0', STR_PAD_LEFT) . ".png";
+                break;
             }
+            $pad ++;
         }
+        return $url;
+    }
 
-        /**
-         * Forms an image URL.
-         *
-         * It will intentionally fail when used for a non constant class.
-         *
-         * @param string $type Image type. valid values are:
-         *   ICON,    LOGO,         CURRENCY,    UNIT,
-         *   AREA,    SKILL,        ESSENCE,     RUNE,
-         *   GRIND,   ELEMENT,      SKILL_GUILD, DECORATION,
-         *   SOURCE,  SKILL_LEADER, INVENTORY,   EFFECT,
-         *   BUILDING
-         * @param string|int $name Filename, with no path or extension. It can also
-         * skip the padding. An id can be used.
-         * @return string URL if found. If not, the URL to an 'unknown' icon.
-         */
-        public static function img($type, $name){
-            $pad = 1;
-            $url = URL::IMG["UNKNOWN"];
-            while ($pad < 10){
-                if (isset(PATH::IMG[$type]) && file_exists(PATH::IMG[$type] . str_pad($name, $pad, '0', STR_PAD_LEFT) . ".png")){
-                    $url = URL::IMG[$type] . str_pad($name, $pad, '0', STR_PAD_LEFT) . ".png";
-                    break;
-                }
-                $pad ++;
-            }
-            return $url;
+    /**
+     * Calculates the effective damage.
+     * 
+     * @param int $atk Attack stat.
+     * @param int $crr Critical rate stat.
+     * @param int $crd Critical damage stat.
+     * @return int Damage stat.
+     */
+    public static function calculate_dmg($atk, $crr, $crd){
+        if (! is_numeric($atk) || ! is_numeric($crr) || ! is_numeric($crd)){
+            return 0;
         }
-
-        /**
-         * Calculates the effective damage.
-         * 
-         * @param int $atk Attack stat.
-         * @param int $crr Critical rate stat.
-         * @param int $crd Critical damage stat.
-         * @return int Damage stat.
-         */
-        public static function calculate_dmg($atk, $crr, $crd){
-            if (! is_numeric($atk) || ! is_numeric($crr) || ! is_numeric($crd)){
-                return 0;
-            }
-            if ($crr > 100){
-                $crr = 100;
-            }
-            $edmg = ceil(($atk * (100 - $crr) / 100) + (($atk + ($atk * $crd / 100)) * $crr / 100));
-            return $edmg;
+        if ($crr > 100){
+            $crr = 100;
         }
+        $edmg = ceil(($atk * (100 - $crr) / 100) + (($atk + ($atk * $crd / 100)) * $crr / 100));
+        return $edmg;
+    }
 
-        /**
-         *  Calculates the effective HP of a unit.
-         * @param int $hp HP stat
-         * @param int $def Defense stat.
-         * @return int Effective HP.
-         */
-        public static function calculate_ehp($hp, $def){
-            $ehp = ceil(((($def * 3.5) + 1140) * $hp) / 1000);
-            return $ehp;
-        }
+    /**
+     *  Calculates the effective HP of a unit.
+     * @param int $hp HP stat
+     * @param int $def Defense stat.
+     * @return int Effective HP.
+     */
+    public static function calculate_ehp($hp, $def){
+        $ehp = ceil(((($def * 3.5) + 1140) * $hp) / 1000);
+        return $ehp;
     }
-?>
+}

+ 36 - 38
application/helper/DB_Helper.php

@@ -1,46 +1,44 @@
 <?php
-    /**
-     * DB helper file.
-     *
-     * Provides a helper to perform database operations.
-     *
-     * @category Helper.
-     */
+/**
+ * DB helper file.
+ *
+ * Provides a helper to perform database operations.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::HELPER . "Helper.php");
+require_once(PATH::HELPER . "Helper.php");
+
+/**
+ * Database helper.
+ *
+ * Contains database utilities to connect.
+ *
+ * @category Helper.
+ */
+final class DB extends Helper{
 
     /**
-     * Database helper.
-     *
-     * Contains database utilities to connect.
-     *
-     * @category Helper.
+     * Creates a database connection using the data in the config files.
+     * 
+     * @return resource Connection to the database.
      */
-    final class DB extends Helper{
-
-        /**
-         * Creates a database connection using the data in the config files.
-         * 
-         * @return resource Connection to the database.
-         */
-        public static function start(){
-            /*class SQLite extends SQLite3 {
-                function __construct($file) {
-                    $this->open($file);
-                }
-            }*/
-            $db = new SQLite3(":memory:");
-            if(!$db) {
-                error_log($db->lastErrorMsg());
-            }
-            else {
-                $db->query("attach '" . PATH::DB_DATA . "' as data");
-                $db->query("attach '" . PATH::DB_KEY . "' as key");
-                return $db;
+    public static function start(){
+        /*class SQLite extends SQLite3 {
+            function __construct($file) {
+                $this->open($file);
             }
+        }*/
+        $db = new SQLite3(":memory:");
+        if(!$db) {
+            error_log($db->lastErrorMsg());
+        }
+        else {
+            $db->query("attach '" . PATH::DB_DATA . "' as data");
+            $db->query("attach '" . PATH::DB_KEY . "' as key");
+            return $db;
         }
     }
-?>
+}

+ 651 - 654
application/helper/HTML_Helper.php

@@ -1,722 +1,719 @@
 <?php
-    /**
-     * HTML helper file.
-     *
-     * Provides a helper to perform HTML operations.
-     *
-     * @category Helper.
-     */
+/**
+ * HTML helper file.
+ *
+ * Provides a helper to perform HTML operations.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::HELPER . "Helper.php");
-    require_once(PATH::ENTITY . "Unit.php");
-    require_once(PATH::ENTITY . "Monster.php");
-    require_once(PATH::ENTITY . "Building.php");
-    require_once(PATH::ENTITY . "Buildable.php");
-    require_once(PATH::ENTITY . "Decoration.php");
-    require_once(PATH::ENTITY . "Decorative.php");
-    require_once(PATH::ENTITY . "Rune.php");
-    require_once(PATH::ENTITY . "Artifact.php");
-    require_once(PATH::ENTITY . "Enchantment.php");
-    require_once(PATH::ENTITY . "Item.php");
+require_once(PATH::HELPER . "Helper.php");
+require_once(PATH::ENTITY . "Unit.php");
+require_once(PATH::ENTITY . "Monster.php");
+require_once(PATH::ENTITY . "Building.php");
+require_once(PATH::ENTITY . "Buildable.php");
+require_once(PATH::ENTITY . "Decoration.php");
+require_once(PATH::ENTITY . "Decorative.php");
+require_once(PATH::ENTITY . "Rune.php");
+require_once(PATH::ENTITY . "Artifact.php");
+require_once(PATH::ENTITY . "Enchantment.php");
+require_once(PATH::ENTITY . "Item.php");
+
+/**
+ * HTML helper.
+ *
+ * Contains utilities to parse and format HTML and to build elements.
+ *
+ * @category Helper.
+ */
+final class HTML extends Helper{
 
     /**
-     * HTML helper.
-     *
-     * Contains utilities to parse and format HTML and to build elements.
+     * Escapes HTML characters
+     * 
+     * Alias for htmlspecialchars([input], ENT_QUOTES)
      *
-     * @category Helper.
+     * @param string $input Text to escape.
+     * @return string Escaped text.
      */
-    final class HTML extends Helper{
+    public static function e($input){
+       return htmlspecialchars($input, ENT_QUOTES);
+    }
 
-        /**
-         * Escapes HTML characters
-         * 
-         * Alias for htmlspecialchars([input], ENT_QUOTES)
-         *
-         * @param string $input Text to escape.
-         * @return string Escaped text.
-         */
-        public static function e($input){
-           return htmlspecialchars($input, ENT_QUOTES);
+    /**
+     * Generates a unit panel.
+     * 
+     * @param Unit|Monster Entity to get the info from.
+     * @return string HTML content for a monster panel. Empty on error.
+     */
+    public static function unit_panel($unit) {
+        if ($unit instanceof Unit){
+            $k = $unit->get_monster();
+            $stars = $unit->get_stars();
+            $level = true;
+            $teams = (sizeof($unit->get_teams()) > 0);
+            $lock = $unit->is_locked();
+            $storage = $unit->is_in_storage();
+            $maxed = ($unit->get_level() == 40 && $unit->is_fully_skilled());
         }
-
-        /**
-         * Generates a unit panel.
-         * 
-         * @param Unit|Monster Entity to get the info from.
-         * @return string HTML content for a monster panel. Empty on error.
-         */
-        public static function unit_panel($unit) {
-            if ($unit instanceof Unit){
-                $k = $unit->get_monster();
-                $stars = $unit->get_stars();
-                $level = true;
-                $teams = (sizeof($unit->get_teams()) > 0);
-                $lock = $unit->is_locked();
-                $storage = $unit->is_in_storage();
-                $maxed = ($unit->get_level() == 40 && $unit->is_fully_skilled());
-            }
-            elseif ($unit instanceof Monster){
-                $k = $unit;
-                $stars = $unit->get_base_stars();
-                $level = false;
-                $teams = 0;
-                $lock = false;
-                $storage = false;
-                $maxed = false;
+        elseif ($unit instanceof Monster){
+            $k = $unit;
+            $stars = $unit->get_base_stars();
+            $level = false;
+            $teams = 0;
+            $lock = false;
+            $storage = false;
+            $maxed = false;
+        }
+        else{
+            return "";
+        }
+        $html = "";
+        if ($k->get_awakens_from() == null && $k->get_awakens_to() == null){
+            // No to, no from
+            if ($k->get_base_stars() >= 4){
+                // SFV Collab event units, always awakened.
+                $star_class = "star_purple";
             }
-            else{
-                return "";
+            elseif($k->get_archetype() == ARCHETYPE_ID::MATERIAL && $k->get_element() == ELEMENT_ID::LIGHT){
+                // Rainbowmon, always awakened
+                $star_class = "star_purple";
             }
-            $html = "";
-            if ($k->get_awakens_from() == null && $k->get_awakens_to() == null){
-                // No to, no from
-                if ($k->get_base_stars() >= 4){
-                    // SFV Collab event units, always awakened.
-                    $star_class = "star_purple";
-                }
-                elseif($k->get_archetype() == ARCHETYPE_ID::MATERIAL && $k->get_element() == ELEMENT_ID::LIGHT){
-                    // Rainbowmon, always awakened
-                    $star_class = "star_purple";
-                }
-                elseif($k->get_archetype() == ARCHETYPE_ID::MATERIAL && $k->get_element() == ELEMENT_ID::DARK){
-                    // Devilmon, always unawakened
-                    $star_class = "star_silver";
-                }
-                else{
-                    // Unawakeable monster
-                    $star_class = "star_silver";
-                }
+            elseif($k->get_archetype() == ARCHETYPE_ID::MATERIAL && $k->get_element() == ELEMENT_ID::DARK){
+                // Devilmon, always unawakened
+                $star_class = "star_silver";
             }
-            elseif ($k->get_awakens_from() != ""){
-                // Already awakened
-                if ($k->get_base_stars() - $k->get_natural_stars() == 1){
-                    // Normal awaken.
-                    $star_class ="star_purple";
-                }
-                else{
-                    // Second awaken.
-                    $star_class ="star_red";
-                }
+            else{
+                // Unawakeable monster
+                $star_class = "star_silver";
             }
-            elseif ($k->get_awakens_to() != ""){
-                // Awakeable.
-                $star_class ="star_gold";
+        }
+        elseif ($k->get_awakens_from() != ""){
+            // Already awakened
+            if ($k->get_base_stars() - $k->get_natural_stars() == 1){
+                // Normal awaken.
+                $star_class ="star_purple";
             }
-            $html .= "<span class='stars'>\n";
-            for ($i = 0; $i < $stars; $i ++){
-                $html .= "<img class='star $star_class' src='" . URL::IMG["ICON"] . "star.png'/>\n";
+            else{
+                // Second awaken.
+                $star_class ="star_red";
             }
+        }
+        elseif ($k->get_awakens_to() != ""){
+            // Awakeable.
+            $star_class ="star_gold";
+        }
+        $html .= "<span class='stars'>\n";
+        for ($i = 0; $i < $stars; $i ++){
+            $html .= "<img class='star $star_class' src='" . URL::IMG["ICON"] . "star.png'/>\n";
+        }
+        $html .= "</span>\n";
+        $html .= "<img title='" . $k->get_title() . "' class='monster border_" . $k->get_element_name() . "' src='" . $k->get_image() . "'/>\n";
+        if ($level){
+            $html .= "<span class='level'>\n";
+            $html .= $unit->get_level() . "\n";
             $html .= "</span>\n";
-            $html .= "<img title='" . $k->get_title() . "' class='monster border_" . $k->get_element_name() . "' src='" . $k->get_image() . "'/>\n";
-            if ($level){
-                $html .= "<span class='level'>\n";
-                $html .= $unit->get_level() . "\n";
-                $html .= "</span>\n";
-            }
-            $html .= "<span class='badges'>\n";
-            if ($maxed){
-                $html .= "<img title='Maxed unit' src='" . URL::IMG["ICON"] . "maxed.png'>";
-            }
-            if ($teams > 0){
-                $title = $teams . " teams";
-                if ($teams == 1){
-                    $title = "1 team: " . $unit->get_teams()[0]->get_name();
-                }
-                $html .= "<img title='$title' src='" . URL::IMG["ICON"] . "team.png'>";
-            }
-            if ($lock == 1){
-                $html .= "<img title='Locked' src='" . URL::IMG["ICON"] . "lock.png'>";
-            }
-            if ($storage){
-                $html .= "<img title='In storage' src='" . URL::IMG["ICON"] . "storage.png'>";
+        }
+        $html .= "<span class='badges'>\n";
+        if ($maxed){
+            $html .= "<img title='Maxed unit' src='" . URL::IMG["ICON"] . "maxed.png'>";
+        }
+        if ($teams > 0){
+            $title = $teams . " teams";
+            if ($teams == 1){
+                $title = "1 team: " . $unit->get_teams()[0]->get_name();
             }
-
-            $html .= "</span>\n";
-            return $html;
+            $html .= "<img title='$title' src='" . URL::IMG["ICON"] . "team.png'>";
+        }
+        if ($lock == 1){
+            $html .= "<img title='Locked' src='" . URL::IMG["ICON"] . "lock.png'>";
+        }
+        if ($storage){
+            $html .= "<img title='In storage' src='" . URL::IMG["ICON"] . "storage.png'>";
         }
 
-        /**
-         * Generates a transformed monster panel.
-         * 
-         * @param Unit|Monster Entity to get the info from.
-         * @return string HTML content for a monster panel. Empty on error.
-         */
-        public static function unit_transformation_panel($unit) {
-            $html = "";
-            if ($unit instanceof Unit){
-                $k = $unit->get_unit();
-            }
-            elseif ($unit instanceof Monster){
-                $k = $unit;
-            }
-            else{
-                return "";
-            }
-            if ($k->get_transformation() == null){
-                return "";
-            }
-            $html .= "<div class='monster_transformation_panel'>\n";
-            $html .= "<img title='" . $unit->get_title() . " (transformed)' class='monster_transformation border_" . $k->get_element_name() . "' src='" . $k->get_transformation()->get_image() . "'/>\n";
-            $html .= "</div>\n";
-            return $html;
+        $html .= "</span>\n";
+        return $html;
+    }
+
+    /**
+     * Generates a transformed monster panel.
+     * 
+     * @param Unit|Monster Entity to get the info from.
+     * @return string HTML content for a monster panel. Empty on error.
+     */
+    public static function unit_transformation_panel($unit) {
+        $html = "";
+        if ($unit instanceof Unit){
+            $k = $unit->get_unit();
+        }
+        elseif ($unit instanceof Monster){
+            $k = $unit;
+        }
+        else{
+            return "";
+        }
+        if ($k->get_transformation() == null){
+            return "";
         }
+        $html .= "<div class='monster_transformation_panel'>\n";
+        $html .= "<img title='" . $unit->get_title() . " (transformed)' class='monster_transformation border_" . $k->get_element_name() . "' src='" . $k->get_transformation()->get_image() . "'/>\n";
+        $html .= "</div>\n";
+        return $html;
+    }
 
-        /**
-         * Generates a rune panel.
-         * 
-         * @param Rune rune Entity to get the info from.
-         * @param Unit unit Optional. The unit the rune is assigned to.
-         * @return string HTML content for a rune panel. Empty on error.
-         */
-        public static function rune_panel($rune, $unit = null) {
-            if (!($rune instanceof Rune)){
-                return "";
-            }
-            $html = "";
-            $html .= "<div class='rune_panel rune_slot_" . $rune->get_slot() . " rune_level_" . $rune->get_level() . " rune_quality_" . strtolower($rune->get_quality_name()) . " rune_original_quality_" . strtolower($rune->get_original_quality_name()) . " rune_ancient_" . (int) $rune->is_ancient() . "'>\n";
-            $html .= "<img class='rune_base' src='" . URL::IMG["RUNE"] . "base.png'/>\n";
-            $html .= "<img class='rune_icon' src='" . $rune->get_set()->get_image() . "'/>\n";
-            $html .= "<span class='rune_stars'>\n";
-            $star_color = "gold";
-            if ($rune->geT_level() == 15){
-                $star_color = "purple";
-            }
-            for ($i = 0; $i < $rune->get_stars(); $i ++){
-                $html .= "<img class='star star_$star_color' src='" . URL::IMG["ICON"] . "star.png'/>\n";
-            }
-            $html .= "</span>\n";
-            $html .= "<span class='rune_level'>\n";
-            $html .= $rune->get_level() . "\n";
-            $html .= "</span>\n";
+    /**
+     * Generates a rune panel.
+     * 
+     * @param Rune rune Entity to get the info from.
+     * @param Unit unit Optional. The unit the rune is assigned to.
+     * @return string HTML content for a rune panel. Empty on error.
+     */
+    public static function rune_panel($rune, $unit = null) {
+        if (!($rune instanceof Rune)){
+            return "";
+        }
+        $html = "";
+        $html .= "<div class='rune_panel rune_slot_" . $rune->get_slot() . " rune_level_" . $rune->get_level() . " rune_quality_" . strtolower($rune->get_quality_name()) . " rune_original_quality_" . strtolower($rune->get_original_quality_name()) . " rune_ancient_" . (int) $rune->is_ancient() . "'>\n";
+        $html .= "<img class='rune_base' src='" . URL::IMG["RUNE"] . "base.png'/>\n";
+        $html .= "<img class='rune_icon' src='" . $rune->get_set()->get_image() . "'/>\n";
+        $html .= "<span class='rune_stars'>\n";
+        $star_color = "gold";
+        if ($rune->geT_level() == 15){
+            $star_color = "purple";
+        }
+        for ($i = 0; $i < $rune->get_stars(); $i ++){
+            $html .= "<img class='star star_$star_color' src='" . URL::IMG["ICON"] . "star.png'/>\n";
+        }
+        $html .= "</span>\n";
+        $html .= "<span class='rune_level'>\n";
+        $html .= $rune->get_level() . "\n";
+        $html .= "</span>\n";
+        $html .= "</div>\n";
+        if ($unit instanceof Unit){
+            $html .= "<div class='assigned'>\n";
+            $html .= "<a target='blank' href='/monsters/" . $unit->get_id() . "'>\n";
+            $html .= "<img title='" . $unit->get_title() . "' class='monster_image border_" . $unit->get_monster()->get_element_name() . "' src='" . $unit->get_monster()->get_image() . "'/>\n";
+            $html .= "</a>\n";
             $html .= "</div>\n";
-            if ($unit instanceof Unit){
-                $html .= "<div class='assigned'>\n";
-                $html .= "<a target='blank' href='/monsters/" . $unit->get_id() . "'>\n";
-                $html .= "<img title='" . $unit->get_title() . "' class='monster_image border_" . $unit->get_monster()->get_element_name() . "' src='" . $unit->get_monster()->get_image() . "'/>\n";
-                $html .= "</a>\n";
-                $html .= "</div>\n";
-            }
-            return $html;
         }
+        return $html;
+    }
 
-        /**
-         * Generates a rune table.
-         * 
-         * @param Rune rune Entity to get the info from.
-         * @param Unit unit Optional. The unit the rune is assigned to.
-         * @return string HTML content for a rune table. Empty on error.
-         */
-        public static function rune_table($rune, $unit = null) {
-            if (!($rune instanceof Rune)){
-                return "";
-            }
-            $html = "";
-            $html .= "<table class='rune' id='rune-" . $rune->get_id() . "'>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='icon'>\n";
-            $html .= HTML::rune_panel($rune, $unit) . "\n";
-            $html .= "</td>\n";
-            $html .= "<td class='stats'>\n";
-            $html .= "<table>\n";
-            // Main stat
-            $html .= "<tr class='main_stat'>\n";
-            $html .= "<td class='stat'>\n";
-            if (in_array($rune->get_main_stat()->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                $stat_name = str_replace("%", "", $rune->get_main_stat()->get_stat_name());
-                $stat_value = "+" . $rune->get_main_stat()->get_value() . "%";
-            }
-            else{
-                $stat_name = $rune->get_main_stat()->get_stat_name();
-                $stat_value = "+" . $rune->get_main_stat()->get_value(). "&nbsp;";
-            }
-            $html .= $stat_name . "\n";
-            $html .= "</td>\n";
-            $html .= "<td class='value'>\n";
-            $html .= $stat_value . "\n";
-            $html .= "</td>\n";
-            $html .= "<td class='grind'>\n";
-            $html .= "</td>\n";
-            $html .= "<td class='enchant'>\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            // Innate stat
-            $html .= "<tr class='innate_stat'>\n";
-            $html .= "<td class='stat'>\n";
-            if ($rune->get_innate_stat() == null){
+    /**
+     * Generates a rune table.
+     * 
+     * @param Rune rune Entity to get the info from.
+     * @param Unit unit Optional. The unit the rune is assigned to.
+     * @return string HTML content for a rune table. Empty on error.
+     */
+    public static function rune_table($rune, $unit = null) {
+        if (!($rune instanceof Rune)){
+            return "";
+        }
+        $html = "";
+        $html .= "<table class='rune' id='rune-" . $rune->get_id() . "'>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='icon'>\n";
+        $html .= HTML::rune_panel($rune, $unit) . "\n";
+        $html .= "</td>\n";
+        $html .= "<td class='stats'>\n";
+        $html .= "<table>\n";
+        // Main stat
+        $html .= "<tr class='main_stat'>\n";
+        $html .= "<td class='stat'>\n";
+        if (in_array($rune->get_main_stat()->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+            $stat_name = str_replace("%", "", $rune->get_main_stat()->get_stat_name());
+            $stat_value = "+" . $rune->get_main_stat()->get_value() . "%";
+        }
+        else{
+            $stat_name = $rune->get_main_stat()->get_stat_name();
+            $stat_value = "+" . $rune->get_main_stat()->get_value(). "&nbsp;";
+        }
+        $html .= $stat_name . "\n";
+        $html .= "</td>\n";
+        $html .= "<td class='value'>\n";
+        $html .= $stat_value . "\n";
+        $html .= "</td>\n";
+        $html .= "<td class='grind'>\n";
+        $html .= "</td>\n";
+        $html .= "<td class='enchant'>\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        // Innate stat
+        $html .= "<tr class='innate_stat'>\n";
+        $html .= "<td class='stat'>\n";
+        if ($rune->get_innate_stat() == null){
+            $stat_name = "&nbsp;";
+            $stat_value = "";
+        }
+        elseif (in_array($rune->get_innate_stat()->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+            $stat_name = str_replace("%", "", $rune->get_innate_stat()->get_stat_name());
+            $stat_value = "+" . $rune->get_innate_stat()->get_value() . "%";
+        }
+        else{
+            $stat_name = $rune->get_innate_stat()->get_stat_name();
+            $stat_value = "+" . $rune->get_innate_stat()->get_value(). "&nbsp;";
+        }
+        $html .= $stat_name . "\n";
+        $html .= "</td>\n";
+        $html .= "<td class='value'>\n";
+        $html .= $stat_value . "\n";
+        $html .= "</td>\n";
+        $html .= "<td class='grind'>\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        for ($i = 0; $i < 4; $i ++){
+            if ($rune->get_substats()[$i] == null){
                 $stat_name = "&nbsp;";
                 $stat_value = "";
             }
-            elseif (in_array($rune->get_innate_stat()->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                $stat_name = str_replace("%", "", $rune->get_innate_stat()->get_stat_name());
-                $stat_value = "+" . $rune->get_innate_stat()->get_value() . "%";
+            elseif (in_array($rune->get_substats()[$i]->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+                $stat_name = str_replace("%", "", $rune->get_substats()[$i]->get_stat_name());
+                $stat_value = "+" . $rune->get_substats()[$i]->get_value() . "%";
             }
             else{
-                $stat_name = $rune->get_innate_stat()->get_stat_name();
-                $stat_value = "+" . $rune->get_innate_stat()->get_value(). "&nbsp;";
+                $stat_name = $rune->get_substats()[$i]->get_stat_name();
+                $stat_value = "+" . $rune->get_substats()[$i]->get_value(). "&nbsp;";
+            }
+            $grind = "";
+            if ($rune->get_substats()[$i] != null && $rune->get_substats()[$i]->get_grind() > 0){
+                $grind = "+" . $rune->get_substats()[$i]->get_grind();
+                if (in_array($rune->get_substats()[$i]->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+                    $grind = $grind . "%";
+                }
             }
+            $html .= "<tr class=substat>\n";
+            $html .= "<td class='stat'>\n";
             $html .= $stat_name . "\n";
             $html .= "</td>\n";
             $html .= "<td class='value'>\n";
             $html .= $stat_value . "\n";
-            $html .= "</td>\n";
-            $html .= "<td class='grind'>\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            for ($i = 0; $i < 4; $i ++){
-                if ($rune->get_substats()[$i] == null){
-                    $stat_name = "&nbsp;";
-                    $stat_value = "";
-                }
-                elseif (in_array($rune->get_substats()[$i]->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                    $stat_name = str_replace("%", "", $rune->get_substats()[$i]->get_stat_name());
-                    $stat_value = "+" . $rune->get_substats()[$i]->get_value() . "%";
-                }
-                else{
-                    $stat_name = $rune->get_substats()[$i]->get_stat_name();
-                    $stat_value = "+" . $rune->get_substats()[$i]->get_value(). "&nbsp;";
-                }
-                $grind = "";
-                if ($rune->get_substats()[$i] != null && $rune->get_substats()[$i]->get_grind() > 0){
-                    $grind = "+" . $rune->get_substats()[$i]->get_grind();
-                    if (in_array($rune->get_substats()[$i]->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                        $grind = $grind . "%";
-                    }
-                }
-                $html .= "<tr class=substat>\n";
-                $html .= "<td class='stat'>\n";
-                $html .= $stat_name . "\n";
-                $html .= "</td>\n";
-                $html .= "<td class='value'>\n";
-                $html .= $stat_value . "\n";
-                $html .= "<td class='grind grind_$grind'>\n";
-                $html .= $grind . "\n";
-                if ($rune->get_substats()[$i] != null && $rune->get_substats()[$i]->is_enchanted()){
-                    $html .= "<img title='Enchanted' src='" . URL::IMG["RUNE"] . "enchanted.png'/>\n";
-                }
-                $html .= "</td>\n";
-                $html .= "</tr>\n";
+            $html .= "<td class='grind grind_$grind'>\n";
+            $html .= $grind . "\n";
+            if ($rune->get_substats()[$i] != null && $rune->get_substats()[$i]->is_enchanted()){
+                $html .= "<img title='Enchanted' src='" . URL::IMG["RUNE"] . "enchanted.png'/>\n";
             }
-            $html .= "</table>\n";
-            $html .= "</td>\n";
-            // Details
-            $html .= "<td class='details'>\n";
-            $html .= "<table class='table_details'>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='title'>\n";
-            $html .= "QY.:\n";
-            $html .= "</td>\n";
-            $html .= "<td class='value'>\n";
-            $html .= "<span class='quality quality_" . strtolower($rune->get_quality_name()) . "'>\n";
-            $html .= $rune->get_quality_name() . "\n";
-            $html .= "</span>\n";
             $html .= "</td>\n";
             $html .= "</tr>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='title'>\n";
-            $html .= "O.QY.:\n";
-            $html .= "</td>\n";
-            $html .= "<td class='value'>\n";
-            $html .= "<span class='quality quality_" . strtolower($rune->geT_original_quality_name()) . "'>\n";
-            $html .= $rune->get_original_quality_name() . "\n";
-            $html .= "</span>\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='title'>\n";
-            $html .= "Value:\n";
-            $html .= "</td>\n";
-            $html .= "<td class='value'>\n";
-            $html .= number_format($rune->get_value(), 0, ".", ",") . "\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='title'>\n";
-            $html .= "EFF.:\n";
-            $html .= "</td>\n";
-            $html .= "<td class='value'>\n";
-            $html .= number_format($rune->get_efficiency(), 2, ".", ",") . "%\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='title'>\n";
-            $html .= "MX.E.:\n";
-            $html .= "</td>\n";
-            $html .= "<td class='value'>\n";
-            $html .= number_format($rune->get_max_efficiency(), 2, ".", ",") . "%\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            $html .= "</table>\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            $html .= "</table>\n";
-            return $html;
         }
+        $html .= "</table>\n";
+        $html .= "</td>\n";
+        // Details
+        $html .= "<td class='details'>\n";
+        $html .= "<table class='table_details'>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='title'>\n";
+        $html .= "QY.:\n";
+        $html .= "</td>\n";
+        $html .= "<td class='value'>\n";
+        $html .= "<span class='quality quality_" . strtolower($rune->get_quality_name()) . "'>\n";
+        $html .= $rune->get_quality_name() . "\n";
+        $html .= "</span>\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='title'>\n";
+        $html .= "O.QY.:\n";
+        $html .= "</td>\n";
+        $html .= "<td class='value'>\n";
+        $html .= "<span class='quality quality_" . strtolower($rune->geT_original_quality_name()) . "'>\n";
+        $html .= $rune->get_original_quality_name() . "\n";
+        $html .= "</span>\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='title'>\n";
+        $html .= "Value:\n";
+        $html .= "</td>\n";
+        $html .= "<td class='value'>\n";
+        $html .= number_format($rune->get_value(), 0, ".", ",") . "\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='title'>\n";
+        $html .= "EFF.:\n";
+        $html .= "</td>\n";
+        $html .= "<td class='value'>\n";
+        $html .= number_format($rune->get_efficiency(), 2, ".", ",") . "%\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='title'>\n";
+        $html .= "MX.E.:\n";
+        $html .= "</td>\n";
+        $html .= "<td class='value'>\n";
+        $html .= number_format($rune->get_max_efficiency(), 2, ".", ",") . "%\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "</table>\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "</table>\n";
+        return $html;
+    }
 
-        // TODO: Icon and background selection must go in the entity code.
-        /**
-         * Generates an artifact panel.
-         * 
-         * @param Artifact artifact Entity to get the info from.
-         * @param Unit unit Optional. The unit the artifact is assigned to.
-         * @return string HTML content for an artifact panel. Empty on error.
-         */
-        public static function artifact_panel($artifact, $unit = null) {
-            if (!($artifact instanceof Artifact)){
-                return "";
-            }
-            $html = "";
-            $html .= "<div class='artifact_panel artifact_level_" . $artifact->get_level() . " artifact_quality_" . strtolower($artifact->get_quality_name()) . " artifact_original_quality_" . strtolower($artifact->get_original_quality_name()) . " '>\n";
-            $background = "";
-            $icon = "";
-            if ($artifact->is_archetypal()){
-                $background = URL::IMG["ARTIFACT"] . "type_" . strtolower($artifact->get_quality_name()) . ".png";
-                $icon = URL::IMG["ARTIFACT"] . "type_";
-                switch ($artifact->get_archetype()){
-                    case ARCHETYPE_ID::ATTACK:
-                        $icon .= "attack";
-                        break;
-                    case ARCHETYPE_ID::DEFENSE:
-                        $icon .= "defense";
-                        break;
-                    case ARCHETYPE_ID::HP:
-                        $icon .= "hp";
-                        break;
-                    case ARCHETYPE_ID::SUPPORT:
-                        $icon .= "support";
-                        break;
-                }
-                $icon .= ".png";
+    // TODO: Icon and background selection must go in the entity code.
+    /**
+     * Generates an artifact panel.
+     * 
+     * @param Artifact artifact Entity to get the info from.
+     * @param Unit unit Optional. The unit the artifact is assigned to.
+     * @return string HTML content for an artifact panel. Empty on error.
+     */
+    public static function artifact_panel($artifact, $unit = null) {
+        if (!($artifact instanceof Artifact)){
+            return "";
+        }
+        $html = "";
+        $html .= "<div class='artifact_panel artifact_level_" . $artifact->get_level() . " artifact_quality_" . strtolower($artifact->get_quality_name()) . " artifact_original_quality_" . strtolower($artifact->get_original_quality_name()) . " '>\n";
+        $background = "";
+        $icon = "";
+        if ($artifact->is_archetypal()){
+            $background = URL::IMG["ARTIFACT"] . "type_" . strtolower($artifact->get_quality_name()) . ".png";
+            $icon = URL::IMG["ARTIFACT"] . "type_";
+            switch ($artifact->get_archetype()){
+                case ARCHETYPE_ID::ATTACK:
+                    $icon .= "attack";
+                    break;
+                case ARCHETYPE_ID::DEFENSE:
+                    $icon .= "defense";
+                    break;
+                case ARCHETYPE_ID::HP:
+                    $icon .= "hp";
+                    break;
+                case ARCHETYPE_ID::SUPPORT:
+                    $icon .= "support";
+                    break;
             }
-            else{
-                $background = URL::IMG["ARTIFACT"] . "element_" . strtolower($artifact->get_quality_name()) . ".png";
-                $icon = URL::IMG["ARTIFACT"] . "element_";
-                switch ($artifact->get_element()){
-                    case ELEMENT_ID::WATER:
-                        $icon .= "water";
-                        break;
-                    case ELEMENT_ID::WIND:
-                        $icon .= "wind";
-                        break;
-                    case ELEMENT_ID::FIRE:
-                        $icon .= "fire";
-                        break;
-                    case ELEMENT_ID::LIGHT:
-                        $icon .= "light";
-                        break;
-                    case ELEMENT_ID::DARK:
-                        $icon .= "dark";
-                        break;
-                }
-                $icon .= ".png";
+            $icon .= ".png";
+        }
+        else{
+            $background = URL::IMG["ARTIFACT"] . "element_" . strtolower($artifact->get_quality_name()) . ".png";
+            $icon = URL::IMG["ARTIFACT"] . "element_";
+            switch ($artifact->get_element()){
+                case ELEMENT_ID::WATER:
+                    $icon .= "water";
+                    break;
+                case ELEMENT_ID::WIND:
+                    $icon .= "wind";
+                    break;
+                case ELEMENT_ID::FIRE:
+                    $icon .= "fire";
+                    break;
+                case ELEMENT_ID::LIGHT:
+                    $icon .= "light";
+                    break;
+                case ELEMENT_ID::DARK:
+                    $icon .= "dark";
+                    break;
             }
-            $html .= "<img class='artifact_base' src='" . $background . "'/>\n";
-            $html .= "<img class='artifact_icon' src='" . $icon . "'/>\n";
-            $html .= "<span class='artifact_stars'>\n";
-            $html .= "</span>\n";
-            $html .= "<span class='artifact_level'>\n";
-            $html .= $artifact->get_level() . "\n";
-            $html .= "</span>\n";
+            $icon .= ".png";
+        }
+        $html .= "<img class='artifact_base' src='" . $background . "'/>\n";
+        $html .= "<img class='artifact_icon' src='" . $icon . "'/>\n";
+        $html .= "<span class='artifact_stars'>\n";
+        $html .= "</span>\n";
+        $html .= "<span class='artifact_level'>\n";
+        $html .= $artifact->get_level() . "\n";
+        $html .= "</span>\n";
+        $html .= "</div>\n";
+        if ($unit instanceof Unit){
+            $html .= "<div class='assigned'>\n";
+            $html .= "<a target='blank' href='/monsters/" . $unit->get_id() . "'>\n";
+            $html .= "<img title='" . $unit->get_title() . "' class='monster_image border_" . $unit->get_monster()->get_element_name() . "' src='" . $unit->get_monster()->get_image() . "'/>\n";
+            $html .= "</a>\n";
             $html .= "</div>\n";
-            if ($unit instanceof Unit){
-                $html .= "<div class='assigned'>\n";
-                $html .= "<a target='blank' href='/monsters/" . $unit->get_id() . "'>\n";
-                $html .= "<img title='" . $unit->get_title() . "' class='monster_image border_" . $unit->get_monster()->get_element_name() . "' src='" . $unit->get_monster()->get_image() . "'/>\n";
-                $html .= "</a>\n";
-                $html .= "</div>\n";
-            }
-            return $html;
         }
+        return $html;
+    }
 
-        /**
-         * Generates a artifact table.
-         * 
-         * @param Artifact artifact Entity to get the info from.
-         * @param Unit unit Optional. The unit the artifact is assigned to.
-         * @return string HTML content for a artifact table. Empty on error.
-         */
-        public static function artifact_table($artifact, $unit = null) {
-            if (!($artifact instanceof Artifact)){
-                return "";
-            }
-            $html = "";
-            $html .= "<table class='artifact' id='artifact-" . $artifact->get_id() . "'>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='icon'>\n";
-            $html .= HTML::artifact_panel($artifact, $unit) . "\n";
-            $html .= "</td>\n";
-            $html .= "<td class='effects'>\n";
-            $html .= "<table>\n";
-            // Main stat
-            $html .= "<tr class='effect main_stat'>\n";
+    /**
+     * Generates a artifact table.
+     * 
+     * @param Artifact artifact Entity to get the info from.
+     * @param Unit unit Optional. The unit the artifact is assigned to.
+     * @return string HTML content for a artifact table. Empty on error.
+     */
+    public static function artifact_table($artifact, $unit = null) {
+        if (!($artifact instanceof Artifact)){
+            return "";
+        }
+        $html = "";
+        $html .= "<table class='artifact' id='artifact-" . $artifact->get_id() . "'>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='icon'>\n";
+        $html .= HTML::artifact_panel($artifact, $unit) . "\n";
+        $html .= "</td>\n";
+        $html .= "<td class='effects'>\n";
+        $html .= "<table>\n";
+        // Main stat
+        $html .= "<tr class='effect main_stat'>\n";
+        $html .= "<td class='effect'>\n";
+        $stat_name = $artifact->get_stat()->get_name();
+        $stat_value = "+" . $artifact->get_stat()->get_value();
+        $html .= $stat_name . "\n";
+        $html .= $stat_value . "\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        //$effects = array($artifact->effect_1_description, $artifact->effect_2_description, $artifact->effect_3_description, $artifact->effect_4_description);
+        for ($i = 0; $i < 4; $i ++){
+            $html .= "<tr class='effect'>\n";
             $html .= "<td class='effect'>\n";
-            $stat_name = $artifact->get_stat()->get_name();
-            $stat_value = "+" . $artifact->get_stat()->get_value();
-            $html .= $stat_name . "\n";
-            $html .= $stat_value . "\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            //$effects = array($artifact->effect_1_description, $artifact->effect_2_description, $artifact->effect_3_description, $artifact->effect_4_description);
-            for ($i = 0; $i < 4; $i ++){
-                $html .= "<tr class='effect'>\n";
-                $html .= "<td class='effect'>\n";
-                if (count($artifact->get_effects()) <= $i){
-                    $name = "&nbsp;";
-                }
-                else{
-                    $name = $artifact->get_effects()[$i]->get_name();
-                    $name = str_replace("Increasing", "Inc.", $name);
-                    $name = str_replace("Decrease", "Dec.", $name);
-                    $name = str_replace("Critical", "Crit.", $name);
-                    $name = str_replace("Received ", "", $name);
-                    $name = str_replace("Damage", "Dmg.", $name);
-                    $name = str_replace("Additional", "Addl.", $name);
-                    $name = str_replace("Proportional", "Rel.", $name);
-                    $name = str_replace("Counterattack", "Counter", $name);
-                    $name = str_replace("Dealt by Attacking Together", "Attacking Together", $name);
-                    $name = str_replace("HP condition is bad", "bad HP", $name);
-                    $name = str_replace("HP condition is good", "good HP", $name);
-                }
-                $html .= $name;
-                $html .= "</td>\n";
-                $html .= "</tr>\n";
+            if (count($artifact->get_effects()) <= $i){
+                $name = "&nbsp;";
             }
-            $html .= "</table>\n";
-            $html .= "</td>\n";
-            $html .= "</tr>\n";
-            $html .= "<tr>\n";
-            $html .= "<td class='details' colspan='2'>\n";
-            $html .= "EFF.: " . number_format($artifact->get_efficiency(), 2, ".", ",") . "%&nbsp;&nbsp;\n";
-            $html .= "MX.E.: " . number_format($artifact->get_max_efficiency(), 2, ".", ",") . "%&nbsp;&nbsp;\n";
-            $html .= "Value.: " . number_format($artifact->get_value(), 0, ".", ",") . "\n";
+            else{
+                $name = $artifact->get_effects()[$i]->get_name();
+                $name = str_replace("Increasing", "Inc.", $name);
+                $name = str_replace("Decrease", "Dec.", $name);
+                $name = str_replace("Critical", "Crit.", $name);
+                $name = str_replace("Received ", "", $name);
+                $name = str_replace("Damage", "Dmg.", $name);
+                $name = str_replace("Additional", "Addl.", $name);
+                $name = str_replace("Proportional", "Rel.", $name);
+                $name = str_replace("Counterattack", "Counter", $name);
+                $name = str_replace("Dealt by Attacking Together", "Attacking Together", $name);
+                $name = str_replace("HP condition is bad", "bad HP", $name);
+                $name = str_replace("HP condition is good", "good HP", $name);
+            }
+            $html .= $name;
             $html .= "</td>\n";
             $html .= "</tr>\n";
-            $html .= "</table>\n";
-            return $html;
         }
+        $html .= "</table>\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "<tr>\n";
+        $html .= "<td class='details' colspan='2'>\n";
+        $html .= "EFF.: " . number_format($artifact->get_efficiency(), 2, ".", ",") . "%&nbsp;&nbsp;\n";
+        $html .= "MX.E.: " . number_format($artifact->get_max_efficiency(), 2, ".", ",") . "%&nbsp;&nbsp;\n";
+        $html .= "Value.: " . number_format($artifact->get_value(), 0, ".", ",") . "\n";
+        $html .= "</td>\n";
+        $html .= "</tr>\n";
+        $html .= "</table>\n";
+        return $html;
+    }
 
-        /**
-         * Generates a grindstone or gem panel.
-         * 
-         * @param Enchantment Entity to get the info from.
-         * @return string HTML content for a rune panel. Empty on error.
-         */
-        public static function enchantment_panel($enchantment) {
-            if (!($enchantment instanceof Enchantment)){
-                return "";
-            }
-            $html = "";
-            if ($enchantment->is_gem()){
-                if ($enchantment->is_inmemorial()){
-                    $base = URL::IMG["GRIND"] . "gem_inmemorial.png";
-                }
-                else{
-                    $base = URL::IMG["GRIND"] . "gem.png";
-                }
-            }
-            else{
-                if ($enchantment->is_inmemorial()){
-                    $base = URL::IMG["GRIND"] . "grind_inmemorial.png";
-                }
-                else{
-                    $base = URL::IMG["GRIND"] . "grind.png";
-                }
-            }
-            if (! $enchantment->is_inmemorial() && $enchantment->get_rune_set() != null){
-                $icon = "<img class='enchantment_icon' src='" . $enchantment->get_rune_set()->get_image() . "'/>\n";
+    /**
+     * Generates a grindstone or gem panel.
+     * 
+     * @param Enchantment Entity to get the info from.
+     * @return string HTML content for a rune panel. Empty on error.
+     */
+    public static function enchantment_panel($enchantment) {
+        if (!($enchantment instanceof Enchantment)){
+            return "";
+        }
+        $html = "";
+        if ($enchantment->is_gem()){
+            if ($enchantment->is_inmemorial()){
+                $base = URL::IMG["GRIND"] . "gem_inmemorial.png";
             }
             else{
-                $icon = "";
+                $base = URL::IMG["GRIND"] . "gem.png";
             }
-            if (in_array($enchantment->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
-                $stat_name = str_replace("%", "", $enchantment->get_stat_name());
-                $stat_value = "+" . $enchantment->get_min() . "~" . $enchantment->get_max() . "%";
+        }
+        else{
+            if ($enchantment->is_inmemorial()){
+                $base = URL::IMG["GRIND"] . "grind_inmemorial.png";
             }
             else{
-                $stat_name = $enchantment->get_stat_name();
-                $stat_value = "+" . $enchantment->get_min() . "~" . $enchantment->get_max();
+                $base = URL::IMG["GRIND"] . "grind.png";
             }
-            $html .= "<div class='enchantment_panel enchantment_quality_" . strtolower($enchantment->get_quality_name()) . " enchantment_ancient_" . $enchantment->is_ancient() . "'>\n";
-            $html .= "<img class='enchantment_base' src='" . $base . "'/>\n";
-            $html .= $icon;
-            $html .= "<span class='enchantment_stat'>\n";
-            $html .= "<span class='enchantment_stat->stat_name'>" . $stat_name . "</span>\n";
-            $html .= "<span class='enchantment_stat->value'>" . $stat_value . "</span>\n";
+        }
+        if (! $enchantment->is_inmemorial() && $enchantment->get_rune_set() != null){
+            $icon = "<img class='enchantment_icon' src='" . $enchantment->get_rune_set()->get_image() . "'/>\n";
+        }
+        else{
+            $icon = "";
+        }
+        if (in_array($enchantment->get_stat_name(), array("CRR", "CRD", "RES", "ACC", "HP%", "ATK%", "DEF%"))){
+            $stat_name = str_replace("%", "", $enchantment->get_stat_name());
+            $stat_value = "+" . $enchantment->get_min() . "~" . $enchantment->get_max() . "%";
+        }
+        else{
+            $stat_name = $enchantment->get_stat_name();
+            $stat_value = "+" . $enchantment->get_min() . "~" . $enchantment->get_max();
+        }
+        $html .= "<div class='enchantment_panel enchantment_quality_" . strtolower($enchantment->get_quality_name()) . " enchantment_ancient_" . $enchantment->is_ancient() . "'>\n";
+        $html .= "<img class='enchantment_base' src='" . $base . "'/>\n";
+        $html .= $icon;
+        $html .= "<span class='enchantment_stat'>\n";
+        $html .= "<span class='enchantment_stat->stat_name'>" . $stat_name . "</span>\n";
+        $html .= "<span class='enchantment_stat->value'>" . $stat_value . "</span>\n";
+        $html .= "</span>\n";
+        if ($enchantment->get_amount() > 1){
+            $html .= "<span class='enchantment_amount'>\n";
+            $html .= "x" . $enchantment->get_amount() . "\n";
             $html .= "</span>\n";
-            if ($enchantment->get_amount() > 1){
-                $html .= "<span class='enchantment_amount'>\n";
-                $html .= "x" . $enchantment->get_amount() . "\n";
-                $html .= "</span>\n";
-            }
-            $html .= "</div>\n";
-            return $html;
         }
+        $html .= "</div>\n";
+        return $html;
+    }
 
-        /**
-         * Generates a building panel.
-         *
-         * @param Building|Decoration|Buildable|Decorative $building Entity to get the info from.
-         * @return string HTML content for a building panel. Empty on error.
-         */
-        public static function building_panel($building) {
-            if ($building instanceof Building){
-                $level = false;
-                $title = $building->get_buildable()->get_name();
-                $description = $building->get_buildable()->get_description();
-                $img = $building->get_buildable()->get_image();
-            }
-            elseif ($building instanceof Buildable){
-                $level = false;
-                $title = $building->get_name();
-                $description = $building->get_description();
-                $img = $building->get_image();
-            }
-            elseif ($building instanceof Decoration){
-                $level = $building->get_level();
-                $title = $building->get_decorative()->get_name();
-                $description = $building->get_decorative()->get_description();
-                $img = $building->get_decorative()->get_image();
-            }
-            elseif ($building instanceof Decorative){
-                $level = false;
-                $title = $building->get_name();
-                $description = $building->get_description();
-                $img = $building->get_image();
-            }
-            else{
-                return "";
-            }
-            if (strlen($description) > 0){
-                $title .= ": " . $description;
-            }
-            $html = "<div class='building_panel'>\n";
-            $html .= "<img title='" . $title . "' class='building' src='" . $img . "'/>\n";
-            if ($level){
-                $html .= "<span class='level'>\n";
-                $html .= $level . "\n";
-                $html .= "</span>\n";
-            }
-            $html .= "</div>\n";
-            return $html;
+    /**
+     * Generates a building panel.
+     *
+     * @param Building|Decoration|Buildable|Decorative $building Entity to get the info from.
+     * @return string HTML content for a building panel. Empty on error.
+     */
+    public static function building_panel($building) {
+        if ($building instanceof Building){
+            $level = false;
+            $title = $building->get_buildable()->get_name();
+            $description = $building->get_buildable()->get_description();
+            $img = $building->get_buildable()->get_image();
         }
+        elseif ($building instanceof Buildable){
+            $level = false;
+            $title = $building->get_name();
+            $description = $building->get_description();
+            $img = $building->get_image();
+        }
+        elseif ($building instanceof Decoration){
+            $level = $building->get_level();
+            $title = $building->get_decorative()->get_name();
+            $description = $building->get_decorative()->get_description();
+            $img = $building->get_decorative()->get_image();
+        }
+        elseif ($building instanceof Decorative){
+            $level = false;
+            $title = $building->get_name();
+            $description = $building->get_description();
+            $img = $building->get_image();
+        }
+        else{
+            return "";
+        }
+        if (strlen($description) > 0){
+            $title .= ": " . $description;
+        }
+        $html = "<div class='building_panel'>\n";
+        $html .= "<img title='" . $title . "' class='building' src='" . $img . "'/>\n";
+        if ($level){
+            $html .= "<span class='level'>\n";
+            $html .= $level . "\n";
+            $html .= "</span>\n";
+        }
+        $html .= "</div>\n";
+        return $html;
+    }
 
-        /**
-         * Generates a item panel.
-         *
-         * @param Inventory $item Entity to get the info from.
-         * @return string HTML content for an item panel. Empty on error.
-         */
-        public static function item_panel($item) {
-            if (!($item instanceof Inventory) && !($item instanceof Item)){
-                return "";
-            }
-
-            if ($item instanceof Item){
-                $html = "<div class='item_panel'>\n";
-                $html .= "<img title='" . $item->get_name() . "' class='item' src='" . $item->get_image() . "'/>\n";
-                $html .= "<span class='amount'>\n";
-                $html .= $item->get_amount() . "\n";
-                $html .= "</span>\n";
-                $html .= "</div>\n";
-            }
-            elseif ($item instanceof Inventory){
-                $html = "<div class='item_panel'>\n";
-                $html .= "<img title='" . $item->get_name() . "' class='item' src='" . $item->get_image() . "'/>\n";
-                $html .= "</div>\n";
-            }
-            return $html;
+    /**
+     * Generates a item panel.
+     *
+     * @param Inventory $item Entity to get the info from.
+     * @return string HTML content for an item panel. Empty on error.
+     */
+    public static function item_panel($item) {
+        if (!($item instanceof Inventory) && !($item instanceof Item)){
+            return "";
         }
 
-        /**
-         * Generates a source panel.
-         *
-         * @param Inventory $source Entity to get the info from.
-         * @return string HTML content for a source panel. Empty on error.
-         */
-        public static function source_panel($source) {
-            //if (!($item instanceof Source)){
-            //    return "";
-            //}
-            $html = "<div class='source_panel'>\n";
-            $html .= "<img title='" . $source->get_name() . "' class='item' src='" . $source->get_image() . "'/>\n";
+        if ($item instanceof Item){
+            $html = "<div class='item_panel'>\n";
+            $html .= "<img title='" . $item->get_name() . "' class='item' src='" . $item->get_image() . "'/>\n";
+            $html .= "<span class='amount'>\n";
+            $html .= $item->get_amount() . "\n";
+            $html .= "</span>\n";
             $html .= "</div>\n";
-            return $html;
         }
-
-        /**
-         * Generates an arena rank icon image.
-         *
-         * @param int $d Arena rank id.
-         * @return string HTML content for the image.
-         */
-        public static function arena_rank_icon($id) {
-            switch ($id){
-                case ARENA_RANK_ID::BEGINER:
-                    $src = URL::IMG["RANK"] . "0901.png";
-                    $tit = "Beginer";
-                    break;
-                case ARENA_RANK_ID::CHALLENGER_1:
-                    $src = URL::IMG["RANK"] . "1001.png";
-                    $tit = "Challenger 1";
-                    break;
-                case ARENA_RANK_ID::CHALLENGER_2:
-                    $src = URL::IMG["RANK"] . "1002.png";
-                    $tit = "Challenger 2";
-                    break;
-                case ARENA_RANK_ID::CHALLENGER_3:
-                    $src = URL::IMG["RANK"] . "1003.png";
-                    $tit = "Challenger 3";
-                    break;
-                case ARENA_RANK_ID::FIGHTER_1:
-                    $src = URL::IMG["RANK"] . "2001.png";
-                    $tit = "Fighter 1";
-                    break;
-                case ARENA_RANK_ID::FIGHTER_2:
-                    $src = URL::IMG["RANK"] . "2002.png";
-                    $tit = "Fighter 2";
-                    break;
-                case ARENA_RANK_ID::FIGHTER_3:
-                    $src = URL::IMG["RANK"] . "2003.png";
-                    $tit = "Fighter 3";
-                    break;
-                case ARENA_RANK_ID::CONQUEROR_1:
-                    $src = URL::IMG["RANK"] . "3001.png";
-                    $tit = "Conqueror 1";
-                    break;
-                case ARENA_RANK_ID::CONQUEROR_2:
-                    $src = URL::IMG["RANK"] . "3002.png";
-                    $tit = "Conqueror 2";
-                    break;
-                case ARENA_RANK_ID::CONQUEROR_3:
-                    $src = URL::IMG["RANK"] . "3003.png";
-                    $tit = "Conqueror 3";
-                    break;
-                case ARENA_RANK_ID::GUARDIAN_1:
-                    $src = URL::IMG["RANK"] . "4001.png";
-                    $tit = "Guardian 1";
-                    break;
-                case ARENA_RANK_ID::GUARDIAN_2:
-                    $src = URL::IMG["RANK"] . "4002.png";
-                    $tit = "Guardian 2";
-                    break;
-                case ARENA_RANK_ID::GUARDIAN_3:
-                    $src = URL::IMG["RANK"] . "4003.png";
-                    $tit = "Guardian 3";
-                    break;
-                case ARENA_RANK_ID::LEGEND:
-                    $src = URL::IMG["RANK"] . "5001.png";
-                    $tit = "Legend";
-                default:
-                    $src = URL::IMG["RANK"] . "0901.png";
-                    $tit = "Beginer";
-            }
-            $html = "<img alt='$tit' title='$tit' src='$src'/>";
-            return $html;
+        elseif ($item instanceof Inventory){
+            $html = "<div class='item_panel'>\n";
+            $html .= "<img title='" . $item->get_name() . "' class='item' src='" . $item->get_image() . "'/>\n";
+            $html .= "</div>\n";
         }
+        return $html;
+    }
+
+    /**
+     * Generates a source panel.
+     *
+     * @param Inventory $source Entity to get the info from.
+     * @return string HTML content for a source panel. Empty on error.
+     */
+    public static function source_panel($source) {
+        //if (!($item instanceof Source)){
+        //    return "";
+        //}
+        $html = "<div class='source_panel'>\n";
+        $html .= "<img title='" . $source->get_name() . "' class='item' src='" . $source->get_image() . "'/>\n";
+        $html .= "</div>\n";
+        return $html;
+    }
 
+    /**
+     * Generates an arena rank icon image.
+     *
+     * @param int $d Arena rank id.
+     * @return string HTML content for the image.
+     */
+    public static function arena_rank_icon($id) {
+        switch ($id){
+            case ARENA_RANK_ID::BEGINER:
+                $src = URL::IMG["RANK"] . "0901.png";
+                $tit = "Beginer";
+                break;
+            case ARENA_RANK_ID::CHALLENGER_1:
+                $src = URL::IMG["RANK"] . "1001.png";
+                $tit = "Challenger 1";
+                break;
+            case ARENA_RANK_ID::CHALLENGER_2:
+                $src = URL::IMG["RANK"] . "1002.png";
+                $tit = "Challenger 2";
+                break;
+            case ARENA_RANK_ID::CHALLENGER_3:
+                $src = URL::IMG["RANK"] . "1003.png";
+                $tit = "Challenger 3";
+                break;
+            case ARENA_RANK_ID::FIGHTER_1:
+                $src = URL::IMG["RANK"] . "2001.png";
+                $tit = "Fighter 1";
+                break;
+            case ARENA_RANK_ID::FIGHTER_2:
+                $src = URL::IMG["RANK"] . "2002.png";
+                $tit = "Fighter 2";
+                break;
+            case ARENA_RANK_ID::FIGHTER_3:
+                $src = URL::IMG["RANK"] . "2003.png";
+                $tit = "Fighter 3";
+                break;
+            case ARENA_RANK_ID::CONQUEROR_1:
+                $src = URL::IMG["RANK"] . "3001.png";
+                $tit = "Conqueror 1";
+                break;
+            case ARENA_RANK_ID::CONQUEROR_2:
+                $src = URL::IMG["RANK"] . "3002.png";
+                $tit = "Conqueror 2";
+                break;
+            case ARENA_RANK_ID::CONQUEROR_3:
+                $src = URL::IMG["RANK"] . "3003.png";
+                $tit = "Conqueror 3";
+                break;
+            case ARENA_RANK_ID::GUARDIAN_1:
+                $src = URL::IMG["RANK"] . "4001.png";
+                $tit = "Guardian 1";
+                break;
+            case ARENA_RANK_ID::GUARDIAN_2:
+                $src = URL::IMG["RANK"] . "4002.png";
+                $tit = "Guardian 2";
+                break;
+            case ARENA_RANK_ID::GUARDIAN_3:
+                $src = URL::IMG["RANK"] . "4003.png";
+                $tit = "Guardian 3";
+                break;
+            case ARENA_RANK_ID::LEGEND:
+                $src = URL::IMG["RANK"] . "5001.png";
+                $tit = "Legend";
+            default:
+                $src = URL::IMG["RANK"] . "0901.png";
+                $tit = "Beginer";
+        }
+        $html = "<img alt='$tit' title='$tit' src='$src'/>";
+        return $html;
     }
 
-?>
+}

+ 18 - 17
application/helper/Helper.php

@@ -1,19 +1,20 @@
 <?php
-    /**
-     * Base helper file.
-     *
-     * Provides an empty helper.
-     *
-     * @category Helper
-     */
+/**
+ * Base helper file.
+ *
+ * Provides an empty helper.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Helper superclass.
-     *
-     * Every other entity must inherit from this one. 
-     * 
-     * @abstract
-     * @category Helper
-     */
-    abstract class Helper{}
-?>
+/**
+ * Helper superclass.
+ *
+ * Every other entity must inherit from this one. 
+ * 
+ * @abstract
+ * @category Helper
+ */
+abstract class Helper{}

+ 49 - 51
application/helper/NET_Helper.php

@@ -1,61 +1,59 @@
 <?php
-    /**
-     * Netowrk helper file.
-     *
-     * Provides a helper to perform network operations.
-     *
-     * @category Helper.
-     */
+/**
+ * Netowrk helper file.
+ *
+ * Provides a helper to perform network operations.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::HELPER . "Helper.php");
+require_once(PATH::HELPER . "Helper.php");
+
+/**
+ * Netowrk helper.
+ *
+ * Contains netowrk related utilities.
+ *
+ * @category Helper.
+ */
+final class NET extends Helper{
 
     /**
-     * Netowrk helper.
+     * Finds out the protocol the user is connecting to the site with.
      *
-     * Contains netowrk related utilities.
-     *
-     * @category Helper.
+     * @return string "http://" or "https://".
      */
-    final class NET extends Helper{
-
-        /**
-         * Finds out the protocol the user is connecting to the site with.
-         *
-         * @return string "http://" or "https://".
-         */
-        public static function get_protocol(){
-            if (isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on" || $_SERVER["HTTPS"] == 1) || isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && $_SERVER["HTTP_X_FORWARDED_PROTO"] == "https") {
-                $protocol = "https://";
-            }
-            else {
-                $protocol = "http://";
-            }
-            return $protocol;
+    public static function get_protocol(){
+        if (isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on" || $_SERVER["HTTPS"] == 1) || isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && $_SERVER["HTTP_X_FORWARDED_PROTO"] == "https") {
+            $protocol = "https://";
         }
-
-        /**
-         * Finds out the IP address of the client.
-         * 
-         * @return string Client IP address.
-         */
-        public static function get_ip(){
-            $client  = @$_SERVER["HTTP_CLIENT_IP"];
-            $forward = @$_SERVER["HTTP_X_FORWARDED_FOR"];
-            $remote  = $_SERVER["REMOTE_ADDR"];
-            if(filter_var($client, FILTER_VALIDATE_IP)){
-                $ip = $client;
-            }
-            elseif(filter_var($forward, FILTER_VALIDATE_IP)){
-                $ip = $forward;
-            }
-            else{
-                $ip = $remote;
-            }
-            return $ip;
+        else {
+            $protocol = "http://";
         }
+        return $protocol;
+    }
 
+    /**
+     * Finds out the IP address of the client.
+     * 
+     * @return string Client IP address.
+     */
+    public static function get_ip(){
+        $client  = @$_SERVER["HTTP_CLIENT_IP"];
+        $forward = @$_SERVER["HTTP_X_FORWARDED_FOR"];
+        $remote  = $_SERVER["REMOTE_ADDR"];
+        if(filter_var($client, FILTER_VALIDATE_IP)){
+            $ip = $client;
+        }
+        elseif(filter_var($forward, FILTER_VALIDATE_IP)){
+            $ip = $forward;
+        }
+        else{
+            $ip = $remote;
+        }
+        return $ip;
     }
-?>
+
+}

+ 92 - 96
application/helper/TEXT_Helper.php

@@ -1,110 +1,106 @@
 <?php
+/**
+ * Text helper file.
+ *
+ * Provides a helper to perform text operations.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::HELPER . "Helper.php");
+
+/**
+ * Text helper.
+ *
+ * Contains utilities to format and escapee text.
+ *
+ * @category Helper.
+ */
+final class TEXT extends Helper{
+
     /**
-     * Text helper file.
-     *
-     * Provides a helper to perform text operations.
-     *
-     * @category Helper.
+     * Turns a date string into a human readable string on the specified
+     * language. Only works for spanish, basque and english.
+     * 
+     * @param string $str_date Date string ('yyyy-mm-dd' or 'yyyy-mm-dd HH:MM:SS')
+     * @param string $time Append the time at the end.
+     * @return string Formatted date string.
      */
+    public static function format_date($str_date, $time = true){
+        $date = strtotime($str_date);
+        $year = date("o", $date);
+        $month = date("n", $date);
+        $month --;
+        $day = date("j", $date);
+        $wday = date("N", $date);
+        $wday --;
+        $hour = date("H", $date);
+        $minute = date("i", $date);
+        $week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
+        $months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+        if ($time){
+            $str = "$week[$wday], $months[$month] $day, $year at $hour:$minute";
+        }
+        else{
+            $str = "$week[$wday], $months[$month] $day, $year";
+        }
+        return $str;
+    }
 
     /**
-     * Require dependent files if not present.
+     * Closes all the opened HTML tags in a given string.
+     * 
+     * @param string html The string with HTML tags.
+     * @return string HTML with closed tags.
      */
-    require_once(PATH::HELPER . "Helper.php");
+    public static function close_tags($html) {
+        $result = [];
+        preg_match_all("#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU", $html, $result);
+        $openedtags = $result[1];
+        preg_match_all("#</([a-z]+)>#iU", $html, $result);
+        $closedtags = $result[1];
+        $len_opened = count($openedtags);
+        if (count($closedtags) == $len_opened) {
+            return $html;
+        }
+        $openedtags = array_reverse($openedtags);
+        for ($i=0; $i < $len_opened; $i++) {
+            if (!in_array($openedtags[$i], $closedtags)) {
+                $html .= "</".$openedtags[$i].">";
+            } else {
+                unset($closedtags[array_search($openedtags[$i], $closedtags)]);
+            }
+        }
+        return $html;
+    }
 
     /**
-     * Text helper.
-     *
-     * Contains utilities to format and escapee text.
+     * Text shortener.
      *
-     * @category Helper.
+     * Given a string, it trims in the proximity of the
+     * desired string, up to the next white character. If indicated, it will
+     * append a link to the full text.
+     * 
+     * @param string $text The text to shorten.
+     * @param int $length The desired length.
+     * @param string $link_text Text for the link. Optional.
+     * @param string $link URI of the link.
+     * @return string Shortened text.
      */
-    final class TEXT extends Helper{
-
-        /**
-         * Turns a date string into a human readable string on the specified
-         * language. Only works for spanish, basque and english.
-         * 
-         * @param string $str_date Date string ('yyyy-mm-dd' or 'yyyy-mm-dd HH:MM:SS')
-         * @param string $time Append the time at the end.
-         * @return string Formatted date string.
-         */
-        public static function format_date($str_date, $time = true){
-            $date = strtotime($str_date);
-            $year = date("o", $date);
-            $month = date("n", $date);
-            $month --;
-            $day = date("j", $date);
-            $wday = date("N", $date);
-            $wday --;
-            $hour = date("H", $date);
-            $minute = date("i", $date);
-            $week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
-            $months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
-            if ($time){
-                $str = "$week[$wday], $months[$month] $day, $year at $hour:$minute";
-            }
-            else{
-                $str = "$week[$wday], $months[$month] $day, $year";
-            }
-            return $str;
+    public static function cut_text($text, $length, $link_text = "", $link = ""){
+        if (strlen($text) < $length){
+            return $text;
         }
-
-        /**
-         * Closes all the opened HTML tags in a given string.
-         * 
-         * @param string html The string with HTML tags.
-         * @return string HTML with closed tags.
-         */
-        public static function close_tags($html) {
-            $result = [];
-            preg_match_all("#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU", $html, $result);
-            $openedtags = $result[1];
-            preg_match_all("#</([a-z]+)>#iU", $html, $result);
-            $closedtags = $result[1];
-            $len_opened = count($openedtags);
-            if (count($closedtags) == $len_opened) {
-                return $html;
-            }
-            $openedtags = array_reverse($openedtags);
-            for ($i=0; $i < $len_opened; $i++) {
-                if (!in_array($openedtags[$i], $closedtags)) {
-                    $html .= "</".$openedtags[$i].">";
-                } else {
-                    unset($closedtags[array_search($openedtags[$i], $closedtags)]);
-                }
-            }
-            return $html;
+        $cut = substr($text, 0, strpos($text, " ", $length));
+        $cut = close_tags($cut);
+        if (strlen($cut) == 0){
+            $cut = $text;
         }
-
-        /**
-         * Text shortener.
-         *
-         * Given a string, it trims in the proximity of the
-         * desired string, up to the next white character. If indicated, it will
-         * append a link to the full text.
-         * 
-         * @param string $text The text to shorten.
-         * @param int $length The desired length.
-         * @param string $link_text Text for the link. Optional.
-         * @param string $link URI of the link.
-         * @return string Shortened text.
-         */
-        public static function cut_text($text, $length, $link_text = "", $link = ""){
-            if (strlen($text) < $length){
-                return $text;
-            }
-            $cut = substr($text, 0, strpos($text, " ", $length));
-            $cut = close_tags($cut);
-            if (strlen($cut) == 0){
-                $cut = $text;
-            }
-            if (strlen($text) != strlen($cut) && strlen($link) > 0 && strlen($link_text) > 0){
-                $cut = $cut . "... <a href='$link'>$link_text</a>";
-            }
-            return $cut;
+        if (strlen($text) != strlen($cut) && strlen($link) > 0 && strlen($link_text) > 0){
+            $cut = $cut . "... <a href='$link'>$link_text</a>";
         }
+        return $cut;
     }
-
-?>
-
+}

+ 249 - 163
application/page/Artifacts_Page.php

@@ -1,187 +1,273 @@
  <?php
+/**
+ * Artifact list page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Artifact.php");
+require_once(PATH::ENTITY . "Unit.php");
+
+/**
+ * Artifact list page model.
+ *
+ * @category Page
+ */
+class Artifacts_Page extends Page{
+    
     /**
-     * Artifact list page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var mixed[] Page filters
      */
+    private $filters = [
+        "TYPE" => 0,
+        "ELEMENT" => [],
+        "ARCHETYPE" => [],
+        "MAIN" => [],
+        "MIN_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_LEVEL" => 0,
+        "MAX_LEVEL" => 15,
+        "MIN_EFFICIENCY" => 0,
+        "MAX_EFFICIENCY" => 100,
+        "MIN_MAX_EFFICIENCY" => 0,
+        "MAX_MAX_EFFICIENCY" => 100,
+        "ASSIGNED" => 1
+    ];
 
     /**
-     * Require dependent files if not present.
+     * @var Artifact[] Artiffacts to show.
+     *
+     * In this case, the monster member is not the id, but a monster
+     * instance.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Artifact.php");
-    require_once(PATH::ENTITY . "Unit.php");
+    private $artifacts = [];
 
     /**
-     * Artifact list page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Artifacts_Page extends Page{
+    public function __construct(){
+        $this->view = PATH::VIEW . "artifacts.php";
+        $this->parse_filters();
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->artifacts, new Artifact($result["id"]));
+        }
 
-        /**
-         * @var Artifact[] Artiffacts to show.
-         *
-         * In this case, the monster member is not the id, but a monster
-         * instance.
-         */
-        public $artifacts = [];
+        $this->title = "Artifacts - SWDB";
+        $this->description = "Artifact inventory";
+        $this->canonical = URL::BASE . "artifacts/";
+    }
 
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "artifacts.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $artifact = new Artifact($r["id"]);
-                array_push($this->artifacts, $artifact);
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        if (isset($_GET["element"])){
+            $elements = $_GET["element"];
+            foreach ($elements as $element){
+                array_push($this->filters["ELEMENT"], intval($element));
             }
-
-            $this->title = "Artifacts - SWDB";
-            $this->description = "Artifact inventory";
-            $this->canonical = URL::BASE . "artifacts/";
         }
-
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            $this->filters = FILTER::ARTIFACT;
-            if (isset($_GET["element"])){
-                $elements = $_GET["element"];
-                foreach ($elements as $element){
-                    array_push($this->filters["ELEMENT"], intval($element));
-                }
-            }
-            if (isset($_GET["archetype"])){
-                $archetypes = $_GET["archetype"];
-                foreach ($archetypes as $archetype){
-                    array_push($this->filters["ARCHETYPE"], intval($archetype));
-                }
-            }
-            if (isset($_GET["main_stat"])){
-                $mains = $_GET["main_stat"];
-                foreach ($mains as $main){
-                    array_push($this->filters["MAIN"], intval($main));
-                }
-            }
-            if (isset($_GET["min_level"]) && intval($_GET["min_level"]) >= 0 && intval($_GET["min_level"]) <= 15){
-                $this->filters["MIN_LEVEL"] = $_GET["min_level"];
-            }
-            if (isset($_GET["max_level"]) && intval($_GET["max_level"]) >= 0 && intval($_GET["max_level"]) <= 15){
-                $this->filters["MAX_LEVEL"] = $_GET["max_level"];
+        if (isset($_GET["archetype"])){
+            $archetypes = $_GET["archetype"];
+            foreach ($archetypes as $archetype){
+                array_push($this->filters["ARCHETYPE"], intval($archetype));
             }
-            if (isset($_GET["min_quality"]) && intval($_GET["min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MIN_QUALITY"] = $_GET["min_quality"];
-            }
-            if (isset($_GET["max_quality"]) && intval($_GET["max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MAX_QUALITY"] = $_GET["max_quality"];
-            }
-            if (isset($_GET["min_original_quality"]) && intval($_GET["min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_original_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MIN_ORIGINAL_QUALITY"] = $_GET["min_original_quality"];
-            }
-            if (isset($_GET["max_original_quality"]) && intval($_GET["max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_original_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MAX_ORIGINAL_QUALITY"] = $_GET["max_original_quality"];
-            }
-            if (isset($_GET["assigned"]) && intval($_GET["assigned"]) >= 0 && intval($_GET["assigned"]) <= 4){
-                $this->filters["ASSIGNED"] = $_GET["assigned"];
+        }
+        if (isset($_GET["main_stat"])){
+            $mains = $_GET["main_stat"];
+            foreach ($mains as $main){
+                array_push($this->filters["MAIN"], intval($main));
             }
         }
+        if (isset($_GET["min_level"]) && intval($_GET["min_level"]) >= 0 && intval($_GET["min_level"]) <= 15){
+            $this->filters["MIN_LEVEL"] = $_GET["min_level"];
+        }
+        if (isset($_GET["max_level"]) && intval($_GET["max_level"]) >= 0 && intval($_GET["max_level"]) <= 15){
+            $this->filters["MAX_LEVEL"] = $_GET["max_level"];
+        }
+        if (isset($_GET["min_quality"]) && intval($_GET["min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MIN_QUALITY"] = $_GET["min_quality"];
+        }
+        if (isset($_GET["max_quality"]) && intval($_GET["max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MAX_QUALITY"] = $_GET["max_quality"];
+        }
+        if (isset($_GET["min_original_quality"]) && intval($_GET["min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_original_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MIN_ORIGINAL_QUALITY"] = $_GET["min_original_quality"];
+        }
+        if (isset($_GET["max_original_quality"]) && intval($_GET["max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_original_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MAX_ORIGINAL_QUALITY"] = $_GET["max_original_quality"];
+        }
+        if (isset($_GET["assigned"]) && intval($_GET["assigned"]) >= 0 && intval($_GET["assigned"]) <= 4){
+            $this->filters["ASSIGNED"] = $_GET["assigned"];
+        }
+    }
 
-        /**
-         * Builds the query to the artifact table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-              SELECT
-                id,
-                (
-                  SELECT DISTINCT unit
-                  FROM unit_artifact
-                  WHERE
-                    artifact = artifact.id AND
-                    rta = " . get_context()->get_game_mode() . "
-                ) AS unit
-              FROM artifact artifact
-              WHERE
-                player = '" . get_context()->get_player()->get_id() . "' AND
-                level >= " . $this->filters["MIN_LEVEL"] . " AND 
-                level <= " . $this->filters["MAX_LEVEL"] . " AND
-                quality >= " . $this->filters["MIN_QUALITY"] . " AND
-                quality <= " . $this->filters["MAX_QUALITY"] . " AND
-                original_quality >= " . $this->filters["MIN_ORIGINAL_QUALITY"] . " AND
-                original_quality <= " . $this->filters["MAX_ORIGINAL_QUALITY"] . " AND
-                efficiency >= " . $this->filters["MIN_EFFICIENCY"] . " AND
-                efficiency <= " . $this->filters["MAX_EFFICIENCY"] . " AND
-                max_efficiency >= " . $this->filters["MIN_MAX_EFFICIENCY"] . " AND
-                max_efficiency <= " . $this->filters["MAX_MAX_EFFICIENCY"] . "
-            ";
-            if (count($this->filters["MAIN"]) > 0){
-                $s = $s . " AND main_stat IN ( ";
-                foreach($this->filters["MAIN"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
-            }
-            if (count($this->filters["ELEMENT"]) == 0 && count($this->filters["ARCHETYPE"]) == 0){
-                // No element/archetype conditions
-            }
-            elseif (count($this->filters["ELEMENT"]) > 0 && count($this->filters["ARCHETYPE"]) == 0){
-                // Only selected elements
-                $s = $s . " AND attribute IN ( ";
-                foreach($this->filters["ELEMENT"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
-            }
-            elseif (count($this->filters["ELEMENT"]) == 0 && count($this->filters["ARCHETYPE"]) > 0){
-                // Only selected types
-                $s = $s . " AND archetype IN ( ";
-                foreach($this->filters["ARCHETYPE"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        
+        // Common items
+        $query = "
+          SELECT id
+          FROM artifact
+          WHERE
+            player = :player AND
+            level BETWEEN :min_level AND :max_level AND
+            quality BETWEEN :min_quality AND :max_quality AND
+            original_quality BETWEEN :min_original_quality AND :max_original_quality AND
+            efficiency BETWEEN :min_efficiency AND :max_efficiency AND
+            max_efficiency BETWEEN :min_max_efficiency AND :max_max_efficiency
+        ";
+        
+        // Some main stat selected.
+        if (count($this->filters["MAIN"]) > 0){
+            $query .= " AND id IN (SELECT artifact FROM artifact_stat WHERE stat IN (";
+            for ($i = 0; $i < sizeof($this->filters["MAIN"]); $i ++){
+                $query .= ":main_$i, ";
             }
-            elseif (count($this->filters["ELEMENT"]) > 0 && count($this->filters["ARCHETYPE"]) > 0){
-                // Selected elements and selected types
-                $s = $s . " AND (archetype IN ( ";
-                foreach($this->filters["ARCHETYPE"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) OR attribute IN ( ";
-                foreach($this->filters["ELEMENT"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1)) ";
+            $query = rtrim($query, ", ") . ")) ";
+        }
+        
+        // Elements / archetypes selected
+        if (count($this->filters["ELEMENT"]) > 0 || count($this->filters["ARCHETYPE"]) > 0){
+            $query .= " AND (attribute IN ( ";
+            for ($i = 0; $i < sizeof($this->filters["ELEMENT"]); $i ++){
+                $query .= ":element_$i, ";
             }
-            switch ($this->filters["ASSIGNED"]){
-                case 1:
-                    $s = $s . " AND unit IS NOT NULL ";
-                    break;
-                case 2:
-                    $s = $s . " AND unit IS NULL ";
-                    break;
-                case 3:
-                    $s = $s . " AND (unit IS NULL OR unit IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ")) ";
-                    break;
-                case 4:
-                    $s = $s . " AND unit IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ") ";
-                    break;
+            $query = rtrim($query, ", ") . ") OR archetype IN (";
+            for ($i = 0; $i < sizeof($this->filters["ARCHETYPE"]); $i ++){
+                $query .= ":archetype_$i, ";
             }
-            $s = $s . " ORDER BY type, attribute, archetype, level DESC, original_quality DESC;";
-            return $s;
+            $query = rtrim($query, ", ") . ")) ";
+        }
+        
+        // Assigned status
+        switch ($this->filters["ASSIGNED"]){
+            case 0: // Assigned or unassigned.
+                break;
+            case 1: // Assigned.
+                $query .= "
+                  AND id IN (
+                    SELECT DISTINCT artifact 
+                    FROM unit_artifact 
+                    WHERE rta = :rta) ";
+                break;
+            case 2: // Unassigned.
+                $query .= "
+                  AND id NOT IN (
+                    SELECT DISTINCT artifact
+                    FROM unit_artifact
+                    WHERE rta = :rta) ";
+                break;
+            case 3: // Unassigned or assignet to monsters not in storage.
+                $query .= "
+                  AND (
+                    id NOT IN (
+                      SELECT DISTINCT artifact
+                      FROM unit_artifact
+                      WHERE rta = :rta
+                    ) OR (
+                      id IN (
+                        SELECT DISTINCT unit_artifact.artifact 
+                        FROM
+                          unit_artifact,
+                          unit
+                        WHERE
+                          unit_artifact.rta = :rta AND
+                          unit_artifact.unit = unit.id AND
+                          unit.building = :storage_building
+                      )
+                    )
+                  )";
+                break;
+            case 4: //Assigned to monsters not in storage.
+                $query .= "
+                  AND (
+                    id IN (
+                      SELECT DISTINCT unit_artifact.artifact
+                      FROM
+                        unit_artifact,
+                        unit
+                      WHERE
+                        unit_artifact.rta = :rta AND
+                        unit_artifact.unit = unit.id AND
+                        unit.building = :storage_building
+                    )
+                  )";
+                break;
         }
+        $query .= " ORDER BY type, attribute, archetype, level DESC, original_quality DESC;";
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":rta", get_context()->get_game_mode(), SQLITE3_INTEGER);
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":min_level", $this->filters["MIN_LEVEL"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_level", $this->filters["MAX_LEVEL"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_quality", $this->filters["MIN_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_quality", $this->filters["MAX_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_original_quality", $this->filters["MIN_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_original_quality", $this->filters["MAX_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_efficiency", $this->filters["MIN_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":max_efficiency", $this->filters["MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":min_max_efficiency", $this->filters["MIN_MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":max_max_efficiency", $this->filters["MAX_MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        for ($i = 0; $i < sizeof($this->filters["MAIN"]); $i ++){
+            $statement->bindValue(":main_$i", $this->filters["MAIN"][$i], SQLITE3_INTEGER);
+        }
+        for ($i = 0; $i < sizeof($this->filters["ELEMENT"]); $i ++){
+            $statement->bindValue(":element_$i", $this->filters["ELEMENT"][$i], SQLITE3_INTEGER);
+        }
+        for ($i = 0; $i < sizeof($this->filters["ARCHETYPE"]); $i ++){
+            $statement->bindValue(":archetype_$i", $this->filters["ARCHETYPE"][$i], SQLITE3_INTEGER);
+        }
+        $statement->bindValue(":storage_building", BUILDING_ID::MONSTER_STORAGE, SQLITE3_INTEGER);
+        return $statement;
     }
-?>
+
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes 
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+
+    /**
+     * Retrieves one filter.
+     * 
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
+        }
+    }
+
+    /**
+     * Retrieves the selection of artifacts.
+     *
+     * @return Artifact[] Artifacts to show on the page. 
+     */
+    public function get_artifacts(){
+        return $this->artifacts;
+    }
+
+}

+ 203 - 200
application/page/Enchantments_Page.php

@@ -1,225 +1,228 @@
  <?php
 
+/**
+ * Enchantment list page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Enchantment.php");
+
+/**
+ * Enchantment list page model.
+ *
+ * @category Page
+ */
+class Enchantments_Page extends Page{
+
     /**
-     * Enchantment list page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Enchantment[] Selected enchantment gems.
      */
+    private $gems = [];
 
     /**
-     * Require dependent files if not present.
+     * @var Enchantment[] Selected enchantment grindstones.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Enchantment.php");
+    private $grindstones = [];
 
     /**
-     * Enchantment list page model.
-     *
-     * @category Page
+     * @var Enchantment[] Selected enchantments.
      */
-    class Enchantments_Page extends Page{
-
-        /**
-         * @var Enchantment[] Owned enchantment gems.
-         */
-        public $gems = [];
+    private $enchantments = [];
 
-        /**
-         * @var Enchantment[] Owned enchantment grindstones.
-         */
-        public $grindstones = [];
+    /**
+     * 
+     * @var mixed[] Page filters.
+     */
+    private $filters = [
+        "TYPE" => [],
+        "RUNE" => [],
+        "STAT" => [],
+        "MIN_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_QUALITY" => QUALITY_ID::LEGEND,
+    ];
 
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "enchantments.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $enchantment = new Enchantment($r["id"]);
-                //if ($enchantment->gem == true){
-                //   array_push($this->gems, $enchantment);
-                //}
-                //else{
-                    array_push($this->grindstones, $enchantment);
-                //}
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     */
+    public function __construct(){
+        $this->view = PATH::VIEW . "enchantments.php";
+        $this->parse_filters();
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            $enchantment = new Enchantment($result["id"]);
+            array_push($this->enchantments, $enchantment);
+            if ($enchantment->is_gem()){
+               array_push($this->gems, $enchantment);
+            }
+            else{
+                array_push($this->grindstones, $enchantment);
             }
-            $this->title = "Enchantments - SWDB";
-            $this->description = "Enchantment inventory";
-            $this->canonical = URL::BASE . "enchantments/";
         }
+        $this->title = "Enchantments - SWDB";
+        $this->description = "Enchantment inventory";
+        $this->canonical = URL::BASE . "enchantments/";
+    }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            $this->filters = FILTER::ENCHANTMENT;
-            if (isset($_GET["min_quality"]) && intval($_GET["min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MIN_QUALITY"] = $_GET["min_quality"];
-            }
-            if (isset($_GET["max_quality"]) && intval($_GET["max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MAX_QUALITY"] = $_GET["max_quality"];
-            }
-            if (isset($_GET["stat"])){
-                $stats = $_GET["stat"];
-                foreach ($stats as $stat){
-                    array_push($this->filters["STAT"], intval($stat));
-                }
-            }
-            if (isset($_GET["rune"])){
-                $runes = $_GET["rune"];
-                foreach ($runes as $rune){
-                    array_push($this->filters["RUNE"], intval($rune));
-                }
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        if (isset($_GET["min_quality"]) && intval($_GET["min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MIN_QUALITY"] = $_GET["min_quality"];
+        }
+        if (isset($_GET["max_quality"]) && intval($_GET["max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MAX_QUALITY"] = $_GET["max_quality"];
+        }
+        if (isset($_GET["stat"])){
+            $stats = $_GET["stat"];
+            foreach ($stats as $stat){
+                array_push($this->filters["STAT"], intval($stat));
             }
-            if (isset($_GET["type"])){
-                $types = $_GET["type"];
-                foreach ($types as $type){
-                    array_push($this->filters["TYPE"], $type);
-                }
+        }
+        if (isset($_GET["rune"])){
+            $runes = $_GET["rune"];
+            foreach ($runes as $rune){
+                array_push($this->filters["RUNE"], intval($rune));
             }
-            // TODO
-            /*
-            if (isset($_GET["archetype"])){
-                $archetypes = $_GET["archetype"];
-                foreach ($archetypes as $archetype){
-                    array_push($this->filters["ARCHETYPE"], intval($archetype));
-                }
+        }
+        if (isset($_GET["type"])){
+            $types = $_GET["type"];
+            foreach ($types as $type){
+                array_push($this->filters["TYPE"], $type);
             }
+        }
+    }
 
-            if (isset($_GET["min_level"]) && intval($_GET["min_level"]) >= 0 && intval($_GET["min_level"]) <= 15){
-                $this->filters["MIN_LEVEL"] = $_GET["min_level"];
-            }
-            if (isset($_GET["max_level"]) && intval($_GET["max_level"]) >= 0 && intval($_GET["max_level"]) <= 15){
-                $this->filters["MAX_LEVEL"] = $_GET["max_level"];
-            }
-            if (isset($_GET["min_original_quality"]) && intval($_GET["min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_original_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MIN_ORIGINAL_QUALITY"] = $_GET["min_original_quality"];
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        // Common items
+        $query = "
+          SELECT id
+          FROM enchantment
+          WHERE
+            player = :player AND
+            quality BETWEEN :min_quality AND :max_quality
+        ";
+        
+        // Some main stat selected.
+        if (count($this->filters["STAT"]) > 0){
+            $query .= " AND stat IN (";
+            for ($i = 0; $i < sizeof($this->filters["STAT"]); $i ++){
+                $query .= ":stat_$i, ";
+            }
+            $query = rtrim($query, ", ") . ") ";
+        }
+        
+        // Some sets selected.
+        if (count($this->filters["RUNE"]) > 0){
+            $query .= " AND (rune IN (";
+            for ($i = 0; $i < sizeof($this->filters["RUNE"]); $i ++){
+                $query .= ":rune_$i, ";
+            }
+            $query = rtrim($query, ", ");
+            $query .= ") OR type IN (:inmemorial_grindstone, :inmemorial_gem))"; // Inmemorials
+        }
+        
+        // Only one type selected.
+        if (count($this->filters["TYPE"]) == 1){
+            // Only one selectd, it's either gems or grindstones
+            if (in_array("GEM", $this->filters["TYPE"])){
+                $query .= " AND type IN (:type_gem, :type_inmemorial_gem) "; // Gems.
             }
-            if (isset($_GET["max_original_quality"]) && intval($_GET["max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_original_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MAX_ORIGINAL_QUALITY"] = $_GET["max_original_quality"];
+            else{
+                $query .= " AND type IN (:type_grindstone, :type_inmemorial_grindstone) "; // Grinds.
             }
-            if (isset($_GET["assigned"]) && intval($_GET["assigned"]) >= 0 && intval($_GET["assigned"]) <= 4){
-                $this->filters["ASSIGNED"] = $_GET["assigned"];
-            }*/
         }
+        $query .= "
+          ORDER BY
+            type = :type_inmemorial_grindstone DESC,  -- Inmemorial Grindstone
+            type = :type_inmemorial_gem DESC,  -- Inmemorial Gem
+            rune,
+            type,
+            quality DESC,
+            stat
+        ";
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":min_quality", $this->filters["MIN_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_quality", $this->filters["MAX_QUALITY"], SQLITE3_INTEGER);
+        for ($i = 0; $i < sizeof($this->filters["STAT"]); $i ++){
+            $statement->bindValue(":stat_$i", $this->filters["STAT"][$i], SQLITE3_INTEGER);
+        }
+        for ($i = 0; $i < sizeof($this->filters["RUNE"]); $i ++){
+            $statement->bindValue(":rune_$i", $this->filters["RUNE"][$i], SQLITE3_INTEGER);
+        }
+        $statement->bindValue(":inmemorial_gem", ENCHANTMENT_TYPE_ID::INMEMORIAL_GEM, SQLITE3_INTEGER);
+        $statement->bindValue(":inmemorial_grindstone", ENCHANTMENT_TYPE_ID::INMEMORIAL_GRINDSTONE, SQLITE3_INTEGER);
+        $statement->bindValue(":type_gem", ENCHANTMENT_TYPE_ID::GEM, SQLITE3_INTEGER);
+        $statement->bindValue(":type_grindstone", ENCHANTMENT_TYPE_ID::GRINDSTONE, SQLITE3_INTEGER);
+        $statement->bindValue(":type_inmemorial_gem", ENCHANTMENT_TYPE_ID::INMEMORIAL_GEM, SQLITE3_INTEGER);
+        $statement->bindValue(":type_inmemorial_grindstone", ENCHANTMENT_TYPE_ID::INMEMORIAL_GRINDSTONE, SQLITE3_INTEGER);
+        return $statement;
+    }
 
-        /**
-         * Builds the query to the artifact table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-              SELECT id
-              FROM enchantment
-              WHERE
-                player = '" . get_context()->get_player()->get_id() . "' AND
-                quality >= " . $this->filters["MIN_QUALITY"] . " AND
-                quality <= " . $this->filters["MAX_QUALITY"] . "
-            ";
-            if (count($this->filters["STAT"]) > 0){
-                $s = $s . " AND stat IN ( ";
-                foreach($this->filters["STAT"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
-            }
-            if (count($this->filters["RUNE"]) > 0){
-                $s = $s . " AND (rune IN ( ";
-                foreach($this->filters["RUNE"] as $t){
-                    $s = $s . "'$t', ";
-                }
-                $s = $s . "'DUMMY0') ";
-                if (in_array('0', $this->filters["RUNE"])){
-                    // Include inmemorials
-                    $s .= " OR type in (3, 4)) ";
-                }
-                else{
-                    $s .= ") ";
-                }
-            }
-            if (count($this->filters["TYPE"]) == 1){
-                // Only one selectd, it's either gems or grindstones
-                if (in_array("GEM", $this->filters["TYPE"])){
-                    $s .= " AND type IN (1, 3, 5) "; // Gems.
-                }
-                else{
-                    $s .= " AND type IN (2, 4, 6) "; // Grindstones.
-                }
-            }
-            $s = $s . "
-              ORDER BY
-                type = 3 DESC,  -- Inmemorial Grindstone
-                type = 4 DESC,  -- Inmemorial Gem
-                rune,
-                type,
-                quality DESC,
-                stat
-            ";
-            /*if (count($this->filters["MAIN"]) > 0){
-                $s = $s . " AND main_stat IN ( ";
-                foreach($this->filters["MAIN"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
-            }
-            if (count($this->filters["ELEMENT"]) == 0 && count($this->filters["ARCHETYPE"]) == 0){
-                // No element/archetype conditions
-            }
-            elseif (count($this->filters["ELEMENT"]) > 0 && count($this->filters["ARCHETYPE"]) == 0){
-                // Only selected elements
-                $s = $s . " AND attribute IN ( ";
-                foreach($this->filters["ELEMENT"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
-            }
-            elseif (count($this->filters["ELEMENT"]) == 0 && count($this->filters["ARCHETYPE"]) > 0){
-                // Only selected types
-                $s = $s . " AND archetype IN ( ";
-                foreach($this->filters["ARCHETYPE"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
-            }
-            elseif (count($this->filters["ELEMENT"]) > 0 && count($this->filters["ARCHETYPE"]) > 0){
-                // Selected elements and selected types
-                $s = $s . " AND (archetype IN ( ";
-                foreach($this->filters["ARCHETYPE"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) OR attribute IN ( ";
-                foreach($this->filters["ELEMENT"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1)) ";
-            }
-            switch ($this->filters["ASSIGNED"]){
-                case 1:
-                    $s = $s . " AND assigned_to IS NOT NULL ";
-                    break;
-                case 2:
-                    $s = $s . " AND assigned_to IS NULL ";
-                    break;
-                case 3:
-                    $s = $s . " AND (assigned_to IS NULL OR assigned_to IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ")) ";
-                    break;
-                case 4:
-                    $s = $s . " AND assigned_to IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ") ";
-                    break;
-            }
-            $s = $s . " ORDER BY type, attribute, archetype, level DESC, original_quality DESC;";
-            */
-            return $s;
+    /**
+     * Retrieves the gems to show.
+     *
+     * @return Enchantment[] Selected gems. 
+     */
+    public function get_gems(){
+        return $this->gems;
+    }
+
+    /**
+     * Retrieves the grindstones to show.
+     *
+     * @return Enchantment[] Selected grindstones. 
+     */
+    public function get_grindstones(){
+        return $this->grindstones;
+    }
+    
+    /**
+     * Retrieves the enchantments to show, both gems and grindstones.
+     *
+     * @return Enchantment[] Selected enchantments.
+     */
+    public function get_enchantments(){
+        return $this->enchantments;
+    }
+
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes 
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+
+    /**
+     * Retrieves one filter.
+     * 
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
         }
     }
-?>
+
+}

+ 67 - 47
application/page/Error_Page.php

@@ -1,59 +1,79 @@
 <?php
+/**
+ * Error page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+
+/**
+ * Error page model.
+ *
+ * @category Page
+ */
+class Error_Page extends Page{
+
     /**
-     * Landing (login) page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var int Error code.
      */
-
+    private $code = 500;
+    
     /**
-     * Require dependent files if not present.
+     * @var string Error description.
      */
-    require_once(PATH::PAGE . "Page.php");
+    private $message = "";
 
     /**
-     * Error page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
+     * 
+     * @param int $code HTTP Error code. Optional, default 500.
      */
-    class Error_Page extends Page{
-
-        /**
-         * @var int Error code.
-         *
-         * HTTP status code.
-         */
-        public $code = 500;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         * 
-         * @param int code Error code. Optional.
-         */
-        public function __construct($code = null){
-            $this->view = PATH::VIEW . "error.php";
-            $this->title = "Error - SWDB";
+    public function __construct($code = null){
+        $this->view = PATH::VIEW . "error.php";
+        $this->title = "Error - SWDB";
 
-            if (null == $code || intval($code) < 200 || intval($code) > 599){
-                $code = 500;
-            }
-            switch(intval($code)){
-                case 400:
-                    $this->description = "Invalid request";
-                    break;
-                case 404:
-                    $this->description = "Not found";
-                    break;
-                case 500:
-                    $this->description = "Server error";
-                    break;
-                default:
-                    $this->description = "Unknown error";
-            }
-            $this->code = intval($code);
+        if (null == $code || intval($code) < 200 || intval($code) > 599){
+            $code = 500;
         }
+        switch(intval($code)){
+            case 400:
+                $this->message = "Invalid request";
+                break;
+            case 404:
+                $this->message = "Not found";
+                break;
+            case 500:
+                $this->message = "Server error";
+                break;
+            default:
+                $this->message = "Unknown error";
+        }
+        $this->code = intval($code);
     }
-?>
+
+    /**
+     * Retrieves the error code.
+     *
+     * @return int HTTP error code
+     */
+    public function get_code(){
+        return $this->code;
+    }
+    
+    /**
+     * Retrieves the error description.
+     *
+     * @return int HTTP error description.
+     */
+    public function get_message(){
+        return $this->message;
+    }
+
+}

+ 86 - 57
application/page/Guild_Page.php

@@ -1,70 +1,99 @@
 <?php
+/**
+ * Guild page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Guild.php");
+require_once(PATH::ENTITY . "Guild_Skill_Group.php");
+
+/**
+ * Guild page model.
+ *
+ * @category Page
+ */
+class Guild_Page extends Page{
+
     /**
-     * Guild page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var bool Indicates if the player is in a guild.
+     */
+    private $in_guild = false;
+    
+    /**
+     * @var Guild Player guild.
      */
+    private $guild;
 
     /**
-     * Require dependent files if not present.
+     * @var Guild_Skill_Group[] List of Guild skill groups.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Guild.php");
-    require_once(PATH::ENTITY . "Guild_Skill_Group.php");
+    private $skill_groups = [];
 
     /**
-     * Guild page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Guild_Page extends Page{
-
-        /**
-         * @var Guild Player guild.
-         */
-        public $guild;
-
-        /**
-         * @var Guild_Skill_Group[] List of Guild skill groups.
-         */
-        public $skill_groups = [];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "guild.php";
-            $s = "
-              SELECT id
-              FROM guild
-              WHERE id = (SELECT guild FROM guild_member WHERE member = '" . get_context()->get_player()->get_id() . "');
-            ";
-            $q = get_context()->get_db()->query($s);
-            $r = $q->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $guild_id =  $r["id"];
-                $this->guild = new Guild($guild_id);
-                $this->title = $this->guild->get_name() . " - SWDB";
-                $this->description = $this->guild->get_name() . " Guild details";
-                $s = "
-                  SELECT id
-                  FROM guild_skill_group
-                  ORDER BY id;
-                ";
-                $q = get_context()->get_db()->query($s);
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    array_push($this->skill_groups, new Guild_Skill_Group($r["id"]));
-                }
-            }
-            else{
-                $this->title = "Guild - SWDB";
-                $this->description = "No guild";
+    public function __construct(){
+        $this->view = PATH::VIEW . "guild.php";
+        $statement = get_context()->get_db()->prepare("
+          SELECT id
+          FROM guild
+          WHERE id = (SELECT guild FROM guild_member WHERE member = :player);
+        ");
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $result_set = $statement->execute();
+        $result = $result_set->fetchArray(SQLITE3_ASSOC);
+        if ($result){
+            $this->in_guild = true;
+            $this->guild = new Guild($result["id"]);
+            $this->title = $this->guild->get_name() . " - SWDB";
+            $this->description = $this->guild->get_name() . " Guild details";
+            $statement = get_context()->get_db()->prepare("SELECT id FROM guild_skill_group ORDER BY id;");
+            $skill_result_set = $statement->execute();
+            while ($result = $skill_result_set->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->skill_groups, new Guild_Skill_Group($result["id"]));
             }
-            $this->canonical = URL::BASE . "guild/";
         }
+        else{
+            $this->in_guild = false;
+            $this->title = "Guild - SWDB";
+            $this->description = "No guild";
+        }
+        $this->canonical = URL::BASE . "guild/";
     }
-?>
+    
+    /**
+     * Checks if the player is in a guild.
+     *
+     * @return bool True if the player is in a guild, false if not.
+     */
+    public function in_guild(){
+        return $this->in_guild;
+    }
+
+    /**
+     * Retrieves the guild.
+     *
+     * @return Guild Selected guild
+     */
+    public function get_guild(){
+        return $this->guild;
+    }
+
+    /**
+     * Retrieves the guild skil groups.
+     *
+     * @return Guild_Skill_Group[] Guild skill groups 
+     */
+    public function get_skill_groups(){
+        return $this->skill_groups;
+    }
+
+}

+ 26 - 34
application/page/Home_Page.php

@@ -1,41 +1,33 @@
 <?php
-    /**
-     * Home page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
-     */
+/**
+ * Home page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Player.php");
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Player.php");
+
+/**
+ * Home page model.
+ *
+ * @category Page
+ */
+class Home_Page extends Page{
 
     /**
-     * Home page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Home_Page extends Page{
-
-        /**
-         * @var Player Player instance.
-         */
-        public $player;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->player = get_context()->get_player();
-            $this->view = PATH::VIEW . "home.php";
-            $this->title = get_context()->get_player()->get_name() . " - SWDB";
-            $this->description = get_context()->get_player()->get_name() . " - Summoners War DataBase";
-            $this->canonical = URL::BASE;
-        }
+    public function __construct(){
+        $this->view = PATH::VIEW . "home.php";
+        $this->title = get_context()->get_player()->get_name() . " - SWDB";
+        $this->description = get_context()->get_player()->get_name() . " - Summoners War DataBase";
+        $this->canonical = URL::BASE;
     }
-?>
+}

+ 55 - 32
application/page/Landing_Page.php

@@ -1,43 +1,66 @@
 <?php
+/**
+ * Landing (login) page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+
+/**
+ * Landing (login) page model.
+ *
+ * @category Page
+ */
+class Landing_Page extends Page{
+
     /**
-     * Landing (login) page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var bool Indicates if the user has been redirected to this page after an error.
      */
-
+    private $is_error = false;
+    
     /**
-     * Require dependent files if not present.
+     * @var string Error message to show when login was unsuccesfull and
+     * the user is back in the login page
      */
-    require_once(PATH::PAGE . "Page.php");
+    private $error_message = "";
 
     /**
-     * Landing (login) page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Landing_Page extends Page{
-
-        /**
-         * @var string Error message to show when login was unsuccesfull and
-         * the user is back in the login page
-         */
-        public $error_message = "";
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "landing.php";
-            $this->title = "Login - SWDB";
-            $this->description = "Login to SWDB";
-            $this->canonical = URL::BASE . "landing/";
-            if (http_response_code() == 401){
-                $this->error_message = "Invalid credentials";
-            }
+    public function __construct(){
+        $this->view = PATH::VIEW . "landing.php";
+        $this->title = "Login - SWDB";
+        $this->description = "Login to SWDB";
+        $this->canonical = URL::BASE . "landing/";
+        if (http_response_code() == 401){
+            $this->is_error = true;
+            $this->error_message = "Invalid credentials";
         }
     }
-?>
+    
+    /**
+     * Checks if a error has redirected the user to shis page.
+     *
+     * @return bool True if there was an error, false otherwise
+     */
+    public function is_error(){
+        return $this->is_error;
+    }
+    
+    /**
+     * Retrieves the error message to show.
+     *
+     * @return string Error message.
+     */
+    public function get_error_message(){
+        return $this->error_message;
+    }
+    
+}

+ 138 - 71
application/page/Monster_Page.php

@@ -1,88 +1,155 @@
  <?php
+/**
+ * Monster details page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Monster.php");
+
+/**
+ * Monster details page model.
+ *
+ * @category Page
+ */
+class Monster_Page extends Page{
+
     /**
-     * Monster details page file.
+     * @var Monster[] Selected unit array.
      *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * [0]: Unawakened monster (null if default purple).
+     * [1]: Awakened monster (null if silver).
+     * [2]: Second awakened monster (null if unavailaable).
      */
+    private $monster = [];
 
     /**
-     * Require dependent files if not present.
+     * @var int[] IDs to other units of the family
+     * @todo Implement.
+     */
+    private $family = [];
+    
+    /**
+     * @var bool Indicates a silver monster.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Monster.php");
+    private $silver = false;
+    
+    /**
+     * @var bool Indicates a default purple (always awaken) monster.
+     */
+    private $purple = false;
+    
+    /**
+     * @var bool Indicates a monstes that can second awaken.
+     */
+    private $red = false;
 
     /**
-     * Monster details page model.
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
      *
-     * @category Page
+     * @param int $id Monster id. Can be any of the awakening stages
      */
-    class Monster_Page extends Page{
-
-        /**
-         * @var Monster[] Selected unit array.
-         *
-         * [0]: Unawakened monster (null if default purple).
-         * [1]: Awakened monster (null if silver).
-         * [2]: Second awakened monster (null if unavailaable).
-         */
-        public $monster = [];
-
-        /**
-         * @var int[] IDs to other units of the family
-         */
-        public $family = [];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         *
-         * @param int $id Monster id. Can be any of the awakening stages
-         */
-        public function __construct($id){
-            $this->view = PATH::VIEW . "monster.php";
-            $title = "";
-            $monster = new Monster($id);
-            if (! $monster->can_awaken()){
-                // Silver star monster.
-                $this->monster[0] = $monster;
-                $this->monster[1] = null;
-                $this->monster[2] = null;
-                $title = $this->monster[0]->element_name . " " . $this->monster[0]->name;
-            }
-            elseif ($monster->can_awaken() && $monster->get_awakens_to() == null && $monster->get_awakens_from() == null){
-                // Default purple (Rainbowmon or King Angelmon)
-                $this->monster[0] = null;
-                $this->monster[1] = $monster;
-                $this->monster[2] = null;
-                $title = $this->monster[1]->name;
-            }
-            elseif ($monster->can_awaken() && $monster->get_awakens_to() == null && $monster->get_awakens_from() != null){
-                // Normal monster, already awakened, no 2a.
-                $this->monster[0] = new Monster($monster->get_awakens_from());
-                $this->monster[1] = $monster;
+    public function __construct($id){
+        $this->view = PATH::VIEW . "monster.php";
+        $title = "";
+        $monster = new Monster($id);
+        if (! $monster->can_awaken()){
+            // Silver star monster.
+            $this->silver = true;
+            $this->monster[0] = $monster;
+            $this->monster[1] = null;
+            $this->monster[2] = null;
+            $title = $this->monster[0]->element_name . " " . $this->monster[0]->name;
+        }
+        elseif ($monster->can_awaken() && $monster->get_awakens_to() == null && $monster->get_awakens_from() == null){
+            // Default purple (Rainbowmon or King Angelmon)
+            $this->purple = true;
+            $this->monster[0] = null;
+            $this->monster[1] = $monster;
+            $this->monster[2] = null;
+            $title = $this->monster[1]->name;
+        }
+        elseif ($monster->can_awaken() && $monster->get_awakens_to() == null && $monster->get_awakens_from() != null){
+            // Normal monster, already awakened, no 2a.
+            $this->monster[0] = new Monster($monster->get_awakens_from());
+            $this->monster[1] = $monster;
+            $this->monster[2] = null;
+            $title = $this->monster[1]->get_name() . " - " .$this->monster[0]->get_element_name() . " " . $this->monster[0]->get_name();
+            $monster = $this->monster[0];
+        }
+        elseif ($monster->can_awaken() && $monster->get_awakens_to() != null && $monster->get_awakens_from() == null){
+            // Normal monster, not awakened, may have 2a.
+            $this->monster[0] = $monster;
+            $this->monster[1] = new Monster($this->monster[0]->get_awakens_to());
+            if ($this->monster[1]->get_awakens_to() == null){
                 $this->monster[2] = null;
-                $title = $this->monster[1]->get_name() . " - " .$this->monster[0]->get_element_name() . " " . $this->monster[0]->get_name();
-                $monster = $this->monster[0];
             }
-            elseif ($monster->can_awaken() && $monster->get_awakens_to() != null && $monster->get_awakens_from() == null){
-                // Normal monster, not awakened, may have 2a.
-                $this->monster[0] = $monster;
-                $this->monster[1] = new Monster($this->monster[0]->get_awakens_to());
-                if ($this->monster[1]->get_awakens_to() == null){
-                    $this->monster[2] = null;
-                }
-                else{
-                    $this->monster[2] = new Monster($this->monster[1]->get_awakens_to());
-                }
-                $title = $this->monster[1]->get_name() . " - " .$this->monster[0]->get_element_name() . " " . $this->monster[0]->get_name();
+            else{
+                $this->red = true;
+                $this->monster[2] = new Monster($this->monster[1]->get_awakens_to());
             }
-
-            $this->title = $title ." - SWDB";
-            $this->description = $title . " info - SWDB";
-            $this->canonical = URL::BASE . "monster_info/" . $id;
+            $title = $this->monster[1]->get_name() . " - " .$this->monster[0]->get_element_name() . " " . $this->monster[0]->get_name();
         }
+
+        $this->title = $title ." - SWDB";
+        $this->description = $title . " info - SWDB";
+        $this->canonical = URL::BASE . "monster_info/" . $id;
+    }
+    /**
+     * Retrieves the monster line to show.
+     * 
+     * Index [0]: Unawakened monster (null if default purple).
+     * Index [1]: Awakened monster (null if silver).
+     * Index [2]: Second awakened monster (null if unavailaable).
+     *
+     * @return Monster[] 
+     */
+    public function get_monsters(){
+        return $this->monster;
+    }
+
+    /**
+     * Retrieves the monster family.
+     *
+     * @return multitype:number 
+     */
+    public function get_family(){
+        return $this->family;
+    }
+
+    /**
+     * Checks if the monster is default silver (non awakeable).
+     *
+     * @return bool True for silver monsters, false otherwise.
+     */
+    public function is_silver(){
+        return $this->silver;
+    }
+
+    /**
+     * Checks if the monster is default purple (always awaken).
+     *
+     * @return bool True for purple monsters, false otherwise.
+     */
+    public function is_purple(){
+        return $this->purple;
     }
+
+    /**
+     * Checks if the monster can second awaken.
+     *
+     * @return bool True for monsters that can 2A, false otherwise.
+     */
+    public function can_2a(){
+        return $this->red;
+    }
+
+}
 ?>

+ 157 - 108
application/page/Monsters_Page.php

@@ -1,125 +1,174 @@
 <?php
+/**
+ * Monster list page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Monster.php");
+
+/**
+ * Monster list page model.
+ *
+ * @category Page
+ */
+class Monsters_Page extends Page{
+
     /**
-     * Catalog page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Monster[] List of monsters to show.
      */
+    private $monsters = [];
 
     /**
-     * Require dependent files if not present.
+     * @var int[] IDs of the monsters marked in the catalog.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Monster.php");
+    private $monsters_open = [];
 
     /**
-     * Catalog page model.
-     *
-     * @category Page
+     * @var mixed[] Default filter values.
      */
-    class Monsters_Page extends Page{
+    private $filters = [
+        "ELEMENT" => -1,
+        "NAME" => "",
+        "MIN_STARS" => 1,
+        "MAX_STARS" => 6,
+    ];
 
-        /**
-         * @var Monster[] List of monsters to show.
-         */
-        public $monsters = [];
-
-        /**
-         * @var int[] IDs of the monsters marked in the catalog.
-         */
-        public $monsters_open = [];
-
-        /**
-         * @var mixed[] Default filter values.
-         */
-        public $filters = [
-            "ELEMENT" => -1,
-            "NAME" => "",
-            "MIN_STARS" => 1,
-            "MAX_STARS" => 6,
-        ];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "monsters.php";
-            $this->parse_filters();
-            $s_mon = $this->build_query();
-            $q_mon = get_context()->get_db()->query($s_mon);
-            while ($r_mon = $q_mon->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->monsters, new Monster($r_mon["id"], false));
-            }
-            $s_open = "
-              SELECT monster
-              FROM collection
-              WHERE
-                player = " . get_context()->get_player()->get_id() . " AND
-                open = 1
-            ";
-            $q_open = get_context()->get_db()->query($s_open);
-            while ($r_open = $q_open->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->monsters_open, $r_open["monster"]);
-            }
-            $this->title = "Catalog - SWDB";
-            $this->description = "Catalog of all monsters";
-            $this->canonical = URL::BASE . "catalog/";
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     */
+    public function __construct(){
+        $this->view = PATH::VIEW . "monsters.php";
+        $this->parse_filters();
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->monsters, new Monster($result["id"], false));
+        }
+        
+        // Get open monsters
+        $statement = get_context()->get_db()->prepare("
+          SELECT monster FROM collection WHERE player = :player AND open = :open");
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":open", 1, SQLITE3_INTEGER);
+        $result_set = $statement->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->monsters_open, $result["monster"]);
         }
+        $this->title = "Catalog - SWDB";
+        $this->description = "Catalog of all monsters";
+        $this->canonical = URL::BASE . "catalog/";
+    }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            if (isset($_GET["element"]) && APPLICATION::valid_id("ELEMENT_ID", strtoupper($_GET["element"]))){
-                $this->filters["ELEMENT"] = $_GET["element"];
-            }
-            if (isset($_GET["name"]) && strlen($_GET["name"]) > 0){
-                $this->filters["NAME"] = SQLite3::escapeString($_GET["name"]);
-            }
-            if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) <= 5){
-                $this->filters["MIN_STARS"] = $_GET["min_stars"];
-            }
-            if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) <= 5){
-                $this->filters["MAX_STARS"] = $_GET["max_stars"];
-            }
-            return;
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        if (isset($_GET["element"]) && APPLICATION::valid_id("ELEMENT_ID", strtoupper($_GET["element"]))){
+            $this->filters["ELEMENT"] = $_GET["element"];
         }
+        if (isset($_GET["name"]) && strlen($_GET["name"]) > 0){
+            $this->filters["NAME"] = SQLite3::escapeString($_GET["name"]);
+        }
+        if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) <= 5){
+            $this->filters["MIN_STARS"] = $_GET["min_stars"];
+        }
+        if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) <= 5){
+            $this->filters["MAX_STARS"] = $_GET["max_stars"];
+        }
+        return;
+    }
 
-        /**
-         * Builds the query to the rune table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-                SELECT id
-                FROM monster
-                WHERE
-                  obtainable = 1 AND
-                  awakens_from IS NULL AND
-                  natural_stars >= " . $this->filters["MIN_STARS"] . " AND 
-                  natural_stars <= " . $this->filters["MAX_STARS"];
-            if(APPLICATION::valid_id("ELEMENT_ID", $this->filters["ELEMENT"])){
-                $s = $s . " AND element = " . $this->filters["ELEMENT"] . " ";
-            }
-            if ($this->filters["NAME"] != ""){
-                $s = $s . " AND upper(name) LIKE '%" . strtoupper($this->filters["NAME"]) . "%' ";
-            }
-            $s = $s . "
-                ORDER BY
-                  element = " . ELEMENT_ID::FIRE ." DESC,
-                  element = " . ELEMENT_ID::WATER ." DESC,
-                  element = " . ELEMENT_ID::WIND ." DESC,
-                  element = " . ELEMENT_ID::LIGHT ." DESC,
-                  element = " . ELEMENT_ID::DARK ." DESC,
-                  natural_stars;
-            ";
-            return $s;
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        // Common items
+        $query = "
+            SELECT id
+            FROM monster
+            WHERE
+              obtainable = 1 AND
+              awakens_from IS NULL AND
+              natural_stars BETWEEN :min_stars AND :max_stars
+        ";
+        if(APPLICATION::valid_id("ELEMENT_ID", $this->filters["ELEMENT"])){
+            $query .= " AND element = :element ";
+        }
+        if ($this->filters["NAME"] != ""){
+            $query .= " AND upper(name) LIKE upper(:name) " ;
         }
+        $query .= "
+            ORDER BY
+              element = :fire DESC,
+              element = :water DESC,
+              element = :wind DESC,
+              element = :light DESC,
+              element = :dark DESC,
+              natural_stars;
+        ";
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":min_stars", $this->filters["MIN_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_stars", $this->filters["MAX_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":element", $this->filters["ELEMENT"], SQLITE3_INTEGER);
+        $statement->bindValue(":name", "%" . $this->filters["NAME"] . "%", SQLITE3_TEXT);
+        $statement->bindValue(":fire", ELEMENT_ID::FIRE, SQLITE3_INTEGER);
+        $statement->bindValue(":water", ELEMENT_ID::WATER, SQLITE3_INTEGER);
+        $statement->bindValue(":wind", ELEMENT_ID::WIND, SQLITE3_INTEGER);
+        $statement->bindValue(":light", ELEMENT_ID::LIGHT, SQLITE3_INTEGER);
+        $statement->bindValue(":dark", ELEMENT_ID::DARK, SQLITE3_INTEGER);
+        return $statement;
+    }
+    /**
+     * Retrieves the monsters to display
+     *
+     * @return Monster[] Selected monsters. 
+     */
+    public function get_monsters(){
+        return $this->monsters;
+    }
+    
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes
+     */
+    public function get_filters(){
+        return $this->filters;
     }
+    
+    /**
+     * Retrieves one filter.
+     *
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
+        }
+    }
+    
+    public function is_open($id){
+        if (in_array($id, $this->monsters_open)){
+            return true;
+        }
+        else{
+            return false;
+        }
+    }
+
+}
 ?>

+ 48 - 59
application/page/Optimizer_Page.php

@@ -1,69 +1,58 @@
  <?php
-    /**
-     * Optimizer team list page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
-     */
+/**
+ * Optimizer team list page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Team.php");
+
+/**
+ * Optimizer team list page model.
+ *
+ * @category Page
+ */
+class Optimizer_Page extends Page{
 
     /**
-     * Require dependent files if not present.
+     * @var Team[] Teams to show.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Team.php");
+    private $teams = [];
 
     /**
-     * Optimizer team list page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Optimizer_Page extends Page{
-
-        /**
-         * @Team[] Teams to show.
-         */
-        public $teams = [];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "optimizer.php";
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->teams, new Team($r["id"]));
-            }
-            $s = "
-              SELECT id
-              FROM unit
-              WHERE player = '" . get_context()->get_player()->get_id() . "';
-            ";
-            $this->title = "Optimizer - SWDB";
-            $this->description = "Optimizer";
-            $this->canonical = URL::BASE . "optimizer/";
+    public function __construct(){
+        
+        $this->view = PATH::VIEW . "optimizer.php";
+        $this->title = "Optimizer - SWDB";
+        $this->description = "Optimizer";
+        $this->canonical = URL::BASE . "optimizer/";
+        
+        // Get teams
+        $statement = get_context()->get_db()->prepare("
+          SELECT id FROM team WHERE player = :player ORDER BY area_type, area");
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $result_set = $statement->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->teams, new Team($result["id"]));
         }
-
-        /**
-         * Builds the query to the rune table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-              SELECT id
-              FROM team
-              WHERE player = '" . get_context()->get_player()->get_id() . "'
-              ORDER BY
-                area_type,
-                area
-            ";
-            return $s;
-        }
-
+        
+    }
+    /**
+     * Retrieves the player teams.
+     *
+     * @return Team[] Player teams.
+     */
+    public function get_teams(){
+        return $this->teams;
     }
-?>
+
+}

+ 40 - 32
application/page/Optimizer_Unit_Page.php

@@ -1,43 +1,51 @@
  <?php
+/**
+ * Optimizer unit page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Unit.php");
+
+/**
+ * Optimizer team list page model.
+ *
+ * @category Page
+ */
+class Optimizer_Unit_Page extends Page{
+
     /**
-     * Optimizer unit page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Unit The unit to optimize.
      */
+    private $unit;
 
     /**
-     * Require dependent files if not present.
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     *
+     * @param string $id Selected unit id.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Unit.php");
-
+    public function __construct($id){
+        $this->view = PATH::VIEW . "optimizer_unit.php";
+        $this->unit = new Unit($id);
+        $this->title = "Optimize " . $this->unit->get_title() . " - SWDB";
+        $this->description = "Optimize " . $this->unit->get_title();
+        $this->canonical = URL::BASE . "optimizer/$id";
+    }
     /**
-     * Optimizer team list page model.
+     * Retrieves the unit to optimize.
      *
-     * @category Page
+     * @return Unit Unit to optimize.
      */
-    class Optimizer_Unit_Page extends Page{
-
-        /**
-         * @var Unit The unit to optimize.
-         */
-        public $unit;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         *
-         * @param string $id Selected unit id
-         */
-        public function __construct($id){
-            $this->view = PATH::VIEW . "optimizer_unit.php";
-            $this->unit = new Unit($id);
-            $this->title = "Optimize " . $this->unit->get_title() . " - SWDB";
-            $this->description = "Optimize " . $this->unit->get_title();
-            $this->canonical = URL::BASE . "optimizer/$id";
-        }
+    public function get_unit(){
+        return $this->unit;
     }
+
+}
 ?>

+ 131 - 65
application/page/Page.php

@@ -1,77 +1,143 @@
 <?php
+/**
+ * Page superclass file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+/**
+ * Page superclass.
+ *
+ * Every visitable page type must inherit from this one.
+ *
+ * @category Page
+ */
+abstract class Page{
+
+    /**
+     * @var string Path to the view associated with the page.
+     */
+    protected $view;
+
+    /**
+     * @var string Title of the page, in the defined language.
+     */
+    protected $title;
+
+    /**
+     * @var string Site name.
+     */
+    protected $name;
+
+    /**
+     * @var string Page description, in the defined language.
+     */
+    protected $description;
+
+    /**
+     * @var string URL to the site favicon.
+     */
+    protected $favicon;
+
+    /**
+     * @var string URL to the page icon or main image.
+     */
+    protected $icon;
+
+    /**
+     * @var string Canonical URL.
+     */
+    protected $canonical;
+
     /**
-     * Page superclass file.
+     * @var string Autjhor URL.
+     */
+    protected $author;
+
+    /**
+     * Constructor.
+     */
+    public function __construct(){
+        $this->favicon = URL::IMG["LOGO"] . "sw.png";
+        $this->icon = URL::IMG["LOGO"] . "sw.png";
+        $this->name = "SWDB";
+        $this->author = URL::BASE;
+    }
+    /**
+     * Retrieves the page view file.
      *
-     * Provides a class with all the properties and methods to display the page.
+     * @return string Path to the view file.
+     */
+    public function get_view(){
+        return $this->view;
+    }
+
+    /**
+     * Retrieves the page title.
      *
-     * @category Page
+     * @return string Page title.
      */
+    public function get_title(){
+        return $this->title;
+    }
 
     /**
-     * Page superclass.
+     * Retrieves the site name.
      *
-     * Every visitable page type must inherit from this one.
+     * @return string Site name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
+
+    /**
+     * Retrieves the page description
      *
-     * @category Page
-     */
-    abstract class Page{
-
-        /**
-         * @var string Path to the view associated with the page.
-         */
-        public $view;
-
-        /**
-         * @var string Title of the page, in the defined language.
-         */
-        public $title;
-
-        /**
-         * @var string Site name.
-         */
-        public $name;
-
-        /**
-         * @var string Page description, in the defined language.
-         */
-        public $description;
-
-        /**
-         * @var string URL to the site favicon.
-         */
-        public $favicon;
-
-        /**
-         * @var string URL to the page icon or main image.
-         */
-        public $icon;
-
-        /**
-         * @var string Canonical URL.
-         */
-        public $canonical;
-
-        /**
-         * @var string Autjhor URL.
-         */
-        public $author;
-
-        /**
-         * @var mixed[] The filters the page can handle.
-         *
-         * @see FILTER::CATALOG
-         */
-        public $filters;
-
-        /**
-         * Constructor.
-         */
-        public function __construct(){
-            $this->favicon = URL::IMG["LOGO"] . "sw.png";
-            $this->icon = URL::IMG["LOGO"] . "sw.png";
-            $this->name = "SWDB";
-            $this->author = URL::BASE;
-        }
+     * @return string Page description.
+     */
+    public function get_description(){
+        return $this->description;
+    }
 
+    /**
+     * Retrieves the URL to the favicon.
+     *
+     * @return string Favicon URL.
+     */
+    public function get_favicon(){
+        return $this->favicon;
     }
+
+    /**
+     * Retrieves the URL to the thumbnail image.
+     *
+     * @return string Thmbnail icon URL.
+     */
+    public function get_icon(){
+        return $this->icon;
+    }
+
+    /**
+     * Retrieves the canonical URL to the page.
+     *
+     * @return string Canonical URL.
+     */
+    public function get_canonical(){
+        return $this->canonical;
+    }
+
+    /**
+     * Retrieves the author URL (site main URL).
+     *
+     * @return string AUthor URL.
+     */
+    public function get_author(){
+        return $this->author;
+    }
+
+}
 ?>

+ 26 - 56
application/page/Profile_Page.php

@@ -1,64 +1,34 @@
  <?php
-    /**
-     * User profile page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
-     */
+/**
+ * User profile page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::PAGE . "Page.php");
+require_once(PATH::PAGE . "Page.php");
+
+/**
+ * User profile page model.
+ *
+ * @category Page
+ */
+class Profile_Page extends Page{
 
     /**
-     * User profile page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Profile_Page extends Page{
-
-        /**
-         * @var string Player name.
-         */
-        public $name;
-
-        /**
-         * @var string Player email.
-         */
-        public $mail;
-
-        /**
-         * @var string Player API key.
-         */
-        public $api_key;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "profile.php";
-            $s = "
-              SELECT
-                name,
-                mail,
-                api_key
-              FROM user
-              WHERE id = '" . get_context()->get_user()->id . "';
-            ";
-            $q = get_context()->get_db()->query($s);
-            if ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $this->name = $r["name"];
-                $this->mail = $r["mail"];
-                $this->api_key = $r["api_key"];
-            }
-            $this->title = $this->name ." - SWDB";
-            $this->description = $this->name . " user profile";
-            $this->canonical = URL::BASE . "profile/";
-        }
-
+    public function __construct(){
+        $this->view = PATH::VIEW . "profile.php";
+        $this->title = get_context()->get_user()->get_name() ." - SWDB";
+        $this->description = get_context()->get_user()->get_name() . " user profile";
+        $this->canonical = URL::BASE . "profile/";
     }
+
+}
 ?>

+ 27 - 34
application/page/Report_Page.php

@@ -1,42 +1,35 @@
  <?php
-    /**
-     * Main reports page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
-     */
+/**
+ * Main reports page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::PAGE . "Page.php");
+require_once(PATH::PAGE . "Page.php");
+
+/**
+ * Main reports page model.
+ *
+ * @category Page
+ */
+class Report_Page extends Page{
 
     /**
-     * Main reports page model.
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
      *
-     * @category Page
      */
-    class Report_Page extends Page{
-
-        /**
-         * @var Filter[] Custom filters for thie rune upgrade form.
-         */
-        public $custom_filters_runeupgrade = [];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         *
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "report.php";
+    public function __construct(){
+        $this->view = PATH::VIEW . "report.php";
 
-            $this->title = "Reports - SWDB";
-            $this->description = "Usefull reports for summoners";
-            $this->canonical = URL::BASE . "report";
-            $this->title = "Reports - SWDB";
-        }
+        $this->title = "Reports - SWDB";
+        $this->description = "Usefull reports for summoners";
+        $this->canonical = URL::BASE . "report";
+        $this->title = "Reports - SWDB";
     }
-?>
+}

+ 393 - 373
application/page/Report_Rune_Enchantment_Page.php

@@ -1,408 +1,428 @@
  <?php
+/**
+ * Upgradeable runes report page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Unit.php");
+require_once(PATH::ENTITY . "Rune.php");
+require_once(PATH::ENTITY . "Enchantment.php");
+
+/**
+ * Upgradeable runes report page model.
+ *
+ * @category Page
+ * @todo Some filters are not implemented (enchantment type, teams...)
+ */
+class Report_Rune_Enchantment_Page extends Page{
+
     /**
-     * Upgradeable runes report page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var mixed[] List of available upgrades.
      */
+    private $upgrades = [];
 
     /**
-     * Require dependent files if not present.
+     * @var mixed[] Default filter values.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Unit.php");
-    require_once(PATH::ENTITY . "Rune.php");
-    require_once(PATH::ENTITY . "Enchantment.php");
+    private $filters = [
+        "MONSTER_NAME" => "",
+        "MONSTER_MIN_STARS" => 5,
+        "MONSTER_MAX_STARS" => 6,
+        "MONSTER_IN_STORAGE" => false,
+        "TEAM" => false,
+        "RUNE_MIN_STARS" => 5,
+        "RUNE_MAX_STARS" => 6,
+        "RUNE_MIN_LEVEL" => 0,
+        "RUNE_MAX_LEVEL" => 15,
+        "RUNE_MIN_QUALITY" => QUALITY_ID::HERO,
+        "RUNE_MAX_QUALITY" => QUALITY_ID::LEGEND,
+        "RUNE_MIN_ORIGINAL_QUALITY" => QUALITY_ID::HERO,
+        "RUNE_MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
+        "RUNE_MIN_EFFICIENCY" => 0,
+        "RUNE_MAX_EFFICIENCY" => 100,
+        "RUNE_MIN_MAX_EFFICIENCY" => 0,
+        "RUNE_MAX_MAX_EFFICIENCY" => 100,
+        "RUNE_SLOT" => [],
+        "GRIND" => 1,
+        "GRIND_MIN_QUALITY" => QUALITY_ID::RARE,
+        "GRIND_STAT" => [
+            RUNE_STAT_ID::HP_P,
+            RUNE_STAT_ID::ATK_P,
+            RUNE_STAT_ID::DEF_P,
+            RUNE_STAT_ID::SPD,
+            RUNE_STAT_ID::CRD,
+            RUNE_STAT_ID::CRR,
+            RUNE_STAT_ID::ACC
+        ],
+        "GEM" => 1,
+        "GEM_MIN_QUALITY" => QUALITY_ID::RARE,
+        "GEM_STAT_FROM" => [
+            RUNE_STAT_ID::HP,
+            RUNE_STAT_ID::ATK,
+            RUNE_STAT_ID::DEF,
+            RUNE_STAT_ID::RES
+        ],
+        "GEM_STAT_TO" => [
+            RUNE_STAT_ID::HP_P,
+            RUNE_STAT_ID::ATK_P,
+            RUNE_STAT_ID::DEF_P,
+            RUNE_STAT_ID::SPD,
+            RUNE_STAT_ID::CRD,
+            RUNE_STAT_ID::CRR,
+            RUNE_STAT_ID::ACC
+        ]
+    ];
 
     /**
-     * Upgradeable runes report page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Report_Rune_Enchantment_Page extends Page{
-
-        /**
-         * @var mixed[] List of available upgrades.
-         *
-         * Can be described as:
-         * $upgrades = [
-         *   [
-         *     unit (Unit),
-         *     upgrade = [
-         *       [
-         *         rune (Rune),
-         *         enchant = [(Enchantment)]
-         *       ]
-         *     ]
-         *   ]
-         * ]
-         */
-        public $upgrades = [];
-
-        /**
-         * @var mixed[] Default filter values.
-         */
-        public $filters = [
-            "MONSTER_NAME" => "",
-            "MONSTER_MIN_STARS" => 5,
-            "MONSTER_MAX_STARS" => 6,
-            "MONSTER_IN_STORAGE" => false,
-            "TEAM" => false,
-            "RUNE_MIN_STARS" => 5,
-            "RUNE_MAX_STARS" => 6,
-            "RUNE_MIN_LEVEL" => 0,
-            "RUNE_MAX_LEVEL" => 15,
-            "RUNE_MIN_QUALITY" => QUALITY_ID::HERO,
-            "RUNE_MAX_QUALITY" => QUALITY_ID::LEGEND,
-            "RUNE_MIN_ORIGINAL_QUALITY" => QUALITY_ID::HERO,
-            "RUNE_MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
-            "RUNE_MIN_EFFICIENCY" => 0,
-            "RUNE_MAX_EFFICIENCY" => 100,
-            "RUNE_MIN_MAX_EFFICIENCY" => 0,
-            "RUNE_MAX_MAX_EFFICIENCY" => 100,
-            "RUNE_SLOT" => [],
-            "GRIND" => 1,
-            "GRIND_MIN_QUALITY" => QUALITY_ID::RARE,
-            "GRIND_STAT" => [
-                RUNE_STAT_ID::HP_P,
-                RUNE_STAT_ID::ATK_P,
-                RUNE_STAT_ID::DEF_P,
-                RUNE_STAT_ID::SPD,
-                RUNE_STAT_ID::CRD,
-                RUNE_STAT_ID::CRR,
-                RUNE_STAT_ID::ACC
-            ],
-            "GEM" => 1,
-            "GEM_MIN_QUALITY" => QUALITY_ID::RARE,
-            "GEM_STAT_FROM" => [
-                RUNE_STAT_ID::HP,
-                RUNE_STAT_ID::ATK,
-                RUNE_STAT_ID::DEF,
-                RUNE_STAT_ID::RES
-            ],
-            "GEM_STAT_TO" => [
-                RUNE_STAT_ID::HP_P,
-                RUNE_STAT_ID::ATK_P,
-                RUNE_STAT_ID::DEF_P,
-                RUNE_STAT_ID::SPD,
-                RUNE_STAT_ID::CRD,
-                RUNE_STAT_ID::CRR,
-                RUNE_STAT_ID::ACC
-            ]
-        ];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "report_rune_enchantment.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            $prev_monster = "";
-            $prev_rune = "";
-            $upgrade = null;
-            $rupgrade = null;
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                if ($r["unit"] != $prev_monster){
-                    if ($prev_rune != ""){
-                        array_push($upgrade["upgrade"], $rupgrade);
-                    }
-                    if ($prev_monster != ""){
-                        array_push($this->upgrades, $upgrade);
-                    }
-                    $prev_monster = $r["unit"];
-                    $prev_rune = "";
-                    $upgrade = [
-                        "unit" => new Unit($r["unit"]),
-                        "upgrade" => [],
-                    ];
-                    $rupgrade = [
-                        "rune" => new Rune($r["rune"]),
-                        "enchantment" => [],
-                    ];
+    public function __construct(){
+        $this->view = PATH::VIEW . "report_rune_enchantment.php";
+        $prev_monster = "";
+        $prev_rune = "";
+        $upgrade = null;
+        $rupgrade = null;
+        $this->parse_filters();
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            if ($result["unit"] != $prev_monster){
+                if ($prev_rune != ""){
+                    array_push($upgrade["upgrade"], $rupgrade);
+                }
+                if ($prev_monster != ""){
+                    array_push($this->upgrades, $upgrade);
                 }
-                if ($r["rune"] != $prev_rune){
-                    if ($prev_rune != ""){
-                        array_push($upgrade["upgrade"], $rupgrade);
-                    }
-                    $prev_rune = $r["rune"];
-                    $rupgrade = [
-                        "rune" => new Rune($r["rune"]),
-                        "enchantment" => [],
-                    ];
+                $prev_monster = $result["unit"];
+                $prev_rune = "";
+                $upgrade = [
+                    "unit" => new Unit($result["unit"]),
+                    "upgrade" => [],
+                ];
+                $rupgrade = [
+                    "rune" => new Rune($result["rune"]),
+                    "enchantment" => [],
+                ];
+            }
+            if ($result["rune"] != $prev_rune){
+                if ($prev_rune != ""){
+                    array_push($upgrade["upgrade"], $rupgrade);
                 }
-                $enchantment= new Enchantment($r["enchantment"]);
-                array_push($rupgrade["enchantment"], $enchantment);
+                $prev_rune = $result["rune"];
+                $rupgrade = [
+                    "rune" => new Rune($result["rune"]),
+                    "enchantment" => [],
+                ];
             }
-            // Last entries
-            array_push($upgrade["upgrade"], $rupgrade);
-            array_push($this->upgrades, $upgrade);
-            $this->title = "Rune enchantment - SWDB";
-            $this->description = "Find runes that can be upgraded via enchantments.";
-            $this->canonical = URL::BASE . "report/rune_enchantment/";
+            $enchantment= new Enchantment($result["enchantment"]);
+            array_push($rupgrade["enchantment"], $enchantment);
         }
+        // Last entries
+        array_push($upgrade["upgrade"], $rupgrade);
+        array_push($this->upgrades, $upgrade);
+        $this->title = "Rune enchantment - SWDB";
+        $this->description = "Find runes that can be upgraded via enchantments.";
+        $this->canonical = URL::BASE . "report/rune_enchantment/";
+    }
 
-        /**
-         * Parses the filters passed in the request and sets $filters.
-         * Filters must be in $_GET, nd the available ones are max_stars (1-6),
-         * min_stars (1-6) and in_storage (on/off).
-         */
-        private function parse_filters(){
-            // Monster
-            if (isset($_GET["monster_min_stars"]) && intval($_GET["monster_min_stars"]) > 0 && intval($_GET["monster_min_stars"]) < 7){
-                $this->filters["MONSTER_MIN_STARS"] = $_GET["monster_min_stars"];
-            }
-            if (isset($_GET["monster_max_stars"]) && intval($_GET["monster_max_stars"]) > 0 && intval($_GET["monster_max_stars"]) < 7){
-                $this->filters["MONSTER_MAX_STARS"] = $_GET["monster_max_stars"];
-            }
-            if (isset($_GET["monster_in_storage"]) && $_GET["monster_in_storage"] == "on"){
-                $this->filters["MONSTER_IN_STORAGE"] = true;
-            }
-            else{
-                $this->filters["MONSTER_IN_STORAGE"] = false;
-            }
-            if (isset($_GET["monster_name"]) && strlen($_GET["monster_name"]) > 0){
-                $this->filters["MONSTER_NAME"] = SQLite3::escapeString($_GET["monster_name"]);
-            }
-            // Runes
-            if (isset($_GET["rune_min_stars"]) && intval($_GET["rune_min_stars"]) > 0 && intval($_GET["rune_min_stars"]) < 7){
-                $this->filters["RUNE_MIN_STARS"] = $_GET["rune_min_stars"];
-            }
-            if (isset($_GET["rune_max_stars"]) && intval($_GET["rune_max_stars"]) > 0 && intval($_GET["rune_max_stars"]) < 7){
-                $this->filters["RUNE_MAX_STARS"] = $_GET["rune_max_stars"];
-            }
-            if (isset($_GET["rune_min_level"]) && intval($_GET["rune_min_level"]) >= 0 && intval($_GET["rune_min_level"]) <= 15){
-                $this->filters["RUNE_MIN_LEVEL"] = $_GET["rune_min_level"];
-            }
-            if (isset($_GET["rune_max_level"]) && intval($_GET["rune_max_level"]) >= 0 && intval($_GET["rune_max_level"]) <= 15){
-                $this->filters["RUNE_MAX_LEVEL"] = $_GET["rune_max_level"];
-            }
-            if (isset($_GET["rune_min_quality"]) && intval($_GET["rune_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_min_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["RUNE_MIN_QUALITY"] = $_GET["rune_min_quality"];
-            }
-            if (isset($_GET["rune_max_quality"]) && intval($_GET["rune_max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_max_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["RUNE_MAX_QUALITY"] = $_GET["rune_max_quality"];
-            }
-            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){
-                $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] = $_GET["rune_min_original_quality"];
-            }
-            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){
-                $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] = $_GET["rune_max_original_quality"];
-            }
-            if (isset($_GET["rune_min_efficiency"]) && intval($_GET["rune_min_efficiency"]) >= 0 && intval($_GET["rune_min_efficiency"]) <= 100){
-                $this->filters["RUNE_MIN_EFFICIENCY"] = $_GET["rune_min_efficiency"];
-            }
-            if (isset($_GET["rune_max_efficiency"]) && intval($_GET["rune_max_efficiency"]) >= 0 && intval($_GET["rune_max_efficiency"]) <= 100){
-                $this->filters["RUNE_MAX_EFFICIENCY"] = $_GET["rune_max_efficiency"];
-            }
-            if (isset($_GET["rune_min_max_efficiency"]) && intval($_GET["rune_min_max_efficiency"]) >= 0 && intval($_GET["rune_min_max_efficiency"]) <= 100){
-                $this->filters["RUNE_MIN_MAX_EFFICIENCY"] = $_GET["rune_min_max_efficiency"];
-            }
-            if (isset($_GET["rune_max_max_efficiency"]) && intval($_GET["rune_max_max_efficiency"]) >= 0 && intval($_GET["rune_max_max_efficiency"]) <= 100){
-                $this->filters["RUNE_MAX_MAX_EFFICIENCY"] = $_GET["rune_max_max_efficiency"];
-            }
-            if (isset($_GET["rune_slot"])){
-                $slots = $_GET["rune_slot"];
-                foreach ($slots as $slot){
-                    if (intval($slot) >= 1 && intval($slot) < 7){
-                        array_push($this->filters["RUNE_SLOT"], intval($slot));
-                    }
+    /**
+     * Parses the filters passed in the request and sets $filters.
+     * Filters must be in $_GET, nd the available ones are max_stars (1-6),
+     * min_stars (1-6) and in_storage (on/off).
+     */
+    private function parse_filters(){
+        // Monster
+        if (isset($_GET["monster_min_stars"]) && intval($_GET["monster_min_stars"]) > 0 && intval($_GET["monster_min_stars"]) < 7){
+            $this->filters["MONSTER_MIN_STARS"] = $_GET["monster_min_stars"];
+        }
+        if (isset($_GET["monster_max_stars"]) && intval($_GET["monster_max_stars"]) > 0 && intval($_GET["monster_max_stars"]) < 7){
+            $this->filters["MONSTER_MAX_STARS"] = $_GET["monster_max_stars"];
+        }
+        if (isset($_GET["monster_in_storage"]) && $_GET["monster_in_storage"] == "on"){
+            $this->filters["MONSTER_IN_STORAGE"] = true;
+        }
+        else{
+            $this->filters["MONSTER_IN_STORAGE"] = false;
+        }
+        if (isset($_GET["monster_name"]) && strlen($_GET["monster_name"]) > 0){
+            $this->filters["MONSTER_NAME"] = SQLite3::escapeString($_GET["monster_name"]);
+        }
+        // Runes
+        if (isset($_GET["rune_min_stars"]) && intval($_GET["rune_min_stars"]) > 0 && intval($_GET["rune_min_stars"]) < 7){
+            $this->filters["RUNE_MIN_STARS"] = $_GET["rune_min_stars"];
+        }
+        if (isset($_GET["rune_max_stars"]) && intval($_GET["rune_max_stars"]) > 0 && intval($_GET["rune_max_stars"]) < 7){
+            $this->filters["RUNE_MAX_STARS"] = $_GET["rune_max_stars"];
+        }
+        if (isset($_GET["rune_min_level"]) && intval($_GET["rune_min_level"]) >= 0 && intval($_GET["rune_min_level"]) <= 15){
+            $this->filters["RUNE_MIN_LEVEL"] = $_GET["rune_min_level"];
+        }
+        if (isset($_GET["rune_max_level"]) && intval($_GET["rune_max_level"]) >= 0 && intval($_GET["rune_max_level"]) <= 15){
+            $this->filters["RUNE_MAX_LEVEL"] = $_GET["rune_max_level"];
+        }
+        if (isset($_GET["rune_min_quality"]) && intval($_GET["rune_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_min_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["RUNE_MIN_QUALITY"] = $_GET["rune_min_quality"];
+        }
+        if (isset($_GET["rune_max_quality"]) && intval($_GET["rune_max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_max_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["RUNE_MAX_QUALITY"] = $_GET["rune_max_quality"];
+        }
+        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){
+            $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] = $_GET["rune_min_original_quality"];
+        }
+        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){
+            $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] = $_GET["rune_max_original_quality"];
+        }
+        if (isset($_GET["rune_min_efficiency"]) && intval($_GET["rune_min_efficiency"]) >= 0 && intval($_GET["rune_min_efficiency"]) <= 100){
+            $this->filters["RUNE_MIN_EFFICIENCY"] = $_GET["rune_min_efficiency"];
+        }
+        if (isset($_GET["rune_max_efficiency"]) && intval($_GET["rune_max_efficiency"]) >= 0 && intval($_GET["rune_max_efficiency"]) <= 100){
+            $this->filters["RUNE_MAX_EFFICIENCY"] = $_GET["rune_max_efficiency"];
+        }
+        if (isset($_GET["rune_min_max_efficiency"]) && intval($_GET["rune_min_max_efficiency"]) >= 0 && intval($_GET["rune_min_max_efficiency"]) <= 100){
+            $this->filters["RUNE_MIN_MAX_EFFICIENCY"] = $_GET["rune_min_max_efficiency"];
+        }
+        if (isset($_GET["rune_max_max_efficiency"]) && intval($_GET["rune_max_max_efficiency"]) >= 0 && intval($_GET["rune_max_max_efficiency"]) <= 100){
+            $this->filters["RUNE_MAX_MAX_EFFICIENCY"] = $_GET["rune_max_max_efficiency"];
+        }
+        if (isset($_GET["rune_slot"])){
+            $slots = $_GET["rune_slot"];
+            foreach ($slots as $slot){
+                if (intval($slot) >= 1 && intval($slot) < 7){
+                    array_push($this->filters["RUNE_SLOT"], intval($slot));
                 }
             }
-            // Grindstones
-            if (isset($_GET["grind_min_quality"]) && intval($_GET["grind_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["grind_min_quality"]) < QUALITY_ID::LEGEND){
-                $this->filters["GRIND_MIN_QUALITY"] = $_GET["grind_min_quality"];
-            }
-            if (isset($_GET["grind_stat"])){
-                $stats = $_GET["grind_stat"];
-                $this->filters["GRIND_STAT"] = [];
-                foreach ($stats as $stat){
-                    array_push($this->filters["GRIND_STAT"], intval($stat));
-                }
+        }
+        // Grindstones
+        if (isset($_GET["grind_min_quality"]) && intval($_GET["grind_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["grind_min_quality"]) < QUALITY_ID::LEGEND){
+            $this->filters["GRIND_MIN_QUALITY"] = $_GET["grind_min_quality"];
+        }
+        if (isset($_GET["grind_stat"])){
+            $stats = $_GET["grind_stat"];
+            $this->filters["GRIND_STAT"] = [];
+            foreach ($stats as $stat){
+                array_push($this->filters["GRIND_STAT"], intval($stat));
             }
-            if (isset($_GET["gem_stat_from"])){
-                $stats = $_GET["gem_stat_from"];
-                $this->filters["GEM_STAT_FROM"] = [];
-                foreach ($stats as $stat){
-                    array_push($this->filters["GEM_STAT_FROM"], intval($stat));
-                }
+        }
+        if (isset($_GET["gem_stat_from"])){
+            $stats = $_GET["gem_stat_from"];
+            $this->filters["GEM_STAT_FROM"] = [];
+            foreach ($stats as $stat){
+                array_push($this->filters["GEM_STAT_FROM"], intval($stat));
             }
-            if (isset($_GET["gem_stat_to"])){
-                $stats = $_GET["gem_stat_to"];
-                $this->filters["GEM_STAT_TO"] = [];
-                foreach ($stats as $stat){
-                    array_push($this->filters["GEM_STAT_TO"], intval($stat));
-                }
+        }
+        if (isset($_GET["gem_stat_to"])){
+            $stats = $_GET["gem_stat_to"];
+            $this->filters["GEM_STAT_TO"] = [];
+            foreach ($stats as $stat){
+                array_push($this->filters["GEM_STAT_TO"], intval($stat));
             }
-            return;
         }
+        return;
+    }
 
-        /**
-         * Builds the query for the page, using the providded or default filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-              SELECT DISTINCT
-                unit.id AS unit,
-                rune.id AS rune,
-                enchantment.id AS enchantment
-              FROM
-                unit,
-                monster,
-                rune,
-                unit_rune,
-                enchantment,
-                enchantment_type
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        // Common items
+        $query = "
+          SELECT DISTINCT
+            unit.id AS unit,
+            rune.id AS rune,
+            enchantment.id AS enchantment
+          FROM
+            unit,
+            monster,
+            rune,
+            unit_rune,
+            enchantment,
+            enchantment_type
+          WHERE
+            unit.player = :player AND
+            rune.player = unit.player AND
+            enchantment.player = unit.player AND
+            unit.id = unit_rune.unit AND
+            rune.id = unit_rune.rune AND
+            unit_rune.rta = :rta AND
+            unit.monster = monster.id AND
+            enchantment.type = enchantment_type.id AND
+            -- RUNE FILTERS
+            rune.stars BETWEEN :rune_min_stars AND :rune_max_stars AND
+            rune.quality BETWEEN :rune_min_quality AND :rune_max_quality AND
+            rune.original_quality BETWEEN :rune_min_original_quality AND :rune_max_original_quality AND
+            rune.level BETWEEN :rune_min_level AND :rune_max_level AND
+            rune.efficiency BETWEEN :rune_min_efficiency AND :rune_max_efficiency AND
+            rune.max_efficiency BETWEEN :rune_min_max_efficiency AND :rune_max_max_efficiency AND
+            (rune.type = enchantment.rune OR enchantment_type.inmemorial = 1) AND
+            enchantment_type.ancient = rune.ancient AND
+            -- No enchantments with the same sat as the runes main or innate
+            enchantment.stat NOT IN (
+              SELECT stat
+              FROM rune_stat
               WHERE
-                unit.player = '" . get_context()->get_player()->get_id() . "'
-                AND rune.player = '" . get_context()->get_player()->get_id() . "'
-                AND enchantment.player = '" . get_context()->get_player()->get_id() . "'
-                AND unit.id = unit_rune.unit
-                AND rune.id = unit_rune.rune
-                AND unit_rune.rta = " . get_context()->get_game_mode() . "
-                AND unit.monster = monster.id
-                AND enchantment.type = enchantment_type.id
-                -- RUNE FILTERS
-                AND unit.stars >= " . $this->filters["RUNE_MIN_STARS"] . "
-                AND unit.stars <= " . $this->filters["RUNE_MAX_STARS"] . "
-                AND rune.quality >= " . $this->filters["RUNE_MIN_QUALITY"] . "
-                AND rune.quality <= " . $this->filters["RUNE_MAX_QUALITY"] . "
-                AND rune.level >= " . $this->filters["RUNE_MIN_LEVEL"] . "
-                AND rune.level <= " . $this->filters["RUNE_MAX_LEVEL"] . "
-                AND rune.stars >= " . $this->filters["RUNE_MIN_STARS"] . "
-                AND rune.stars <= " . $this->filters["RUNE_MAX_STARS"] . "
-                AND rune.original_quality >= " . $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] . "
-                AND rune.original_quality <= " . $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] . "
-                AND rune.efficiency >= " . $this->filters["RUNE_MIN_EFFICIENCY"] . "
-                AND rune.efficiency <= " . $this->filters["RUNE_MAX_EFFICIENCY"] . "
-                AND rune.max_efficiency >= " . $this->filters["RUNE_MIN_MAX_EFFICIENCY"] . "
-                AND rune.max_efficiency <= " . $this->filters["RUNE_MAX_MAX_EFFICIENCY"] . "
-                AND (
-                  rune.type = enchantment.rune
-                  OR enchantment_type.inmemorial = 1
+                rune_stat.rune = rune.id AND
+                (
+                  rune_stat.slot = :stat_main OR
+                  rune_stat.slot = :stat_innate
                 )
-                AND enchantment_type.ancient = rune.ancient
-            ";
-
-            // Monster name
-            $cond = "";
-            if (strlen($this->filters["MONSTER_NAME"]) > 0){
-                $cond = "AND upper(monster.name) LIKE upper('%" . $this->filters["MONSTER_NAME"] . "%') ";
+            ) AND
+            ( -- TYPE SWITCH
+              ( -- BEGIN GRINDSTONE BLOCK
+                enchantment_type.gem = 0 AND
+                enchantment.stat IN (SELECT stat FROM rune_stat WHERE rune_stat.rune = rune.id) AND
+                enchantment.quality >= :grind_min_quality
+        ";
+        // GRindstone stats
+        if (count($this->filters["GRIND_STAT"]) > 0){
+            $query .= " AND enchantment.stat IN (";
+            for ($i = 0; $i < sizeof($this->filters["GRIND_STAT"]); $i ++){
+                $query .= ":grind_stat_$i, ";
             }
-            $s .= $cond . " -- MONSTER NAME \n";
-
-            // Monsters in storage
-            $cond = "";
-            if (!$this->filters["MONSTER_IN_STORAGE"]){
-                $cond = "AND unit.building <> " . BUILDING_ID::MONSTER_STORAGE . " ";
-            }
-            $s .= $cond . " -- STORAGE \n";
-
-            // Rune slot
-            $cond = "";
-            if (count($this->filters["RUNE_SLOT"]) > 0){
-                $in = "(";
-                foreach($this->filters["RUNE_SLOT"] as $t){
-                    $in .= "$t, ";
-                }
-                $in = rtrim($in, ", ") . ")";
-                $cond = "AND rune.slot IN $in";
+            $query = rtrim($query, ", ") . ") ";
+        }
+        $query .= "
+              ) -- END GRINDSTONE BLOCK
+              OR
+              ( -- BEGIN GEM BLOCK
+                enchantment_type.gem = 1 AND
+                enchantment.stat NOT IN (SELECT stat FROM rune_stat WHERE rune_stat.rune = rune.id) AND
+                enchantment.quality >= :gem_min_quality
+        ";
+        // Gem stats from
+        if (count($this->filters["GEM_STAT_TO"]) > 0){
+            $query .= " AND enchantment.stat IN (";
+            for ($i = 0; $i < sizeof($this->filters["GEM_STAT_TO"]); $i ++){
+                $query .= ":gem_stat_to_$i, ";
             }
-            $s .= $cond . " -- RUNE SLOT \n";
-
-            // Nevermind the type, discard enchantments with the same stat as
-            // the main or inate substat
-            $s .= "
-              AND enchantment.stat NOT IN (
-                SELECT stat
+            $query = rtrim($query, ", ") . ") ";
+        }
+        //Gem stats from
+        if (count($this->filters["GEM_STAT_FROM"]) > 0){
+            //$query .= " AND enchantment.stat IN (";
+            $query .= "
+              AND rune.id IN (
+                SELECT DISTINCT rune
                 FROM rune_stat
                 WHERE
-                  rune_stat.rune = rune.id
-                  AND (
-                    rune_stat.slot = " . RUNE_STAT_SLOT_ID::MAIN . "
-                    OR rune_stat.slot = " . RUNE_STAT_SLOT_ID::INNATE . "
-                  )
-              )
-            ";
-
-            // Begin type switch block
-            $s .= " AND ( -- TYPE SWITCH \n";
-
-            // Begin grindstone block
-            $s .= "
-              (
-                enchantment_type.gem = 0
-                AND enchantment.stat IN (SELECT stat FROM rune_stat rune_stat WHERE rune_stat.rune = rune.id)
-                AND enchantment.quality >= " . $this->filters["GRIND_MIN_QUALITY"] . " -- GRINDSTONE QUALITY
-            ";
-
-            // Grindstone stat
-            $cond = "";
-            if (count($this->filters["GRIND_STAT"]) > 0){
-                $in = "(";
-                foreach($this->filters["GRIND_STAT"] as $t){
-                    $in .= "$t, ";
-                }
-                $in = rtrim($in, ", ") . ")";
-                $cond = "AND enchantment.stat IN $in";
+                  rune_stat.rune = rune.id AND
+                  stat IN (
+                ";
+            for ($i = 0; $i < sizeof($this->filters["GEM_STAT_FROM"]); $i ++){
+                $query .= ":gem_stat_from_$i, ";
             }
-            $s .= $cond . " -- GRINDSTONE STAT \n";
-            $s .= "
-              )\n
-            ";
+            $query = rtrim($query, ", ") . ")) ";
+        }
+        $query .= "
+            ) -- END GEM BLOCK
+          ) -- END SWITCH
+        ";
 
-            // Begin gem block
-            $s .= " OR (
-              enchantment_type.gem = 1
-              AND enchantment.stat NOT IN (SELECT stat FROM rune_stat rune_stat WHERE rune_stat.rune = rune.id)
-              AND enchantment.quality >= " . $this->filters["GEM_MIN_QUALITY"] . " -- GEM QUALITY
-            ";
+        // Monster name
+        if ($this->filters["MONSTER_NAME"] != ""){
+            $query .= " AND upper(monster.name) LIKE upper(:monster_name) " ;
+        }
 
-            // Gem stat to
-            $cond = "";
-            if (count($this->filters["GEM_STAT_TO"]) > 0){
-                $in = "(";
-                foreach($this->filters["GEM_STAT_TO"] as $t){
-                    $in .= "$t, ";
-                }
-                $in = rtrim($in, ", ") . ")";
-                $cond = "AND enchantment.stat IN $in";
-            }
-            $s .= $cond . " -- GEM STAT TO \n";
+        // Monsters in storage
+        if (! $this->filters["MONSTER_IN_STORAGE"]){
+            $query .= "AND unit.building <> :storage_building ";
+        }
 
-            // Gem stat from
-            $cond = "";
-            if (count($this->filters["GEM_STAT_FROM"]) > 0){
-                $in = "(";
-                foreach($this->filters["GEM_STAT_FROM"] as $t){
-                    $in .= "$t, ";
-                }
-                $in = rtrim($in, ", ") . ")";
-                $cond = "
-                  AND rune.id IN(
-                    SELECT DISTINCT rune
-                    FROM rune_stat rune_stat
-                    WHERE
-                      rune_stat.rune = rune.id
-                      AND stat IN $in
-                  )
-                ";
+        // Rune slot
+        if (count($this->filters["RUNE_SLOT"]) > 0){
+            $query .= " AND rune.slot IN (";
+            for ($i = 0; $i < sizeof($this->filters["RUNE_SLOT"]); $i ++){
+                $query .= ":rune_slot_$i, ";
             }
-            $s .= $cond . " -- GEM STAT FROM \n";
-            $s .= "
-              )\n
-            ";
-
-            // End type switch block
-            $s .= " ) -- END TYPE SWITCH \n";
-
-            return $s;
+            $query = rtrim($query, ", ") . ") ";
+        }
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":rta", get_context()->get_game_mode(), SQLITE3_TEXT);
+        $statement->bindValue(":rune_min_stars", $this->filters["RUNE_MIN_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_max_stars", $this->filters["RUNE_MAX_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_min_quality", $this->filters["RUNE_MIN_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_max_quality", $this->filters["RUNE_MAX_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_min_original_quality", $this->filters["RUNE_MIN_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_max_original_quality", $this->filters["RUNE_MAX_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_min_level", $this->filters["RUNE_MIN_LEVEL"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_max_level", $this->filters["RUNE_MAX_LEVEL"], SQLITE3_INTEGER);
+        $statement->bindValue(":rune_min_efficiency", $this->filters["RUNE_MIN_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":rune_max_efficiency", $this->filters["RUNE_MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":rune_min_max_efficiency", $this->filters["RUNE_MIN_MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":rune_max_max_efficiency", $this->filters["RUNE_MAX_MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":monster_name", "%" . $this->filters["MONSTER_NAME"] . "%", SQLITE3_TEXT);
+        $statement->bindValue(":storage_building", BUILDING_ID::MONSTER_STORAGE, SQLITE3_INTEGER);
+        for ($i = 0; $i < sizeof($this->filters["RUNE_SLOT"]); $i ++){
+            $statement->bindValue(":rune_slot_$i", $this->filters["RUNE_SLOT"][$i], SQLITE3_INTEGER);
         }
+        $statement->bindValue(":stat_main", RUNE_STAT_SLOT_ID::MAIN, SQLITE3_INTEGER);
+        $statement->bindValue(":stat_innate", RUNE_STAT_SLOT_ID::INNATE, SQLITE3_INTEGER);
+        $statement->bindValue(":grind_min_quality", $this->filters["GRIND_MIN_QUALITY"], SQLITE3_INTEGER);
+        for ($i = 0; $i < sizeof($this->filters["GRIND_STAT"]); $i ++){
+            $statement->bindValue(":grind_stat_$i", $this->filters["GRIND_STAT"][$i], SQLITE3_INTEGER);
+        }
+        $statement->bindValue(":gem_min_quality", $this->filters["GEM_MIN_QUALITY"], SQLITE3_INTEGER);
+        for ($i = 0; $i < sizeof($this->filters["GEM_STAT_TO"]); $i ++){
+            $statement->bindValue(":gem_stat_to_$i", $this->filters["GEM_STAT_TO"][$i], SQLITE3_INTEGER);
+        }
+        for ($i = 0; $i < sizeof($this->filters["GEM_STAT_FROM"]); $i ++){
+            $statement->bindValue(":gem_stat_from_$i", $this->filters["GEM_STAT_FROM"][$i], SQLITE3_INTEGER);
+        }
+        return $statement;
     }
-?>
+    /**
+     * Retrieves the computed upgrades.
+     * 
+     * Can be described as:
+     * $upgrades = [
+     *   [
+     *     unit (Unit),
+     *     upgrade = [
+     *       [
+     *         rune (Rune),
+     *         enchant = [(Enchantment)]
+     *       ]
+     *     ]
+     *   ]
+     * ]
+     *
+     * @return mixed[] Upgrades to show. 
+     */
+    public function get_upgrades(){
+        return $this->upgrades;
+    }
+    
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+    
+    /**
+     * Retrieves one filter.
+     *
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
+        }
+    }
+
+}

+ 303 - 254
application/page/Report_Skillup_Page.php

@@ -1,276 +1,325 @@
  <?php
+/**
+ * Urgent Skillup report page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Unit.php");
+
+/**
+ * Urgent Skillup report page model.
+ *
+ * @category Page
+ */
+class Report_Skillup_Page extends Page{
+
     /**
-     * Urgent Skillup report page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Unit[] Sorted list of units.
      */
+    private $units = [];
 
     /**
-     * Require dependent files if not present.
+     * @var mixed[] Default filter values.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Unit.php");
+    private $filters = [
+        "MIN_STARS" => 5,
+        "MAX_STARS" => 6,
+        "MIN_NATURAL_STARS" => 5,
+        "MAX_NATURAL_STARS" => 5,
+        "IN_STORAGE" => false,
+        "WITHOUT_RUNES" => false,
+        "FAMILY" => false,
+        "MAXED" => false,
+        "2A" => false,
+        "HOMUNCULUS" => true,
+        "UNIT" => 0, // 0: All, 1: In teams, 2: In teams (score > 0)
+        "PONDERATION" => [1, 1.5, 2, 2.5]
+    ];
 
     /**
-     * Urgent Skillup report page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Report_Skillup_Page extends Page{
-
-        /**
-         * @var Unit[] Sorted list of units.
-         */
-        public $units = [];
-
-        /**
-         * @var mixed[] Default filter values.
-         */
-        public $filters = [
-            "MIN_STARS" => 5,
-            "MAX_STARS" => 6,
-            "MIN_NATURAL_STARS" => 5,
-            "MAX_NATURAL_STARS" => 5,
-            "IN_STORAGE" => false,
-            "WITHOUT_RUNES" => false,
-            "FAMILY" => false,
-            "MAXED" => false,
-            "2A" => true,
-            "HOMUNCULUS" => true,
-            "UNIT" => 0, // 0: All, 1: In teams, 2: In teams (score > 0)
-            "PONDERATION" => [1, 1.5, 2, 2.5]
-        ];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "report_skillup.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->units, new Unit($r["id"]));
-            }
-            $this->title = "Urgent skill-ups - SWDB";
-            $this->description = "Monster in need of skilling up";
-            $this->canonical = URL::BASE . "report/skillups";
+    public function __construct(){
+        $this->view = PATH::VIEW . "report_skillup.php";
+        $this->parse_filters();
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->units, new Unit($result["id"]));
         }
+        $this->title = "Urgent skill-ups - SWDB";
+        $this->description = "Monster in need of skilling up";
+        $this->canonical = URL::BASE . "report/skillups";
+    }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
 
-            if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) < 7){
-                $this->filters["MIN_STARS"] = intval($_GET["min_stars"]);
-            }
-            if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) < 7){
-                $this->filters["MAX_STARS"] = intval($_GET["max_stars"]);
-            }
-            if (isset($_GET["min_natural_stars"]) && intval($_GET["min_natural_stars"]) > 0 && intval($_GET["min_natural_stars"]) < 6){
-                $this->filters["MIN_NATURAL_STARS"] = intval($_GET["min_natural_stars"]);
-            }
-            if (isset($_GET["max_natural_stars"]) && intval($_GET["max_natural_stars"]) > 0 && intval($_GET["max_natural_stars"]) < 6){
-                $this->filters["MAX_NATURAL_STARS"] = intval($_GET["max_natural_stars"]);
-            }
-            if (isset($_GET["in_storage"]) && $_GET["in_storage"] == "on"){
-                $this->filters["IN_STORAGE"] = true;
-            }
-            if (isset($_GET["without_runes"]) && $_GET["without_runes"] == "on"){
-                $this->filters["WITHOUT_RUNES"] = true;
-            }
-            if (isset($_GET["family"]) && $_GET["family"] == "on"){
-                $this->filters["FAMILY"] = true;
-            }
-            if (isset($_GET["maxed"]) && $_GET["maxed"] == "on"){
-                $this->filters["MAXED"] = true;
-            }
-            if (!isset($_GET["2a"]) || $_GET["2a"] != "on"){
-                $this->filters["2A"] = false;
-            }
-            if (isset($_GET["homunculus"]) && $_GET["homunculus"] == "on"){
-                $this->filters["HOMUNCULUS"] = true;
-            }
-            if (isset($_GET["unit"]) && intval($_GET["unit"]) >= 0 && intval($_GET["unit"]) <= 2){
-                $this->filters["UNIT"] = intval($_GET["unit"]);
-            }
-            if (isset($_GET["pond_1"]) && floatval($_GET["pond_1"]) >= 0 && floatval($_GET["pond_1"]) <= 4){
-                $this->filters["PONDERATION"][0] = floatval($_GET["pond_1"]);
-            }
-            if (isset($_GET["pond_2"]) && floatval($_GET["pond_2"]) >= 0 && floatval($_GET["pond_2"]) <= 4){
-                $this->filters["PONDERATION"][1] = floatval($_GET["pond_2"]);
-            }
-            if (isset($_GET["pond_3"]) && floatval($_GET["pond_3"]) >= 0 && floatval($_GET["pond_3"]) <= 4){
-                $this->filters["PONDERATION"][2] = floatval($_GET["pond_3"]);
-            }
-            if (isset($_GET["pond_4"]) && floatval($_GET["pond_4"]) >= 0 && floatval($_GET["pond_4"]) <= 4){
-                $this->filters["PONDERATION"][3] = floatval($_GET["pond_4"]);
-            }
-            return;
+        if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) < 7){
+            $this->filters["MIN_STARS"] = intval($_GET["min_stars"]);
+        }
+        if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) < 7){
+            $this->filters["MAX_STARS"] = intval($_GET["max_stars"]);
+        }
+        if (isset($_GET["min_natural_stars"]) && intval($_GET["min_natural_stars"]) > 0 && intval($_GET["min_natural_stars"]) < 6){
+            $this->filters["MIN_NATURAL_STARS"] = intval($_GET["min_natural_stars"]);
+        }
+        if (isset($_GET["max_natural_stars"]) && intval($_GET["max_natural_stars"]) > 0 && intval($_GET["max_natural_stars"]) < 6){
+            $this->filters["MAX_NATURAL_STARS"] = intval($_GET["max_natural_stars"]);
+        }
+        if (isset($_GET["in_storage"]) && $_GET["in_storage"] == "on"){
+            $this->filters["IN_STORAGE"] = true;
+        }
+        if (isset($_GET["without_runes"]) && $_GET["without_runes"] == "on"){
+            $this->filters["WITHOUT_RUNES"] = true;
+        }
+        if (isset($_GET["family"]) && $_GET["family"] == "on"){
+            $this->filters["FAMILY"] = true;
+        }
+        if (isset($_GET["maxed"]) && $_GET["maxed"] == "on"){
+            $this->filters["MAXED"] = true;
+        }
+        if (!isset($_GET["2a"]) || $_GET["2a"] != "on"){
+            $this->filters["2A"] = false;
+        }
+        else{
+            $this->filters["2A"] = true;
+        }
+        if (isset($_GET["homunculus"]) && $_GET["homunculus"] == "on"){
+            $this->filters["HOMUNCULUS"] = true;
+        }
+        if (isset($_GET["unit"]) && intval($_GET["unit"]) >= 0 && intval($_GET["unit"]) <= 2){
+            $this->filters["UNIT"] = intval($_GET["unit"]);
+        }
+        if (isset($_GET["pond_1"]) && floatval($_GET["pond_1"]) >= 0 && floatval($_GET["pond_1"]) <= 4){
+            $this->filters["PONDERATION"][0] = floatval($_GET["pond_1"]);
+        }
+        if (isset($_GET["pond_2"]) && floatval($_GET["pond_2"]) >= 0 && floatval($_GET["pond_2"]) <= 4){
+            $this->filters["PONDERATION"][1] = floatval($_GET["pond_2"]);
+        }
+        if (isset($_GET["pond_3"]) && floatval($_GET["pond_3"]) >= 0 && floatval($_GET["pond_3"]) <= 4){
+            $this->filters["PONDERATION"][2] = floatval($_GET["pond_3"]);
+        }
+        if (isset($_GET["pond_4"]) && floatval($_GET["pond_4"]) >= 0 && floatval($_GET["pond_4"]) <= 4){
+            $this->filters["PONDERATION"][3] = floatval($_GET["pond_4"]);
         }
+        return;
+    }
 
-        /**
-         * Builds the query to the rune table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-              SELECT DISTINCT
-                unit.id AS id,
-                --sum(unit_skill.level * (CAST(skill.slot + 1 AS FLOAT) / 2.0)) AS ponderated_lvl,
-                sum(unit_skill.level *
-                  CASE
-                    WHEN skill.slot = 1 THEN  " . $this->filters["PONDERATION"][0] . "
-                    WHEN skill.slot = 2 THEN  " . $this->filters["PONDERATION"][1] . "
-                    WHEN skill.slot = 3 THEN  " . $this->filters["PONDERATION"][2] . "
-                    WHEN skill.slot = 4 THEN  " . $this->filters["PONDERATION"][3] . "
-                    ELSE 1
-                    END
-                ) AS ponderated_lvl,
-                sum(unit_skill.level) AS lvl,
-                --sum(skill.max_level * (CAST(skill.slot + 1 AS FLOAT) / 2.0)) AS ponderated_max_lvl,
-                sum(skill.max_level * 
-                  CASE
-                    WHEN skill.slot = 1 THEN  " . $this->filters["PONDERATION"][0] . "
-                    WHEN skill.slot = 2 THEN  " . $this->filters["PONDERATION"][1] . "
-                    WHEN skill.slot = 3 THEN  " . $this->filters["PONDERATION"][2] . "
-                    WHEN skill.slot = 4 THEN  " . $this->filters["PONDERATION"][3] . "
-                    ELSE 1
-                  END
-                ) AS ponderated_max_lvl,
-                sum(skill.max_level) AS max_lvl
-              FROM
-                unit,
-                monster,
-                unit_skill,
-                monster_skill,
-                skill
-              WHERE
-                unit.player = '" . get_context()->get_player()->get_id() . "' AND
-                unit.monster = monster.id AND
-                unit_skill.unit = unit.id AND ";
-            switch ($this->filters["UNIT"]){
-                case 0: // All units, do ot fiter.
-                    break;
-                case 1: // Units in teams.
-                    $s .= "
-                      (
-                        unit.id IN (
-                          SELECT DISTINCT unit
-                          FROM
-                            team,
-                            team_unit
-                          WHERE
-                            team.id = team_unit.team AND
-                            team.player = '" . get_context()->get_player()->get_id() . "'
-                        )
-                      ) AND ";
-                    break;
-                case 2: // Units in teams with score.
-                    $s .= "
-                      (
-                        unit.id IN (
-                          SELECT DISTINCT unit
-                          FROM
-                            team,
-                            team_unit
-                          WHERE
-                            team.id = team_unit.team AND
-                            team.player = '" . get_context()->get_player()->get_id() . "' AND
-                            team.score > 0
-                        )
-                      ) AND ";
-                    break;
-            }
-            if (!$this->filters["HOMUNCULUS"]){
-                $s .= "
-                  -- TODO: filter by units id
-                  --monster.homunculus <> 1 AND
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        // Common items
+        $query = "
+          SELECT DISTINCT
+            unit.id AS id,
+            --sum(unit_skill.level * (CAST(skill.slot + 1 AS FLOAT) / 2.0)) AS ponderated_lvl,
+            sum(unit_skill.level *
+              CASE
+                WHEN skill.slot = 1 THEN :ponderation_0
+                WHEN skill.slot = 2 THEN :ponderation_1
+                WHEN skill.slot = 3 THEN :ponderation_2
+                WHEN skill.slot = 4 THEN :ponderation_3
+                ELSE 1
+                END
+            ) AS ponderated_lvl,
+            sum(unit_skill.level) AS lvl,
+            --sum(skill.max_level * (CAST(skill.slot + 1 AS FLOAT) / 2.0)) AS ponderated_max_lvl,
+            sum(skill.max_level * 
+              CASE
+                WHEN skill.slot = 1 THEN :ponderation_0
+                WHEN skill.slot = 2 THEN :ponderation_1
+                WHEN skill.slot = 3 THEN :ponderation_2
+                WHEN skill.slot = 4 THEN :ponderation_3
+                ELSE 1
+              END
+            ) AS ponderated_max_lvl,
+            sum(skill.max_level) AS max_lvl
+          FROM
+            unit,
+            monster,
+            unit_skill,
+            monster_skill,
+            skill
+          WHERE
+            unit.player = :player AND
+            unit.monster = monster.id AND
+            unit_skill.unit = unit.id  ";
+        switch ($this->filters["UNIT"]){
+            case 0: // All units, do not fiter.
+                break;
+            case 1: // Units in teams.
+                $query .= "
+                  AND (
+                    unit.id IN (
+                      SELECT DISTINCT unit
+                      FROM
+                        team,
+                        team_unit
+                      WHERE
+                        team.id = team_unit.team AND
+                        team.player = unit.player
+                    )
+                  ) AND ";
+                break;
+            case 2: // Units in teams with score.
+                $query .= "
+                  AND (
+                    unit.id IN (
+                      SELECT DISTINCT unit
+                      FROM
+                        team,
+                        team_unit
+                      WHERE
+                        team.id = team_unit.team AND
+                        team.player = unit.player AND
+                        team.score > 0
+                    )
+                  ) ";
+                break;
+        }
+        if (!$this->filters["HOMUNCULUS"]){
+            $query .= "
+              -- TODO: filter by units id
+              --monster.homunculus <> 1 AND
+              AND unit_skill.skill = monster_skill.skill AND
+              monster.id = monster_skill.monster AND
+              skill.id = monster_skill.monster
+              ";
+        }
+        else{
+            $query .= "
+              AND  (
+                (
+                  monster.homunculus <> 1 AND 
                   unit_skill.skill = monster_skill.skill AND
                   monster.id = monster_skill.monster AND
-                  skill.id = monster_skill.monster AND
-                  ";
-              }
-              else{
-                $s .= "
-                  (
-                    (
-                      monster.homunculus <> 1 AND 
-                      unit_skill.skill = monster_skill.skill AND
-                      monster.id = monster_skill.monster AND
-                      skill.id = monster_skill.skill
-                    ) OR
-                    (
-                      -- TODO: Flter by uit IDs
-                      --unit.homunculus = 1 AND
-                      unit.monster = monster.id AND
-                      unit_skill.unit = unit.id AND
-                      unit_skill.skill = skill.id AND
-                      unit.id = unit_skill.unit
-                    )
-                  ) AND
-                  ";
-              }
-              $s .= "
-                skill.max_level > 1 AND
-                unit.stars >= " . $this->filters["MIN_STARS"] . " AND
-                unit.stars <= " . $this->filters["MAX_STARS"]
-            ;
-            if ($this->filters["2A"]){
-                $s = $s . "
-                    AND ((
-                      monster.natural_stars >= " . $this->filters["MIN_NATURAL_STARS"] . " AND
-                      monster.natural_stars <= " . $this->filters["MAX_NATURAL_STARS"] . "
-                    ) OR (
-                      monster.base_stars - monster.natural_stars > 1
-                    ))
-                ";
-            }
-            else{
-                $s = $s . "
-                    AND monster.natural_stars >= " . $this->filters["MIN_NATURAL_STARS"] . " AND
-                    monster.natural_stars <= " . $this->filters["MAX_NATURAL_STARS"]
-                ;
-            }
-            if (!$this->filters["IN_STORAGE"]){
-                $s = $s . " AND unit.building <> " . BUILDING_ID::MONSTER_STORAGE;
-            }
-            if (!$this->filters["WITHOUT_RUNES"]){
-                $s = $s . " AND unit.id IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . get_context()->get_game_mode() . ") ";
-            }
-            if (!$this->filters["FAMILY"]){
-                $s = $s . " AND unit.monster NOT IN (SELECT id FROM monster m WHERE family IN (SELECT family FROM monster k WHERE k.family = m.family AND k.natural_stars < m.natural_stars AND k.natural_stars < " . $this->filters["MIN_NATURAL_STARS"] . ")) ";
-                // Special case: Eirgar (Dark Vampire lord). Nat5 can be powered with 4 star Vampires.
-                if ($this->filters["MIN_NATURAL_STARS"] >= 5){
-                    $s = $s . " AND monster.id <> 19114 AND monster.id <> 19104 ";
-                }
-                // Special case: Fran (Light Fairy Queen). Nat3 can be powered with 2 star Fairies.
-                if ($this->filters["MIN_NATURAL_STARS"] >= 3){
-                    $s = $s . " AND monster.id <> 23015 AND monster.id <> 23005 ";
-                }
+                  skill.id = monster_skill.skill
+                ) OR
+                (
+                  -- TODO: Flter by unit IDs
+                  --unit.homunculus = 1 AND
+                  unit.monster = monster.id AND
+                  unit_skill.unit = unit.id AND
+                  unit_skill.skill = skill.id AND
+                  unit.id = unit_skill.unit
+                )
+              )
+              ";
+        }
+          
+        $query .= "
+          AND skill.max_level > 1 AND
+          unit.stars BETWEEN :min_stars AND :max_stars
+        ";
+        if ($this->filters["2A"]){
+            $query .= "
+                AND ((
+                  monster.natural_stars BETWEEN :min_natural_stars AND :max_natural_stars
+                ) OR (
+                  monster.base_stars - monster.natural_stars > 1
+                ))
+            ";
+        }
+        else{
+            $query .= "
+                AND monster.natural_stars BETWEEN :min_natural_stars AND :max_natural_stars
+            ";
+        }
+        if (!$this->filters["IN_STORAGE"]){
+            $query .= "
+              AND unit.building <> :storage_building
+            ";
+        }
+        if (! $this->filters["WITHOUT_RUNES"]){
+            $query .= "
+              AND unit.id IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = :rta)
+            ";
+        }
+        if (! $this->filters["FAMILY"]){
+            $query .= "
+              AND unit.monster NOT IN (SELECT id FROM monster m WHERE family IN (SELECT family FROM monster k WHERE k.family = m.family AND k.natural_stars < m.natural_stars AND k.natural_stars < :min_natural_stars))
+            ";
+            // Special case: Eirgar (Dark Vampire lord). Nat5 can be powered with 4 star Vampires.
+            if ($this->filters["MIN_NATURAL_STARS"] >= 5){
+                $query .= " AND monster.id <> 19114 AND monster.id <> 19104 ";
             }
-            $s = $s .
-              "GROUP BY unit.id ";
-            if (!$this->filters["MAXED"]){
-                $s = $s . " HAVING ponderated_lvl < ponderated_max_lvl ";
+            // Special case: Fran (Light Fairy Queen). Nat3 can be powered with 2 star Fairies.
+            if ($this->filters["MIN_NATURAL_STARS"] >= 3){
+                $query .= " AND monster.id <> 23015 AND monster.id <> 23005 ";
             }
-            $s = $s . "
-              ORDER BY
-                CAST(ponderated_lvl * 100 AS FLOAT) / CAST(ponderated_max_lvl * 100 AS FLOAT),
-                unit.stars DESC,
-                unit.level DESC,
-                CAST(lvl AS FLOAT) / CAST(max_lvl AS FLOAT),
-                max_lvl - lvl DESC
-            ";
-            return $s;
         }
+        $query .= " GROUP BY unit.id ";
+        if (! $this->filters["MAXED"]){
+            $query .= " HAVING ponderated_lvl < ponderated_max_lvl ";
+        }
+        $query .= "
+          ORDER BY
+            CAST(ponderated_lvl * 100 AS FLOAT) / CAST(ponderated_max_lvl * 100 AS FLOAT),
+            unit.stars DESC,
+            unit.level DESC,
+            CAST(lvl AS FLOAT) / CAST(max_lvl AS FLOAT),
+            max_lvl - lvl DESC
+        ";
+        $statement = get_context()->get_db()->prepare($query);
+        for ($i = 0; $i < 4; $i ++){
+            $statement->bindValue(":ponderation_$i", $this->filters["PONDERATION"][$i], SQLITE3_FLOAT);
+        }
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":min_stars", $this->filters["MIN_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_stars", $this->filters["MAX_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_natural_stars", $this->filters["MIN_NATURAL_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_natural_stars", $this->filters["MAX_NATURAL_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":storage_building", BUILDING_ID::MONSTER_STORAGE, SQLITE3_INTEGER);
+        $statement->bindValue(":rta", get_context()->get_game_mode(), SQLITE3_INTEGER);
+        return $statement;
     }
+    
+    /**
+     * Retrieves the selected units, sorted by urgency.
+     *
+     * @return Unit[] Selected units. 
+     */
+    public function get_units(){
+        return $this->units;
+    }
+    
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+    
+    /**
+     * Retrieves one filter.
+     *
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
+        }
+    }
+
+}
 ?>

+ 306 - 229
application/page/Runes_Page.php

@@ -1,256 +1,333 @@
  <?php
+/**
+ * Rune list page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Rune.php");
+require_once(PATH::ENTITY . "Unit.php");
+
+/**
+ * Rune list page model.
+ *
+ * @category Page
+ */
+class Runes_Page extends Page{
 
     /**
-     * Rune list page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
+     * @var Rune[] Runes to show.
      *
-     * @category Page
+     * In this case, the monster member is not the id, but a monster
+     * instance.
      */
+    private $runes = [];
 
     /**
-     * Require dependent files if not present.
+     * @var mixed[] Default filter values.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Rune.php");
-    require_once(PATH::ENTITY . "Unit.php");
+    private $filters = [
+        "TYPE" => [],
+        "MAIN" => [],
+        "SUB" => [],
+        "SLOT" => [],
+        "MIN_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_STARS" => 1,
+        "MAX_STARS" => 6,
+        "MIN_LEVEL" => 0,
+        "MAX_LEVEL" => 15,
+        "MIN_EFFICIENCY" => 0,
+        "MAX_EFFICIENCY" => 100,
+        "MIN_MAX_EFFICIENCY" => 0,
+        "MAX_MAX_EFFICIENCY" => 100,
+        "ASSIGNED" => 1,
+        "GROUP" => "SLOT"
+    ];
 
     /**
-     * Rune list page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Runes_Page extends Page{
-
-        /**
-         * @var Rune[] Runes to show.
-         *
-         * In this case, the monster member is not the id, but a monster
-         * instance.
-         */
-        public $runes = [];
-
-        /**
-         * @var mixed[] Default filter values.
-         */
-        public $filters = [
-            "TYPE" => [],
-            "MAIN" => [],
-            "SUB" => [],
-            "SLOT" => [],
-            "MIN_QUALITY" => QUALITY_ID::NORMAL,
-            "MAX_QUALITY" => QUALITY_ID::LEGEND,
-            "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
-            "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
-            "MIN_STARS" => 1,
-            "MAX_STARS" => 6,
-            "MIN_LEVEL" => 0,
-            "MAX_LEVEL" => 15,
-            "MIN_EFFICIENCY" => 0,
-            "MAX_EFFICIENCY" => 100,
-            "MIN_MAX_EFFICIENCY" => 0,
-            "MAX_MAX_EFFICIENCY" => 100,
-            "ASSIGNED" => 1,
-            "GROUP" => "SLOT"
-        ];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "runes.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $this->filters["GROUP"] = 1;
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $rune = new Rune($r["id"]);
-                array_push($this->runes, $rune);
-            }
-            $this->title = "Runes - SWDB";
-            $this->description = "Rune inventory";
-            $this->canonical = URL::BASE . "runes/";
+    public function __construct(){
+        $this->view = PATH::VIEW . "runes.php";
+        $this->parse_filters();
+        // TODO: Group hardcoded
+        $this->filters["GROUP"] = 1;
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->runes, new Rune($result["id"]));
         }
+        $this->title = "Runes - SWDB";
+        $this->description = "Rune inventory";
+        $this->canonical = URL::BASE . "runes/";
+    }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            if (isset($_GET["type"])){
-                $types = $_GET["type"];
-                foreach ($types as $type){
-                    array_push($this->filters["TYPE"], intval($type));
-                }
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        if (isset($_GET["type"])){
+            $types = $_GET["type"];
+            foreach ($types as $type){
+                array_push($this->filters["TYPE"], intval($type));
             }
-            if (isset($_GET["main_stat"])){
-                $mains = $_GET["main_stat"];
-                foreach ($mains as $main){
-                    array_push($this->filters["MAIN"], intval($main));
-                }
+        }
+        if (isset($_GET["main_stat"])){
+            $mains = $_GET["main_stat"];
+            foreach ($mains as $main){
+                array_push($this->filters["MAIN"], intval($main));
             }
-            if (isset($_GET["sub_stat"])){
-                $subs = $_GET["sub_stat"];
-                foreach ($subs as $sub){
-                    array_push($this->filters["SUB"], intval($sub));
-                }
+        }
+        if (isset($_GET["sub_stat"])){
+            $subs = $_GET["sub_stat"];
+            foreach ($subs as $sub){
+                array_push($this->filters["SUB"], intval($sub));
             }
-            if (isset($_GET["slot"])){
-                $slots = $_GET["slot"];
-                foreach ($slots as $slot){
-                    if (intval($slot) >= 1 && intval($slot) < 7){
-                        array_push($this->filters["SLOT"], intval($slot));
-                    }
+        }
+        if (isset($_GET["slot"])){
+            $slots = $_GET["slot"];
+            foreach ($slots as $slot){
+                if (intval($slot) >= 1 && intval($slot) < 7){
+                    array_push($this->filters["SLOT"], intval($slot));
                 }
             }
-            if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) < 7){
-                $this->filters["MIN_STARS"] = $_GET["min_stars"];
-            }
-            if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) < 7){
-                $this->filters["MAX_STARS"] = $_GET["max_stars"];
-            }
-            if (isset($_GET["min_level"]) && intval($_GET["min_level"]) >= 0 && intval($_GET["min_level"]) <= 15){
-                $this->filters["MIN_LEVEL"] = $_GET["min_level"];
-            }
-            if (isset($_GET["max_level"]) && intval($_GET["max_level"]) >= 0 && intval($_GET["max_level"]) <= 15){
-                $this->filters["MAX_LEVEL"] = $_GET["max_level"];
-            }
-            if (isset($_GET["min_quality"]) && intval($_GET["min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MIN_QUALITY"] = $_GET["min_quality"];
-            }
-            if (isset($_GET["max_quality"]) && intval($_GET["max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MAX_QUALITY"] = $_GET["max_quality"];
-            }
-            if (isset($_GET["min_original_quality"]) && intval($_GET["min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_original_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MIN_ORIGINAL_QUALITY"] = $_GET["min_original_quality"];
-            }
-            if (isset($_GET["max_original_quality"]) && intval($_GET["max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_original_quality"]) <= QUALITY_ID::LEGEND){
-                $this->filters["MAX_ORIGINAL_QUALITY"] = $_GET["max_original_quality"];
-            }
-            if (isset($_GET["min_efficiency"]) && intval($_GET["min_efficiency"]) >= 0 && intval($_GET["min_efficiency"]) <= 100){
-                $this->filters["MIN_EFFICIENCY"] = $_GET["min_efficiency"];
-            }
-            if (isset($_GET["max_efficiency"]) && intval($_GET["max_efficiency"]) >= 0 && intval($_GET["max_efficiency"]) <= 100){
-                $this->filters["MAX_EFFICIENCY"] = $_GET["max_efficiency"];
-            }
-            if (isset($_GET["min_max_efficiency"]) && intval($_GET["min_max_efficiency"]) >= 0 && intval($_GET["min_max_efficiency"]) <= 100){
-                $this->filters["MIN_MAX_EFFICIENCY"] = $_GET["min_max_efficiency"];
-            }
-            if (isset($_GET["max_max_efficiency"]) && intval($_GET["max_max_efficiency"]) >= 0 && intval($_GET["max_max_efficiency"]) <= 100){
-                $this->filters["MAX_MAX_EFFICIENCY"] = $_GET["max_max_efficiency"];
-            }
-            if (isset($_GET["assigned"]) && intval($_GET["assigned"]) >= 0 && intval($_GET["assigned"]) <= 4){
-                $this->filters["ASSIGNED"] = $_GET["assigned"];
-            }
-            if (isset($_GET["group"]) && ($_GET["group"] == "1" || $_GET["group"] == "0")){
-                $this->filters["GROUP"] = $_GET["group"];
-            }
         }
+        if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) < 7){
+            $this->filters["MIN_STARS"] = $_GET["min_stars"];
+        }
+        if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) < 7){
+            $this->filters["MAX_STARS"] = $_GET["max_stars"];
+        }
+        if (isset($_GET["min_level"]) && intval($_GET["min_level"]) >= 0 && intval($_GET["min_level"]) <= 15){
+            $this->filters["MIN_LEVEL"] = $_GET["min_level"];
+        }
+        if (isset($_GET["max_level"]) && intval($_GET["max_level"]) >= 0 && intval($_GET["max_level"]) <= 15){
+            $this->filters["MAX_LEVEL"] = $_GET["max_level"];
+        }
+        if (isset($_GET["min_quality"]) && intval($_GET["min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MIN_QUALITY"] = $_GET["min_quality"];
+        }
+        if (isset($_GET["max_quality"]) && intval($_GET["max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MAX_QUALITY"] = $_GET["max_quality"];
+        }
+        if (isset($_GET["min_original_quality"]) && intval($_GET["min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_original_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MIN_ORIGINAL_QUALITY"] = $_GET["min_original_quality"];
+        }
+        if (isset($_GET["max_original_quality"]) && intval($_GET["max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_original_quality"]) <= QUALITY_ID::LEGEND){
+            $this->filters["MAX_ORIGINAL_QUALITY"] = $_GET["max_original_quality"];
+        }
+        if (isset($_GET["min_efficiency"]) && intval($_GET["min_efficiency"]) >= 0 && intval($_GET["min_efficiency"]) <= 100){
+            $this->filters["MIN_EFFICIENCY"] = $_GET["min_efficiency"];
+        }
+        if (isset($_GET["max_efficiency"]) && intval($_GET["max_efficiency"]) >= 0 && intval($_GET["max_efficiency"]) <= 100){
+            $this->filters["MAX_EFFICIENCY"] = $_GET["max_efficiency"];
+        }
+        if (isset($_GET["min_max_efficiency"]) && intval($_GET["min_max_efficiency"]) >= 0 && intval($_GET["min_max_efficiency"]) <= 100){
+            $this->filters["MIN_MAX_EFFICIENCY"] = $_GET["min_max_efficiency"];
+        }
+        if (isset($_GET["max_max_efficiency"]) && intval($_GET["max_max_efficiency"]) >= 0 && intval($_GET["max_max_efficiency"]) <= 100){
+            $this->filters["MAX_MAX_EFFICIENCY"] = $_GET["max_max_efficiency"];
+        }
+        if (isset($_GET["assigned"]) && intval($_GET["assigned"]) >= 0 && intval($_GET["assigned"]) <= 4){
+            $this->filters["ASSIGNED"] = $_GET["assigned"];
+        }
+        if (isset($_GET["group"]) && ($_GET["group"] == "1" || $_GET["group"] == "0")){
+            $this->filters["GROUP"] = $_GET["group"];
+        }
+    }
 
-        /**
-         * Builds the query to the rune table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-              SELECT
-                id,
-                (
-                  SELECT DISTINCT unit
-                  FROM unit_rune
-                  WHERE
-                    rune = rune.id AND
-                    rta = " . get_context()->get_game_mode() . "
-                ) AS unit
-              FROM
-                rune rune
-              WHERE
-                player = '" . get_context()->get_player()->get_id() . "' AND
-                stars >= " . $this->filters["MIN_STARS"] . " AND
-                stars <= " . $this->filters["MAX_STARS"] . " AND
-                level >= " . $this->filters["MIN_LEVEL"] . " AND
-                level <= " . $this->filters["MAX_LEVEL"] . " AND
-                quality >= " . $this->filters["MIN_QUALITY"] . " AND
-                quality <= " . $this->filters["MAX_QUALITY"] . " AND
-                original_quality >= " . $this->filters["MIN_ORIGINAL_QUALITY"] . " AND
-                original_quality <= " . $this->filters["MAX_ORIGINAL_QUALITY"] . " AND
-                efficiency >= " . $this->filters["MIN_EFFICIENCY"] . " AND
-                efficiency <= " . $this->filters["MAX_EFFICIENCY"] . " AND
-                max_efficiency >= " . $this->filters["MIN_MAX_EFFICIENCY"] . " AND
-                max_efficiency <= " . $this->filters["MAX_MAX_EFFICIENCY"] . "
-            ";
-            if (count($this->filters["MAIN"]) > 0){
-                $values = "(";
-                foreach($this->filters["MAIN"] as $t){
-                    $values = $values . "'$t', ";
-                }
-                $values = $values . "'DUMMY0') ";
-                $s .= "
-                  AND id IN (
-                    SELECT rune
-                    FROM rune_stat
-                    WHERE
-                      slot = " . RUNE_STAT_SLOT_ID::MAIN . " AND
-                      stat IN $values
-                  )
-                ";
-            }
-            if (count($this->filters["SUB"]) > 0){
-                $values = "(";
-                foreach($this->filters["SUB"] as $t){
-                    $values = $values . "'$t', ";
-                }
-                $values = $values . "'DUMMY0') ";
-                $s .= "
-                  AND id IN (
-                    SELECT rune
-                    FROM rune_stat
-                    WHERE
-                      slot != " . RUNE_STAT_SLOT_ID::MAIN . " AND
-                      stat IN $values
-                  )
-                ";
-            }
-            if (count($this->filters["TYPE"]) > 0){
-                $s = $s . " AND upper(type) IN ( ";
-                foreach($this->filters["TYPE"] as $t){
-                    $s = $s . "'$t', ";
-                }
-                $s = $s . "'DUMMY0') ";
-            }
-            if (count($this->filters["SLOT"]) > 0){
-                $s = $s . " AND slot IN ( ";
-                foreach($this->filters["SLOT"] as $t){
-                    $s = $s . "$t, ";
-                }
-                $s = $s . "-1) ";
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        // Common items
+        $query = "
+          SELECT
+            id
+          FROM
+            rune
+          WHERE
+            player = :player AND
+            stars BETWEEN :min_stars AND :max_stars AND
+            level BETWEEN :min_level AND :max_level AND
+            quality BETWEEN :min_quality AND :max_quality AND
+            original_quality BETWEEN :min_original_quality AND :max_original_quality AND
+            efficiency BETWEEN :min_efficiency AND :max_efficiency AND
+            max_efficiency BETWEEN :min_max_efficiency AND :max_max_efficiency
+        ";
+        
+        // Some main stat selected.
+        if (count($this->filters["MAIN"]) > 0){
+            $query .= " AND id IN (SELECT rune FROM rune_stat WHERE slot = :slot_main AND stat IN (";
+            for ($i = 0; $i < sizeof($this->filters["MAIN"]); $i ++){
+                $query .= ":main_$i, ";
             }
-            switch ($this->filters["ASSIGNED"]){
-                case 1:
-                    $s = $s . " AND unit IS NOT NULL ";
-                    break;
-                case 2:
-                    $s = $s . " AND unit IS NULL ";
-                    break;
-                case 3:
-                    $s = $s . " AND (unit IS NULL OR unit IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ")) ";
-                    break;
-                case 4:
-                    $s = $s . " AND unit IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ") ";
-                    break;
+            $query = rtrim($query, ", ") . ")) ";
+        }
+        
+        // Some substat selected.
+        if (count($this->filters["SUB"]) > 0){
+            $query .= " AND id IN (SELECT rune FROM rune_stat WHERE slot <> :slot_main AND stat IN (";
+            for ($i = 0; $i < sizeof($this->filters["MAIN"]); $i ++){
+                $query .= ":sub_$i, ";
             }
-            $s = $s . " ORDER BY ";
-            if ($this->filters["GROUP"] == 1){ // 1: Type, 0: Slot
-                $s = $s . " type, slot, stars DESC, original_quality DESC, quality DESC, level;";
+            $query = rtrim($query, ", ") . ")) ";
+        }
+        
+        // Some sets selected.
+        if (count($this->filters["TYPE"]) > 0){
+            $query .= " AND type IN (";
+            for ($i = 0; $i < sizeof($this->filters["TYPE"]); $i ++){
+                $query .= ":type_$i, ";
             }
-            else{
-                $s = $s . " slot, type, stars DESC, original_quality DESC, quality DESC, level;";
+            $query = rtrim($query, ", ") . ") ";
+        }
+        
+        // Some slots selected.
+        if (count($this->filters["SLOT"]) > 0){
+            $query .= " AND slot IN (";
+            for ($i = 0; $i < sizeof($this->filters["SLOT"]); $i ++){
+                $query .= ":slot_$i, ";
             }
-            return $s;
+            $query = rtrim($query, ", ") . ") ";
+        }
+        
+        switch ($this->filters["ASSIGNED"]){
+            case 0: // All
+                break;
+            case 1: // Assigned
+                $query .= "
+                  AND id IN (
+                    SELECT DISTINCT rune
+                    FROM unit_rune
+                    WHERE rta = :rta) ";
+                break;
+            case 2: // Unassigned
+                $query .= "
+                  AND id NOT IN (
+                    SELECT DISTINCT rune
+                    FROM unit_rune
+                    WHERE rta = :rta) ";
+                break;
+            case 3: // Unassigned or assigned to non-storage units
+                $query .= "
+                  AND (
+                    id NOT IN (
+                      SELECT DISTINCT rune
+                      FROM unit_rune
+                      WHERE rta = :rta
+                    ) OR (
+                      id IN (
+                        SELECT DISTINCT unit_rune.rune
+                        FROM
+                          unit_rune,
+                          unit
+                        WHERE
+                          unit_rune.rta = :rta AND
+                          unit_rune.unit = unit.id AND
+                          unit.building = :storage_building
+                      )
+                    )
+                  )";
+                break;
+            case 4: // Assigned to non-storage units
+                $query .= "
+                  AND (
+                    id IN (
+                      SELECT DISTINCT unit_rune.rune
+                      FROM
+                        unit_rune,
+                        unit
+                      WHERE
+                        unit_rune.rta = :rta AND
+                        unit_rune.unit = unit.id AND
+                        unit.building = :storage_building
+                    )
+                  )";
+                break;
+        }
+        $query .= " ORDER BY ";
+        if ($this->filters["GROUP"] == 1){ // 1: Type, 0: Slot
+            $query .= " type, slot, stars DESC, original_quality DESC, quality DESC, level;";
         }
+        else{
+            $query .= " slot, type, stars DESC, original_quality DESC, quality DESC, level;";
+        }
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":rta", get_context()->get_game_mode(), SQLITE3_INTEGER);
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":min_stars", $this->filters["MIN_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_stars", $this->filters["MAX_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_level", $this->filters["MIN_LEVEL"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_level", $this->filters["MAX_LEVEL"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_quality", $this->filters["MIN_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_quality", $this->filters["MAX_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_original_quality", $this->filters["MIN_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_original_quality", $this->filters["MAX_ORIGINAL_QUALITY"], SQLITE3_INTEGER);
+        $statement->bindValue(":min_efficiency", $this->filters["MIN_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":max_efficiency", $this->filters["MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":min_max_efficiency", $this->filters["MIN_MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":max_max_efficiency", $this->filters["MAX_MAX_EFFICIENCY"], SQLITE3_FLOAT);
+        $statement->bindValue(":slot_main", RUNE_STAT_SLOT_ID::MAIN, SQLITE3_FLOAT);
+        for ($i = 0; $i < sizeof($this->filters["MAIN"]); $i ++){
+            $statement->bindValue(":main_$i", $this->filters["MAIN"][$i], SQLITE3_INTEGER);
+        }
+        for ($i = 0; $i < sizeof($this->filters["SUB"]); $i ++){
+            $statement->bindValue(":sub_$i", $this->filters["SUB"][$i], SQLITE3_INTEGER);
+        }
+        for ($i = 0; $i < sizeof($this->filters["TYPE"]); $i ++){
+            $statement->bindValue(":type_$i", $this->filters["TYPE"][$i], SQLITE3_INTEGER);
+        }
+        for ($i = 0; $i < sizeof($this->filters["SLOT"]); $i ++){
+            $statement->bindValue(":slot_$i", $this->filters["SLOT"][$i], SQLITE3_INTEGER);
+        }
+        $statement->bindValue(":storage_building", BUILDING_ID::MONSTER_STORAGE, SQLITE3_INTEGER);
+error_log($statement->getSQL(true));
+        return $statement;
+    }
+
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+    
+    /**
+     * Retrieves one filter.
+     *
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
+        }
+    }
+    
+    /**
+     * Retrieves the selection of runes.
+     *
+     * @return Rune[] Runes to show on the page.
+     */
+    public function get_runes(){
+        return $this->runes;
     }
-?>
+}

+ 167 - 112
application/page/Runs_Page.php

@@ -1,129 +1,184 @@
  <?php
+/**
+ * Run list file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Run.php");
+
+/**
+ * Run list page model.
+ *
+ * @category Page
+ */
+class Runs_Page extends Page{
+
     /**
-     * Run list file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Run[] Runs to show.
      */
+    private $runs = [];
 
     /**
-     * Require dependent files if not present.
+     * @var mixed[] Page filters
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Run.php");
+    private $filters = [
+        "AREA_TYPE" => 0,
+        "AREA" => 0,
+        "STAGE" => 0,
+        "DIFFICULTY" => 0,
+        "DATE_MIN" => null,
+        "DATE_MAX" => null,
+        "DEFEAT" => false,
+        "HELPER" => false,
+        "NUMBER" => 20,
+    ];
 
     /**
-     * Run list page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Runs_Page extends Page{
-
-        /**
-         * @var Run[] Runs to show.
-         */
-        public $runs = [];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "runs.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->runs, new Run($r["id"]));
-            }
-            $this->title = "Runs - SWDB";
-            $this->description = "Run logs";
-            $this->canonical = URL::BASE . "runs/";
+    public function __construct(){
+        $this->view = PATH::VIEW . "runs.php";
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->runs, new Run($result["id"]));
         }
+        $this->title = "Runs - SWDB";
+        $this->description = "Run logs";
+        $this->canonical = URL::BASE . "runs/";
+    }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            $this->filters = FILTER::RUN;
-            if (isset($_GET["area_type"]) && intval($_GET["area_type"]) > 0){
-                $this->filters["AREA_TYPE"] = $_GET["area_type"];
-            }
-            if (isset($_GET["area"]) && intval($_GET["area"]) > 0){
-                $this->filters["AREA"] = $_GET["area"];
-            }
-            if (isset($_GET["stage"]) && intval($_GET["stage"]) > 0){
-                $this->filters["STAGE"] = $_GET["stage"];
-            }
-            if (isset($_GET["difficulty"]) && intval($_GET["difficulty"]) >= DIFFICULTY_ID::NORMAL && intval($_GET["difficulty"]) <= DIFFICULTY_ID::HELL){
-                $this->filters["DIFFICULTY"] = $_GET["difficulty"];
-            }
-            if (isset($_GET["date_min"]) && strlen($_GET["date_min"]) > 0){
-                $this->filters["DATE_MIN"] = DateTime::createFromFormat('Y-m-d', $_GET["date_min"])->format('Y-m-d');
-            }
-            if (isset($_GET["date_max"]) && strlen($_GET["date_max"]) > 0){
-                $this->filters["DATE_MAX"] = DateTime::createFromFormat('Y-m-d', $_GET["date_max"])->format('Y-m-d');
-            }
-            if (isset($_GET["defeat"]) && $_GET["defeat"] == "on"){
-                $this->filters["DEFEAT"] = true;
-            }
-            else{
-                $this->filters["HELPER"] = false;
-            }
-            if (isset($_GET["helper"]) && $_GET["helper"] == "on"){
-                $this->filters["HELPER"] = true;
-            }
-            else{
-                $this->filters["HELPER"] = false;
-            }
-            if (isset($_GET["number"]) && intval($_GET["number"]) > 0){
-                $this->filters["NUMBER"] = $_GET["number"];
-            }
-            return;
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        $this->filters = FILTER::RUN;
+        if (isset($_GET["area_type"]) && intval($_GET["area_type"]) > 0){
+            $this->filters["AREA_TYPE"] = $_GET["area_type"];
+        }
+        if (isset($_GET["area"]) && intval($_GET["area"]) > 0){
+            $this->filters["AREA"] = $_GET["area"];
+        }
+        if (isset($_GET["stage"]) && intval($_GET["stage"]) > 0){
+            $this->filters["STAGE"] = $_GET["stage"];
         }
+        if (isset($_GET["difficulty"]) && intval($_GET["difficulty"]) >= DIFFICULTY_ID::NORMAL && intval($_GET["difficulty"]) <= DIFFICULTY_ID::HELL){
+            $this->filters["DIFFICULTY"] = $_GET["difficulty"];
+        }
+        if (isset($_GET["date_min"]) && strlen($_GET["date_min"]) > 0){
+            $this->filters["DATE_MIN"] = DateTime::createFromFormat('Y-m-d', $_GET["date_min"])->format('Y-m-d');
+        }
+        if (isset($_GET["date_max"]) && strlen($_GET["date_max"]) > 0){
+            $this->filters["DATE_MAX"] = DateTime::createFromFormat('Y-m-d', $_GET["date_max"])->format('Y-m-d');
+        }
+        if (isset($_GET["defeat"]) && $_GET["defeat"] == "on"){
+            $this->filters["DEFEAT"] = true;
+        }
+        else{
+            $this->filters["HELPER"] = false;
+        }
+        if (isset($_GET["helper"]) && $_GET["helper"] == "on"){
+            $this->filters["HELPER"] = true;
+        }
+        else{
+            $this->filters["HELPER"] = false;
+        }
+        if (isset($_GET["number"]) && intval($_GET["number"]) > 0){
+            $this->filters["NUMBER"] = $_GET["number"];
+        }
+        return;
+    }
 
-        /**
-         * Builds the query to the run table using the selected or default
-         * filters.
-         * 
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-                SELECT id
-                FROM run
-                WHERE player = '" . get_context()->get_player()->get_id() . "'
-             ";
-            if ($this->filters["AREA_TYPE"] > 0){
-                $s = $s . " AND area_type =  " . $this->filters["AREA_TYPE"] . " ";
-            }
-            if ($this->filters["AREA"] > 0){
-                $s = $s . " AND area =  " . $this->filters["AREA"] . " ";
-            }
-            if ($this->filters["STAGE"] > 0){
-                $s = $s . " AND stage =  " . $this->filters["STAGE"] . " ";
-            }
-            if ($this->filters["DIFFICULTY"] > 0){
-                $s = $s . " AND difficulty =  " . $this->filters["DIFFICULTY"] . " ";
-            }
-            if (!$this->filters["DEFEAT"]){
-                $s = $s . " AND win = 1 ";
-            }
-            if (!$this->filters["HELPER"]){
-                $s = $s . " AND helper = 0 ";
-            }
-            if ($this->filters["DATE_MIN"] != null){
-                $s = $s . " AND date(dtime) >= date('" . $this->filters["DATE_MIN"] . "') ";
-            }
-            if ($this->filters["DATE_MAX"] != null){
-                $s = $s . " AND date(dtime) >= date('" . $this->filters["DATE_MAX"] . "') ";
-            }
-            $s = $s . " ORDER BY dtime DESC ";
-            $s = $s . " LIMIT " . $this->filters["NUMBER"] . ";";
-            return $s;
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        
+        // Common items
+        $query = "
+            SELECT id
+            FROM run
+            WHERE player = :player
+         ";
+        if ($this->filters["AREA_TYPE"] > 0){
+            $query .= " AND area_type =  :area_type ";
+        }
+        if ($this->filters["AREA"] > 0){
+            $query .= " AND area =  :area ";
+        }
+        if ($this->filters["STAGE"] > 0){
+            $query .= " AND stage =  :stage ";
+        }
+        if ($this->filters["DIFFICULTY"] > 0){
+            $query .= " AND difficulty =  :difficulty ";
+        }
+        if (! $this->filters["DEFEAT"]){
+            $query .= " AND win = 1 ";
+        }
+        if (! $this->filters["HELPER"]){
+            $query .= " AND helper = 0 ";
+        }
+        if ($this->filters["DATE_MIN"] != null){
+            $query .= " AND date(dtime) >= date(:date_min) ";
+        }
+        if ($this->filters["DATE_MAX"] != null){
+            $query .= " AND date(dtime) >= date(:date_max) ";
+        }
+        $query .= " ORDER BY dtime DESC LIMIT :limit;";
+        
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":area_type", $this->filters["AREA_TYPE"], SQLITE3_INTEGER);
+        $statement->bindValue(":area", $this->filters["AREA"], SQLITE3_INTEGER);
+        $statement->bindValue(":stage", $this->filters["STAGE"], SQLITE3_INTEGER);
+        $statement->bindValue(":difficulty", $this->filters["DIFFICULTY"], SQLITE3_INTEGER);
+        $statement->bindValue(":date_min", $this->filters["DATE_MIN"], SQLITE3_TEXT);
+        $statement->bindValue(":date_max", $this->filters["DATE_MAX"], SQLITE3_TEXT);
+        $statement->bindValue(":limit", $this->filters["LIMIT"], SQLITE3_INTEGER);
+        return $statement;
+    }
+    
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+    
+    /**
+     * Retrieves one filter.
+     *
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
         }
+        else{
+            return null;
+        }
+    }
+    
+    /**
+     * Retrieves the selection of runs.
+     *
+     * @return Run[] Runs to show on the page.
+     */
+    public function get_runs(){
+        return $this->runs;
     }
+}
 ?>

+ 239 - 229
application/page/Stats_Page.php

@@ -1,244 +1,254 @@
  <?php
+/**
+ * Statistics page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @todo Not workig, redo.
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Run.php");
+
+/**
+ * Statistics page model.
+ *
+ * @category Page
+ */
+class Stats_Page extends Page{
+
     /**
-     * Statistics page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var bool Indicates if there is data to show.
+     */
+    public $show_data = true;
+
+    /**
+     * @var Run The best run for the selected area
+     */
+    public $best_run = null;
+
+    /**
+     * @var int[] 0 index: total victories. 1 index: total losses.
+     */
+    public $win_lose = [0, 0];
+
+    /**
+     * @var int[] Item type drops.
      */
+    public $drop_type = [
+        "rune" => 0,
+        "rune_craft" => 0,
+        "item" => 0,
+        "sd" => 0,
+        "shapeshifting" => 0,
+        "unit" => 0
+    ];
 
     /**
-     * Require dependent files if not present.
+     * @var int[] Rune drop rate by slot.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Run.php");
+    public $drop_rune_slot = [
+        "1" => 0,
+        "2" => 0,
+        "3" => 0,
+        "4" => 0,
+        "5" => 0,
+        "6" => 0
+    ];
 
     /**
-     * Statistics page model.
+     * @var int[] Rune drop rate by stars.
+     */
+    public $drop_rune_stars = [
+        "1" => 0,
+        "2" => 0,
+        "3" => 0,
+        "4" => 0,
+        "5" => 0,
+        "6" => 0
+    ];
+
+    public $drop_rune_quality = [
+        QUALITY_ID::NORMAL => 0,
+        QUALITY_ID::MAGIC => 0,
+        QUALITY_ID::RARE => 0,
+        QUALITY_ID::HERO => 0,
+        QUALITY_ID::LEGEND => 0
+    ];
+    
+    /**
+     * @var mixed[] Page filters
+     */
+    public $filters = [
+        "AREA_TYPE" => null,
+        "AREA" => null,
+        "STAGE" => null,
+        "DIFFICULTY" => null,
+        "INCLUDE_HELPER" => false
+    ];
+
+    /**
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Stats_Page extends Page{
-
-        /**
-         * @var bool Indicates if there is data to show.
-         */
-        public $show_data = true;
-
-        /**
-         * @var Run The best run for the selected area
-         */
-        public $best_run = null;
-
-        /**
-         * @var int[] 0 index: total victories. 1 index: total losses.
-         */
-        public $win_lose = [0, 0];
-
-        /**
-         * @var int[] Item type drops.
-         */
-        public $drop_type = [
-            "rune" => 0,
-            "rune_craft" => 0,
-            "item" => 0,
-            "sd" => 0,
-            "shapeshifting" => 0,
-            "unit" => 0
-        ];
-
-        /**
-         * @var int[] Rune drop rate by slot.
-         */
-        public $drop_rune_slot = [
-            "1" => 0,
-            "2" => 0,
-            "3" => 0,
-            "4" => 0,
-            "5" => 0,
-            "6" => 0
-        ];
-
-        /**
-         * @var int[] Rune drop rate by stars.
-         */
-        public $drop_rune_stars = [
-            "1" => 0,
-            "2" => 0,
-            "3" => 0,
-            "4" => 0,
-            "5" => 0,
-            "6" => 0
-        ];
-
-        public $drop_rune_quality = [
-            QUALITY_ID::NORMAL => 0,
-            QUALITY_ID::MAGIC => 0,
-            QUALITY_ID::RARE => 0,
-            QUALITY_ID::HERO => 0,
-            QUALITY_ID::LEGEND => 0
-        ];
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "stats.php";
-            $this->title = "Stats - SWDB";
-            $this->description = "Player statistics";
-            $this->canonical = URL::BASE . "stats/";
-
-            $this->parse_filters();
-
-            // If no filters, stop
-            if ($this->filters["AREA"] == null){
-                $this->show_data = false;
-                return;
-            }
-
-            // Build query modifier:
-            $query_where = "
-              run.player = '" . get_context()->get_player()->get_id() . "' AND
-              run.area = " . $this->filters["AREA"] . "
-            ";
-            if ($this->filters["STAGE"] > 0){
-                $query_where = $query_where . " AND run.stage =  " . $this->filters["STAGE"] . " ";
-            }
-            if ($this->filters["DIFFICULTY"] > 0){
-                $query_where = $query_where . " AND run.difficulty =  " . $this->filters["DIFFICULTY"] . " ";
-            }
-            if (!$this->filters["INCLUDE_HELPER"]){
-                $query_where = $query_where . " AND run.helper = 0 ";
-            }
-
-            // Best run:
-            $s = "
-              SELECT id
-              FROM run
-              WHERE
-                $query_where
-              ORDER BY time DESC
-              LIMIT 1;
-            ";
-            $q = get_context()->get_db()->query($s);
-            if ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $this->best_run = new Run($r["id"]);
-            }
-
-            // Win/lose ratio
-            $s = "
-              SELECT
-                (SELECT COUNT(win) FROM run WHERE $query_where AND win = 1 ) AS win,
-                (SELECT COUNT(win) FROM run WHERE $query_where AND win = 0) AS lose;
-            ";
-            $q = get_context()->get_db()->query($s);
-            $r = $q->fetchArray(SQLITE3_ASSOC);
-            $this->win_lose = [$r["win"], $r["lose"]];
-
-            // Drop type rate
-            $s = "
-              SELECT
-                (SELECT COUNT(run) FROM run run, run_drop_rune run_drop_rune WHERE $query_where AND run.id = run_drop_rune.run AND player = '" . get_context()->get_player()->get_id() . "') AS rune,
-                (SELECT COUNT(run) FROM run run, run_drop_rune_craft run_drop_rune_craft WHERE $query_where AND run.id = run_drop_rune_craft.run AND player = '" . get_context()->get_player()->get_id() . "') AS rune_craft,
-                (SELECT COUNT(run) FROM run run, run_drop_item run_drop_item WHERE $query_where AND run.id = run_drop_item.run AND player = '" . get_context()->get_player()->get_id() . "') AS item,
-                (SELECT COUNT(run) FROM run run, run_drop_sd run_drop_sd WHERE $query_where AND run.id = run_drop_sd.run AND player = '" . get_context()->get_player()->get_id() . "') AS sd,
-                (SELECT COUNT(run) FROM run run, run_drop_shapeshifting run_drop_shapeshifting WHERE $query_where AND run.id = run_drop_shapeshifting.run AND player = '" . get_context()->get_player()->get_id() . "') AS shapeshifting,
-                (SELECT COUNT(run) run run, run_drop_unit run_drop_unit WHERE $query_where AND run.id = run_drop_unit.run AND player = '" . get_context()->get_player()->get_id() . "') AS unit;
-            ";
-            $q = get_context()->get_db()->query($s);
-            $r = $q->fetchArray(SQLITE3_ASSOC);
-            $this->drop_type["rune"] = $r["rune"];
-            $this->drop_type["rune_craft"] = $r["rune_craft"];
-            $this->drop_type["item"] = $r["item"];
-            $this->drop_type["sd"] = $r["sd"];
-            $this->drop_type["shapeshifting"] = $r["shapeshifting"];
-            $this->drop_type["unit"] = $r["unit"];
-
-            // Rune drop rate by slot
-            $s = "
-              SELECT 
-                slot,
-                count(run.id) AS count
-              FROM
-                run run,
-                run_drop_rune run_drop_rune
-              WHERE
-                $query_where AND 
-                run.id = run_drop_rune.run
-              GROUP BY slot
-              ORDER BY slot;
-            ";
-                $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $this->drop_rune_slot[$r["slot"]] = $r["count"];
-            }
-
-            // Rune drop rate by slot
-            $s = "
-              SELECT 
-                stars,
-                count(run.id) AS count
-              FROM
-                run run,
-                run_drop_rune run_drop_rune
-              WHERE
-                $query_where AND 
-                run.id = run_drop_rune.run
-              GROUP BY stars
-              ORDER BY stars DESC;
-            ";
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $this->drop_rune_stars[strval($r["stars"])] = $r["count"];
-            }
-
-            // Rune drop rate by quality
-            $s = "
-              SELECT 
-                quality,
-                count(run.id) AS count
-              FROM
-                run run,
-                run_drop_rune run_drop_rune
-              WHERE
-                $query_where AND 
-                run.id = run_drop_rune.run
-              GROUP BY quality
-              ORDER BY quality DESC;
-            ";
+    public function __construct(){
+        $this->view = PATH::VIEW . "stats.php";
+        $this->title = "Stats - SWDB";
+        $this->description = "Player statistics";
+        $this->canonical = URL::BASE . "stats/";
+
+        $this->parse_filters();
+
+        // If no filters, stop
+        if ($this->filters["AREA"] == null){
+            $this->show_data = false;
+            return;
+        }
+
+        // Build query modifier:
+        $query_where = "
+          run.player = '" . get_context()->get_player()->get_id() . "' AND
+          run.area = " . $this->filters["AREA"] . "
+        ";
+        if ($this->filters["STAGE"] > 0){
+            $query_where = $query_where . " AND run.stage =  " . $this->filters["STAGE"] . " ";
+        }
+        if ($this->filters["DIFFICULTY"] > 0){
+            $query_where = $query_where . " AND run.difficulty =  " . $this->filters["DIFFICULTY"] . " ";
+        }
+        if (!$this->filters["INCLUDE_HELPER"]){
+            $query_where = $query_where . " AND run.helper = 0 ";
+        }
+
+        // Best run:
+        $s = "
+          SELECT id
+          FROM run
+          WHERE
+            $query_where
+          ORDER BY time DESC
+          LIMIT 1;
+        ";
+        $q = get_context()->get_db()->query($s);
+        if ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            $this->best_run = new Run($r["id"]);
+        }
+
+        // Win/lose ratio
+        $s = "
+          SELECT
+            (SELECT COUNT(win) FROM run WHERE $query_where AND win = 1 ) AS win,
+            (SELECT COUNT(win) FROM run WHERE $query_where AND win = 0) AS lose;
+        ";
+        $q = get_context()->get_db()->query($s);
+        $r = $q->fetchArray(SQLITE3_ASSOC);
+        $this->win_lose = [$r["win"], $r["lose"]];
+
+        // Drop type rate
+        $s = "
+          SELECT
+            (SELECT COUNT(run) FROM run run, run_drop_rune run_drop_rune WHERE $query_where AND run.id = run_drop_rune.run AND player = '" . get_context()->get_player()->get_id() . "') AS rune,
+            (SELECT COUNT(run) FROM run run, run_drop_rune_craft run_drop_rune_craft WHERE $query_where AND run.id = run_drop_rune_craft.run AND player = '" . get_context()->get_player()->get_id() . "') AS rune_craft,
+            (SELECT COUNT(run) FROM run run, run_drop_item run_drop_item WHERE $query_where AND run.id = run_drop_item.run AND player = '" . get_context()->get_player()->get_id() . "') AS item,
+            (SELECT COUNT(run) FROM run run, run_drop_sd run_drop_sd WHERE $query_where AND run.id = run_drop_sd.run AND player = '" . get_context()->get_player()->get_id() . "') AS sd,
+            (SELECT COUNT(run) FROM run run, run_drop_shapeshifting run_drop_shapeshifting WHERE $query_where AND run.id = run_drop_shapeshifting.run AND player = '" . get_context()->get_player()->get_id() . "') AS shapeshifting,
+            (SELECT COUNT(run) run run, run_drop_unit run_drop_unit WHERE $query_where AND run.id = run_drop_unit.run AND player = '" . get_context()->get_player()->get_id() . "') AS unit;
+        ";
+        $q = get_context()->get_db()->query($s);
+        $r = $q->fetchArray(SQLITE3_ASSOC);
+        $this->drop_type["rune"] = $r["rune"];
+        $this->drop_type["rune_craft"] = $r["rune_craft"];
+        $this->drop_type["item"] = $r["item"];
+        $this->drop_type["sd"] = $r["sd"];
+        $this->drop_type["shapeshifting"] = $r["shapeshifting"];
+        $this->drop_type["unit"] = $r["unit"];
+
+        // Rune drop rate by slot
+        $s = "
+          SELECT 
+            slot,
+            count(run.id) AS count
+          FROM
+            run run,
+            run_drop_rune run_drop_rune
+          WHERE
+            $query_where AND 
+            run.id = run_drop_rune.run
+          GROUP BY slot
+          ORDER BY slot;
+        ";
             $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $this->drop_rune_quality[strval($r["quality"])] = $r["count"];
-            }
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            $this->drop_rune_slot[$r["slot"]] = $r["count"];
         }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            $this->filters = FILTER::STATS;
-            if (isset($_GET["area_type"]) && intval($_GET["area_type"]) > 0){
-                $this->filters["AREA_TYPE"] = $_GET["area_type"];
-            }
-            if (isset($_GET["area"]) && intval($_GET["area"]) > 0){
-                $this->filters["AREA"] = $_GET["area"];
-            }
-            if (isset($_GET["stage"]) && intval($_GET["stage"]) > 0){
-                $this->filters["STAGE"] = $_GET["stage"];
-            }
-            if (isset($_GET["difficulty"]) && intval($_GET["difficulty"]) >= DIFFICULTY_ID::NORMAL && intval($_GET["difficulty"]) <= DIFFICULTY_ID::HELL){
-                $this->filters["DIFFICULTY"] = $_GET["difficulty"];
-            }
-            if (isset($_GET["include_helper"]) && $_GET["include_helper"] == "on"){
-                $this->filters["INCLUDE_HELPER"] = true;
-            }
-            else{
-                $this->filters["INCLUDE_HELPER"] = false;
-            }
-            return;
+        // Rune drop rate by slot
+        $s = "
+          SELECT 
+            stars,
+            count(run.id) AS count
+          FROM
+            run run,
+            run_drop_rune run_drop_rune
+          WHERE
+            $query_where AND 
+            run.id = run_drop_rune.run
+          GROUP BY stars
+          ORDER BY stars DESC;
+        ";
+        $q = get_context()->get_db()->query($s);
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            $this->drop_rune_stars[strval($r["stars"])] = $r["count"];
+        }
+
+        // Rune drop rate by quality
+        $s = "
+          SELECT 
+            quality,
+            count(run.id) AS count
+          FROM
+            run run,
+            run_drop_rune run_drop_rune
+          WHERE
+            $query_where AND 
+            run.id = run_drop_rune.run
+          GROUP BY quality
+          ORDER BY quality DESC;
+        ";
+        $q = get_context()->get_db()->query($s);
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            $this->drop_rune_quality[strval($r["quality"])] = $r["count"];
+        }
+    }
+
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        $this->filters = FILTER::STATS;
+        if (isset($_GET["area_type"]) && intval($_GET["area_type"]) > 0){
+            $this->filters["AREA_TYPE"] = $_GET["area_type"];
+        }
+        if (isset($_GET["area"]) && intval($_GET["area"]) > 0){
+            $this->filters["AREA"] = $_GET["area"];
+        }
+        if (isset($_GET["stage"]) && intval($_GET["stage"]) > 0){
+            $this->filters["STAGE"] = $_GET["stage"];
+        }
+        if (isset($_GET["difficulty"]) && intval($_GET["difficulty"]) >= DIFFICULTY_ID::NORMAL && intval($_GET["difficulty"]) <= DIFFICULTY_ID::HELL){
+            $this->filters["DIFFICULTY"] = $_GET["difficulty"];
+        }
+        if (isset($_GET["include_helper"]) && $_GET["include_helper"] == "on"){
+            $this->filters["INCLUDE_HELPER"] = true;
+        }
+        else{
+            $this->filters["INCLUDE_HELPER"] = false;
         }
+        return;
     }
-?>
+}

+ 136 - 82
application/page/Teams_Page.php

@@ -1,101 +1,155 @@
  <?php
+/**
+ * Team list page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Team.php");
+
+/**
+ * Team list page model.
+ *
+ * @category Page
+ */
+class Teams_Page extends Page{
+
     /**
-     * Team list page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Team[] Teams to show.
      */
+    private $teams = [];
 
     /**
-     * Require dependent files if not present.
+     * @var Unit[] List of all units for team creation.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Team.php");
+    private $units = [];
+    
+    /**
+     * @var mixed[] Page filters
+     */
+    private $filters = [
+        "NAME" => "",
+        "AREA" => null
+    ];
 
     /**
-     * Team list page model.
+     * Constructor.
      *
-     * @category Page
+     * Retrieves the data and initializes the variables.
      */
-    class Teams_Page extends Page{
-
-        /**
-         * @var Team[] Teams to show.
-         */
-        public $teams = [];
+    public function __construct(){
+        $this->view = PATH::VIEW . "teams.php";
+        $this->title = "Teams - SWDB";
+        $this->description = "Teams";
+        $this->canonical = URL::BASE . "teams/";
 
-        /**
-         * @var Unit[] List of all units for team creation.
-         */
-        public $units = [];
+        $this->parse_filters();
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->teams, new Team($result["id"]));
+        }
+        $statement = get_context()->get_db()->prepare("
+          SELECT id
+          FROM unit
+          WHERE player = :player;
+        ");
 
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "teams.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->teams, new Team($r["id"]));
-            }
-            $statement = get_context()->get_db()->prepare("
-              SELECT id
-              FROM unit
-              WHERE player = :player;
-            ");
-            $statement->bindValue(':player', get_context()->get_player()->get_id(), SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->units, new Unit($r["id"], false));
-            }
-            $this->title = "Teams - SWDB";
-            $this->description = "Teams";
-            $this->canonical = URL::BASE . "teams/";
+        // Get all player units, for the team creation combos.
+        $statement->bindValue(':player', get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $result_set = $statement->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->units, new Unit($result["id"], false));
         }
+    }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            $this->filters = FILTER::TEAM;
-            if (isset($_GET["area"]) && APPLICATION::valid_id("AREA_TYPE_ID", $_GET["area"])){
-                $this->filters["AREA"] = $_GET["area"];
-            }
-            if (isset($_GET["name"]) && strlen($_GET["name"]) > 0){
-                $this->filters["NAME"] = SQLite3::escapeString($_GET["name"]);
-            }
-            return;
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        if (isset($_GET["area"]) && APPLICATION::valid_id("AREA_TYPE_ID", $_GET["area"])){
+            $this->filters["AREA"] = $_GET["area"];
+        }
+        if (isset($_GET["name"]) && strlen($_GET["name"]) > 0){
+            $this->filters["NAME"] = SQLite3::escapeString($_GET["name"]);
         }
+        return;
+    }
+
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
 
-        /**
-         * Builds the query to the rune table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-              SELECT id
-              FROM team
-              WHERE player = '" . get_context()->get_player()->get_id() . "'
-              ORDER BY
-                area_type,
-                area
-            ";
-            if (APPLICATION::valid_id("AREA_ID", $this->filters["AREA"])){
-                $s = $s . " AND area  = '" . strtoupper($this->filters["AREA"]) . "') ";
-            }
-            if ($this->filters["NAME"] != ""){
-                $s = $s . " AND upper(name) LIKE '%" . strtoupper($this->filters["NAME"]) . "%' ";
-            }
-            return $s;
+        // Common items
+        $query = "
+          SELECT id
+          FROM team
+          WHERE player = :player
+        ";
+          
+        if (APPLICATION::valid_id("AREA_TYPE_ID", $this->filters["AREA"])){
+            $query .= " AND area_type  = :area ";
         }
+        if ($this->filters["NAME"] != ""){
+            $query .= " AND upper(name) LIKE :name ";
+        }
+        $query .= " ORDER BY area_type, area;";
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":area", $this->filters["AREA"], SQLITE3_INTEGER);
+        $statement->bindValue(":name", "%" . $this->filters["NAME"] . "%", SQLITE3_TEXT);
+        return $statement;
+    }
 
+    /**
+     * Retrieves the teams to show.
+     *
+     * @return Team[] Selected teams.
+     */
+    public function get_teams(){
+        return $this->teams;
+    }
+
+    /**
+     * Retrieves $all of the player units.
+     *
+     * @return Unit Player units. 
+     */
+    public function get_units(){
+        return $this->units;
+    }
+    
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+    
+    /**
+     * Retrieves one filter.
+     *
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
+        }
     }
-?>
+
+
+}

+ 40 - 33
application/page/Unit_Page.php

@@ -1,44 +1,51 @@
  <?php
+/**
+ * Unit view page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Unit.php");
+
+/**
+ * Unit view page model.
+ *
+ * @category Page
+ */
+class Unit_Page extends Page{
+
     /**
-     * Unit view page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Unit Selected Unit.
      */
+    private $unit;
 
     /**
-     * Require dependent files if not present.
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     *
+     * @param string $id Selected unit id
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Unit.php");
+    public function __construct($id){
+        $this->view = PATH::VIEW . "unit.php";
+        $this->unit = new Unit($id, true);
+        $this->title = $this->unit->get_title() ." - SWDB";
+        $this->description = "Owned " . $this->unit->get_title();
+        $this->canonical = URL::BASE . "monster/" . $id;
+    }
 
     /**
-     * Unit view page model.
+     * Retrieves the selected unit.
      *
-     * @category Page
+     * @return Unit Selected unit.
      */
-    class Unit_Page extends Page{
-
-        /**
-         * @var Unit Selected Unit.
-         */
-        public $unit;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         *
-         * @param string $id Selected unit id
-         */
-        public function __construct($id){
-            $this->view = PATH::VIEW . "unit.php";
-            $this->unit = new Unit($id, true);
-            $this->title = $this->unit->get_title() ." - SWDB";
-            $this->description = "Owned " . $this->unit->get_title();
-            $this->canonical = URL::BASE . "monster/" . $id;
-        }
-
+    public function get_unit(){
+        return $this->unit;
     }
-?>
+
+}

+ 225 - 167
application/page/Units_Page.php

@@ -1,189 +1,247 @@
  <?php
+/**
+ * Unit list page file.
+ *
+ * Provides a class with all the properties and methods to display the page.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::PAGE . "Page.php");
+require_once(PATH::ENTITY . "Unit.php");
+require_once(PATH::ENTITY . "Effect.php");
+
+/**
+ * Unit list page model.
+ *
+ * @category Page
+ */
+class Units_Page extends Page{
+
     /**
-     * Unit list page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
+     * @var Unit[] Units to show.
      */
+    private $units = [];
 
     /**
-     * Require dependent files if not present.
+     * @var mixed[] Default filter values.
      */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Unit.php");
-    require_once(PATH::ENTITY . "Effect.php");
+    private $filters = [
+        "ELEMENT" => -1,
+        "NAME" => "",
+        "MIN_STARS" => 1,
+        "MAX_STARS" => 6,
+        "IN_STORAGE" => false,
+        "WITHOUT_RUNES" => false,
+        "EFFECT" => [],
+        "EFFECT_OPTION" => "any"
+    ];
 
     /**
-     * Unit list page model.
-     *
-     * @category Page
+     * @var Effect[] All availabe skill effects, for the filter selector.
      */
-    class Units_Page extends Page{
-
-        /**
-         * @var Unit[] Units to show.
-         */
-        public $units = [];
+    private $effects = [];
 
-        /**
-         * @var mixed[] Default filter values.
-         */
-        public $filters = [
-            "ELEMENT" => -1,
-            "NAME" => "",
-            "MIN_STARS" => 1,
-            "MAX_STARS" => 6,
-            "IN_STORAGE" => false,
-            "WITHOUT_RUNES" => false,
-            "EFFECT" => [],
-            "EFFECT_OPTION" => "any"
-        ];
-
-        /**
-         * @var Effect[] All availabe skill effects, for the tfilter selector.
-         */
-        public $effects = [];
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     */
+    public function __construct(){
+        $this->view = PATH::VIEW . "units.php";
+        $this->title = "Units - SWDB";
+        $this->description = "Owned units";
+        $this->canonical = URL::BASE . "units/";
 
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         */
-        public function __construct(){
-            $this->view = PATH::VIEW . "units.php";
-            $this->parse_filters();
-            $s = $this->build_query();
-            $q = get_context()->get_db()->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->units, new Unit($r["id"]));
-            }
-            // Get skill effects
-            $s_eff = "SELECT id FROM effect ORDER BY is_buff DESC";
-            $q_eff = get_context()->get_db()->query($s_eff);
-            while ($r_eff = $q_eff->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->effects, new Effect($r_eff["id"]));
-            }
-            $this->title = "Units - SWDB";
-            $this->description = "Owned units";
-            $this->canonical = URL::BASE . "units/";
+        $this->parse_filters();
+        $result_set = $this->prepare_statement()->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->units, new Unit($result["id"]));
         }
+        
+        // Get skill effects
+        $s_eff = "SELECT id FROM effect ORDER BY is_buff DESC";
+        $q_eff = get_context()->get_db()->query($s_eff);
+        while ($r_eff = $q_eff->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->effects, new Effect($r_eff["id"]));
+        }
+        
+    }
 
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            if (isset($_GET["element"]) && APPLICATION::valid_id("ELEMENT_ID", strtoupper($_GET["element"]))){
-                $this->filters["ELEMENT"] = $_GET["element"];
-            }
-            if (isset($_GET["name"]) && strlen($_GET["name"]) > 0){
-                $this->filters["NAME"] = SQLite3::escapeString($_GET["name"]);
-            }
-            if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) <= 6){
-                $this->filters["MIN_STARS"] = $_GET["min_stars"];
-            }
-            if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) <= 6){
-                $this->filters["MAX_STARS"] = $_GET["max_stars"];
-            }
-            if (isset($_GET["in_storage"]) && $_GET["in_storage"] == "on"){
-                $this->filters["IN_STORAGE"] = true;
-            }
-            else{
-                $this->filters["IN_STORAGE"] = false;
-            }
-            if (isset($_GET["without_runes"]) && $_GET["without_runes"] == "on"){
-                $this->filters["WITHOUT_RUNES"] = true;
-            }
-            if (isset($_GET["effect"])){
-                $effects = $_GET["effect"];
-                foreach ($effects as $effect){
-                    if (intval($effect) > 0){
-                        array_push($this->filters["EFFECT"], intval($effect));
-                    }
+    /**
+     * Parses the request looking for the selected filters, validates them
+     * and adds them to the $filters array.
+     */
+    private function parse_filters(){
+        if (isset($_GET["element"]) && APPLICATION::valid_id("ELEMENT_ID", strtoupper($_GET["element"]))){
+            $this->filters["ELEMENT"] = $_GET["element"];
+        }
+        if (isset($_GET["name"]) && strlen($_GET["name"]) > 0){
+            $this->filters["NAME"] = SQLite3::escapeString($_GET["name"]);
+        }
+        if (isset($_GET["min_stars"]) && intval($_GET["min_stars"]) > 0 && intval($_GET["min_stars"]) <= 6){
+            $this->filters["MIN_STARS"] = $_GET["min_stars"];
+        }
+        if (isset($_GET["max_stars"]) && intval($_GET["max_stars"]) > 0 && intval($_GET["max_stars"]) <= 6){
+            $this->filters["MAX_STARS"] = $_GET["max_stars"];
+        }
+        if (isset($_GET["in_storage"]) && $_GET["in_storage"] == "on"){
+            $this->filters["IN_STORAGE"] = true;
+        }
+        else{
+            $this->filters["IN_STORAGE"] = false;
+        }
+        if (isset($_GET["without_runes"]) && $_GET["without_runes"] == "on"){
+            $this->filters["WITHOUT_RUNES"] = true;
+        }
+        if (isset($_GET["effect"])){
+            $effects = $_GET["effect"];
+            foreach ($effects as $effect){
+                if (intval($effect) > 0){
+                    array_push($this->filters["EFFECT"], intval($effect));
                 }
             }
-            if (isset($_GET["effect_option"]) && ($_GET["effect_option"] == "and" || $_GET["effect_option"] == "or")){
-                $this->filters["EFFECT_OPTION"] = $_GET["effect_option"];
-            }
-            return;
         }
+        if (isset($_GET["effect_option"]) && ($_GET["effect_option"] == "and" || $_GET["effect_option"] == "or")){
+            $this->filters["EFFECT_OPTION"] = $_GET["effect_option"];
+        }
+        return;
+    }
 
-        /**
-         * Builds the query to the rune table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s = "
-                SELECT unit.id AS id
-                FROM
-                  unit,
-                  monster
-                WHERE
-                  unit.player = '" . get_context()->get_player()->get_id() . "' AND
-                  unit.monster = monster.id AND 
-                  stars >= " . $this->filters["MIN_STARS"] . " AND 
-                  stars <= " . $this->filters["MAX_STARS"];
-            if (APPLICATION::valid_id("ELEMENT_ID", $this->filters["ELEMENT"])){
-                $s = $s . " AND monster IN (SELECT id FROM monster WHERE element = " . $this->filters["ELEMENT"] . ") ";
-            }
-            if ($this->filters["NAME"] != ""){
-                $s = $s . " AND monster IN (SELECT id FROM monster WHERE upper(name) LIKE '%" . strtoupper($this->filters["NAME"]) . "%') ";
-            }
-            if (!$this->filters["IN_STORAGE"]){
-                $s = $s . " AND building NOT IN (SELECT id FROM building WHERE building = " . BUILDING_ID::MONSTER_STORAGE . ") ";
-            }
-            if (!$this->filters["WITHOUT_RUNES"]){
-                $s = $s . " AND unit.id IN (SELECT DISTINCT unit FROM unit_rune) ";
-            }
-            if (sizeof($this->filters["EFFECT"]) > 0){
-                if ($this->filters["EFFECT_OPTION"] == "and"){
-                    foreach ($this->filters["EFFECT"] as $effect){
-                        $s .= "
-                        AND monster.id IN (
-                          SELECT DISTINCT unit
-                          FROM
-                            monster_skill,
-                            skill_effect
-                          WHERE
-                            monster_skill.skill = skill_effect.skill AND
-                            skill_effect.effect = $effect
-                        )
-                        ";
-                    }
+    /**
+     * Prepares the statement to execute against the database using the filter values.
+     *
+     * @return SQLite3Stmt prepared statement.
+     */
+    private function prepare_statement(){
+        
+        // Common items
+        $query = "
+            SELECT unit.id AS id
+            FROM
+              unit,
+              monster
+            WHERE
+              unit.player = :player AND
+              unit.monster = monster.id AND 
+              unit.stars BETWEEN :min_stars AND :max_stars
+        ";
+        if (APPLICATION::valid_id("ELEMENT_ID", $this->filters["ELEMENT"])){
+            $query .= " AND monster.element = :element ";
+        }
+        if ($this->filters["NAME"] != ""){
+            $query .= " AND upper(monster.name) LIKE upper(:name) ";
+        }
+        if (! $this->filters["IN_STORAGE"]){
+            $query .= " AND unit.building <> :storage_building ";
+        }
+        if (!$this->filters["WITHOUT_RUNES"]){
+            $query .= " AND unit.id IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = :rta) ";
+        }
+        if (sizeof($this->filters["EFFECT"]) > 0){
+            if ($this->filters["EFFECT_OPTION"] == "and"){
+                for ($i = 0; $i < sizeof($this->filters["EFFECT"]); $i ++){
+                    $query .= "
+                    AND monster.id IN (
+                      SELECT DISTINCT monster
+                      FROM
+                        monster_skill,
+                        skill_effect
+                      WHERE
+                        monster_skill.skill = skill_effect.skill AND
+                        skill_effect.effect = :effect_$i
+                      )
+                    ";
                 }
-                elseif ($this->filters["EFFECT_OPTION"] == "or"){
-                    $s .= " AND ( ";
-                    foreach ($this->filters["EFFECT"] as $effect){
-                        $s .= "
-                        monster.id IN (
-                          SELECT DISTINCT unit
-                          FROM
-                            monster_skill,
-                            skill_effect
-                          WHERE
-                            monster_skill.skill = skill_effect.skill AND
-                            skill_effect.effect = $effect
-                        ) OR
-                        ";
-                    }
-                    $s .= " 1 = 2 ) ";
+            }
+            elseif ($this->filters["EFFECT_OPTION"] == "or"){
+                $query .= " AND ( ";
+                for ($i = 0; $i < sizeof($this->filters["EFFECT"]); $i ++){
+                    $query .= "
+                    monster.id IN (
+                      SELECT DISTINCT monster
+                      FROM
+                        monster_skill,
+                        skill_effect
+                      WHERE
+                        monster_skill.skill = skill_effect.skill AND
+                        skill_effect.effect = :effect_$i
+                    ) OR ";
                 }
+                $query = rtrim($query, " OR ") . ") ";
             }
-            $s = $s . "
-                ORDER BY
-                  stars DESC,
-                  level DESC,
-                  element = " . ELEMENT_ID::FIRE ." DESC,
-                  element = " . ELEMENT_ID::WATER ." DESC,
-                  element = " . ELEMENT_ID::WIND ." DESC,
-                  element = " . ELEMENT_ID::LIGHT ." DESC,
-                  element = " . ELEMENT_ID::DARK ." DESC
-            ";
-            return $s;
         }
-
+        $query .= "
+            ORDER BY
+              stars DESC,
+              level DESC,
+              element = :fire DESC,
+              element = :water DESC,
+              element = :wind DESC,
+              element = :light DESC,
+              element = :dark DESC
+        ";
+        $statement = get_context()->get_db()->prepare($query);
+        $statement->bindValue(":player", get_context()->get_player()->get_id(), SQLITE3_TEXT);
+        $statement->bindValue(":min_stars", $this->filters["MIN_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":max_stars", $this->filters["MAX_STARS"], SQLITE3_INTEGER);
+        $statement->bindValue(":element", $this->filters["ELEMENT"], SQLITE3_INTEGER);
+        $statement->bindValue(":name", "%" . $this->filters["NAME"] . "%", SQLITE3_TEXT);
+        $statement->bindValue(":storage_building", BUILDING_ID::MONSTER_STORAGE, SQLITE3_INTEGER);
+        $statement->bindValue(":rta", get_context()->get_game_mode(), SQLITE3_INTEGER);
+        for ($i = 0; $i < sizeof($this->filters["EFFECT"]); $i ++){
+            $statement->bindValue(":effect_$i", $this->filters["EFFECT"][$i], SQLITE3_INTEGER);
+        }
+        $statement->bindValue(":fire", ELEMENT_ID::FIRE, SQLITE3_INTEGER);
+        $statement->bindValue(":water", ELEMENT_ID::WATER, SQLITE3_INTEGER);
+        $statement->bindValue(":wind", ELEMENT_ID::WIND, SQLITE3_INTEGER);
+        $statement->bindValue(":light", ELEMENT_ID::LIGHT, SQLITE3_INTEGER);
+        $statement->bindValue(":dark", ELEMENT_ID::DARK, SQLITE3_INTEGER);
+        return $statement;
     }
-?>
+    
+    /**
+     * Retrieves the page filters.
+     *
+     * @return mixed[] Page filtes
+     */
+    public function get_filters(){
+        return $this->filters;
+    }
+    
+    /**
+     * Retrieves one filter.
+     *
+     * @param string $key
+     * @return mixed Filter value, null if if doesn't exist.
+     */
+    public function get_filter($key){
+        if (array_key_exists($key, $this->filters)){
+            return $this->filters[$key];
+        }
+        else{
+            return null;
+        }
+    }
+    
+    /**
+     * Retrieves the selection of units.
+     *
+     * @return Unit[] Unit to show on the page.
+     */
+    public function get_units(){
+        return $this->units;
+    }
+    
+    /**
+     * Retrieves all existing skill effects.
+     *
+     * @return Effect[] Every skill effects.
+     */
+    public function get_effects(){
+        return $this->effects;
+    }
+
+}

+ 38 - 36
application/view/artifacts.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Artifacts view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Artifacts_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Artifacts view.
+ *
+ * Contains the view layout and code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Artifacts_Page $page The page model.
+ * @var Artifacts_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>artifacts.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -70,7 +72,7 @@
                                 foreach($reflect->getConstants() as $name => $id){
                                     if ($id != ELEMENT_ID::PURE){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["ELEMENT"])){
+                                        if (in_array($id, $page->get_filter("ELEMENT"))){
                                             $selected = "selected='selected'";
                                         }
 ?>
@@ -93,7 +95,7 @@
                                 foreach($reflect->getConstants() as $name => $id){
                                     if ($id != ARCHETYPE_ID::NONE && $id != ARCHETYPE_ID::MATERIAL){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["ARCHETYPE"])){
+                                        if (in_array($id, $page->get_filter("ARCHETYPE"))){
                                             $selected = "selected='selected'";
                                         }
 ?>
@@ -115,7 +117,7 @@
                                 $reflect = new ReflectionClass("ARTIFACT_STAT_ID");
                                 foreach($reflect->getConstants() as $name => $id){
                                     $selected = "";
-                                    if (in_array($id, $page->filters["MAIN"])){
+                                    if (in_array($id, $page->get_filter("MAIN"))){
                                         $selected = "selected='selected'";
                                     }
 ?>
@@ -131,9 +133,9 @@
                             Level:
                         </td>
                         <td>
-                            <input type='number' name='min_level' id='filter_level_min' min='0' max='15' value='<?=$page->filters["MIN_LEVEL"]?>'/>
+                            <input type='number' name='min_level' id='filter_level_min' min='0' max='15' value='<?=$page->get_filter("MIN_LEVEL")?>'/>
                             -
-                            <input type='number' name='max_level' id='filter_level_max' min='0' max='15' value='<?=$page->filters["MAX_LEVEL"]?>'/>
+                            <input type='number' name='max_level' id='filter_level_max' min='0' max='15' value='<?=$page->get_filter("MAX_LEVEL")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -143,7 +145,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MIN_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MIN_QUALITY") - 1] = "selected";
 ?>
                             <select name='min_quality' id='filter_quality_min'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -155,7 +157,7 @@
                             -
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MAX_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MAX_QUALITY") - 1] = "selected";
 ?>
                             <select name='max_quality' id='filter_quality_max'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -173,7 +175,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MIN_ORIGINAL_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MIN_ORIGINAL_QUALITY") - 1] = "selected";
 ?>
                             <select name='min_original_quality' id='filter_original_quality_min'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -185,7 +187,7 @@
                             -
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MAX_ORIGINAL_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MAX_ORIGINAL_QUALITY") - 1] = "selected";
 ?>
                             <select name='max_original_quality' id='filter_original_quality_max'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -203,7 +205,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["ASSIGNED"]] = "selected";
+                            $selected[$page->get_filter("ASSIGNED")] = "selected";
 ?>
                             <select name='assigned' id='filter_assigned'>
                                 <option value='0' <?=$selected[0]?>>All</option>
@@ -231,7 +233,7 @@
                     $group = "";
                     $group_title = "";
                     $group_image = "";
-                    foreach ($page->artifacts as $artifact){
+                    foreach ($page->get_artifacts() as $artifact){
                         $group = $artifact->get_type() . "-" . $artifact->get_element() . "-" . $artifact->get_archetype();
                         if ($prev_group != $group){
                             switch ($artifact->get_type()){

+ 40 - 45
application/view/enchantments.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Artifacts view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Artifacts_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Artifacts view.
+ *
+ * Contains the view layout and code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Artifacts_Page $page The page model.
+ * @var Artifacts_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>enchantments.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
             /**
@@ -104,14 +106,14 @@
                             <select multiple name='type[]' id='filter_type'>
 <?php
                                 $selected = "";
-                                if (in_array("GRI", $page->filters["TYPE"])){
+                                if (in_array("GRI", $page->get_filter("TYPE"))){
                                     $selected = "selected='selected'";
                                 }
 ?>
                                 <option value='GRI' <?=$selected?>>Grindstone</option>
 <?php
                                 $selected = "";
-                                if (in_array("GEM", $page->filters["TYPE"])){
+                                if (in_array("GEM", $page->get_filter("TYPE"))){
                                     $selected = "selected='selected'";
                                 }
 ?>
@@ -126,7 +128,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MIN_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MIN_QUALITY") - 1] = "selected";
 ?>
                             <select name='min_quality' id='filter_quality_min'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -138,7 +140,7 @@
                             -
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MAX_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MAX_QUALITY") - 1] = "selected";
 ?>
                             <select name='max_quality' id='filter_quality_max'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -156,20 +158,13 @@
                         <td class='rune'>
                             <div>
                                 <select multiple name='rune[]' id='filter_rune'>
-<?php
-                                    $selected = "";
-                                    if (in_array(0, $page->filters["RUNE"])){
-                                        $selected = "selected='selected'";
-                                    }
-?>
-                                    <option value='0' <?=$selected?>>Inmemorial</option>
 <?php
                                     $reflect = new ReflectionClass("RUNE_SET_ID");
-                                    $i = 1;
+                                    $i = 0;
                                     $j = 1;
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["TYPE"])){
+                                        if (in_array($id, $page->get_filter("RUNE"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(strtolower($name));
@@ -205,7 +200,7 @@
                                     $j = 1;
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["SUB"])){
+                                        if (in_array($id, $page->get_filter("STAT"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(str_replace("_P", "%", $name));
@@ -242,16 +237,16 @@
                     $group = "";
                     $group_title = "";
                     $group_image = "";
-                    foreach ($page->grindstones as $grindstone){
-                        $group = ($grindstone->is_inmemorial() ? "I" : $grindstone->get_rune_set()->get_id()) . "-" . $grindstone->is_inmemorial();
+                    foreach ($page->get_enchantments() as $enchantment){
+                        $group = ($enchantment->is_inmemorial() ? "I" : $enchantment->get_rune_set()->get_id()) . "-" . $enchantment->is_inmemorial();
                         if ($prev_group != $group){
-                            if ($grindstone->is_inmemorial()){
+                            if ($enchantment->is_inmemorial()){
                                 $group_title = "Inmemorial";
                                 $group_image = URL::IMG["ICON"] . "star.png";
                             }
                             else{
-                                $group_title = $grindstone->get_rune_set()->get_name();
-                                $group_image = URL::IMG["RUNE"] . str_pad($grindstone->get_rune_set()->get_id(), 2, '0', STR_PAD_LEFT) . ".png";
+                                $group_title = $enchantment->get_rune_set()->get_name();
+                                $group_image = URL::IMG["RUNE"] . str_pad($enchantment->get_rune_set()->get_id(), 2, '0', STR_PAD_LEFT) . ".png";
                             }
                             if ($prev_group == ""){
 ?>
@@ -280,7 +275,7 @@
 <?php
                         }
 ?>
-                        <?=HTML::enchantment_panel($grindstone)?>
+                        <?=HTML::enchantment_panel($enchantment)?>
 <?php
                     }
 ?>

+ 15 - 12
application/view/error.php

@@ -1,21 +1,24 @@
 <?php
-    /**
-     * Error view.
-     *
-     * Contains the view layout and some code to present the data.
-     *
-     * @category View
-     * @var Landing_Page $page The page model.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Error view.
+ *
+ * Contains the view layout and some code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Error_Page $page The page model.
+ * @var Error_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -41,7 +44,7 @@
                     Error
                 </h2>
                 <article>
-                    Error <?=$page->code?>: <?=$page->description?>
+                    Error <?=$page->get_code()?>: <?=$page->get_message()?>
                 </article>
             </section> <!-- #catalog -->
         </main>

+ 30 - 27
application/view/guild.php

@@ -4,9 +4,12 @@
  *
  * Contains the view layout and some code to present the data.
  *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  * @category View
+ * @property Guild_Page $page The page model.
  * @var Guild_Page $page The page model.
- * @var int get_context()->get_game_mode() Game mode.
  */
 ?>
 <!DOCTYPE html>
@@ -14,8 +17,8 @@
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -27,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>guild.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -51,7 +54,7 @@
 ?>
         <aside>
 <?php
-            if (!isset($page->guild)){
+            if (! $page->in_guild()){
 ?>
                 <h2>
                     Guild
@@ -64,19 +67,19 @@
             else{
 ?>
                 <h2>
-                    <?=$page->guild->get_name()?>
+                    <?=$page->get_guild()->get_name()?>
                 </h2>
                 <span id='guild_level'>
-                    Lv. <?=$page->guild->get_level()?>
+                    Lv. <?=$page->get_guild()->get_level()?>
                 </span>
                 <span id='guild_experience'>
-                    (Exp: <?=$page->guild->get_experience()?>)
+                    (Exp: <?=$page->get_guild()->get_experience()?>)
                 </span>
                 <p id='guild_comment'>
-                    <?=$page->guild->get_comment()?>
+                    <?=$page->get_guild()->get_comment()?>
                 </p>
                 <p id='guild_notice'>
-                    <?=$page->guild->get_notice()?>
+                    <?=$page->get_guild()->get_notice()?>
                 </p>
 <?php
             }
@@ -84,7 +87,7 @@
         </aside>
         <main>
 <?php
-            if (!isset($page->guild)){
+            if (! $page->in_guild()){
 ?>
                 <section id='no_guild'>
                     <h2>
@@ -98,12 +101,12 @@
 ?>
                 <section id='guild_info' class='content'>
                     <h2>
-                        <?=$page->guild->get_name()?>
+                        <?=$page->get_guild()->get_name()?>
                     </h2>
                     <div id='guild_details'>
                         <div id='guild_skills'>
 <?php
-                            foreach ($page->skill_groups as $group){
+                            foreach ($page->get_skill_groups() as $group){
 ?>
                                 <div class='skill_group'>
                                     <span class='skill_group_title'>
@@ -117,7 +120,7 @@
                                         <ul>
 <?php
                                             foreach ($group->get_skills() as $skill){
-                                                if ($skill->get_level() > $page->guild->get_level()){
+                                                if ($skill->get_level() > $page->get_guild()->get_level()){
                                                     $unavailable = "unavailable";
                                                 }
                                                 else{
@@ -164,7 +167,7 @@
                         </tr>
 <?php
                         $odd = "";
-                        foreach ($page->guild->get_members() as $member){
+                        foreach ($page->get_guild()->get_members() as $member){
 ?>
                             <tr>
                                 <td class='grade <?=$odd?>'>

+ 15 - 15
application/view/help.php

@@ -15,8 +15,8 @@
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +28,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>help.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>

+ 52 - 30
application/view/home.php

@@ -1,23 +1,24 @@
 <?php
-    /**
-     * Home view.
-     *
-     * Contains the view layout and some code to present the data.
-     *
-     * @category View
-     * @var Home_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int[] $EFFECT_AREA Required constants.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Home view.
+ *
+ * Contains the view layout and some code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Home_Page $page The page model.
+ * @var Home_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -29,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>home.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -134,7 +135,14 @@
                                         <?=HTML::unit_panel($defense)?>
                                     </div>
 <?php
-                                    if ($first && null != $defense->get_monster()->get_leader_skill() && ($defense->get_monster()->get_leader_skill()->get_area() == $EFFECT_AREA["GENERAL"] || $defense->unit->leader_skill->area == $EFFECT_AREA["ARENA"])){
+                                    if (
+                                      $first && 
+                                      null != $defense->get_monster()->get_leader_skill() &&
+                                      (
+                                        $defense->get_monster()->get_leader_skill()->get_area() == EFFECT_AREA_ID::GENERAL ||
+                                        $defense->get_monster()->get_leader_skill()->get_area() == EFFECT_AREA_ID::ARENA
+                                      )
+                                    ){
 ?>
                                         <div class='skill'>
                                             <img class='skill_img' title='<?=$defense->get_monster()->get_leader_skill()->get_description()?>' src='<?=$defense->get_monster()->get_leader_skill()->get_image()?>'/>
@@ -158,7 +166,14 @@
                                         <?=HTML::unit_panel($defense)?>
                                     </div>
 <?php
-                                    if ($first && null != $defense->get_monster()->get_leader_skill() && ($defense->get_monster()->get_leader_skill()->get_area() == $EFFECT_AREA["GENERAL"] || $defense->unit->leader_skill->area == $EFFECT_AREA["ARENA"])){
+                                    if (
+                                      $first &&
+                                      null != $defense->get_monster()->get_leader_skill() &&
+                                      (
+                                        $defense->get_monster()->get_leader_skill()->get_area() == EFFECT_AREA_ID::GENERAL ||
+                                        $defense->get_monster()->get_leader_skill()->get_area() == EFFECT_AREA_ID::GUILD
+                                      )
+                                    ){
 ?>
                                         <div class='skill'>
                                             <img class='skill_img' title='<?=$defense->get_monster()->get_leader_skill()->get_description()?>' src='<?=$defense->get_monster()->get_leader_skill()->get_image()?>'/>
@@ -169,7 +184,7 @@
                                 }
 ?>
                                 <hr/>
-                        <?php
+<?php
                                 $first = true;
                                 // TODO: Watch if null
                                 foreach (get_context()->get_player()->get_gw_defense()[1] as $defense){
@@ -179,7 +194,14 @@
                                     </div>
 <?php
                                         // TODO: Guild content, not arena.
-                                        if ($first && null != $defense->get_monster()->get_leader_skill() && ($defense->get_monster()->get_leader_skill()->get_area() == $EFFECT_AREA["GENERAL"] || $defense->get_monster()->get_leader_skill()->get_area() == $EFFECT_AREA["ARENA"])){
+                                        if (
+                                          $first &&
+                                          null != $defense->get_monster()->get_leader_skill() &&
+                                          (
+                                            $defense->get_monster()->get_leader_skill()->get_area() == EFFECT_AREA_ID::GENERAL ||
+                                            $defense->get_monster()->get_leader_skill()->get_area() == EFFECT_AREA_ID::GUILD
+                                          )
+                                        ){
 ?>
                                         <div class='skill'>
                                             <img class='skill_img' title='<?=$defense->get_monster()->get_leader_skill()->get_description()?>' src='<?=$defense->get_monster()->get_leader_skill()->get_image()?>'/>

+ 28 - 24
application/view/landing.php

@@ -1,40 +1,44 @@
 <?php
-    /**
-     * Login view.
-     *
-     * Contains the view layout and some code to present the data.
-     *
-     * @category View
-     * @var Landing_Page $page The page model.
-     */
+/**
+ * Login view.
+ *
+ * Contains the view layout and some code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Landing_Page $page The page model.
+ * @var Landing_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>landing.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -78,7 +82,7 @@
                                 </td>
                             </tr>
 <?php
-                            if ($page->error_message != ""){
+                            if ($page->is_error()){
 ?>
                                 <tr>
                                     <td class='error' colspan='2'>

+ 52 - 48
application/view/monster.php

@@ -1,13 +1,16 @@
 <?php
-    /**
-     * Monster Page view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Monster_Page $page The page model.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Monster Page view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Monster_Page $page The page model.
+ * @var Monster_Page $page The page model.
+ */
 
 ?>
 <!DOCTYPE html>
@@ -15,8 +18,8 @@
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +31,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>monster_info.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -52,7 +55,7 @@
 ?>
         <aside>
             <h2>
-                <?=str_replace(" - SWDB", "", $page->title)?>
+                <?=str_replace(" - SWDB", "", $page->get_title())?>
             </h2>
             <p>
                 Monster info:
@@ -60,7 +63,7 @@
             <nav>
 <?php
                 $i = 0;
-                foreach ($page->monster as $monster){
+                foreach ($page->get_monsters() as $monster){
 ?>
                     <a href='#section_<?=$i?>'>
                         <div class='monster_panel'>
@@ -76,19 +79,20 @@
         <main>
 <?php
             for ($i = 0; $i < 3; $i ++){
-                if ($page->monster[$i] != null){
-                    $stats = $page->monster[$i]->get_stats();
+                $monster = $page->get_monsters()[$i];
+                if ($monster != null){
+                    $stats = $monster->get_stats();
 ?>
                     <section class='content' id='section_<?=$i?>'>
                         <h2>
-                            <?=$page->monster[$i]->get_title()?>
+                            <?=$monster->get_title()?>
                         </h2>
                         <article class='stage'>
                             <div class='profile'>
                                 <div class='monster_panel'>
-                                    <?=HTML::unit_panel($page->monster[$i])?>
+                                    <?=HTML::unit_panel($monster)?>
                                 </div>
-                                <?=HTML::unit_transformation_panel($page->monster[$i])?>
+                                <?=HTML::unit_transformation_panel($monster)?>
                             </div>
                             <table class='stats'>
                                 <tr>
@@ -96,7 +100,7 @@
                                         Type
                                     </th>
                                     <td>
-                                        <?=$page->monster[$i]->get_archetype_name()?>
+                                        <?=$monster->get_archetype_name()?>
                                     </td>
                                 </tr>
                                 <tr>
@@ -166,14 +170,14 @@
                             </table>
                             <div class='extra'>
 <?php
-                                if (count($page->monster[$i]->get_sources()) > 0){
+                                if (count($monster->get_sources()) > 0){
 ?>
                                     <!-- TODO NOT WORKING<div class='sources'>
                                         <span>
                                             Obtainable from:
                                         </span>
 <?php
-                                        foreach ($page->monster[$i]->get_sources() as $source){
+                                        foreach ($monster->get_sources() as $source){
 ?>
                                             <img title='<?=$source->get_name()?>' class='source' src='<?=$source->get_image()?>' />
 <?php
@@ -182,14 +186,14 @@
                                     </div>-->
 <?php
                                 }
-                                if (count($page->monster[$i]->get_essences()) > 0){
+                                if (count($monster->get_essences()) > 0){
 ?>
                                     <div class='essences'>
                                         <span>
                                             Awake with:
                                         </span>
 <?php
-                                        foreach ($page->monster[$i]->get_essences() as $essence){
+                                        foreach ($monster->get_essences() as $essence){
 ?>
                                         <div class='essence border_<?=explode(" ", $essence["item"]->get_name())[2]?>'>
                                                 <img alt='<?=$essence["item"]->get_name()?>' title='<?=$essence["amount"]?>x <?=$essence["item"]->get_name()?>' class='essence' src='<?=$essence["item"]->get_image()?>'/>
@@ -203,14 +207,14 @@
                                     </div>
 <?php
                                 }
-                                if (count($page->monster[$i]->get_sources()) > 0){
+                                if (count($monster->get_sources()) > 0){
 ?>
                                     <div class='sources'>
                                         <span>
                                             Obtainable from:
                                         </span>
 <?php
-                                        foreach ($page->monster[$i]->get_sources() as $source){
+                                        foreach ($monster->get_sources() as $source){
 ?>
                                             <?=HTML::source_panel($source)?>
 <?php
@@ -228,24 +232,24 @@
                                     </th>
                                 <tr/>
 <?php
-                                if ($page->monster[$i]->get_leader_skill()){
+                                if ($monster->get_leader_skill()){
 ?>
                                     <tr>
                                         <td class='skill_img'>
-                                            <img src='<?=$page->monster[$i]->get_leader_skill()->get_image()?>'/>
+                                            <img src='<?=$monster->get_leader_skill()->get_image()?>'/>
                                         </td>
                                         <td colspan='3' class='skill_text'>
                                             <h4>
                                                 Leader Skill
                                             </h4>
                                             <p>
-                                                <?=$page->monster[$i]->get_leader_skill()->get_description()?>
+                                                <?=$monster->get_leader_skill()->get_description()?>
                                             </p>
                                         </td>
                                     </tr>
 <?php
                                 }
-                                foreach ($page->monster[$i]->get_skills() as $skill){
+                                foreach ($monster->get_skills() as $skill){
 ?>
                                     <tr>
                                         <td class='skill_img'>
@@ -306,7 +310,7 @@
                             </table>
 
 <?php
-                            if ($page->monster[$i]->get_transformation() != null){
+                            if ($monster->get_transformation() != null){
 ?>
                                 <table class='skills'>
                                     <tr>
@@ -315,24 +319,24 @@
                                         </th>
                                     <tr/>
 <?php
-                                    if ($page->monster[$i]->get_leader_skill() != null){
+                                    if ($monster->get_leader_skill() != null){
 ?>
                                         <tr>
                                             <td class='skill_img'>
-                                                <img src='<?=$page->monster[$i]->get_leader_skill()->get_image()?>'/>
+                                                <img src='<?=$monster->get_leader_skill()->get_image()?>'/>
                                             </td>
                                             <td colspan='3' class='skill_text'>
                                                 <h4>
                                                     Leader Skill
                                                 </h4>
                                                 <p>
-                                                    <?=$page->monster[$i]->get_leader_skill()->get_description()?>
+                                                    <?=$monster->get_leader_skill()->get_description()?>
                                                 </p>
                                             </td>
                                         </tr>
 <?php
                                     }
-                                    foreach ($page->monster[$i]->get_transformation()->get_skills() as $skill){
+                                    foreach ($monster->get_transformation()->get_skills() as $skill){
 ?>
                                         <tr>
                                             <td class='skill_img'>
@@ -398,7 +402,7 @@
                         </article>
                     </section>
 <?php
-                } // if ($page->monster[$i] != null)
+                } // if ($monster != null)
             } // for (int $i = 0; $i < 3; $i ++)
 ?>
         </main>

+ 37 - 35
application/view/monsters.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Catalog view.
-     *
-     * Contains the view layout and some code to present the data
-     *
-     * @category View
-     * @var Monsters_Page $page The page model
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Catalog view.
+ *
+ * Contains the view layout and some code to present the data
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Monsters_Page $page The page model,.
+ * @var Monsters_Page $page The page model,.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>monsters.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
 
     </head>
@@ -67,7 +69,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["ELEMENT"] - 1] = "selected";
+                            $selected[$page->get_filter("ELEMENT") - 1] = "selected";
 ?>
                             <select name='element'>
                                 <option value='0'>All</option>
@@ -84,9 +86,9 @@
                             Stars:
                         </td>
                         <td>
-                            <input type='number' name='min_stars' id='filter_stars_min' min='1' max='5' value='<?=$page->filters["MIN_STARS"]?>'/>
+                            <input type='number' name='min_stars' id='filter_stars_min' min='1' max='5' value='<?=$page->get_filter("MIN_STARS")?>'/>
                             -
-                            <input type='number' name='max_stars' id='filter_stars_max' min='1' max='5' value='<?=$page->filters["MAX_STARS"]?>'/>
+                            <input type='number' name='max_stars' id='filter_stars_max' min='1' max='5' value='<?=$page->get_filter("MAX_STARS")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -94,7 +96,7 @@
                             Name:
                         </td>
                         <td>
-                            <input type='text' name='name' id='filter_name' value='<?=$page->filters["NAME"]?>'/>
+                            <input type='text' name='name' id='filter_name' value='<?=$page->get_filter("NAME")?>'/>
                         </td>
                     </tr>
                 </table>
@@ -110,17 +112,17 @@
                 <article>
 <?php
                     $element = "";
-                    foreach ($page->monsters as $mon){
-                        if ($mon->get_element() != $element){
+                    foreach ($page->get_monsters() as $monster){
+                        if ($monster->get_element() != $element){
                             if ($element != ""){
 ?>
                                 </article>
                                 <article>
 <?php
                             }
-                            $element = $mon->get_element();
+                            $element = $monster->get_element();
                         }
-                        if (!in_array($mon->get_id(), $page->monsters_open)){
+                        if (! $page->is_open($monster->get_id())){
                             $closed = "closed";
                         }
                         else{
@@ -128,9 +130,9 @@
                         }
 ?>
                         <div class='monster <?=$closed?>'>
-                            <a href='/<?=get_context()->get_player()->get_id()?>/monsters/<?=$mon->get_id()?>'>
+                            <a href='/<?=get_context()->get_player()->get_id()?>/monsters/<?=$monster->get_id()?>'>
                                 <div class='monster_panel'>
-                                    <?=HTML::unit_panel($mon)?>
+                                    <?=HTML::unit_panel($monster)?>
                                 </div>
                             </a>
                         </div>

+ 30 - 28
application/view/optimizer.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Optimizer teams view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Optimizer_Page $page The page model.
-     * @var Player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Optimizer teams view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Optimizer_Page $page The page model.
+ * @var Optimizer_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,28 +30,28 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>optimizer.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
             units = [];
 <?php
             $units_added = [];
-            foreach ($page->teams as $team){
+            foreach ($page->get_teams() as $team){
                 foreach ($team->get_units() as $unit){
                     if (!in_array($unit->get_id(), $units_added)){
                         array_push($units_added, $unit->get_id());
@@ -186,7 +188,7 @@
                 <br/>
                 <br/>
                 <br/>
-                To optimize units that are not on teams, do so from the <a href='/<?=get_context()->get_player()->get_id()?>/monsters/'>monsters page</a>.
+                To optimize units that are not on teams, do so from the <a href='/<?=get_context()->get_player()->get_id()?>/units/'>units page</a>.
             </p>
         </aside>
         <main>
@@ -209,7 +211,7 @@
                         </tr>
 <?php
                         $odd = "odd";
-                        foreach ($page->teams as $team){
+                        foreach ($page->get_teams() as $team){
 ?>
                             <tr>
                                 <td class='team <?=$odd?>'>

+ 130 - 128
application/view/optimizer_unit.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Optimizer Unit view.
-     *
-     * Contains the view layout and some code to present the data.
-     *
-     * @category View
-     * @var Optimizer_Unit_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Optimizer Unit view.
+ *
+ * Contains the view layout and some code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Optimizer_Unit_Page $page The page model.
+ * @var Optimizer_Unit_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>optimizer.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
 
@@ -51,16 +53,16 @@
              * Unit current stats.
              */
             var current_stats = {
-                "atk": <?=$page->unit->get_stats()["atk"]?>,
-                "def": <?=$page->unit->get_stats()["def"]?>,
-                "hp": <?=$page->unit->get_stats()["hp"]?>,
-                "spd": <?=$page->unit->get_stats()["spd"]?>,
-                "crr": <?=$page->unit->get_stats()["crr"]?>,
-                "crd": <?=$page->unit->get_stats()["crd"]?>,
-                "acc": <?=$page->unit->get_stats()["acc"]?>,
-                "res": <?=$page->unit->get_stats()["res"]?>,
-                "ehp": <?=$page->unit->get_stats()["ehp"]?>,
-                "dmg": <?=$page->unit->get_stats()["dmg"]?>
+                "atk": <?=$page->get_unit()->get_stats()["atk"]?>,
+                "def": <?=$page->get_unit()->get_stats()["def"]?>,
+                "hp": <?=$page->get_unit()->get_stats()["hp"]?>,
+                "spd": <?=$page->get_unit()->get_stats()["spd"]?>,
+                "crr": <?=$page->get_unit()->get_stats()["crr"]?>,
+                "crd": <?=$page->get_unit()->get_stats()["crd"]?>,
+                "acc": <?=$page->get_unit()->get_stats()["acc"]?>,
+                "res": <?=$page->get_unit()->get_stats()["res"]?>,
+                "ehp": <?=$page->get_unit()->get_stats()["ehp"]?>,
+                "dmg": <?=$page->get_unit()->get_stats()["dmg"]?>
             }
 
             var set_stats = {
@@ -75,16 +77,16 @@
             }
 
             var base_stats = {
-                "atk": <?=$page->unit->get_base_stats()["atk"]?>,
-                "def": <?=$page->unit->get_base_stats()["def"]?>,
-                "hp": <?=$page->unit->get_base_stats()["hp"]?>,
-                "spd": <?=$page->unit->get_base_stats()["spd"]?>,
-                "crr": <?=$page->unit->get_base_stats()["crr"]?>,
-                "crd": <?=$page->unit->get_base_stats()["crd"]?>,
-                "acc": <?=$page->unit->get_base_stats()["acc"]?>,
-                "res": <?=$page->unit->get_base_stats()["res"]?>,
-                "ehp": <?=$page->unit->get_base_stats()["ehp"]?>,
-                "dmg": <?=$page->unit->get_base_stats()["dmg"]?>
+                "atk": <?=$page->get_unit()->get_base_stats()["atk"]?>,
+                "def": <?=$page->get_unit()->get_base_stats()["def"]?>,
+                "hp": <?=$page->get_unit()->get_base_stats()["hp"]?>,
+                "spd": <?=$page->get_unit()->get_base_stats()["spd"]?>,
+                "crr": <?=$page->get_unit()->get_base_stats()["crr"]?>,
+                "crd": <?=$page->get_unit()->get_base_stats()["crd"]?>,
+                "acc": <?=$page->get_unit()->get_base_stats()["acc"]?>,
+                "res": <?=$page->get_unit()->get_base_stats()["res"]?>,
+                "ehp": <?=$page->get_unit()->get_base_stats()["ehp"]?>,
+                "dmg": <?=$page->get_unit()->get_base_stats()["dmg"]?>
             }
 
             var requested_sets = {
@@ -114,7 +116,7 @@
 <?php
             // Get current rune sets
             $sets = [];
-            foreach ($page->unit->get_runes() as $rune){
+            foreach ($page->get_unit()->get_runes() as $rune){
                 if (!in_array($rune->get_set()->get_id(), $sets)){
                     array_push($sets, $rune->get_set()->get_id());
                 }
@@ -128,7 +130,7 @@
             // Get current main stats in even slots
 <?php
             $mains = [0, 0, 0];
-            foreach ($page->unit->get_runes() as $rune){
+            foreach ($page->get_unit()->get_runes() as $rune){
                 if ($rune->get_slot() % 2 == 0){
                     $mains[($rune->get_slot() / 2) - 1] = $rune->get_main_stat();
                 }
@@ -237,7 +239,7 @@
                 params += '&mode=<?=get_context()->get_game_mode()?>';
 
                 // Unit id - mandatory
-                params += '&unit=<?=$page->unit->get_id()?>';
+                params += '&unit=<?=$page->get_unit()->get_id()?>';
 
                 // Rune set 1 - mandatory
                 params += '&set[]=' + document.getElementById('set_1').options[document.getElementById('set_1').selectedIndex].value;
@@ -747,7 +749,7 @@
                         }
                     }
                 };
-                params = 'player=<?=get_context()->get_player()->get_id()?>&unit=<?=$page->unit->get_id()?>&tuning=' + document.getElementById('tuning').options[document.getElementById('tuning').selectedIndex].value;
+                params = 'player=<?=get_context()->get_player()->get_id()?>&unit=<?=$page->get_unit()->get_id()?>&tuning=' + document.getElementById('tuning').options[document.getElementById('tuning').selectedIndex].value;
                 params += '&options=' + JSON.stringify(valid_combinations);
                 xhttp.open('POST', '/action/optimize_get_options/', true);
                 xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
@@ -1236,15 +1238,15 @@
 ?>
         <aside>
             <h2>
-                Optimize <?=$page->unit->get_title()?>
+                Optimize <?=$page->get_unit()->get_title()?>
             </h2>
             <div id='monster_info'>
                 <div class='monster_panel'>
-                    <?=HTML::unit_panel($page->unit)?>
+                    <?=HTML::unit_panel($page->get_unit())?>
                 </div>
                 <div id='monster_details'>
 <?php
-                        if (sizeof($page->unit->get_teams()) > 0){
+                        if (sizeof($page->get_unit()->get_teams()) > 0){
 ?>
                         <div id='teams'>
                             <h4>
@@ -1252,7 +1254,7 @@
                             </h4>
                             <ul>
 <?php
-                                foreach($page->unit->get_teams() as $team){
+                                foreach($page->get_unit()->get_teams() as $team){
 ?>
                                     <li>
                                         <a target='blank' href='/<?=get_context()->get_player()->get_id()?>/teams/<?=$team->get_id()?>'>
@@ -1273,7 +1275,7 @@
         <main>
             <section id='monster' class='content'>
                 <h2>
-                    Optimize <?=$page->unit->get_title()?>
+                    Optimize <?=$page->get_unit()->get_title()?>
                 </h2>
                 <article id='profile'>
                     <table id='stats'>
@@ -1302,23 +1304,23 @@
                                 ATK
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["atk"]?>
+                                <?=$page->get_unit()->get_base_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["atk"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["atk"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["atk"]?>
+                                +<?=$page->get_unit()->get_building_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["atk"]?>
+                                <?=$page->get_unit()->get_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -1327,23 +1329,23 @@
                                 DEF
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["def"]?>
+                                <?=$page->get_unit()->get_base_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["def"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["def"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["def"]?>
+                                +<?=$page->get_unit()->get_building_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["def"]?>
+                                <?=$page->get_unit()->get_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -1352,23 +1354,23 @@
                                 HP
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["hp"]?>
+                                <?=$page->get_unit()->get_base_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["hp"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["hp"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["hp"]?>
+                                +<?=$page->get_unit()->get_building_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["hp"]?>
+                                <?=$page->get_unit()->get_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -1377,23 +1379,23 @@
                                 SPD
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["spd"]?>
+                                <?=$page->get_unit()->get_base_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["spd"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["spd"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["spd"]?>
+                                +<?=$page->get_unit()->get_building_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["spd"]?>
+                                <?=$page->get_unit()->get_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -1402,23 +1404,23 @@
                                 CRR
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["crr"]?>
+                                <?=$page->get_unit()->get_base_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["crr"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["crr"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["crr"]?>
+                                +<?=$page->get_unit()->get_building_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["crr"]?>
+                                <?=$page->get_unit()->get_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -1427,23 +1429,23 @@
                                 CRD
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["crd"]?>
+                                <?=$page->get_unit()->get_base_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["crd"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["crd"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["crd"]?>
+                                +<?=$page->get_unit()->get_building_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["crd"]?>
+                                <?=$page->get_unit()->get_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -1452,23 +1454,23 @@
                                 ACC
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["acc"]?>
+                                <?=$page->get_unit()->get_base_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["acc"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["acc"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["acc"]?>
+                                +<?=$page->get_unit()->get_building_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["acc"]?>
+                                <?=$page->get_unit()->get_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -1477,23 +1479,23 @@
                                 RES
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["res"]?>
+                                <?=$page->get_unit()->get_base_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["res"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["res"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["res"]?>
+                                +<?=$page->get_unit()->get_building_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["res"]?>
+                                <?=$page->get_unit()->get_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -1502,23 +1504,23 @@
                                 EHP
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["ehp"]?>
+                                <?=$page->get_unit()->get_base_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["ehp"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["ehp"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["ehp"]?>
+                                +<?=$page->get_unit()->get_building_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["ehp"]?>
+                                <?=$page->get_unit()->get_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -1527,38 +1529,38 @@
                                 DMG
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["dmg"]?>
+                                <?=$page->get_unit()->get_base_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["dmg"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["dmg"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["dmg"]?>
+                                +<?=$page->get_unit()->get_building_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["dmg"]?>
+                                <?=$page->get_unit()->get_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
                     </table>
                     <div id='artifacts'>
-                        <?=HTML::artifact_table($page->unit->get_artifacts()[ARTIFACT_TYPE::ARCHETYPE])?>
-                        <?=HTML::artifact_table($page->unit->get_artifacts()[ARTIFACT_TYPE::ELEMENT])?>
+                        <?=HTML::artifact_table($page->get_unit()->get_artifacts()[ARTIFACT_TYPE::ARCHETYPE])?>
+                        <?=HTML::artifact_table($page->get_unit()->get_artifacts()[ARTIFACT_TYPE::ELEMENT])?>
                     </div>
                 </article> <!-- #profile -->
                 <article id='current_runes'>
 <?php
                     $show_list = [6, 1, 2, 5, 4, 3];
-                    //foreach ($page->unit->get_base_stats()["rune"] as $rune){
+                    //foreach ($page->get_unit()->get_base_stats()["rune"] as $rune){
                     foreach ($show_list as $i){
-                        $rune = $page->unit->get_runes()[$i - 1];
+                        $rune = $page->get_unit()->get_runes()[$i - 1];
 ?>
                         <?=HTML::rune_table($rune)?>
 <?php
@@ -1632,8 +1634,8 @@
                                 Min HP
                             </td>
                             <td class='value'>
-                                <input id='min_hp' type='range' value='<?=$page->unit->get_stats()["hp"]?>' min='<?=$page->unit->get_stats()["hp"]?>' max='50000' oninput='updateMinValue("hp", this);'>
-                                <input type='number' id='lbl_min_hp' value='<?=$page->unit->get_stats()["hp"]?>' min='<?=$page->unit->get_base_stats()["hp"]?>' max='50000' onChange='updateMinValue("hp", this);'></input><span class='slider_percent'> </span>
+                                <input id='min_hp' type='range' value='<?=$page->get_unit()->get_stats()["hp"]?>' min='<?=$page->get_unit()->get_stats()["hp"]?>' max='50000' oninput='updateMinValue("hp", this);'>
+                                <input type='number' id='lbl_min_hp' value='<?=$page->get_unit()->get_stats()["hp"]?>' min='<?=$page->get_unit()->get_base_stats()["hp"]?>' max='50000' onChange='updateMinValue("hp", this);'></input><span class='slider_percent'> </span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("hp");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1674,8 +1676,8 @@
                                 Min ATK
                             </td>
                             <td class='value'>
-                                <input id='min_atk' type='range' value='<?=$page->unit->get_stats()["atk"]?>' min='<?=$page->unit->get_base_stats()["atk"]?>' max='4000' oninput='updateMinValue("atk", this);'>
-                                <input type='number' id='lbl_min_atk' value='<?=$page->unit->get_stats()["atk"]?>' min='<?=$page->unit->get_base_stats()["atk"]?>' max='4000' onChange='updateMinValue("atk", this);'></input><span class='slider_percent'> </span>
+                                <input id='min_atk' type='range' value='<?=$page->get_unit()->get_stats()["atk"]?>' min='<?=$page->get_unit()->get_base_stats()["atk"]?>' max='4000' oninput='updateMinValue("atk", this);'>
+                                <input type='number' id='lbl_min_atk' value='<?=$page->get_unit()->get_stats()["atk"]?>' min='<?=$page->get_unit()->get_base_stats()["atk"]?>' max='4000' onChange='updateMinValue("atk", this);'></input><span class='slider_percent'> </span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("atk");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1703,8 +1705,8 @@
                                 Min DEF
                             </td>
                             <td class='value'>
-                                <input id='min_def' type='range' value='<?=$page->unit->get_stats()["def"]?>' min='<?=$page->unit->get_base_stats()["def"]?>' max='4000' oninput='updateMinValue("def", this);'>
-                                <input type='number' id='lbl_min_def' value='<?=$page->unit->get_stats()["def"]?>' min='<?=$page->unit->get_base_stats()["def"]?>' max='4000' onChange='updateMinValue("def", this);'></input><span class='slider_percent'> </span>
+                                <input id='min_def' type='range' value='<?=$page->get_unit()->get_stats()["def"]?>' min='<?=$page->get_unit()->get_base_stats()["def"]?>' max='4000' oninput='updateMinValue("def", this);'>
+                                <input type='number' id='lbl_min_def' value='<?=$page->get_unit()->get_stats()["def"]?>' min='<?=$page->get_unit()->get_base_stats()["def"]?>' max='4000' onChange='updateMinValue("def", this);'></input><span class='slider_percent'> </span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("def");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1731,8 +1733,8 @@
                                 Min SPD
                             </td>
                             <td class='value'>
-                                <input id='min_spd' type='range' value='<?=$page->unit->get_stats()["spd"]?>' min='<?=$page->unit->get_base_stats()["spd"]?>' max='400' oninput='updateMinValue("spd", this);'>
-                                <input type='number' id='lbl_min_spd' value='<?=$page->unit->get_stats()["spd"]?>' min='<?=$page->unit->get_base_stats()["spd"]?>' max='400' onChange='updateMinValue("spd", this);'></input><span class='slider_percent'> </span>
+                                <input id='min_spd' type='range' value='<?=$page->get_unit()->get_stats()["spd"]?>' min='<?=$page->get_unit()->get_base_stats()["spd"]?>' max='400' oninput='updateMinValue("spd", this);'>
+                                <input type='number' id='lbl_min_spd' value='<?=$page->get_unit()->get_stats()["spd"]?>' min='<?=$page->get_unit()->get_base_stats()["spd"]?>' max='400' onChange='updateMinValue("spd", this);'></input><span class='slider_percent'> </span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("spd");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1754,8 +1756,8 @@
                                 Min CRR
                             </td>
                             <td class='value'>
-                                <input id='min_crr' type='range' value='<?=$page->unit->get_stats()["crr"]?>' min='<?=$page->unit->get_base_stats()["crr"]?>' max='100' oninput='updateMinValue("crr", this);'>
-                                <input type='number' id='lbl_min_crr' value='<?=$page->unit->get_stats()["crr"]?>' min='<?=$page->unit->get_base_stats()["crr"]?>' max='100' onChange='updateMinValue("crr", this);'></input><span class='slider_percent'>%</span>
+                                <input id='min_crr' type='range' value='<?=$page->get_unit()->get_stats()["crr"]?>' min='<?=$page->get_unit()->get_base_stats()["crr"]?>' max='100' oninput='updateMinValue("crr", this);'>
+                                <input type='number' id='lbl_min_crr' value='<?=$page->get_unit()->get_stats()["crr"]?>' min='<?=$page->get_unit()->get_base_stats()["crr"]?>' max='100' onChange='updateMinValue("crr", this);'></input><span class='slider_percent'>%</span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("crr");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1781,8 +1783,8 @@
                                 Min CRD
                             </td>
                             <td class='value'>
-                                <input id='min_crd' type='range' value='<?=$page->unit->get_stats()["crd"]?>' min='<?=$page->unit->get_base_stats()["crd"]?>' max='400' oninput='updateMinValue("crd", this);'>
-                                <input type='number' id='lbl_min_crd' value='<?=$page->unit->get_stats()["crd"]?>' min='<?=$page->unit->get_base_stats()["crd"]?>' max='400' onChange='updateMinValue("crd", this);'></input><span class='slider_percent'>%</span>
+                                <input id='min_crd' type='range' value='<?=$page->get_unit()->get_stats()["crd"]?>' min='<?=$page->get_unit()->get_base_stats()["crd"]?>' max='400' oninput='updateMinValue("crd", this);'>
+                                <input type='number' id='lbl_min_crd' value='<?=$page->get_unit()->get_stats()["crd"]?>' min='<?=$page->get_unit()->get_base_stats()["crd"]?>' max='400' onChange='updateMinValue("crd", this);'></input><span class='slider_percent'>%</span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("crd");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1802,8 +1804,8 @@
                                 Min ACC
                             </td>
                             <td class='value'>
-                                <input id='min_acc' type='range' value='<?=$page->unit->get_stats()["acc"]?>' min='<?=$page->unit->get_base_stats()["acc"]?>' max='85' oninput='updateMinValue("acc", this);'>
-                                <input type='number' id='lbl_min_acc' value='<?=$page->unit->get_stats()["acc"]?>' min='<?=$page->unit->get_base_stats()["acc"]?>' max='85' onChange='updateMinValue("acc", this);'></input><span class='slider_percent'>%</span>
+                                <input id='min_acc' type='range' value='<?=$page->get_unit()->get_stats()["acc"]?>' min='<?=$page->get_unit()->get_base_stats()["acc"]?>' max='85' oninput='updateMinValue("acc", this);'>
+                                <input type='number' id='lbl_min_acc' value='<?=$page->get_unit()->get_stats()["acc"]?>' min='<?=$page->get_unit()->get_base_stats()["acc"]?>' max='85' onChange='updateMinValue("acc", this);'></input><span class='slider_percent'>%</span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("acc");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1823,8 +1825,8 @@
                                 Min RES
                             </td>
                             <td class='value'>
-                                <input id='min_res' type='range' value='<?=$page->unit->get_stats()["res"]?>' min='<?=$page->unit->get_base_stats()["res"]?>' max='85' oninput='updateMinValue("res", this);'>
-                                <input type='number' id='lbl_min_res' value='<?=$page->unit->get_stats()["res"]?>' min='<?=$page->unit->get_base_stats()["res"]?>' max='85' onChange='updateMinValue("res", this);'></input><span class='slider_percent'>%</span>
+                                <input id='min_res' type='range' value='<?=$page->get_unit()->get_stats()["res"]?>' min='<?=$page->get_unit()->get_base_stats()["res"]?>' max='85' oninput='updateMinValue("res", this);'>
+                                <input type='number' id='lbl_min_res' value='<?=$page->get_unit()->get_stats()["res"]?>' min='<?=$page->get_unit()->get_base_stats()["res"]?>' max='85' onChange='updateMinValue("res", this);'></input><span class='slider_percent'>%</span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("res");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1844,8 +1846,8 @@
                                 Min EHP
                             </td>
                             <td class='value'>
-                                <input id='min_ehp' type='range' value='<?=$page->unit->get_base_stats()["ehp"]?>' min='0' max='200000' oninput='updateMinValue("ehp", this);'>
-                                <input type='number' id='lbl_min_ehp' value='<?=$page->unit->get_base_stats()["ehp"]?>' min='0' max='200000' onChange='updateMinValue("ehp", this);'></input><span class='slider_percent'> </span>
+                                <input id='min_ehp' type='range' value='<?=$page->get_unit()->get_base_stats()["ehp"]?>' min='0' max='200000' oninput='updateMinValue("ehp", this);'>
+                                <input type='number' id='lbl_min_ehp' value='<?=$page->get_unit()->get_base_stats()["ehp"]?>' min='0' max='200000' onChange='updateMinValue("ehp", this);'></input><span class='slider_percent'> </span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("ehp");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>
@@ -1868,8 +1870,8 @@
                                 Min DMG
                             </td>
                             <td class='value'>
-                                <input id='min_dmg' type='range' value='<?=$page->unit->get_base_stats()["dmg"]?>' min='0' max='7000' oninput='updateMinValue("dmg", this);'>
-                                <input type='number' id='lbl_min_dmg' value='<?=$page->unit->get_base_stats()["dmg"]?>' min='0' max='7000' onChange='updateMinValue("dmg", this);'></input><span class='slider_percent'> </span>
+                                <input id='min_dmg' type='range' value='<?=$page->get_unit()->get_base_stats()["dmg"]?>' min='0' max='7000' oninput='updateMinValue("dmg", this);'>
+                                <input type='number' id='lbl_min_dmg' value='<?=$page->get_unit()->get_base_stats()["dmg"]?>' min='0' max='7000' onChange='updateMinValue("dmg", this);'></input><span class='slider_percent'> </span>
                                 <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("dmg");'>
                                     <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                 </a>

+ 36 - 34
application/view/profile.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * User profile view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Profile_Page $page The page model.
-     * @var User $USER Currently logged-in user.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * User profile view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Profile_Page $page The page model.
+ * @var Profile_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>profile.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
 
@@ -115,7 +117,7 @@
                         }
                     }
                 }
-                http.send('user=<?=$USER->id?>&mail=' + mail);
+                http.send('user=<?=get_context()->get_user()->get_id()?>&mail=' + mail);
             }
 
             /**
@@ -177,7 +179,7 @@
                         }
                     }
                 }
-                http.send('user=<?=$USER->id?>&pass=' + pass + '&currentPass=' + currentPass);
+                http.send('user=<?=get_context()->get_user()->get_id()?>&pass=' + pass + '&currentPass=' + currentPass);
             }
 
             /**
@@ -199,7 +201,7 @@
                         }
                     }
                 }
-                http.send('user=<?=$USER->id?>&api=1');
+                http.send('user=<?=get_context()->get_user()->get_id()?>&api=1');
             }
         </script>
     </head>
@@ -209,7 +211,7 @@
 ?>
         <aside>
             <h2>
-                <?=$page->name?>
+                <?=get_context()->get_user()->get_name()?>
             </h2>
             <p>
                 Edit your profile settings
@@ -218,7 +220,7 @@
         <main>
             <section class='content'>
                 <h2>
-                    <?=$page->name?>
+                    <?=get_context()->get_user()->get_name()?>
                 </h2>
                 <article>
                     <table id='profile'>
@@ -228,7 +230,7 @@
                             </td>
                             <td class='value'>
                                 <span>
-                                    <?=$page->name?>
+                                    <?=get_context()->get_user()->get_name()?>
                                 </span>
                             </td>
                             <td class='action'>
@@ -241,9 +243,9 @@
                             </td>
                             <td class='value'>
                                 <span id='static_mail'>
-                                    <?=$page->mail?>
+                                    <?=get_context()->get_user()->get_mail()?>
                                 </span>
-                                <input id='edit_mail' type='text' value='<?=$page->mail?>'/>
+                                <input id='edit_mail' type='text' value='<?=get_context()->get_user()->get_mail()?>'/>
                             </td>
                             <td class='action'>
                                 <input id='change_mail' onclick='changeMail();' type='button' value='Change'/>
@@ -256,7 +258,7 @@
                             </td>
                             <td class='value'>
                                 <span id='api_key'>
-                                    <?=$page->api_key?>
+                                    <?=get_context()->get_user()->get_api_key()?>
                                 </span>
                             </td>
                             <td class='action'>

+ 27 - 25
application/view/report.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Main report view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Report_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Main report view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Report_Page $page The page model.
+ * @var Report_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>report.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body id='body_reports'>

+ 54 - 52
application/view/report_rune_enchantment.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Rune Enchantment report view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Report_Rune_Enchantment_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Rune Enchantment report view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Report_Rune_Enchantment_Page $page The page model.
+ * @var Report_Rune_Enchantment_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>report_rune_enchantment.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
 
@@ -128,7 +130,7 @@
                             </div>
                         </td>
                         <td>
-                            <input type='text' name='monster_name' id='filter_name' value='<?=$page->filters["MONSTER_NAME"]?>'/>
+                            <input type='text' name='monster_name' id='filter_name' value='<?=$page->get_filter("MONSTER_NAME")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -136,9 +138,9 @@
                             Stars:
                         </td>
                         <td>
-                            <input type='number' name='monster_min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->filters["MONSTER_MIN_STARS"]?>'/>
+                            <input type='number' name='monster_min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->get_filter("MONSTER_MIN_STARS")?>'/>
                             -
-                            <input type='number' name='monster_max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->filters["MONSTER_MAX_STARS"]?>'/>
+                            <input type='number' name='monster_max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->get_filter("MONSTER_MAX_STARS")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -148,7 +150,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["TEAM"]] = "selected";
+                            $selected[$page->get_filter("TEAM")] = "selected";
 ?>
                             <select name='unit'>
                                 <option value='0' <?=$selected[0]?>>All</option>
@@ -161,7 +163,7 @@
                         <td class='label' colspan='2'>
 <?php
                             $checked = "";
-                            if ($page->filters["MONSTER_IN_STORAGE"]){
+                            if ($page->get_filter("MONSTER_IN_STORAGE")){
                                 $checked = "checked";
                             }
 ?>
@@ -179,9 +181,9 @@
                             Stars:
                         </td>
                         <td>
-                            <input type='number' name='rune_min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->filters["RUNE_MIN_STARS"]?>'/>
+                            <input type='number' name='rune_min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->get_filter("RUNE_MIN_STARS")?>'/>
                             -
-                            <input type='number' name='rune_max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->filters["RUNE_MAX_STARS"]?>'/>
+                            <input type='number' name='rune_max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->get_filter("RUNE_MAX_STARS")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -189,9 +191,9 @@
                             Level:
                         </td>
                         <td>
-                            <input type='number' name='rune_min_level' id='filter_level_min' min='0' max='15' value='<?=$page->filters["RUNE_MIN_LEVEL"]?>'/>
+                            <input type='number' name='rune_min_level' id='filter_level_min' min='0' max='15' value='<?=$page->get_filter("RUNE_MIN_LEVEL")?>'/>
                             -
-                            <input type='number' name='rune_max_level' id='filter_level_max' min='0' max='15' value='<?=$page->filters["RUNE_MAX_LEVEL"]?>'/>
+                            <input type='number' name='rune_max_level' id='filter_level_max' min='0' max='15' value='<?=$page->get_filter("RUNE_MAX_LEVEL")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -202,7 +204,7 @@
 <?php
 
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["RUNE_MIN_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("RUNE_MIN_QUALITY") - 1] = "selected";
 ?>
                             <select name='rune_min_quality' id='filter_quality_min'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -214,7 +216,7 @@
                             -
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["RUNE_MAX_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("RUNE_MAX_QUALITY") - 1] = "selected";
 ?>
                             <select name='rune_max_quality' id='filter_quality_max'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -232,7 +234,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["RUNE_MIN_ORIGINAL_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("RUNE_MIN_ORIGINAL_QUALITY") - 1] = "selected";
 ?>
                             <select name='rune_min_original_quality' id='filter_original_quality_min'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -244,7 +246,7 @@
                             -
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["RUNE_MAX_ORIGINAL_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("RUNE_MAX_ORIGINAL_QUALITY") - 1] = "selected";
 ?>
                             <select name='rune_max_original_quality' id='filter_original_quality_max'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -260,9 +262,9 @@
                             Efficiency:
                         </td>
                         <td>
-                            <input type='number' name='rune_min_efficiency' id='filter_efficiency_min' min='0' max='100' value='<?=$page->filters["RUNE_MIN_EFFICIENCY"]?>'/>%
+                            <input type='number' name='rune_min_efficiency' id='filter_efficiency_min' min='0' max='100' value='<?=$page->get_filter("RUNE_MIN_EFFICIENCY")?>'/>%
                             -
-                            <input type='number' name='rune_max_efficiency' id='filter_efficiency_max' min='0' max='100' value='<?=$page->filters["RUNE_MAX_EFFICIENCY"]?>'/>%
+                            <input type='number' name='rune_max_efficiency' id='filter_efficiency_max' min='0' max='100' value='<?=$page->get_filter("RUNE_MAX_EFFICIENCY")?>'/>%
                         </td>
                     </tr>
                     <tr>
@@ -270,9 +272,9 @@
                             Max. eff.:
                         </td>
                         <td>
-                            <input type='number' name='rune_min_max_efficiency' id='filter_max_efficiency_min' min='0' max='100' value='<?=$page->filters["RUNE_MIN_MAX_EFFICIENCY"]?>'/>%
+                            <input type='number' name='rune_min_max_efficiency' id='filter_max_efficiency_min' min='0' max='100' value='<?=$page->get_filter("RUNE_MIN_MAX_EFFICIENCY")?>'/>%
                             -
-                            <input type='number' name='rune_max_max_efficiency' id='filter_max_efficiency_max' min='0' max='100' value='<?=$page->filters["RUNE_MAX_MAX_EFFICIENCY"]?>'/>%
+                            <input type='number' name='rune_max_max_efficiency' id='filter_max_efficiency_max' min='0' max='100' value='<?=$page->get_filter("RUNE_MAX_MAX_EFFICIENCY")?>'/>%
                         </td>
                     </tr>
                     <tr>
@@ -283,7 +285,7 @@
                             <select multiple name='rune_slot[]' id='filter_slot'>
 <?php
                                 for ($i = 1; $i <= 6; $i ++){
-                                    if (in_array($i, $page->filters["RUNE_SLOT"])){
+                                    if (in_array($i, $page->get_filter("RUNE_SLOT"))){
                                         $selected = "selected='selected'";
                                     }
                                     else{
@@ -301,7 +303,7 @@
                         <td colspan='2' class='header'>
 <?php
                             $checked = "";
-                            if ($page->filters["GRIND"]){
+                            if ($page->get_filter("GRIND")){
                                 $checked = "checked";
                             }
 ?>
@@ -316,7 +318,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["GRIND_MIN_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("GRIND_MIN_QUALITY") - 1] = "selected";
 ?>
                             <select name='grind_min_quality'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -340,7 +342,7 @@
                                     $i = 0;
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["GRIND_STAT"])){
+                                        if (in_array($id, $page->get_filter("GRIND_STAT"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(str_replace("_P", "%", $name));
@@ -364,7 +366,7 @@
                         <td colspan='2' class='header'>
 <?php
                             $checked = "";
-                            if ($page->filters["GEM"]){
+                            if ($page->get_filter("GEM")){
                                 $checked = "checked";
                             }
 ?>
@@ -379,7 +381,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["GEM_MIN_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("GEM_MIN_QUALITY") - 1] = "selected";
 ?>
                             <select name='gem_min_quality'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -403,7 +405,7 @@
                                     $i = 0;
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["GEM_STAT_FROM"])){
+                                        if (in_array($id, $page->get_filter("GEM_STAT_FROM"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(str_replace("_P", "%", $name));
@@ -436,7 +438,7 @@
                                     $i = 0;
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["GEM_STAT_TO"])){
+                                        if (in_array($id, $page->get_filter("GEM_STAT_TO"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(str_replace("_P", "%", $name));
@@ -469,8 +471,8 @@
                 </h2>
                 <table id='results'>
 <?php
-                    foreach ($page->upgrades as $upgrade){
-    ?>
+                    foreach ($page->get_upgrades() as $upgrade){
+?>
                         <tr>
                             <td class='header' colspan='2'>
                                 <a href='/<?=get_context()->get_player()->get_id()?>/units/<?=$upgrade["unit"]->get_id()?>/' target='_blank'>

+ 45 - 43
application/view/report_skillup.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Skillup report view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Report_Skillup_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Skillup report view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Report_Skillup_Page $page The page model.
+ * @var Report_Skillup_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>report_skillup.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body id='body_report_skillup'>
@@ -62,9 +64,9 @@
                                 Stars:
                             </td>
                             <td>
-                                <input type='number' name='min_stars' min='1' max='6' value='<?=$page->filters["MIN_STARS"]?>'/>
+                                <input type='number' name='min_stars' min='1' max='6' value='<?=$page->get_filter("MIN_STARS")?>'/>
                                 -
-                                <input type='number' name='max_stars'  min='1' max='6' value='<?=$page->filters["MAX_STARS"]?>'/>
+                                <input type='number' name='max_stars'  min='1' max='6' value='<?=$page->get_filter("MAX_STARS")?>'/>
                             </td>
                         </tr>
                         <tr>
@@ -72,9 +74,9 @@
                                 Natural stars:
                             </td>
                             <td>
-                                <input type='number' name='min_natural_stars' min='1' max='5' value='<?=$page->filters["MIN_NATURAL_STARS"]?>'/>
+                                <input type='number' name='min_natural_stars' min='1' max='5' value='<?=$page->get_filter("MIN_NATURAL_STARS")?>'/>
                                 -
-                                <input type='number' name='max_natural_stars' min='1' max='5' value='<?=$page->filters["MAX_NATURAL_STARS"]?>'/>
+                                <input type='number' name='max_natural_stars' min='1' max='5' value='<?=$page->get_filter("MAX_NATURAL_STARS")?>'/>
                             </td>
                         </tr>
                         <tr>
@@ -84,7 +86,7 @@
                             <td>
 <?php
                                 $selected = Array("", "", "", "", "");
-                                $selected[$page->filters["UNIT"]] = "selected";
+                                $selected[$page->get_filter("UNIT")] = "selected";
 ?>
                                 <select name='unit'>
                                     <option value='0' <?=$selected[0]?>>All</option>
@@ -103,21 +105,21 @@
                                 </div>
                             </td>
                             <td class='filter'>
-                                &nbsp;S1:<input type='number' step='0.1' min='0' max='4' name='pond_1' id='pond_1' value='<?=$page->filters["PONDERATION"][0]?>'/>
-                                &nbsp;S2:<input type='number' step='0.1' min='0' max='4' name='pond_2' id='pond_2' value='<?=$page->filters["PONDERATION"][1]?>'/>
+                                &nbsp;S1:<input type='number' step='0.1' min='0' max='4' name='pond_1' id='pond_1' value='<?=$page->get_filter("PONDERATION")[0]?>'/>
+                                &nbsp;S2:<input type='number' step='0.1' min='0' max='4' name='pond_2' id='pond_2' value='<?=$page->get_filter("PONDERATION")[1]?>'/>
                             </td>
                         </tr>
                         <tr>
                             <td class='filter'>
-                                &nbsp;S3:<input type='number' step='0.1' min='0' max='4' name='pond_3' id='pond_3' value='<?=$page->filters["PONDERATION"][2]?>'/>
-                                &nbsp;S4:<input type='number' step='0.1' min='0' max='4' name='pond_4' id='pond_4' value='<?=$page->filters["PONDERATION"][3]?>'/>
+                                &nbsp;S3:<input type='number' step='0.1' min='0' max='4' name='pond_3' id='pond_3' value='<?=$page->get_filter("PONDERATION")[2]?>'/>
+                                &nbsp;S4:<input type='number' step='0.1' min='0' max='4' name='pond_4' id='pond_4' value='<?=$page->get_filter("PONDERATION")[3]?>'/>
                             </td>
                         </tr>
                         <tr>
                             <td class='filter' colspan='2'>
 <?php
                                 $checked = "";
-                                if ($page->filters["FAMILY"]){
+                                if ($page->get_filter("FAMILY")){
                                     $checked = "checked";
                                 }
 ?>
@@ -134,7 +136,7 @@
                             <td class='filter' colspan='2'>
 <?php
                                 $checked = "";
-                                if ($page->filters["2A"]){
+                                if ($page->get_filter("2A")){
                                     $checked = "checked";
                                 }
 ?>
@@ -146,7 +148,7 @@
                             <td class='filter' colspan='2'>
 <?php
                                 $checked = "";
-                                if ($page->filters["HOMUNCULUS"]){
+                                if ($page->get_filter("HOMUNCULUS")){
                                     $checked = "checked";
                                 }
 ?>
@@ -158,7 +160,7 @@
                             <td class='filter' colspan='2'>
 <?php
                                 $checked = "";
-                                if ($page->filters["IN_STORAGE"]){
+                                if ($page->get_filter("IN_STORAGE")){
                                     $checked = "checked";
                                 }
 ?>
@@ -170,7 +172,7 @@
                             <td class='filter' colspan='2'>
 <?php
                                 $checked = "";
-                                if ($page->filters["WITHOUT_RUNES"]){
+                                if ($page->get_filter("WITHOUT_RUNES")){
                                     $checked = "checked";
                                 }
 ?>
@@ -182,7 +184,7 @@
                             <td class='filter' colspan='2'>
 <?php
                                 $checked = "";
-                                if ($page->filters["MAXED"]){
+                                if ($page->get_filter("MAXED")){
                                     $checked = "checked";
                                 }
 ?>
@@ -205,7 +207,7 @@
                 <table id='results'>
 <?php
                     $index = 1;
-                    foreach ($page->units as $unit){
+                    foreach ($page->get_units() as $unit){
                         switch ($index % 10){
                             case 1:
                                 $index_title = $index . "<span class='superindex'>st</span> - " . $unit->get_title();
@@ -254,8 +256,8 @@
                                 $cur_lvl = $unit->get_skill_levels()[$skill_num - 1];
                                 if ($skill->get_max_level() > 1){
                                     $absolute_level += $cur_lvl;
-                                    $ponderated_level += $cur_lvl * (($skill_num + 1) / 2.0);
-                                    $ponderated_max_level += $skill->get_max_level() * (($skill_num + 1) / 2.0);
+                                    $ponderated_level += $cur_lvl * $page->get_filter("PONDERATION")[$skill_num - 1];//$cur_lvl * (($skill_num + 1) / 2.0);
+                                    $ponderated_max_level += $skill->get_max_level() * $page->get_filter("PONDERATION")[$skill_num - 1];//$skill->get_max_level() * (($skill_num + 1) / 2.0);
                                 }
                                 $max_lvl = $skill->get_max_level();
                                 if ($max_lvl == $cur_lvl){

+ 48 - 45
application/view/runes.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Runes view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Runes_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Runes view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Runes_Page $page The page model.
+ * @var Runes_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>runes.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
 
@@ -120,9 +122,9 @@
                             Stars:
                         </td>
                         <td>
-                            <input type='number' name='min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->filters["MIN_STARS"]?>'/>
+                            <input type='number' name='min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->get_filter("MIN_STARS")?>'/>
                             -
-                            <input type='number' name='max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->filters["MAX_STARS"]?>'/>
+                            <input type='number' name='max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->get_filter("MAX_STARS")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -132,7 +134,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MIN_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MIN_QUALITY") - 1] = "selected";
 ?>
                             <select name='min_quality' id='filter_quality_min'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -144,7 +146,7 @@
                             -
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MAX_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MAX_QUALITY") - 1] = "selected";
 ?>
                             <select name='max_quality' id='filter_quality_max'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -162,7 +164,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MIN_ORIGINAL_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MIN_ORIGINAL_QUALITY") - 1] = "selected";
 ?>
                             <select name='min_original_quality' id='filter_original_quality_min'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -174,7 +176,7 @@
                             -
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["MAX_ORIGINAL_QUALITY"] - 1] = "selected";
+                            $selected[$page->get_filter("MAX_ORIGINAL_QUALITY") - 1] = "selected";
 ?>
                             <select name='max_original_quality' id='filter_original_quality_max'>
                                 <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
@@ -190,9 +192,9 @@
                             Level:
                         </td>
                         <td>
-                            <input type='number' name='min_level' id='filter_level_min' min='0' max='15' value='<?=$page->filters["MIN_LEVEL"]?>'/>
+                            <input type='number' name='min_level' id='filter_level_min' min='0' max='15' value='<?=$page->get_filter("MIN_LEVEL")?>'/>
                             -
-                            <input type='number' name='max_level' id='filter_level_max' min='0' max='15' value='<?=$page->filters["MAX_LEVEL"]?>'/>
+                            <input type='number' name='max_level' id='filter_level_max' min='0' max='15' value='<?=$page->get_filter("MAX_LEVEL")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -200,9 +202,9 @@
                             Efficiency:
                         </td>
                         <td>
-                            <input type='number' name='min_efficiency' id='filter_efficiency_min' min='0' max='100' value='<?=$page->filters["MIN_EFFICIENCY"]?>'/>%
+                            <input type='number' name='min_efficiency' id='filter_efficiency_min' min='0' max='100' value='<?=$page->get_filter("MIN_EFFICIENCY")?>'/>%
                             -
-                            <input type='number' name='max_efficiency' id='filter_efficiency_max' min='0' max='100' value='<?=$page->filters["MAX_EFFICIENCY"]?>'/>%
+                            <input type='number' name='max_efficiency' id='filter_efficiency_max' min='0' max='100' value='<?=$page->get_filter("MAX_EFFICIENCY")?>'/>%
                         </td>
                     </tr>
                     <tr>
@@ -210,9 +212,9 @@
                             Max. eff.:
                         </td>
                         <td>
-                            <input type='number' name='min_max_efficiency' id='filter_max_efficiency_min' min='0' max='100' value='<?=$page->filters["MIN_MAX_EFFICIENCY"]?>'/>%
+                            <input type='number' name='min_max_efficiency' id='filter_max_efficiency_min' min='0' max='100' value='<?=$page->get_filter("MIN_MAX_EFFICIENCY")?>'/>%
                             -
-                            <input type='number' name='max_max_efficiency' id='filter_max_efficiency_max' min='0' max='100' value='<?=$page->filters["MAX_MAX_EFFICIENCY"]?>'/>%
+                            <input type='number' name='max_max_efficiency' id='filter_max_efficiency_max' min='0' max='100' value='<?=$page->get_filter("MAX_MAX_EFFICIENCY")?>'/>%
                         </td>
                     </tr>
                     <tr>
@@ -228,7 +230,7 @@
                                     $reflect = new ReflectionClass("RUNE_STAT_ID");
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["MAIN"])){
+                                        if (in_array($id, $page->get_filter("MAIN"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(str_replace("_P", "%", $name));
@@ -261,7 +263,7 @@
                                     $j = 1;
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["SUB"])){
+                                        if (in_array($id, $page->get_filter("SUB"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(str_replace("_P", "%", $name));
@@ -294,7 +296,7 @@
                                     $j = 1;
                                     foreach($reflect->getConstants() as $name => $id){
                                         $selected = "";
-                                        if (in_array($id, $page->filters["TYPE"])){
+                                        if (in_array($id, $page->get_filter("TYPE"))){
                                             $selected = "selected='selected'";
                                         }
                                         $name_format = ucwords(strtolower($name));
@@ -325,7 +327,7 @@
                             <select multiple name='slot[]' id='filter_slot'>
 <?php
                                 for ($i = 1; $i <= 6; $i ++){
-                                    if (in_array($i, $page->filters["SLOT"])){
+                                    if (in_array($i, $page->get_filter("SLOT"))){
                                         $selected = "selected='selected'";
                                     }
                                     else{
@@ -346,7 +348,7 @@
                         <td>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["ASSIGNED"]] = "selected";
+                            $selected[$page->get_filter("ASSIGNED")] = "selected";
 ?>
                             <select name='assigned' id='filter_assigned'>
                                 <option value='0' <?=$selected[0]?>>All</option>
@@ -364,7 +366,7 @@
                         <td>
 <?php
                             $selected = Array("", "");
-                            $selected[$page->filters["GROUP"]] = "selected";
+                            $selected[$page->get_filter("GROUP")] = "selected";
 ?>
                             <select name='group' id='filter_group'>
                                 <option value='0' <?=$selected[0]?>>Slot</option>
@@ -387,8 +389,8 @@
                     $group = "";
                     $group_title = "";
                     $group_image = "";
-                    foreach ($page->runes as $rune){
-                        switch ($page->filters["GROUP"]){
+                    foreach ($page->get_runes() as $rune){
+                        switch ($page->get_filter("GROUP")){
                             case 1: // "TYPE":
                                 $group = $rune->get_set()->get_name();
                                 $group_title = $rune->get_set()->get_name();
@@ -441,3 +443,4 @@
 ?>
     </body>
 </html>
+

+ 34 - 32
application/view/runs.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Runs view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Runs_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Runs view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Runs_Page $page The page model.
+ * @var Runs_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>runs.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
 
@@ -164,7 +166,7 @@
                         <td>
 <?php
                             $selected = array_fill(0, 12 + 1, "");
-                            $selected[$page->filters["AREA_TYPE"]] = "selected";
+                            $selected[$page->get_filter("AREA_TYPE")] = "selected";
 ?>
                             <select name='area_type' id='filter_area_type' onchange='selectAreaType();'>
                                 <option value='0'>All</option>
@@ -183,7 +185,7 @@
                             </select>
 <?php
                             $selected = array_fill(0, 9002, "");
-                            $selected[$page->filters["AREA"]] = "selected";
+                            $selected[$page->get_filter("AREA")] = "selected";
 ?>
                             <select id='filter_area_scenario' class='filter_area'>
                                 <option value='0'>All</option>
@@ -228,16 +230,16 @@
                             Date range:
                         </td>
                         <td>
-                            <input type='date' name='date_min' id='date_min' value='<?=$page->filters["DATE_MIN"]?>'/>
+                            <input type='date' name='date_min' id='date_min' value='<?=$page->get_filter("DATE_MIN")?>'/>
                             -
-                            <input type='date' name='date_max' id='date_max' value='<?=$page->filters["DATE_MAX"]?>'/>
+                            <input type='date' name='date_max' id='date_max' value='<?=$page->get_filter("DATE_MAX")?>'/>
                         </td>
                     </tr>
                     <tr>
                         <td colspan='2'>
 <?php
                             $checked = "";
-                            if ($page->filters["DEFEAT"]){
+                            if ($page->get_filter("DEFEAT")){
                                 $checked = "checked";
                             }
 ?>
@@ -249,7 +251,7 @@
                         <td colspan='2'>
 <?php
                             $checked = "";
-                            if ($page->filters["HELPER"]){
+                            if ($page->get_filter("HELPER")){
                                 $checked = "checked";
                             }
 ?>
@@ -259,7 +261,7 @@
                     </tr>
                     <tr>
                         <td colspan='2'>
-                            <input type='number' name='number' id='number' min='1' value='<?=$page->filters["NUMBER"]?>'/> runs per page
+                            <input type='number' name='number' id='number' min='1' value='<?=$page->get_filter("NUMBER")?>'/> runs per page
                         </td>
                     </tr>
                 </table>

+ 27 - 25
application/view/stats.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Runs view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Stats_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Runs view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Stats_Page $page The page model.
+ * @var Stats_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>stats.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
 

+ 66 - 40
application/view/teams.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Teamss view.
-     *
-     * Contains the view layout and ome code to present the data.
-     *
-     * @category View
-     * @var Teams_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Teams view.
+ *
+ * Contains the view layout and ome code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Teams_Page $page The page model.
+ * @var Teams_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>teams.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
         <script>
             units = [];
@@ -54,7 +56,7 @@
             current_slot_id = "";
             leader_id = "";
 <?php
-            foreach ($page->units as $unit){
+            foreach ($page->get_units() as $unit){
 ?>
                 units.push(
                     {
@@ -719,7 +721,7 @@
                             Name:
                         </td>
                         <td>
-                            <input type='text' name='name' id='filter_name' value='<?=$page->filters["NAME"]?>'/>
+                            <input type='text' name='name' id='filter_name' value='<?=$page->get_filter("NAME")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -729,18 +731,42 @@
                         <td>
                             <select name='area'>
                                 <option value=''> </option>
-                                <option value='<?=AREA_TYPE_ID::SCENARIO?>'>Scenario</option>
-                                <option value='<?=AREA_TYPE_ID::CAIROS_DUNGEON?>'>Cairos Dungeon</option>
-                                <option value='<?=AREA_TYPE_ID::RIFT_DUNGEON?>'>Rift Dungeon</option>
-                                <option value='<?=AREA_TYPE_ID::RIFT_RAID?>'>Rift Raid</option>
-                                <option value='<?=AREA_TYPE_ID::DIMENSIONAL_HOLE?>'>Dimensional Hole></option>
-                                <option value='<?=AREA_TYPE_ID::ARENA?>'>Arena</option>
-                                <option value='<?=AREA_TYPE_ID::GUILD_WAR?>'>Guild War</option>
-                                <option value='<?=AREA_TYPE_ID::GUILD_SIEGE?>'>Guild Siege</option>
-                                <option value='<?=AREA_TYPE_ID::TARTARUS_LABYRINTH?>'>Tartarus Labyrinth</option>
-                                <option value='<?=AREA_TYPE_ID::TRIAL_OF_ASCENSION?>'>Trial of Ascension</option>
-                                <option value='<?=AREA_TYPE_ID::WORLD_BOSS?>'>World Boss</option>
-                                <option value='<?=AREA_TYPE_ID::DIMENSIONAL_RIFT?>'>Dimensinal Rift</option>
+                                <option value='<?=AREA_TYPE_ID::SCENARIO?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::SCENARIO ? "selected='selected'" : "")?>>
+                                    Scenario
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::CAIROS_DUNGEON?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::CAIROS_DUNGEON ? "selected='selected'" : "")?>>
+                                    Cairos Dungeon
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::RIFT_DUNGEON?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::RIFT_DUNGEON ? "selected='selected'" : "")?>>
+                                    Rift Dungeon
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::RIFT_RAID?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::RIFT_RAID ? "selected='selected'" : "")?>>
+                                    Rift Raid
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::DIMENSIONAL_HOLE?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::DIMENSIONAL_HOLE ? "selected='selected'" : "")?>>
+                                    Dimensional Hole>
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::ARENA?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::ARENA ? "selected='selected'" : "")?>>
+                                    Arena
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::GUILD_WAR?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::GUILD_WAR ? "selected='selected'" : "")?>>
+                                    Guild War
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::GUILD_SIEGE?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::GUILD_SIEGE ? "selected='selected'" : "")?>>
+                                    Guild Siege
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::TARTARUS_LABYRINTH?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::TARTARUS_LABYRINTH ? "selected='selected'" : "")?>>
+                                    Tartarus Labyrinth
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::TRIAL_OF_ASCENSION?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::TRIAL_OF_ASCENSION ? "selected='selected'" : "")?>>
+                                    Trial of Ascension
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::WORLD_BOSS?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::WORLD_BOSS ? "selected='selected'" : "")?>>
+                                    World Boss
+                                </option>
+                                <option value='<?=AREA_TYPE_ID::DIMENSIONAL_RIFT?>' <?=($page->get_filter("AREA") == AREA_TYPE_ID::DIMENSIONAL_RIFT ? "selected='selected'" : "")?>>
+                                    Dimensinal Rift
+                                </option>
                             </select>
                         </td>
                     </tr>
@@ -774,7 +800,7 @@
                         </tr>
 <?php
                         $odd = "odd";
-                        foreach ($page->teams as $team){
+                        foreach ($page->get_teams() as $team){
 ?>
                             <tr>
                                 <td class='team <?=$odd?>'>

+ 97 - 95
application/view/unit.php

@@ -1,22 +1,24 @@
 <?php
-    /**
-     * Monster view.
-     *
-     * Contains the view layout and some code to present the data.
-     *
-     * @category View
-     * @var Monster_Page $page The page model.
-     * @var player get_context()->get_player() Currently selected player.
-     * @var int get_context()->get_game_mode() Game mode.
-     */
+/**
+ * Monster view.
+ *
+ * Contains the view layout and some code to present the data.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ * @category View
+ * @property Unit_Page $page The page model.
+ * @var Unit_Page $page The page model.
+ */
 ?>
 <!DOCTYPE html>
 <html lang='en'>
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +30,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>monster.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -52,23 +54,23 @@
 ?>
         <aside>
             <h2>
-                <?=$page->unit->get_title()?>
+                <?=$page->get_unit()->get_title()?>
             </h2>
             <div id='monster_info'>
                 <div class='monster_panel'>
-                    <?=HTML::unit_panel($page->unit)?>
+                    <?=HTML::unit_panel($page->get_unit())?>
                 </div>
 <?php
-                if ($page->unit->get_experience_level() != 0){
-                    $exp_pct = ceil($page->unit->get_current_level_experience() * 100 / $page->unit->get_experience_level());
-                    $exp_txt = $page->unit->get_current_level_experience() . " / " . $page->unit->get_experience_level();
+                if ($page->get_unit()->get_experience_level() != 0){
+                    $exp_pct = ceil($page->get_unit()->get_current_level_experience() * 100 / $page->get_unit()->get_experience_level());
+                    $exp_txt = $page->get_unit()->get_current_level_experience() . " / " . $page->get_unit()->get_experience_level();
                 }
                 else{
                     $exp_pct = 100;
                     $exp_txt = "MAX";
                 }
                 $now = time();
-                $date  = strtotime($page->unit->get_creation_time('Y-m-d H:i:s'));
+                $date  = strtotime($page->get_unit()->get_creation_time('Y-m-d H:i:s'));
                 $datediff = $now - $date;
 ?>
                 <div id='monster_details'>
@@ -79,9 +81,9 @@
                             <?=$exp_txt?>
                         </span>
                     </div>
-                    Obtained on <?=$date?> (<?=$datediff?> days ago)<!-- from <?=$page->unit->get_source()->get_name()?> TODO SOurce name, days ago -->
+                    Obtained on <?=$date?> (<?=$datediff?> days ago)<!-- from <?=$page->get_unit()->get_source()->get_name()?> TODO SOurce name, days ago -->
 <?php
-                    if (sizeof($page->unit->get_teams()) > 0){
+                    if (sizeof($page->get_unit()->get_teams()) > 0){
 ?>
                         <div id='teams'>
                             <h4>
@@ -89,11 +91,11 @@
                             </h4>
                             <ul>
 <?php
-                                foreach($page->unit->get_teams() as $team){
+                                foreach($page->get_unit()->get_teams() as $team){
 ?>
                                     <li>
-                                        <a target='blank' href='/<?=get_context()->get_player()->get_id()?>/teams/<?=$team->id?>'>
-                                            <?=$team->name?>
+                                        <a target='blank' href='/<?=get_context()->get_player()->get_id()?>/teams/<?=$team->get_id()?>'>
+                                            <?=$team->get_name()?>
                                         </a>
                                     </li>
 <?php
@@ -104,7 +106,7 @@
 <?php
                     }
 ?>
-                    <a id='optimize' class='a_button' href='/<?=get_context()->get_player()->get_id()?>/optimizer/<?=$page->unit->get_id()?>'>
+                    <a id='optimize' class='a_button' href='/<?=get_context()->get_player()->get_id()?>/optimizer/<?=$page->get_unit()->get_id()?>'>
                         Optimize
                     </a>
                 </div>
@@ -113,7 +115,7 @@
         <main>
             <section id='monster' class='content'>
                 <h2>
-                    <?=$page->unit->get_title()?>
+                    <?=$page->get_unit()->get_title()?>
                 </h2>
                 <article id='stats'>
                     <table>
@@ -142,23 +144,23 @@
                                 ATK
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["atk"]?>
+                                <?=$page->get_unit()->get_base_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["atk"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["atk"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["atk"]?>
+                                +<?=$page->get_unit()->get_building_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["atk"]?>
+                                <?=$page->get_unit()->get_stats()["atk"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -167,23 +169,23 @@
                                 DEF
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["def"]?>
+                                <?=$page->get_unit()->get_base_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["def"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["def"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["def"]?>
+                                +<?=$page->get_unit()->get_building_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["def"]?>
+                                <?=$page->get_unit()->get_stats()["def"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -192,23 +194,23 @@
                                 HP
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["hp"]?>
+                                <?=$page->get_unit()->get_base_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["hp"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["hp"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["hp"]?>
+                                +<?=$page->get_unit()->get_building_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["hp"]?>
+                                <?=$page->get_unit()->get_stats()["hp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -217,23 +219,23 @@
                                 SPD
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["spd"]?>
+                                <?=$page->get_unit()->get_base_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["spd"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["spd"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["spd"]?>
+                                +<?=$page->get_unit()->get_building_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["spd"]?>
+                                <?=$page->get_unit()->get_stats()["spd"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -242,23 +244,23 @@
                                 CRR
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["crr"]?>
+                                <?=$page->get_unit()->get_base_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["crr"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["crr"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["crr"]?>
+                                +<?=$page->get_unit()->get_building_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["crr"]?>
+                                <?=$page->get_unit()->get_stats()["crr"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -267,23 +269,23 @@
                                 CRD
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["crd"]?>
+                                <?=$page->get_unit()->get_base_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["crd"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["crd"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["crd"]?>
+                                +<?=$page->get_unit()->get_building_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["crd"]?>
+                                <?=$page->get_unit()->get_stats()["crd"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -292,23 +294,23 @@
                                 ACC
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["acc"]?>
+                                <?=$page->get_unit()->get_base_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["acc"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["acc"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["acc"]?>
+                                +<?=$page->get_unit()->get_building_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["acc"]?>
+                                <?=$page->get_unit()->get_stats()["acc"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -317,23 +319,23 @@
                                 RES
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["res"]?>
+                                <?=$page->get_unit()->get_base_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["res"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["res"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["res"]?>
+                                +<?=$page->get_unit()->get_building_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["res"]?>
+                                <?=$page->get_unit()->get_stats()["res"]?>
                                 <span class='percent'>%</span>
                             </td>
                         </tr>
@@ -342,23 +344,23 @@
                                 EHP
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["ehp"]?>
+                                <?=$page->get_unit()->get_base_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["ehp"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["ehp"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["ehp"]?>
+                                +<?=$page->get_unit()->get_building_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["ehp"]?>
+                                <?=$page->get_unit()->get_stats()["ehp"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
@@ -367,31 +369,31 @@
                                 DMG
                             </th>
                             <td class='base'>
-                                <?=$page->unit->get_base_stats()["dmg"]?>
+                                <?=$page->get_unit()->get_base_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_rune_stats()["dmg"]?>
+                                +<?=$page->get_unit()->get_rune_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_artifact_stats()["dmg"]?>
+                                +<?=$page->get_unit()->get_artifact_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='extra'>
-                                +<?=$page->unit->get_building_stats()["dmg"]?>
+                                +<?=$page->get_unit()->get_building_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                             <td class='total'>
-                                <?=$page->unit->get_stats()["dmg"]?>
+                                <?=$page->get_unit()->get_stats()["dmg"]?>
                                 <span class='percent'>&nbsp;</span>
                             </td>
                         </tr>
                     </table>
                 </article>
                 <article id='artifacts'>
-                    <?=HTML::artifact_table($page->unit->get_artifacts()[ARTIFACT_TYPE::ARCHETYPE])?>
-                    <?=HTML::artifact_table($page->unit->get_artifacts()[ARTIFACT_TYPE::ELEMENT])?>
+                    <?=HTML::artifact_table($page->get_unit()->get_artifacts()[ARTIFACT_TYPE::ARCHETYPE])?>
+                    <?=HTML::artifact_table($page->get_unit()->get_artifacts()[ARTIFACT_TYPE::ELEMENT])?>
                 </article>
                 <article id='runes'>
 <?php
@@ -404,7 +406,7 @@
                     $total_runes = 0;
                     $show_list = [6, 1, 2, 5, 4, 3];
                     foreach ($show_list as $i){
-                        $rune = $page->unit->get_runes()[$i - 1];
+                        $rune = $page->get_unit()->get_runes()[$i - 1];
                         $total_efficiency += $rune->get_efficiency();
                         $total_max_efficiency += $rune->get_max_efficiency();
                         if ($rune->get_max_efficiency() > 0){
@@ -492,7 +494,7 @@
                             </th>
                         <tr/>
 <?php
-                        $l_skill = $page->unit->get_monster()->get_leader_skill();
+                        $l_skill = $page->get_unit()->get_monster()->get_leader_skill();
                         if ($l_skill != null){
 
 ?>
@@ -516,11 +518,11 @@
                         $absolute_max_level = 0;
                         $ponderated_level = 0;
                         $ponderated_max_level = 0;
-                        foreach ($page->unit->get_monster()->get_skills() as $skill){
+                        foreach ($page->get_unit()->get_monster()->get_skills() as $skill){
                             if ($skill->get_max_level() > 1){
                                     $absolute_max_level += $skill->get_max_level() - 1;
                                 }
-                                $cur_lvl = $page->unit->get_skill_levels()[$skill_num];
+                                $cur_lvl = $page->get_unit()->get_skill_levels()[$skill_num];
                                 if ($skill->get_max_level() > 1){
                                     $absolute_level += $cur_lvl - 1;
                                     $ponderated_level += ($cur_lvl - 1) * (1 + ($skill_num / 2));
@@ -564,7 +566,7 @@
                                     </div>
                                 </td>
 <?php
-                                $cur_lvl = $page->unit->get_skill_levels()[$skill_num];
+                                $cur_lvl = $page->get_unit()->get_skill_levels()[$skill_num];
 ?>
                                 <td class='skill_ups'>
 <?php

+ 28 - 28
application/view/units.php

@@ -15,8 +15,8 @@
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <title><?=$page->get_title()?></title>
+        <link rel='shortcut icon' href='<?=$page->get_favicon()?>'/>
         <!-- CSS files -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
 <?php
@@ -28,22 +28,22 @@
 ?>
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>monsters.css'/>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <link rel='canonical' href='<?=$page->get_canonical()?>'/>
+        <link rel='author' href='<?=$page->get_author()?>'/>
+        <link rel='publisher' href='<?=$page->get_author()?>'/>
+        <meta name='description' content='<?=$page->get_description()?>'/>
+        <meta property='og:title' content='<?=$page->get_title()?>'/>
+        <meta property='og:url' content='<?=$page->get_canonical()?>'/>
+        <meta property='og:description' content='<?=$page->get_description()?>'/>
+        <meta property='og:image' content='<?=$page->get_icon()?>'/>
+        <meta property='og:site_name' content='<?=$page->get_name()?>?>'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='twitter:title' content='<?=$page->get_title()?>'/>
+        <meta name='twitter:description' content='<?=$page->get_description()?>'/>
+        <meta name='twitter:image' content='<?=$page->get_icon()?>'/>
+        <meta name='twitter:url' content='<?=$page->get_canonical()?>'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -66,12 +66,12 @@
                         <td class='value'>
 <?php
                             $selected = Array("", "", "", "", "");
-                            $selected[$page->filters["ELEMENT"] - 1] = "selected";
+                            $selected[$page->get_filter("ELEMENT") - 1] = "selected";
 ?>
                             <select name='element'>
                                 <option> </option>
-                                <option value='<?=ELEMENT_ID::FIRE?>' <?=$selected[0]?>>Fire</option>
-                                <option value='<?=ELEMENT_ID::WATER?>' <?=$selected[1]?>>Water</option>
+                                <option value='<?=ELEMENT_ID::FIRE?>' <?=$selected[1]?>>Fire</option>
+                                <option value='<?=ELEMENT_ID::WATER?>' <?=$selected[0]?>>Water</option>
                                 <option value='<?=ELEMENT_ID::WIND?>' <?=$selected[2]?>>Wind</option>
                                 <option value='<?=ELEMENT_ID::LIGHT?>' <?=$selected[3]?>>Light</option>
                                 <option value='<?=ELEMENT_ID::DARK?>' <?=$selected[4]?>>Dark</option>
@@ -83,9 +83,9 @@
                             Stars:
                         </td>
                         <td class='value'>
-                            <input type='number' name='min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->filters["MIN_STARS"]?>'/>
+                            <input type='number' name='min_stars' id='filter_stars_min' min='1' max='6' value='<?=$page->get_filter("MIN_STARS")?>'/>
                             -
-                            <input type='number' name='max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->filters["MAX_STARS"]?>'/>
+                            <input type='number' name='max_stars' id='filter_stars_max' min='1' max='6' value='<?=$page->get_filter("MAX_STARS")?>'/>
                         </td>
                     </tr>
                     <tr>
@@ -93,14 +93,14 @@
                             Name:
                         </td>
                         <td class='value'>
-                            <input type='text' name='name' id='filter_name' value='<?=$page->filters["NAME"]?>'/>
+                            <input type='text' name='name' id='filter_name' value='<?=$page->get_filter("NAME")?>'/>
                         </td>
                     </tr>
                     <tr>
                         <td class='filter' colspan='2'>
 <?php
                             $checked = "";
-                            if ($page->filters["IN_STORAGE"]){
+                            if ($page->get_filter("IN_STORAGE")){
                                 $checked = "checked";
                             }
 ?>
@@ -112,7 +112,7 @@
                         <td class='filter' colspan='2'>
 <?php
                             $checked = "";
-                            if ($page->filters["WITHOUT_RUNES"]){
+                            if ($page->get_filter("WITHOUT_RUNES")){
                                 $checked = "checked";
                             }
 ?>
@@ -130,15 +130,15 @@
                             </div>
                             <br/>
                             <select name='effect_option' id='filter_effect_option'>
-                                <option value='or' <?=($page->filters["EFFECT_OPTION"] == "or") ? ("selected='selected'") : ("");?>>Any</option>
-                                <option value='and' <?=($page->filters["EFFECT_OPTION"] == "and") ? ("selected='selected'") : ("");?>>All</option>
+                                <option value='or' <?=($page->get_filter("EFFECT_OPTION") == "or") ? ("selected='selected'") : ("");?>>Any</option>
+                                <option value='and' <?=($page->get_filter("EFFECT_OPTION") == "and") ? ("selected='selected'") : ("");?>>All</option>
                             </select>
                         </td>
                         <td class='value'>
                             <select multiple name='effect[]' id='filter_effect'>
 <?php
-                                foreach ($page->effects as $effect){
-                                    if (in_array($effect->get_id(), $page->filters["EFFECT"])){
+                                foreach ($page->get_effects() as $effect){
+                                    if (in_array($effect->get_id(), $page->get_filter("EFFECT"))){
                                         $selected = "selected='selected'";
                                     }
                                     else{
@@ -174,7 +174,7 @@
                 </h2>
                 <article>
 <?php
-                    foreach ($page->units as $unit){
+                    foreach ($page->get_units() as $unit){
 ?>
                         <div class='monster'>
                             <a href='/<?=get_context()->get_player()->get_id()?>/units/<?=$unit->get_id()?>'>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 773 - 517
parser/swarfarm_parser


+ 1 - 0
public/css/report_skillup.css

@@ -54,6 +54,7 @@ section#results table#results td.skill{
     width: 5em;
     padding: 0.2em;
     color: #ffffff;
+    vertical-align: top;
 }
 section#results table#results td.skill.empty{
     width: 0;

+ 19 - 21
public/index.php

@@ -1,27 +1,25 @@
 <?php
-    /**
-     * Index page.
-     *
-     * Receives every request and instantiates a {@see Constroller}.
-     *
-     * @category Public
-     */
+/**
+ * Index page.
+ *
+ * Receives every request and instantiates a {@see Constroller}.
+ *
+ * @category Public
+ */
 
-    require_once(__DIR__ . "/../application/Controller.php");
+require_once(__DIR__ . "/../application/Controller.php");
 
-    $controller = new Controller();
+$controller = new Controller();
 
-    $request = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
-    $params = explode('/', $request);
+$request = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
+$params = explode('/', $request);
 
-    function get_context(){
-        global $controller;
-        return $controller->get_context();
-    }
+function get_context(){
+    global $controller;
+    return $controller->get_context();
+}
 
-    $request = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
-    $params = explode('/', $request);
-    $controller->prepare($params);
-    $controller->action();
-
-?>
+$request = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
+$params = explode('/', $request);
+$controller->prepare($params);
+$controller->action();

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor