Ver código fonte

SWEX plugin now parses record book. Battle and rank records and guild defense parsed by API. The home page has gone a good overhaul.

Iñigo Valentin 5 anos atrás
pai
commit
4ca64844f4

+ 3 - 0
application/API/v2/API_Controller.php

@@ -56,6 +56,9 @@
                     case "upload_run_rift":
                         require_once(__DIR__ . "/upload_run_rift.php");
                         break;
+                    case "update_logbook":
+                        require_once(__DIR__ . "/update_logbook.php");
+                        break;
                     case "units":
                         require_once(__DIR__ . "/units.php");
                         break;

+ 283 - 0
application/API/v2/bin/update_logbook.py

@@ -0,0 +1,283 @@
+#!/usr/bin/python3
+
+import sqlite3
+import json
+import sys
+import os
+
+
+"""
+Reads the API KEY, that must be passed as first command line argument.
+
+:returns: Recovered API KEY.
+:raises Exception: Th KEY couldn't be red.
+"""
+def readKey():
+    try:
+        #print(sys.argv[0])
+        key = sys.argv[1]
+        return key
+    except Exception as e:
+        print("Error parsing API KEY: " + str(e))
+        raise
+
+"""
+Reads the JSON data, that must be passed as second command line argument.
+
+:returns: Recovered data, in JSON format.
+:raises Exception: The data couldn't be red or converted to JSON.
+"""
+def readData():
+    try:
+        data = json.loads(sys.argv[2])
+        return data
+    except Exception as e:
+        print("Error parsing data: " + str(e))
+        raise
+
+"""
+Verifies that the API key matches the player data and that it exists in th DB.
+
+:param db: Connection to the database.
+:returns: Connection to the database.
+:param data: Data in json format.
+:param key: API KEY.
+:returns: True if key and player match, False otherwise.
+:raises IntegrityError: The queryes couldn't bre executed.
+"""
+def verifyKey(db, data, key):
+    print('Verifying KEY...')
+    status = False
+    try:
+        uid = data["lobby_wizard_log"]["wizard_id"]
+        cursor = db.cursor()
+        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
+        if cursor.fetchone()[0] == 1:
+            status = True
+        cursor.close()
+    except sqlite3.IntegrityError as e:
+        print("Error executing statement: " + str(e))
+        raise
+    return status
+
+"""
+Opens the database file and deletes from the user tables
+
+:param name: The path to the sqlite database.
+:returns: Connection to the database.
+:raises IntegrityError: The queryes couldn't bre executed.
+:raises IOError: The sqlite file couldn't be created.
+"""
+def openDatabase():
+    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
+    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
+    print('Configuring database...')
+    try:
+        db = sqlite3.connect(kdb)
+        cursor = db.cursor()
+        cursor.execute('attach "' + udb + '" as data;')
+        cursor.close()
+        return db
+    except sqlite3.IntegrityError as e:
+        print("Error executing statement: " + str(e))
+        raise
+    except IOError as e:
+        print("I/O Error creating database " + name + ": " + str(e))
+        raise
+
+"""
+Inserts a row into the database.
+
+:param db: Connection to the database.
+:param table: Name of the table to insert into.
+:param values: List of values to insert.
+:raises IntegrityError: The insert query was unsuccesfull.
+"""
+def insert(db, table, values):
+    cursor = db.cursor()
+    placeholders = ''
+    for x in range(0, len(values)):
+        placeholders = placeholders + '?, '
+    placeholders = placeholders[:len(placeholders) - 2]
+    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
+    try:
+        cursor.execute(query, values)
+    except sqlite3.IntegrityError as e:
+        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
+        raise
+    cursor.close;
+
+"""
+Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
+run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
+run_drop_shapeshifting).
+
+:param db: Sqlite database connection.
+:param data: JSON data.
+"""
+def parseData(db, data):
+
+    cursor = db.cursor()
+
+    # Page 1: Cairos non-elemental, rift raid, rift dungeon.
+    if (data["lobby_wizard_log"]["page_no"] == 1):
+        print("Parsing logbook data...")
+        
+        uid = data["lobby_wizard_log"]["wizard_id"]
+        joined = data["lobby_wizard_log"]["account_create_timestamp"]
+        top_rank_arena = data["lobby_wizard_log"]["pvp_best_rating_id"]
+        top_rank_world_arena = data["lobby_wizard_log"]["rtpvp_rank_best_rating_id"]
+        top_rank_special_league = data["lobby_wizard_log"]["rtpvp_contest_best_rating_id"]
+        top_rank_gw = data["lobby_wizard_log"]["guildwar_best_rating_id"]
+        top_rank_siege = data["lobby_wizard_log"]["guildsiege_best_rating_id"]
+        top_rank_wboss = data["lobby_wizard_log"]["world_boss_best_rank_id"]
+        top_rank_toan = data["lobby_wizard_log"]["trial_tower_normal_best_floor"]
+        top_rank_toah = data["lobby_wizard_log"]["trial_tower_hard_best_floor"]
+        cursor.execute("""
+            UPDATE player SET 
+              joined = ?,
+              top_rank_arena = ?,
+              top_rank_world_arena = ?,
+              top_rank_special_league = ?,
+              top_rank_gw = ?,
+              top_rank_siege = ?,
+              top_rank_wboss = ?,
+              top_rank_toan = ?,
+              top_rank_toah = ?
+            WHERE uid = ?;
+            """,
+            (
+                joined,
+                top_rank_arena,
+                top_rank_world_arena,
+                top_rank_special_league,
+                top_rank_gw,
+                top_rank_siege,
+                top_rank_wboss,
+                top_rank_toan,
+                top_rank_toah,
+                uid,
+            )
+        )
+
+        # Loop Cairos records
+        for record in data["lobby_wizard_log"]["dungeon_best_clear_info_list"]:
+            area_type = 2 # Cairos Dungeons
+            area = record["dungeon_id"]
+            stage = record["stage_id"]
+            time = record["clear_time"]
+            score = 0 # No scores in Cairos
+            rank = None # No rank in Cairos
+            cursor.execute("DELETE FROM record_party WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            cursor.execute("DELETE FROM record WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            insert(db, "record", (uid, area_type, area, stage, time, score, rank))
+            for party in record["my_unit_deck_list"]:
+                unit_id = party["unit_id"]
+                unit_master_id = party["unit_master_id"]
+                leader = party["leader"]
+                front = 0 # No frontline in Cairos
+                insert(db, "record_party", (uid, area_type, area, unit_id, unit_master_id, leader, front))
+
+        # Rift Raid record
+        if data["lobby_wizard_log"]["raid_best_clear_info_list"][0]:
+            area_type = 4
+            stage = data["lobby_wizard_log"]["raid_best_clear_info_list"][0]["stage_id"]
+            area = stage
+            time = data["lobby_wizard_log"]["raid_best_clear_info_list"][0]["clear_time"]
+            score = 0 # No scores in Rift Raid
+            rank = None # No rank in Rift Raid
+            cursor.execute("DELETE FROM record_party WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            cursor.execute("DELETE FROM record WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            insert(db, "record", (uid, area_type, area, stage, time, score, rank))
+            for party in data["lobby_wizard_log"]["raid_best_clear_info_list"][0]["my_unit_deck_list"]:
+                unit_id = party["unit_id"]
+                unit_master_id = party["unit_master_id"]
+                leader = party["leader"]
+                if party["slot_index"] <= 4:
+                    front = 1
+                else:
+                    front = 0
+                insert(db, "record_party", (uid, area_type, area, unit_id, unit_master_id, leader, front))
+
+        # Loop Rift Dungeon records
+        for record in data["lobby_wizard_log"]["rift_dungeon_best_clear_info_list"]:
+            area_type = 3 # Rift Elemental Dungeons
+            area = record["rift_dungeon_id"]
+            stage = 0 # No stage in Rift Dungeons
+            time = 0 # No time in Rift Dungeons
+            score = record["clear_damage"]
+            raw_rank = raw_rank = record["clear_rating"]
+            if raw_rank == 2:
+                rank = "D"
+            elif raw_rank == 3:
+                rank = "C"
+            elif raw_rank == 4:
+                rank = "B-"
+            elif raw_rank == 5:
+                rank = "B"
+            elif raw_rank == 6:
+                rank = "B+"
+            elif raw_rank == 7:
+                rank = "A-"
+            elif raw_rank == 8:
+                rank = "A"
+            elif raw_rank == 9:
+                rank = "A+"
+            elif raw_rank == 90:
+                rank = "S"
+            elif raw_rank == 11:
+                rank = "SS"
+            elif raw_rank == 12:
+                rank = "SSS"
+            else:
+                rank = None
+            cursor.execute("DELETE FROM record_party WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            cursor.execute("DELETE FROM record WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            insert(db, "record", (uid, area_type, area, stage, time, score, rank))
+            for party in record["my_unit_deck_list"]:
+                unit_id = party["unit_id"]
+                unit_master_id = party["unit_master_id"]
+                leader = party["leader"]
+                if party["slot_index"] <= 4:
+                    front = 1
+                else:
+                    front = 0
+                insert(db, "record_party", (uid, area_type, area, unit_id, unit_master_id, leader, front))
+        db.commit()
+
+    # Page 2: Cairos non-elemental, rift raid, rift dungeon.
+    elif (data["lobby_wizard_log"]["page_no"] == 2):
+        uid = data["lobby_wizard_log"]["wizard_id"]
+        # Loop Cairos records
+        for record in data["lobby_wizard_log"]["dungeon_best_clear_info_list"]:
+            area_type = 2 # Cairos Dungeons
+            area = record["dungeon_id"]
+            stage = record["stage_id"]
+            time = record["clear_time"]
+            score = 0 # No scores in Cairos
+            rank = None # No rank in Cairos
+            cursor.execute("DELETE FROM record_party WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            cursor.execute("DELETE FROM record WHERE uid = ? AND area_type = ? AND area = ?;", (uid, area_type, area))
+            insert(db, "record", (uid, area_type, area, stage, time, score, rank))
+            for party in record["my_unit_deck_list"]:
+                unit_id = party["unit_id"]
+                unit_master_id = party["unit_master_id"]
+                leader = party["leader"]
+                front = 0 # No frontline in Cairos
+                insert(db, "record_party", (uid, area_type, area, unit_id, unit_master_id, leader, front))
+        db.commit()
+
+"""
+Begin script
+"""
+data = readData()
+key = readKey()
+db = openDatabase()
+if verifyKey(db, data, key) == False:
+    print("Invalid API KEY...")
+    sys.exit(-1)
+else:
+    parseData(db, data)
+sys.exit(0)
+
+

+ 30 - 0
application/API/v2/bin/upload_profile.py

@@ -107,6 +107,7 @@ def clearData(db, data):
         cursor.execute('PRAGMA foreign_keys = OFF;')
         cursor.execute('DELETE FROM scenario WHERE uid = ?', [uid])
         cursor.execute('DELETE FROM defense WHERE uid = ?', [uid])
+        cursor.execute('DELETE FROM gw_defense WHERE uid = ?', [uid])
         cursor.execute('DELETE FROM unit_skill WHERE unit IN (SELECT id FROM unit WHERE uid = ?)', [uid])
         cursor.execute('DELETE FROM unit WHERE uid = ?', [uid])
         cursor.execute('DELETE FROM rune WHERE uid = ?', [uid])
@@ -296,6 +297,30 @@ def parseDefense(db, data):
         insert(db, "defense", (uid, unit, position))
     db.commit()
 
+"""
+Parses guild war defense units (table gw_defense).
+
+:param db: Sqlite database connection.
+:param data: Data in json format.
+"""
+def parseGWDefense(db, data):
+    print("Parsing guild war defense...")
+    uid = data["wizard_info"]["wizard_id"]
+    if data["guildwar_defense_unit_list"][0]:
+        position = 1
+        for defense in data["guildwar_defense_unit_list"][0]:
+            unit = defense["unit_id"]
+            insert(db, "gw_defense", (uid, unit, position))
+            position = position + 1
+    if data["guildwar_defense_unit_list"][1]:
+        position = 4
+        for defense in data["guildwar_defense_unit_list"][1]:
+            unit = defense["unit_id"]
+            insert(db, "gw_defense", (uid, unit, position))
+            position = position + 1
+        
+    db.commit()
+
 """
 Parses buildings (table building).
 
@@ -1248,6 +1273,11 @@ else:
     except Exception as e:
         print("Error parsing defense data: " + str(e))
         sys.exit(400)
+    try:
+        parseGWDefense(db, data)
+    except Exception as e:
+        print("Error parsing guild war defense data: " + str(e))
+        sys.exit(400)
     try:
         parseBuildings(db, data)
     except Exception as e:

+ 77 - 0
application/API/v2/update_logbook.php

@@ -0,0 +1,77 @@
+<?php
+    /**
+     * Logbook logger script.
+     *
+     * Exposes an API to update the logbook for player data and records.
+     * Reads post data and calls the update_logbook.py script.
+     * Mandatory POST parameters are:
+     *  - data: Received JSON file after a run.
+     *  - key: User API key.
+     *
+     * @category API
+     */
+
+    global $db;
+
+    try{
+        // Check data
+        $data = filter_input(INPUT_POST, 'response');
+        if ($data == null || $data == false){
+            http_response_code(400);
+            return 400;
+        }
+        // Check API key.
+        $key = filter_input(INPUT_POST, 'key');
+        if ($key == null || $key == false){
+            http_response_code(401);
+            return 401;
+        }
+        // Check data format.
+        $json = json_decode($data);
+        if ($json === null){
+            http_response_code(400);
+            return 400;
+        }
+        // Authenticate
+        $uid = $json->{"lobby_wizard_log"}->{"wizard_id"};
+        $s = "SELECT COUNT(uid) AS c FROM player WHERE uid = $uid AND api_key = '$key';";
+        if (1 != $db->query($s)->fetchArray(SQLITE3_ASSOC)["c"]){
+            http_response_code(401);
+            return 401;
+        }
+
+        // Run scenario run parser script
+        $cmd = __DIR__ . "/bin/update_logbook.py " . $key . " " . escapeshellarg($data);;
+        $out = [];
+        $ret = 0;
+        try{
+            exec($cmd, $out, $ret);
+        }
+        catch(Exception $e) {
+            error_log("Error running scenario run script '$cmd': " . $e->getMessage());
+            http_response_code(500);
+            return 500;
+        }
+
+        if ($ret != 200){
+            try{
+                http_response_code($ret);
+                return $ret;
+            }
+            catch(Exception $e) {
+                error_log("Dungeon run script '$cmd' returned an unexpected value $ret: " . $e->getMessage());
+                http_response_code(500);
+                return 500;
+            }
+        }
+
+        // At this point, status code should be 200
+        http_response_code($ret);
+        return $ret;
+    }
+    catch(Exception $e) {
+        error_log("Unknown error parsing scenario run: " . $e->getMessage());
+        http_response_code(500);
+        return 500;
+    }
+?>

+ 107 - 1
application/Constant.php

@@ -500,7 +500,7 @@
         /**
          * Steel Fortress
          */
-        const STEEL_FORTRESS = 9602; // TODO: Find out
+        const STEEL_FORTRESS = 9501;
 
         /**
          * Hall of Light.
@@ -1788,6 +1788,112 @@
         const LEGEND = 1;
     };
 
+    /**
+     * Arena rank constant.
+     *
+     * @category Data
+     */
+    final class ARENA_RANK_ID{
+
+        /**
+         * Beginer.
+         */
+        const BEGINER = 901;
+
+        /**
+         * Challenger 1.
+         */
+        const CHALLENGER_1 = 1001;
+
+        /**
+         * Challenger 2.
+         */
+        const CHALLENGER_2 = 1002;
+
+        /**
+         * Challenger 3.
+         */
+        const CHALLENGER_3 = 1003;
+
+        /**
+         * Fighter 1.
+         */
+        const FIGHTER_1 = 2001;
+
+        /**
+         * Fighter 2.
+         */
+        const FIGHTER_2 = 2002;
+
+        /**
+         * Fighter 3.
+         */
+        const FIGHTER_3 = 2003;
+
+        /**
+         * Conqueror 1.
+         */
+        const CONQUEROR_1 = 3001;
+
+        /**
+         * Conqueror 2.
+         */
+        const CONQUEROR_2 = 3002;
+
+        /**
+         * Conqueror 3.
+         */
+        const CONQUEROR_3 = 3003;
+
+        /**
+         * Guardian 1.
+         */
+        const GUARDIAN_1 = 4001;
+
+        /**
+         * Guardian 2.
+         */
+        const GUARDIAN_2 = 4002;
+
+        /**
+         * Guardian 3.
+         */
+        const GUARDIAN_3 = 40003;
+
+        /**
+         * Legend.
+         */
+        const LEGEND = 5001;
+    }
+
+    /**
+     * World Boss rank constant.
+     *
+     * @category Data
+     */
+    final class WORLD_BOSS_RANK_ID{
+
+        /**
+         * Beginer.
+         */
+        const RANK = [
+            0 => "F",
+            1 => "D",
+            2 => "C",
+            3 => "B-",
+            4 => "B",
+            5 => "B+",
+            6 => "A-",
+            7 => "A",
+            8 => "A+",
+            9 => "S",
+            10 => "SS",
+            11 => "SSS"
+        ];
+
+        
+    }
+
     /**
      * Default filter values;
      * 

+ 1 - 0
application/config.php

@@ -60,6 +60,7 @@
             "ICON" => BASE_URL . "img/icon/",
             "LOGO" => BASE_URL . "img/logo/",
             "CURRENCY" => BASE_URL . "img/currency/",
+            "RANK" => BASE_URL . "img/rank/",
             "UNIT" => BASE_URL . "img/unit/",
             "AREA" => BASE_URL . "img/area/",
             "SKILL" => BASE_URL . "img/skill/",

+ 2 - 2
application/entity/K_Area.php

@@ -110,10 +110,10 @@
                         return APPLICATION::img("UNIT", 62105);
                         break;
                     case DUNGEON_ID::STEEL_FORTRESS:
-                        return APPLICATION::img("UNIT", 62105); // TODO: Correct image.
+                        return APPLICATION::img("UNIT", 62403);
                         break;
                     case DUNGEON_ID::PUNISHERS_CRYPT:
-                        return APPLICATION::img("UNIT", 62105); // TODO: Correct image.
+                        return APPLICATION::img("UNIT", 62604);
                         break;
                     case DUNGEON_ID::HALL_OF_WATER:
                         return APPLICATION::img("UNIT", 60101);

+ 429 - 0
application/entity/Player.php

@@ -0,0 +1,429 @@
+<?php
+    /**
+     * Player entity file.
+     *
+     * Creates the entity and makes it available.
+     *
+     * @category Entity
+     */
+
+    /**
+     * Require dependent entities if not present.
+     */
+    require_once(PATH::ENTITY . "Entity.php");
+    require_once(PATH::ENTITY . "Unit.php");
+    require_once(PATH::ENTITY . "Building.php");
+    require_once(PATH::ENTITY . "Decoration.php");
+    require_once(PATH::ENTITY . "Inventory.php");
+    require_once(PATH::ENTITY . "Record.php");
+
+    /**
+     * A Unit.
+     *
+     * Represents an object from the table 'unit'.
+     *
+     * @category Entity
+     */
+    class Player extends Entity{
+
+        /**
+         * @var int Player ID.
+         */
+        public $uid;
+
+        /**
+         * @var int Player level.
+         */
+        public $level;
+
+        /**
+         * @var string Player name.
+         */
+        public $name;
+
+        /**
+         * @var string Player country (XX).
+         */
+        public $country;
+
+        /**
+         * @var int Total experience.
+         */
+        public $experience;
+
+        /**
+         * @var Unit Representative Unit.
+         */
+        public $rep;
+
+        /**
+         * @var int Timestamp of player registration.
+         */
+        public $joined = 0;
+
+        /**
+         * @var int Top rank in arena.
+         */
+        public $top_rank_arena = 0;
+
+        /**
+         * @var int Top rank in world arena.
+         */
+        public $top_rank_world_arena = 0;
+
+        /**
+         * @var int Top rank in special league.
+         */
+        public $top_rank_special_league = 0;
+
+        /**
+         * @var int Top rank in guild war.
+         */
+        public $top_rank_gw = 0;
+
+        /**
+         * @var int Top rank in guild siege.
+         */
+        public $top_rank_siege = 0;
+
+        /**
+         * @var int Top rank in World Boss.
+         */
+        public $top_rank_wboss = 0;
+
+        /**
+         * @var int Top rank in TOA normal.
+         */
+        public $top_rank_toan = 0;
+
+        /**
+         * @var int Top rank in TOA HARD.
+         */
+        public $top_rank_toah = 0;
+
+        /**
+         * @var \Unit[] Units in Arena defense.
+         */
+        public $defense = [];
+
+        /**
+         * @var \Unit[] Units in Arena defense.
+         */
+        public $gw_defense = [[], []];
+
+        /**
+         * @var int[] Currency.
+         */
+        public $currency = [
+            "mana" => 0,
+            "crystal" => 0,
+            "energy" => 0,
+            "energy_max" => 0,
+            "arena_energy" => 0,
+            "arena_energy_max" => 0,
+            "darkportal_energy" => 0,
+            "darkportal_energy_max" => 0,
+            "dimension_energy" => 0,
+            "dimension_energy_max" => 0,
+            "honor_point" => 0,
+            "guild_point" => 0,
+            "honor_medal" => 0,
+            "honor_mark" => 0,
+            "event_coin" => 0,
+            "social_point" => 0,
+            "ancient_stone" => 0,
+            "costume_point" => 0,
+        ];
+
+        /**
+         * @var \Building[] List of Buildings.
+         */
+        public $building = [];
+
+        /**
+         * @var \Decoration[] List of Decorations.
+         */
+        public $decoration = [];
+
+        /**
+         * @var \Inventory[] List of Scrolls in Inventory.
+         */
+        public $inventory_scroll = [];
+
+        /**
+         * @var \Inventory[] List of rune crafting items in Inventory.
+         */
+        public $inventory_craft_rune = [];
+
+        /**
+         * @var \Inventory[] List of rune crafting items in Inventory.
+         */
+        public $inventory_craft = [];
+
+        /**
+         * @var \Inventory[] List of rune crafting items in Inventory.
+         */
+        public $inventory_essence = [];
+
+        /**
+         * @var \Record[] Player record runs.
+         */
+        public $record = [];
+
+
+        /**
+         * Constructor.
+         *
+         * Searches the database and retrieves the information about the
+         * player, populating it and it's items.
+         *
+         * @param int $id Monster identifier.
+         * @param bool $complete If false, query only monster and k_monster.
+         * @global int Player ID.
+         * @global resource Database connection.
+         */
+        public function __construct($id, $complete = true){
+            global $UID;
+            global $db;
+            $s = "
+              SELECT
+                uid,
+                name,
+                level,
+                country,
+                experience,
+                rep,
+                mana,
+                crystal,
+                energy,
+                energy_max,
+                arena_energy,
+                arena_energy_max,
+                darkportal_energy,
+                darkportal_energy_max,
+                dimension_energy,
+                dimension_energy_max,
+                honor_point,
+                guild_point,
+                honor_medal,
+                honor_mark,
+                event_coin,
+                social_point,
+                costume_point,
+                joined,
+                top_rank_arena,
+                top_rank_world_arena,
+                top_rank_special_league,
+                top_rank_gw,
+                top_rank_siege,
+                top_rank_wboss,
+                top_rank_toan,
+                top_rank_toah
+              FROM player
+              WHERE uid = '$UID';
+            ";
+            $q = $db->query($s);
+            $r = $q->fetchArray(SQLITE3_ASSOC);
+            if ($r){
+                $this->uid = $r["uid"];
+                $this->name = $r["name"];
+                $this->level = $r["level"];
+                $this->country = $r["country"];
+                $this->experience = $r["experience"];
+                if (strlen($r["rep"]) > 0){
+                    $this->rep = new Unit($r["rep"]);
+                }
+                $this->currency["mana"] = $r["mana"];
+                $this->currency["crystal"] = $r["crystal"];
+                $this->currency["energy"] = $r["energy"];
+                $this->currency["energy_max"] = $r["energy_max"];
+                $this->currency["arena_energy"] = $r["arena_energy"];
+                $this->currency["arena_energy_max"] = $r["arena_energy_max"];
+                $this->currency["darkportal_energy"] = $r["darkportal_energy"];
+                $this->currency["darkportal_energy_max"] = $r["darkportal_energy_max"];
+                $this->currency["dimension_energy"] = $r["dimension_energy"];
+                $this->currency["dimension_energy_max"] = $r["dimension_energy_max"];
+                $this->currency["honor_point"] = $r["honor_point"];
+                $this->currency["guild_point"] = $r["guild_point"];
+                $this->currency["honor_medal"] = $r["honor_medal"];
+                $this->currency["honor_mark"] = $r["honor_mark"];
+                $this->currency["event_coin"] = $r["event_coin"];
+                $this->currency["social_point"] = $r["social_point"];
+                $this->currency["costume_point"] = $r["costume_point"];
+                $this->joined = $r["joined"];
+                $this->top_rank_arena = $r["top_rank_arena"];
+                $this->top_rank_world_arena = $r["top_rank_world_arena"];
+                $this->top_rank_special_league = $r["top_rank_special_league"];
+                $this->top_rank_gw = $r["top_rank_gw"];
+                $this->top_rank_siege = $r["top_rank_siege"];
+                $this->top_rank_wboss = $r["top_rank_wboss"];
+                $this->top_rank_toan = $r["top_rank_toan"];
+                $this->top_rank_toah = $r["top_rank_toah"];
+            }
+            $s = "
+                SELECT unit
+                FROM defense
+                WHERE uid = '$UID'
+                ORDER BY position;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->defense, new Unit($r["unit"], false));
+            }
+            $s = "
+                SELECT
+                  unit,
+                  position
+                FROM gw_defense
+                WHERE uid = '$UID'
+                ORDER BY position;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                if ($r["position"] <= 3){
+                    array_push($this->gw_defense[0], new Unit($r["unit"], false));
+                }
+                else{
+                    array_push($this->gw_defense[1], new Unit($r["unit"], false));
+                }
+            }
+            $s = "
+                SELECT
+                  building.id,
+                  min(building)
+                FROM
+                  building,
+                  k_building
+                WHERE
+                  uid = '$UID' AND
+                  building.building = k_building.id 
+                GROUP BY building.building;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->building, new Building($r["id"]));
+            }
+            $s = "
+                SELECT id
+                FROM decoration
+                WHERE uid = '$UID';
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->decoration, new Decoration($r["id"]));
+            }
+            $s = "
+                SELECT
+                  id,
+                  type
+                FROM inventory
+                WHERE
+                  uid = '$UID' AND
+                  type = " . INVENTORY_TYPE_ID::SCROLL . " AND
+                  amount > 0
+                ORDER BY inventory.type;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->inventory_scroll, new Inventory($r["id"], $r["type"]));
+            }
+            // Rune crafting items are marked as generic crafting.
+            $s = "
+                SELECT
+                  inventory.id AS id,
+                  inventory.type AS type
+                FROM
+                  inventory
+                WHERE
+                  inventory.uid = '$UID' AND
+                  inventory.type = " . INVENTORY_TYPE_ID::RUNE_CRAFT . " AND
+                  amount > 0
+                ORDER BY inventory.id;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->inventory_craft_rune, new Inventory($r["id"], $r["type"]));
+            }
+            $s = "
+                SELECT
+                  inventory.id AS id,
+                  inventory.type AS type
+                FROM
+                  inventory
+                WHERE
+                  inventory.uid = '$UID' AND
+                  inventory.type = " . INVENTORY_TYPE_ID::CRAFT_STUFF . " AND
+                  amount > 0
+                ORDER BY inventory.id;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->inventory_craft, new Inventory($r["id"], $r["type"]));
+            }
+            $s = "
+                SELECT
+                  inventory.id AS id,
+                  inventory.type AS type
+                FROM
+                  inventory,
+                  k_inventory
+                WHERE
+                  inventory.id = k_inventory.id AND
+                  inventory.type = k_inventory.type AND
+                  inventory.uid = '$UID' AND
+                  inventory.type = " . INVENTORY_TYPE_ID::ESSENCES . " AND
+                  amount > 0
+                ORDER BY
+                  upper(name) NOT LIKE '%MAGIC%',
+                  upper(name) NOT LIKE '%FIRE%',
+                  upper(name) NOT LIKE '%WATER%',
+                  upper(name) NOT LIKE '%WIND%',
+                  upper(name) NOT LIKE '%LIGHT%',
+                  upper(name) NOT LIKE '%DARK%',
+                  upper(name) NOT LIKE '%LOW%',
+                  upper(name) NOT LIKE '%MID%',
+                  upper(name) NOT LIKE '%HIGH%'
+                ;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->inventory_essence, new Inventory($r["id"], $r["type"]));
+            }
+            $s = "
+                SELECT
+                  uid,
+                  area_type,
+                  area
+                FROM record
+                WHERE uid = '$UID'
+                ORDER BY
+                  CASE
+
+                    WHEN (area_type = 2 AND area = 8001) THEN  1 -- Giant's Keep
+                    WHEN (area_type = 2 AND area = 9001) THEN  2 -- Dragon's Lair
+                    WHEN (area_type = 2 AND area = 6001) THEN  3 -- Necropolis
+                    WHEN (area_type = 2 AND area = 9501) THEN  4 -- Steel Fortress
+                    WHEN (area_type = 2 AND area = 9502) THEN  5 -- Punisher's Crypt
+                    WHEN (area_type = 4)                 THEN  6 -- Rift of Worlds
+                    WHEN (area_type = 3 AND area = 1001) THEN  7 -- Rift Dungeon - Ice Beast
+                    WHEN (area_type = 3 AND area = 2001) THEN  8 -- Rift Dungeon - Fire Beast
+                    WHEN (area_type = 3 AND area = 3001) THEN  9 -- Rift Dungeon - Wind Beast
+                    WHEN (area_type = 3 AND area = 4001) THEN 10 -- Rift Dungeon - Light Beast
+                    WHEN (area_type = 3 AND area = 5001) THEN 11 -- Rift Dungeon - Dark Beast
+                    WHEN (area_type = 2 AND area = 5001) THEN 12 -- Hall of Magic
+                    WHEN (area_type = 2 AND area = 3001) THEN 13 -- Hall of Water
+                    WHEN (area_type = 2 AND area = 2001) THEN 14 -- Hall of Fire
+                    WHEN (area_type = 2 AND area = 4001) THEN 15 -- Hall of Wind
+                    WHEN (area_type = 2 AND area = 7001) THEN 16 -- Hall of Light
+                    WHEN (area_type = 2 AND area = 1001) THEN 17 -- Hall of Dark
+                    ELSE area 
+                    END ASC
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->record, new Record($r["uid"], $r["area_type"], $r["area"]));
+            }
+        }
+
+    }
+?>

+ 146 - 0
application/entity/Record.php

@@ -0,0 +1,146 @@
+<?php
+    /**
+     * Record run entity file.
+     *
+     * Creates the entity and makes it available.
+     *
+     * @category Entity
+     */
+
+    /**
+     * Require dependent entities if not present.
+     */
+    require_once(PATH::ENTITY . "Entity.php");
+    require_once(PATH::ENTITY . "Unit.php");
+    require_once(PATH::ENTITY . "K_Unit.php");
+    require_once(PATH::ENTITY . "K_Area.php");
+
+
+    /**
+     * A record run.
+     *
+     * Represents an object from the table 'record'.
+     *
+     * @category Entity
+     */
+    class Record extends Entity{
+
+        /**
+         * @var int Player identifier.
+         */
+        public $uid;
+
+        /**
+         * @var K_Area Area.
+         */
+        public $area;
+
+        /**
+         * @var int Stage.
+         */
+        public $stage;
+
+        /**
+         * @var int Clear time, milliseconds.
+         */
+        public $time;
+
+        /**
+         * @var int Score in battles that are rated (WB, rift dungeons...).
+         */
+        public $score;
+
+        /**
+         * @var String Rank in battles that are rated (WB, rift dungeons...).
+         */
+        public $rank;
+
+        /**
+         * @var \Unit[]|\K_Unit[] Uits used.
+         * If the unit is still owned, it will be a instance of Unit.
+         * If not, it will be a instance of K_Unit.
+         */
+        public $party = [];
+
+        /**
+         * @var int ID of the leader unit.
+         */
+        public $leader;
+
+        /**
+         * @var int[] List of IDs of the frontline units.
+         */
+        public $frontline = [];
+
+        /**
+         * Constructor.
+         *
+         * Searches the database and retrieves the information about the
+         * run, populating it and it's items.
+         *
+         * @param int $id Run identifier.
+         * @global resource Database connection.
+         */
+        public function __construct($uid, $area_type, $area){
+
+            global $db;
+
+            $s = "
+                SELECT
+                  uid,
+                  area_type,
+                  area,
+                  stage,
+                  time,
+                  score,
+                  rank
+                FROM record
+                WHERE
+                  uid = $uid AND
+                  area_type = $area_type AND
+                  area = $area;
+            ";
+            error_log($s);
+            $q = $db->query($s);
+            $r = $q->fetchArray(SQLITE3_ASSOC);
+            $this->uid = $r["uid"];
+            $this->area = new K_Area($r["area"], $r["area_type"]);
+            $this->stage = $r["stage"];
+            $this->time = $r["time"];
+            $this->score = $r["score"];
+            $this->rank = $r["rank"];
+            $s = "
+                SELECT
+                  unit,
+                  k_unit,
+                  (SELECT count(id) FROM unit WHERE unit.id = record_party.unit) AS owned,
+                  leader,
+                  front
+                FROM record_party
+                WHERE
+                  uid = $uid AND
+                  area_type = $area_type AND
+                  area = $area
+                ORDER BY 
+                  front DESC,
+                  leader DESC;
+            ";
+            $q = $db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                if ($r["owned"] > 0){
+                    array_push($this->party, new Unit($r["unit"], false));
+                }
+                else{
+                    array_push($this->party, new K_Unit($r["k_unit"], false));
+                }
+                if ($r["leader"] == 1){
+                    $this->leader = $r["unit"];
+                }
+                if ($r["front"] == 1){
+                    array_push($this->frontline, $r["unit"]);
+                }
+            }
+        }
+
+    }
+?>

+ 71 - 0
application/helper/HTML_Helper.php

@@ -668,6 +668,77 @@
             $html .= "</div>\n";
             return $html;
         }
+
+        /**
+         * Generates an arena rank icon image.
+         *
+         * @param int $d Arena rank id.
+         * @return string HTML content for the image.
+         */
+        public static function arena_rank_icon($id) {
+            switch ($id){
+                case ARENA_RANK_ID::BEGINER:
+                    $src = URL::IMG["RANK"] . "0901.png";
+                    $tit = "Beginer";
+                    break;
+                case ARENA_RANK_ID::CHALLENGER_1:
+                    $src = URL::IMG["RANK"] . "1001.png";
+                    $tit = "Challenger 1";
+                    break;
+                case ARENA_RANK_ID::CHALLENGER_2:
+                    $src = URL::IMG["RANK"] . "1002.png";
+                    $tit = "Challenger 2";
+                    break;
+                case ARENA_RANK_ID::CHALLENGER_3:
+                    $src = URL::IMG["RANK"] . "1003.png";
+                    $tit = "Challenger 3";
+                    break;
+                case ARENA_RANK_ID::FIGHTER_1:
+                    $src = URL::IMG["RANK"] . "2001.png";
+                    $tit = "Fighter 1";
+                    break;
+                case ARENA_RANK_ID::FIGHTER_2:
+                    $src = URL::IMG["RANK"] . "2002.png";
+                    $tit = "Fighter 2";
+                    break;
+                case ARENA_RANK_ID::FIGHTER_3:
+                    $src = URL::IMG["RANK"] . "2003.png";
+                    $tit = "Fighter 3";
+                    break;
+                case ARENA_RANK_ID::CONQUEROR_1:
+                    $src = URL::IMG["RANK"] . "3001.png";
+                    $tit = "Conqueror 1";
+                    break;
+                case ARENA_RANK_ID::CONQUEROR_2:
+                    $src = URL::IMG["RANK"] . "3002.png";
+                    $tit = "Conqueror 2";
+                    break;
+                case ARENA_RANK_ID::CONQUEROR_3:
+                    $src = URL::IMG["RANK"] . "3003.png";
+                    $tit = "Conqueror 3";
+                    break;
+                case ARENA_RANK_ID::GUARDIAN_1:
+                    $src = URL::IMG["RANK"] . "4001.png";
+                    $tit = "Guardian 1";
+                    break;
+                case ARENA_RANK_ID::GUARDIAN_2:
+                    $src = URL::IMG["RANK"] . "4002.png";
+                    $tit = "Guardian 2";
+                    break;
+                case ARENA_RANK_ID::GUARDIAN_3:
+                    $src = URL::IMG["RANK"] . "4003.png";
+                    $tit = "Guardian 3";
+                    break;
+                case ARENA_RANK_ID::LEGEND:
+                    $src = URL::IMG["RANK"] . "5001.png";
+                    $tit = "Legend";
+                default:
+                    $src = URL::IMG["RANK"] . $id . ".png";
+            }
+            $html = "<img alt='$tit' title='$tit' src='$src'/>";
+            return $html;
+        }
+
     }
 
 ?>

+ 6 - 263
application/page/Home_Page.php

@@ -11,10 +11,7 @@
      * Require dependent files if not present.
      */
     require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Unit.php");
-    require_once(PATH::ENTITY . "Building.php");
-    require_once(PATH::ENTITY . "Decoration.php");
-    require_once(PATH::ENTITY . "Inventory.php");
+    require_once(PATH::ENTITY . "Player.php");
 
 
     /**
@@ -25,93 +22,9 @@
     class Home_Page extends Page{
 
         /**
-         * @var int Player ID.
+         * @var Player Player instance.
          */
-        public $uid;
-
-        /**
-         * @var int Player level.
-         */
-        public $level;
-
-        /**
-         * @var string Player name.
-         */
-        public $name;
-
-        /**
-         * @var string Player country (XX).
-         */
-        public $country;
-
-        /**
-         * @var int Total experience.
-         */
-        public $experience;
-
-        /**
-         * @var Unit Representative Unit.
-         */
-        public $rep;
-
-        /**
-         * @var \Unit[] Unitss in Arena defense.
-         */
-        public $defense = [];
-
-        /**
-         * @var int[] Currency.
-         */
-        public $currency = [
-            "mana" => 0,
-            "crystal" => 0,
-            "energy" => 0,
-            "energy_max" => 0,
-            "arena_energy" => 0,
-            "arena_energy_max" => 0,
-            "darkportal_energy" => 0,
-            "darkportal_energy_max" => 0,
-            "dimension_energy" => 0,
-            "dimension_energy_max" => 0,
-            "honor_point" => 0,
-            "guild_point" => 0,
-            "honor_medal" => 0,
-            "honor_mark" => 0,
-            "event_coin" => 0,
-            "social_point" => 0,
-            "ancient_stone" => 0,
-            "costume_point" => 0,
-        ];
-
-        /**
-         * @var \Building[] List of Buildings.
-         */
-        public $building = [];
-
-        /**
-         * @var \Decoration[] List of Decorations.
-         */
-        public $decoration = [];
-
-        /**
-         * @var \Inventory[] List of Scrolls in Inventory.
-         */
-        public $inventory_scroll = [];
-
-        /**
-         * @var \Inventory[] List of rune crafting items in Inventory.
-         */
-        public $inventory_craft_rune = [];
-
-        /**
-         * @var \Inventory[] List of rune crafting items in Inventory.
-         */
-        public $inventory_craft = [];
-
-        /**
-         * @var \Inventory[] List of rune crafting items in Inventory.
-         */
-        public $inventory_essence = [];
+        public $player;
 
         /**
          * Constructor.
@@ -119,183 +32,13 @@
          * Retrieves the data and initializes the variables.
          *
          * @global int Player ID.
-         * @global resource Connection to the database.
          */
         public function __construct(){
             global $UID;
-            global $db;
             $this->view = PATH::VIEW . "home.php";
-            $s = "
-              SELECT
-                uid,
-                name,
-                level,
-                country,
-                experience,
-                rep,
-                mana,
-                crystal,
-                energy,
-                energy_max,
-                arena_energy,
-                arena_energy_max,
-                darkportal_energy,
-                darkportal_energy_max,
-                dimension_energy,
-                dimension_energy_max,
-                honor_point,
-                guild_point,
-                honor_medal,
-                honor_mark,
-                event_coin,
-                social_point,
-                costume_point
-              FROM player
-              WHERE uid = '$UID';
-            ";
-            $q = $db->query($s);
-            $r = $q->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->uid = $r["uid"];
-                $this->name = $r["name"];
-                $this->level = $r["level"];
-                $this->country = $r["country"];
-                $this->experience = $r["experience"];
-                if (strlen($r["rep"]) > 0){
-                    $this->rep = new Unit($r["rep"]);
-                }
-                $this->currency["mana"] = $r["mana"];
-                $this->currency["crystal"] = $r["crystal"];
-                $this->currency["energy"] = $r["energy"];
-                $this->currency["energy_max"] = $r["energy_max"];
-                $this->currency["arena_energy"] = $r["arena_energy"];
-                $this->currency["arena_energy_max"] = $r["arena_energy_max"];
-                $this->currency["darkportal_energy"] = $r["darkportal_energy"];
-                $this->currency["darkportal_energy_max"] = $r["darkportal_energy_max"];
-                $this->currency["dimension_energy"] = $r["dimension_energy"];
-                $this->currency["dimension_energy_max"] = $r["dimension_energy_max"];
-                $this->currency["honor_point"] = $r["honor_point"];
-                $this->currency["guild_point"] = $r["guild_point"];
-                $this->currency["honor_medal"] = $r["honor_medal"];
-                $this->currency["honor_mark"] = $r["honor_mark"];
-                $this->currency["event_coin"] = $r["event_coin"];
-                $this->currency["social_point"] = $r["social_point"];
-                $this->currency["costume_point"] = $r["costume_point"];
-            }
-            $s = "
-                SELECT unit
-                FROM defense
-                WHERE uid = '$UID'
-                ORDER BY position;
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->defense, new Unit($r["unit"], false));
-            }
-            $s = "
-                SELECT
-                  building.id,
-                  min(building)
-                FROM
-                  building,
-                  k_building
-                WHERE
-                  uid = '$UID' AND
-                  building.building = k_building.id 
-                GROUP BY building.building;
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->building, new Building($r["id"]));
-            }
-            $s = "
-                SELECT id
-                FROM decoration
-                WHERE uid = '$UID';
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->decoration, new Decoration($r["id"]));
-            }
-            $s = "
-                SELECT
-                  id,
-                  type
-                FROM inventory
-                WHERE
-                  uid = '$UID' AND
-                  type = " . INVENTORY_TYPE_ID::SCROLL . " AND
-                  amount > 0
-                ORDER BY inventory.type;
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->inventory_scroll, new Inventory($r["id"], $r["type"]));
-            }
-            // Rune crafting items are marked as generic crafting.
-            $s = "
-                SELECT
-                  inventory.id AS id,
-                  inventory.type AS type
-                FROM
-                  inventory
-                WHERE
-                  inventory.uid = '$UID' AND
-                  inventory.type = " . INVENTORY_TYPE_ID::RUNE_CRAFT . " AND
-                  amount > 0
-                ORDER BY inventory.id;
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->inventory_craft_rune, new Inventory($r["id"], $r["type"]));
-            }
-            $s = "
-                SELECT
-                  inventory.id AS id,
-                  inventory.type AS type
-                FROM
-                  inventory
-                WHERE
-                  inventory.uid = '$UID' AND
-                  inventory.type = " . INVENTORY_TYPE_ID::CRAFT_STUFF . " AND
-                  amount > 0
-                ORDER BY inventory.id;
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->inventory_craft, new Inventory($r["id"], $r["type"]));
-            }
-            $s = "
-                SELECT
-                  inventory.id AS id,
-                  inventory.type AS type
-                FROM
-                  inventory,
-                  k_inventory
-                WHERE
-                  inventory.id = k_inventory.id AND
-                  inventory.type = k_inventory.type AND
-                  inventory.uid = '$UID' AND
-                  inventory.type = " . INVENTORY_TYPE_ID::ESSENCES . " AND
-                  amount > 0
-                ORDER BY
-                  upper(name) NOT LIKE '%MAGIC%',
-                  upper(name) NOT LIKE '%FIRE%',
-                  upper(name) NOT LIKE '%WATER%',
-                  upper(name) NOT LIKE '%WIND%',
-                  upper(name) NOT LIKE '%LIGHT%',
-                  upper(name) NOT LIKE '%DARK%',
-                  upper(name) NOT LIKE '%LOW%',
-                  upper(name) NOT LIKE '%MID%',
-                  upper(name) NOT LIKE '%HIGH%'
-                ;
-            ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->inventory_essence, new Inventory($r["id"], $r["type"]));
-            }
-            $this->title = "SWDB";
-            $this->description = "Summoners War DataBase";
+            $this->player = new Player($UID);
+            $this->title = $this->player->name . " - SWDB";
+            $this->description = $this->player->name . " - Summoners War DataBase";
             $this->canonical = URL::BASE;
         }
     }

BIN
application/sw.sqlite


+ 14 - 14
application/view/guild.php

@@ -161,59 +161,59 @@
                             <td class='score_icon <?=$odd?>'>
 <?php
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::BEGINER && (ARENA_RANKING_RANK::BEGINER == null || $member->rating <= ARENA_RANKING_RANK::BEGINER)){
-                                    $src = URL::IMG["ICON"] . "rank_beg.png";
+                                    $src = URL::IMG["RANK"] . "0900.png";
                                     $tit = "Beginer";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::CHALLENGER_1 && (ARENA_RANKING_RANK::CHALLENGER_1 == null || $member->rating <= ARENA_RANKING_RANK::CHALLENGER_1)){
-                                    $src = URL::IMG["ICON"] . "rank_cha1.png";
+                                    $src = URL::IMG["RANK"] . "1001.png";
                                     $tit = "Challenger 1";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::CHALLENGER_2 && (ARENA_RANKING_RANK::CHALLENGER_2 == null || $member->rating <= ARENA_RANKING_RANK::CHALLENGER_2)){
-                                    $src = URL::IMG["ICON"] . "rank_cha2.png";
+                                    $src = URL::IMG["RANK"] . "1002.png";
                                     $tit = "Challenger 2";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::CHALLENGER_3 && (ARENA_RANKING_RANK::CHALLENGER_3 == null || $member->rating <= ARENA_RANKING_RANK::CHALLENGER_3)){
-                                    $src = URL::IMG["ICON"] . "rank_cha3.png";
+                                    $src = URL::IMG["RANK"] . "1003.png";
                                     $tit = "Challenger 3";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::FIGHTER_1 && (ARENA_RANKING_RANK::FIGHTER_1 == null || $member->rating <= ARENA_RANKING_RANK::FIGHTER_1)){
-                                    $src = URL::IMG["ICON"] . "rank_fig1.png";
+                                    $src = URL::IMG["RANK"] . "2001.png";
                                     $tit = "Fighter 1";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::FIGHTER_2 && (ARENA_RANKING_RANK::FIGHTER_2 == null || $member->rating <= ARENA_RANKING_RANK::FIGHTER_2)){
-                                    $src = URL::IMG["ICON"] . "rank_fig2.png";
+                                    $src = URL::IMG["RANK"] . "2002.png";
                                     $tit = "Fighter 2";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::FIGHTER_3 && (ARENA_RANKING_RANK::FIGHTER_3 == null || $member->rating <= ARENA_RANKING_RANK::FIGHTER_3)){
-                                    $src = URL::IMG["ICON"] . "rank_fig3.png";
+                                    $src = URL::IMG["RANK"] . "2003.png";
                                     $tit = "Fighter 3";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::CONQUEROR_1 && (ARENA_RANKING_RANK::CONQUEROR_1 == null || $member->rating <= ARENA_RANKING_RANK::CONQUEROR_1)){
-                                    $src = URL::IMG["ICON"] . "rank_con1.png";
+                                    $src = URL::IMG["RANK"] . "3001.png";
                                     $tit = "Conqueror 1";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::CONQUEROR_2 && (ARENA_RANKING_RANK::CONQUEROR_2 == null || $member->rating <= ARENA_RANKING_RANK::CONQUEROR_2)){
-                                    $src = URL::IMG["ICON"] . "rank_con2.png";
+                                    $src = URL::IMG["RANK"] . "3002.png";
                                     $tit = "Conqueror 2";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::CONQUEROR_3 && (ARENA_RANKING_RANK::CONQUEROR_3 == null || $member->rating <= ARENA_RANKING_RANK::CONQUEROR_3)){
-                                    $src = URL::IMG["ICON"] . "rank_con3.png";
+                                    $src = URL::IMG["RANK"] . "3003.png";
                                     $tit = "Conqueror 3";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::GUARDIAN_1 && (ARENA_RANKING_RANK::GUARDIAN_1 == null || $member->rating <= ARENA_RANKING_RANK::GUARDIAN_1)){
-                                    $src = URL::IMG["ICON"] . "rank_gua1.png";
+                                    $src = URL::IMG["RANK"] . "4001.png";
                                     $tit = "Guardian 1";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::GUARDIAN_2 && (ARENA_RANKING_RANK::GUARDIAN_2 == null || $member->rating <= ARENA_RANKING_RANK::GUARDIAN_2)){
-                                    $src = URL::IMG["ICON"] . "rank_gua2.png";
+                                    $src = URL::IMG["RANK"] . "4002.png";
                                     $tit = "Guardian 2";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::GUARDIAN_3 && (ARENA_RANKING_RANK::GUARDIAN_3 == null || $member->rating <= ARENA_RANKING_RANK::GUARDIAN_3)){
-                                    $src = URL::IMG["ICON"] . "rank_gua3.png";
+                                    $src = URL::IMG["RANK"] . "4003.png";
                                     $tit = "Guardian 3";
                                 }
                                 if ($member->arena_score >= ARENA_RANKING_POINTS::LEGEND && (ARENA_RANKING_RANK::LEGEND == null || $member->rating <= ARENA_RANKING_RANK::LEGEND)){
-                                    $src = URL::IMG["ICON"] . "rank_leg.png";
+                                    $src = URL::IMG["RANK"] . "5001.png";
                                     $tit = "Legend";
                                 }
 ?>

+ 422 - 177
application/view/home.php

@@ -48,234 +48,479 @@
                 </span>
             </h2>
             <article id='profile'>
-                <h3>
-                    <span id='user_name'>
-                        <?=$page->name?>
-                    </span>
-                    <span id='user_level'>
-                        Lv. <?=$page->level?>
-                        <span id='user_exp'>
-                            (exp: <?=$page->experience?>)
-                        </span>
-                    </span>
-                </h3>
-<?php
-                if (isset($page->rep)){
-?>
-                    <div id='rep' class='profile_section'>
+                <div class='panel' id='panel_left'>
+                    <div id='player' class='profile_section'>
                         <h4>
-                            Rep. Monster
+                            <?=$page->player->name?>
                         </h4>
-                        <div class='monster_panel'>
-                            <?=HTML::unit_panel($page->rep)?>
-                        </div> <!-- .monster_panel -->
+                        <table>
+                            <tr>
+                                <td class='label'>
+                                    Lv.
+                                </td>
+                                <td class='value'>
+                                    <?=$page->player->level?>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='label'>
+                                    Exp.
+                                </td>
+                                <td class='value'>
+                                    <?=$page->player->experience?>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='label'>
+                                    Country
+                                </td>
+                                <td class='value'>
+                                    <?=$page->player->country?>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='label'>
+                                    Since
+                                </td>
+                                <td class='value'>
+                                    <?=date('Y-m-d', $page->player->joined)?>
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class='label'>
+                                    Days
+                                </td>
+                                <td class='value'>
+                                    <?=round((time() - $page->player->joined) / (60 * 60 * 24))?>
+                                </td>
+                            </tr>
+                        </table>
                     </div>
+                    <div id='placements' class='profile_section'>
+                        <h4>
+                            Placements
+                        </h4>
+                        <div id='placements_rep'>
+                            <h5>
+                                Rep monster:
+                            </h5>
+                            <div class='monster_panel'>
+                                <?=HTML::unit_panel($page->player->rep)?>
+                            </div> <!-- .monster_panel -->
+                        </div>
+                        <div id='placements_arena'>
+                            <h5>
+                                Arena defense:
+                            </h5>
 <?php
-                } // if (isset($page->rep))
+                            $first = true;
+                            foreach ($page->player->defense as $defense){
 ?>
-                <div id='defense' class='profile_section'>
-                    <h4>
-                        Arena defense
-                    </h4>
+                                <div class='monster_panel'>
+                                    <?=HTML::unit_panel($defense)?>
+                                </div>
 <?php
-                    $first = true;
-                    foreach ($page->defense as $defense){
+                                if ($first && isset($defense->unit->leader_skill) && ($defense->unit->leader_skill->area == $EFFECT_AREA["GENERAL"] || $defense->unit->leader_skill->area == $EFFECT_AREA["ARENA"])){
+?>
+                                    <div class='skill'>
+                                        <img class='skill_img' title='<?=$defense->unit->leader_skill->create_description()?>' src='<?=$defense->unit->leader_skill->get_image()?>'/>
+                                    </div>
+<?php
+                                }
+                                $first = false;
+                            }
 ?>
-                        <div class='monster_panel'>
-                            <?=HTML::unit_panel($defense)?>
                         </div>
+                        <div id='placements_gw'>
+                            <h5>
+                                Guild War defense:
+                            </h5>
 <?php
-                        if ($first && isset($defense->unit->leader_skill) && ($defense->unit->leader_skill->area == $EFFECT_AREA["GENERAL"] || $defense->unit->leader_skill->area == $EFFECT_AREA["ARENA"])){
+                            $first = true;
+                            foreach ($page->player->gw_defense[0] as $defense){
 ?>
-                            <div class='skill'>
-                                <img class='skill_img' title='<?=$defense->unit->leader_skill->create_description()?>' src='<?=$defense->unit->leader_skill->get_image()?>'/>
-                            </div>
+                                <div class='monster_panel'>
+                                    <?=HTML::unit_panel($defense)?>
+                                </div>
 <?php
-                        }
-                        $first = false;
-                    }
+                                if ($first && isset($defense->unit->leader_skill) && ($defense->unit->leader_skill->area == $EFFECT_AREA["GENERAL"] || $defense->unit->leader_skill->area == $EFFECT_AREA["ARENA"])){
+?>
+                                    <div class='skill'>
+                                        <img class='skill_img' title='<?=$defense->unit->leader_skill->create_description()?>' src='<?=$defense->unit->leader_skill->get_image()?>'/>
+                                    </div>
+<?php
+                                }
+                                $first = false;
+                            }
+?>
+                            <hr/>
+                        <?php
+                            $first = true;
+                            foreach ($page->player->gw_defense[1] as $defense){
 ?>
-                </div>
-                <div id='building' class='profile_section'>
-                    <h4>
-                        Buildings
-                    </h4>
+                                <div class='monster_panel'>
+                                    <?=HTML::unit_panel($defense)?>
+                                </div>
 <?php
-                    $half = sizeof($page->building) / 2;
-                    $i = 0;
-                    foreach ($page->building as $building){
-                        if ($i == $half){
+                                if ($first && isset($defense->unit->leader_skill) && ($defense->unit->leader_skill->area == $EFFECT_AREA["GENERAL"] || $defense->unit->leader_skill->area == $EFFECT_AREA["ARENA"])){
 ?>
-                            <br class='desktop'/>
+                                    <div class='skill'>
+                                        <img class='skill_img' title='<?=$defense->unit->leader_skill->create_description()?>' src='<?=$defense->unit->leader_skill->get_image()?>'/>
+                                    </div>
 <?php
-                        }
+                                }
+                                $first = false;
+                            }
 ?>
-                        <?=HTML::building_panel($building)?>
+                        </div>
+                    </div>
+                    <div id='building' class='profile_section'>
+                        <h4>
+                            Buildings
+                        </h4>
 <?php
-                        $i ++;
-                    }$i ++;
+                        // Buildings
+                        $half = sizeof($page->player->building) / 2;
+                        $i = 0;
+                        foreach ($page->player->building as $building){
+                            if ($i == $half){
 ?>
-                </div>
-                <div id='decoration' class='profile_section'>
-                    <h4>
-                        Decorations
-                    </h4>
+                                <br class='desktop'/>
 <?php
-                    $half = sizeof($page->decoration) / 2;
-                    $i = 0;
-                    foreach ($page->decoration as $decoration){
-                        if ($i == $half){
+                            }
 ?>
-                            <br class='desktop'/>
+                            <?=HTML::building_panel($building)?>
 <?php
+                            $i ++;
                         }
 ?>
-                        <?=HTML::building_panel($decoration)?>
+                        <br/>
 <?php
-                        $i ++;
-                    }
+                        // Decorations
+                        $half = sizeof($page->player->decoration) / 2;
+                        $i = 0;
+                        foreach ($page->player->decoration as $decoration){
+                            if ($i == $half){
 ?>
-                </div>
-                <div class='inventory profile_section' id='inventory_scroll'>
-                    <h4>
-                        Scrolls
-                    </h4>
+                                <br class='desktop'/>
 <?php
-                    $half = sizeof($page->building) / 2;
-                    $i = 0;
-                    foreach ($page->inventory_scroll as $item){
-                        if ($half > 6 && $i == $half){
+                            }
 ?>
-                            <br class='desktop'/>
+                            <?=HTML::building_panel($decoration)?>
 <?php
+                            $i ++;
                         }
 ?>
-                        <?=HTML::item_panel($item)?>
+                    </div>
+                    <div class='inventory profile_section' id='inventory'>
+                        <h4>
+                            Inventory
+                        </h4>
+                        <ul>
+                            <li>
+                                <img title='Energy' src='<?=URL::IMG["CURRENCY"]?>energy.png'/>
+                                <?=$page->player->currency["energy"]?> / <?=$page->player->currency["energy_max"]?>
+                            </li>
+                            <li>
+                                <img title='Arena Invitations' src='<?=URL::IMG["CURRENCY"]?>arenaenergy.png'/>
+                                <?=$page->player->currency["arena_energy"]?> / <?=$page->player->currency["arena_energy_max"]?>
+                            </li>
+                            <li>
+                                <img title='Dimensional Energy' src='<?=URL::IMG["CURRENCY"]?>dimensionenergy.png'/>
+                                <?=$page->player->currency["dimension_energy"]?> / <?=$page->player->currency["dimension_energy_max"]?>
+                            </li>
+                            <li>
+                                <img title='Dimensional Crystal' src='<?=URL::IMG["CURRENCY"]?>darkportalenergy.png'/>
+                                <?=$page->player->currency["darkportal_energy"]?> / <?=$page->player->currency["darkportal_energy_max"]?>
+                            </li>
+                            <li>
+                                <img title='Mana' src='<?=URL::IMG["CURRENCY"]?>mana.png'/>
+                                <?=$page->player->currency["mana"]?>
+                            </li>
+                            <li>
+                                <img title='Crystal' src='<?=URL::IMG["CURRENCY"]?>crystal.png'/>
+                                <?=$page->player->currency["crystal"]?>
+                            </li>
+                            <li>
+                                <img title='Social Points' src='<?=URL::IMG["CURRENCY"]?>socialpoint.png'/>
+                                <?=$page->player->currency["social_point"]?>
+                            </li>
+                            <li>
+                                <img title='Honor Points' src='<?=URL::IMG["CURRENCY"]?>honor.png'/>
+                                <?=$page->player->currency["honor_point"]?>
+                            </li>
+                            <li>
+                                <img title='Guild Points' src='<?=URL::IMG["CURRENCY"]?>guildpoint.png'/>
+                                <?=$page->player->currency["guild_point"]?>
+                            </li>
+                            <li>
+                                <img title='Honor Medals' src='<?=URL::IMG["CURRENCY"]?>badge.png'/>
+                                <?=$page->player->currency["honor_medal"]?>
+                            </li>
+                            <li>
+                                <img src='<?=URL::IMG["CURRENCY"]?>mark.png'/>
+                                <?=$page->player->currency["honor_mark"]?>
+                            </li>
+                            <li>
+                                <img title='Ancient Coins' src='<?=URL::IMG["CURRENCY"]?>ancientcoin.png'/>
+                                <?=$page->player->currency["event_coin"]?>
+                            </li>
+                            <li>
+                                <img title='Ancient Crystal' src='<?=URL::IMG["CURRENCY"]?>ancientstone.png'/>
+                                <?=$page->player->currency["ancient_stone"]?>
+                            </li>
+                            <li>
+                                <img title='Shapeshifting Stones' src='<?=URL::IMG["CURRENCY"]?>costumestone.png'/>
+                                <?=$page->player->currency["costume_point"]?>
+                            </li>
+                        </ul>
+<?php
+                        // Scrolls
+                        $half = sizeof($page->player->building) / 2;
+                        $i = 0;
+                        foreach ($page->player->inventory_scroll as $item){
+                            if ($half > 6 && $i == $half){
+?>
+                                <br class='desktop'/>
+<?php
+                            }
+?>
+                            <?=HTML::item_panel($item)?>
 <?php
-                        $i ++;
-                    }
+                            $i ++;
+                        }
 ?>
-                </div>
-                <div class='inventory profile_section' id='inventory_craft_rune'>
-                    <h4>
-                        Rune crafting items
-                    </h4>
+                        <br/>
 <?php
-                    $prev = 0;
-                    foreach ($page->inventory_craft_rune as $item){
-                        if ($prev != 0 && $prev + 2000 < $item->id){
+                        // Rune craft materials
+                        $prev = 0;
+                        foreach ($page->player->inventory_craft_rune as $item){
 ?>
-                            <br class='desktop'/>
+                            <?=HTML::item_panel($item)?>
 <?php
+                            $prev = $item->id;
                         }
 ?>
-                        <?=HTML::item_panel($item)?>
+                        <br/>
 <?php
-                        $prev = $item->id;
-                    }
+                        // Other craft materials
+                        $prev = 0;
+                        foreach ($page->player->inventory_craft as $item){
+                            if ($prev != 0 && $prev < 5000 && $item->id > 5000){
 ?>
-                </div>
-                <div class='inventory profile_section' id='inventory_craft'>
-                    <h4>
-                        Other crafting items
-                    </h4>
+                                <br class='desktop'/>
 <?php
-                    $prev = 0;
-                    foreach ($page->inventory_craft as $item){
-                        if ($prev != 0 && $prev < 5000 && $item->id > 5000){
+                            }
 ?>
-                            <br class='desktop'/>
+                            <?=HTML::item_panel($item)?>
 <?php
+                            $prev = $item->id;
                         }
 ?>
-                        <?=HTML::item_panel($item)?>
+                        <br/>
 <?php
-                        $prev = $item->id;
-                    }
+                        // Essences
+                        $prev = "";
+                        $i = 0;
+                        foreach ($page->player->inventory_essence as $item){
+                            //if ($prev != "" && $prev != preg_split('/\s+/', $item->name)[2]){
+                            if ($i > 0 && $i % 6 == 0){
 ?>
-                </div>
-                <div class='inventory profile_section' id='inventory_essence'>
-                    <h4>
-                        Essences
-                    </h4>
+                                <br class='desktop'/>
 <?php
-                    $prev = "";
-                    foreach ($page->inventory_essence as $item){
-                        if ($prev != "" && $prev != preg_split('/\s+/', $item->name)[2]){
+                            }
 ?>
-                            <br class='desktop'/>
+                            <?=HTML::item_panel($item)?>
 <?php
+                            $prev = preg_split('/\s+/', $item->name)[2];
+                            $i ++;
                         }
 ?>
-                        <?=HTML::item_panel($item)?>
-<?php
-                        $prev = preg_split('/\s+/', $item->name)[2];
-                    }
-?>
-                </div>
-                <div id='currency' class='profile_section'>
-                    <h4>
-                        Currency
-                    </h4>
-                    <ul>
-                        <li>
-                            <img title='Energy' src='<?=URL::IMG["CURRENCY"]?>energy.png'/>
-                            <?=$page->currency["energy"]?> / <?=$page->currency["energy_max"]?>
-                        </li>
-                        <li>
-                            <img title='Arena Invitations' src='<?=URL::IMG["CURRENCY"]?>arenaenergy.png'/>
-                            <?=$page->currency["arena_energy"]?> / <?=$page->currency["arena_energy_max"]?>
-                        </li>
-                        <li>
-                            <img title='Dimensional Energy' src='<?=URL::IMG["CURRENCY"]?>dimensionenergy.png'/>
-                            <?=$page->currency["dimension_energy"]?> / <?=$page->currency["dimension_energy_max"]?>
-                        </li>
-                        <li>
-                            <img title='Dimensional Crystal' src='<?=URL::IMG["CURRENCY"]?>darkportalenergy.png'/>
-                            <?=$page->currency["darkportal_energy"]?> / <?=$page->currency["darkportal_energy_max"]?>
-                        </li>
-                        <li>
-                            <img title='Mana' src='<?=URL::IMG["CURRENCY"]?>mana.png'/>
-                            <?=$page->currency["mana"]?>
-                        </li>
-                        <li>
-                            <img title='Crystal' src='<?=URL::IMG["CURRENCY"]?>crystal.png'/>
-                            <?=$page->currency["crystal"]?>
-                        </li>
-                        <li>
-                            <img title='Social Points' src='<?=URL::IMG["CURRENCY"]?>socialpoint.png'/>
-                            <?=$page->currency["social_point"]?>
-                        </li>
-                        <li>
-                            <img title='Honor Points' src='<?=URL::IMG["CURRENCY"]?>honor.png'/>
-                            <?=$page->currency["honor_point"]?>
-                        </li>
-                        <li>
-                            <img title='Guild Points' src='<?=URL::IMG["CURRENCY"]?>guildpoint.png'/>
-                            <?=$page->currency["guild_point"]?>
-                        </li>
-                        <li>
-                            <img title='Honor Medals' src='<?=URL::IMG["CURRENCY"]?>badge.png'/>
-                            <?=$page->currency["honor_medal"]?>
-                        </li>
-                        <li>
-                            <img src='<?=URL::IMG["CURRENCY"]?>mark.png'/>
-                            <?=$page->currency["honor_mark"]?>
-                        </li>
-                        <li>
-                            <img title='Ancient Coins' src='<?=URL::IMG["CURRENCY"]?>ancientcoin.png'/>
-                            <?=$page->currency["event_coin"]?>
-                        </li>
-                        <li>
-                            <img title='Ancient Crystal' src='<?=URL::IMG["CURRENCY"]?>ancientstone.png'/>
-                            <?=$page->currency["ancient_stone"]?>
-                        </li>
-                        <li>
-                            <img title='Shapeshifting Stones' src='<?=URL::IMG["CURRENCY"]?>costumestone.png'/>
-                            <?=$page->currency["costume_point"]?>
-                        </li>
-                    </ul>
-                </div>
+                    </div>
+                </div> <!-- #panel_left -->
+                <div class='panel' id='panel_right'>
+                    <div class='profile_section' id='records'>
+                        <h4>
+                            Records
+                        </h4>
+                        <div class='record'>
+                            <table id='rank_records'>
+                                <tr>
+                                    <td class='label'>
+                                        Arena
+                                    </td>
+                                    <td class='value rank'>
+                                        <?=HTML::arena_rank_icon($page->player->top_rank_arena)?>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td class='label'>
+                                        World Arena
+                                    </td>
+                                    <td class='value rank'>
+                                        <?=HTML::arena_rank_icon($page->player->top_rank_world_arena)?>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td class='label'>
+                                        Special League
+                                    </td>
+                                    <td class='value rank'>
+                                        <?=HTML::arena_rank_icon($page->player->top_rank_special_league)?>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td class='label'>
+                                        Guild War
+                                    </td>
+                                    <td class='value rank'>
+                                        <?=HTML::arena_rank_icon($page->player->top_rank_gw - 10)?>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td class='label'>
+                                        Siege Battle
+                                    </td>
+                                    <td class='value rank'>
+                                        <?=HTML::arena_rank_icon($page->player->top_rank_siege)?>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td class='label'>
+                                        World Boss
+                                    </td>
+                                    <td class='value wboss'>
+                                        <?=WORLD_BOSS_RANK_ID::RANK[$page->player->top_rank_wboss]?>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td class='label'>
+                                        Trial of Ascension (N)
+                                    </td>
+                                    <td class='value toa'>
+                                        <?=$page->player->top_rank_toan?>F
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td class='label'>
+                                        Trial of Ascension (N)
+                                    </td>
+                                    <td class='value toa'>
+                                        <?=$page->player->top_rank_toah?>F
+                                    </td>
+                                </tr>
+                            </table>
+                            <table id='battle_records'>
+<?php
+                                foreach ($page->player->record as $record){
+?>
+                                    <tr>
+                                        <td class='record_dungeon'>
+                                            <img title='<?=$record->area->name?>' class='area' src='<?=$record->area->get_image()?>'/>
+                                        </td>
+                                        <td class='record_info'>
+                                            <span class='title'>
+<?php
+                                                $title = "";
+                                                switch ($record->area->type){
+                                                    case AREA_TYPE_ID::CAIROS_DUNGEON:
+                                                        $title = $record->area->name . " " . $record->stage . "F";
+                                                        break;
+                                                    case AREA_TYPE_ID::RIFT_DUNGEON:
+                                                        $title = $record->area->name;
+                                                        break;
+                                                    case AREA_TYPE_ID::RIFT_RAID:
+                                                        $title = $record->area->name;
+                                                    
+                                                }
+?>
+                                                <?=$title?>
+                                            </span>
+<?php
+                                            if ($record->area->type == AREA_TYPE_ID::RIFT_DUNGEON){
+?>
+                                                <span class='score'>
+                                                    <?=$record->score?>
+                                                </span>
+                                                <span class='rank'>
+                                                    <?=$record->rank?>
+                                                </span>
+<?php
+                                            }
+                                            else{
+                                                $s = floor($record->time / 1000);
+                                                $m = floor($s / 60);
+                                                $s = floor($s % 60);
+                                                $ms = ($record-> time - (1000 * 60 * $m) - (1000 * 60 * $s) / 100);
+                                                $s = str_pad($s, 2, '0', STR_PAD_LEFT);
+                                                $ms = str_pad($ms, 2, '0', STR_PAD_LEFT);
+?>
+                                                <span class='time'>
+                                                    <?=$m?>:<?=$s?><span class='ms'>.<?=$ms?></span>
+                                                </span>
+<?php
+                                            }
+?>
+                                        </td>
+<?php
+                                        $class_frontline = "";
+                                        if ($record->area->type == AREA_TYPE_ID::RIFT_DUNGEON || $record->area->type == AREA_TYPE_ID::RIFT_RAID){
+                                            $class_frontline = "frontlines";
+                                        }
+?>
+                                        <td class='record_party <?=$class_frontline?>'>
+<?php
+                                            $prev_front = false;
+                                            $front = "undefined";
+                                            foreach ($record->party as $party){
+                                                $front = in_array($party->id, $record->frontline);
+                                                if ($front != "undefined" && $prev_front != $front){
+?>
+                                                    <hr class='frontline'/>
+<?php
+                                                }
+                                                if ($party instanceof K_Unit){
+                                                    $enable_save = false;
+                                                    $disabled = "disabled";
+                                                }
+                                                else{
+                                                    $disabled = "";
+                                                }
+                                                if ($disabled == ""){
+?>
+                                                    <a target='_blank' href='/<?=$UID?>>/monster/<?=$party->id?>'>
+<?php
+                                                }
+?>
+                                                <div class='monster_panel <?=$disabled?>'>
+                                                    <?=HTML::unit_panel($party)?>
+<?php
+                                                        if ($party->id == $record->leader){
+?>
+                                                            <img alt='Leader' class='leader' src='<?=URL::IMG["ICON"]?>leader.png'/>
+<?php
+                                                        }
+?>
+                                                </div>
+<?php
+                                                if ($disabled == ""){
+?>
+                                                    </a>
+<?php
+                                                }
+                                                $prev_front = $front;
+                                            }
+?>
+                                        </td>
+                                    </tr>
+                                
+<?php
+                                }
+?>
+                            </table>
+                        </div>
+                    </div>
+                </div> <!-- #panel_right -->
             </article>
         </section>
 <?php

+ 1 - 1
application/view/runs.php

@@ -219,7 +219,7 @@
 ?>
                                 <?=date_format($date, "Y/m/d H:i:s")?>
                             </td>
-                            <td class='team'>
+                            <td class='team <?=$class_frontline?>'>
 <?php
                                 if ($run->helper == 1){
                                     $enable_save = false;

+ 12 - 10
install_data/install_base.sql

@@ -126,16 +126,18 @@ INSERT INTO k_area VALUES(6001,2,'Necropolis');
 INSERT INTO k_area VALUES(7001,2,'Hall of Light');
 INSERT INTO k_area VALUES(8001,2,'Giant''s Keep');
 INSERT INTO k_area VALUES(9001,2,'Dragon''s Lair');
-INSERT INTO k_area VALUES(1001,3,'Rift Dungeon - Ice Beast');
-INSERT INTO k_area VALUES(2001,3,'Rift Dungeon - Fire Beast');
-INSERT INTO k_area VALUES(3001,3,'Rift Dungeon - Wind Beast');
-INSERT INTO k_area VALUES(4001,3,'Rift Dungeon - Light Beast');
-INSERT INTO k_area VALUES(5001,3,'Rift Dungeon - Dark Beast');
-INSERT INTO k_area VALUES(1,4,'Rift of Worlds - level 1');
-INSERT INTO k_area VALUES(2,4,'Rift of Worlds - level 2');
-INSERT INTO k_area VALUES(3,4,'Rift of Worlds - level 3');
-INSERT INTO k_area VALUES(4,4,'Rift of Worlds - level 4');
-INSERT INTO k_area VALUES(5,4,'Rift of Worlds - level 5');
+INSERT INTO k_area VALUES(9501,2,'Steel Fortress');
+INSERT INTO k_area VALUES(9502,2,'Punisher''s Crypt');
+INSERT INTO k_area VALUES(1001,3,'Ice Beast');
+INSERT INTO k_area VALUES(2001,3,'Fire Beast');
+INSERT INTO k_area VALUES(3001,3,'Wind Beast');
+INSERT INTO k_area VALUES(4001,3,'Light Beast');
+INSERT INTO k_area VALUES(5001,3,'Dark Beast');
+INSERT INTO k_area VALUES(1,4,'Rift Raid - Level 1');
+INSERT INTO k_area VALUES(2,4,'Rift Raid - Level 2');
+INSERT INTO k_area VALUES(3,4,'Rift Raid - Level 3');
+INSERT INTO k_area VALUES(4,4,'Rift Raid - Level 4');
+INSERT INTO k_area VALUES(5,4,'Rift Raid - Level 5');
 INSERT INTO k_area VALUES(9,9,'Tartarus Labyrinth');
 CREATE TABLE k_decoration(
     id INT NOT NULL PRIMARY KEY,

+ 34 - 0
install_data/install_data.sql

@@ -30,8 +30,36 @@ CREATE TABLE player(
     event_coin INT NOT NULL CHECK (event_coin >= 0),
     storage_slots INT NOT NULL CHECK (storage_slots >= 0),
     island INT NOT NULL CHECK (island >= 0),
+    joined TIMESTAMP,
+    top_rank_arena INT DEFAULT 0,
+    top_rank_world_arena INT DEFAULT 0,
+    top_rank_special_league INT DEFAULT 0,
+    top_rank_gw INT DEFAULT 0,
+    top_rank_siege INT DEFAULT 0,
+    top_rank_wboss INT DEFAULT 0,
+    top_rank_toan INT DEFAULT 0,
+    top_rank_toah INT DEFAULT 0,
     public INT NOT NULL DEFAULT 0 CHECK(public IN (0, 1))
 );
+CREATE TABLE record(
+    uid INT NOT NULL REFERENCES player(id),
+    area_type INT NOT NULL REFERENCES k_area_type,
+    area INT NOT NULL REFERENCES k_area,
+    stage INT CHECK(stage >= 0),
+    time INT,
+    score INT,
+    rank TEXT,
+    PRIMARY KEY (uid, area_type, area)
+);
+CREATE TABLE record_party(
+    uid INT NOT NULL REFERENCES player(id),
+    area_type INT NOT NULL REFERENCES k_area_type,
+    area INT NOT NULL REFERENCES k_area,
+    unit INT NOT NULL REFERENCES unit(id),
+    k_unit INT NOT NULL REFERENCES k_unit(id),
+    leader INT NOT NULL DEFAULT 0,
+    front INT NOT NULL DEFAULT 0
+);
 CREATE TABLE scenario(
     uid INT NOT NULL REFERENCES player(id),
     region INT NOT NULL REFERENCES k_area(id),
@@ -46,6 +74,12 @@ CREATE TABLE defense(
     position INT NOT NULL CHECK(position BETWEEN 1 AND 4),
     PRIMARY KEY (uid, unit)
 );
+CREATE TABLE gw_defense(
+    uid INT NOT NULL REFERENCES player(id),
+    unit INT NOT NULL REFERENCES unit(id),
+    position INT NOT NULL CHECK(position BETWEEN 1 AND 6),
+    PRIMARY KEY (uid, unit)
+);
 CREATE TABLE unit(
     uid INT NOT NULL REFERENCES player(id),
     id INT PRIMARY KEY NOT NULL,

+ 149 - 39
public/css/home.css

@@ -2,28 +2,21 @@ article#profile{
     text-align: center;
 }
 
-article#profile h3 span#user_name{
-    font-size: 160%;
-    font-weight: bold;
-    display: block;
-}
-
-article#profile h3 span#user_level{
-    font-size: 100%;
-}
-
-article#profile h3 span#user_level span#user_exp{
-    font-style: italic;
-    font-weight: normal;
+div.panel{
+    width: 49%;
+    margin: 0;
+    padding: 0;
+    display: inline-block;
+    vertical-align: top;
 }
 
 article#profile div.profile_section{
     border: 0.2em solid var(--ui-color-border);
-    max-width: 45%;
+/*     max-width: 45%; */
     margin: 0.5em;
     padding: 0 0.5em 0.5em 0.5em;
     border-radius: 0.5em;
-    display: inline-block;
+    display: block;
     vertical-align: top;
     text-align: center;
     background-color: #00000033;
@@ -46,31 +39,47 @@ article#profile div.profile_section h4{
     background-color: #00000033;
 }
 
-article#profile div#rep div.monster_panel{
-    font-size: 50%;
-    margin: 0.2em;
+article#profile div#player table{
+    border-collapse: collapse;
+    margin: 0 auto;
 }
-@media screen and (max-width : 990px){
-    article#profile div#rep div.monster_panel{font-size: 70%;}
+
+article#profile div#player table td{
+    border-top: 0.1em solid #00000077;
+    border-bottom: 0.1em solid #00000077;
 }
 
-article#profile div#defense{
-    position: relative;
+article#profile div#player table td.label{
+    text-align: left;
+    padding-right: 1.5em;
+}
+article#profile div#player table td.value{
+    text-align: right;
+}
+
+article#profile div#placements h5{
+    font-weight: bold;
+    margin-top: 0.5em;
+    margin-bottom: 0.3em;
 }
 
-article#profile div#defense div.monster_panel{
-    font-size: 50%;
+article#profile div#placements div#placements_rep div.monster_panel{
+    font-size: 45%;
     margin: 0.2em;
 }
 
-article#profile div#defense div.skill{
-    position: absolute;
-    left: 0.2em;
-    top: 4em;
+article#profile div#placements div#placements_arena div.monster_panel{
+    font-size: 35%;
+    margin: 0.15em;
 }
-article#profile div#defense div.skill img{
-    width: 1.5em;
-    height: 1.5em;
+
+article#profile div#placements div#placements_gw div.monster_panel{
+    font-size: 40%;
+    margin: 0.2em;
+}
+article#profile div#placements div#placements_gw hr{
+    width: 12em;
+    margin: 0.1em auto;
 }
 
 article#profile div#building div.building_panel{
@@ -91,7 +100,7 @@ article#profile div#building div.building_panel img.building, img.decoration{
     border-radius: 15%;
 }
 
-article#profile div#decoration div.building_panel{
+article#profile div#building div.building_panel{
     display: inline-block;
     width: 2em;
     height: 2em;
@@ -101,7 +110,7 @@ article#profile div#decoration div.building_panel{
     vertical-align: middle;
 }
 
-article#profile div#decoration div.building_panel img.building, img.decoration{
+article#profile div#building div.building_panel img.building, img.decoration{
     width: 2em;
     height: 2em;
     border-style: solid;
@@ -109,7 +118,7 @@ article#profile div#decoration div.building_panel img.building, img.decoration{
     border-radius: 15%;
 }
 
-article#profile div#decoration div.building_panel span.level{
+article#profile div#building div.building_panel span.level{
     position: relative;
     bottom: 1.6em;
     font-weight: bold;
@@ -155,17 +164,118 @@ article#profile div.inventory div.item_panel span.amount{
     pointer-events: none;
 }
 
-article#profile div#currency{
-    text-align: left;
-}
 
-article#profile div#currency ul{
+article#profile div#inventory ul{
     column-count: 2;
+    text-align: left;
+    margin: 0.5em auto;
 }
 
 
-article#profile div#currency ul li img{
+article#profile div#inventory ul li img{
     height: 1.2em;
     width: 1.2em;
     vertical-align: middle;
 }
+
+article#profile div#records div.record table#rank_records{
+    border-collapse: collapse;
+    margin: 0 auto;
+}
+
+article#profile div#records div.record table#rank_records td{
+    border-top: 0.1em solid #00000077;
+    border-bottom: 0.1em solid #00000077;
+}
+
+article#profile div#records div.record table#rank_records td.label{
+    text-align: left;
+    padding-right: 1.5em;
+}
+article#profile div#records div.record table#rank_records td.value{
+    text-align: center;
+}
+article#profile div#records div.record table#rank_records td.value.rank img{
+    width: 1.5em;
+    height: 1.5em;
+}
+article#profile div#records div.record table#rank_records td.value.wboss{
+    font-size: 110%;
+    color: #ff6633;
+    text-shadow: 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.2em #ff0, 0 0 0.2em #ff0, 0 0 0.2em #ff0, 0 0 0.2em #ff0;
+    font-style: italic;
+}
+
+article#profile div#records div.record table#rank_records td.value.toa{
+    font-size: 110%;
+    font-weight: bold;
+}
+
+article#profile div#records div.record table#battle_records{
+    border-collapse: collapse;
+    margin: 0 auto;
+}
+
+article#profile div#records div.record table#battle_records td{
+    border-top: 0.1em solid #00000077;
+    border-bottom: 0.1em solid #00000077;
+}
+article#profile div#records div.record table#battle_records td.record_dungeon img{
+    width: 2em;
+    height: 2em;
+    border: 0.2em solid #555555;
+    border-radius: 0.5em;
+    background-color: #777777;
+}
+
+article#profile div#records div.record table#battle_records td.record_party{
+    font-size: 30%;
+    width: 45em;
+}
+
+article#profile div#records div.record table#battle_records td.record_party.frontlines{
+    font-size: 25%;
+}
+
+article#profile div#records div.record table#battle_records td.record_party hr{
+    width: 33em;
+}
+
+article#profile div#records div.record table#battle_records td.record_info{
+    text-align: left;
+}
+
+article#profile div#records div.record table#battle_records td.record_info span.title{
+    font-weight: bold;
+    font-size: 75%;
+}
+
+article#profile div#records div.record table#battle_records td.record_info span.title{
+    font-weight: bold;
+    font-size: 110%;
+    display: block;
+    margin: 0.1em;
+}
+
+article#profile div#records div.record table#battle_records td.record_info span.time{
+    font-size: 90%;
+    font-style: italic;
+}
+article#profile div#records div.record table#battle_records td.record_info span.time span.ms{
+    font-size: 70%;
+}
+
+article#profile div#records div.record table#battle_records td.record_info span.rank{
+    display: inline-block;
+    vertical-align: bottom;
+    font-size: 100%;
+    color: #ff6633;
+    text-shadow: 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.1em #000, 0 0 0.2em #ff0, 0 0 0.2em #ff0, 0 0 0.2em #ff0, 0 0 0.2em #ff0;
+    font-style: italic;
+}
+article#profile div#records div.record table#battle_records td.record_info span.score{
+    font-size: 90%;
+    font-style: italic;
+}
+
+

+ 0 - 0
public/img/icon/rank_beg.png → public/img/rank/0901.png


+ 0 - 0
public/img/icon/rank_cha1.png → public/img/rank/1001.png


+ 0 - 0
public/img/icon/rank_cha2.png → public/img/rank/1002.png


+ 0 - 0
public/img/icon/rank_cha3.png → public/img/rank/1003.png


+ 0 - 0
public/img/icon/rank_fig1.png → public/img/rank/2001.png


+ 0 - 0
public/img/icon/rank_fig2.png → public/img/rank/2002.png


+ 0 - 0
public/img/icon/rank_fig3.png → public/img/rank/2003.png


+ 0 - 0
public/img/icon/rank_con1.png → public/img/rank/3001.png


+ 0 - 0
public/img/icon/rank_con2.png → public/img/rank/3002.png


+ 0 - 0
public/img/icon/rank_con3.png → public/img/rank/3003.png


+ 0 - 0
public/img/icon/rank_gua1.png → public/img/rank/4001.png


+ 0 - 0
public/img/icon/rank_gua2.png → public/img/rank/4002.png


+ 0 - 0
public/img/icon/rank_gua3.png → public/img/rank/4003.png


+ 0 - 0
public/img/icon/rank_leg.png → public/img/rank/5001.png


+ 6 - 1
swex-plugin/swdb.js

@@ -100,7 +100,12 @@ module.exports = {
                 apiCommand = "upload_profile";
                 success = "Profile uploaded sucesfully!"
                 break;
-
+                
+            // Profile logbook
+            case 'GetLobbyWizardLog':
+                apiCommand = "update_logbook";
+                success = "Logbook updated succesfully!";
+                break;
             // Battle runs
             case 'BattleDungeonResult':
                 apiCommand = "upload_run_dungeon";