Переглянути джерело

Building pages added. User registration enabled. Some fixes applied.

Iñigo Valentin 5 роки тому
батько
коміт
d9607d0b6b
60 змінених файлів з 992 додано та 163 видалено
  1. 0 4
      application/API/v1/profile/PUT.php
  2. 0 3
      application/API/v1/run/POST.php
  3. 32 8
      application/Controller.php
  4. 3 2
      application/action/Add_Team_Action.php
  5. 25 12
      application/action/Delete_Team_Action.php
  6. 148 0
      application/action/Register_Action.php
  7. BIN
      application/key.sqlite
  8. 1 1
      application/page/Artifacts_Page.php
  9. 113 0
      application/page/Building_Page.php
  10. 105 0
      application/page/Buildings_Page.php
  11. 1 1
      application/page/Enchantments_Page.php
  12. 1 1
      application/page/Guild_Page.php
  13. 38 0
      application/page/Help_Page.php
  14. 2 2
      application/page/Login_Page.php
  15. 0 3
      application/page/Monster_Page.php
  16. 0 24
      application/page/Monsters_Page.php
  17. 1 1
      application/page/Optimizer_Page.php
  18. 1 1
      application/page/Optimizer_Unit_Page.php
  19. 1 1
      application/page/Player_Page.php
  20. 1 1
      application/page/Profile_Page.php
  21. 37 0
      application/page/Register_Page.php
  22. 1 1
      application/page/Report_Page.php
  23. 1 1
      application/page/Report_Rune_Enchantment_Page.php
  24. 1 1
      application/page/Report_Skillup_Page.php
  25. 1 1
      application/page/Runes_Page.php
  26. 1 1
      application/page/Runs_Page.php
  27. 39 0
      application/page/Search_Page.php
  28. 0 1
      application/page/Stats_Page.php
  29. 1 1
      application/page/Teams_Page.php
  30. 1 1
      application/page/Unit_Page.php
  31. 1 1
      application/page/Units_Page.php
  32. 1 1
      application/view/artifacts.php
  33. 87 0
      application/view/building.php
  34. 89 0
      application/view/buildings.php
  35. 1 1
      application/view/enchantments.php
  36. 12 6
      application/view/help.php
  37. 1 1
      application/view/inc/header_app.php
  38. 1 2
      application/view/login.php
  39. 1 1
      application/view/monster.php
  40. 3 9
      application/view/monsters.php
  41. 1 1
      application/view/optimizer.php
  42. 1 1
      application/view/optimizer_unit.php
  43. 1 1
      application/view/player.php
  44. 92 0
      application/view/register.php
  45. 2 2
      application/view/report.php
  46. 2 2
      application/view/report_rune_enchantment.php
  47. 2 2
      application/view/report_skillup.php
  48. 1 1
      application/view/runes.php
  49. 1 2
      application/view/runs.php
  50. 48 0
      application/view/search.php
  51. 1 1
      application/view/teams.php
  52. 2 2
      application/view/unit.php
  53. 2 2
      application/view/units.php
  54. 4 4
      install_data/03_INSERT_KEYS_FIXED.sql
  55. 32 0
      public/css/building.css
  56. 0 0
      public/css/buildings.css
  57. 0 0
      public/css/login.css
  58. 1 47
      public/css/player.css
  59. 15 0
      public/css/register.css
  60. 31 0
      public/css/ui.css

+ 0 - 4
application/API/v1/profile/PUT.php

