Kaynağa Gözat

Basic optimizator implemented.

Iñigo Valentin 5 yıl önce
ebeveyn
işleme
e377aa95cf

+ 8 - 2
application/Controller.php

@@ -122,8 +122,14 @@
                         break;
                     case "OPTIMIZE":
                         require_once(PATH::ACTION . "optimize.php");
-                        action();
-                        return;
+                        $response = action();
+                        if (strlen($response) > 1){
+                            echo($response);
+                            return;
+                        }
+                        else{
+                            return;
+                        }
                         break;
                     case "EDIT_PROFILE":
                         require_once(PATH::ACTION . "edit_profile.php");

+ 416 - 19
application/action/optimize.php

@@ -26,18 +26,27 @@
     function action(){
 
         global $db;
+        
+        $candidates = [
+            1 => [],
+            2 => [],
+            3 => [],
+            4 => [],
+            5 => [],
+            6 => []
+        ];
+        
+        $options = [];
 
         $response = null;
 
         $uid = filter_input(INPUT_POST, 'uid');
         if ($uid == null){
-error_log("-1");
             return -1;
         }
 
-        $unit = filter_input(INPUT_POST, 'unit');
-        if ($uid == null){
-error_log("-2");
+        $unit_id = filter_input(INPUT_POST, 'unit');
+        if ($unit_id == null){
             return -2;
         }
 
@@ -49,7 +58,6 @@ error_log("-2");
             array_push($sets, intval($x));
         }
         if (sizeof($sets) < 2 || sizeof($sets) > 3){
-error_log("-3");
             return -3;
         }
 
@@ -63,45 +71,62 @@ error_log("-3");
 
         $source = filter_input(INPUT_POST, 'source');
         if ($source == null){
-error_log("-4");
             return -4;
         }
 
         $tuning = filter_input(INPUT_POST, 'tuning');
         if ($tuning == null){
-error_log("-5");
             return -5;
         }
+        
+        $min = [
+            "attack" => intval(filter_input(INPUT_POST, 'min_attack')),
+            "defense" => intval(filter_input(INPUT_POST, 'min_defense')),
+            "hp" => intval(filter_input(INPUT_POST, 'min_hp')),
+            "speed" => intval(filter_input(INPUT_POST, 'min_speed')),
+            "crit_rate" => intval(filter_input(INPUT_POST, 'min_crit_rate')),
+            "crit_damage" => intval(filter_input(INPUT_POST, 'min_crit_damage')),
+            "accuracy" => intval(filter_input(INPUT_POST, 'min_accuracy')),
+            "resistance" => intval(filter_input(INPUT_POST, 'min_resistance')),
+            "ehp" => intval(filter_input(INPUT_POST, 'min_ehp')),
+            "dmg" => intval(filter_input(INPUT_POST, 'min_dmg'))
+        ];
 
-        // Get optimization id and create the view:
-        $optmization_id = $uid . "-" . $unit . "-" . rand(0,1000);
-        $db->query($s);
+        // Get Buld query:
         $s = "
-          SELECT *
+          SELECT
+            id,
+            slot
           FROM rune
           WHERE
             uid = $uid AND
-            set IN (
+            type IN (
         ";
         foreach ($sets as $set){
             $s .= ($set . ",");
         }
         $s .= "-1) AND ";
         switch ($source){
-            case 0: // Storage only
-                $s .= "assigned_to IS NULL";
+            case 0: // Storage only (or itself)
+                $s .= "
+                  (
+                    assigned_to = $unit_id OR
+                    assigned_to IS NULL
+                  )";
                 break;
-            case 1: // Units in no teams
+            case 1: // Units in no teams (or itself)
                 $s .= "
                   (
+                    assigned_to = $unit_id OR
                     assigned_to IS NULL OR 
                     assigned_to NOT IN (SELECT DISTINCT unit FROM team_unit)
                   )
                 ";
                 break;
-            case 2: // Units in teams with 0 score
+            case 2: // Units in teams with 0 score (or itself)
                 $s .= "
                   (
+                    assigned_to = $unit_id OR
                     assigned_to IS NULL OR 
                     assigned_to NOT IN (SELECT DISTINCT unit FROM team_unit) OR
                     assigned_to NOT IN (
@@ -116,7 +141,7 @@ error_log("-5");
                   )
                 ";
                 break;
-            case 3: // Units with lower overall score
+            case 3: // Units with lower overall score (or itself)
                 // TODO
                 break;
             case 4: // All runes - dont filter
@@ -125,10 +150,258 @@ error_log("-5");
             default: // Invalid options - return nothing
                 $s .= " 1 = 0 ";
         }
+        // Even slots stats
+        $s .= "
+          AND
+          (
+            slot <> 2 OR
+            (
+              slot = 2 AND
+              main_stat = " . $stats[0] . "
+            )
+          ) AND
+          (
+            slot <> 4 OR
+            (
+              slot = 4 AND
+              main_stat = " . $stats[1] . "
+            )
+          ) AND
+          (
+            slot <> 6 OR
+            (
+              slot = 6 AND
+              main_stat = " . $stats[2] . "
+            )
+          )
+        ";
+        error_log($s);
+        $q = $db->query($s);
+        $total_candidates = 0;
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($candidates[$r["slot"]], new Rune($r["id"]));
+            $total_candidates ++;
+        }
+        $max_combinations = sizeof($candidates[1]) * sizeof($candidates[2]) * sizeof($candidates[3]) * sizeof($candidates[4]) * sizeof($candidates[5]) * sizeof($candidates[6]);
+        if ($max_combinations == 0){
+            $res = [
+                "total" => 0,
+                "options" => []
+            ];
+            $response = json_encode($res);
+            return $response;
+        }
+        
+        // Get the unit and its base stats
+        $unit = new Unit($unit_id, true, $uid);
+        $unit_attack = $unit->attack + $unit->artifact_attack + $unit->building_attack;
+        $unit_base_attack = $unit->attack;
+        $unit_defense = $unit->defense + $unit->artifact_defense + $unit->building_defense;
+        $unit_base_defense = $unit->defense;
+        $unit_hp = $unit->hp + $unit->artifact_hp + $unit->building_hp;
+        $unit_base_hp = $unit->hp;
+        $unit_speed = $unit->speed + $unit->artifact_speed + $unit->building_speed;
+        $unit_base_speed = $unit->speed;
+        $unit_crit_rate = $unit->crit_rate + $unit->artifact_crit_rate + $unit->building_crit_rate;
+        $unit_base_crit_rate = $unit->crit_rate;
+        $unit_crit_damage = $unit->crit_damage + $unit->artifact_crit_damage + $unit->building_crit_damage;
+        $unit_base_crit_damage = $unit->crit_damage;
+        $unit_accuracy = $unit->accuracy + $unit->artifact_accuracy + $unit->building_accuracy;
+        $unit_base_accuracy = $unit->accuracy;
+        $unit_resistance = $unit->resistance + $unit->artifact_resistance + $unit->building_resistance;
+        $unit_base_resistance = $unit->resistance;
+
+        $i = [0, 0, 0, 0, 0, 0, 0]; // 7, so I can start with 1
+        while (true){
+            
+            
+            // Check if set combination is valid
+            if (valid_sets($candidates, $i)){                
+                // Do things
+                $iteration = [
+                    "attack" => $unit_attack,
+                    "defense" => $unit_defense,
+                    "hp" => $unit_hp,
+                    "speed" => $unit_speed,
+                    "crit_rate" => $unit_crit_rate,
+                    "crit_damage" => $unit_crit_damage,
+                    "accuracy" => $unit_accuracy,
+                    "resistance" => $unit_resistance,
+                    "ehp" => 0, // TODO
+                    "dmg" => 0, // TODO
+                ];
+                for ($r = 1; $r <= 6; $r ++){
+                    // Loop selected runes and calculate stats
+                    sum_rune_stat(
+                      $candidates[$r][$i[$r]]->main_stat,
+                      $candidates[$r][$i[$r]]->main_stat_value,
+                      $iteration,
+                      $unit_base_attack,
+                      $unit_base_defense,
+                      $unit_base_hp,
+                    );
+                    sum_rune_stat(
+                      $candidates[$r][$i[$r]]->innate_stat,
+                      $candidates[$r][$i[$r]]->innate_stat_value,
+                      $iteration,
+                      $unit_base_attack,
+                      $unit_base_defense,
+                      $unit_base_hp,
+                    );
+                    sum_rune_stat(
+                      $candidates[$r][$i[$r]]->substat_1,
+                      $candidates[$r][$i[$r]]->substat_1_value,
+                      $iteration,
+                      $unit_base_attack,
+                      $unit_base_defense,
+                      $unit_base_hp,
+                    );
+                    sum_rune_stat(
+                      $candidates[$r][$i[$r]]->substat_2,
+                      $candidates[$r][$i[$r]]->substat_2_value,
+                      $iteration,
+                      $unit_base_attack,
+                      $unit_base_defense,
+                      $unit_base_hp,
+                    );
+                    sum_rune_stat(
+                      $candidates[$r][$i[$r]]->substat_3,
+                      $candidates[$r][$i[$r]]->substat_3_value,
+                      $iteration,
+                      $unit_base_attack,
+                      $unit_base_defense,
+                      $unit_base_hp,
+                    );
+                    sum_rune_stat(
+                      $candidates[$r][$i[$r]]->substat_4,
+                      $candidates[$r][$i[$r]]->substat_4_value,
+                      $iteration,
+                      $unit_base_attack,
+                      $unit_base_defense,
+                      $unit_base_hp,
+                    );
+                }
+                
+                // Compare with filters:
+                // TODO: Calculat EHP and DMG
+                if (
+                  $iteration["attack"] >= $min["attack"] &&
+                  $iteration["defense"] >= $min["defense"] &&
+                  $iteration["hp"] >= $min["hp"] &&
+                  $iteration["speed"] >= $min["speed"] &&
+                  $iteration["crit_rate"] >= $min["crit_rate"] &&
+                  $iteration["crit_damage"] >= $min["crit_damage"] &&
+                  $iteration["accuracy"] >= $min["accuracy"] &&
+                  $iteration["resistance"] >= $min["resistance"]
+                  // TODO ehp dmg
+                ){
+                    // Calculate the variation
+                    $variation = 0;
+                    $variation += (($iteration["attack"] - $unit->total_attack) * 1);
+                    $variation += (($iteration["defense"] - $unit->total_defense) * 1);
+                    $variation += (($iteration["hp"] - $unit->total_hp) * (1 / 15));
+                    $variation += (($iteration["speed"] - $unit->total_speed) * 1.5);
+                    $variation += (($iteration["crit_rate"] - $unit->total_crit_rate) * 0.85);
+                    $variation += (($iteration["crit_damage"] - $unit->total_crit_damage) * 0.9);
+                    $variation += (($iteration["accuracy"] - $unit->total_accuracy) * 0.85);
+                    $variation += (($iteration["resistance"] - $unit->total_resistance) * 0.85);
+                    $variation = ceil($variation);
+                    // Build the array
+                    $option = [
+                        "variation" => $variation,
+                        "runes" => [
+                            [
+                                "id" => $candidates[1][$i[1]]->id,
+                                "html" => (HTML::rune_table($candidates[1][$i[1]]))
+                            ],
+                            [
+                                "id" => $candidates[2][$i[2]]->id,
+                                "html" => (HTML::rune_table($candidates[2][$i[2]]))
+                            ],
+                            [
+                                "id" => $candidates[3][$i[3]]->id,
+                                "html" => (HTML::rune_table($candidates[3][$i[3]]))
+                            ],
+                            [
+                                "id" => $candidates[4][$i[4]]->id,
+                                "html" => (HTML::rune_table($candidates[4][$i[4]]))
+                            ],
+                            [
+                                "id" => $candidates[5][$i[5]]->id,
+                                "html" => (HTML::rune_table($candidates[5][$i[5]]))
+                            ],
+                            [
+                                "id" => $candidates[1][$i[1]]->id,
+                                "html" => HTML::rune_table($candidates[6][$i[6]])
+                            ]
+                        ],
+                        "stats" => [
+                            "attack" => ceil($iteration["attack"]),
+                            "defense" => ceil($iteration["defense"]),
+                            "hp" => ceil($iteration["hp"]),
+                            "speed" => ceil($iteration["speed"]),
+                            "crit_rate" => ceil($iteration["crit_rate"]),
+                            "crit_damage" => ceil($iteration["crit_damage"]),
+                            "accuracy" => ceil($iteration["accuracy"]),
+                            "attack" => ceil($iteration["attack"]),
+                            "resistance" => ceil($iteration["resistance"]),
+                            "ehp" => ceil($iteration["ehp"]),
+                            "dmg" => ceil($iteration["dmg"])
+                        ]
+                    ];
+                    array_push($options, $option);
+                    if (sizeof($options) > 100){
+                        http_response_code(413); // Payload too large;
+                        die();
+                        return;
+                    }
+                }
+            }
+
+            // Increase counters
+            $i[6] ++;
+            if ($i[6] == sizeof($candidates[6])){
+                $i[6] = 0;
+                $i[5] ++;
+            }
+            if ($i[5] == sizeof($candidates[5])){
+                $i[5] = 0;
+                $i[4] ++;
+            }
+            if ($i[4] == sizeof($candidates[4])){
+                $i[4] = 0;
+                $i[3] ++;
+            }
+            if ($i[3] == sizeof($candidates[3])){
+                $i[3] = 0;
+                $i[2] ++;
+            }
+            if ($i[2] == sizeof($candidates[2])){
+                $i[2] = 0;
+                $i[1] ++;
+            }
 
-error_log($s);
-        $response = $s;
+            // Calculate exit condition
+            if (
+                $i[1] >= sizeof($candidates[1]) - 1 &&
+                $i[2] >= sizeof($candidates[2]) - 1 &&
+                $i[3] >= sizeof($candidates[3]) - 1 &&
+                $i[4] >= sizeof($candidates[4]) - 1 &&
+                $i[5] >= sizeof($candidates[5]) - 1 &&
+                $i[6] >= sizeof($candidates[6]) - 1
+            ){
+                break;
+            }
+        }
 
+        // Sort options by variation
+        usort($options, "sortOptions");
+        $res = [
+            "total" => sizeof($options),
+            "options" => $options
+        ];
+        
+        $response = json_encode($res);
         if ($response == null){
             return 0;
         }
@@ -136,4 +409,128 @@ error_log($s);
             return $response;
         }
     }
+    
+    /**
+     * Validates a rune combination.
+     *
+     * Checks that set numbers are OK.
+     *
+     * TODO: Verify that it complies with filters
+     *
+     * @param \Rune[][] $candidates Candidate runes.
+     * @param int[] $indexes Currently selected indexes.
+     */
+    function valid_sets($candidates, $indexes){
+        
+        $sets = [
+            RUNE_SET_ID::ENERGY => 0,
+            RUNE_SET_ID::GUARD => 0,
+            RUNE_SET_ID::SWIFT => 0,
+            RUNE_SET_ID::BLADE => 0,
+            RUNE_SET_ID::RAGE => 0,
+            RUNE_SET_ID::FOCUS => 0,
+            RUNE_SET_ID::ENDURE => 0,
+            RUNE_SET_ID::FATAL => 0,
+            RUNE_SET_ID::DESPAIR => 0,
+            RUNE_SET_ID::VAMPIRE => 0,
+            RUNE_SET_ID::VIOLENT => 0,
+            RUNE_SET_ID::NEMESIS => 0,
+            RUNE_SET_ID::WILL => 0,
+            RUNE_SET_ID::SHIELD => 0,
+            RUNE_SET_ID::REVENGE => 0,
+            RUNE_SET_ID::DESTROY => 0,
+            RUNE_SET_ID::FIGHT => 0,
+            RUNE_SET_ID::DETERMINATION => 0,
+            RUNE_SET_ID::ENHANCE => 0,
+            RUNE_SET_ID::ACCURACY => 0,
+            RUNE_SET_ID::TOLERANCE => 0
+        ];
+        for ($i = 1; $i <= 6; $i++){
+            $sets[$candidates[$i][$indexes[$i]]->type->id] ++;
+        }
+        for ($i = 0; $i < sizeof($sets); $i ++){
+            switch ($i){
+                case RUNE_SET_ID::ENERGY:
+                case RUNE_SET_ID::GUARD:
+                case RUNE_SET_ID::NEMESIS:
+                case RUNE_SET_ID::BLADE:
+                case RUNE_SET_ID::FOCUS:
+                case RUNE_SET_ID::ENDURE:
+                case RUNE_SET_ID::WILL:
+                case RUNE_SET_ID::SHIELD:
+                case RUNE_SET_ID::REVENGE:
+                case RUNE_SET_ID::DESTROY:
+                case RUNE_SET_ID::FIGHT:
+                case RUNE_SET_ID::DETERMINATION:
+                case RUNE_SET_ID::ENHANCE:
+                case RUNE_SET_ID::ACCURACY:
+                case RUNE_SET_ID::TOLERANCE:
+                    if ($sets[$i] % 2 != 0){
+                        return false;
+                    }
+                    break;
+                
+                case RUNE_SET_ID::DESPAIR:
+                case RUNE_SET_ID::SWIFT:
+                case RUNE_SET_ID::RAGE:
+                case RUNE_SET_ID::FATAL:
+                case RUNE_SET_ID::VAMPIRE:
+                case RUNE_SET_ID::VIOLENT:
+                    if ($sets[$i] != 4 && $sets[$i != 0]){
+                        return false;
+                    }
+                    break;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * Calculates the stat increase by a rune property.
+     * 
+     * @param string $stat Stat type.
+     * @param int $value Stat increase value.
+     * @param int[] Reference to iteration stats array.
+     */
+    function sum_rune_stat($stat, $value, &$iteration, $base_atk, $base_def, $base_hp){
+        switch ($stat){
+            case RUNE_STAT_ID::ATK:
+                $iteration["attack"] += $value;
+                break;
+            case RUNE_STAT_ID::DEF:
+                $iteration["defense"] += $value;
+                break;
+            case RUNE_STAT_ID::HP:
+                $iteration["hp"] += $value;
+                break;
+            case RUNE_STAT_ID::SPD:
+                $iteration["speed"] += $value;
+                break;
+            case RUNE_STAT_ID::CRR:
+                $iteration["crit_rate"] += $value;
+                break;
+            case RUNE_STAT_ID::CRD:
+                $iteration["crit_damage"] += $value;
+                break;
+            case RUNE_STAT_ID::ACC:
+                $iteration["accuracy"] += $value;
+                break;
+            case RUNE_STAT_ID::RES:
+                $iteration["resistance"] += $value;
+                break;
+            case RUNE_STAT_ID::ATK_P:
+                $iteration["attack"] += ($base_atk * $value / 100);
+                break;
+            case RUNE_STAT_ID::DEF_P:
+                $iteration["defense"] += ($base_def * $value / 100);
+                break;
+            case RUNE_STAT_ID::HP_P:
+                $iteration["hp"] += ($base_hp * $value / 100);
+                break;
+        }
+    }
+    
+    function sortOptions($a, $b) {
+        return $b["variation"] - $a["variation"];
+    }
 ?>

+ 5 - 2
application/entity/Unit.php

@@ -371,9 +371,12 @@
          * @global int Player ID.
          * @global resource Database connection.
          */
-        public function __construct($id, $complete = true){
+        public function __construct($id, $complete = true, $uid = 0){
             global $UID;
             global $db;
+            if ($uid == 0){
+                $uid = $UID;
+            }
             $s =
               "SELECT " .
               "  uid, " .
@@ -400,7 +403,7 @@
               "  lock " .
               "FROM unit " .
               "WHERE " .
-              "  uid = '$UID' AND " .
+              "  uid = '$uid' AND " .
               "  id = '$id'; ";
             $q = $db->query($s);
             $r = $q->fetchArray(SQLITE3_ASSOC);

+ 0 - 112
application/page/Optimizer_Unit_Page.php

@@ -25,33 +25,6 @@
          */
         public $unit;
 
-        /**
-         * @var mixed[] Stats gained by building.
-         */
-        public $building_stats = [
-            "atk" => 0,
-            "def" => 0,
-            "hp" => 0,
-            "spd" => 0,
-            "crd" => 0,
-            "elm" => [
-                1 => 0,
-                2 => 0,
-                3 => 0,
-                4 => 0,
-                5 => 0
-            ]
-        ];
-
-        /**
-         * @var int[] Stats gained by artifacts.
-         */
-        public $artifact_stats = [
-            "atk" => 0,
-            "def" => 0,
-            "hp" => 0
-        ];
-
         /**
          * Constructor.
          *
@@ -62,94 +35,9 @@
         public function __construct($id){
             $this->view = PATH::VIEW . "optimizer_unit.php";
             $this->unit = new Unit($id);
-            $this->calculate_buildings();
-            $this->calculate_artifacts();
             $this->title = "Optimize " . $this->unit->unit->name . " - SWDB";
             $this->description = "Optimize " . $this->unit->unit->name;
             $this->canonical = URL::BASE . "optmizer/$id";
         }
-
-        /**
-         * Calculates the stats gained from bulding upgrades and populates the
-         * $building_stats array.
-         *
-         * @gobal int User ID.
-         * @global resource Database connection.
-         */
-        private function calculate_buildings(){
-            global $UID;
-            global $db;
-            $s = "
-              SELECT
-                affected_stat,
-                bonus,
-                element
-              FROM
-                k_decoration,
-                k_decoration_level,
-                decoration
-              WHERE
-                decoration.uid = '$UID' AND
-                k_decoration.id = decoration.decoration AND
-                decoration.decoration = k_decoration_level.decoration AND
-                decoration.level = k_decoration_level.level AND
-                area = " . EFFECT_AREA_ID::GENERAL . " AND
-                affected_stat IN (" . STAT_ID::ATK . ", " . STAT_ID::DEF . ", " . STAT_ID::HP . ", " . STAT_ID::SPD . ", " . STAT_ID::CRIT_DMG . ");
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                switch($r["affected_stat"]){
-                    case STAT_ID::DEF:
-                        $this->building_stats["def"] += $r["bonus"];
-                        break;
-                    case STAT_ID::HP:
-                        $this->building_stats["hp"] += $r["bonus"];
-                        break;
-                    case STAT_ID::SPD:
-                        $this->building_stats["spd"] += $r["bonus"];
-                        break;
-                    case STAT_ID::CRIT_DMG:
-                        $this->building_stats["crd"] += $r["bonus"];
-                        break;
-                    case STAT_ID::ATK:
-                        if(strlen($r["element"]) > 0){
-                            $this->building_stats["elm"][$r["element"]] += $r["bonus"];
-                        }
-                        else{
-                            $this->building_stats["atk"] += $r["bonus"];
-                        }
-                        break;
-                }
-            }
-        }
-
-        private function calculate_artifacts(){
-            if ($this->unit->artifact_type != null){
-                switch ($this->unit->artifact_type->main_stat){
-                    case ARTIFACT_STAT_ID::HP:
-                        $this->artifact_stats["hp"] += $this->unit->artifact_type->main_stat_value;
-                        break;
-                    case ARTIFACT_STAT_ID::DEF:
-                        $this->artifact_stats["def"] += $this->unit->artifact_type->main_stat_value;
-                        break;
-                    case ARTIFACT_STAT_ID::ATK:
-                        $this->artifact_stats["atk"] += $this->unit->artifact_type->main_stat_value;
-                        break;
-                }
-            }
-            if ($this->unit->artifact_element != null){
-                switch ($this->unit->artifact_element->main_stat){
-                    case ARTIFACT_STAT_ID::HP:
-                        $this->artifact_stats["hp"] += $this->unit->artifact_element->main_stat_value;
-                        break;
-                    case ARTIFACT_STAT_ID::DEF:
-                        $this->artifact_stats["def"] += $this->unit->artifact_element->main_stat_value;
-                        break;
-                    case ARTIFACT_STAT_ID::ATK:
-                        $this->artifact_stats["atk"] += $this->unit->artifact_element->main_stat_value;
-                        break;
-                }
-            }
-        }
     }
 ?>

BIN
application/sw.sqlite


+ 611 - 77
application/view/optimizer_unit.php

@@ -38,6 +38,22 @@
         <meta name='twitter:url' content='<?=$page->canonical?>'/>
         <meta name='robots' content='index follow'/>
         <script>
+        
+            /**
+             * Unit current stats.
+             */
+            var current_stats = {
+                "attack": <?=$page->unit->total_attack?>,
+                "defense": <?=$page->unit->total_defense?>,
+                "hp": <?=$page->unit->total_hp?>,
+                "speed": <?=$page->unit->total_speed?>,
+                "crit_rate": <?=$page->unit->total_crit_rate?>,
+                "crit_damage": <?=$page->unit->total_crit_damage?>,
+                "accuracy": <?=$page->unit->total_accuracy?>,
+                "resistance": <?=$page->unit->total_resistance?>,
+                "ehp": <?=$page->unit->effective_hp?>,
+                "dmg": <?=$page->unit->effective_dmg?>
+            }
 
             /**
              * Updates the value next to the sliders when they change.
@@ -45,8 +61,20 @@
              * @param stat Name of the stat to set.
              * @param value Value of the slider.
              */
-            function updateMinValue(stat, value){
-                document.getElementById('lbl_min_' + stat).innerHTML = value;
+            function updateMinValue(stat, element){
+                var value = Number(element.value);
+                var max = Number(element.max);
+                var min = Number(element.min);
+                if (value < min){
+                    value = min;
+                    console.log("Correcting for min: " + value + "/" + min);
+                }
+                if (value > max){
+                    console.log("Correcting for max: " + value + "/" + max);
+                    value = max;
+                }
+                document.getElementById('lbl_min_' + stat).value = value;
+                document.getElementById('min_' + stat).value = value;
             }
 
             /**
@@ -99,59 +127,472 @@
                 params += '&tuning=' + document.getElementById('tuning').options[document.getElementById('tuning').selectedIndex].value;
 
                 // Min HP - Optional
-                if (document.getElementById('min_hp').value > document.getElementById('min_hp').min){
+                if (Number(document.getElementById('min_hp').value) > Number(document.getElementById('min_hp').min)){
                     params += '&min_hp=' + document.getElementById('min_hp').value;
                 }
 
                 // Min ATK - Optional
-                if (document.getElementById('min_attack').value > document.getElementById('min_attack').min){
+                if (Number(document.getElementById('min_attack').value) > Number(document.getElementById('min_attack').min)){
                     params += '&min_attack=' + document.getElementById('min_attack').value;
                 }
 
                 // Min DEF - Optional
-                if (document.getElementById('min_defense').value > document.getElementById('min_defense').min){
+                if (Number(document.getElementById('min_defense').value) > Number(document.getElementById('min_defense').min)){
                     params += '&min_defense=' + document.getElementById('min_defense').value;
                 }
 
                 // Min SPD - Optional
-                if (document.getElementById('min_speed').value > document.getElementById('min_speed').min){
+                if (Number(document.getElementById('min_speed').value) > Number(document.getElementById('min_speed').min)){
                     params += '&min_speed=' + document.getElementById('min_speed').value;
                 }
 
                 // Min CRR - Optional
-                if (document.getElementById('min_crit_rate').value > document.getElementById('min_crit_rate').min){
+                if (Number(document.getElementById('min_crit_rate').value) > Number(document.getElementById('min_crit_rate').min)){
                     params += '&min_crit_rate=' + document.getElementById('min_crit_rate').value;
                 }
 
                 // Min CRD - Optional
-                if (document.getElementById('min_crit_damage').value > document.getElementById('min_crit_damage').min){
+                if (Number(document.getElementById('min_crit_damage').value) > Number(document.getElementById('min_crit_damage').min)){
                     params += '&min_crit_damage=' + document.getElementById('min_crit_damage').value;
                 }
 
                 // Min ACC - Optional
-                if (document.getElementById('min_accuracy').value > document.getElementById('min_accuracy').min){
+                if (Number(document.getElementById('min_accuracy').value) > Number(document.getElementById('min_accuracy').min)){
                     params += '&min_accuracy=' + document.getElementById('min_accuracy').value;
                 }
 
                 // Min RES - Optional
-                if (document.getElementById('min_resistance').value > document.getElementById('min_resistance').min){
+                if (Number(document.getElementById('min_resistance').value) > Number(document.getElementById('min_resistance').min)){
                     params += '&min_resistance=' + document.getElementById('min_resistance').value;
                 }
 
+                // Min EHP - Optional
+                if (Number(document.getElementById('min_ehp').value) > 0){
+                    params += '&min_ehp=' + document.getElementById('min_ehp').value;
+                }
+
+                // Min DMG - Optional
+                if (Number(document.getElementById('min_dmg').value) > 0){
+                    params += '&min_dmg=' + document.getElementById('min_dmg').value;
+                }
+
                 // Send th request
                 var xhttp = new XMLHttpRequest();
                 xhttp.onreadystatechange = function() {
-                    if (this.readyState == 4 && this.status == 200) {
-                        showOptimizations(this.response);
+                    if (this.readyState == 4){
+                        if(this.status == 200) {
+                            showOptimizations(this.response, this.status);
+                        }
+                        else if (this.status == 413) { // Payload too large
+                            alert("Over 100 combination found. Plesase narow your criteria and retry.");
+                        }
                     }
                 };
+                
+                // TODO DEBUG
+                params = "uid=8114048&unit=6441802832&set[]=1&set[]=1&set[]=4&stat[]=4&stat[]=4&stat[]=4&source=0&tuning=0&min_defense=700";
+                
                 xhttp.open("POST", "/action/optimize/", true);
                 xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                 xhttp.send(params);
             }
 
-            function showOptimizations(content){
-                console.log("RESPONSE: " + content);
+            function showOptimizations(content, status){
+                var container = document.getElementById("optimizations");
+                while (container.firstChild) {
+                    container.removeChild(container.firstChild);
+                }
+                var data = JSON.parse(content);
+                if (Number(data.total) == 0){
+                    alert("No results");
+                    return;
+                }
+                var option;
+                var tr;
+                var td;
+                var stat_table;
+                var stat_tr;
+                var stat_td;
+                var span;
+                var text;
+                for (i = 0; i < data.options.length; i++){
+                    option = data.options[i];
+                    tr = document.createElement('tr');
+                    td = document.createElement('td');
+                    td.setAttribute('class', 'stats');
+                    stat_table = document.createElement('table');
+                    stat_table.setAttribute('class', 'stat_table');
+
+                    // attack
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('ATK');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.attack + " ");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.attack) > Number(current_stats["attack"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.attack - current_stats["attack"]);
+                        
+                    }
+                    else if (Number(option.stats.attack) < Number(current_stats["attack"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["attack"] - option.stats.attack);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+                    
+                    // defense
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('DEF');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.defense + " ");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.defense) > Number(current_stats["defense"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.defense - current_stats["defense"]);
+                        
+                    }
+                    else if (Number(option.stats.defense) < Number(current_stats["defense"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["defense"] - option.stats.defense);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // hp
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('HP ');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.hp + " ");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.hp) > Number(current_stats["hp"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.hp - current_stats["hp"]);
+                        
+                    }
+                    else if (Number(option.stats.hp) < Number(current_stats["hp"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["hp"] - option.stats.hp);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // speed
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('SPD');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.speed + " ");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.speed) > Number(current_stats["speed"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.speed - current_stats["speed"]);
+                        
+                    }
+                    else if (Number(option.stats.speed) < Number(current_stats["speed"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["speed"] - option.stats.speed);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // crit_rate
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('CRR');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.crit_rate + "%");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.crit_rate) > Number(current_stats["crit_rate"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.crit_rate - current_stats["crit_rate"]);
+                        
+                    }
+                    else if (Number(option.stats.crit_rate) < Number(current_stats["crit_rate"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["crit_rate"] - option.stats.crit_rate);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // crit_damage
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('CRD');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.crit_damage + "%");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.crit_damage) > Number(current_stats["crit_damage"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.crit_damage - current_stats["crit_damage"]);
+                        
+                    }
+                    else if (Number(option.stats.crit_damage) < Number(current_stats["crit_damage"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["crit_damage"] - option.stats.crit_damage);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // accuracy
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('ACC');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.accuracy + "%");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.accuracy) > Number(current_stats["accuracy"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.accuracy - current_stats["accuracy"]);
+                        
+                    }
+                    else if (Number(option.stats.accuracy) < Number(current_stats["accuracy"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["accuracy"] - option.stats.accuracy);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // resistance
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('RES');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.resistance + "%");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.resistance) > Number(current_stats["resistance"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.resistance - current_stats["resistance"]);
+                        
+                    }
+                    else if (Number(option.stats.resistance) < Number(current_stats["resistance"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["resistance"] - option.stats.resistance);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // ehp
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('EHP');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.ehp + " ");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.ehp) > Number(current_stats["ehp"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.ehp - current_stats["ehp"]);
+                        
+                    }
+                    else if (Number(option.stats.ehp) < Number(current_stats["ehp"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["ehp"] - option.stats.ehp);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+                    
+                    // dmg
+                    stat_tr = document.createElement('tr');
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'label');
+                    text = document.createTextNode('DMG');
+                    stat_td.appendChild(text);
+                    stat_tr.appendChild(stat_td);
+                    stat_td = document.createElement('td');
+                    stat_td.setAttribute('class', 'value');
+                    span = document.createElement('span');
+                    span.setAttribute('class', 'stat');
+                    text = document.createTextNode(option.stats.dmg + " ");
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    span = document.createElement('span');
+                    if (Number(option.stats.dmg) > Number(current_stats["dmg"])){
+                        
+                        span.setAttribute('class', 'variation increment');
+                        text = document.createTextNode(option.stats.dmg - current_stats["dmg"]);
+                        
+                    }
+                    else if (Number(option.stats.dmg) < Number(current_stats["dmg"])){
+                        span.setAttribute('class', 'variation decrement');
+                        text = document.createTextNode(current_stats["dmg"] - option.stats.dmg);
+                        
+                    }
+                    else{
+                        span.setAttribute('class', 'variation');
+                        text = document.createTextNode(" ");
+                    }
+                    span.appendChild(text);
+                    stat_td.appendChild(span);
+                    stat_tr.appendChild(stat_td);
+                    stat_table.appendChild(stat_tr);
+
+                    // Add to the main table
+                    td.appendChild(stat_table);
+                    tr.appendChild(td);
+                    
+                    // Runes td
+                    td = document.createElement('td');
+                    td.setAttribute('class', 'runes');
+                    td.innerHTML += option.runes[6 - 1].html;
+                    td.innerHTML += option.runes[1 - 1].html;
+                    td.innerHTML += option.runes[2 - 1].html;
+                    td.innerHTML += "<br/>";
+                    td.innerHTML += option.runes[5 - 1].html;
+                    td.innerHTML += option.runes[4 - 1].html;
+                    td.innerHTML += option.runes[3 - 1].html;
+
+                    // Add the table
+                    tr.appendChild(td);
+                    container.appendChild(tr);
+
+                }
             }
         </script>
     </head>
@@ -209,16 +650,6 @@
 ?>
                     </div>
                 </div>
-<?php
-                $building_attack = floor(($page->unit->attack * $page->building_stats["atk"] / 100) + ($page->unit->attack * $page->building_stats["elm"][$page->unit->unit->element] / 100));
-                $building_defense = floor($page->building_stats["def"] * $page->unit->defense / 100);
-                $building_hp = floor($page->building_stats["hp"] * $page->unit->hp / 100);
-                $building_speed = $page->building_stats["spd"];
-                $building_crit_rate = 0;
-                $building_crit_damage = $page->building_stats["crd"];
-                $building_accuracy = 0;
-                $building_resistance = 0;
-?>
                 <table id='stats'>
                     <tr>
                         <th>
@@ -246,18 +677,23 @@
                         </th>
                         <td class='base'>
                             <?=$page->unit->attack?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
                             +<?=$page->unit->rune_attack?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +<?=$page->artifact_stats["atk"]?>
+                            +<?=$page->unit->artifact_attack?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_attack?>
+                            +<?=$page->unit->building_attack?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='total'>
-                            <?=$page->unit->attack + $page->unit->rune_attack + $building_attack + $page->artifact_stats["atk"]?>
+                            <?=$page->unit->total_attack?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                     </tr>
                     <tr>
@@ -266,18 +702,23 @@
                         </th>
                         <td class='base'>
                             <?=$page->unit->defense?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
                             +<?=$page->unit->rune_defense?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +<?=$page->artifact_stats["def"]?>
+                            +<?=$page->unit->artifact_defense?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_defense?>
+                            +<?=$page->unit->building_defense?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='total'>
-                            <?=$page->unit->defense + $page->unit->rune_defense + $building_defense + $page->artifact_stats["def"]?>
+                            <?=$page->unit->total_defense?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                     </tr>
                     <tr>
@@ -286,18 +727,23 @@
                         </th>
                         <td class='base'>
                             <?=$page->unit->hp?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
                             +<?=$page->unit->rune_hp?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +<?=$page->artifact_stats["hp"]?>
+                            +<?=$page->unit->artifact_hp?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_hp?>
+                            +<?=$page->unit->building_hp?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='total'>
-                            <?=$page->unit->hp + $page->unit->rune_hp + $building_hp + $page->artifact_stats["hp"]?>
+                            <?=$page->unit->total_hp?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                     </tr>
                     <tr>
@@ -306,18 +752,23 @@
                         </th>
                         <td class='base'>
                             <?=$page->unit->speed?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
                             +<?=$page->unit->rune_speed?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +0
+                            +<?=$page->unit->artifact_speed?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_speed?>
+                            +<?=$page->unit->building_speed?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                         <td class='total'>
-                            <?=$page->unit->speed + $page->unit->rune_speed + $building_speed?>
+                            <?=$page->unit->total_speed?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                     </tr>
                     <tr>
@@ -325,19 +776,24 @@
                             CRR
                         </th>
                         <td class='base'>
-                            <?=$page->unit->crit_rate?>%
+                            <?=$page->unit->crit_rate?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$page->unit->rune_crit_rate?>%
+                            +<?=$page->unit->rune_crit_rate?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +0%
+                            +<?=$page->unit->artifact_crit_rate?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_crit_rate?>%
+                            +<?=$page->unit->building_crit_rate?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='total'>
-                            <?=$page->unit->crit_rate + $page->unit->rune_crit_rate + $building_crit_rate?>%
+                            <?=$page->unit->total_crit_rate?>
+                            <span class='percent'>%</span>
                         </td>
                     </tr>
                     <tr>
@@ -345,19 +801,24 @@
                             CRD
                         </th>
                         <td class='base'>
-                            <?=$page->unit->crit_damage?>%
+                            <?=$page->unit->crit_damage?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$page->unit->rune_crit_damage?>%
+                            +<?=$page->unit->rune_crit_damage?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +0%
+                            +<?=$page->unit->artifact_crit_damage?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_crit_damage?>%
+                            +<?=$page->unit->building_crit_damage?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='total'>
-                            <?=$page->unit->crit_damage + $page->unit->rune_crit_damage + $building_crit_damage?>%
+                            <?=$page->unit->total_crit_damage?>
+                            <span class='percent'>%</span>
                         </td>
                     </tr>
                     <tr>
@@ -365,19 +826,24 @@
                             ACC
                         </th>
                         <td class='base'>
-                            <?=$page->unit->accuracy?>%
+                            <?=$page->unit->accuracy?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$page->unit->rune_accuracy?>%
+                            +<?=$page->unit->rune_accuracy?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +0%
+                            +<?=$page->unit->artifact_accuracy?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_accuracy?>%
+                            +<?=$page->unit->building_accuracy?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='total'>
-                            <?=$page->unit->accuracy + $page->unit->rune_accuracy + $building_accuracy?>%
+                            <?=$page->unit->total_accuracy?>
+                            <span class='percent'>%</span>
                         </td>
                     </tr>
                     <tr>
@@ -385,19 +851,42 @@
                             RES
                         </th>
                         <td class='base'>
-                            <?=$page->unit->resistance?>%
+                            <?=$page->unit->resistance?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$page->unit->rune_resistance?>%
+                            +<?=$page->unit->rune_resistance?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +0%
+                            +<?=$page->unit->artifact_resistance?>
+                            <span class='percent'>%</span>
                         </td>
                         <td class='extra'>
-                            +<?=$building_resistance?>%
+                            +<?=$page->unit->building_resistance?>
+                            <span class='percent'>%</span>
+                        </td>
+                        <td class='total'>
+                            <?=$page->unit->total_resistance?>
+                            <span class='percent'>%</span>
                         </td>
+                    </tr>
+                    <tr>
+                        <th colspan='5'>
+                            Effective HP
+                        </th>
+                        <td class='total'>
+                            <?=$page->unit->effective_hp?>
+                            <span class='percent'>&nbsp;</span>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th colspan='5'>
+                            Effective DMG
+                        </th>
                         <td class='total'>
-                            <?=$page->unit->resistance + $page->unit->rune_resistance + $building_resistance?>%
+                            <?=$page->unit->effective_dmg?>
+                            <span class='percent'>&nbsp;</span>
                         </td>
                     </tr>
                 </table>
@@ -415,7 +904,7 @@
                 $total_stars = 0;
                 $total_value = 0;
                 $total_runes = 0;
-                $show_list = [6, 1, 2, 3, 4, 5];
+                $show_list = [6, 1, 2, 5, 4, 3];
                 //foreach ($page->unit->rune as $rune){
                 foreach ($show_list as $i){
                     $rune = $page->unit->rune[$i - 1];
@@ -520,7 +1009,7 @@
                                     $selected = "selected='selected'";
                                 }
 ?>
-                                <option value='<?=$id?>' <?=$selected?>><?=$name?></option>
+                                <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
 <?php
                             }
 ?>
@@ -533,7 +1022,7 @@
                                     $selected = "selected='selected'";
                                 }
 ?>
-                                <option value='<?=$id?>' <?=$selected?>><?=$name?></option>
+                                <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
 <?php
                             }
 ?>
@@ -547,7 +1036,7 @@
                                     $selected = "selected='selected'";
                                 }
 ?>
-                                <option value='<?=$id?>' <?=$selected?>><?=$name?></option>
+                                <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
 <?php
                             }
 ?>
@@ -559,8 +1048,8 @@
                             Min HP
                         </td>
                         <td class='value'>
-                            <input id='min_hp' type='range' value='<?=$page->unit->hp?>' value='<?=$page->unit->hp?>' min='<?=$page->unit->hp?>' max='50000' oninput='updateMinValue("hp", this.value);'>
-                            <span id='lbl_min_hp'><?=$page->unit->hp?></span>
+                            <input id='min_hp' type='range' value='<?=$page->unit->total_hp?>' min='<?=$page->unit->hp?>' max='50000' oninput='updateMinValue("hp", this);'>
+                            <input type='number' id='lbl_min_hp' value='<?=$page->unit->total_hp?>' min='<?=$page->unit->hp?>' max='50000' onChange='updateMinValue("hp", this);'></input>
                         </td>
                     </tr>
                     <tr>
@@ -595,8 +1084,8 @@
                             Min ATK
                         </td>
                         <td class='value'>
-                            <input id='min_attack' type='range' value='<?=$page->unit->attack?>' value='<?=$page->unit->attack?>' min='<?=$page->unit->attack?>' max='10000' oninput='updateMinValue("attack", this.value);'>
-                            <span id='lbl_min_attack'><?=$page->unit->attack?></span>
+                            <input id='min_attack' type='range' value='<?=$page->unit->total_attack?>' min='<?=$page->unit->attack?>' max='4000' oninput='updateMinValue("attack", this);'>
+                            <input type='number' id='lbl_min_attack' value='<?=$page->unit->total_attack?>' min='<?=$page->unit->attack?>' max='4000' onChange='updateMinValue("attack", this);'></input>
                         </td>
                     </tr>
                     <tr>
@@ -618,8 +1107,8 @@
                             Min DEF
                         </td>
                         <td class='value'>
-                            <input id='min_defense' type='range' value='<?=$page->unit->defense?>' value='<?=$page->unit->defense?>' min='<?=$page->unit->defense?>' max='10000' oninput='updateMinValue("defense", this.value);'>
-                            <span id='lbl_min_defense'><?=$page->unit->defense?></span>
+                            <input id='min_defense' type='range' value='<?=$page->unit->total_defense?>' min='<?=$page->unit->defense?>' max='4000' oninput='updateMinValue("defense", this);'>
+                            <input type='number' id='lbl_min_defense' value='<?=$page->unit->total_defense?>' min='<?=$page->unit->defense?>' max='4000' onChange='updateMinValue("defense", this);'></input>
                         </td>
                     </tr>
                     <tr>
@@ -640,8 +1129,8 @@
                             Min SPD
                         </td>
                         <td class='value'>
-                            <input id='min_speed' type='range' value='<?=$page->unit->speed?>' value='<?=$page->unit->speed?>' min='<?=$page->unit->speed?>' max='400' oninput='updateMinValue("speed", this.value);'>
-                            <span id='lbl_min_speed'><?=$page->unit->speed?></span>
+                            <input id='min_speed' type='range' value='<?=$page->unit->total_speed?>' min='<?=$page->unit->speed?>' max='400' oninput='updateMinValue("speed", this);'>
+                            <input type='number' id='lbl_min_speed' value='<?=$page->unit->total_speed?>' min='<?=$page->unit->speed?>' max='400' onChange='updateMinValue("speed", this);'></input>
                         </td>
                     </tr>
                     <tr>
@@ -655,8 +1144,8 @@
                             Min CRR
                         </td>
                         <td class='value'>
-                            <input id='min_crit_rate' type='range' value='<?=$page->unit->crit_rate?>' value='<?=$page->unit->crit_rate?>' min='<?=$page->unit->crit_rate?>' max='100' oninput='updateMinValue("crit_rate", this.value);'>
-                            <span id='lbl_min_crit_rate'><?=$page->unit->crit_rate?></span>
+                            <input id='min_crit_rate' type='range' value='<?=$page->unit->total_crit_rate?>' min='<?=$page->unit->crit_rate?>' max='100' oninput='updateMinValue("crit_rate", this);'>
+                            <input type='number' id='lbl_min_crit_rate' value='<?=$page->unit->total_crit_rate?>' min='<?=$page->unit->crit_rate?>' max='100' onChange='updateMinValue("crit_rate", this);'></input>%
                         </td>
                     </tr>
                     <tr>
@@ -670,8 +1159,8 @@
                             Min CRD
                         </td>
                         <td class='value'>
-                            <input id='min_crit_damage' type='range' value='<?=$page->unit->crit_damage?>' value='<?=$page->unit->crit_damage?>' min='<?=$page->unit->crit_damage?>' max='400' oninput='updateMinValue("crit_damage", this.value);'>
-                            <span id='lbl_min_crit_damage'><?=$page->unit->crit_damage?></span>
+                            <input id='min_crit_damage' type='range' value='<?=$page->unit->total_crit_damage?>' min='<?=$page->unit->crit_damage?>' max='400' oninput='updateMinValue("crit_damage", this);'>
+                            <input type='number' id='lbl_min_crit_damage' value='<?=$page->unit->total_crit_damage?>' min='<?=$page->unit->crit_damage?>' max='400' onChange='updateMinValue("crit_damage", this);'></input>%
                         </td>
                     </tr>
                     <tr>
@@ -685,8 +1174,38 @@
                             Min ACC
                         </td>
                         <td class='value'>
-                            <input id='min_accuracy' type='range' value='<?=$page->unit->accuracy?>' value='<?=$page->unit->accuracy?>' min='<?=$page->unit->accuracy?>' max='85' oninput='updateMinValue("accuracy", this.value);'>
-                            <span id='lbl_min_accuracy'><?=$page->unit->accuracy?></span>
+                            <input id='min_accuracy' type='range' value='<?=$page->unit->total_accuracy?>' min='<?=$page->unit->accuracy?>' max='85' oninput='updateMinValue("accuracy", this);'>
+                            <input type='number' id='lbl_min_accuracy' value='<?=$page->unit->total_accuracy?>' min='<?=$page->unit->accuracy?>' max='85' onChange='updateMinValue("accuracy", this);'></input>%
+                        </td>
+                    </tr>
+                    <tr>
+                        <td class='empty'>
+                        </td>
+                        <td class='empty'>
+                        </td>
+                        <td class='empty'>
+                        </td>
+                        <td class='name'>
+                            Min RES
+                        </td>
+                        <td class='value'>
+                            <input id='min_resistance' type='range' value='<?=$page->unit->total_resistance?>' min='<?=$page->unit->resistance?>' max='85' oninput='updateMinValue("resistance", this);'>
+                            <input type='number' id='lbl_min_resistance' value='<?=$page->unit->total_resistance?>' min='<?=$page->unit->resistance?>' max='85' onChange='updateMinValue("resistance", this);'></input>%
+                        </td>
+                    </tr>
+                    <tr>
+                        <td class='empty'>
+                        </td>
+                        <td class='empty'>
+                        </td>
+                        <td class='empty'>
+                        </td>
+                        <td class='name'>
+                            Min EHP
+                        </td>
+                        <td class='value'>
+                            <input id='min_ehp' type='range' value='<?=$page->unit->effective_hp?>' min='0' max='200000' oninput='updateMinValue("ehp", this);'>
+                            <input type='number' id='lbl_min_ehp' value='<?=$page->unit->effective_hp?>' min='0' max='200000' onChange='updateMinValue("ehp", this);'></input>
                         </td>
                     </tr>
                     <tr>
@@ -698,13 +1217,28 @@
                         <td class='empty'>
                         </td>
                         <td class='name'>
-                            Min RES
+                            Min DMG
                         </td>
                         <td class='value'>
-                            <input id='min_resistance' type='range' value='<?=$page->unit->resistance?>' value='<?=$page->unit->resistance?>' min='<?=$page->unit->resistance?>' max='100' oninput='updateMinValue("resistance", this.value);'>
-                            <span id='lbl_min_resistance'><?=$page->unit->resistance?></span>
+                            <input id='min_dmg' type='range' value='<?=$page->unit->effective_dmg?>' min='0' max='7000' oninput='updateMinValue("dmg", this);'>
+                            <input type='number' id='lbl_min_dmg' value='<?=$page->unit->effective_dmg?>' min='0' max='7000' onChange='updateMinValue("dmg", this);'></input>
                         </td>
                     </tr>
+                    
+                    
+                    
+                    
+                </table>
+            </article>
+        </section>
+        <section id='results' class='content'>
+            <h2>
+                Optimization results
+            </h2>
+            <article>
+                <table>
+                    <tbody id='optimizations'>
+                    </tbody>
                 </table>
             </article>
         </section>

+ 66 - 21
public/css/optimizer.css

@@ -100,7 +100,6 @@ section#monster article#profile div#monster_info{
 section#monster article#profile div#monster_info div#monster_details{
     display: block;
     font-size: 70%;
-    margin-top: -3em;
 }
 
 section#monster article#profile div#monster_info div#monster_details div#teams{
@@ -111,27 +110,15 @@ section#monster article#profile div#monster_info div#monster_details div#teams h
     margin: 0.2em auto;
 }
 
-section#monster article#profile div#monster_info div#exp{
-    border: 0.3em solid var(--ui-color-border);
-    border-radius: 0.5em;
-    height: 1em;
-    background-color: #00000088;
-    position: relative;
-    font-size: 100%;
-}
-section#monster article#profile div#monster_info div#exp span#exp_bar{
-    height: 1em;
+section#monster article#profile table#stats{
+    font-size: 90%;
+    vertical-align: top;
+    display: inline-block;
+    border: 0.1em solid black;
+    color: #ffffff;
+    margin: auto;
+    border-collapse: collapse;
     border-radius: 0.4em;
-    display: block;
-    background-color: #cc0000;
-}
-section#monster article#profile div#monster_info div#exp span#exp_text{
-    display: block;
-    text-align: center;
-    margin-top: -1.5em;
-    font-weight: bold;
-    font-size: 0.5em;
-    text-shadow: 0 0 0.1em #000000, 0 0 0.1em #000000, 0 0 0.1em #000000, 0 0 0.1em #000000, 0 0 0.1em #000000;
 }
 
 section#monster article#profile table#stats{
@@ -153,6 +140,14 @@ section#monster article#profile table#stats th{
 section#monster article#profile table#stats td{
     font-weight: bold;
     background-color: #ffffff33;
+    text-align: right;
+    font-family: monospace;
+    font-size: 120%;
+}
+
+section#monster article#profile table#stats td span.percent{
+    margin: 0 0 0 -0.7em;
+    font-size: 80%;
 }
 
 section#monster article#profile table#stats td, th{
@@ -180,3 +175,53 @@ section#monster article#profile div#artifacts table.artifact{
 section#parameters article{
     text-align: left;
 }
+
+section#parameters article input[type="number"]{
+    width: 4em;
+    text-align: right;
+    -moz-appearance: textfield;
+}
+
+/*section#results table.rune{
+    font-size: 50%;
+    display: inline-block;
+}*/
+
+
+section#results table.stat_table{
+    border-collapse: collapse;
+}
+
+section#results table.stat_table td.label{
+    text-align: left;
+}
+
+section#results table.stat_table td.value{
+    text-align: right;
+    font-family: monospace;
+    font-size: 110%;
+}
+
+section#results table.stat_table td.value span.variation{
+    font-size: 90%;
+    width: 3em;
+    display: inline-block;
+    text-align: left;
+    padding-left: 0.5em;
+    font-weight: bold
+}
+
+section#results table.stat_table td.value span.variation.increment{
+    color: #00ff00;
+}
+
+section#results table.stat_table td.value span.variation.increment::before {
+    content: "▲"; /*"&#9650;";*/
+}
+
+section#results table.stat_table td.value span.variation.decrement{
+    color: #ff0000;
+}
+section#results table.stat_table td.value span.variation.decrement::before {
+    content: "▼"; /*"&#9660;";
+}