Răsfoiți Sursa

Artifacts section

Iñigo Valentin 6 ani în urmă
părinte
comite
9fbf4ed021

+ 21 - 0
application/Constant.php

@@ -1944,6 +1944,27 @@
             "GROUP" => "SLOT"
         ];
 
+        /**
+         * Default values for the artifact filters.
+         */
+        const ARTIFACT = [
+            "TYPE" => 0,
+            "ELEMENT" => [],
+            "ARCHETYPE" => [],
+            "MAIN" => [],
+            "MIN_QUALITY" => QUALITY_ID::NORMAL,
+            "MAX_QUALITY" => QUALITY_ID::LEGEND,
+            "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
+            "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
+            "MIN_LEVEL" => 0,
+            "MAX_LEVEL" => 15,
+            "MIN_EFFICIENCY" => 0,
+            "MAX_EFFICIENCY" => 100,
+            "MIN_MAX_EFFICIENCY" => 0,
+            "MAX_MAX_EFFICIENCY" => 100,
+            "ASSIGNED" => 1
+        ];
+
         /**
          * Default values for the run filters.
          */

+ 4 - 0
application/Controller.php

@@ -195,6 +195,10 @@
                     require_once(PATH::PAGE . "Runes_Page.php");
                     $page = new Runes_Page();
                 }
+                elseif (strtoupper($pars[0]) == "ARTIFACTS"){
+                    require_once(PATH::PAGE . "Artifacts_Page.php");
+                    $page = new Artifacts_Page();
+                }
                 elseif (strtoupper($pars[0]) == "GUILD"){
                     require_once(PATH::PAGE . "Guild_Page.php");
                     $page = new Guild_Page();

+ 7 - 0
application/action/login.php

@@ -26,20 +26,26 @@
         global $db;
 
         if (!isset($_POST['uname'], $_POST['password'])){
+error_log("-1");
             return -1;
         }
         $uname = SQLite3::escapeString($_POST['uname']);
         if (strlen($uname) == 0){
+error_log("-2");
             return -2;
         }
         $password = SQLite3::escapeString($_POST['password']);
         if (strlen($password) == 0){
+error_log("-3");
             return -3;
         }
         $password = hash('sha256', $password);
+error_log("SELECT uid FROM player WHERE upper(name) = upper('$uname') AND password = '$password';");
         $q = $db->query("SELECT uid FROM player;");
         $r = $q->fetchArray(SQLITE3_ASSOC);
+error_log("RET ID: " . $r["uid"]);
         if (!$r){
+error_log("-4");
             return -4;
         }
         $uid = $r["uid"];
@@ -50,6 +56,7 @@
         $_SESSION['uid'] = $uid;
         header("Location: /$uid/");
         die();
+error_log("0");
         return 0;
     }
 ?>

+ 1 - 1
application/entity/Artifact.php

@@ -240,7 +240,7 @@
                 $this->id = $r["id"];
                 $this->assigned_to = $r["assigned_to"];
                 $this->type = $r["type"];
-                $this->attribute = $r["attribute"];
+                $this->element = $r["attribute"];
                 $this->archetype = $r["archetype"];
                 $this->level = $r["level"];
                 $this->quality = $r["quality"];

+ 13 - 13
application/entity/Unit.php

@@ -307,24 +307,24 @@
                     $this->check_storage();
                     $this->lock = $r["lock"];
                     $s =
-                    "SELECT level " .
-                    "FROM " .
-                    "  unit_skill, " .
-                    "  k_skill " .
-                    "WHERE " .
-                    "  k_skill.id = unit_skill.skill AND " .
-                    "  unit = '$this->id' " .
-                    "ORDER BY slot;";
+                      "SELECT level " .
+                      "FROM " .
+                      "  unit_skill, " .
+                      "  k_skill " .
+                      "WHERE " .
+                      "  k_skill.id = unit_skill.skill AND " .
+                      "  unit = '$this->id' " .
+                      "ORDER BY slot;";
                     $q = $db->query($s);
                     while ($r = $q->fetchArray(SQLITE3_ASSOC)){
                         array_push($this->skill_levels, $r["level"]);
                     }
                     $s =
