Kaynağa Gözat

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

Iñigo Valentin 5 yıl önce
ebeveyn
işleme
d9607d0b6b
60 değiştirilmiş dosya ile 992 ekleme ve 163 silme
  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(":value", $rune->{"sec_eff"}[0][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[0][2], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[0][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[0][3], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[0][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
         $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(":value", $rune->{"sec_eff"}[1][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[1][2], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[1][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[1][3], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[1][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
         $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(":value", $rune->{"sec_eff"}[2][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[2][2], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[2][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[2][3], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[2][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
         $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(":value", $rune->{"sec_eff"}[3][1], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[3][2], SQLITE3_INTEGER);
         $statement->bindValue(":enchant", $rune->{"sec_eff"}[3][2], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[3][3], SQLITE3_INTEGER);
         $statement->bindValue(":grind", $rune->{"sec_eff"}[3][3], SQLITE3_INTEGER);
-        // TODO: Calculate rolls
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->bindValue(":rolls", 0, SQLITE3_INTEGER);
         $statement->execute();
         $statement->execute();
     }
     }

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

@@ -1104,9 +1104,6 @@ function log_cairos_run($db, $id, $player_id, $json){
                     default:
                     default:
                         $statement->bindValue(":value", 3870, SQLITE3_INTEGER);
                         $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(":efficiency", null, SQLITE3_FLOAT);
                 $statement->bindValue(":max_efficiency", null, SQLITE3_FLOAT);
                 $statement->bindValue(":max_efficiency", null, SQLITE3_FLOAT);
                 $statement->bindValue(":stat", $artifact->{"pri_effect"}[0], SQLITE3_INTEGER);
                 $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){
         if ($player_id != null){
             $this->context->set_player(new Player($player_id));
             $this->context->set_player(new Player($player_id));
             if ($this->context->get_player()->get_id() == null){
             if ($this->context->get_player()->get_id() == null){
-                // TODO: error 404;
                 $this->status = 404;
                 $this->status = 404;
                 $this->message = "Requested player doesn't exist";
                 $this->message = "Requested player doesn't exist";
                 return;
                 return;
@@ -251,6 +250,7 @@ class Controller extends Context{
                 }
                 }
                 break;
                 break;
             case "API": // An API call
             case "API": // An API call
+                error_log("STARTING API CALL");
                 if (count($this->params) == 1){
                 if (count($this->params) == 1){
                     // TODO: Redirect to current version
                     // TODO: Redirect to current version
                 }
                 }
@@ -261,8 +261,10 @@ class Controller extends Context{
                     array_shift($api_params);
                     array_shift($api_params);
                     switch ($version){
                     switch ($version){
                         case "v1":
                         case "v1":
+                            error_log("STARTING API V1 Controller");
                             require_once(__DIR__ . "/API/v1/API_Controller.php");
                             require_once(__DIR__ . "/API/v1/API_Controller.php");
                             new API_Controller($this->params);
                             new API_Controller($this->params);
+                            return;
                             break;
                             break;
                         default:
                         default:
                             require_once(PATH::PAGE . "Error_Page.php");
                             require_once(PATH::PAGE . "Error_Page.php");
@@ -307,6 +309,10 @@ class Controller extends Context{
                         require_once(PATH::ACTION . "Logout_Action.php");
                         require_once(PATH::ACTION . "Logout_Action.php");
                         $action = new Logout_Action();
                         $action = new Logout_Action();
                         break;
                         break;
+                    case "REGISTER":
+                        require_once(PATH::ACTION . "Register_Action.php");
+                        $action = new Register_Action();
+                        break;
                     case "ADD_TEAM":
                     case "ADD_TEAM":
                         require_once(PATH::ACTION . "Add_Team_Action.php");
                         require_once(PATH::ACTION . "Add_Team_Action.php");
                         $action = new Add_Team_Action();
                         $action = new Add_Team_Action();
@@ -443,6 +449,17 @@ class Controller extends Context{
                     break;
                     break;
                 }
                 }
                 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
             case "LOGIN": // The login page
                 require_once(PATH::PAGE . "Login_Page.php");
                 require_once(PATH::PAGE . "Login_Page.php");
                 $page = new Login_Page();
                 $page = new Login_Page();
@@ -455,18 +472,25 @@ class Controller extends Context{
                 require_once(PATH::PAGE . "Search_Page.php");
                 require_once(PATH::PAGE . "Search_Page.php");
                 $page = new Search_Page();
                 $page = new Search_Page();
                 break;
                 break;
-            case "DUNGEON": // Dungeon static pages
+            /*case "DUNGEONS": // Dungeon static pages
                 require_once(PATH::PAGE . "Login_Page.php");
                 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;
                 break;
-            case "BUILDING": // Building static pages
-                require_once(PATH::PAGE . "Building_Page.php");
-                $page = new Building_Page();
                 break;
                 break;
-            case "FUSION": // Fusion static pages
+            /*case "FUSION": // Fusion static pages
                 require_once(PATH::PAGE . "Fusion_Page.php");
                 require_once(PATH::PAGE . "Fusion_Page.php");
                 $page = new Fusion_Page();
                 $page = new Fusion_Page();
-                break;
+                break;*/
             case "HELP": // Help static page
             case "HELP": // Help static page
                 require_once(PATH::PAGE . "Help_Page.php");
                 require_once(PATH::PAGE . "Help_Page.php");
                 $page = new Help_Page();
                 $page = new Help_Page();

+ 3 - 2
application/action/Add_Team_Action.php

@@ -12,7 +12,7 @@
 require_once(PATH::ACTION . "Action.php");
 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:
  * Reads the POST parameters looking for the following KEYS:
  *  player: The owner's player ID.
  *  player: The owner's player ID.
@@ -22,11 +22,12 @@ require_once(PATH::ACTION . "Action.php");
  *  difficulty: Optional, the difficulty ID ({@see DIFFICULTY_ID})
  *  difficulty: Optional, the difficulty ID ({@see DIFFICULTY_ID})
  *  ids: Unit IDs of the party.
  *  ids: Unit IDs of the party.
  *  name: Team name.
  *  name: Team name.
+ *  leader: Id of the leader unit.
+ *  front: Number of units in the frontline.
  *  description: Optional, team description.
  *  description: Optional, team description.
  * Validates the data and creates the team in the database.
  * Validates the data and creates the team in the database.
  * 
  * 
  * @category Action
  * @category Action
- * @todo: Document properly
  */
  */
 class Add_Team_Action extends Action{
 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.
  * Deletes a team.
  *
  *
  * Reads the POST parameters looking for the following KEYS:
  * Reads the POST parameters looking for the following KEYS:
- *  player: the team owner's player id.
  *  id: the team id.
  *  id: the team id.
  * 
  * 
  * @category Action
  * @category Action
@@ -24,21 +23,35 @@ class Delete_Team_Action extends Action{
 
 
     /**
     /**
      * Executes the action.
      * Executes the action.
-     * @todo secure
      */
      */
     function execute(){
     function execute(){
     
     
-        $player = filter_input(INPUT_POST, 'player');
         $id = filter_input(INPUT_POST, 'id');
         $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;
         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_view("artifacts.php");
         $this->set_title("Artifacts");
         $this->set_title("Artifacts");
         $this->set_description(get_context()->get_player()->get_name() . "'s 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->add_css("artifacts.css");
         
         
         $this->parse_filters();
         $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_view("enchantments.php");
         $this->set_title("Enchantments");
         $this->set_title("Enchantments");
         $this->set_description(get_context()->get_player()->get_name() . "'s 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->add_css("enchantments.css");
 
 
         $this->parse_filters();
         $this->parse_filters();

+ 1 - 1
application/page/Guild_Page.php

@@ -44,7 +44,7 @@ class Guild_Page extends Page{
         parent::__construct();
         parent::__construct();
         $this->set_public(true);
         $this->set_public(true);
         $this->set_view("guild.php");
         $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");
         $this->add_css("guild.css");
         
         
         $statement = get_context()->get_db()->prepare("
         $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_view("login.php");
         $this->set_title("Login");
         $this->set_title("Login");
         $this->set_description("Login to SWDB");
         $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){
         if (http_response_code() == 401){
             $this->is_error = true;
             $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
      * @var int[] IDs to other units of the family
-     * @todo Implement.
      */
      */
     private $family = [];
     private $family = [];
     
     
@@ -143,8 +142,6 @@ class Monster_Page extends Page{
             array_push($this->family, new Monster($result["id"]));
             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_title($title);
         $this->set_description($title . " details");
         $this->set_description($title . " details");
     }
     }

+ 0 - 24
application/page/Monsters_Page.php

@@ -24,11 +24,6 @@ class Monsters_Page extends Page{
      */
      */
     private $monsters = [];
     private $monsters = [];
 
 
-    /**
-     * @var int[] IDs of the monsters marked in the catalog.
-     */
-    private $monsters_open = [];
-
     /**
     /**
      * @var mixed[] Default filter values.
      * @var mixed[] Default filter values.
      */
      */
@@ -58,16 +53,6 @@ class Monsters_Page extends Page{
         while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
         while ($result = $result_set->fetchArray(SQLITE3_ASSOC)){
             array_push($this->monsters, new Monster($result["id"], false));
             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_code(200);
         $this->set_message("OK");
         $this->set_message("OK");
     }
     }
@@ -166,15 +151,6 @@ class Monsters_Page extends Page{
             return null;
             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_view("optimizer.php");
         $this->set_title("Optimizer");
         $this->set_title("Optimizer");
         $this->set_description("Rune 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");
         $this->add_css("optimizer.css");
         
         
         // Get teams
         // 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->unit = new Unit($id);
         $this->set_title("Optimize " . $this->unit->get_title());
         $this->set_title("Optimize " . $this->unit->get_title());
         $this->set_description("Optimize " . $this->unit->get_title() . "'s runes");
         $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->add_css("optimizer.css");
         $this->set_code(200);
         $this->set_code(200);
         $this->set_message("OK");
         $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_view("player.php");
         $this->set_title(get_context()->get_player()->get_name());
         $this->set_title(get_context()->get_player()->get_name());
         $this->set_description(get_context()->get_player()->get_name() . "'s profile");
         $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->add_css("player.css");
         $this->set_code(200);
         $this->set_code(200);
         $this->set_message("OK");
         $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_view("profile.php");
         $this->set_title(get_context()->get_user()->get_name() . "'s profile");
         $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_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_code(200);
         $this->set_message("OK");
         $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_view("report.php");
         $this->set_title("Reports");
         $this->set_title("Reports");
         $this->set_description("Reports for summoners");
         $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->add_css("report.css");
         $this->set_code(200);
         $this->set_code(200);
         $this->set_message("OK");
         $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_view("report_rune_enchantment.php");
         $this->set_title("Rune enchantment");
         $this->set_title("Rune enchantment");
         $this->set_description("Find runes that can be upgraded via enchantments");
         $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");
         $this->add_css("report_rune_enchantment.css");
         
         
         $prev_monster = "";
         $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_view("report_skillup.php");
         $this->set_title("Urgent skill-ups");
         $this->set_title("Urgent skill-ups");
         $this->set_description("FMonster in need of skilling up");
         $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->add_css("report_skillup.css");
         
         
         $this->parse_filters();
         $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_view("runes.php");
         $this->set_title("Runes");
         $this->set_title("Runes");
         $this->set_description(get_context()->get_player()->get_name() . "'s 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->add_css("runes.css");
         
         
         $this->parse_filters();
         $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_view("runs.php");
         $this->set_title("Runs");
         $this->set_title("Runs");
         $this->set_description(get_context()->get_player()->get_name() . "'s run logs");
         $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->add_css("runs.css");
         $this->parse_filters();
         $this->parse_filters();
         $result_set = $this->prepare_statement()->execute();
         $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.
      * and adds them to the $filters array.
      */
      */
     private function parse_filters(){
     private function parse_filters(){
-        $this->filters = FILTER::STATS;
         if (isset($_GET["area_type"]) && intval($_GET["area_type"]) > 0){
         if (isset($_GET["area_type"]) && intval($_GET["area_type"]) > 0){
             $this->filters["AREA_TYPE"] = $_GET["area_type"];
             $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_view("teams.php");
         $this->set_title("Teams");
         $this->set_title("Teams");
         $this->set_description(get_context()->get_player()->get_name() . "'s 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->add_css("teams.css");
 
 
         $this->parse_filters();
         $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_title($this->unit->get_title());
         $this->set_description(get_context()->get_player()->get_name() . "'s " . $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");
         $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_view("units.php");
         $this->set_title("Units");
         $this->set_title("Units");
         $this->set_description(get_context()->get_player()->get_name() . "'s 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->add_css("units.css");
 
 
         $this->parse_filters();
         $this->parse_filters();

+ 1 - 1
application/view/artifacts.php

@@ -29,7 +29,7 @@
             <p>
             <p>
                 Manage your enchantments
                 Manage your enchantments
             </p>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td class='label'>
                         <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>
             <p>
                 Manage your enchantments
                 Manage your enchantments
             </p>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td class='label'>
                         <td class='label'>

+ 12 - 6
application/view/help.php

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

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

@@ -61,7 +61,7 @@
                 else{
                 else{
 ?>
 ?>
                     <td class='item'>
                     <td class='item'>
-                        <a href='/<?=get_context()->get_user()->get_id()?>/'>
+                        <a href='/'>
                             Account
                             Account
                         </a>
                         </a>
                     </td>
                     </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
  * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
  * @package SWDB
  * @package SWDB
  * @category View
  * @category View
- * @property Landing_Page $page The page model.
+ * @property Login_Page $page The page model.
  * @var Login_Page $page The page model.
  * @var Login_Page $page The page model.
  */
  */
 ?>
 ?>
@@ -20,7 +20,6 @@
     <body>
     <body>
 <?php
 <?php
         include __DIR__ . "/inc/header_app.php";
         include __DIR__ . "/inc/header_app.php";
-        include __DIR__ . "/inc/header_player.php";
 ?>
 ?>
         <aside>
         <aside>
         </aside>
         </aside>

+ 1 - 1
application/view/monster.php

@@ -59,7 +59,7 @@
                 
                 
                 foreach ($page->get_family() as $family){
                 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'>
                         <div class='monster_panel'>
                             <?=HTML::unit_panel($family)?>
                             <?=HTML::unit_panel($family)?>
                         </div>
                         </div>

+ 3 - 9
application/view/monsters.php

@@ -30,7 +30,7 @@
             <p>
             <p>
                 A list with every monster in the game.
                 A list with every monster in the game.
             </p>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td class='label'>
                         <td class='label'>
@@ -92,15 +92,9 @@
                             }
                             }
                             $element = $monster->get_element();
                             $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'>
                                 <div class='monster_panel'>
                                     <?=HTML::unit_panel($monster)?>
                                     <?=HTML::unit_panel($monster)?>
                                 </div>
                                 </div>

+ 1 - 1
application/view/optimizer.php

@@ -79,7 +79,7 @@
              * @param unit ID of the unit to optimize.
              * @param unit ID of the unit to optimize.
              */
              */
             function optimize(unit){
             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){
                                 foreach($page->get_unit()->get_teams() as $team){
 ?>
 ?>
                                     <li>
                                     <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()?>
                                             <?=$team->get_name()?>
                                         </a>
                                         </a>
                                     </li>
                                     </li>

+ 1 - 1
application/view/player.php

@@ -537,7 +537,7 @@
                                                     }
                                                     }
                                                     if ($disabled == ""){
                                                     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
 <?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
                         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. 
                         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>
                     </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
                         Go
                     </a>
                     </a>
                 </article>
                 </article>
@@ -58,7 +58,7 @@
                         Shows monsters with runes that can be grinded or enchanted.
                         Shows monsters with runes that can be grinded or enchanted.
                         It list the grindstones and gems that are available for each rune.
                         It list the grindstones and gems that are available for each rune.
                     </p>
                     </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
                         Go
                     </a>
                     </a>
                 </article>
                 </article>

+ 2 - 2
application/view/report_rune_enchantment.php

@@ -85,7 +85,7 @@
             <h2>
             <h2>
                 Report filters
                 Report filters
             </h2>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td colspan='2' class='header'>
                         <td colspan='2' class='header'>
@@ -447,7 +447,7 @@
 ?>
 ?>
                         <tr>
                         <tr>
                             <td class='header' colspan='2'>
                             <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'>
                                     <div class='monster_panel'>
                                         <?=HTML::unit_panel($upgrade["unit"])?>
                                         <?=HTML::unit_panel($upgrade["unit"])?>
                                     </div>
                                     </div>

+ 2 - 2
application/view/report_skillup.php

@@ -29,7 +29,7 @@
                 Report filters
                 Report filters
             </h2>
             </h2>
             <article id='filters_content'>
             <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>
                     <table>
                         <tr>
                         <tr>
                             <td class='filter' id='filter_stars'>
                             <td class='filter' id='filter_stars'>
@@ -209,7 +209,7 @@
                         </tr>
                         </tr>
                         <tr>
                         <tr>
                             <td rowspan='3' class='img'>
                             <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'>
                                     <div class='monster_panel'>
                                         <?=HTML::unit_panel($unit)?>
                                         <?=HTML::unit_panel($unit)?>
                                     </div>
                                     </div>

+ 1 - 1
application/view/runes.php

@@ -87,7 +87,7 @@
             <p>
             <p>
                 Manage your runes
                 Manage your runes
             </p>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td class='label' >
                         <td class='label' >

+ 1 - 2
application/view/runs.php

@@ -129,7 +129,7 @@
             <p>
             <p>
                 View and compare saved runs
                 View and compare saved runs
             </p>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td class='label'>
                         <td class='label'>
@@ -490,7 +490,6 @@
                                         </div>
                                         </div>
 <?php
 <?php
                                     }
                                     }
-                                    // TODO: Artifacts
                                     foreach ($run->get_rewards()["enchantment"] as $enchantment){
                                     foreach ($run->get_rewards()["enchantment"] as $enchantment){
 ?>
 ?>
                                         <div class='item item_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>
             <p>
                 View and manage teams
                 View and manage teams
             </p>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td class='label'>
                         <td class='label'>

+ 2 - 2
application/view/unit.php

@@ -66,7 +66,7 @@
                                 foreach($page->get_unit()->get_teams() as $team){
                                 foreach($page->get_unit()->get_teams() as $team){
 ?>
 ?>
                                     <li>
                                     <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()?>
                                             <?=$team->get_name()?>
                                         </a>
                                         </a>
                                     </li>
                                     </li>
@@ -78,7 +78,7 @@
 <?php
 <?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
                         Optimize
                     </a>
                     </a>
                 </div>
                 </div>

+ 2 - 2
application/view/units.php

@@ -29,7 +29,7 @@
             <p>
             <p>
                 Monsters
                 Monsters
             </p>
             </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>
                 <table>
                     <tr>
                     <tr>
                         <td class='label'>
                         <td class='label'>
@@ -149,7 +149,7 @@
                     foreach ($page->get_units() as $unit){
                     foreach ($page->get_units() as $unit){
 ?>
 ?>
                         <div class='monster'>
                         <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'>
                                 <div class='monster_panel'>
                                     <?=HTML::unit_panel($unit)?>
                                     <?=HTML::unit_panel($unit)?>
                                 </div>
                                 </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(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(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(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(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(7,1,NULL,NULL,'Arcane Booster Tower','',10);
 INSERT INTO key.decorative VALUES(34,1,NULL,NULL,'Crystal Rock','',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{
 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
  * /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;
+}
  
  
  
  
 /**
 /**