@@ -329,7 +329,6 @@ function parse_rune($player_id, $rune, $lock_list){
         $statement->bindValue(":value", $rune->{"sec_eff"}[0][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[0][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[0][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
     }
@@ -341,7 +340,6 @@ function parse_rune($player_id, $rune, $lock_list){
         $statement->bindValue(":value", $rune->{"sec_eff"}[1][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[1][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[1][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
     }
@@ -353,7 +351,6 @@ function parse_rune($player_id, $rune, $lock_list){
         $statement->bindValue(":value", $rune->{"sec_eff"}[2][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[2][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[2][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
     }
@@ -365,7 +362,6 @@ function parse_rune($player_id, $rune, $lock_list){
         $statement->bindValue(":value", $rune->{"sec_eff"}[3][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[3][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[3][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
     }

+ 0 - 3
application/API/v1/run/POST.php

@@ -1104,9 +1104,6 @@ function log_cairos_run($db, $id, $player_id, $json){
                     default:
                         $statement->bindValue(":value", 3870, SQLITE3_INTEGER);
                 }
-                // TODO:
-                //$efficiency = calculate_artifact_efficiency($artifact);
-                //$max_efficiency = calculate_maximum_efficiency($artifact);
                 $statement->bindValue(":efficiency", null, SQLITE3_FLOAT);
                 $statement->bindValue(":max_efficiency", null, SQLITE3_FLOAT);
                 $statement->bindValue(":stat", $artifact->{"pri_effect"}[0], SQLITE3_INTEGER);

+ 32 - 8
application/Controller.php

@@ -169,7 +169,6 @@ class Controller extends Context{
         if ($player_id != null){
             $this->context->set_player(new Player($player_id));
             if ($this->context->get_player()->get_id() == null){
-                // TODO: error 404;
                 $this->status = 404;
                 $this->message = "Requested player doesn't exist";
                 return;
@@ -251,6 +250,7 @@ class Controller extends Context{
                 }
                 break;
             case "API": // An API call
+                error_log("STARTING API CALL");
                 if (count($this->params) == 1){
                     // TODO: Redirect to current version
                 }
@@ -261,8 +261,10 @@ class Controller extends Context{
                     array_shift($api_params);
                     switch ($version){
                         case "v1":
+                            error_log("STARTING API V1 Controller");
                             require_once(__DIR__ . "/API/v1/API_Controller.php");
                             new API_Controller($this->params);
+                            return;
                             break;
                         default:
                             require_once(PATH::PAGE . "Error_Page.php");
@@ -307,6 +309,10 @@ class Controller extends Context{
                         require_once(PATH::ACTION . "Logout_Action.php");
                         $action = new Logout_Action();
                         break;
+                    case "REGISTER":
+                        require_once(PATH::ACTION . "Register_Action.php");
+                        $action = new Register_Action();
+                        break;
                     case "ADD_TEAM":
                         require_once(PATH::ACTION . "Add_Team_Action.php");
                         $action = new Add_Team_Action();
@@ -443,6 +449,17 @@ class Controller extends Context{
                     break;
                 }
                 break;
+            case "MONSTERS":
+                error_log("PARAM2: " . $this->params[1]);
+                if (sizeof($this->params) > 1){
+                    require_once(PATH::PAGE . "Monster_Page.php");
+                    $page = new Monster_Page($this->params[1]);
+                }
+                else{
+                    require_once(PATH::PAGE . "Monsters_Page.php");
+                    $page = new Monsters_Page();
+                }
+                break;
             case "LOGIN": // The login page
                 require_once(PATH::PAGE . "Login_Page.php");
                 $page = new Login_Page();
@@ -455,18 +472,25 @@ class Controller extends Context{
                 require_once(PATH::PAGE . "Search_Page.php");
                 $page = new Search_Page();
                 break;
-            case "DUNGEON": // Dungeon static pages
+            /*case "DUNGEONS": // Dungeon static pages
                 require_once(PATH::PAGE . "Login_Page.php");
-                $page = new Dungeon_Page();
+                $page = new Dungeons_Page();
+                break;*/
+            case "BUILDINGS": // Building static pages
+                if (sizeof($this->params) > 1){
+                    require_once(PATH::PAGE . "Building_Page.php");
+                    $page = new Building_Page($this->params[1]);
+                }
+                else{
+                    require_once(PATH::PAGE . "Buildings_Page.php");
+                    $page = new Buildings_Page();
+                }
                 break;
-            case "BUILDING": // Building static pages
-                require_once(PATH::PAGE . "Building_Page.php");
-                $page = new Building_Page();
                 break;
-            case "FUSION": // Fusion static pages
+            /*case "FUSION": // Fusion static pages
                 require_once(PATH::PAGE . "Fusion_Page.php");
                 $page = new Fusion_Page();
-                break;
+                break;*/
             case "HELP": // Help static page
                 require_once(PATH::PAGE . "Help_Page.php");
                 $page = new Help_Page();

+ 3 - 2
application/action/Add_Team_Action.php

@@ -12,7 +12,7 @@
 require_once(PATH::ACTION . "Action.php");
 
 /**
- * Logs the user out and redirects to the login page.
+ * Saves a team to the database.
  *
  * Reads the POST parameters looking for the following KEYS:
  *  player: The owner's player ID.
@@ -22,11 +22,12 @@ require_once(PATH::ACTION . "Action.php");
  *  difficulty: Optional, the difficulty ID ({@see DIFFICULTY_ID})
  *  ids: Unit IDs of the party.
  *  name: Team name.
+ *  leader: Id of the leader unit.
+ *  front: Number of units in the frontline.
  *  description: Optional, team description.
  * Validates the data and creates the team in the database.
  * 
  * @category Action
- * @todo: Document properly
  */
 class Add_Team_Action extends Action{
     

+ 25 - 12
application/action/Delete_Team_Action.php

@@ -15,7 +15,6 @@ require_once(PATH::ACTION . "Action.php");
  * Deletes a team.
  *
  * Reads the POST parameters looking for the following KEYS:
- *  player: the team owner's player id.
  *  id: the team id.
  * 
  * @category Action
@@ -24,21 +23,35 @@ class Delete_Team_Action extends Action{
 
     /**
      * Executes the action.
-     * @todo secure
      */
     function execute(){
     
-        $player = filter_input(INPUT_POST, 'player');
         $id = filter_input(INPUT_POST, 'id');
-        $statement = get_context()->get_db()->prepare('DELETE FROM team WHERE player = :player AND id = :id;');
-        $statement->bindValue(':player', $player, SQLITE3_TEXT);
-        $statement->bindValue(':id', $id, SQLITE3_TEXT);
-        $statement->execute();
-        $statement = get_context()->get_db()->prepare('DELETE FROM team_unit WHERE team = :id;');
-        $statement->bindValue(':id', $id, SQLITE3_TEXT);
-        $statement->execute();
-        $this->code = 204;
-        $this->message = "No content.";
+        $statement = get_context()->get_db()->prepare("
+          SELECT count(team.id) AS c
+          FROM
+            team,
+            player
+          WHERE
+            team.id = :team AND
+            player.user = :user
+        ");
+        $statement->bindValue(':team', $id, SQLITE3_TEXT);
+        $statement->bindValue(':user', get_context()->get_user()->get_id(), SQLITE3_TEXT);
+        if ($statement->execute()->fetchArray(SQLITE3_ASSOC)["c"] == 0){
+            $this->code = 401;
+            $this->message = "Unauthorized";
+        }
+        else{
+            $statement = get_context()->get_db()->prepare("DELETE FROM team WHERE id = :id;");
+            $statement->bindValue(':id', $id, SQLITE3_TEXT);
+            $statement->execute();
+            $statement = get_context()->get_db()->prepare("DELETE FROM team_unit WHERE team = :id;");
+            $statement->bindValue(':id', $id, SQLITE3_TEXT);
+            $statement->execute();
+            $this->code = 204;
+            $this->message = "No Content";
+        }
         return;
     }
 }

+ 148 - 0
application/action/Register_Action.php

@@ -0,0 +1,148 @@
+<?php
+/**
+ * File for the login action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @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::ACTION . "Action.php");
+
+/**
+ * Logs the user in.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  uname: username.
+ *  e-mail: e-mail.
+ *  password: password.
+ *  password_repeat: password.
+ * If there is a match, it generates a token and sets cookies and session variablesand
+ * redirects to the user homepage.
+ *
+ * @category Action
+ */
+class Register_Action extends Action{
+    
+    /**
+     * Executes the action.
+     */
+    function execute(){
+
+        if (!isset($_POST['uname'])){
+            $this->code = 400;
+            $this->message = "Username is required.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        if (!isset($_POST['password'])){
+            $this->code = 400;
+            $this->message = "Password is required.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        if (!isset($_POST['password_repeat'])){
+            $this->code = 400;
+            $this->message = "Passwords do not match.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        if (!isset($_POST['mail'])){
+            $this->code = 400;
+            $this->message = "eMail is required.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        $uname = SQLite3::escapeString($_POST['uname']);
+        if (strlen($uname) == 0){
+            $this->code = 400;
+            $this->message = "Username is required.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        $mail = SQLite3::escapeString($_POST['mail']);
+        // TODO: Validate email
+        if (strlen($mail) == 0){
+            $this->code = 400;
+            $this->message = "eMail is required.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        $password = SQLite3::escapeString($_POST['password']);
+        if (strlen($password) == 0){
+            $this->code = 400;
+            $this->message = "Password is required.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        $password_repeat = SQLite3::escapeString($_POST['password_repeat']);
+        if ($password_repeat != $password){
+            $this->code = 400;
+            $this->message = "Passwords do not match.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        $statement = get_context()->get_db()->prepare("
+          SELECT count(id) AS c
+          FROM user WHERE name = :name;
+        ");
+        $statement->bindValue(":name", $uname, SQLITE3_TEXT);
+        if ($statement->execute()->fetchArray(SQLITE3_ASSOC)["c"] != 0){
+            $this->code = 400;
+            $this->message = "Username already in use.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        $statement = get_context()->get_db()->prepare("
+          SELECT count(id) AS c
+          FROM user WHERE mail = :mail;
+        ");
+        $statement->bindValue(":mail", $mail, SQLITE3_TEXT);
+        if ($statement->execute()->fetchArray(SQLITE3_ASSOC)["c"] != 0){
+            $this->code = 400;
+            $this->message = "Mail address already in use.";
+            header("Location: " . URL::BASE . "register/");
+            return;
+        }
+        
+        // All data is correct
+        
+        // Generate an API key
+        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+        $charactersLength = 16;
+        $api = '';
+        for ($i = 0; $i < $charactersLength; $i++) {
+            $api .= $characters[rand(0, $charactersLength - 1)];
+        }
+        
+        // Encode password
+        $password = hash('sha256', $password);
+        
+        // Insert
+        $statement = get_context()->get_db()->prepare("
+          INSERT INTO user (id, name, mail, password, api_key, admin)
+          VALUES(
+            (SELECT max(id) + 1 FROM user),
+            :name,
+            :mail,
+            :password,
+            :api_key,
+            :admin
+          );
+        ");
+        $statement->bindValue(":name", $uname, SQLITE3_TEXT);
+        $statement->bindValue(":mail", $uname, SQLITE3_TEXT);
+        $statement->bindValue(":password", $password, SQLITE3_TEXT);
+        $statement->bindValue(":api_key", $api, SQLITE3_TEXT);
+        $statement->bindValue(":admin", 0, SQLITE3_INTEGER);
+        $statement->execute();
+        $statement->execute();
+        // TODO: Redirect to login?
+        $this->code = 204;
+        $this->message = "No content.";
+        header("Location: " . URL::BASE);
+        return;
+    }
+}

BIN
application/key.sqlite


+ 1 - 1
application/page/Artifacts_Page.php

@@ -60,7 +60,7 @@ class Artifacts_Page extends Page{
         $this->set_view("artifacts.php");
         $this->set_title("Artifacts");
         $this->set_description(get_context()->get_player()->get_name() . "'s artifacts");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/artifacts/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/artifacts/");
         $this->add_css("artifacts.css");
         
         $this->parse_filters();

+ 113 - 0
application/page/Building_Page.php

@@ -0,0 +1,113 @@
+ <?php
+/**
+ * Building 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");
+
+/**
+ * Building view page model.
+ *
+ * @category Page
+ */
+class Building_Page extends Page{
+
+    /**
+     * @var Buildable|Decorative Selected building.
+     */
+    private $building;
+
+    /**
+     *  @var bool Checks if the selected item is a Decorative.
+     */
+    private $type_decorative = false;
+
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     *
+     * @param string $id Selected unit id
+     */
+    public function __construct($id){
+        parent::__construct();
+        $this->set_public(true);
+        $this->set_view("building.php");
+        
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            type
+          FROM (
+            SELECT id, 'buildable' AS type from buildable
+            UNION
+            SELECT id, 'decorative' as type FROM decorative
+          )
+          WHERE id = :id;
+        ");
+        $statement->bindValue(":id", $id, SQLITE3_INTEGER);
+        
+        $result = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if (! $result){
+            $this->set_code(404);
+            $this->set_message("Building not found");
+        }
+        else{
+            if ($result["type"] == "buildable"){
+                $this->building = new Buildable($id);
+                $this->type_decorative = false;
+            }
+            elseif ($result["type"] == "decorative"){
+                $this->building = new Decorative($id);
+                $this->type_decorative = true;
+            }
+            if ($this->building == null || $this->building->get_id() == null){
+                $this->set_code(404);
+                $this->set_message("Building not found");
+            }
+            else{
+                $this->set_code(200);
+                $this->set_message("OK");
+                $this->set_title($this->building->get_name());
+                $this->set_description($this->building->get_name() . " details");
+                $this->set_canonical("buildings/" . $this->building->get_id());
+                $this->add_css("building.css");
+            }
+        }
+    }
+
+    /**
+     * Retrieves the selected building.
+     *
+     * @return Buildable|Decorative Selected building.
+     */
+    public function get_building(){
+        return $this->building;
+    }
+    
+    /**
+     * Checks if the selcted item is a decorative.
+     * 
+     * @return bool True if Decorative, false if Buildable.
+     */
+    public function is_decorative(){
+        return $this->type_decorative;
+    }
+
+    /**
+     * Checks if the selcted item is a buildable.
+     *
+     * @return bool True if Buildable, false if Decorative.
+     */
+    public function is_buildable(){
+        return (! $this->type_decorative);
+    }
+
+}

+ 105 - 0
application/page/Buildings_Page.php

@@ -0,0 +1,105 @@
+<?php
+/**
+ * Building 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 . "Buildable.php");
+require_once(PATH::ENTITY . "Decorative.php");
+
+/**
+ * Building list page model.
+ *
+ * @category Page
+ */
+class Buildings_Page extends Page{
+
+    /**
+     * @var Buildable[] List of buildables to show.
+     */
+    private $buildables = [];
+    
+    /**
+     * @var Decorative[] List of decoratives to show.
+     */
+    private $decoratives = [];
+    
+    /**
+     * @var Decorative[] List of Guild Flags to show.
+     */
+    private $flags = [];
+
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     */
+    public function __construct(){
+        parent::__construct();
+        $this->set_public(true);
+        $this->set_view("buildings.php");
+        $this->set_title("Buildings");
+        $this->set_description("List of all buildings");
+        $this->set_canonical("buildings/");
+        $this->add_css("buildings.css");
+        
+        // Buildings
+        $statement = get_context()->get_db()->prepare("SELECT id FROM buildable;");
+        $result_set = $statement->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->buildables, new Buildable($result["id"]));
+        }
+        
+        // Decorations
+        $statement = get_context()->get_db()->prepare("SELECT id FROM decorative WHERE area != :guild;");
+        $statement->bindValue(":guild", EFFECT_AREA_ID::GUILD);
+        $result_set = $statement->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->decoratives, new Decorative($result["id"]));
+        }
+
+        // Flags
+        $statement = get_context()->get_db()->prepare("SELECT id FROM decorative WHERE area = :guild;");
+        $statement->bindValue(":guild", EFFECT_AREA_ID::GUILD);
+        $result_set = $statement->execute();
+        while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->flags, new Decorative($result["id"]));
+        }
+        $this->set_code(200);
+        $this->set_message("OK");
+    }
+
+    /**
+     * Retrieves the buildings to display
+     *
+     * @return Buildable[] Selected buildables. 
+     */
+    public function get_buildables(){
+        return $this->buildables;
+    }
+
+    /**
+     * Retrieves the decorations to display, excluding Guild Flags
+     *
+     * @return Decorative[] Selected decoratives.
+     */
+    public function get_decoratives(){
+        return $this->decoratives;
+    }
+
+    /**
+     * Retrieves the Guild Flags to display
+     *
+     * @return Decorative[] Selected flags.
+     */
+    public function get_flags(){
+        return $this->flags;
+    }
+    
+}

+ 1 - 1
application/page/Enchantments_Page.php

@@ -58,7 +58,7 @@ class Enchantments_Page extends Page{
         $this->set_view("enchantments.php");
         $this->set_title("Enchantments");
         $this->set_description(get_context()->get_player()->get_name() . "'s enchantments");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/enchantments/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/enchantments/");
         $this->add_css("enchantments.css");
 
         $this->parse_filters();

+ 1 - 1
application/page/Guild_Page.php

@@ -44,7 +44,7 @@ class Guild_Page extends Page{
         parent::__construct();
         $this->set_public(true);
         $this->set_view("guild.php");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/guild/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/guild/");
         $this->add_css("guild.css");
         
         $statement = get_context()->get_db()->prepare("

+ 38 - 0
application/page/Help_Page.php

@@ -0,0 +1,38 @@
+<?php
+/**
+ * Help 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 . "Player.php");
+
+/**
+ * Help page model.
+ *
+ * @category Page
+ */
+class Help_Page extends Page{
+    
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     */
+    public function __construct(){
+        parent::__construct();
+        $this->set_public(true);
+        $this->set_view("help.php");
+        $this->set_title("Help");
+        $this->set_description("Help");
+        $this->set_canonical("help/");
+        $this->add_css("help.css");
+        $this->set_code(200);
+        $this->set_message("OK");
+    }
+}

+ 2 - 2
application/page/Login_Page.php

@@ -40,8 +40,8 @@ class Login_Page extends Page{
         $this->set_view("login.php");
         $this->set_title("Login");
         $this->set_description("Login to SWDB");
-        $this->set_canonical("");
-        $this->add_css("landing.css");
+        $this->set_canonical("login/");
+        $this->add_css("login.css");
         
         if (http_response_code() == 401){
             $this->is_error = true;

+ 0 - 3
application/page/Monster_Page.php

@@ -30,7 +30,6 @@ class Monster_Page extends Page{
 
     /**
      * @var int[] IDs to other units of the family
-     * @todo Implement.
      */
     private $family = [];
     
@@ -143,8 +142,6 @@ class Monster_Page extends Page{
             array_push($this->family, new Monster($result["id"]));
         }
 
-        $this->set_description(get_context()->get_player()->get_name() . "'s enchantments");
-        
         $this->set_title($title);
         $this->set_description($title . " details");
     }

+ 0 - 24
application/page/Monsters_Page.php

@@ -24,11 +24,6 @@ class Monsters_Page extends Page{
      */
     private $monsters = [];
 
-    /**
-     * @var int[] IDs of the monsters marked in the catalog.
-     */
-    private $monsters_open = [];
-
     /**
      * @var mixed[] Default filter values.
      */
@@ -58,16 +53,6 @@ class Monsters_Page extends Page{
         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->set_code(200);
         $this->set_message("OK");
     }
@@ -166,15 +151,6 @@ class Monsters_Page extends Page{
             return null;
         }
     }
-    
-    public function is_open($id){
-        if (in_array($id, $this->monsters_open)){
-            return true;
-        }
-        else{
-            return false;
-        }
-    }
 
 }
 ?>

+ 1 - 1
application/page/Optimizer_Page.php

@@ -36,7 +36,7 @@ class Optimizer_Page extends Page{
         $this->set_view("optimizer.php");
         $this->set_title("Optimizer");
         $this->set_description("Rune optimizer");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/optimizer/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/optimizer/");
         $this->add_css("optimizer.css");
         
         // Get teams

+ 1 - 1
application/page/Optimizer_Unit_Page.php

@@ -38,7 +38,7 @@ class Optimizer_Unit_Page extends Page{
         $this->unit = new Unit($id);
         $this->set_title("Optimize " . $this->unit->get_title());
         $this->set_description("Optimize " . $this->unit->get_title() . "'s runes");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/optimize/" . $this->unit->get_id());
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/optimize/" . $this->unit->get_id());
         $this->add_css("optimizer.css");
         $this->set_code(200);
         $this->set_message("OK");

+ 1 - 1
application/page/Player_Page.php

@@ -30,7 +30,7 @@ class Player_Page extends Page{
         $this->set_view("player.php");
         $this->set_title(get_context()->get_player()->get_name());
         $this->set_description(get_context()->get_player()->get_name() . "'s profile");
-        $this->set_canonical("");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id());
         $this->add_css("player.css");
         $this->set_code(200);
         $this->set_message("OK");

+ 1 - 1
application/page/Profile_Page.php

@@ -29,7 +29,7 @@ class Profile_Page extends Page{
         $this->set_view("profile.php");
         $this->set_title(get_context()->get_user()->get_name() . "'s profile");
         $this->set_description(get_context()->get_user()->get_name() . "'s profile settings");
-        $this->set_canonical("profile/" . get_context()->get_user()->get_id());
+        $this->set_canonical("profile/");
         $this->set_code(200);
         $this->set_message("OK");
     }

+ 37 - 0
application/page/Register_Page.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ * Registration 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");
+
+/**
+ * Registration page model.
+ *
+ * @category Page
+ */
+class Register_Page extends Page{
+
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     */
+    public function __construct(){
+        parent::__construct();
+        $this->set_public(true);
+        $this->set_view("register.php");
+        $this->set_title("Register");
+        $this->set_description("Create an account");
+        $this->set_canonical("register/");
+        $this->add_css("register.css");
+        $this->set_code(200);
+        $this->set_message("OK");
+    }
+}

+ 1 - 1
application/page/Report_Page.php

@@ -30,7 +30,7 @@ class Report_Page extends Page{
         $this->set_view("report.php");
         $this->set_title("Reports");
         $this->set_description("Reports for summoners");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/report/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/report/");
         $this->add_css("report.css");
         $this->set_code(200);
         $this->set_message("OK");

+ 1 - 1
application/page/Report_Rune_Enchantment_Page.php

@@ -90,7 +90,7 @@ class Report_Rune_Enchantment_Page extends Page{
         $this->set_view("report_rune_enchantment.php");
         $this->set_title("Rune enchantment");
         $this->set_description("Find runes that can be upgraded via enchantments");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/report/rune_enchantment//");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/report/rune_enchantment//");
         $this->add_css("report_rune_enchantment.css");
         
         $prev_monster = "";

+ 1 - 1
application/page/Report_Skillup_Page.php

@@ -53,7 +53,7 @@ class Report_Skillup_Page extends Page{
         $this->set_view("report_skillup.php");
         $this->set_title("Urgent skill-ups");
         $this->set_description("FMonster in need of skilling up");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/report/report_skillup/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/report/report_skillup/");
         $this->add_css("report_skillup.css");
         
         $this->parse_filters();

+ 1 - 1
application/page/Runes_Page.php

@@ -63,7 +63,7 @@ class Runes_Page extends Page{
         $this->set_view("runes.php");
         $this->set_title("Runes");
         $this->set_description(get_context()->get_player()->get_name() . "'s runes");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/runes/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/runes/");
         $this->add_css("runes.css");
         
         $this->parse_filters();

+ 1 - 1
application/page/Runs_Page.php

@@ -50,7 +50,7 @@ class Runs_Page extends Page{
         $this->set_view("runs.php");
         $this->set_title("Runs");
         $this->set_description(get_context()->get_player()->get_name() . "'s run logs");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/runs/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/runs/");
         $this->add_css("runs.css");
         $this->parse_filters();
         $result_set = $this->prepare_statement()->execute();

+ 39 - 0
application/page/Search_Page.php

@@ -0,0 +1,39 @@
+ <?php
+/**
+ * Search results 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 Implement
+ */
+
+require_once(PATH::PAGE . "Page.php");
+
+/**
+ * Main reports page model.
+ *
+ * @category Page
+ */
+class Search_Page extends Page{
+
+    /**
+     * Constructor.
+     *
+     * Retrieves the data and initializes the variables.
+     *
+     */
+    public function __construct($query){
+        parent::__construct();
+        $this->set_public(false);
+        $this->set_view("search.php");
+        $this->set_title("Search results");
+        $this->set_description("Search results: " . htmlentities($query));
+        $this->set_canonical("search/" . $query);
+        $this->add_css("search.css");
+        $this->set_code(200);
+        $this->set_message("OK");
+    }
+}

+ 0 - 1
application/page/Stats_Page.php

@@ -230,7 +230,6 @@ class Stats_Page extends Page{
      * 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"];
         }

+ 1 - 1
application/page/Teams_Page.php

@@ -48,7 +48,7 @@ class Teams_Page extends Page{
         $this->set_view("teams.php");
         $this->set_title("Teams");
         $this->set_description(get_context()->get_player()->get_name() . "'s teams");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/teams/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/teams/");
         $this->add_css("teams.css");
 
         $this->parse_filters();

+ 1 - 1
application/page/Unit_Page.php

@@ -46,7 +46,7 @@ class Unit_Page extends Page{
         }
         $this->set_title($this->unit->get_title());
         $this->set_description(get_context()->get_player()->get_name() . "'s " . $this->unit->get_title());
-        $this->set_canonical(get_context()->get_player()->get_id() . "/unit/" . $this->unit->get_id());
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/unit/" . $this->unit->get_id());
         $this->add_css("unit.css");
         
     }

+ 1 - 1
application/page/Units_Page.php

@@ -55,7 +55,7 @@ class Units_Page extends Page{
         $this->set_view("units.php");
         $this->set_title("Units");
         $this->set_description(get_context()->get_player()->get_name() . "'s units");
-        $this->set_canonical(get_context()->get_player()->get_id() . "/units/");
+        $this->set_canonical("player/" . get_context()->get_player()->get_id() . "/units/");
         $this->add_css("units.css");
 
         $this->parse_filters();

+ 1 - 1
application/view/artifacts.php

@@ -29,7 +29,7 @@
             <p>
                 Manage your enchantments
             </p>
-            <form action='/<?=get_context()->get_player()->get_id()?>/artifacts/' method='get' id='filter_artifacts' class='filter'>
+            <form action='/player/<?=get_context()->get_player()->get_id()?>/artifacts/' method='get' id='filter_artifacts' class='filter'>
                 <table>
                     <tr>
                         <td class='label'>

+ 87 - 0
application/view/building.php

@@ -0,0 +1,87 @@
+<?php
+/**
+ * Building 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 Building_Page $page The page model,.
+ * @var Building_Page $page The page model,.
+ */
+?>
+<!DOCTYPE html>
+<html lang='en'>
+    <head>
+        <?=$page->generate_head()?>
+    </head>
+    <body>
+        <header>
+<?php
+            include __DIR__ . "/inc/header_app.php";
+?>
+        </header>
+        <aside id='filters' class='content filters'>
+            <h2 id='filters_title'>
+                <?=$page->get_building()->get_name()?>
+            </h2>
+            <p>
+                <?=HTML::building_panel($page->get_building())?>
+                <?=$page->get_building()->get_description()?>
+            </p>
+        </aside>
+        <main>
+<?php
+            if ($page->is_decorative()){
+?>
+                <section class='content'>
+                    <h2>
+                        Levels
+                    </h2>
+                    <article>
+                        <table id='levels'>
+                            <tr>
+                                <th>
+                                    Level
+                                </th>
+                                <th>
+                                    Bonus
+                                </th>
+                                <th>
+                                    Cost
+                                </th>
+                             <tr>
+<?php
+                            $bonus = $page->get_building()->get_level_bonus();
+                            $cost = $page->get_building()->get_level_cost();
+                            for ($i = 1; $i <= min([sizeof($bonus), sizeof($cost)]); $i ++){
+?>
+                                <tr class='<?=($i % 2 == 0 ? "even" : "odd")?>'>
+                                    <td>
+                                        <?=$i?>
+                                    </td>
+                                    <td>
+                                        <?=$bonus[$i]?>
+                                    </td>
+                                    <td>
+                                        <?=$cost[$i]?>
+                                    </td>
+                                </tr>
+<?php
+                            }
+?>
+                        </table>
+                    </article>
+                </section>
+<?php    
+            }
+?>
+        </main>
+
+<?php
+        include __DIR__ . "/inc/footer.php";
+?>
+    </body>
+</html>

+ 89 - 0
application/view/buildings.php

@@ -0,0 +1,89 @@
+<?php
+/**
+ * Building list 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 Buildings_Page $page The page model,.
+ * @var Buildings_Page $page The page model,.
+ */
+?>
+<!DOCTYPE html>
+<html lang='en'>
+    <head>
+        <?=$page->generate_head()?>
+    </head>
+    <body>
+        <header>
+<?php
+            include __DIR__ . "/inc/header_app.php";
+?>
+        </header>
+        <aside id='filters' class='content filters'>
+            <h2 id='filters_title'>
+                Buildings
+            </h2>
+            <p>
+                A list with every building in the game.
+            </p>
+        </aside>
+        <main>
+            <section id='list' class='list'>
+                <h2>
+                    Buildings
+                </h2>
+                <article>
+<?php
+                    foreach ($page->get_buildables() as $buildable){
+?>
+                        <a href='/buildings/<?=$buildable->get_id()?>'>
+                            <?=HTML::building_panel($buildable)?>
+                        </a>
+<?php
+                    }
+?>
+                </article>
+            </section>
+            <section id='list' class='list'>
+                <h2>
+                    Decorations
+                </h2>
+                <article>
+<?php
+                    foreach ($page->get_decoratives() as $decorative){
+?>
+                        <a href='/buildings/<?=$decorative->get_id()?>'>
+                            <?=HTML::building_panel($decorative)?>
+                        </a>
+<?php
+                    }
+?>
+                </article>
+            </section>
+            <section id='list' class='list'>
+                <h2>
+                    Guild Flags
+                </h2>
+                <article>
+<?php
+                    foreach ($page->get_flags() as $flag){
+?>
+                        <a href='/buildings/<?=$flag->get_id()?>'>
+                            <?=HTML::building_panel($flag)?>
+                        </a>
+<?php
+                    }
+?>
+                </article>
+            </section>
+        </main>
+
+<?php
+        include __DIR__ . "/inc/footer.php";
+?>
+    </body>
+</html>

+ 1 - 1
application/view/enchantments.php

@@ -68,7 +68,7 @@
             <p>
                 Manage your enchantments
             </p>
-            <form action='/<?=get_context()->get_player()->get_id()?>/enchantments/' method='get' id='filter_artifacts' class='filter'>
+            <form action='/player/<?=get_context()->get_player()->get_id()?>/enchantments/' method='get' id='filter_artifacts' class='filter'>
                 <table>
                     <tr>
                         <td class='label'>

+ 12 - 6
application/view/help.php

@@ -21,13 +21,19 @@
             include __DIR__ . "/inc/header_app.php";
 ?>
         </header>
-        <div id='content'>
-            <div class='section'>
-                <h3 class='section_title'>
+        <aside>
+        </aside>
+        <main>
+            <section class='content'>
+                <h2>
                     Help
-                </h3>
-            </div> <!-- .section -->
-        </div> <!-- .content -->
+                </h2>
+                <article>
+                    <!-- TODO: Add content -->
+                    Help page
+                </article>
+            </section>
+        </main>
 <?php
         include __DIR__ . "/inc/footer.php";
 ?>

+ 1 - 1
application/view/inc/header_app.php

@@ -61,7 +61,7 @@
                 else{
 ?>
                     <td class='item'>
-                        <a href='/<?=get_context()->get_user()->get_id()?>/'>
+                        <a href='/'>
                             Account
                         </a>
                     </td>

+ 1 - 2
application/view/login.php

@@ -8,7 +8,7 @@
  * @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.
+ * @property Login_Page $page The page model.
  * @var Login_Page $page The page model.
  */
 ?>
@@ -20,7 +20,6 @@
     <body>
 <?php
         include __DIR__ . "/inc/header_app.php";
-        include __DIR__ . "/inc/header_player.php";
 ?>
         <aside>
         </aside>

+ 1 - 1
application/view/monster.php

@@ -59,7 +59,7 @@
                 
                 foreach ($page->get_family() as $family){
 ?>
-                    <a href='/<?=get_context()->get_player()->get_id()?>/monsters/<?=$family->get_id()?>'>
+                    <a href='/monsters/<?=$family->get_id()?>'>
                         <div class='monster_panel'>
                             <?=HTML::unit_panel($family)?>
                         </div>

+ 3 - 9
application/view/monsters.php

@@ -30,7 +30,7 @@
             <p>
                 A list with every monster in the game.
             </p>
-            <form action='/<?=get_context()->get_player()->get_id()?>/monsters/' method='get' id='filter_catalog' class='filter'>
+            <form action='/monsters/' method='get' id='filter_catalog' class='filter'>
                 <table>
                     <tr>
                         <td class='label'>
@@ -92,15 +92,9 @@
                             }
                             $element = $monster->get_element();
                         }
-                        if (! $page->is_open($monster->get_id())){
-                            $closed = "closed";
-                        }
-                        else{
-                            $closed = "";
-                        }
 ?>
-                        <div class='monster <?=$closed?>'>
-                            <a href='/<?=get_context()->get_player()->get_id()?>/monsters/<?=$monster->get_id()?>'>
+                        <div class='monster'>
+                            <a href='/monsters/<?=$monster->get_id()?>'>
                                 <div class='monster_panel'>
                                     <?=HTML::unit_panel($monster)?>
                                 </div>

+ 1 - 1
application/view/optimizer.php

@@ -79,7 +79,7 @@
              * @param unit ID of the unit to optimize.
              */
             function optimize(unit){
-                window.location.href = "/<?=get_context()->get_player()->get_id()?>/optimizer/" + unit;
+                window.location.href = "/player/<?=get_context()->get_player()->get_id()?>/optimizer/" + unit;
             }
 
             /**

+ 1 - 1
application/view/optimizer_unit.php

@@ -1295,7 +1295,7 @@
                                 foreach($page->get_unit()->get_teams() as $team){
 ?>
                                     <li>
-                                        <a target='blank' href='/<?=get_context()->get_player()->get_id()?>/teams/<?=$team->get_id()?>'>
+                                        <a target='blank' href='/player/<?=get_context()->get_player()->get_id()?>/teams/<?=$team->get_id()?>'>
                                             <?=$team->get_name()?>
                                         </a>
                                     </li>

+ 1 - 1
application/view/player.php

@@ -537,7 +537,7 @@
                                                     }
                                                     if ($disabled == ""){
 ?>
-                                                        <a target='_blank' href='/<?=get_context()->get_player()->get_id()?>/units/<?=$party->get_id()?>'>
+                                                        <a target='_blank' href='/player/<?=get_context()->get_player()->get_id()?>/units/<?=$party->get_id()?>'>
 <?php
                                                     }
 ?>

+ 92 - 0
application/view/register.php

@@ -0,0 +1,92 @@
+<?php
+/**
+ * Registration 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 Register_Page $page The page model.
+ * @var Register_Page $page The page model.
+ */
+?>
+<!DOCTYPE html>
+<html lang='en'>
+    <head>
+        <?=$page->generate_head()?>
+    </head>
+    <body>
+        <header>
+<?php
+            include __DIR__ . "/inc/header_app.php";
+?>
+        </header>
+        <aside>
+        </aside>
+        <main>
+            <section class='content'>
+                <h2>
+                    Create an account
+                </h2>
+                <article>
+                    <!-- TODO: Action via JS, and fallback in controller -->
+                    <form method='POST' action='/action/register/'>
+                        <table>
+                            <tr>
+                                <td class='label'>
+                                    <label for='uname'>
+                                        Username
+                                    </label>
+                                </td>
+                                <td class='input'>
+                                    <input type='text' name='uname' id='uname' required/>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='label'>
+                                    <label for='uname'>
+                                        e-mail
+                                    </label>
+                                </td>
+                                <td class='input'>
+                                    <input type='text' name='mail' id='mail' required/>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='label'>
+                                    <label for='password'>
+                                        Password
+                                    </label>
+                                </td>
+                                <td class='input'>
+                                    <input type='password' name='password' id='password' required/>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='label'>
+                                    <label for='password'>
+                                        Repeat password
+                                    </label>
+                                </td>
+                                <td class='input'>
+                                    <input type='password' name='password_repeat' id='password_repeat' required/>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='submit' colspan='2'>
+                                    <input type='submit' value='Create'/>
+                                </td>
+                            </tr>
+                        </table>
+                    </form>
+                </article>
+            </section>
+        </main>
+
+<?php
+        include __DIR__ . "/inc/footer.php";
+?>
+    </body>
+</html>

+ 2 - 2
application/view/report.php

@@ -43,7 +43,7 @@
                         Shows a list of the monstes in need of skilling-up
                         It sorts monster not by the absolute ammount of remaining power-ups, but by a ponderated list tht takes into account to which skills the previous power ups have gone, placing more value in the more advanced skills. 
                     </p>
-                    <a class='a_button' href='/<?=get_context()->get_player()->get_id()?>/report/skillup/'>
+                    <a class='a_button' href='/player/<?=get_context()->get_player()->get_id()?>/report/skillup/'>
                         Go
                     </a>
                 </article>
@@ -58,7 +58,7 @@
                         Shows monsters with runes that can be grinded or enchanted.
                         It list the grindstones and gems that are available for each rune.
                     </p>
-                    <a class='a_button' href='/<?=get_context()->get_player()->get_id()?>/report/rune_enchantment/'>
+                    <a class='a_button' href='/player/<?=get_context()->get_player()->get_id()?>/report/rune_enchantment/'>
                         Go
                     </a>
                 </article>

+ 2 - 2
application/view/report_rune_enchantment.php

@@ -85,7 +85,7 @@
             <h2>
                 Report filters
             </h2>
-            <form action='/<?=get_context()->get_player()->get_id()?>/report/rune_enchantment/' method='get' id='filter_runeenchantment' class='filter'>
+            <form action='/player/<?=get_context()->get_player()->get_id()?>/report/rune_enchantment/' method='get' id='filter_runeenchantment' class='filter'>
                 <table>
                     <tr>
                         <td colspan='2' class='header'>
@@ -447,7 +447,7 @@
 ?>
                         <tr>
                             <td class='header' colspan='2'>
-                                <a href='/<?=get_context()->get_player()->get_id()?>/units/<?=$upgrade["unit"]->get_id()?>/' target='_blank'>
+                                <a href='/player/<?=get_context()->get_player()->get_id()?>/units/<?=$upgrade["unit"]->get_id()?>/' target='_blank'>
                                     <div class='monster_panel'>
                                         <?=HTML::unit_panel($upgrade["unit"])?>
                                     </div>

+ 2 - 2
application/view/report_skillup.php

@@ -29,7 +29,7 @@
                 Report filters
             </h2>
             <article id='filters_content'>
-                <form action='/<?=get_context()->get_player()->get_id()?>/report/skillup/' method='get' id='filter_skillup' class='filter'>
+                <form action='/player/<?=get_context()->get_player()->get_id()?>/report/skillup/' method='get' id='filter_skillup' class='filter'>
                     <table>
                         <tr>
                             <td class='filter' id='filter_stars'>
@@ -209,7 +209,7 @@
                         </tr>
                         <tr>
                             <td rowspan='3' class='img'>
-                                <a href='/<?=get_context()->get_player()->get_id()?>/monsters/<?=$unit->get_id()?>/' target='_blank'>
+                                <a href='/player/<?=get_context()->get_player()->get_id()?>/monsters/<?=$unit->get_id()?>/' target='_blank'>
                                     <div class='monster_panel'>
                                         <?=HTML::unit_panel($unit)?>
                                     </div>

+ 1 - 1
application/view/runes.php

@@ -87,7 +87,7 @@
             <p>
                 Manage your runes
             </p>
-            <form action='/<?=get_context()->get_player()->get_id()?>/runes/' method='get' id='filter_runes' class='filter'>
+            <form action='/player/<?=get_context()->get_player()->get_id()?>/runes/' method='get' id='filter_runes' class='filter'>
                 <table>
                     <tr>
                         <td class='label' >

+ 1 - 2
application/view/runs.php

@@ -129,7 +129,7 @@
             <p>
                 View and compare saved runs
             </p>
-            <form action='/<?=get_context()->get_player()->get_id()?>/runs/' method='get' id='filter_runeupgrade' class='filter'>
+            <form action='/player/<?=get_context()->get_player()->get_id()?>/runs/' method='get' id='filter_runeupgrade' class='filter'>
                 <table>
                     <tr>
                         <td class='label'>
@@ -490,7 +490,6 @@
                                         </div>
 <?php
                                     }
-                                    // TODO: Artifacts
                                     foreach ($run->get_rewards()["enchantment"] as $enchantment){
 ?>
                                         <div class='item item_enchantment'>

+ 48 - 0
application/view/search.php

@@ -0,0 +1,48 @@
+<?php
+/**
+ * Building 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 Search_Page $page The page model,.
+ * @var Search_Page $page The page model,.
+ */
+?>
+<!DOCTYPE html>
+<html lang='en'>
+    <head>
+        <?=$page->generate_head()?>
+    </head>
+    <body>
+        <header>
+<?php
+            include __DIR__ . "/inc/header_app.php";
+?>
+        </header>
+        <aside id='filters' class='content filters'>
+            <h2 id='filters_title'>
+                Search filters
+            </h2>
+            <p>
+                
+            </p>
+        </aside>
+        <main>
+            <section class='content'>
+                <h2>
+                    Results
+                </h2>
+                <article>
+                </article>
+            </section>
+        </main>
+
+<?php
+        include __DIR__ . "/inc/footer.php";
+?>
+    </body>
+</html>

+ 1 - 1
application/view/teams.php

@@ -686,7 +686,7 @@
             <p>
                 View and manage teams
             </p>
-            <form action='/<?=get_context()->get_player()->get_id()?>/teams/' method='get'  id='filter_monsters' class='filter'>
+            <form action='/player/<?=get_context()->get_player()->get_id()?>/teams/' method='get'  id='filter_monsters' class='filter'>
                 <table>
                     <tr>
                         <td class='label'>

+ 2 - 2
application/view/unit.php

@@ -66,7 +66,7 @@
                                 foreach($page->get_unit()->get_teams() as $team){
 ?>
                                     <li>
-                                        <a target='blank' href='/<?=get_context()->get_player()->get_id()?>/teams/<?=$team->get_id()?>'>
+                                        <a target='blank' href='/player/<?=get_context()->get_player()->get_id()?>/teams/<?=$team->get_id()?>'>
                                             <?=$team->get_name()?>
                                         </a>
                                     </li>
@@ -78,7 +78,7 @@
 <?php
                     }
 ?>
-                    <a id='optimize' class='a_button' href='/<?=get_context()->get_player()->get_id()?>/optimizer/<?=$page->get_unit()->get_id()?>'>
+                    <a id='optimize' class='a_button' href='/player/<?=get_context()->get_player()->get_id()?>/optimizer/<?=$page->get_unit()->get_id()?>'>
                         Optimize
                     </a>
                 </div>

+ 2 - 2
application/view/units.php

@@ -29,7 +29,7 @@
             <p>
                 Monsters
             </p>
-            <form action='/<?=get_context()->get_player()->get_id()?>/units/' method='get'  id='filter_monsters' class='filter'>
+            <form action='/player/<?=get_context()->get_player()->get_id()?>/units/' method='get'  id='filter_monsters' class='filter'>
                 <table>
                     <tr>
                         <td class='label'>
@@ -149,7 +149,7 @@
                     foreach ($page->get_units() as $unit){
 ?>
                         <div class='monster'>
-                            <a href='/<?=get_context()->get_player()->get_id()?>/units/<?=$unit->get_id()?>'>
+                            <a href='/player/<?=get_context()->get_player()->get_id()?>/units/<?=$unit->get_id()?>'>
                                 <div class='monster_panel'>
                                     <?=HTML::unit_panel($unit)?>
                                 </div>

+ 4 - 4
install_data/03_INSERT_KEYS_FIXED.sql

@@ -139,10 +139,10 @@ INSERT INTO key.decorative VALUES(19,1,2,5,'Dark Sanctuary','',10);
 INSERT INTO key.decorative VALUES(31,1,6,NULL,'Fallen Ancient Guardian','',10);
 INSERT INTO key.decorative VALUES(6,1,4,NULL,'Sky Tribe Totem','',10);
 INSERT INTO key.decorative VALUES(8,1,1,NULL,'Crystal Altar','',10);
-INSERT INTO key.decorative VALUES(36,5,2,NULL,'Flag of Battle','',10);
-INSERT INTO key.decorative VALUES(37,5,6,NULL,'Flag of Rage','',10);
-INSERT INTO key.decorative VALUES(38,5,1,NULL,'Flag of Hope','',10);
-INSERT INTO key.decorative VALUES(39,5,3,NULL,'Flag of Will','',10);
+INSERT INTO key.decorative VALUES(36,4,2,NULL,'Flag of Battle','',10);
+INSERT INTO key.decorative VALUES(37,4,6,NULL,'Flag of Rage','',10);
+INSERT INTO key.decorative VALUES(38,4,1,NULL,'Flag of Hope','',10);
+INSERT INTO key.decorative VALUES(39,4,3,NULL,'Flag of Will','',10);
 INSERT INTO key.decorative VALUES(9,1,2,NULL,'Ancient Sword','',10);
 INSERT INTO key.decorative VALUES(7,1,NULL,NULL,'Arcane Booster Tower','',10);
 INSERT INTO key.decorative VALUES(34,1,NULL,NULL,'Crystal Rock','',10);

+ 32 - 0
public/css/building.css

@@ -0,0 +1,32 @@
+aside{
+    text-align: center;
+}
+
+aside div.building_panel{
+    display: block;
+    font-size: 200%;
+    margin: 2em auto 1em auto;
+}
+
+main table#levels{
+    border-collapse: collapse;
+    margin: auto;
+}
+
+main table#levels td, th{
+    border: 0.1em solid #000000;
+}
+
+main table#levels th{
+    font-weight: bold;
+    padding: 0.5em;
+    background-color: #000000aa;
+}
+
+main table#levels tr.even td{
+    background-color: #00000022;
+}
+
+main table#levels tr.odd td{
+    background-color: #00000044;
+}

+ 0 - 0
public/css/buildings.css


+ 0 - 0
public/css/landing.css → public/css/login.css


+ 1 - 47
public/css/player.css

@@ -115,53 +115,7 @@ article#profile div#placements div#placements_siege hr{
 }
 
 article#profile div#building div.building_panel{
-    display: inline-block;
-    width: 2em;
-    height: 2em;
-    margin: 0.2em 0em;
-    position: relative;
-    border-radius: 15%;
-    vertical-align: middle;
-}
-
-article#profile div#building div.building_panel img.building, img.decoration{
-    width: 2em;
-    height: 2em;
-    border-style: solid;
-    border-width: 0.1em;
-    border-radius: 15%;
-}
-
-article#profile div#building div.building_panel{
-    display: inline-block;
-    width: 2em;
-    height: 2em;
-    margin: 0.2em 0em;
-    position: relative;
-    border-radius: 15%;
-    vertical-align: middle;
-}
-
-article#profile div#building div.building_panel img.building, img.decoration{
-    width: 2em;
-    height: 2em;
-    border-style: solid;
-    border-width: 0.1em;
-    border-radius: 15%;
-}
-
-article#profile div#building div.building_panel span.level{
-    position: relative;
-    bottom: 1.6em;
-    font-weight: bold;
-    color: #000;
-    text-shadow: 0 0 0.1em #fff, 0 0 0.2em #fff, 0 0 0.4em #fff, 0 0 0.4em #fff;
-    bottom: 1.4em;
-    z-index: 1;
-    font-size: 1em;
-    display: block;
-    text-align: right;
-    pointer-events: none;
+    font-size: 50%;
 }
 
 

+ 15 - 0
public/css/register.css

@@ -0,0 +1,15 @@
+form table{
+    margin: auto;
+}
+form table td.label{
+    text-align: right;
+    padding-right: 1em;
+}
+form table td.input{
+    text-align: left;
+}
+form table td.submit{
+    text-align: center;
+}
+
+

+ 31 - 0
public/css/ui.css

@@ -887,6 +887,37 @@ div.monster_transformation_panel img.monster_transformation{
 /**
  * /Monster transformation panel
  */
+div.building_panel{
+    display: inline-block;
+    width: 4em;
+    height: 4em;
+    margin: 0.2em 0em;
+    position: relative;
+    border-radius: 15%;
+    vertical-align: middle;
+}
+
+div.building_panel img.building, img.decoration{
+    width: 4em;
+    height: 4em;
+    border-style: solid;
+    border-width: 0.1em;
+    border-radius: 15%;
+}
+
+div.building_panel span.level{
+    position: relative;
+    bottom: 1.6em;
+    font-weight: bold;
+    color: #000;
+    text-shadow: 0 0 0.1em #fff, 0 0 0.2em #fff, 0 0 0.4em #fff, 0 0 0.4em #fff;
+    bottom: 1.4em;
+    z-index: 1;
+    font-size: 1em;
+    display: block;
+    text-align: right;
+    pointer-events: none;
+}
  
  
 /**