-                    "SELECT exp " .
-                    "FROM k_experience " .
-                    "WHERE " .
-                    "  stars = $this->stars AND " .
-                    "  level = $this->level;";
+                      "SELECT exp " .
+                      "FROM k_experience " .
+                      "WHERE " .
+                      "  stars = $this->stars AND " .
+                      "  level = $this->level;";
                     $q = $db->query($s);
                     $r = $q->fetchArray(SQLITE3_ASSOC);
                     $this->experience_level = $r["exp"];

+ 1 - 1
application/helper/HTML_Helper.php

@@ -383,7 +383,7 @@
             else{
                 $background = URL::IMG["ARTIFACT"] . "element_" . strtolower($artifact->quality_name) . ".png";
                 $icon = URL::IMG["ARTIFACT"] . "element_";
-                switch ($artifact->attribute){
+                switch ($artifact->element){
                     case ELEMENT_ID::WATER:
                         $icon .= "water";
                         break;

+ 246 - 0
application/page/Artifacts_Page.php

@@ -0,0 +1,246 @@
+ <?php
+ 
+    /**
+     * Artifact list page file.
+     *
+     * Provides a class with all the properties and methods to display the page.
+     *
+     * @category Page
+     */
+
+    /**
+     * Require dependent files if not present.
+     */
+    require_once(PATH::PAGE . "Page.php");
+    require_once(PATH::ENTITY . "Custom_Filter.php");
+    require_once(PATH::ENTITY . "Artifact.php");
+    require_once(PATH::ENTITY . "Unit.php");
+
+    /**
+     * Artifact list page model.
+     *
+     * @category Page
+     */
+    class Artifacts_Page extends Page{
+
+        /**
+         * @var \Artifact[] Artiffacts to show.
+         *
+         * In this case, the monster member is not the id, but a monster
+         * instance.
+         */
+        public $artifacts = [];
+
+        /**
+         * @var \Filter[] Custom filters for this page.
+         */
+        public $custom_filters = [];
+
+        /**
+         * Constructor.
+         *
+         * Retrieves the data and initializes the variables.
+         *
+         * @global int Player ID.
+         * @global resource Database connection.
+         */
+        public function __construct(){
+            global $UID;
+            global $db;
+            $this->view = PATH::VIEW . "artifacts.php";
+            $this->parse_filters();
+            if (!isset($_GET["custom_filter"])){
+                $s = $this->build_query();
+            }
+            else{
+                $s = $this->build_custom_query($_GET["custom_filter"]);
+            }
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                $artifact = new Artifact($r["id"]);
+                if (strlen($artifact->assigned_to) > 0){
+                    $artifact->assigned_to = new Unit($artifact->assigned_to, false);
+                }
+                array_push($this->artifacts, $artifact);
+            }
+            $s = "
+              SELECT id
+              FROM filter
+              WHERE
+                uid = '$UID' AND
+                page = 'ARTIFACTS';
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->custom_filters, new Custom_Filter($r["id"]));
+            }
+            $this->title = "Artifacts - SWDB";
+            $this->description = "Artifact inventory";
+            $this->canonical = URL::BASE . "artifacts/";
+        }
+
+        /**
+         * Parses the request looking for the selected filters, validates them
+         * and adds them to the $filters array.
+         */
+        private function parse_filters(){
+            $this->filters = FILTER::ARTIFACT;
+            if (isset($_GET["element"])){
+                $elements = $_GET["element"];
+                foreach ($elements as $element){
+                    array_push($this->filters["ELEMENT"], intval($element));
+                }
+            }
+            if (isset($_GET["archetype"])){
+                $archetypes = $_GET["archetype"];
+                foreach ($archetypes as $archetype){
+                    array_push($this->filters["ARCHETYPE"], intval($archetype));
+                }
+            }
+            if (isset($_GET["main_stat"])){
+                $mains = $_GET["main_stat"];
+                foreach ($mains as $main){
+                    array_push($this->filters["MAIN"], intval($main));
+                }
+            }
+            if (isset($_GET["min_level"]) && intval($_GET["min_level"]) >= 0 && intval($_GET["min_level"]) <= 15){
+                $this->filters["MIN_LEVEL"] = $_GET["min_level"];
+            }
+            if (isset($_GET["max_level"]) && intval($_GET["max_level"]) >= 0 && intval($_GET["max_level"]) <= 15){
+                $this->filters["MAX_LEVEL"] = $_GET["max_level"];
+            }
+            if (isset($_GET["min_quality"]) && intval($_GET["min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_quality"]) <= QUALITY_ID::LEGEND){
+                $this->filters["MIN_QUALITY"] = $_GET["min_quality"];
+            }
+            if (isset($_GET["max_quality"]) && intval($_GET["max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_quality"]) <= QUALITY_ID::LEGEND){
+                $this->filters["MAX_QUALITY"] = $_GET["max_quality"];
+            }
+            if (isset($_GET["min_original_quality"]) && intval($_GET["min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["min_original_quality"]) <= QUALITY_ID::LEGEND){
+                $this->filters["MIN_ORIGINAL_QUALITY"] = $_GET["min_original_quality"];
+            }
+            if (isset($_GET["max_original_quality"]) && intval($_GET["max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["max_original_quality"]) <= QUALITY_ID::LEGEND){
+                $this->filters["MAX_ORIGINAL_QUALITY"] = $_GET["max_original_quality"];
+            }
+            if (isset($_GET["assigned"]) && intval($_GET["assigned"]) >= 0 && intval($_GET["assigned"]) <= 4){
+                $this->filters["ASSIGNED"] = $_GET["assigned"];
+            }
+        }
+
+        /**
+         * Builds the query to the artifact table using the a custom filter.
+         * 
+         * @param int $filter Custom filter ID.
+         * @return string The query to be executed.
+         * @global int Player ID.
+         * @global resource Database connection.
+         */
+        private function build_custom_query($filter){
+            global $UID;
+            global $db;
+            $s = "
+              SELECT condition
+              FROM filter
+              WHERE
+                uid = '$UID' AND
+                id = $filter;
+            ";
+            $q = $db->query($s);
+            $r = $q->fetchArray(SQLITE3_ASSOC);
+            $cond = $r["condition"];
+            $s = "
+              SELECT
+                id,
+                assigned_to
+              FROM artifact
+              WHERE uid = '$UID' AND (
+                $cond
+              )
+              ORDER BY slot, type, stars DESC, original_quality DESC, quality DESC, level;
+            ";
+            return $s;
+        }
+
+        /**
+         * Builds the query to the artifact table using the selected or default
+         * filters.
+         * 
+         * @return string The query to be executed.
+         * @global int Player ID.
+         */
+        private function build_query(){
+            global $UID;
+            $s =
+              "SELECT " .
+              "  id, " .
+              "  assigned_to " .
+              "FROM artifact " .
+              "WHERE " .
+              "  uid = '$UID' AND " .
+              "  level >= " . $this->filters["MIN_LEVEL"] . " AND " .
+              "  level <= " . $this->filters["MAX_LEVEL"] . " AND " .
+              "  quality >= " . $this->filters["MIN_QUALITY"] . " AND " .
+              "  quality <= " . $this->filters["MAX_QUALITY"] . " AND " .
+              "  original_quality >= " . $this->filters["MIN_ORIGINAL_QUALITY"] . " AND " .
+              "  original_quality <= " . $this->filters["MAX_ORIGINAL_QUALITY"] . " AND " .
+              "  efficiency >= " . $this->filters["MIN_EFFICIENCY"] . " AND " .
+              "  efficiency <= " . $this->filters["MAX_EFFICIENCY"] . " AND " .
+              "  max_efficiency >= " . $this->filters["MIN_MAX_EFFICIENCY"] . " AND " .
+              "  max_efficiency <= " . $this->filters["MAX_MAX_EFFICIENCY"] . " ";
+            if (count($this->filters["MAIN"]) > 0){
+                $s = $s . " AND main_stat IN ( ";
+                foreach($this->filters["MAIN"] as $t){
+                    $s = $s . "$t, ";
+                }
+                $s = $s . "-1) ";
+            }
+            if (count($this->filters["ELEMENT"]) == 0 && count($this->filters["ARCHETYPE"]) == 0){
+                // No element/archetype conditions
+            }
+            elseif (count($this->filters["ELEMENT"]) > 0 && count($this->filters["ARCHETYPE"]) == 0){
+                // Only selected elements
+                $s = $s . " AND attribute IN ( ";
+                foreach($this->filters["ELEMENT"] as $t){
+                    $s = $s . "$t, ";
+                }
+                $s = $s . "-1) ";
+            }
+            elseif (count($this->filters["ELEMENT"]) == 0 && count($this->filters["ARCHETYPE"]) > 0){
+                // Only selected types
+                $s = $s . " AND archetype IN ( ";
+                foreach($this->filters["ARCHETYPE"] as $t){
+                    $s = $s . "$t, ";
+                }
+                $s = $s . "-1) ";
+            }
+            elseif (count($this->filters["ELEMENT"]) > 0 && count($this->filters["ARCHETYPE"]) > 0){
+                // Selected elements and selected types
+                $s = $s . " AND (archetype IN ( ";
+                foreach($this->filters["ARCHETYPE"] as $t){
+                    $s = $s . "$t, ";
+                }
+                $s = $s . "-1) OR attribute IN ( ";
+                foreach($this->filters["ELEMENT"] as $t){
+                    $s = $s . "$t, ";
+                }
+                $s = $s . "-1)) ";
+            }
+            switch ($this->filters["ASSIGNED"]){
+                case 1:
+                    $s = $s . " AND assigned_to IS NOT NULL ";
+                    break;
+                case 2:
+                    $s = $s . " AND assigned_to IS NULL ";
+                    break;
+                case 3:
+                    $s = $s . " AND (assigned_to IS NULL OR assigned_to IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ")) ";
+                    break;
+                case 4:
+                    $s = $s . " AND assigned_to IN (SELECT DISTINCT id FROM unit WHERE building <> " . BUILDING_ID::MONSTER_STORAGE . ") ";
+                    break;
+            }
+            $s = $s . " ORDER BY type, attribute, archetype, level DESC, original_quality DESC;";
+            error_log($s);
+            return $s;
+        }
+    }
+?>

+ 166 - 0
application/view/artifacts.php

@@ -0,0 +1,166 @@
+<?php
+    /**
+     * Artifacts view.
+     *
+     * Contains the view layout and ome code to present the data.
+     *
+     * @category View
+     * @property_read Artifacts_Page $page The page model.
+     */
+?>
+<!DOCTYPE html>
+<html lang='en'>
+    <head>
+        <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
+        <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
+        <title><?=$page->title?></title>
+        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <!-- CSS files -->
+        <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
+        <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>artifacts.css'/>
+        <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>filters.css'/>
+        <!-- Meta tags -->
+        <link rel='canonical' href='<?=$page->canonical?>'/>
+        <link rel='author' href='<?=$page->author?>'/>
+        <link rel='publisher' href='<?=$page->author?>'/>
+        <meta name='description' content='<?=$page->description?>'/>
+        <meta property='og:title' content='<?=$page->title?>'/>
+        <meta property='og:url' content='<?=$page->canonical?>'/>
+        <meta property='og:description' content='<?=$page->description?>'/>
+        <meta property='og:image' content='<?=$page->icon?>'/>
+        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <meta property='og:type' content='website'/>
+        <meta property='og:locale' content='en'/>
+        <meta name='twitter:card' content='summary'/>
+        <meta name='twitter:title' content='<?=$page->title?>'/>
+        <meta name='twitter:description' content='<?=$page->description?>'/>
+        <meta name='twitter:image' content='<?=$page->icon?>'/>
+        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='robots' content='index follow'/>
+        <script>
+
+            /**
+             * Shows or hiddes the filters panel.
+             */
+            function toggleFilters(){
+                var content = document.getElementById('filters_content');
+                var slid = document.getElementById('filters_slid');
+                if (content.style.maxHeight != '55em'){
+                    content.style.maxHeight = '55em';
+                    slid.style.transform = 'rotate(90deg)';
+                }
+                else{
+                    content.style.maxHeight = '0px';
+                    slid.style.transform = 'rotate(0deg)';
+                }
+            };
+        </script>
+    </head>
+    <body>
+<?php
+        include __DIR__ . "/inc/header.php";
+?>
+        <section class='filters'>
+            <h2 id='filters_title' onClick='toggleFilters();'>
+                <img id='filters_slid' id='filters_slid' alt=' ' src='<?=URL::IMG["ICON"]?>slid.png'/>
+                Artifact filters
+            </h2>
+            <article id='filters_content'>
+<?php
+                $filters = $page->filters;
+                $custom_filters = $page->custom_filters;
+                include __DIR__ . "/inc/filter_artifacts.php";
+?>
+            </article>
+
+        </section> <!-- #filters -->
+<?php
+            $prev_group = "";
+            $group = "";
+            $group_title = "";
+            $group_image = "";
+            foreach ($page->artifacts as $artifact){
+                $group = $artifact->type . "-" . $artifact->element . "-" . $artifact->archetype;
+                
+                if ($prev_group != $group){
+                    switch ($artifact->type){
+                        case ARTIFACT_TYPE::ELEMENT:
+                            switch ($artifact->element){
+                                case ELEMENT_ID::WATER:
+                                    $group_title = "Water";
+                                    $group_image = URL::IMG["ARTIFACT"] . "element_water.png";
+                                    break;
+                                case ELEMENT_ID::FIRE:
+                                    $group_title = "Fire";
+                                    $group_image = URL::IMG["ARTIFACT"] . "element_fire.png";
+                                    break;
+                                case ELEMENT_ID::WIND:
+                                    $group_title = "Wind";
+                                    $group_image = URL::IMG["ARTIFACT"] . "element_wind.png";
+                                    break;
+                                case ELEMENT_ID::LIGHT:
+                                    $group_title = "Light";
+                                    $group_image = URL::IMG["ARTIFACT"] . "element_light.png";
+                                    break;
+                                case ELEMENT_ID::DARK:
+                                    $group_title = "Dark";
+                                    $group_image = URL::IMG["ARTIFACT"] . "element_dark.png";
+                                    break;
+                            }
+                            break;
+                        case ARTIFACT_TYPE::ARCHETYPE:
+                            switch ($artifact->archetype){
+                                case ARCHETYPE_ID::ATTACK:
+                                    $group_title = "Attack";
+                                    $group_image = URL::IMG["ARTIFACT"] . "type_attack.png";
+                                    break;
+                                case ARCHETYPE_ID::DEFENSE:
+                                    $group_title = "Defense";
+                                    $group_image = URL::IMG["ARTIFACT"] . "type_defense.png";
+                                    break;
+                                case ARCHETYPE_ID::SUPPORT:
+                                    $group_title = "Support";
+                                    $group_image = URL::IMG["ARTIFACT"] . "type_support.png";
+                                    break;
+                                case ARCHETYPE_ID::HP:
+                                    $group_title = "HP";
+                                    $group_image = URL::IMG["ARTIFACT"] . "type_hp.png";
+                                    break;
+                            }
+                    }
+                    if ($prev_group == ""){
+?>
+                        <section class='list'>
+<?php
+                    }
+                    else{
+?>
+                            </article>
+                        </section>
+                        <section class='list'>
+<?php
+                    }
+                    $prev_group = $group;
+?>
+                    <h2>
+                        <img class='group_image_<?=$group?>' alt='<?=$group_title?>' src='<?=$group_image?>'>
+                        <span>
+                            <?=$group_title?>
+                        </span>
+                    </h2>
+                    <article>
+<?php
+                }
+?>
+                <?=HTML::artifact_table($artifact, $artifact->assigned_to)?>
+<?php
+            }
+?>
+            </article> <!-- Close last group -->
+        </section>
+
+<?php
+        include __DIR__ . "/inc/footer.php";
+?>
+    </body>
+</html>

+ 204 - 0
application/view/inc/filter_artifacts.php

@@ -0,0 +1,204 @@
+<?php
+    /**
+     * Artifact filter view.
+     *
+     * To be included from the artifact view.
+     *
+     * @category View
+     * @property_read mixed[] $filters Selected filters.
+     * @property_read int $page Player ID.
+     */
+
+    if (count($custom_filters) > 0){
+?>
+        <script>
+            /**
+             * Changes the filter description.
+             *
+             * @param id Filter id.
+             */
+            function customFilterDescription(id){
+                switch (id){
+<?php
+                    foreach($custom_filters AS $filter){
+?>
+                        case '<?=$filter->id?>':
+                            document.getElementById("custom_filter_description").style.display = 'block';
+                            document.getElementById("custom_filter_description").innerHTML = '<?=$filter->description?>';
+                            break;
+<?php
+                    }
+?>
+                }
+            }
+        </script>
+        <form action='/<?=$UID?>/artifacts/' method='get' id='custom_filter_artifacts' class='custom_filter'>
+            <span class='custom_filter_title'>Custom filters:</span>
+            <select name='custom_filter' onChange='customFilterDescription(this.value);' onload='customFilterDescription("<?=filter_input(INPUT_GET, 'custom_filter')?>");'>
+                <option> </option>
+<?php
+                 foreach($custom_filters AS $filter){
+                    if (filter_input(INPUT_GET, 'custom_filter') == $filter->id){
+                        $selected = "selected='selected'";
+                    }
+                    else{
+                        $selected = "";
+                    }
+?>
+                    <option value='<?=$filter->id?>' <?=$selected?>><?=$filter->name?></option>
+<?php
+                 }
+?>
+            </select>
+            <input type='submit' value='Apply'/>
+            <p id='custom_filter_description'> </p>
+            <script>
+                customFilterDescription("<?=filter_input(INPUT_GET, 'custom_filter')?>");
+            </script>
+        </form>
+<?php
+    }
+?>
+<form action='/<?=$UID?>/artifacts/' method='get' id='filter_artifacts' class='filter'>
+    <div class='custom_filters'>
+    <table>
+        <tr>
+            <td class='filter'>
+                <span>Element:</span>
+                <select multiple name='element[]' id='filter_element'>
+<?php
+                    $reflect = new ReflectionClass("ELEMENT_ID");
+                    foreach($reflect->getConstants() as $name => $id){
+                        if ($id != ELEMENT_ID::PURE){
+                            $selected = "";
+                            if (in_array($id, $filters["ELEMENT"])){
+                                $selected = "selected='selected'";
+                            }
+?>
+                            <option value='<?=$id?>' <?=$selected?>><?=$name?></option>
+<?php
+                        }
+                    }
+?>
+                </select>
+            </td>
+            <td class='filter'>
+                <span>Type:</span>
+                <select multiple name='archetype[]' id='filter_archetype'>
+<?php
+                    $reflect = new ReflectionClass("ARCHETYPE_ID");
+                    foreach($reflect->getConstants() as $name => $id){
+                        if ($id != ARCHETYPE_ID::NONE && $id != ARCHETYPE_ID::MATERIAL){
+                            $selected = "";
+                            if (in_array($id, $filters["ARCHETYPE"])){
+                                $selected = "selected='selected'";
+                            }
+?>
+                            <option value='<?=$id?>' <?=$selected?>><?=$name?></option>
+<?php
+                        }
+                    }
+?>
+                </select>
+            </td>
+            <td class='filter'>
+                <span>Main stat:</span>
+                <select multiple name='main_stat[]' id='filter_main_stat'>
+<?php
+                    $reflect = new ReflectionClass("ARTIFACT_STAT_ID");
+                    foreach($reflect->getConstants() as $name => $id){
+                        $selected = "";
+                        if (in_array($id, $filters["MAIN"])){
+                            $selected = "selected='selected'";
+                        }
+?>
+                        <option value='<?=$id?>' <?=$selected?>><?=$name?></option>
+<?php
+                    }
+?>
+                </select>
+            </td>
+        </tr>
+        <tr>
+            <td class='filter'>
+                <span>Level:</span>
+                <input type='number' name='min_level' id='filter_level_min' min='0' max='15' value='<?=$filters["MIN_LEVEL"]?>'/>
+                -
+                <input type='number' name='max_level' id='filter_level_max' min='0' max='15' value='<?=$filters["MAX_LEVEL"]?>'/>
+            </td>
+            <td class='filter' colspan='2'>
+                <span>Quality:</span>
+<?php
+                $selected = Array("", "", "", "", "");
+                $selected[$filters["MIN_QUALITY"] - 1] = "selected";
+?>
+                <select name='min_quality' id='filter_quality_min'>
+                    <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
+                    <option value='<?=QUALITY_ID::MAGIC?>' <?=$selected[1]?>>Magic</option>
+                    <option value='<?=QUALITY_ID::RARE?>' <?=$selected[2]?>>Rare</option>
+                    <option value='<?=QUALITY_ID::HERO?>' <?=$selected[3]?>>Hero</option>
+                    <option value='<?=QUALITY_ID::LEGEND?>' <?=$selected[4]?>>Legend</option>
+                </select>
+                -
+<?php
+                $selected = Array("", "", "", "", "");
+                $selected[$filters["MAX_QUALITY"] - 1] = "selected";
+?>
+                <select name='max_quality' id='filter_quality_max'>
+                    <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
+                    <option value='<?=QUALITY_ID::MAGIC?>' <?=$selected[1]?>>Magic</option>
+                    <option value='<?=QUALITY_ID::RARE?>' <?=$selected[2]?>>Rare</option>
+                    <option value='<?=QUALITY_ID::HERO?>' <?=$selected[3]?>>Hero</option>
+                    <option value='<?=QUALITY_ID::LEGEND?>' <?=$selected[4]?>>Legend</option>
+                </select>
+            </td>
+        </tr>
+        <tr>
+            <td class='filter'>
+                <span>
+                    Assigned:
+                </span>
+<?php
+                $selected = Array("", "", "", "", "");
+                $selected[$filters["ASSIGNED"]] = "selected";
+?>
+                <select name='assigned' id='filter_assigned'>
+                    <option value='0' <?=$selected[0]?>>All</option>
+                    <option value='1' <?=$selected[1]?>>Assigned</option>
+                    <option value='2' <?=$selected[2]?>>Unassigned</option>
+                    <option value='3' <?=$selected[3]?>>All (no storage)</option>
+                    <option value='4' <?=$selected[4]?>>Assigned (no storage)</option>
+                </select>
+            </td>
+            <td class='filter' colspan='2'>
+                <span>Original quality:</span>
+<?php
+                $selected = Array("", "", "", "", "");
+                $selected[$filters["MIN_ORIGINAL_QUALITY"] - 1] = "selected";
+?>
+                <select name='min_original_quality' id='filter_original_quality_min'>
+                    <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
+                    <option value='<?=QUALITY_ID::MAGIC?>' <?=$selected[1]?>>Magic</option>
+                    <option value='<?=QUALITY_ID::RARE?>' <?=$selected[2]?>>Rare</option>
+                    <option value='<?=QUALITY_ID::HERO?>' <?=$selected[3]?>>Hero</option>
+                    <option value='<?=QUALITY_ID::LEGEND?>' <?=$selected[4]?>>Legend</option>
+                </select>
+                -
+<?php
+                $selected = Array("", "", "", "", "");
+                $selected[$filters["MAX_ORIGINAL_QUALITY"] - 1] = "selected";
+?>
+                <select name='max_original_quality' id='filter_original_quality_max'>
+                    <option value='<?=QUALITY_ID::NORMAL?>' <?=$selected[0]?>>Normal</option>
+                    <option value='<?=QUALITY_ID::MAGIC?>' <?=$selected[1]?>>Magic</option>
+                    <option value='<?=QUALITY_ID::RARE?>' <?=$selected[2]?>>Rare</option>
+                    <option value='<?=QUALITY_ID::HERO?>' <?=$selected[3]?>>Hero</option>
+                    <option value='<?=QUALITY_ID::LEGEND?>' <?=$selected[4]?>>Legend</option>
+                </select>
+            </td>
+        </tr>
+    </table>
+    <div id='filter_apply'>
+        <input type='submit' value='Apply'/>
+    </div>
+</form>

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

@@ -34,7 +34,7 @@
         </script>
         <form action='/<?=$UID?>/runes/' method='get' id='custom_filter_runes' class='custom_filter'>
             <span class='custom_filter_title'>Custom filters:</span>
-            <select name='custom_filter' onChange='customFilterDescription(this.value);' onload='alert("LOAD");customFilterDescription("<?=filter_input(INPUT_GET, 'custom_filter')?>");'>
+            <select name='custom_filter' onChange='customFilterDescription(this.value);' onload='customFilterDescription("<?=filter_input(INPUT_GET, 'custom_filter')?>");'>
                 <option> </option>
 <?php
                  foreach($custom_filters AS $filter){

+ 3 - 0
application/view/inc/header.php

@@ -33,6 +33,9 @@
             <a href='/<?=$UID?>/runes/'>
                 Runes
             </a>
+            <a href='/<?=$UID?>/artifacts/'>
+                Artifacts
+            </a>
             <a href='/<?=$UID?>/fusion/'>
                 Fusion
             </a>

+ 42 - 0
public/css/artifacts.css

@@ -0,0 +1,42 @@
+section.filters td.filter select#filter_element{
+    overflow: hidden;
+    height: 7em;
+}
+section.filters td.filter select#filter_archetype{
+    height: 6em;
+    overflow: hidden;
+}
+section.filters td.filter select#filter_main_stat{
+    height: 5em;
+    overflow: hidden;
+}
+section.filters td.filter select#filter_sub_stat{
+    height: 5em;
+    overflow: hidden;
+}
+
+section h2 img, span{
+    display: inline-block;
+    vertical-align: middle;
+}
+section h2 img{
+    height: 1.5em;
+}
+section h2 img.group_image_1{
+    transform: rotate(0deg);
+}
+section h2 img.group_image_2{
+    transform: rotate(57deg);
+}
+section h2 img.group_image_3{
+    transform: rotate(123deg);
+}
+section h2 img.group_image_4{
+    transform: rotate(180deg);
+}
+section h2 img.group_image_5{
+    transform: rotate(237deg);
+}
+section h2 img.group_image_6{
+    transform: rotate(303deg);
+}

+ 12 - 4
public/css/ui.css

@@ -729,12 +729,16 @@ table.rune{
     font-size: 70%;
     border: 0.3em solid #3c2929;
 }
+table.rune td.icon{
+    vertical-align: top;
+    padding-top: 0.3em;
+}
 table.rune td.icon div.assigned{
     max-width: 2.5em;
     max-height: 2.5em;
     position: absolute;
-    left: 0.5em;
-    bottom: 1em;
+    left: 0.2em;
+    top: 3.6em;
 }
 table.rune td.icon div.assigned img.monster_image{
     width: 2.5em;
@@ -827,12 +831,16 @@ table.artifact{
     font-size: 70%;
     border: 0.3em solid #3c2929;
 }
+table.artifact td.icon{
+    vertical-align: top;
+    padding-top: 0.3em;
+}
 table.artifact td.icon div.assigned{
     max-width: 2.5em;
     max-height: 2.5em;
     position: absolute;
-    left: 0.5em;
-    bottom: 1em;
+    left: 0.2em;
+    top: 3.6em;
 }
 table.artifact td.icon div.assigned img.monster_image{
     width: 2.5em;