瀏覽代碼

All entities use encapsulation now, and they are properly formatted and documented. This commit finally breaks the runs sections of the site, it will be fixed later.

Iñigo Valentin 5 年之前
父節點
當前提交
8e945466fc
共有 73 個文件被更改,包括 12162 次插入11338 次删除
  1. 1 1
      application/API/v1/profile/DELETE.php
  2. 1 1
      application/API/v1/profile/POST.php
  3. 4697 4702
      application/Constant.php
  4. 99 80
      application/Context.php
  5. 359 354
      application/Controller.php
  6. 36 37
      application/action/change_game_mode.php
  7. 31 31
      application/action/delete_team.php
  8. 76 75
      application/action/edit_profile.php
  9. 88 84
      application/action/login.php
  10. 24 27
      application/action/logout.php
  11. 221 221
      application/action/new_team.php
  12. 163 159
      application/action/optimize_get_options.php
  13. 328 328
      application/action/optimize_get_rune_list.php
  14. 39 38
      application/action/rate_team.php
  15. 102 98
      application/action/save_run_team.php
  16. 157 153
      application/config.php
  17. 347 338
      application/entity/Area.php
  18. 495 410
      application/entity/Artifact.php
  19. 132 112
      application/entity/Artifact_Effect.php
  20. 86 77
      application/entity/Artifact_Stat.php
  21. 86 75
      application/entity/Buildable.php
  22. 78 68
      application/entity/Building.php
  23. 79 68
      application/entity/Decoration.php
  24. 196 198
      application/entity/Decorative.php
  25. 107 94
      application/entity/Effect.php
  26. 360 320
      application/entity/Enchantment.php
  27. 17 27
      application/entity/Entity.php
  28. 55 52
      application/entity/Guild.php
  29. 72 31
      application/entity/Guild_Member.php
  30. 92 79
      application/entity/Guild_Skill.php
  31. 127 106
      application/entity/Guild_Skill_Group.php
  32. 16 18
      application/entity/Inventory.php
  33. 21 23
      application/entity/Item.php
  34. 29 31
      application/entity/Leader_Skill.php
  35. 761 612
      application/entity/Monster.php
  36. 32 29
      application/entity/Monster_Transformation.php
  37. 798 631
      application/entity/Player.php
  38. 45 40
      application/entity/Record.php
  39. 494 496
      application/entity/Run.php
  40. 113 96
      application/entity/Rune.php
  41. 17 19
      application/entity/Rune_Set.php
  42. 73 78
      application/entity/Rune_Stat.php
  43. 61 63
      application/entity/Server.php
  44. 63 47
      application/entity/Skill.php
  45. 79 81
      application/entity/Skill_Level.php
  46. 25 28
      application/entity/Source.php
  47. 48 40
      application/entity/Team.php
  48. 636 459
      application/entity/Unit.php
  49. 42 35
      application/entity/User.php
  50. 2 2
      application/helper/APPLICATION_Helper.php
  51. 1 1
      application/helper/HTML_Helper.php
  52. 2 2
      application/page/Artifacts_Page.php
  53. 4 5
      application/page/Enchantments_Page.php
  54. 1 1
      application/page/Error_Page.php
  55. 1 1
      application/page/Guild_Page.php
  56. 0 1
      application/page/Home_Page.php
  57. 1 2
      application/page/Monster_Page.php
  58. 1 2
      application/page/Monsters_Page.php
  59. 3 3
      application/page/Optimizer_Page.php
  60. 0 1
      application/page/Profile_Page.php
  61. 1 1
      application/page/Report_Page.php
  62. 1 1
      application/page/Report_Skillup_Page.php
  63. 2 2
      application/page/Runes_Page.php
  64. 1 1
      application/page/Runs_Page.php
  65. 2 3
      application/page/Teams_Page.php
  66. 0 1
      application/page/Unit_Page.php
  67. 1 1
      application/page/Units_Page.php
  68. 2 2
      application/view/home.php
  69. 2 2
      application/view/monster.php
  70. 15 16
      application/view/optimizer_unit.php
  71. 0 1
      application/view/stats.php
  72. 13 14
      application/view/teams.php
  73. 2 2
      application/view/unit.php

+ 1 - 1
application/API/v1/profile/DELETE.php

@@ -42,7 +42,7 @@
             syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
             return 400;
         }
-        
+
         $db = get_context()->get_db();
 
         // Authenticate

+ 1 - 1
application/API/v1/profile/POST.php

@@ -76,7 +76,7 @@
             syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Existing user.");
             return 400;
         }
-        
+
         // Get and validate API key
         $api_key = $_POST["key"];
         if ($api_key == null || $api_key == false){

+ 4697 - 4702
application/Constant.php

@@ -1,4718 +1,4713 @@
 <?php
+/**
+ * Constants file.
+ *
+ * Provides some fixed values to be used accross the app.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+ /**
+  * Stage difficulty constants.
+  *
+  * @category Data
+  */
+final class DIFFICULTY_ID{
+
+    /**
+     * Difficulty EASY (Tartarus Labyrinth only).
+     */
+    const EASY = 0;
+
+    /**
+     * Difficulty EASY (Scenario, TOA, Labyrinth).
+     */
+    const NORMAL = 1;
+
+    /**
+     * Difficulty EASY (Scenario, TOA, Labyrinth).
+     */
+    const HARD = 2;
+
+    /**
+     * Difficulty EASY (Scenario, Labyrinth).
+     */
+    const HELL = 3;
+};
+
+/**
+ * Unit source constants.
+ *
+ * @category Data
+ */
+final class SOURCE_ID{
+
+    /**
+     * Unknown Scroll (elemental 1-3*).
+     */
+    const SCROLL_UNKNOWN = 1;
+
+    /**
+     * Mystical Scroll (elemental 3-5*).
+     */
+    const SCROLL_MYSTICAL = 2;
+
+    /**
+     * Light and Darkness Scroll (LD 3-5*).
+     */
+    const SCROLL_LIGHT_AND_DARK = 3;
+
+    /**
+     * Water scroll (water 3-5*)
+     */
+    const SCROLL_WATER = 4;
+
+    /**
+     * Fire scroll (fire 3-5*)
+     */
+    const SCROLL_FIRE = 5;
+
+    /**
+     * Wind scroll (wind 3-5*)
+     */
+    const SCROLL_WIND = 6;
+
+    /**
+     * Legendary Scroll (elemental 4-5*)
+     */
+    const SCROLL_LEGENDARY = 7;
+
+    /**
+     * Summon Stones (elemental 3-5*)
+     */
+    const SUMMON_EXCLUSIVE = 8;
+
+    /**
+     * Legendary Summoning Pieces (4-5*)
+     */
+    const SUMMON_LEGENDARY_PIECES = 9;
+
+    /**
+     * Light and Darkness Scroll (LD 3-5*).
+     */
+    const SUMMON_LIGHT_AND_DARK_PIECES = 10;
+
+    /**
+     * Transcendance Scroll (elemental 5*)
+     */
+    const SCROLL_TRANSCENDANCE = 11;
+
+    /**
+     * Legendary Water Scroll (water 4-5*)
+     */
+    const SCROLL_LEGENDARY_WATER = 12;
+
+    /**
+     * Legendary Fire Scroll (fire 4-5*)
+     */
+    const SCROLL_LEGENDARY_FIRE = 13;
+
+    /**
+     * Legendary Wind Scroll (wind 4-5*)
+     */
+    const SCROLL_LEGENDARY_WIND = 14;
+};
+
+/**
+ * Element constants.
+ *
+ * @category Data
+ */
+final class ELEMENT_ID{
+
+    /**
+     * Water
+     */
+    const WATER = 1;
+
+    /**
+     * Fire
+     */
+    const FIRE = 2;
+
+    /**
+     * Wind
+     */
+    const WIND = 3;
+
+    /**
+     * Light
+     */
+    const LIGHT = 4;
+
+    /**
+     * Dark
+     */
+    const DARK = 5;
+
+    /**
+     * Pure
+     */
+    const PURE = 6;
+};
+
+/**
+ * Unit archetype constants.
+ *
+ * @category Data
+ */
+final class ARCHETYPE_ID{
+
+    /**
+     * None
+     */
+    const NONE = 0;
+
+    /**
+     * Attack
+     */
+    const ATTACK = 1;
+
+    /**
+     * Defense
+     */
+    const DEFENSE = 2;
+
+    /**
+     * HP
+     */
+    const HP = 3;
+
+    /**
+     * Support
+     */
+    const SUPPORT = 4;
+
+    /**
+     * Material
+     */
+    const MATERIAL = 5;
+};
+
+/**
+ * Stat constants.
+ *
+ * Used for unit stats, for rune stat types, see {@see RUNE_STAT_ID}
+ *
+ * @category Data
+ */
+final class STAT_ID{
+
+    /**
+     * HP
+     */
+    const HP = 1;
+
+    /**
+     * ATK
+     */
+    const ATK = 2;
+
+    /**
+     * DEF
+     */
+    const DEF = 3;
+
+    /**
+     * SPD
+     */
+    const SPD = 4;
+
+    /**
+     * CRIT_RATE
+     */
+    const CRIT_RATE = 5;
+
+    /**
+     * CRIT_DMG
+     */
+    const CRIT_DMG = 6;
+
+    /**
+     * RESIST
+     */
+    const RESIST = 7;
+
+    /**
+     * ACCURACY
+     */
+    const ACCURACY = 8;
+};
+
+/**
+ * Leadr skill area constants.
+ *
+ * @category Data
+ */
+final class EFFECT_AREA_ID{
+
+    /**
+     * General (all areas).
+     */
+    const GENERAL = 1;
+
+    /**
+     * Arena (offense and defense).
+     */
+    const ARENA = 3;
+
+    /**
+     * Dungeon (Cairos, elemental Rifts, Dimensinal Hole).
+     */
+    const DUNGEON = 2;
+
+    /**
+     * Guild content (battle, siege, Labyrinth).
+     */
+    const GUILD = 5;
+};
+
+/**
+ * Playable area group constants.
+ *
+ * @category Data
+ */
+final class AREA_TYPE_ID{
+
+    /**
+     * Scenario.
+     */
+    const SCENARIO = 1;
+
+    /**
+     * Cairos Dungeon.
+     */
+    const CAIROS_DUNGEON = 2;
+
+    /**
+     * Elemental Rift Dungeons.
+     */
+    const RIFT_DUNGEON = 3;
+
+    /**
+     * Rift Raid.
+     */
+    const RIFT_RAID = 4;
+
+    /**
+     * Dimensional Hole.
+     */
+    const DIMENSIONAL_HOLE = 5;
+
+    /**
+     * Arena.
+     */
+    const ARENA = 6;
+
+    /**
+     * Guild War.
+     */
+    const GUILD_WAR = 7;
+
+    /**
+     * Guild Siege.
+     */
+    const GUILD_SIEGE = 8;
+
+    /**
+     * Tartarus Labyrinth.
+     */
+    const TARTARUS_LABYRINTH = 9;
+
+    /**
+     * Trial of Ascension.
+     */
+    const TRIAL_OF_ASCENSION = 10;
+
+    /**
+     * World Boss.
+     */
+    const WORLD_BOSS = 11;
+
+    /**
+     * Dimensional Rift.
+     */
+    const DIMENSIONAL_RIFT = 12;
+};
+
+/**
+ * Scenario area constants.
+ *
+ * @category Data
+ */
+final class SCENARIO_ID{
+
+    /**
+     * Garen Forest.
+     */
+    const GAREN_FOREST = 1;
+
+    /**
+     * Mt. Siz.
+     */
+    const MT_SIZ = 2;
+
+    /**
+     * Kabir Ruins.
+     */
+    const KABIR_RUINS = 3;
+
+    /**
+     * Mt. White Ragon.
+     */
+    const MT_WHITE_RAGON = 4;
+
+    /**
+     * Telain Forest.
+     */
+    const TELAIN_FOREST = 5;
+
+    /**
+     * Hydeni Ruins.
+     */
+    const HYDENI_RUINS = 6;
+
+    /**
+     * Tamor Desert.
+     */
+    const TAMOR_DESERT = 7;
+
+    /**
+     * Vrofagus Ruins.
+     */
+    const VROFAGUS_RUINS = 8;
+
+    /**
+     * Faimon Volcano.
+     */
+    const FAIMON_VOLCANO = 9;
+
+    /**
+     * Aiden Forest.
+     */
+    const AIDEN_FOREST = 10;
+
+    /**
+     * Ferun Castle.
+     */
+    const FERUN_CASTLE = 11;
+
+    /**
+     * Mt Runar.
+     */
+    const MT_RUNAR = 12;
+
+    /**
+     * Chiruka Remains.
+     */
+    const CHIRUKA_REMAINS = 13;
+};
+
+/**
+ * Dungeon section constants.
+ *
+ * Includes Cairos Dungeons and Dimension Hole Dungeons.
+ *
+ * @category Data
+ */
+final class DUNGEON_ID{
+
+    /**
+     * Hall of Dark.
+     */
+    const HALL_OF_DARK = 1001;
+
+    /**
+     * Sanctuary of Dreaming Fairies.
+     */
+    const SANCTUARY_OF_DREAMING_FAIRIES = 1101;
+
+    /**
+     * Ellunia Remains (Fairy).
+     */
+    const ELLUNIA_REMAINS_FAIRY = 1201;
+
+    /**
+     * Ellunia Remains (Pixie).
+     */
+    const ELLUNIA_REMAINS_PIXIE = 1202;
+
+    /**
+     * Hall of Fire.
+     */
+    const HALL_OF_FIRE = 2001;
+
+    /**
+     * Forest of Roaring Beasts.
+     */
+    const FOREST_OF_ROARING_BEASTS = 2101;
+
+    /**
+     * Karzhan Remains (Warbear).
+     */
+    const KARZHAN_REMAINS_WARBEAR = 2201;
+
+    /**
+     * Karzhan Remains (Inugami).
+     */
+    const KARZHAN_REMAINS_INUGAMI = 2202;
+
+    /**
+     * Cliff of Tough Beast Men.
+     */
+    const CLIFF_OF_TOUGH_BEASTS_MEN = 3101;
+
+    /**
+     * Lumel Remains (Werewolf).
+     */
+    const LUMEL_REMAINS_WEREWOLF = 3201;
+
+    /**
+     * Lumel Remains (Martial Cat).
+     */
+    const LUMEL_REMAINS_MARTIAL_CAT = 3202;
+
+    /**
+     * Hall of water.
+     */
+    const HALL_OF_WATER = 3001;
+
+    /**
+     * Hall of Wind.
+     */
+    const HALL_OF_WIND = 4001;
+
+    /**
+     * Hall of Magic.
+     */
+    const HALL_OF_MAGIC = 5001;
+
+    /**
+     * Necropolis.
+     */
+    const NECROPOLIS = 6001;
+
+    /**
+     * Punisher's Crypt.
+     */
+    const PUNISHERS_CRYPT = 9502;
+
+    /**
+     * Steel Fortress
+     */
+    const STEEL_FORTRESS = 9501;
+
+    /**
+     * Hall of Light.
+     */
+    const HALL_OF_LIGHT = 7001;
+
+    /**
+     * Giants Keep.
+     */
+    const GIANTS_KEEP = 8001;
+
+    /**
+     * Dragons Lair.
+     */
+    const DRAGONS_LAIR = 9001;
+};
+
+/**
+ * Cairos Dungeons section constants.
+ *
+ * @category Data
+ */
+final class CAIROS_DUNGEON_ID{
+
+    /**
+     * Hall of Dark.
+     */
+    const HALL_OF_DARK = 1001;
+
+    /**
+     * Hall of Fire.
+     */
+    const HALL_OF_FIRE = 2001;
+
+    /**
+     * Hall of water.
+     */
+    const HALL_OF_WATER = 3001;
+
+    /**
+     * Hall of Wind.
+     */
+    const HALL_OF_WIND = 4001;
+
+    /**
+     * Hall of Magic.
+     */
+    const HALL_OF_MAGIC = 5001;
+
+    /**
+     * Necropolis.
+     */
+    const NECROPOLIS = 6001;
+
+    /**
+     * Punisher's Crypt.
+     */
+    const PUNISHERS_CRYPT = 9502;
+
+    /**
+     * Steel Fortress
+     */
+    const STEEL_FORTRESS = 9602; // TODO: Find out
+
+    /**
+     * Hall of Light.
+     */
+    const HALL_OF_LIGHT = 7001;
+
+    /**
+     * Giants Keep.
+     */
+    const GIANTS_KEEP = 8001;
+
+    /**
+     * Dragons Lair.
+     */
+    const DRAGONS_LAIR = 9001;
+};
+
+/**
+ * Dimensional Dungeons section constants.
+ *
+ * @category Data
+ */
+final class DIMENSION_DUNGEON_ID{
+
+    /**
+     * Sanctuary of Dreaming Fairies.
+     */
+    const SANCTUARY_OF_DREAMING_FAIRIES = 1101;
+
+    /**
+     * Ellunia Remains (Fairy).
+     */
+    const ELLUNIA_REMAINS_FAIRY = 1201;
+
+    /**
+     * Ellunia Remains (Pixie).
+     */
+    const ELLUNIA_REMAINS_PIXIE = 1202;
+
+    /**
+     * Forest of Roaring Beasts.
+     */
+    const FOREST_OF_ROARING_BEASTS = 2101;
+
+    /**
+     * Karzhan Remains (Warbear).
+     */
+    const KARZHAN_REMAINS_WARBEAR = 2201;
+
+    /**
+     * Karzhan Remains (Inugami).
+     */
+    const KARZHAN_REMAINS_INUGAMI = 2202;
+
+    /**
+     * Cliff of Tough Beast Men.
+     */
+    const CLIFF_OF_TOUGH_BEASTS_MEN = 3101;
+
+    /**
+     * Lumel Remains (Werewolf).
+     */
+    const LUMEL_REMAINS_WEREWOLF = 3201;
+
+    /**
+     * Lumel Remains (Martial Cat).
+     */
+    const LUMEL_REMAINS_MARTIAL_CAT = 3202;
+};
+
+/**
+ * Elemental Rift Dungeon constants.
+ *
+ * @category Data
+ */
+final class ELEMENTAL_RIFT_DUNGEON_ID{
+
+    /**
+     * Ice Beast.
+     */
+    const ICE_BEAST = 1001;
+
+    /**
+     * Fire Beast.
+     */
+    const FIRE_BEAST = 2001;
+
+    /**
+     * Wind Beast.
+     */
+    const WIND_BEAST = 3001;
+
+    /**
+     * Light Beast.
+     */
+    const LIGHT_BEAST = 4001;
+
+    /**
+     * Dark Beast.
+     */
+    const DARK_BEAST = 5001;
+};
+
+/**
+ * Rift raid level constants.
+ *
+ * @category Data
+ */
+final class RAID_RIFT_DUNGEON_ID{
+
+    /**
+     * Level 1.
+     */
+    const LEVEL_1 = 1;
+
+    /**
+     * Level 2.
+     */
+    const LEVEL_2 = 2;
+
+    /**
+     * Level 3.
+     */
+    const LEVEL_3 = 3;
+
+    /**
+     * Level 4.
+     */
+    const LEVEL_4 = 4;
+
+    /**
+     * Level 5.
+     */
+    const LEVEL_5 = 5;
+};
+
+/**
+ * Constants for all the types of stages in the Tartarus Labyrinth.
+ *
+ * @category Data
+ */
+final class LABYRINTH_STAGES_ID{
+
+    /**
+     * Tartarus (Labyrinth Guardian).
+     */
+    const TARTARUS = 1;
+
+    /**
+     * Kottos (Fire Gaurdian).
+     */
+    const KOTTOS = 2;
+
+    /**
+     * Leos (Waer Guardian).
+     */
+    const LEOS = 3;
+
+    /**
+     * Aquiles (Wind Guardian).
+     */
+    const AQUILES = 4;
+
+    /**
+     * Normal stage.
+     */
+    const NORMAL = 5;
+
+    /**
+     * Rescue stage.
+     */
+    const RESCUE = 6;
+
+    /**
+     * Explode stage.
+     */
+    const EXPLODE = 7;
+
+    /**
+     * Cool Time UP stage.
+     */
+    const COOL_TIME = 8;
+
+    /**
+     * Speed Limit stage.
+     */
+    const SPEED_LIMIT = 9;
+
+    /**
+     * Time Limit stage.
+     */
+    const TIME_LIMIT = 10;
+};
+
+/**
+ * Building constants.
+ *
+ * @category Data
+ */
+final class BUILDING_ID{
+
+    /**
+     * Summoners Tower.
+     */
+    const SUMMONERS_TOWER = 1;
+
+    /**
+     * Summonhenge.
+     */
+    const SUMMONHENGE = 2;
+
+    /**
+     * Pond of Mana.
+     */
+    const POND_OF_MANA = 3;
+
+    /**
+     * Crystal Mine.
+     */
+    const CRYSTAL_MINE = 4;
+
+    /**
+     * Gateway.
+     */
+    const GATEWAY = 8;
+
+    /**
+     * Temple of Wishes.
+     */
+    const TEMPLE_OF_WISHES = 10;
+
+    /**
+     * Magic Shop.
+     */
+    const MAGIC_SHOP = 11;
+
+    /**
+     * Ancient Stones.
+     */
+    const ANCIENT_STONES = 12;
+
+    /**
+     * Arcane Tower.
+     */
+    const ARCANE_TOWER = 14;
+
+    /**
+     * Crystal Titan.
+     */
+    const CRYSTAL_TITAN = 15;
+
+    /**
+     * Fusion Hexagram.
+     */
+    const FUSION_HEXAGRAM = 16;
+
+    /**
+     * Fuse Center.
+     */
+    const FUSE_CENTER = 17;
+
+    /**
+     * Power Up Circle.
+     */
+    const POWER_UP_CIRCLE = 20;
+
+    /**
+     * Tranquil Forest.
+     */
+    const TRANQUIL_FOREST = 22;
+
+    /**
+     * Gusty Cliffs.
+     */
+    const GUSTY_CLIFFS = 23;
+
+    /**
+     * Deep Forest Ent.
+     */
+    const DEEP_FOREST_ENT = 24;
+
+    /**
+     * Monster Storage.
+     */
+    const MONSTER_STORAGE = 25;
+
+    /**
+     * Transmogrification Building.
+     */
+    const TRANSMOGRIFICATION_BUILDING = 27;
+};
+
+/**
+ * Decoration constants.
+ *
+ * @category Data
+ */
+final class DECORATION_ID{
+
+    /**
+     * Guardstone.
+     */
+    const GUARDSTONE = 4;
+
+    /**
+     * Mana Fountain.
+     */
+    const MANA_FOUNTAIN = 5;
+
+    /**
+     * Sky Tribe Totem.
+     */
+    const SKY_TRIBE_TOTEM = 6;
+
+    /**
+     * Arcane Booster Tower.
+     */
+    const ARCANE_BOOSTER_TOWER = 7;
+
+    /**
+     * Crystal Altar.
+     */
+    const CRYSTAL_ALTAR = 8;
+
+    /**
+     * Ancient Sword.
+     */
+    const ANCIENT_SWORD = 9;
+
+    /**
+     * Sanctum of Energy.
+     */
+    const SANCTUM_OF_ENERGY = 10;
+
+    /**
+     * Mysterious Plant.
+     */
+    const MYSTERIOUS_PLANT = 11;
+
+    /**
+     * Fire Sanctuary.
+     */
+    const FIRE_SANCTUARY = 15;
+
+    /**
+     * Water Sanctuary.
+     */
+    const WATER_SANCTUARY = 16;
+
+    /**
+     * Wind Sanctuary.
+     */
+    const WIND_SANCTUARY = 17;
+
+    /**
+     * Light Sanctuary.
+     */
+    const LIGHT_SANCTUARY = 18;
+
+    /**
+     * Dark Sanctuary.
+     */
+    const DARK_SANCTUARY = 19;
+
+    /**
+     * Fallen Ancient Guardian.
+     */
+    const FALLEN_ANCIENT_GUARDIAN = 31;
+
+    /**
+     * Crystal Rock.
+     */
+    const CRYSTAL_ROCK = 34;
+
+    /**
+     * Fairy Tree.
+     */
+    const FAIRY_TREE = 35;
+
+    /**
+     * Flag of Battle.
+     */
+    const FLAG_OF_BATTLE = 36;
+
+    /**
+     * Flag of Rage.
+     */
+    const FLAG_OF_RAGE = 37;
+
+    /**
+     * Flag of Hope.
+     */
+    const FLAG_OF_HOPE = 38;
+
+    /**
+     * Flag of Will.
+     */
+    const FLAG_OF_WILL = 39;
+};
+
+/**
+ * Inventory categories constants.
+ *
+ * @category Data
+ */
+final class INVENTORY_TYPE_ID{
+
+    /**
+     * Monster.
+     */
+    const MONSTER = 1;
+
+    /**
+     * Currency.
+     */
+    const CURRENCY = 6;
+
+    /**
+     * Rune.
+     */
+    const RUNE = 8;
+
+    /**
+     * Scroll.
+     */
+    const SCROLL = 9;
+
+    /**
+     * Booster.
+     */
+    const BOOSTER = 10;
+
+    /**
+     * Essences.
+     */
+    const ESSENCES = 11;
+
+    /**
+     * Monster Piece.
+     */
+    const MONSTER_PIECE = 12;
+
+    // '' => 15, Unknown. Appears in inventory_info with qty 0
+
+    /**
+     * Guild Monster piece.
+     */
+    const GUILD_MONSTER_PIECE = 19;
+
+    /**
+     * Rainbowmon.
+     */
+    const RAINBOWMON = 25;   # Possibly material monsters in general. Appears when wish returns a rainbowmon.
+
+    /**
+     * Enchantment.
+     */
+    const ENCHANTMENT = 27;
+
+    /**
+     * Craft Stuff.
+     */
+    const CRAFT_STUFF = 29;
+
+    /**
+     * Enhancing Monster.
+     */
+    const ENHANCING_MONSTER = 61;
+};
+
+/**
+ * Items constants.
+ *
+ * @category Data
+ */
+final class INVENTORY_ID{
+
+    /**
+     * Essence of Magic (Low).
+     */
+    const ESSENCE_MAGIC_LOW = 11006;
+
+    /**
+     * Essence of Magic (Mid).
+     */
+    const ESSENCE_MAGIC_MID = 12006;
+
+    /**
+     * Essence of Magic (High).
+     */
+    const ESSENCE_MAGIC_HIGH = 13006;
+
+    /**
+     * Essence of Water (Low).
+     */
+    const ESSENCE_WATER_LOW = 11001;
+
+    /**
+     * Essence of Water (Mid).
+     */
+    const ESSENCE_WATER_MID = 12001;
+
+    /**
+     * Essence of Water (High).
+     */
+    const ESSENCE_WATER_HIGH = 13001;
+
+    /**
+     * Essence of Fire (Low).
+     */
+    const ESSENCE_FIRE_LOW = 11002;
+
+    /**
+     * Essence of Fire (Mid).
+     */
+    const ESSENCE_FIRE_MID = 12002;
+
+    /**
+     * Essence of Fire (High).
+     */
+    const ESSENCE_FIRE_HIGH = 13002;
+
+    /**
+     * Essence of Wind (Low).
+     */
+    const ESSENCE_WIND_LOW = 11003;
+
+    /**
+     * Essence of Wind (Mid).
+     */
+    const ESSENCE_WIND_MID = 12003;
+
+    /**
+     * Essence of Wind (High).
+     */
+    const ESSENCE_WIND_HIGH = 13003;
+
+    /**
+     * Essence of Light (Low).
+     */
+    const ESSENCE_LIGHT_LOW = 11004;
+
+    /**
+     * Essence of Light (Mid).
+     */
+    const ESSENCE_LIGHT_MID = 12004;
+
+    /**
+     * Essence of Light (High).
+     */
+    const ESSENCE_LIGHT_HIGH = 13004;
+
+    /**
+     * Essence of Dark (Low).
+     */
+    const ESSENCE_DARK_LOW = 11005;
+
+    /**
+     * Essence of Dark (Mid).
+     */
+    const ESSENCE_DARK_MID = 12005;
+
+    /**
+     * Essence of Dark (High).
+     */
+    const ESSENCE_DARK_HIGH = 13005;
+
+    /**
+     * Wood.
+     */
+    const WOOD = 1001;
+
+    /**
+     * Leather.
+     */
+    const LEATHER = 1002;
+
+    /**
+     * Rock.
+     */
+    const ROCK = 1003;
+
+    /**
+     * Ore.
+     */
+    const ORE = 1004;
+
+    /**
+     * Mithril.
+     */
+    const MITHRIL = 1005;
+
+    /**
+     * Cloth.
+     */
+    const CLOTH = 1006;
+
+    /**
+     * Rune Piece.
+     */
+    const RUNE_PIECE = 2001;
+
+    /**
+     * Powder.
+     */
+    const POWDER = 3001;
+
+    /**
+     * Symbol of Harmony.
+     */
+    const SYMBOL_HARMONY = 4001;
+
+    /**
+     * Symbol of Transcendance.
+     */
+    const SYMBOL_TRANSCENDANCE = 4002;
+
+    /**
+     * Symbol of Chaos.
+     */
+    const SYMBOL_CHAOS = 4003;
+
+    /**
+     * Frozen Water Crystal.
+     */
+    const CRYSTAL_WATER = 5001;
+
+    /**
+     * Flaming Fire Crystal.
+     */
+    const CRYSTAL_FIRE = 5002;
+
+    /**
+     * Whirling Wind Crystal.
+     */
+    const CRYSTAL_WIND = 5003;
+
+    /**
+     * Shiny Light Crystal.
+     */
+    const CRYSTAL_LIGHT = 5004;
+
+    /**
+     * Pitch-Black Dark Crystal.
+     */
+    const CRYSTAL_DARK = 5005;
+
+    /**
+     * Condensed Magic Crystal.
+     */
+    const CRYSTAL_MAGIC = 6001;
+
+    /**
+     * Pure Crystal.
+     */
+    const CRYSTAL_PURE = 7001;
+};
+
+/**
+ * Storage-able enhance monster constants.
+ *
+ * @category Data
+ */
+final class ENHANCE_MONSTER_ID{
+
+    /**
+     * Water Angelmon.
+     */
+    const WATER_ANGELMON = 142110115;
+
+    /**
+     * Fire Angelmon.
+     */
+    const FIRE_ANGELMON = 142120115;
+
+    /**
+     * Wind Angelmon.
+     */
+    const WIND_ANGELMON = 142130115;
+
+    /**
+     * Light Angelmon.
+     */
+    const LIGHT_ANGELMON = 142140115;
+
+    /**
+     * Dark Angelmon.
+     */
+    const DARK_ANGELMON = 142150115;
+
+    /**
+     * Water King Angelmon.
+     */
+    const WATER_KING_ANGELMON = 182110115;
+
+    /**
+     * Fire King Angelmon.
+     */
+    const FIRE_KING_ANGELMON = 182120115;
+
+    /**
+     * Wind King Angelmon.
+     */
+    const WIND_KING_ANGELMON = 182130115;
+
+    /**
+     * Light King Angelmon.
+     */
+    const LIGHT_KING_ANGELMON = 182140115;
+
+    /**
+     * Dark King Angelmon.
+     */
+    const DARK_KING_ANGELMON = 182150115;
+
+    /**
+     * 2* Rainbowmon (Lv. 20).
+     */
+    const RAINBOWMON_2_20 = 143140220;
+
+    /**
+     * 3* Rainbowmon (Lv. 1).
+     */
+    const RAINBOWMON_3_1 = 143140301;
+
+    /**
+     * 3* Rainbowmon (Lv. 25).
+     */
+    const RAINBOWMON_3_25 = 143140325;
+
+    /**
+     * 4* Rainbowmon (Lv. 1).
+     */
+    const RAINBOWMON_4_1 = 143140401;
+
+    /**
+     * 4* Rainbowmon (Lv. 30).
+     */
+    const RAINBOWMON_4_30 = 143140430;
+
+    /**
+     * 5* Rainbowmon (Lv. 1).
+     */
+    const RAINBOWMON_5_1 = 143140501;
+
+    /**
+     * Devilmon.
+     */
+    const DEVILMON = 151050101;
+
+    /**
+     * Super Angelmon.
+     */
+    const SUPER_ANGELMON = 217140115;
+};
+
+/**
+ * Rune set constants.
+ *
+ * @category Data
+ */
+final class RUNE_SET_ID{
+
+    /**
+     * Energy.
+     */
+    const ENERGY = 1;
+
+    /**
+     * Guard.
+     */
+    const GUARD = 2;
+
+    /**
+     * Swift.
+     */
+    const SWIFT = 3;
+
+    /**
+     * Blade.
+     */
+    const BLADE = 4;
+
+    /**
+     * Rage.
+     */
+    const RAGE = 5;
+
+    /**
+     * Focus.
+     */
+    const FOCUS = 6;
+
+    /**
+     * Endure.
+     */
+    const ENDURE = 7;
+
+    /**
+     * Fatal.
+     */
+    const FATAL = 8;
+
+    /**
+     * Despair.
+     */
+    const DESPAIR = 10;
+
+    /**
+     * Vampire.
+     */
+    const VAMPIRE = 11;
+
+    /**
+     * Violent.
+     */
+    const VIOLENT = 13;
+
+    /**
+     * Nemesis.
+     */
+    const NEMESIS = 14;
+
+    /**
+     * Will.
+     */
+    const WILL = 15;
+
+    /**
+     * Shield.
+     */
+    const SHIELD = 16;
+
+    /**
+     * Revenge.
+     */
+    const REVENGE = 17;
+
+    /**
+     * Destroy.
+     */
+    const DESTROY = 18;
+
+    /**
+     * Fight.
+     */
+    const FIGHT = 19;
+
+    /**
+     * Determination.
+     */
+    const DETERMINATION = 20;
+
+    /**
+     * Enhance.
+     */
+    const ENHANCE = 21;
+
+    /**
+     * Accuracy.
+     */
+    const ACCURACY = 22;
+
+    /**
+     * Tolerance.
+     */
+    const TOLERANCE = 23;
+};
+
+/**
+ * Rune stat slot constants.
+ *
+ * Includes all the stat slots a rune can have.
+ *
+ * @category Data
+ */
+final class RUNE_STAT_SLOT_ID{
+
+    /**
+     * Main stat.
+     */
+    const MAIN = -1;
+
+    /**
+     * Innate stat.
+     */
+    const INNATE = 0;
+
+    /**
+     * Substat 1.
+     */
+    const SUBSTAT_1 = 1;
+
+    /**
+     * Substat 2.
+     */
+    const SUBSTAT_2 = 2;
+
+    /**
+     * Substat 3.
+     */
+    const SUBSTAT_3 = 3;
+
+    /**
+     * Substat 4.
+     */
+    const SUBSTAT_4 = 4;
+
+}
+
+/**
+ * Artifact effectslot constants.
+ *
+ * Includes all the effect slots an artifact can have.
+ *
+ * @category Data
+ */
+final class ARTIFACT_EFFECT_SLOT_ID{
+
+    /**
+     * Effect 1.
+     */
+    const EFFECT_1 = 1;
+
+    /**
+     * Effect 2.
+     */
+    const EFFECT_2 = 2;
+
+    /**
+     * Effect 3.
+     */
+    const EFFECT_3 = 3;
+
+    /**
+     * Effect 4.
+     */
+    const EFFECT_4 = 4;
+
+}
+
+/**
+ * Application modes.
+ *
+ * Modes to use RTA configurations or normal configuration.
+ *
+ * @category Data
+ */
+final class GAME_MODE_ID{
+
+    /**
+     * Normal mode.
+     */
+    const NORMAL = 0;
+
+    /**
+     * RTA mode.
+     */
+    const RTA = 1;
+
+}
+
+/**
+ * Rune stat constants.
+ *
+ * Includes all stats a rune can have. For unit stats, see{@see $STAT_ID}.
+ *
+ * @category Data
+ */
+final class RUNE_STAT_ID{
+
+    /**
+     * HP (flat).
+     */
+    const HP = 1;
+
+    /**
+     * HP (percent).
+     */
+    const HP_P = 2;
+
+    /**
+     * Attack  (flat).
+     */
+    const ATK = 3;
+
+    /**
+     * Attack (percent).
+     */
+    const ATK_P = 4;
+
+    /**
+     * Defense  (flat).
+     */
+    const DEF = 5;
+
+    /**
+     * Defense (percent).
+     */
+    const DEF_P = 6;
+
+    /**
+     * Speed.
+     */
+    const SPD = 8;
+
+    /**
+     * Critical Rate.
+     */
+    const CRR = 9;
+
+    /**
+     * Critical Damage.
+     */
+    const CRD = 10;
+
+    /**
+     * Resistance.
+     */
+    const RES = 11;
+
+    /**
+     * Accuracy.
+     */
+    const ACC = 12;
+};
+
+/**
+ * Rune main stat values constants.
+ *
+ * Includes the value of the main stats for type, stars, and level.
+ *
+ * @category Data
+ */
+final class RUNE_STAT_VALUES{
+
     /**
-     * Provides constants.
-     *
-     * Usefull data to be used across the site.
-     *
-     * @category Data
-     */
-
-     /**
-      * Stage difficulty constants.
-      *
-      * @category Data
-      */
-    final class DIFFICULTY_ID{
-
-        /**
-         * Difficulty EASY (Tartarus Labyrinth only).
-         */
-        const EASY = 0;
-
-        /**
-         * Difficulty EASY (Scenario, TOA, Labyrinth).
-         */
-        const NORMAL = 1;
-
-        /**
-         * Difficulty EASY (Scenario, TOA, Labyrinth).
-         */
-        const HARD = 2;
-
-        /**
-         * Difficulty EASY (Scenario, Labyrinth).
-         */
-        const HELL = 3;
-    };
-
-    /**
-     * Unit source constants.
-     *
-     * @category Data
-     */
-    final class SOURCE_ID{
-
-        /**
-         * Unknown Scroll (elemental 1-3*).
-         */
-        const SCROLL_UNKNOWN = 1;
-
-        /**
-         * Mystical Scroll (elemental 3-5*).
-         */
-        const SCROLL_MYSTICAL = 2;
-
-        /**
-         * Light and Darkness Scroll (LD 3-5*).
-         */
-        const SCROLL_LIGHT_AND_DARK = 3;
-
-        /**
-         * Water scroll (water 3-5*)
-         */
-        const SCROLL_WATER = 4;
-
-        /**
-         * Fire scroll (fire 3-5*)
-         */
-        const SCROLL_FIRE = 5;
-
-        /**
-         * Wind scroll (wind 3-5*)
-         */
-        const SCROLL_WIND = 6;
-
-        /**
-         * Legendary Scroll (elemental 4-5*)
-         */
-        const SCROLL_LEGENDARY = 7;
-
-        /**
-         * Summon Stones (elemental 3-5*)
-         */
-        const SUMMON_EXCLUSIVE = 8;
-
-        /**
-         * Legendary Summoning Pieces (4-5*)
-         */
-        const SUMMON_LEGENDARY_PIECES = 9;
-
-        /**
-         * Light and Darkness Scroll (LD 3-5*).
-         */
-        const SUMMON_LIGHT_AND_DARK_PIECES = 10;
-
-        /**
-         * Transcendance Scroll (elemental 5*)
-         */
-        const SCROLL_TRANSCENDANCE = 11;
-
-        /**
-         * Legendary Water Scroll (water 4-5*)
-         */
-        const SCROLL_LEGENDARY_WATER = 12;
-
-        /**
-         * Legendary Fire Scroll (fire 4-5*)
-         */
-        const SCROLL_LEGENDARY_FIRE = 13;
-
-        /**
-         * Legendary Wind Scroll (wind 4-5*)
-         */
-        const SCROLL_LEGENDARY_WIND = 14;
-    };
-
-    /**
-     * Element constants.
-     *
-     * @category Data
-     */
-    final class ELEMENT_ID{
-
-        /**
-         * Water
-         */
-        const WATER = 1;
-
-        /**
-         * Fire
-         */
-        const FIRE = 2;
-
-        /**
-         * Wind
-         */
-        const WIND = 3;
-
-        /**
-         * Light
-         */
-        const LIGHT = 4;
-
-        /**
-         * Dark
-         */
-        const DARK = 5;
-
-        /**
-         * Pure
-         */
-        const PURE = 6;
-    };
-
-    /**
-     * Unit archetype constants.
-     *
-     * @category Data
-     */
-    final class ARCHETYPE_ID{
-
-        /**
-         * None
-         */
-        const NONE = 0;
-
-        /**
-         * Attack
-         */
-        const ATTACK = 1;
-
-        /**
-         * Defense
-         */
-        const DEFENSE = 2;
-
-        /**
-         * HP
-         */
-        const HP = 3;
-
-        /**
-         * Support
-         */
-        const SUPPORT = 4;
-
-        /**
-         * Material
-         */
-        const MATERIAL = 5;
-    };
-
-    /**
-     * Stat constants.
-     *
-     * Used for unit stats, for rune stat types, see {@see RUNE_STAT_ID}
-     *
-     * @category Data
-     */
-    final class STAT_ID{
-
-        /**
-         * HP
-         */
-        const HP = 1;
-
-        /**
-         * ATK
-         */
-        const ATK = 2;
-
-        /**
-         * DEF
-         */
-        const DEF = 3;
-
-        /**
-         * SPD
-         */
-        const SPD = 4;
-
-        /**
-         * CRIT_RATE
-         */
-        const CRIT_RATE = 5;
-
-        /**
-         * CRIT_DMG
-         */
-        const CRIT_DMG = 6;
-
-        /**
-         * RESIST
-         */
-        const RESIST = 7;
-
-        /**
-         * ACCURACY
-         */
-        const ACCURACY = 8;
-    };
-
-    /**
-     * Leadr skill area constants.
-     *
-     * @category Data
-     */
-    final class EFFECT_AREA_ID{
-
-        /**
-         * General (all areas).
-         */
-        const GENERAL = 1;
-
-        /**
-         * Arena (offense and defense).
-         */
-        const ARENA = 3;
-
-        /**
-         * Dungeon (Cairos, elemental Rifts, Dimensinal Hole).
-         */
-        const DUNGEON = 2;
-
-        /**
-         * Guild content (battle, siege, Labyrinth).
-         */
-        const GUILD = 5;
-    };
-
-    /**
-     * Playable area group constants.
-     *
-     * @category Data
-     */
-    final class AREA_TYPE_ID{
-
-        /**
-         * Scenario.
-         */
-        const SCENARIO = 1;
-
-        /**
-         * Cairos Dungeon.
-         */
-        const CAIROS_DUNGEON = 2;
-
-        /**
-         * Elemental Rift Dungeons.
-         */
-        const RIFT_DUNGEON = 3;
-
-        /**
-         * Rift Raid.
-         */
-        const RIFT_RAID = 4;
-
-        /**
-         * Dimensional Hole.
-         */
-        const DIMENSIONAL_HOLE = 5;
-
-        /**
-         * Arena.
-         */
-        const ARENA = 6;
-
-        /**
-         * Guild War.
-         */
-        const GUILD_WAR = 7;
-
-        /**
-         * Guild Siege.
-         */
-        const GUILD_SIEGE = 8;
-
-        /**
-         * Tartarus Labyrinth.
-         */
-        const TARTARUS_LABYRINTH = 9;
-
-        /**
-         * Trial of Ascension.
-         */
-        const TRIAL_OF_ASCENSION = 10;
-
-        /**
-         * World Boss.
-         */
-        const WORLD_BOSS = 11;
-
-        /**
-         * Dimensional Rift.
-         */
-        const DIMENSIONAL_RIFT = 12;
-    };
-
-    /**
-     * Scenario area constants.
-     *
-     * @category Data
-     */
-    final class SCENARIO_ID{
-
-        /**
-         * Garen Forest.
-         */
-        const GAREN_FOREST = 1;
-
-        /**
-         * Mt. Siz.
-         */
-        const MT_SIZ = 2;
-
-        /**
-         * Kabir Ruins.
-         */
-        const KABIR_RUINS = 3;
-
-        /**
-         * Mt. White Ragon.
-         */
-        const MT_WHITE_RAGON = 4;
-
-        /**
-         * Telain Forest.
-         */
-        const TELAIN_FOREST = 5;
-
-        /**
-         * Hydeni Ruins.
-         */
-        const HYDENI_RUINS = 6;
-
-        /**
-         * Tamor Desert.
-         */
-        const TAMOR_DESERT = 7;
-
-        /**
-         * Vrofagus Ruins.
-         */
-        const VROFAGUS_RUINS = 8;
-
-        /**
-         * Faimon Volcano.
-         */
-        const FAIMON_VOLCANO = 9;
-
-        /**
-         * Aiden Forest.
-         */
-        const AIDEN_FOREST = 10;
-
-        /**
-         * Ferun Castle.
-         */
-        const FERUN_CASTLE = 11;
-
-        /**
-         * Mt Runar.
-         */
-        const MT_RUNAR = 12;
-
-        /**
-         * Chiruka Remains.
-         */
-        const CHIRUKA_REMAINS = 13;
-    };
-
-    /**
-     * Dungeon section constants.
-     *
-     * Includes Cairos Dungeons and Dimension Hole Dungeons.
-     *
-     * @category Data
-     */
-    final class DUNGEON_ID{
-
-        /**
-         * Hall of Dark.
-         */
-        const HALL_OF_DARK = 1001;
-
-        /**
-         * Sanctuary of Dreaming Fairies.
-         */
-        const SANCTUARY_OF_DREAMING_FAIRIES = 1101;
-
-        /**
-         * Ellunia Remains (Fairy).
-         */
-        const ELLUNIA_REMAINS_FAIRY = 1201;
-
-        /**
-         * Ellunia Remains (Pixie).
-         */
-        const ELLUNIA_REMAINS_PIXIE = 1202;
-
-        /**
-         * Hall of Fire.
-         */
-        const HALL_OF_FIRE = 2001;
-
-        /**
-         * Forest of Roaring Beasts.
-         */
-        const FOREST_OF_ROARING_BEASTS = 2101;
-
-        /**
-         * Karzhan Remains (Warbear).
-         */
-        const KARZHAN_REMAINS_WARBEAR = 2201;
-
-        /**
-         * Karzhan Remains (Inugami).
-         */
-        const KARZHAN_REMAINS_INUGAMI = 2202;
-
-        /**
-         * Cliff of Tough Beast Men.
-         */
-        const CLIFF_OF_TOUGH_BEASTS_MEN = 3101;
-
-        /**
-         * Lumel Remains (Werewolf).
-         */
-        const LUMEL_REMAINS_WEREWOLF = 3201;
-
-        /**
-         * Lumel Remains (Martial Cat).
-         */
-        const LUMEL_REMAINS_MARTIAL_CAT = 3202;
-
-        /**
-         * Hall of water.
-         */
-        const HALL_OF_WATER = 3001;
-
-        /**
-         * Hall of Wind.
-         */
-        const HALL_OF_WIND = 4001;
-
-        /**
-         * Hall of Magic.
-         */
-        const HALL_OF_MAGIC = 5001;
-
-        /**
-         * Necropolis.
-         */
-        const NECROPOLIS = 6001;
-
-        /**
-         * Punisher's Crypt.
-         */
-        const PUNISHERS_CRYPT = 9502;
-
-        /**
-         * Steel Fortress
-         */
-        const STEEL_FORTRESS = 9501;
-
-        /**
-         * Hall of Light.
-         */
-        const HALL_OF_LIGHT = 7001;
-
-        /**
-         * Giants Keep.
-         */
-        const GIANTS_KEEP = 8001;
-
-        /**
-         * Dragons Lair.
-         */
-        const DRAGONS_LAIR = 9001;
-    };
-
-    /**
-     * Cairos Dungeons section constants.
-     *
-     * @category Data
-     */
-    final class CAIROS_DUNGEON_ID{
-
-        /**
-         * Hall of Dark.
-         */
-        const HALL_OF_DARK = 1001;
-
-        /**
-         * Hall of Fire.
-         */
-        const HALL_OF_FIRE = 2001;
-
-        /**
-         * Hall of water.
-         */
-        const HALL_OF_WATER = 3001;
-
-        /**
-         * Hall of Wind.
-         */
-        const HALL_OF_WIND = 4001;
-
-        /**
-         * Hall of Magic.
-         */
-        const HALL_OF_MAGIC = 5001;
-
-        /**
-         * Necropolis.
-         */
-        const NECROPOLIS = 6001;
-
-        /**
-         * Punisher's Crypt.
-         */
-        const PUNISHERS_CRYPT = 9502;
-
-        /**
-         * Steel Fortress
-         */
-        const STEEL_FORTRESS = 9602; // TODO: Find out
-
-        /**
-         * Hall of Light.
-         */
-        const HALL_OF_LIGHT = 7001;
-
-        /**
-         * Giants Keep.
-         */
-        const GIANTS_KEEP = 8001;
-
-        /**
-         * Dragons Lair.
-         */
-        const DRAGONS_LAIR = 9001;
-    };
-
-    /**
-     * Dimensional Dungeons section constants.
-     *
-     * @category Data
-     */
-    final class DIMENSION_DUNGEON_ID{
-
-        /**
-         * Sanctuary of Dreaming Fairies.
-         */
-        const SANCTUARY_OF_DREAMING_FAIRIES = 1101;
-
-        /**
-         * Ellunia Remains (Fairy).
-         */
-        const ELLUNIA_REMAINS_FAIRY = 1201;
-
-        /**
-         * Ellunia Remains (Pixie).
-         */
-        const ELLUNIA_REMAINS_PIXIE = 1202;
-
-        /**
-         * Forest of Roaring Beasts.
-         */
-        const FOREST_OF_ROARING_BEASTS = 2101;
-
-        /**
-         * Karzhan Remains (Warbear).
-         */
-        const KARZHAN_REMAINS_WARBEAR = 2201;
-
-        /**
-         * Karzhan Remains (Inugami).
-         */
-        const KARZHAN_REMAINS_INUGAMI = 2202;
-
-        /**
-         * Cliff of Tough Beast Men.
-         */
-        const CLIFF_OF_TOUGH_BEASTS_MEN = 3101;
-
-        /**
-         * Lumel Remains (Werewolf).
-         */
-        const LUMEL_REMAINS_WEREWOLF = 3201;
-
-        /**
-         * Lumel Remains (Martial Cat).
-         */
-        const LUMEL_REMAINS_MARTIAL_CAT = 3202;
-    };
-
-    /**
-     * Elemental Rift Dungeon constants.
-     *
-     * @category Data
-     */
-    final class ELEMENTAL_RIFT_DUNGEON_ID{
-
-        /**
-         * Ice Beast.
-         */
-        const ICE_BEAST = 1001;
-
-        /**
-         * Fire Beast.
-         */
-        const FIRE_BEAST = 2001;
-
-        /**
-         * Wind Beast.
-         */
-        const WIND_BEAST = 3001;
-
-        /**
-         * Light Beast.
-         */
-        const LIGHT_BEAST = 4001;
-
-        /**
-         * Dark Beast.
-         */
-        const DARK_BEAST = 5001;
-    };
-
-    /**
-     * Rift raid level constants.
-     *
-     * @category Data
-     */
-    final class RAID_RIFT_DUNGEON_ID{
-
-        /**
-         * Level 1.
-         */
-        const LEVEL_1 = 1;
-
-        /**
-         * Level 2.
-         */
-        const LEVEL_2 = 2;
-
-        /**
-         * Level 3.
-         */
-        const LEVEL_3 = 3;
-
-        /**
-         * Level 4.
-         */
-        const LEVEL_4 = 4;
-
-        /**
-         * Level 5.
-         */
-        const LEVEL_5 = 5;
-    };
-
-    /**
-     * Constants for all the types of stages in the Tartarus Labyrinth.
-     *
-     * @category Data
-     */
-    final class LABYRINTH_STAGES_ID{
-
-        /**
-         * Tartarus (Labyrinth Guardian).
-         */
-        const TARTARUS = 1;
-
-        /**
-         * Kottos (Fire Gaurdian).
-         */
-        const KOTTOS = 2;
-
-        /**
-         * Leos (Waer Guardian).
-         */
-        const LEOS = 3;
-
-        /**
-         * Aquiles (Wind Guardian).
-         */
-        const AQUILES = 4;
-
-        /**
-         * Normal stage.
-         */
-        const NORMAL = 5;
-
-        /**
-         * Rescue stage.
-         */
-        const RESCUE = 6;
-
-        /**
-         * Explode stage.
-         */
-        const EXPLODE = 7;
-
-        /**
-         * Cool Time UP stage.
-         */
-        const COOL_TIME = 8;
-
-        /**
-         * Speed Limit stage.
-         */
-        const SPEED_LIMIT = 9;
-
-        /**
-         * Time Limit stage.
-         */
-        const TIME_LIMIT = 10;
-    };
-
-    /**
-     * Building constants.
-     *
-     * @category Data
-     */
-    final class BUILDING_ID{
-
-        /**
-         * Summoners Tower.
-         */
-        const SUMMONERS_TOWER = 1;
-
-        /**
-         * Summonhenge.
-         */
-        const SUMMONHENGE = 2;
-
-        /**
-         * Pond of Mana.
-         */
-        const POND_OF_MANA = 3;
-
-        /**
-         * Crystal Mine.
-         */
-        const CRYSTAL_MINE = 4;
-
-        /**
-         * Gateway.
-         */
-        const GATEWAY = 8;
-
-        /**
-         * Temple of Wishes.
-         */
-        const TEMPLE_OF_WISHES = 10;
-
-        /**
-         * Magic Shop.
-         */
-        const MAGIC_SHOP = 11;
-
-        /**
-         * Ancient Stones.
-         */
-        const ANCIENT_STONES = 12;
-
-        /**
-         * Arcane Tower.
-         */
-        const ARCANE_TOWER = 14;
-
-        /**
-         * Crystal Titan.
-         */
-        const CRYSTAL_TITAN = 15;
-
-        /**
-         * Fusion Hexagram.
-         */
-        const FUSION_HEXAGRAM = 16;
-
-        /**
-         * Fuse Center.
-         */
-        const FUSE_CENTER = 17;
-
-        /**
-         * Power Up Circle.
-         */
-        const POWER_UP_CIRCLE = 20;
-
-        /**
-         * Tranquil Forest.
-         */
-        const TRANQUIL_FOREST = 22;
-
-        /**
-         * Gusty Cliffs.
-         */
-        const GUSTY_CLIFFS = 23;
-
-        /**
-         * Deep Forest Ent.
-         */
-        const DEEP_FOREST_ENT = 24;
-
-        /**
-         * Monster Storage.
-         */
-        const MONSTER_STORAGE = 25;
-
-        /**
-         * Transmogrification Building.
-         */
-        const TRANSMOGRIFICATION_BUILDING = 27;
-    };
-
-    /**
-     * Decoration constants.
-     *
-     * @category Data
-     */
-    final class DECORATION_ID{
-
-        /**
-         * Guardstone.
-         */
-        const GUARDSTONE = 4;
-
-        /**
-         * Mana Fountain.
-         */
-        const MANA_FOUNTAIN = 5;
-
-        /**
-         * Sky Tribe Totem.
-         */
-        const SKY_TRIBE_TOTEM = 6;
-
-        /**
-         * Arcane Booster Tower.
-         */
-        const ARCANE_BOOSTER_TOWER = 7;
-
-        /**
-         * Crystal Altar.
-         */
-        const CRYSTAL_ALTAR = 8;
-
-        /**
-         * Ancient Sword.
-         */
-        const ANCIENT_SWORD = 9;
-
-        /**
-         * Sanctum of Energy.
-         */
-        const SANCTUM_OF_ENERGY = 10;
-
-        /**
-         * Mysterious Plant.
-         */
-        const MYSTERIOUS_PLANT = 11;
-
-        /**
-         * Fire Sanctuary.
-         */
-        const FIRE_SANCTUARY = 15;
-
-        /**
-         * Water Sanctuary.
-         */
-        const WATER_SANCTUARY = 16;
-
-        /**
-         * Wind Sanctuary.
-         */
-        const WIND_SANCTUARY = 17;
-
-        /**
-         * Light Sanctuary.
-         */
-        const LIGHT_SANCTUARY = 18;
-
-        /**
-         * Dark Sanctuary.
-         */
-        const DARK_SANCTUARY = 19;
-
-        /**
-         * Fallen Ancient Guardian.
-         */
-        const FALLEN_ANCIENT_GUARDIAN = 31;
-
-        /**
-         * Crystal Rock.
-         */
-        const CRYSTAL_ROCK = 34;
-
-        /**
-         * Fairy Tree.
-         */
-        const FAIRY_TREE = 35;
-
-        /**
-         * Flag of Battle.
-         */
-        const FLAG_OF_BATTLE = 36;
-
-        /**
-         * Flag of Rage.
-         */
-        const FLAG_OF_RAGE = 37;
-
-        /**
-         * Flag of Hope.
-         */
-        const FLAG_OF_HOPE = 38;
-
-        /**
-         * Flag of Will.
-         */
-        const FLAG_OF_WILL = 39;
-    };
-
-    /**
-     * Inventory categories constants.
-     *
-     * @category Data
-     */
-    final class INVENTORY_TYPE_ID{
-
-        /**
-         * Monster.
-         */
-        const MONSTER = 1;
-
-        /**
-         * Currency.
-         */
-        const CURRENCY = 6;
-
-        /**
-         * Rune.
-         */
-        const RUNE = 8;
-
-        /**
-         * Scroll.
-         */
-        const SCROLL = 9;
-
-        /**
-         * Booster.
-         */
-        const BOOSTER = 10;
-
-        /**
-         * Essences.
-         */
-        const ESSENCES = 11;
-
-        /**
-         * Monster Piece.
-         */
-        const MONSTER_PIECE = 12;
-
-        // '' => 15, Unknown. Appears in inventory_info with qty 0
-
-        /**
-         * Guild Monster piece.
-         */
-        const GUILD_MONSTER_PIECE = 19;
-
-        /**
-         * Rainbowmon.
-         */
-        const RAINBOWMON = 25;   # Possibly material monsters in general. Appears when wish returns a rainbowmon.
-
-        /**
-         * Enchantment.
-         */
-        const ENCHANTMENT = 27;
-
-        /**
-         * Craft Stuff.
-         */
-        const CRAFT_STUFF = 29;
-
-        /**
-         * Enhancing Monster.
-         */
-        const ENHANCING_MONSTER = 61;
-    };
-
-    /**
-     * Items constants.
-     *
-     * @category Data
-     */
-    final class INVENTORY_ID{
-
-        /**
-         * Essence of Magic (Low).
-         */
-        const ESSENCE_MAGIC_LOW = 11006;
-
-        /**
-         * Essence of Magic (Mid).
-         */
-        const ESSENCE_MAGIC_MID = 12006;
-
-        /**
-         * Essence of Magic (High).
-         */
-        const ESSENCE_MAGIC_HIGH = 13006;
-
-        /**
-         * Essence of Water (Low).
-         */
-        const ESSENCE_WATER_LOW = 11001;
-
-        /**
-         * Essence of Water (Mid).
-         */
-        const ESSENCE_WATER_MID = 12001;
-
-        /**
-         * Essence of Water (High).
-         */
-        const ESSENCE_WATER_HIGH = 13001;
-
-        /**
-         * Essence of Fire (Low).
-         */
-        const ESSENCE_FIRE_LOW = 11002;
-
-        /**
-         * Essence of Fire (Mid).
-         */
-        const ESSENCE_FIRE_MID = 12002;
-
-        /**
-         * Essence of Fire (High).
-         */
-        const ESSENCE_FIRE_HIGH = 13002;
-
-        /**
-         * Essence of Wind (Low).
-         */
-        const ESSENCE_WIND_LOW = 11003;
-
-        /**
-         * Essence of Wind (Mid).
-         */
-        const ESSENCE_WIND_MID = 12003;
-
-        /**
-         * Essence of Wind (High).
-         */
-        const ESSENCE_WIND_HIGH = 13003;
-
-        /**
-         * Essence of Light (Low).
-         */
-        const ESSENCE_LIGHT_LOW = 11004;
-
-        /**
-         * Essence of Light (Mid).
-         */
-        const ESSENCE_LIGHT_MID = 12004;
-
-        /**
-         * Essence of Light (High).
-         */
-        const ESSENCE_LIGHT_HIGH = 13004;
-
-        /**
-         * Essence of Dark (Low).
-         */
-        const ESSENCE_DARK_LOW = 11005;
-
-        /**
-         * Essence of Dark (Mid).
-         */
-        const ESSENCE_DARK_MID = 12005;
-
-        /**
-         * Essence of Dark (High).
-         */
-        const ESSENCE_DARK_HIGH = 13005;
-
-        /**
-         * Wood.
-         */
-        const WOOD = 1001;
-
-        /**
-         * Leather.
-         */
-        const LEATHER = 1002;
-
-        /**
-         * Rock.
-         */
-        const ROCK = 1003;
-
-        /**
-         * Ore.
-         */
-        const ORE = 1004;
-
-        /**
-         * Mithril.
-         */
-        const MITHRIL = 1005;
-
-        /**
-         * Cloth.
-         */
-        const CLOTH = 1006;
-
-        /**
-         * Rune Piece.
-         */
-        const RUNE_PIECE = 2001;
-
-        /**
-         * Powder.
-         */
-        const POWDER = 3001;
-
-        /**
-         * Symbol of Harmony.
-         */
-        const SYMBOL_HARMONY = 4001;
-
-        /**
-         * Symbol of Transcendance.
-         */
-        const SYMBOL_TRANSCENDANCE = 4002;
-
-        /**
-         * Symbol of Chaos.
-         */
-        const SYMBOL_CHAOS = 4003;
-
-        /**
-         * Frozen Water Crystal.
-         */
-        const CRYSTAL_WATER = 5001;
-
-        /**
-         * Flaming Fire Crystal.
-         */
-        const CRYSTAL_FIRE = 5002;
-
-        /**
-         * Whirling Wind Crystal.
-         */
-        const CRYSTAL_WIND = 5003;
-
-        /**
-         * Shiny Light Crystal.
-         */
-        const CRYSTAL_LIGHT = 5004;
-
-        /**
-         * Pitch-Black Dark Crystal.
-         */
-        const CRYSTAL_DARK = 5005;
-
-        /**
-         * Condensed Magic Crystal.
-         */
-        const CRYSTAL_MAGIC = 6001;
-
-        /**
-         * Pure Crystal.
-         */
-        const CRYSTAL_PURE = 7001;
-    };
-
-    /**
-     * Storage-able enhance monster constants.
-     *
-     * @category Data
-     */
-    final class ENHANCE_MONSTER_ID{
-
-        /**
-         * Water Angelmon.
-         */
-        const WATER_ANGELMON = 142110115;
-
-        /**
-         * Fire Angelmon.
-         */
-        const FIRE_ANGELMON = 142120115;
-
-        /**
-         * Wind Angelmon.
-         */
-        const WIND_ANGELMON = 142130115;
-
-        /**
-         * Light Angelmon.
-         */
-        const LIGHT_ANGELMON = 142140115;
-
-        /**
-         * Dark Angelmon.
-         */
-        const DARK_ANGELMON = 142150115;
-
-        /**
-         * Water King Angelmon.
-         */
-        const WATER_KING_ANGELMON = 182110115;
-
-        /**
-         * Fire King Angelmon.
-         */
-        const FIRE_KING_ANGELMON = 182120115;
-
-        /**
-         * Wind King Angelmon.
-         */
-        const WIND_KING_ANGELMON = 182130115;
-
-        /**
-         * Light King Angelmon.
-         */
-        const LIGHT_KING_ANGELMON = 182140115;
-
-        /**
-         * Dark King Angelmon.
-         */
-        const DARK_KING_ANGELMON = 182150115;
-
-        /**
-         * 2* Rainbowmon (Lv. 20).
-         */
-        const RAINBOWMON_2_20 = 143140220;
-
-        /**
-         * 3* Rainbowmon (Lv. 1).
-         */
-        const RAINBOWMON_3_1 = 143140301;
-
-        /**
-         * 3* Rainbowmon (Lv. 25).
-         */
-        const RAINBOWMON_3_25 = 143140325;
-
-        /**
-         * 4* Rainbowmon (Lv. 1).
-         */
-        const RAINBOWMON_4_1 = 143140401;
-
-        /**
-         * 4* Rainbowmon (Lv. 30).
-         */
-        const RAINBOWMON_4_30 = 143140430;
-
-        /**
-         * 5* Rainbowmon (Lv. 1).
-         */
-        const RAINBOWMON_5_1 = 143140501;
-
-        /**
-         * Devilmon.
-         */
-        const DEVILMON = 151050101;
-
-        /**
-         * Super Angelmon.
-         */
-        const SUPER_ANGELMON = 217140115;
-    };
-
-    /**
-     * Rune set constants.
-     *
-     * @category Data
-     */
-    final class RUNE_SET_ID{
-
-        /**
-         * Energy.
-         */
-        const ENERGY = 1;
-
-        /**
-         * Guard.
-         */
-        const GUARD = 2;
-
-        /**
-         * Swift.
-         */
-        const SWIFT = 3;
-
-        /**
-         * Blade.
-         */
-        const BLADE = 4;
-
-        /**
-         * Rage.
-         */
-        const RAGE = 5;
-
-        /**
-         * Focus.
-         */
-        const FOCUS = 6;
-
-        /**
-         * Endure.
-         */
-        const ENDURE = 7;
-
-        /**
-         * Fatal.
-         */
-        const FATAL = 8;
-
-        /**
-         * Despair.
-         */
-        const DESPAIR = 10;
-
-        /**
-         * Vampire.
-         */
-        const VAMPIRE = 11;
-
-        /**
-         * Violent.
-         */
-        const VIOLENT = 13;
-
-        /**
-         * Nemesis.
-         */
-        const NEMESIS = 14;
-
-        /**
-         * Will.
-         */
-        const WILL = 15;
-
-        /**
-         * Shield.
-         */
-        const SHIELD = 16;
-
-        /**
-         * Revenge.
-         */
-        const REVENGE = 17;
-
-        /**
-         * Destroy.
-         */
-        const DESTROY = 18;
-
-        /**
-         * Fight.
-         */
-        const FIGHT = 19;
-
-        /**
-         * Determination.
-         */
-        const DETERMINATION = 20;
-
-        /**
-         * Enhance.
-         */
-        const ENHANCE = 21;
-
-        /**
-         * Accuracy.
-         */
-        const ACCURACY = 22;
-
-        /**
-         * Tolerance.
-         */
-        const TOLERANCE = 23;
-    };
-
-
-    /**
-     * Rune stat slot constants.
-     *
-     * Includes all the stat slots a rune can have.
-     *
-     * @category Data
+     * Values of the HP main stat [stars][level]
      */
-    final class RUNE_STAT_SLOT_ID{
-
-        /**
-         * Main stat.
-         */
-        const MAIN = -1;
-
-        /**
-         * Innate stat.
-         */
-        const INNATE = 0;
-
-        /**
-         * Substat 1.
-         */
-        const SUBSTAT_1 = 1;
-
-        /**
-         * Substat 2.
-         */
-        const SUBSTAT_2 = 2;
-
-        /**
-         * Substat 3.
-         */
-        const SUBSTAT_3 = 3;
-
-        /**
-         * Substat 4.
-         */
-        const SUBSTAT_4 = 4;
-
-    }
+    const HP = [
+        "1" => [
+            "0" => 40,
+            "1" => 85,
+            "2" => 130,
+            "3" => 175,
+            "4" => 220,
+            "5" => 265,
+            "6" => 310,
+            "7" => 355,
+            "8" => 400,
+            "9" => 445,
+            "10" => 490,
+            "11" => 535,
+            "12" => 580,
+            "13" => 625,
+            "14" => 670,
+            "15" => 804
+        ],
+        "2" => [
+            "0" => 70,
+            "1" => 130,
+            "2" => 190,
+            "3" => 250,
+            "4" => 310,
+            "5" => 370,
+            "6" => 430,
+            "7" => 490,
+            "8" => 550,
+            "9" => 610,
+            "10" => 670,
+            "11" => 730,
+            "12" => 790,
+            "13" => 850,
+            "14" => 910,
+            "15" => 1092
+        ],
+        "3" => [
+            "0" => 100,
+            "1" => 175,
+            "2" => 250,
+            "3" => 325,
+            "4" => 400,
+            "5" => 475,
+            "6" => 550,
+            "7" => 625,
+            "8" => 700,
+            "9" => 775,
+            "10" => 850,
+            "11" => 925,
+            "12" => 1000,
+            "13" => 1075,
+            "14" => 1150,
+            "15" => 1380
+        ],
+        "4" => [
+            "0" => 160,
+            "1" => 250,
+            "2" => 340,
+            "3" => 430,
+            "4" => 520,
+            "5" => 610,
+            "6" => 700,
+            "7" => 790,
+            "8" => 880,
+            "9" => 970,
+            "10" => 1060,
+            "11" => 1150,
+            "12" => 1240,
+            "13" => 1330,
+            "14" => 1420,
+            "15" => 1704
+        ],
+        "5" => [
+            "0" => 270,
+            "1" => 375,
+            "2" => 480,
+            "3" => 585,
+            "4" => 690,
+            "5" => 795,
+            "6" => 900,
+            "7" => 1005,
+            "8" => 1110,
+            "9" => 1215,
+            "10" => 1320,
+            "11" => 1425,
+            "12" => 1530,
+            "13" => 1635,
+            "14" => 1740,
+            "15" => 2088
+        ],
+        "6" => [
+            "0" => 360,
+            "1" => 480,
+            "2" => 600,
+            "3" => 720,
+            "4" => 840,
+            "5" => 960,
+            "6" => 1080,
+            "7" => 1200,
+            "8" => 1320,
+            "9" => 1440,
+            "10" => 1560,
+            "11" => 1680,
+            "12" => 1800,
+            "13" => 1920,
+            "14" => 2040,
+            "15" => 2448
+        ]
+    ];
 
+    /**
+     * Values of the HP_P main stat[stars][level]
+     */
+    const HP_P = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 24,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 36,
+            "15" => 43
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 10,
+            "2" => 12,
+            "3" => 15,
+            "4" => 17,
+            "5" => 20,
+            "6" => 22,
+            "7" => 24,
+            "8" => 27,
+            "9" => 29,
+            "10" => 32,
+            "11" => 34,
+            "12" => 37,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 14,
+            "2" => 17,
+            "3" => 20,
+            "4" => 23,
+            "5" => 26,
+            "6" => 29,
+            "7" => 32,
+            "8" => 35,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 47,
+            "13" => 50,
+            "14" => 53,
+            "15" => 63
+        ]
+    ];
+
+    /**
+     * Values of the ATK main stat[stars][level]
+     */
+    const ATK = [
+        "1" => [
+            "0" => 3,
+            "1" => 6,
+            "2" => 9,
+            "3" => 12,
+            "4" => 15,
+            "5" => 18,
+            "6" => 21,
+            "7" => 24,
+            "8" => 27,
+            "9" => 30,
+            "10" => 33,
+            "11" => 36,
+            "12" => 39,
+            "13" => 42,
+            "14" => 45,
+            "15" => 54
+        ],
+        "2" => [
+            "0" => 5,
+            "1" => 9,
+            "2" => 13,
+            "3" => 17,
+            "4" => 21,
+            "5" => 25,
+            "6" => 29,
+            "7" => 33,
+            "8" => 37,
+            "9" => 41,
+            "10" => 45,
+            "11" => 49,
+            "12" => 53,
+            "13" => 57,
+            "14" => 61,
+            "15" => 73
+        ],
+        "3" => [
+            "0" => 7,
+            "1" => 12,
+            "2" => 17,
+            "3" => 22,
+            "4" => 27,
+            "5" => 32,
+            "6" => 37,
+            "7" => 42,
+            "8" => 47,
+            "9" => 52,
+            "10" => 57,
+            "11" => 62,
+            "12" => 67,
+            "13" => 72,
+            "14" => 77,
+            "15" => 92
+        ],
+        "4" => [
+            "0" => 10,
+            "1" => 16,
+            "2" => 22,
+            "3" => 28,
+            "4" => 34,
+            "5" => 40,
+            "6" => 46,
+            "7" => 52,
+            "8" => 58,
+            "9" => 64,
+            "10" => 70,
+            "11" => 76,
+            "12" => 82,
+            "13" => 88,
+            "14" => 94,
+            "15" => 112
+        ],
+        "5" => [
+            "0" => 15,
+            "1" => 22,
+            "2" => 29,
+            "3" => 36,
+            "4" => 43,
+            "5" => 50,
+            "6" => 57,
+            "7" => 64,
+            "8" => 71,
+            "9" => 78,
+            "10" => 85,
+            "11" => 92,
+            "12" => 99,
+            "13" => 106,
+            "14" => 113,
+            "15" => 135
+        ],
+        "6" => [
+            "0" => 22,
+            "1" => 30,
+            "2" => 38,
+            "3" => 46,
+            "4" => 54,
+            "5" => 62,
+            "6" => 70,
+            "7" => 78,
+            "8" => 86,
+            "9" => 94,
+            "10" => 102,
+            "11" => 110,
+            "12" => 118,
+            "13" => 126,
+            "14" => 134,
+            "15" => 160
+        ]
+    ];
+
+    /**
+     * Values of the ATK_P main stat[stars][level]
+     */
+    const ATK_P = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 24,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 36,
+            "15" => 43
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 10,
+            "2" => 12,
+            "3" => 15,
+            "4" => 17,
+            "5" => 20,
+            "6" => 22,
+            "7" => 24,
+            "8" => 27,
+            "9" => 29,
+            "10" => 32,
+            "11" => 34,
+            "12" => 37,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 14,
+            "2" => 17,
+            "3" => 20,
+            "4" => 23,
+            "5" => 26,
+            "6" => 29,
+            "7" => 32,
+            "8" => 35,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 47,
+            "13" => 50,
+            "14" => 53,
+            "15" => 63
+        ]
+    ];
+
+    /**
+     * Values of the DEF main stat[stars][level]
+     */
+    const DEF = [
+        "1" => [
+            "0" => 3,
+            "1" => 6,
+            "2" => 9,
+            "3" => 12,
+            "4" => 15,
+            "5" => 18,
+            "6" => 21,
+            "7" => 24,
+            "8" => 27,
+            "9" => 30,
+            "10" => 33,
+            "11" => 36,
+            "12" => 39,
+            "13" => 42,
+            "14" => 45,
+            "15" => 54
+        ],
+        "2" => [
+            "0" => 5,
+            "1" => 9,
+            "2" => 13,
+            "3" => 17,
+            "4" => 21,
+            "5" => 25,
+            "6" => 29,
+            "7" => 33,
+            "8" => 37,
+            "9" => 41,
+            "10" => 45,
+            "11" => 49,
+            "12" => 53,
+            "13" => 57,
+            "14" => 61,
+            "15" => 73
+        ],
+        "3" => [
+            "0" => 7,
+            "1" => 12,
+            "2" => 17,
+            "3" => 22,
+            "4" => 27,
+            "5" => 32,
+            "6" => 37,
+            "7" => 42,
+            "8" => 47,
+            "9" => 52,
+            "10" => 57,
+            "11" => 62,
+            "12" => 67,
+            "13" => 72,
+            "14" => 77,
+            "15" => 92
+        ],
+        "4" => [
+            "0" => 10,
+            "1" => 16,
+            "2" => 22,
+            "3" => 28,
+            "4" => 34,
+            "5" => 40,
+            "6" => 46,
+            "7" => 52,
+            "8" => 58,
+            "9" => 64,
+            "10" => 70,
+            "11" => 76,
+            "12" => 82,
+            "13" => 88,
+            "14" => 94,
+            "15" => 112
+        ],
+        "5" => [
+            "0" => 15,
+            "1" => 22,
+            "2" => 29,
+            "3" => 36,
+            "4" => 43,
+            "5" => 50,
+            "6" => 57,
+            "7" => 64,
+            "8" => 71,
+            "9" => 78,
+            "10" => 85,
+            "11" => 92,
+            "12" => 99,
+            "13" => 106,
+            "14" => 113,
+            "15" => 135
+        ],
+        "6" => [
+            "0" => 22,
+            "1" => 30,
+            "2" => 38,
+            "3" => 46,
+            "4" => 54,
+            "5" => 62,
+            "6" => 70,
+            "7" => 78,
+            "8" => 86,
+            "9" => 94,
+            "10" => 102,
+            "11" => 110,
+            "12" => 118,
+            "13" => 126,
+            "14" => 134,
+            "15" => 160
+        ]
+    ];
+
+    /**
+     * Values of the DEF_P main stat[stars][level]
+     */
+    const DEF_P = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 24,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 36,
+            "15" => 43
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 10,
+            "2" => 12,
+            "3" => 15,
+            "4" => 17,
+            "5" => 20,
+            "6" => 22,
+            "7" => 24,
+            "8" => 27,
+            "9" => 29,
+            "10" => 32,
+            "11" => 34,
+            "12" => 37,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 14,
+            "2" => 17,
+            "3" => 20,
+            "4" => 23,
+            "5" => 26,
+            "6" => 29,
+            "7" => 32,
+            "8" => 35,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 47,
+            "13" => 50,
+            "14" => 53,
+            "15" => 63
+        ]
+    ];
+
+    /**
+     * Values of the SPD main stat[stars][level]
+     */
+    const SPD = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 3,
+            "1" => 4,
+            "2" => 5,
+            "3" => 6,
+            "4" => 8,
+            "5" => 9,
+            "6" => 10,
+            "7" => 12,
+            "8" => 13,
+            "9" => 14,
+            "10" => 16,
+            "11" => 17,
+            "12" => 18,
+            "13" => 19,
+            "14" => 21,
+            "15" => 25
+        ],
+        "4" => [
+            "0" => 4,
+            "1" => 5,
+            "2" => 7,
+            "3" => 8,
+            "4" => 10,
+            "5" => 11,
+            "6" => 13,
+            "7" => 14,
+            "8" => 16,
+            "9" => 17,
+            "10" => 19,
+            "11" => 20,
+            "12" => 22,
+            "13" => 23,
+            "14" => 25,
+            "15" => 30
+        ],
+        "5" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 15,
+            "6" => 17,
+            "7" => 19,
+            "8" => 21,
+            "9" => 23,
+            "10" => 25,
+            "11" => 27,
+            "12" => 29,
+            "13" => 31,
+            "14" => 33,
+            "15" => 39
+        ],
+        "6" => [
+            "0" => 7,
+            "1" => 9,
+            "2" => 11,
+            "3" => 13,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 21,
+            "8" => 23,
+            "9" => 25,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 35,
+            "15" => 42
+        ]
+    ];
+
+    /**
+     * Values of the CRR main stat[stars][level]
+     */
+    const CRR = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 3,
+            "1" => 5,
+            "2" => 7,
+            "3" => 9,
+            "4" => 11,
+            "5" => 13,
+            "6" => 15,
+            "7" => 17,
+            "8" => 19,
+            "9" => 21,
+            "10" => 23,
+            "11" => 25,
+            "12" => 27,
+            "13" => 29,
+            "14" => 31,
+            "15" => 37
+        ],
+        "4" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 11,
+            "4" => 13,
+            "5" => 15,
+            "6" => 17,
+            "7" => 19,
+            "8" => 22,
+            "9" => 24,
+            "10" => 26,
+            "11" => 28,
+            "12" => 30,
+            "13" => 33,
+            "14" => 35,
+            "15" => 41
+        ],
+        "5" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 10,
+            "3" => 12,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 22,
+            "8" => 24,
+            "9" => 27,
+            "10" => 29,
+            "11" => 31,
+            "12" => 34,
+            "13" => 36,
+            "14" => 39,
+            "15" => 47
+        ],
+        "6" => [
+            "0" => 7,
+            "1" => 10,
+            "2" => 13,
+            "3" => 16,
+            "4" => 19,
+            "5" => 22,
+            "6" => 25,
+            "7" => 28,
+            "8" => 31,
+            "9" => 34,
+            "10" => 37,
+            "11" => 40,
+            "12" => 43,
+            "13" => 46,
+            "14" => 49,
+            "15" => 58
+        ]
+    ];
+
+    /**
+     * Values of the CRD main stat[stars][level]
+     */
+    const CRD = [
+        "1" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "2" => [
+            "0" => 3,
+            "1" => 5,
+            "2" => 7,
+            "3" => 9,
+            "4" => 11,
+            "5" => 13,
+            "6" => 15,
+            "7" => 17,
+            "8" => 19,
+            "9" => 21,
+            "10" => 23,
+            "11" => 25,
+            "12" => 27,
+            "13" => 29,
+            "14" => 31,
+            "15" => 37
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 25,
+            "10" => 27,
+            "11" => 29,
+            "12" => 32,
+            "13" => 34,
+            "14" => 36,
+            "15" => 43
+        ],
+        "4" => [
+            "0" => 6,
+            "1" => 9,
+            "2" => 12,
+            "3" => 15,
+            "4" => 18,
+            "5" => 21,
+            "6" => 24,
+            "7" => 27,
+            "8" => 30,
+            "9" => 33,
+            "10" => 36,
+            "11" => 39,
+            "12" => 42,
+            "13" => 45,
+            "14" => 48,
+            "15" => 57
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 11,
+            "2" => 15,
+            "3" => 18,
+            "4" => 21,
+            "5" => 25,
+            "6" => 28,
+            "7" => 31,
+            "8" => 34,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 48,
+            "13" => 51,
+            "14" => 54,
+            "15" => 65
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 15,
+            "2" => 19,
+            "3" => 23,
+            "4" => 27,
+            "5" => 31,
+            "6" => 35,
+            "7" => 39,
+            "8" => 43,
+            "9" => 47,
+            "10" => 51,
+            "11" => 55,
+            "12" => 59,
+            "13" => 63,
+            "14" => 67,
+            "15" => 80
+        ]
+    ];
+
+    /**
+     * Values of the ACC main stat[stars][level]
+     */
+    const ACC = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 6,
+            "1" => 8,
+            "2" => 10,
+            "3" => 13,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 21,
+            "8" => 24,
+            "9" => 26,
+            "10" => 28,
+            "11" => 30,
+            "12" => 32,
+            "13" => 35,
+            "14" => 37,
+            "15" => 44
+        ],
+        "5" => [
+            "0" => 9,
+            "1" => 11,
+            "2" => 14,
+            "3" => 16,
+            "4" => 19,
+            "5" => 21,
+            "6" => 23,
+            "7" => 26,
+            "8" => 28,
+            "9" => 31,
+            "10" => 33,
+            "11" => 35,
+            "12" => 38,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 12,
+            "1" => 15,
+            "2" => 18,
+            "3" => 21,
+            "4" => 24,
+            "5" => 27,
+            "6" => 30,
+            "7" => 33,
+            "8" => 36,
+            "9" => 39,
+            "10" => 42,
+            "11" => 45,
+            "12" => 48,
+            "13" => 51,
+            "14" => 54,
+            "15" => 64
+        ]
+    ];
+
+    /**
+     * Values of the RES main stat[stars][level]
+     */
+    const RES = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 6,
+            "1" => 8,
+            "2" => 10,
+            "3" => 13,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 21,
+            "8" => 24,
+            "9" => 26,
+            "10" => 28,
+            "11" => 30,
+            "12" => 32,
+            "13" => 35,
+            "14" => 37,
+            "15" => 44
+        ],
+        "5" => [
+            "0" => 9,
+            "1" => 11,
+            "2" => 14,
+            "3" => 16,
+            "4" => 19,
+            "5" => 21,
+            "6" => 23,
+            "7" => 26,
+            "8" => 28,
+            "9" => 31,
+            "10" => 33,
+            "11" => 35,
+            "12" => 38,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 12,
+            "1" => 15,
+            "2" => 18,
+            "3" => 21,
+            "4" => 24,
+            "5" => 27,
+            "6" => 30,
+            "7" => 33,
+            "8" => 36,
+            "9" => 39,
+            "10" => 42,
+            "11" => 45,
+            "12" => 48,
+            "13" => 51,
+            "14" => 54,
+            "15" => 64
+        ]
+    ];
+};
+
+/**
+ * Rune main stat values constants.
+ *
+ * Includes the value of the main stats for type, stars, and level.
+ *
+ * @category Data
+ */
+final class RUNE_SUBSTAT_MAX_VALUES{
+
+    const SUBSTAT = [
+        RUNE_STAT_ID::HP => [
+            "1" => 300,
+            "2" => 525,
+            "3" => 825,
+            "4" => 1125,
+            "5" => 1500,
+            "6" => 1875
+        ],
+        RUNE_STAT_ID::HP_P => [
+            "1" => 10,
+            "2" => 15,
+            "3" => 25,
+            "4" => 30,
+            "5" => 35,
+            "6" => 40
+        ],
+        RUNE_STAT_ID::ATK => [
+            "1" => 20,
+            "2" => 25,
+            "3" => 40,
+            "4" => 50,
+            "5" => 75,
+            "6" => 100
+        ],
+        RUNE_STAT_ID::ATK_P => [
+            "1" => 10,
+            "2" => 15,
+            "3" => 25,
+            "4" => 30,
+            "5" => 35,
+            "6" => 40
+        ],
+        RUNE_STAT_ID::DEF => [
+            "1" => 20,
+            "2" => 25,
+            "3" => 40,
+            "4" => 50,
+            "5" => 75,
+            "6" => 100
+        ],
+        RUNE_STAT_ID::DEF_P => [
+            "1" => 10,
+            "2" => 15,
+            "3" => 25,
+            "4" => 30,
+            "5" => 35,
+            "6" => 40
+        ],
+        RUNE_STAT_ID::SPD => [
+            "1" => 5,
+            "2" => 10,
+            "3" => 15,
+            "4" => 20,
+            "5" => 25,
+            "6" => 30
+        ],
+        RUNE_STAT_ID::CRR => [
+            "1" => 5,
+            "2" => 10,
+            "3" => 15,
+            "4" => 20,
+            "5" => 25,
+            "6" => 30
+        ],
+        RUNE_STAT_ID::CRD => [
+            "1" => 10,
+            "2" => 15,
+            "3" => 20,
+            "4" => 25,
+            "5" => 30,
+            "6" => 35
+        ],
+        RUNE_STAT_ID::RES => [
+            "1" => 10,
+            "2" => 15,
+            "3" => 25,
+            "4" => 30,
+            "5" => 35,
+            "6" => 40
+        ],
+        RUNE_STAT_ID::ACC => [
+            "1" => 10,
+            "2" => 15,
+            "3" => 25,
+            "4" => 30,
+            "5" => 35,
+            "6" => 40
+        ]
+    ];
+
+    /**
+     * Values of the HP main stat [stars][level]
+     */
+    const HP = [
+        "1" => [
+            "0" => 40,
+            "1" => 85,
+            "2" => 130,
+            "3" => 175,
+            "4" => 220,
+            "5" => 265,
+            "6" => 310,
+            "7" => 355,
+            "8" => 400,
+            "9" => 445,
+            "10" => 490,
+            "11" => 535,
+            "12" => 580,
+            "13" => 625,
+            "14" => 670,
+            "15" => 804
+        ],
+        "2" => [
+            "0" => 70,
+            "1" => 130,
+            "2" => 190,
+            "3" => 250,
+            "4" => 310,
+            "5" => 370,
+            "6" => 430,
+            "7" => 490,
+            "8" => 550,
+            "9" => 610,
+            "10" => 670,
+            "11" => 730,
+            "12" => 790,
+            "13" => 850,
+            "14" => 910,
+            "15" => 1092
+        ],
+        "3" => [
+            "0" => 100,
+            "1" => 175,
+            "2" => 250,
+            "3" => 325,
+            "4" => 400,
+            "5" => 475,
+            "6" => 550,
+            "7" => 625,
+            "8" => 700,
+            "9" => 775,
+            "10" => 850,
+            "11" => 925,
+            "12" => 1000,
+            "13" => 1075,
+            "14" => 1150,
+            "15" => 1380
+        ],
+        "4" => [
+            "0" => 160,
+            "1" => 250,
+            "2" => 340,
+            "3" => 430,
+            "4" => 520,
+            "5" => 610,
+            "6" => 700,
+            "7" => 790,
+            "8" => 880,
+            "9" => 970,
+            "10" => 1060,
+            "11" => 1150,
+            "12" => 1240,
+            "13" => 1330,
+            "14" => 1420,
+            "15" => 1704
+        ],
+        "5" => [
+            "0" => 270,
+            "1" => 375,
+            "2" => 480,
+            "3" => 585,
+            "4" => 690,
+            "5" => 795,
+            "6" => 900,
+            "7" => 1005,
+            "8" => 1110,
+            "9" => 1215,
+            "10" => 1320,
+            "11" => 1425,
+            "12" => 1530,
+            "13" => 1635,
+            "14" => 1740,
+            "15" => 2088
+        ],
+        "6" => [
+            "0" => 360,
+            "1" => 480,
+            "2" => 600,
+            "3" => 720,
+            "4" => 840,
+            "5" => 960,
+            "6" => 1080,
+            "7" => 1200,
+            "8" => 1320,
+            "9" => 1440,
+            "10" => 1560,
+            "11" => 1680,
+            "12" => 1800,
+            "13" => 1920,
+            "14" => 2040,
+            "15" => 2448
+        ]
+    ];
+
+    /**
+     * Values of the HP_P main stat[stars][level]
+     */
+    const HP_P = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 24,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 36,
+            "15" => 43
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 10,
+            "2" => 12,
+            "3" => 15,
+            "4" => 17,
+            "5" => 20,
+            "6" => 22,
+            "7" => 24,
+            "8" => 27,
+            "9" => 29,
+            "10" => 32,
+            "11" => 34,
+            "12" => 37,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 14,
+            "2" => 17,
+            "3" => 20,
+            "4" => 23,
+            "5" => 26,
+            "6" => 29,
+            "7" => 32,
+            "8" => 35,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 47,
+            "13" => 50,
+            "14" => 53,
+            "15" => 63
+        ]
+    ];
+
+    /**
+     * Values of the ATK main stat[stars][level]
+     */
+    const ATK = [
+        "1" => [
+            "0" => 3,
+            "1" => 6,
+            "2" => 9,
+            "3" => 12,
+            "4" => 15,
+            "5" => 18,
+            "6" => 21,
+            "7" => 24,
+            "8" => 27,
+            "9" => 30,
+            "10" => 33,
+            "11" => 36,
+            "12" => 39,
+            "13" => 42,
+            "14" => 45,
+            "15" => 54
+        ],
+        "2" => [
+            "0" => 5,
+            "1" => 9,
+            "2" => 13,
+            "3" => 17,
+            "4" => 21,
+            "5" => 25,
+            "6" => 29,
+            "7" => 33,
+            "8" => 37,
+            "9" => 41,
+            "10" => 45,
+            "11" => 49,
+            "12" => 53,
+            "13" => 57,
+            "14" => 61,
+            "15" => 73
+        ],
+        "3" => [
+            "0" => 7,
+            "1" => 12,
+            "2" => 17,
+            "3" => 22,
+            "4" => 27,
+            "5" => 32,
+            "6" => 37,
+            "7" => 42,
+            "8" => 47,
+            "9" => 52,
+            "10" => 57,
+            "11" => 62,
+            "12" => 67,
+            "13" => 72,
+            "14" => 77,
+            "15" => 92
+        ],
+        "4" => [
+            "0" => 10,
+            "1" => 16,
+            "2" => 22,
+            "3" => 28,
+            "4" => 34,
+            "5" => 40,
+            "6" => 46,
+            "7" => 52,
+            "8" => 58,
+            "9" => 64,
+            "10" => 70,
+            "11" => 76,
+            "12" => 82,
+            "13" => 88,
+            "14" => 94,
+            "15" => 112
+        ],
+        "5" => [
+            "0" => 15,
+            "1" => 22,
+            "2" => 29,
+            "3" => 36,
+            "4" => 43,
+            "5" => 50,
+            "6" => 57,
+            "7" => 64,
+            "8" => 71,
+            "9" => 78,
+            "10" => 85,
+            "11" => 92,
+            "12" => 99,
+            "13" => 106,
+            "14" => 113,
+            "15" => 135
+        ],
+        "6" => [
+            "0" => 22,
+            "1" => 30,
+            "2" => 38,
+            "3" => 46,
+            "4" => 54,
+            "5" => 62,
+            "6" => 70,
+            "7" => 78,
+            "8" => 86,
+            "9" => 94,
+            "10" => 102,
+            "11" => 110,
+            "12" => 118,
+            "13" => 126,
+            "14" => 134,
+            "15" => 160
+        ]
+    ];
+
+    /**
+     * Values of the ATK_P main stat[stars][level]
+     */
+    const ATK_P = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 24,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 36,
+            "15" => 43
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 10,
+            "2" => 12,
+            "3" => 15,
+            "4" => 17,
+            "5" => 20,
+            "6" => 22,
+            "7" => 24,
+            "8" => 27,
+            "9" => 29,
+            "10" => 32,
+            "11" => 34,
+            "12" => 37,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 14,
+            "2" => 17,
+            "3" => 20,
+            "4" => 23,
+            "5" => 26,
+            "6" => 29,
+            "7" => 32,
+            "8" => 35,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 47,
+            "13" => 50,
+            "14" => 53,
+            "15" => 63
+        ]
+    ];
+
+    /**
+     * Values of the DEF main stat[stars][level]
+     */
+    const DEF = [
+        "1" => [
+            "0" => 3,
+            "1" => 6,
+            "2" => 9,
+            "3" => 12,
+            "4" => 15,
+            "5" => 18,
+            "6" => 21,
+            "7" => 24,
+            "8" => 27,
+            "9" => 30,
+            "10" => 33,
+            "11" => 36,
+            "12" => 39,
+            "13" => 42,
+            "14" => 45,
+            "15" => 54
+        ],
+        "2" => [
+            "0" => 5,
+            "1" => 9,
+            "2" => 13,
+            "3" => 17,
+            "4" => 21,
+            "5" => 25,
+            "6" => 29,
+            "7" => 33,
+            "8" => 37,
+            "9" => 41,
+            "10" => 45,
+            "11" => 49,
+            "12" => 53,
+            "13" => 57,
+            "14" => 61,
+            "15" => 73
+        ],
+        "3" => [
+            "0" => 7,
+            "1" => 12,
+            "2" => 17,
+            "3" => 22,
+            "4" => 27,
+            "5" => 32,
+            "6" => 37,
+            "7" => 42,
+            "8" => 47,
+            "9" => 52,
+            "10" => 57,
+            "11" => 62,
+            "12" => 67,
+            "13" => 72,
+            "14" => 77,
+            "15" => 92
+        ],
+        "4" => [
+            "0" => 10,
+            "1" => 16,
+            "2" => 22,
+            "3" => 28,
+            "4" => 34,
+            "5" => 40,
+            "6" => 46,
+            "7" => 52,
+            "8" => 58,
+            "9" => 64,
+            "10" => 70,
+            "11" => 76,
+            "12" => 82,
+            "13" => 88,
+            "14" => 94,
+            "15" => 112
+        ],
+        "5" => [
+            "0" => 15,
+            "1" => 22,
+            "2" => 29,
+            "3" => 36,
+            "4" => 43,
+            "5" => 50,
+            "6" => 57,
+            "7" => 64,
+            "8" => 71,
+            "9" => 78,
+            "10" => 85,
+            "11" => 92,
+            "12" => 99,
+            "13" => 106,
+            "14" => 113,
+            "15" => 135
+        ],
+        "6" => [
+            "0" => 22,
+            "1" => 30,
+            "2" => 38,
+            "3" => 46,
+            "4" => 54,
+            "5" => 62,
+            "6" => 70,
+            "7" => 78,
+            "8" => 86,
+            "9" => 94,
+            "10" => 102,
+            "11" => 110,
+            "12" => 118,
+            "13" => 126,
+            "14" => 134,
+            "15" => 160
+        ]
+    ];
+
+    /**
+     * Values of the DEF_P main stat[stars][level]
+     */
+    const DEF_P = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 24,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 36,
+            "15" => 43
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 10,
+            "2" => 12,
+            "3" => 15,
+            "4" => 17,
+            "5" => 20,
+            "6" => 22,
+            "7" => 24,
+            "8" => 27,
+            "9" => 29,
+            "10" => 32,
+            "11" => 34,
+            "12" => 37,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 14,
+            "2" => 17,
+            "3" => 20,
+            "4" => 23,
+            "5" => 26,
+            "6" => 29,
+            "7" => 32,
+            "8" => 35,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 47,
+            "13" => 50,
+            "14" => 53,
+            "15" => 63
+        ]
+    ];
+
+    /**
+     * Values of the SPD main stat[stars][level]
+     */
+    const SPD = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 3,
+            "1" => 4,
+            "2" => 5,
+            "3" => 6,
+            "4" => 8,
+            "5" => 9,
+            "6" => 10,
+            "7" => 12,
+            "8" => 13,
+            "9" => 14,
+            "10" => 16,
+            "11" => 17,
+            "12" => 18,
+            "13" => 19,
+            "14" => 21,
+            "15" => 25
+        ],
+        "4" => [
+            "0" => 4,
+            "1" => 5,
+            "2" => 7,
+            "3" => 8,
+            "4" => 10,
+            "5" => 11,
+            "6" => 13,
+            "7" => 14,
+            "8" => 16,
+            "9" => 17,
+            "10" => 19,
+            "11" => 20,
+            "12" => 22,
+            "13" => 23,
+            "14" => 25,
+            "15" => 30
+        ],
+        "5" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 15,
+            "6" => 17,
+            "7" => 19,
+            "8" => 21,
+            "9" => 23,
+            "10" => 25,
+            "11" => 27,
+            "12" => 29,
+            "13" => 31,
+            "14" => 33,
+            "15" => 39
+        ],
+        "6" => [
+            "0" => 7,
+            "1" => 9,
+            "2" => 11,
+            "3" => 13,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 21,
+            "8" => 23,
+            "9" => 25,
+            "10" => 27,
+            "11" => 29,
+            "12" => 31,
+            "13" => 33,
+            "14" => 35,
+            "15" => 42
+        ]
+    ];
+
+    /**
+     * Values of the CRR main stat[stars][level]
+     */
+    const CRR = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 3,
+            "1" => 5,
+            "2" => 7,
+            "3" => 9,
+            "4" => 11,
+            "5" => 13,
+            "6" => 15,
+            "7" => 17,
+            "8" => 19,
+            "9" => 21,
+            "10" => 23,
+            "11" => 25,
+            "12" => 27,
+            "13" => 29,
+            "14" => 31,
+            "15" => 37
+        ],
+        "4" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 11,
+            "4" => 13,
+            "5" => 15,
+            "6" => 17,
+            "7" => 19,
+            "8" => 22,
+            "9" => 24,
+            "10" => 26,
+            "11" => 28,
+            "12" => 30,
+            "13" => 33,
+            "14" => 35,
+            "15" => 41
+        ],
+        "5" => [
+            "0" => 5,
+            "1" => 7,
+            "2" => 10,
+            "3" => 12,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 22,
+            "8" => 24,
+            "9" => 27,
+            "10" => 29,
+            "11" => 31,
+            "12" => 34,
+            "13" => 36,
+            "14" => 39,
+            "15" => 47
+        ],
+        "6" => [
+            "0" => 7,
+            "1" => 10,
+            "2" => 13,
+            "3" => 16,
+            "4" => 19,
+            "5" => 22,
+            "6" => 25,
+            "7" => 28,
+            "8" => 31,
+            "9" => 34,
+            "10" => 37,
+            "11" => 40,
+            "12" => 43,
+            "13" => 46,
+            "14" => 49,
+            "15" => 58
+        ]
+    ];
+
+    /**
+     * Values of the CRD main stat[stars][level]
+     */
+    const CRD = [
+        "1" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "2" => [
+            "0" => 3,
+            "1" => 5,
+            "2" => 7,
+            "3" => 9,
+            "4" => 11,
+            "5" => 13,
+            "6" => 15,
+            "7" => 17,
+            "8" => 19,
+            "9" => 21,
+            "10" => 23,
+            "11" => 25,
+            "12" => 27,
+            "13" => 29,
+            "14" => 31,
+            "15" => 37
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 9,
+            "3" => 11,
+            "4" => 13,
+            "5" => 16,
+            "6" => 18,
+            "7" => 20,
+            "8" => 22,
+            "9" => 25,
+            "10" => 27,
+            "11" => 29,
+            "12" => 32,
+            "13" => 34,
+            "14" => 36,
+            "15" => 43
+        ],
+        "4" => [
+            "0" => 6,
+            "1" => 9,
+            "2" => 12,
+            "3" => 15,
+            "4" => 18,
+            "5" => 21,
+            "6" => 24,
+            "7" => 27,
+            "8" => 30,
+            "9" => 33,
+            "10" => 36,
+            "11" => 39,
+            "12" => 42,
+            "13" => 45,
+            "14" => 48,
+            "15" => 57
+        ],
+        "5" => [
+            "0" => 8,
+            "1" => 11,
+            "2" => 15,
+            "3" => 18,
+            "4" => 21,
+            "5" => 25,
+            "6" => 28,
+            "7" => 31,
+            "8" => 34,
+            "9" => 38,
+            "10" => 41,
+            "11" => 44,
+            "12" => 48,
+            "13" => 51,
+            "14" => 54,
+            "15" => 65
+        ],
+        "6" => [
+            "0" => 11,
+            "1" => 15,
+            "2" => 19,
+            "3" => 23,
+            "4" => 27,
+            "5" => 31,
+            "6" => 35,
+            "7" => 39,
+            "8" => 43,
+            "9" => 47,
+            "10" => 51,
+            "11" => 55,
+            "12" => 59,
+            "13" => 63,
+            "14" => 67,
+            "15" => 80
+        ]
+    ];
+
+    /**
+     * Values of the ACC main stat[stars][level]
+     */
+    const ACC = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 6,
+            "1" => 8,
+            "2" => 10,
+            "3" => 13,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 21,
+            "8" => 24,
+            "9" => 26,
+            "10" => 28,
+            "11" => 30,
+            "12" => 32,
+            "13" => 35,
+            "14" => 37,
+            "15" => 44
+        ],
+        "5" => [
+            "0" => 9,
+            "1" => 11,
+            "2" => 14,
+            "3" => 16,
+            "4" => 19,
+            "5" => 21,
+            "6" => 23,
+            "7" => 26,
+            "8" => 28,
+            "9" => 31,
+            "10" => 33,
+            "11" => 35,
+            "12" => 38,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 12,
+            "1" => 15,
+            "2" => 18,
+            "3" => 21,
+            "4" => 24,
+            "5" => 27,
+            "6" => 30,
+            "7" => 33,
+            "8" => 36,
+            "9" => 39,
+            "10" => 42,
+            "11" => 45,
+            "12" => 48,
+            "13" => 51,
+            "14" => 54,
+            "15" => 64
+        ]
+    ];
+
+    /**
+     * Values of the RES main stat[stars][level]
+     */
+    const RES = [
+        "1" => [
+            "0" => 1,
+            "1" => 2,
+            "2" => 3,
+            "3" => 4,
+            "4" => 5,
+            "5" => 6,
+            "6" => 7,
+            "7" => 8,
+            "8" => 9,
+            "9" => 10,
+            "10" => 11,
+            "11" => 12,
+            "12" => 13,
+            "13" => 14,
+            "14" => 15,
+            "15" => 18
+        ],
+        "2" => [
+            "0" => 2,
+            "1" => 3,
+            "2" => 4,
+            "3" => 5,
+            "4" => 6,
+            "5" => 7,
+            "6" => 8,
+            "7" => 9,
+            "8" => 10,
+            "9" => 11,
+            "10" => 12,
+            "11" => 13,
+            "12" => 14,
+            "13" => 15,
+            "14" => 16,
+            "15" => 19
+        ],
+        "3" => [
+            "0" => 4,
+            "1" => 6,
+            "2" => 8,
+            "3" => 10,
+            "4" => 12,
+            "5" => 14,
+            "6" => 16,
+            "7" => 18,
+            "8" => 20,
+            "9" => 22,
+            "10" => 24,
+            "11" => 26,
+            "12" => 28,
+            "13" => 30,
+            "14" => 32,
+            "15" => 38
+        ],
+        "4" => [
+            "0" => 6,
+            "1" => 8,
+            "2" => 10,
+            "3" => 13,
+            "4" => 15,
+            "5" => 17,
+            "6" => 19,
+            "7" => 21,
+            "8" => 24,
+            "9" => 26,
+            "10" => 28,
+            "11" => 30,
+            "12" => 32,
+            "13" => 35,
+            "14" => 37,
+            "15" => 44
+        ],
+        "5" => [
+            "0" => 9,
+            "1" => 11,
+            "2" => 14,
+            "3" => 16,
+            "4" => 19,
+            "5" => 21,
+            "6" => 23,
+            "7" => 26,
+            "8" => 28,
+            "9" => 31,
+            "10" => 33,
+            "11" => 35,
+            "12" => 38,
+            "13" => 40,
+            "14" => 43,
+            "15" => 51
+        ],
+        "6" => [
+            "0" => 12,
+            "1" => 15,
+            "2" => 18,
+            "3" => 21,
+            "4" => 24,
+            "5" => 27,
+            "6" => 30,
+            "7" => 33,
+            "8" => 36,
+            "9" => 39,
+            "10" => 42,
+            "11" => 45,
+            "12" => 48,
+            "13" => 51,
+            "14" => 54,
+            "15" => 64
+        ]
+    ];
+};
+
+/**
+ * Artifact types.
+ *
+ * The two types of artifacts.
+ */
+final class ARTIFACT_TYPE{
+
+    /**
+     * Elemental attribute.
+     */
+    const ELEMENT = 0;
+
+    /**
+     * Type artifact.
+     */
+    const ARCHETYPE = 1;
+ }
+
+/**
+ * Artifact stat constants.
+ *
+ * The stats an artifact can have. For unit stats, see{@see $STAT_ID}.
+ *
+ * @category Data
+ */
+final class ARTIFACT_STAT_ID{
+
+    /**
+     * HP.
+     */
+    const HP = 100;
+
+    /**
+     * ATK.
+     */
+    const ATK = 101;
+
+    /**
+     * DEF.
+     */
+    const DEF = 102;
+}
+
+/**
+ * Rune (and other items) quality constants.
+ *
+ * @category Data
+ */
+final class QUALITY_ID{
+
+    /**
+     * Normal.
+     */
+    const NORMAL = 1;
+
+    /**
+     * Magic.
+     */
+    const MAGIC = 2;
+
+    /**
+     * Rare.
+     */
+    const RARE = 3;
+
+    /**
+     * Hero.
+     */
+    const HERO = 4;
+
+    /**
+     * Legend.
+     */
+    const LEGEND = 5;
+};
+
+/**
+ * Craft items constants.
+ *
+ * @category Data
+ */
+final class CRAFT_ID{
+
+    /**
+     * Enchant Gem.
+     */
+    const ENCHANT_GEM = 1;
+
+    /**
+     * Grindstone.
+     */
+    const GRINDSTONE = 2;
+
+    /**
+     * Immemorial Gem.
+     */
+    const IMMEMORIAL_GEM = 3;
+
+    /**
+     * Immemorial Grindstone.
+     */
+    const IMMEMORIAL_GRINDSTONE = 4;
+};
+
+/**
+ * Guild member rank constants.
+ *
+ * @category Data
+ */
+final class GUILD_MEMBER_GRADE_ID{
+
+    /**
+     * Leader.
+     */
+    const LEADER = 1;
+
+    /**
+     * Viceleader.
+     */
+    const VICELEADER = 3;
+
+    /**
+     * Normal member.
+     */
+    const NORMAL = 2;
+};
+
+/**
+ * Arena ranking constant.
+ *
+ * Each element contains the minimum points for a rank. To calculate rank,
+ * @{see ARENA_RANKING_RANK} is neeeded too.
+ *
+ * @category Data
+ */
+final class ARENA_RANKING_POINTS{
+
+    /**
+     * Beginer.
+     */
+    const BEGINER = 0;
+
+    /**
+     * Challenger 1.
+     */
+    const CHALLENGER_1 = 900;
+
+    /**
+     * Challenger 2.
+     */
+    const CHALLENGER_2 = 1000;
+
+    /**
+     * Challenger 3.
+     */
+    const CHALLENGER_3 = 1100;
 
     /**
-     * Artifact effectslot constants.
-     *
-     * Includes all the effect slots an artifact can have.
-     *
-     * @category Data
-     */
-    final class ARTIFACT_EFFECT_SLOT_ID{
+     * Fighter 1.
+     */
+    const FIGHTER_1 = 1200;
+
+    /**
+     * Fighter 2.
+     */
+    const FIGHTER_2 = 1300;
+
+    /**
+     * Fighter 3.
+     */
+    const FIGHTER_3 = 1400;
+
+    /**
+     * Conqueror 1.
+     */
+    const CONQUEROR_1 = 1500;
+
+    /**
+     * Conqueror 2.
+     */
+    const CONQUEROR_2 = 1600;
+
+    /**
+     * Conqueror 3.
+     */
+    const CONQUEROR_3 = 1700;
+
+    /**
+     * Guardian 1.
+     */
+    const GUARDIAN_1 = 1700;
+
+    /**
+     * Guardian 2.
+     */
+    const GUARDIAN_2 = 1700;
+
+    /**
+     * Guardian 3.
+     */
+    const GUARDIAN_3 = 1700;
+
+    /**
+     * Legend.
+     */
+    const LEGEND = 1700;
+};
+
+/**
+ * Arena ranking constant.
+ *
+ * Each element contains the minimum top needed for a rank. A null value
+ * indicates that there is no top requeriment.To calculate rank,
+ * @{see ARENA_RANKING_POINTS} is neeeded too.
+ *
+ * @category Data
+ */
+final class ARENA_RANKING_RANK{
+
+    /**
+     * Beginer.
+     */
+    const BEGINER = null;
+
+    /**
+     * Challenger 1.
+     */
+    const CHALLENGER_1 = null;
+
+    /**
+     * Challenger 2.
+     */
+    const CHALLENGER_2 = null;
+
+    /**
+     * Challenger 3.
+     */
+    const CHALLENGER_3 = null;
+
+    /**
+     * Fighter 1.
+     */
+    const FIGHTER_1 = null;
+
+    /**
+     * Fighter 2.
+     */
+    const FIGHTER_2 = null;
+
+    /**
+     * Fighter 3.
+     */
+    const FIGHTER_3 = null;
+
+    /**
+     * Conqueror 1.
+     */
+    const CONQUEROR_1 = 10000;
+
+    /**
+     * Conqueror 2.
+     */
+    const CONQUEROR_2 = 3000;
+
+    /**
+     * Conqueror 3.
+     */
+    const CONQUEROR_3 = 1000;
+
+    /**
+     * Guardian 1.
+     */
+    const GUARDIAN_1 = 300;
+
+    /**
+     * Guardian 2.
+     */
+    const GUARDIAN_2 = 100;
 
-        /**
-         * Effect 1.
-         */
-        const EFFECT_1 = 1;
+    /**
+     * Guardian 3.
+     */
+    const GUARDIAN_3 = 30;
+
+    /**
+     * Legend.
+     */
+    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;
+}
 
-        /**
-         * Effect 2.
-         */
-        const EFFECT_2 = 2;
+/**
+ * World Boss rank constant.
+ *
+ * @category Data
+ */
+final class WORLD_BOSS_RANK_ID{
 
-        /**
-         * Effect 3.
-         */
-        const EFFECT_3 = 3;
+    /**
+     * 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;
+ * 
+ * @category Data
+ */
+final class FILTER{
+
+    /**
+     * Default values for the fusion filters.
+     */
+    const FUSION = [
+        "PRODUCT" => 0
+    ];
+
+    /**
+     * Default values for the rune filters.
+     */
+    const RUNE = [
+        "TYPE" => [],
+        "MAIN" => [],
+        "SUB" => [],
+        "SLOT" => [],
+        "MIN_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_STARS" => 1,
+        "MAX_STARS" => 6,
+        "MIN_LEVEL" => 0,
+        "MAX_LEVEL" => 15,
+        "MIN_EFFICIENCY" => 0,
+        "MAX_EFFICIENCY" => 100,
+        "MIN_MAX_EFFICIENCY" => 0,
+        "MAX_MAX_EFFICIENCY" => 100,
+        "ASSIGNED" => 1,
+        "GROUP" => "SLOT"
+    ];
 
-        /**
-         * Effect 4.
-         */
-        const EFFECT_4 = 4;
+    /**
+     * Default values for the artifact filters.
+     */
+    const ARTIFACT = [
+        "TYPE" => 0,
+        "ELEMENT" => [],
+        "ARCHETYPE" => [],
+        "MAIN" => [],
+        "MIN_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
+        "MIN_LEVEL" => 0,
+        "MAX_LEVEL" => 15,
+        "MIN_EFFICIENCY" => 0,
+        "MAX_EFFICIENCY" => 100,
+        "MIN_MAX_EFFICIENCY" => 0,
+        "MAX_MAX_EFFICIENCY" => 100,
+        "ASSIGNED" => 1
+    ];
 
-    }
+    /**
+     * Default values for the enchantment filters.
+     */
+    const ENCHANTMENT = [
+        "TYPE" => [],
+        "RUNE" => [],
+        "STAT" => [],
+        "MIN_QUALITY" => QUALITY_ID::NORMAL,
+        "MAX_QUALITY" => QUALITY_ID::LEGEND,
+    ];
 
+    /**
+     * Default values for the run filters.
+     */
+    const RUN = [
+        "AREA_TYPE" => 0,
+        "AREA" => 0,
+        "STAGE" => 0,
+        "DIFFICULTY" => 0,
+        "DATE_MIN" => null,
+        "DATE_MAX" => null,
+        "DEFEAT" => false,
+        "HELPER" => false,
+        "NUMBER" => 20,
+    ];
 
     /**
-     * Application modes.
-     *
-     * Modes to use RTA configurations or normal configuration.
-     *
-     * @category Data
+     * Default values for the rune team filters.
      */
-    final class GAME_MODE_ID{
+    const TEAM = [
+        "NAME" => "",
+        "AREA" => null
+    ];
 
-        /**
-         * Normal mode.
-         */
-        const NORMAL = 0;
-
-        /**
-         * RTA mode.
-         */
-        const RTA = 1;
-
-    }
-
-
-    /**
-     * Rune stat constants.
-     *
-     * Includes all stats a rune can have. For unit stats, see{@see $STAT_ID}.
-     *
-     * @category Data
-     */
-    final class RUNE_STAT_ID{
-
-        /**
-         * HP (flat).
-         */
-        const HP = 1;
-
-        /**
-         * HP (percent).
-         */
-        const HP_P = 2;
-
-        /**
-         * Attack  (flat).
-         */
-        const ATK = 3;
-
-        /**
-         * Attack (percent).
-         */
-        const ATK_P = 4;
-
-        /**
-         * Defense  (flat).
-         */
-        const DEF = 5;
-
-        /**
-         * Defense (percent).
-         */
-        const DEF_P = 6;
-
-        /**
-         * Speed.
-         */
-        const SPD = 8;
-
-        /**
-         * Critical Rate.
-         */
-        const CRR = 9;
-
-        /**
-         * Critical Damage.
-         */
-        const CRD = 10;
-
-        /**
-         * Resistance.
-         */
-        const RES = 11;
-
-        /**
-         * Accuracy.
-         */
-        const ACC = 12;
-    };
-
-
-    /**
-     * Rune main stat values constants.
-     *
-     * Includes the value of the main stats for type, stars, and level.
-     *
-     * @category Data
-     */
-    final class RUNE_STAT_VALUES{
-
-        /**
-         * Values of the HP main stat [stars][level]
-         */
-        const HP = [
-            "1" => [
-                "0" => 40,
-                "1" => 85,
-                "2" => 130,
-                "3" => 175,
-                "4" => 220,
-                "5" => 265,
-                "6" => 310,
-                "7" => 355,
-                "8" => 400,
-                "9" => 445,
-                "10" => 490,
-                "11" => 535,
-                "12" => 580,
-                "13" => 625,
-                "14" => 670,
-                "15" => 804
-            ],
-            "2" => [
-                "0" => 70,
-                "1" => 130,
-                "2" => 190,
-                "3" => 250,
-                "4" => 310,
-                "5" => 370,
-                "6" => 430,
-                "7" => 490,
-                "8" => 550,
-                "9" => 610,
-                "10" => 670,
-                "11" => 730,
-                "12" => 790,
-                "13" => 850,
-                "14" => 910,
-                "15" => 1092
-            ],
-            "3" => [
-                "0" => 100,
-                "1" => 175,
-                "2" => 250,
-                "3" => 325,
-                "4" => 400,
-                "5" => 475,
-                "6" => 550,
-                "7" => 625,
-                "8" => 700,
-                "9" => 775,
-                "10" => 850,
-                "11" => 925,
-                "12" => 1000,
-                "13" => 1075,
-                "14" => 1150,
-                "15" => 1380
-            ],
-            "4" => [
-                "0" => 160,
-                "1" => 250,
-                "2" => 340,
-                "3" => 430,
-                "4" => 520,
-                "5" => 610,
-                "6" => 700,
-                "7" => 790,
-                "8" => 880,
-                "9" => 970,
-                "10" => 1060,
-                "11" => 1150,
-                "12" => 1240,
-                "13" => 1330,
-                "14" => 1420,
-                "15" => 1704
-            ],
-            "5" => [
-                "0" => 270,
-                "1" => 375,
-                "2" => 480,
-                "3" => 585,
-                "4" => 690,
-                "5" => 795,
-                "6" => 900,
-                "7" => 1005,
-                "8" => 1110,
-                "9" => 1215,
-                "10" => 1320,
-                "11" => 1425,
-                "12" => 1530,
-                "13" => 1635,
-                "14" => 1740,
-                "15" => 2088
-            ],
-            "6" => [
-                "0" => 360,
-                "1" => 480,
-                "2" => 600,
-                "3" => 720,
-                "4" => 840,
-                "5" => 960,
-                "6" => 1080,
-                "7" => 1200,
-                "8" => 1320,
-                "9" => 1440,
-                "10" => 1560,
-                "11" => 1680,
-                "12" => 1800,
-                "13" => 1920,
-                "14" => 2040,
-                "15" => 2448
-            ]
-        ];
-        
-        /**
-         * Values of the HP_P main stat[stars][level]
-         */
-        const HP_P = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 24,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 36,
-                "15" => 43
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 10,
-                "2" => 12,
-                "3" => 15,
-                "4" => 17,
-                "5" => 20,
-                "6" => 22,
-                "7" => 24,
-                "8" => 27,
-                "9" => 29,
-                "10" => 32,
-                "11" => 34,
-                "12" => 37,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 14,
-                "2" => 17,
-                "3" => 20,
-                "4" => 23,
-                "5" => 26,
-                "6" => 29,
-                "7" => 32,
-                "8" => 35,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 47,
-                "13" => 50,
-                "14" => 53,
-                "15" => 63
-            ]
-        ];
-
-        /**
-         * Values of the ATK main stat[stars][level]
-         */
-        const ATK = [
-            "1" => [
-                "0" => 3,
-                "1" => 6,
-                "2" => 9,
-                "3" => 12,
-                "4" => 15,
-                "5" => 18,
-                "6" => 21,
-                "7" => 24,
-                "8" => 27,
-                "9" => 30,
-                "10" => 33,
-                "11" => 36,
-                "12" => 39,
-                "13" => 42,
-                "14" => 45,
-                "15" => 54
-            ],
-            "2" => [
-                "0" => 5,
-                "1" => 9,
-                "2" => 13,
-                "3" => 17,
-                "4" => 21,
-                "5" => 25,
-                "6" => 29,
-                "7" => 33,
-                "8" => 37,
-                "9" => 41,
-                "10" => 45,
-                "11" => 49,
-                "12" => 53,
-                "13" => 57,
-                "14" => 61,
-                "15" => 73
-            ],
-            "3" => [
-                "0" => 7,
-                "1" => 12,
-                "2" => 17,
-                "3" => 22,
-                "4" => 27,
-                "5" => 32,
-                "6" => 37,
-                "7" => 42,
-                "8" => 47,
-                "9" => 52,
-                "10" => 57,
-                "11" => 62,
-                "12" => 67,
-                "13" => 72,
-                "14" => 77,
-                "15" => 92
-            ],
-            "4" => [
-                "0" => 10,
-                "1" => 16,
-                "2" => 22,
-                "3" => 28,
-                "4" => 34,
-                "5" => 40,
-                "6" => 46,
-                "7" => 52,
-                "8" => 58,
-                "9" => 64,
-                "10" => 70,
-                "11" => 76,
-                "12" => 82,
-                "13" => 88,
-                "14" => 94,
-                "15" => 112
-            ],
-            "5" => [
-                "0" => 15,
-                "1" => 22,
-                "2" => 29,
-                "3" => 36,
-                "4" => 43,
-                "5" => 50,
-                "6" => 57,
-                "7" => 64,
-                "8" => 71,
-                "9" => 78,
-                "10" => 85,
-                "11" => 92,
-                "12" => 99,
-                "13" => 106,
-                "14" => 113,
-                "15" => 135
-            ],
-            "6" => [
-                "0" => 22,
-                "1" => 30,
-                "2" => 38,
-                "3" => 46,
-                "4" => 54,
-                "5" => 62,
-                "6" => 70,
-                "7" => 78,
-                "8" => 86,
-                "9" => 94,
-                "10" => 102,
-                "11" => 110,
-                "12" => 118,
-                "13" => 126,
-                "14" => 134,
-                "15" => 160
-            ]
-        ];
-
-        /**
-         * Values of the ATK_P main stat[stars][level]
-         */
-        const ATK_P = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 24,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 36,
-                "15" => 43
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 10,
-                "2" => 12,
-                "3" => 15,
-                "4" => 17,
-                "5" => 20,
-                "6" => 22,
-                "7" => 24,
-                "8" => 27,
-                "9" => 29,
-                "10" => 32,
-                "11" => 34,
-                "12" => 37,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 14,
-                "2" => 17,
-                "3" => 20,
-                "4" => 23,
-                "5" => 26,
-                "6" => 29,
-                "7" => 32,
-                "8" => 35,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 47,
-                "13" => 50,
-                "14" => 53,
-                "15" => 63
-            ]
-        ];
-        
-        /**
-         * Values of the DEF main stat[stars][level]
-         */
-        const DEF = [
-            "1" => [
-                "0" => 3,
-                "1" => 6,
-                "2" => 9,
-                "3" => 12,
-                "4" => 15,
-                "5" => 18,
-                "6" => 21,
-                "7" => 24,
-                "8" => 27,
-                "9" => 30,
-                "10" => 33,
-                "11" => 36,
-                "12" => 39,
-                "13" => 42,
-                "14" => 45,
-                "15" => 54
-            ],
-            "2" => [
-                "0" => 5,
-                "1" => 9,
-                "2" => 13,
-                "3" => 17,
-                "4" => 21,
-                "5" => 25,
-                "6" => 29,
-                "7" => 33,
-                "8" => 37,
-                "9" => 41,
-                "10" => 45,
-                "11" => 49,
-                "12" => 53,
-                "13" => 57,
-                "14" => 61,
-                "15" => 73
-            ],
-            "3" => [
-                "0" => 7,
-                "1" => 12,
-                "2" => 17,
-                "3" => 22,
-                "4" => 27,
-                "5" => 32,
-                "6" => 37,
-                "7" => 42,
-                "8" => 47,
-                "9" => 52,
-                "10" => 57,
-                "11" => 62,
-                "12" => 67,
-                "13" => 72,
-                "14" => 77,
-                "15" => 92
-            ],
-            "4" => [
-                "0" => 10,
-                "1" => 16,
-                "2" => 22,
-                "3" => 28,
-                "4" => 34,
-                "5" => 40,
-                "6" => 46,
-                "7" => 52,
-                "8" => 58,
-                "9" => 64,
-                "10" => 70,
-                "11" => 76,
-                "12" => 82,
-                "13" => 88,
-                "14" => 94,
-                "15" => 112
-            ],
-            "5" => [
-                "0" => 15,
-                "1" => 22,
-                "2" => 29,
-                "3" => 36,
-                "4" => 43,
-                "5" => 50,
-                "6" => 57,
-                "7" => 64,
-                "8" => 71,
-                "9" => 78,
-                "10" => 85,
-                "11" => 92,
-                "12" => 99,
-                "13" => 106,
-                "14" => 113,
-                "15" => 135
-            ],
-            "6" => [
-                "0" => 22,
-                "1" => 30,
-                "2" => 38,
-                "3" => 46,
-                "4" => 54,
-                "5" => 62,
-                "6" => 70,
-                "7" => 78,
-                "8" => 86,
-                "9" => 94,
-                "10" => 102,
-                "11" => 110,
-                "12" => 118,
-                "13" => 126,
-                "14" => 134,
-                "15" => 160
-            ]
-        ];
-        
-        /**
-         * Values of the DEF_P main stat[stars][level]
-         */
-        const DEF_P = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 24,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 36,
-                "15" => 43
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 10,
-                "2" => 12,
-                "3" => 15,
-                "4" => 17,
-                "5" => 20,
-                "6" => 22,
-                "7" => 24,
-                "8" => 27,
-                "9" => 29,
-                "10" => 32,
-                "11" => 34,
-                "12" => 37,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 14,
-                "2" => 17,
-                "3" => 20,
-                "4" => 23,
-                "5" => 26,
-                "6" => 29,
-                "7" => 32,
-                "8" => 35,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 47,
-                "13" => 50,
-                "14" => 53,
-                "15" => 63
-            ]
-        ];
-
-        /**
-         * Values of the SPD main stat[stars][level]
-         */
-        const SPD = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 3,
-                "1" => 4,
-                "2" => 5,
-                "3" => 6,
-                "4" => 8,
-                "5" => 9,
-                "6" => 10,
-                "7" => 12,
-                "8" => 13,
-                "9" => 14,
-                "10" => 16,
-                "11" => 17,
-                "12" => 18,
-                "13" => 19,
-                "14" => 21,
-                "15" => 25
-            ],
-            "4" => [
-                "0" => 4,
-                "1" => 5,
-                "2" => 7,
-                "3" => 8,
-                "4" => 10,
-                "5" => 11,
-                "6" => 13,
-                "7" => 14,
-                "8" => 16,
-                "9" => 17,
-                "10" => 19,
-                "11" => 20,
-                "12" => 22,
-                "13" => 23,
-                "14" => 25,
-                "15" => 30
-            ],
-            "5" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 15,
-                "6" => 17,
-                "7" => 19,
-                "8" => 21,
-                "9" => 23,
-                "10" => 25,
-                "11" => 27,
-                "12" => 29,
-                "13" => 31,
-                "14" => 33,
-                "15" => 39
-            ],
-            "6" => [
-                "0" => 7,
-                "1" => 9,
-                "2" => 11,
-                "3" => 13,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 21,
-                "8" => 23,
-                "9" => 25,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 35,
-                "15" => 42
-            ]
-        ];
-
-        /**
-         * Values of the CRR main stat[stars][level]
-         */
-        const CRR = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 3,
-                "1" => 5,
-                "2" => 7,
-                "3" => 9,
-                "4" => 11,
-                "5" => 13,
-                "6" => 15,
-                "7" => 17,
-                "8" => 19,
-                "9" => 21,
-                "10" => 23,
-                "11" => 25,
-                "12" => 27,
-                "13" => 29,
-                "14" => 31,
-                "15" => 37
-            ],
-            "4" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 11,
-                "4" => 13,
-                "5" => 15,
-                "6" => 17,
-                "7" => 19,
-                "8" => 22,
-                "9" => 24,
-                "10" => 26,
-                "11" => 28,
-                "12" => 30,
-                "13" => 33,
-                "14" => 35,
-                "15" => 41
-            ],
-            "5" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 10,
-                "3" => 12,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 22,
-                "8" => 24,
-                "9" => 27,
-                "10" => 29,
-                "11" => 31,
-                "12" => 34,
-                "13" => 36,
-                "14" => 39,
-                "15" => 47
-            ],
-            "6" => [
-                "0" => 7,
-                "1" => 10,
-                "2" => 13,
-                "3" => 16,
-                "4" => 19,
-                "5" => 22,
-                "6" => 25,
-                "7" => 28,
-                "8" => 31,
-                "9" => 34,
-                "10" => 37,
-                "11" => 40,
-                "12" => 43,
-                "13" => 46,
-                "14" => 49,
-                "15" => 58
-            ]
-        ];
-
-        /**
-         * Values of the CRD main stat[stars][level]
-         */
-        const CRD = [
-            "1" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "2" => [
-                "0" => 3,
-                "1" => 5,
-                "2" => 7,
-                "3" => 9,
-                "4" => 11,
-                "5" => 13,
-                "6" => 15,
-                "7" => 17,
-                "8" => 19,
-                "9" => 21,
-                "10" => 23,
-                "11" => 25,
-                "12" => 27,
-                "13" => 29,
-                "14" => 31,
-                "15" => 37
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 25,
-                "10" => 27,
-                "11" => 29,
-                "12" => 32,
-                "13" => 34,
-                "14" => 36,
-                "15" => 43
-            ],
-            "4" => [
-                "0" => 6,
-                "1" => 9,
-                "2" => 12,
-                "3" => 15,
-                "4" => 18,
-                "5" => 21,
-                "6" => 24,
-                "7" => 27,
-                "8" => 30,
-                "9" => 33,
-                "10" => 36,
-                "11" => 39,
-                "12" => 42,
-                "13" => 45,
-                "14" => 48,
-                "15" => 57
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 11,
-                "2" => 15,
-                "3" => 18,
-                "4" => 21,
-                "5" => 25,
-                "6" => 28,
-                "7" => 31,
-                "8" => 34,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 48,
-                "13" => 51,
-                "14" => 54,
-                "15" => 65
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 15,
-                "2" => 19,
-                "3" => 23,
-                "4" => 27,
-                "5" => 31,
-                "6" => 35,
-                "7" => 39,
-                "8" => 43,
-                "9" => 47,
-                "10" => 51,
-                "11" => 55,
-                "12" => 59,
-                "13" => 63,
-                "14" => 67,
-                "15" => 80
-            ]
-        ];
-
-        /**
-         * Values of the ACC main stat[stars][level]
-         */
-        const ACC = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 6,
-                "1" => 8,
-                "2" => 10,
-                "3" => 13,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 21,
-                "8" => 24,
-                "9" => 26,
-                "10" => 28,
-                "11" => 30,
-                "12" => 32,
-                "13" => 35,
-                "14" => 37,
-                "15" => 44
-            ],
-            "5" => [
-                "0" => 9,
-                "1" => 11,
-                "2" => 14,
-                "3" => 16,
-                "4" => 19,
-                "5" => 21,
-                "6" => 23,
-                "7" => 26,
-                "8" => 28,
-                "9" => 31,
-                "10" => 33,
-                "11" => 35,
-                "12" => 38,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 12,
-                "1" => 15,
-                "2" => 18,
-                "3" => 21,
-                "4" => 24,
-                "5" => 27,
-                "6" => 30,
-                "7" => 33,
-                "8" => 36,
-                "9" => 39,
-                "10" => 42,
-                "11" => 45,
-                "12" => 48,
-                "13" => 51,
-                "14" => 54,
-                "15" => 64
-            ]
-        ];
-
-        /**
-         * Values of the RES main stat[stars][level]
-         */
-        const RES = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 6,
-                "1" => 8,
-                "2" => 10,
-                "3" => 13,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 21,
-                "8" => 24,
-                "9" => 26,
-                "10" => 28,
-                "11" => 30,
-                "12" => 32,
-                "13" => 35,
-                "14" => 37,
-                "15" => 44
-            ],
-            "5" => [
-                "0" => 9,
-                "1" => 11,
-                "2" => 14,
-                "3" => 16,
-                "4" => 19,
-                "5" => 21,
-                "6" => 23,
-                "7" => 26,
-                "8" => 28,
-                "9" => 31,
-                "10" => 33,
-                "11" => 35,
-                "12" => 38,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 12,
-                "1" => 15,
-                "2" => 18,
-                "3" => 21,
-                "4" => 24,
-                "5" => 27,
-                "6" => 30,
-                "7" => 33,
-                "8" => 36,
-                "9" => 39,
-                "10" => 42,
-                "11" => 45,
-                "12" => 48,
-                "13" => 51,
-                "14" => 54,
-                "15" => 64
-            ]
-        ];
-    };
-
-    /**
-     * Rune main stat values constants.
-     *
-     * Includes the value of the main stats for type, stars, and level.
-     *
-     * @category Data
-     */
-    final class RUNE_SUBSTAT_MAX_VALUES{
-    
-        const SUBSTAT = [
-            RUNE_STAT_ID::HP => [
-                "1" => 300,
-                "2" => 525,
-                "3" => 825,
-                "4" => 1125,
-                "5" => 1500,
-                "6" => 1875
-            ],
-            RUNE_STAT_ID::HP_P => [
-                "1" => 10,
-                "2" => 15,
-                "3" => 25,
-                "4" => 30,
-                "5" => 35,
-                "6" => 40
-            ],
-            RUNE_STAT_ID::ATK => [
-                "1" => 20,
-                "2" => 25,
-                "3" => 40,
-                "4" => 50,
-                "5" => 75,
-                "6" => 100
-            ],
-            RUNE_STAT_ID::ATK_P => [
-                "1" => 10,
-                "2" => 15,
-                "3" => 25,
-                "4" => 30,
-                "5" => 35,
-                "6" => 40
-            ],
-            RUNE_STAT_ID::DEF => [
-                "1" => 20,
-                "2" => 25,
-                "3" => 40,
-                "4" => 50,
-                "5" => 75,
-                "6" => 100
-            ],
-            RUNE_STAT_ID::DEF_P => [
-                "1" => 10,
-                "2" => 15,
-                "3" => 25,
-                "4" => 30,
-                "5" => 35,
-                "6" => 40
-            ],
-            RUNE_STAT_ID::SPD => [
-                "1" => 5,
-                "2" => 10,
-                "3" => 15,
-                "4" => 20,
-                "5" => 25,
-                "6" => 30
-            ],
-            RUNE_STAT_ID::CRR => [
-                "1" => 5,
-                "2" => 10,
-                "3" => 15,
-                "4" => 20,
-                "5" => 25,
-                "6" => 30
-            ],
-            RUNE_STAT_ID::CRD => [
-                "1" => 10,
-                "2" => 15,
-                "3" => 20,
-                "4" => 25,
-                "5" => 30,
-                "6" => 35
-            ],
-            RUNE_STAT_ID::RES => [
-                "1" => 10,
-                "2" => 15,
-                "3" => 25,
-                "4" => 30,
-                "5" => 35,
-                "6" => 40
-            ],
-            RUNE_STAT_ID::ACC => [
-                "1" => 10,
-                "2" => 15,
-                "3" => 25,
-                "4" => 30,
-                "5" => 35,
-                "6" => 40
-            ]
-        ];
-
-        /**
-         * Values of the HP main stat [stars][level]
-         */
-        const HP = [
-            "1" => [
-                "0" => 40,
-                "1" => 85,
-                "2" => 130,
-                "3" => 175,
-                "4" => 220,
-                "5" => 265,
-                "6" => 310,
-                "7" => 355,
-                "8" => 400,
-                "9" => 445,
-                "10" => 490,
-                "11" => 535,
-                "12" => 580,
-                "13" => 625,
-                "14" => 670,
-                "15" => 804
-            ],
-            "2" => [
-                "0" => 70,
-                "1" => 130,
-                "2" => 190,
-                "3" => 250,
-                "4" => 310,
-                "5" => 370,
-                "6" => 430,
-                "7" => 490,
-                "8" => 550,
-                "9" => 610,
-                "10" => 670,
-                "11" => 730,
-                "12" => 790,
-                "13" => 850,
-                "14" => 910,
-                "15" => 1092
-            ],
-            "3" => [
-                "0" => 100,
-                "1" => 175,
-                "2" => 250,
-                "3" => 325,
-                "4" => 400,
-                "5" => 475,
-                "6" => 550,
-                "7" => 625,
-                "8" => 700,
-                "9" => 775,
-                "10" => 850,
-                "11" => 925,
-                "12" => 1000,
-                "13" => 1075,
-                "14" => 1150,
-                "15" => 1380
-            ],
-            "4" => [
-                "0" => 160,
-                "1" => 250,
-                "2" => 340,
-                "3" => 430,
-                "4" => 520,
-                "5" => 610,
-                "6" => 700,
-                "7" => 790,
-                "8" => 880,
-                "9" => 970,
-                "10" => 1060,
-                "11" => 1150,
-                "12" => 1240,
-                "13" => 1330,
-                "14" => 1420,
-                "15" => 1704
-            ],
-            "5" => [
-                "0" => 270,
-                "1" => 375,
-                "2" => 480,
-                "3" => 585,
-                "4" => 690,
-                "5" => 795,
-                "6" => 900,
-                "7" => 1005,
-                "8" => 1110,
-                "9" => 1215,
-                "10" => 1320,
-                "11" => 1425,
-                "12" => 1530,
-                "13" => 1635,
-                "14" => 1740,
-                "15" => 2088
-            ],
-            "6" => [
-                "0" => 360,
-                "1" => 480,
-                "2" => 600,
-                "3" => 720,
-                "4" => 840,
-                "5" => 960,
-                "6" => 1080,
-                "7" => 1200,
-                "8" => 1320,
-                "9" => 1440,
-                "10" => 1560,
-                "11" => 1680,
-                "12" => 1800,
-                "13" => 1920,
-                "14" => 2040,
-                "15" => 2448
-            ]
-        ];
-        
-        /**
-         * Values of the HP_P main stat[stars][level]
-         */
-        const HP_P = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 24,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 36,
-                "15" => 43
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 10,
-                "2" => 12,
-                "3" => 15,
-                "4" => 17,
-                "5" => 20,
-                "6" => 22,
-                "7" => 24,
-                "8" => 27,
-                "9" => 29,
-                "10" => 32,
-                "11" => 34,
-                "12" => 37,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 14,
-                "2" => 17,
-                "3" => 20,
-                "4" => 23,
-                "5" => 26,
-                "6" => 29,
-                "7" => 32,
-                "8" => 35,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 47,
-                "13" => 50,
-                "14" => 53,
-                "15" => 63
-            ]
-        ];
-
-        /**
-         * Values of the ATK main stat[stars][level]
-         */
-        const ATK = [
-            "1" => [
-                "0" => 3,
-                "1" => 6,
-                "2" => 9,
-                "3" => 12,
-                "4" => 15,
-                "5" => 18,
-                "6" => 21,
-                "7" => 24,
-                "8" => 27,
-                "9" => 30,
-                "10" => 33,
-                "11" => 36,
-                "12" => 39,
-                "13" => 42,
-                "14" => 45,
-                "15" => 54
-            ],
-            "2" => [
-                "0" => 5,
-                "1" => 9,
-                "2" => 13,
-                "3" => 17,
-                "4" => 21,
-                "5" => 25,
-                "6" => 29,
-                "7" => 33,
-                "8" => 37,
-                "9" => 41,
-                "10" => 45,
-                "11" => 49,
-                "12" => 53,
-                "13" => 57,
-                "14" => 61,
-                "15" => 73
-            ],
-            "3" => [
-                "0" => 7,
-                "1" => 12,
-                "2" => 17,
-                "3" => 22,
-                "4" => 27,
-                "5" => 32,
-                "6" => 37,
-                "7" => 42,
-                "8" => 47,
-                "9" => 52,
-                "10" => 57,
-                "11" => 62,
-                "12" => 67,
-                "13" => 72,
-                "14" => 77,
-                "15" => 92
-            ],
-            "4" => [
-                "0" => 10,
-                "1" => 16,
-                "2" => 22,
-                "3" => 28,
-                "4" => 34,
-                "5" => 40,
-                "6" => 46,
-                "7" => 52,
-                "8" => 58,
-                "9" => 64,
-                "10" => 70,
-                "11" => 76,
-                "12" => 82,
-                "13" => 88,
-                "14" => 94,
-                "15" => 112
-            ],
-            "5" => [
-                "0" => 15,
-                "1" => 22,
-                "2" => 29,
-                "3" => 36,
-                "4" => 43,
-                "5" => 50,
-                "6" => 57,
-                "7" => 64,
-                "8" => 71,
-                "9" => 78,
-                "10" => 85,
-                "11" => 92,
-                "12" => 99,
-                "13" => 106,
-                "14" => 113,
-                "15" => 135
-            ],
-            "6" => [
-                "0" => 22,
-                "1" => 30,
-                "2" => 38,
-                "3" => 46,
-                "4" => 54,
-                "5" => 62,
-                "6" => 70,
-                "7" => 78,
-                "8" => 86,
-                "9" => 94,
-                "10" => 102,
-                "11" => 110,
-                "12" => 118,
-                "13" => 126,
-                "14" => 134,
-                "15" => 160
-            ]
-        ];
-
-        /**
-         * Values of the ATK_P main stat[stars][level]
-         */
-        const ATK_P = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 24,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 36,
-                "15" => 43
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 10,
-                "2" => 12,
-                "3" => 15,
-                "4" => 17,
-                "5" => 20,
-                "6" => 22,
-                "7" => 24,
-                "8" => 27,
-                "9" => 29,
-                "10" => 32,
-                "11" => 34,
-                "12" => 37,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 14,
-                "2" => 17,
-                "3" => 20,
-                "4" => 23,
-                "5" => 26,
-                "6" => 29,
-                "7" => 32,
-                "8" => 35,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 47,
-                "13" => 50,
-                "14" => 53,
-                "15" => 63
-            ]
-        ];
-        
-        /**
-         * Values of the DEF main stat[stars][level]
-         */
-        const DEF = [
-            "1" => [
-                "0" => 3,
-                "1" => 6,
-                "2" => 9,
-                "3" => 12,
-                "4" => 15,
-                "5" => 18,
-                "6" => 21,
-                "7" => 24,
-                "8" => 27,
-                "9" => 30,
-                "10" => 33,
-                "11" => 36,
-                "12" => 39,
-                "13" => 42,
-                "14" => 45,
-                "15" => 54
-            ],
-            "2" => [
-                "0" => 5,
-                "1" => 9,
-                "2" => 13,
-                "3" => 17,
-                "4" => 21,
-                "5" => 25,
-                "6" => 29,
-                "7" => 33,
-                "8" => 37,
-                "9" => 41,
-                "10" => 45,
-                "11" => 49,
-                "12" => 53,
-                "13" => 57,
-                "14" => 61,
-                "15" => 73
-            ],
-            "3" => [
-                "0" => 7,
-                "1" => 12,
-                "2" => 17,
-                "3" => 22,
-                "4" => 27,
-                "5" => 32,
-                "6" => 37,
-                "7" => 42,
-                "8" => 47,
-                "9" => 52,
-                "10" => 57,
-                "11" => 62,
-                "12" => 67,
-                "13" => 72,
-                "14" => 77,
-                "15" => 92
-            ],
-            "4" => [
-                "0" => 10,
-                "1" => 16,
-                "2" => 22,
-                "3" => 28,
-                "4" => 34,
-                "5" => 40,
-                "6" => 46,
-                "7" => 52,
-                "8" => 58,
-                "9" => 64,
-                "10" => 70,
-                "11" => 76,
-                "12" => 82,
-                "13" => 88,
-                "14" => 94,
-                "15" => 112
-            ],
-            "5" => [
-                "0" => 15,
-                "1" => 22,
-                "2" => 29,
-                "3" => 36,
-                "4" => 43,
-                "5" => 50,
-                "6" => 57,
-                "7" => 64,
-                "8" => 71,
-                "9" => 78,
-                "10" => 85,
-                "11" => 92,
-                "12" => 99,
-                "13" => 106,
-                "14" => 113,
-                "15" => 135
-            ],
-            "6" => [
-                "0" => 22,
-                "1" => 30,
-                "2" => 38,
-                "3" => 46,
-                "4" => 54,
-                "5" => 62,
-                "6" => 70,
-                "7" => 78,
-                "8" => 86,
-                "9" => 94,
-                "10" => 102,
-                "11" => 110,
-                "12" => 118,
-                "13" => 126,
-                "14" => 134,
-                "15" => 160
-            ]
-        ];
-        
-        /**
-         * Values of the DEF_P main stat[stars][level]
-         */
-        const DEF_P = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 24,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 36,
-                "15" => 43
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 10,
-                "2" => 12,
-                "3" => 15,
-                "4" => 17,
-                "5" => 20,
-                "6" => 22,
-                "7" => 24,
-                "8" => 27,
-                "9" => 29,
-                "10" => 32,
-                "11" => 34,
-                "12" => 37,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 14,
-                "2" => 17,
-                "3" => 20,
-                "4" => 23,
-                "5" => 26,
-                "6" => 29,
-                "7" => 32,
-                "8" => 35,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 47,
-                "13" => 50,
-                "14" => 53,
-                "15" => 63
-            ]
-        ];
-
-        /**
-         * Values of the SPD main stat[stars][level]
-         */
-        const SPD = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 3,
-                "1" => 4,
-                "2" => 5,
-                "3" => 6,
-                "4" => 8,
-                "5" => 9,
-                "6" => 10,
-                "7" => 12,
-                "8" => 13,
-                "9" => 14,
-                "10" => 16,
-                "11" => 17,
-                "12" => 18,
-                "13" => 19,
-                "14" => 21,
-                "15" => 25
-            ],
-            "4" => [
-                "0" => 4,
-                "1" => 5,
-                "2" => 7,
-                "3" => 8,
-                "4" => 10,
-                "5" => 11,
-                "6" => 13,
-                "7" => 14,
-                "8" => 16,
-                "9" => 17,
-                "10" => 19,
-                "11" => 20,
-                "12" => 22,
-                "13" => 23,
-                "14" => 25,
-                "15" => 30
-            ],
-            "5" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 15,
-                "6" => 17,
-                "7" => 19,
-                "8" => 21,
-                "9" => 23,
-                "10" => 25,
-                "11" => 27,
-                "12" => 29,
-                "13" => 31,
-                "14" => 33,
-                "15" => 39
-            ],
-            "6" => [
-                "0" => 7,
-                "1" => 9,
-                "2" => 11,
-                "3" => 13,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 21,
-                "8" => 23,
-                "9" => 25,
-                "10" => 27,
-                "11" => 29,
-                "12" => 31,
-                "13" => 33,
-                "14" => 35,
-                "15" => 42
-            ]
-        ];
-
-        /**
-         * Values of the CRR main stat[stars][level]
-         */
-        const CRR = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 3,
-                "1" => 5,
-                "2" => 7,
-                "3" => 9,
-                "4" => 11,
-                "5" => 13,
-                "6" => 15,
-                "7" => 17,
-                "8" => 19,
-                "9" => 21,
-                "10" => 23,
-                "11" => 25,
-                "12" => 27,
-                "13" => 29,
-                "14" => 31,
-                "15" => 37
-            ],
-            "4" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 11,
-                "4" => 13,
-                "5" => 15,
-                "6" => 17,
-                "7" => 19,
-                "8" => 22,
-                "9" => 24,
-                "10" => 26,
-                "11" => 28,
-                "12" => 30,
-                "13" => 33,
-                "14" => 35,
-                "15" => 41
-            ],
-            "5" => [
-                "0" => 5,
-                "1" => 7,
-                "2" => 10,
-                "3" => 12,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 22,
-                "8" => 24,
-                "9" => 27,
-                "10" => 29,
-                "11" => 31,
-                "12" => 34,
-                "13" => 36,
-                "14" => 39,
-                "15" => 47
-            ],
-            "6" => [
-                "0" => 7,
-                "1" => 10,
-                "2" => 13,
-                "3" => 16,
-                "4" => 19,
-                "5" => 22,
-                "6" => 25,
-                "7" => 28,
-                "8" => 31,
-                "9" => 34,
-                "10" => 37,
-                "11" => 40,
-                "12" => 43,
-                "13" => 46,
-                "14" => 49,
-                "15" => 58
-            ]
-        ];
-
-        /**
-         * Values of the CRD main stat[stars][level]
-         */
-        const CRD = [
-            "1" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "2" => [
-                "0" => 3,
-                "1" => 5,
-                "2" => 7,
-                "3" => 9,
-                "4" => 11,
-                "5" => 13,
-                "6" => 15,
-                "7" => 17,
-                "8" => 19,
-                "9" => 21,
-                "10" => 23,
-                "11" => 25,
-                "12" => 27,
-                "13" => 29,
-                "14" => 31,
-                "15" => 37
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 9,
-                "3" => 11,
-                "4" => 13,
-                "5" => 16,
-                "6" => 18,
-                "7" => 20,
-                "8" => 22,
-                "9" => 25,
-                "10" => 27,
-                "11" => 29,
-                "12" => 32,
-                "13" => 34,
-                "14" => 36,
-                "15" => 43
-            ],
-            "4" => [
-                "0" => 6,
-                "1" => 9,
-                "2" => 12,
-                "3" => 15,
-                "4" => 18,
-                "5" => 21,
-                "6" => 24,
-                "7" => 27,
-                "8" => 30,
-                "9" => 33,
-                "10" => 36,
-                "11" => 39,
-                "12" => 42,
-                "13" => 45,
-                "14" => 48,
-                "15" => 57
-            ],
-            "5" => [
-                "0" => 8,
-                "1" => 11,
-                "2" => 15,
-                "3" => 18,
-                "4" => 21,
-                "5" => 25,
-                "6" => 28,
-                "7" => 31,
-                "8" => 34,
-                "9" => 38,
-                "10" => 41,
-                "11" => 44,
-                "12" => 48,
-                "13" => 51,
-                "14" => 54,
-                "15" => 65
-            ],
-            "6" => [
-                "0" => 11,
-                "1" => 15,
-                "2" => 19,
-                "3" => 23,
-                "4" => 27,
-                "5" => 31,
-                "6" => 35,
-                "7" => 39,
-                "8" => 43,
-                "9" => 47,
-                "10" => 51,
-                "11" => 55,
-                "12" => 59,
-                "13" => 63,
-                "14" => 67,
-                "15" => 80
-            ]
-        ];
-
-        /**
-         * Values of the ACC main stat[stars][level]
-         */
-        const ACC = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 6,
-                "1" => 8,
-                "2" => 10,
-                "3" => 13,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 21,
-                "8" => 24,
-                "9" => 26,
-                "10" => 28,
-                "11" => 30,
-                "12" => 32,
-                "13" => 35,
-                "14" => 37,
-                "15" => 44
-            ],
-            "5" => [
-                "0" => 9,
-                "1" => 11,
-                "2" => 14,
-                "3" => 16,
-                "4" => 19,
-                "5" => 21,
-                "6" => 23,
-                "7" => 26,
-                "8" => 28,
-                "9" => 31,
-                "10" => 33,
-                "11" => 35,
-                "12" => 38,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 12,
-                "1" => 15,
-                "2" => 18,
-                "3" => 21,
-                "4" => 24,
-                "5" => 27,
-                "6" => 30,
-                "7" => 33,
-                "8" => 36,
-                "9" => 39,
-                "10" => 42,
-                "11" => 45,
-                "12" => 48,
-                "13" => 51,
-                "14" => 54,
-                "15" => 64
-            ]
-        ];
-
-        /**
-         * Values of the RES main stat[stars][level]
-         */
-        const RES = [
-            "1" => [
-                "0" => 1,
-                "1" => 2,
-                "2" => 3,
-                "3" => 4,
-                "4" => 5,
-                "5" => 6,
-                "6" => 7,
-                "7" => 8,
-                "8" => 9,
-                "9" => 10,
-                "10" => 11,
-                "11" => 12,
-                "12" => 13,
-                "13" => 14,
-                "14" => 15,
-                "15" => 18
-            ],
-            "2" => [
-                "0" => 2,
-                "1" => 3,
-                "2" => 4,
-                "3" => 5,
-                "4" => 6,
-                "5" => 7,
-                "6" => 8,
-                "7" => 9,
-                "8" => 10,
-                "9" => 11,
-                "10" => 12,
-                "11" => 13,
-                "12" => 14,
-                "13" => 15,
-                "14" => 16,
-                "15" => 19
-            ],
-            "3" => [
-                "0" => 4,
-                "1" => 6,
-                "2" => 8,
-                "3" => 10,
-                "4" => 12,
-                "5" => 14,
-                "6" => 16,
-                "7" => 18,
-                "8" => 20,
-                "9" => 22,
-                "10" => 24,
-                "11" => 26,
-                "12" => 28,
-                "13" => 30,
-                "14" => 32,
-                "15" => 38
-            ],
-            "4" => [
-                "0" => 6,
-                "1" => 8,
-                "2" => 10,
-                "3" => 13,
-                "4" => 15,
-                "5" => 17,
-                "6" => 19,
-                "7" => 21,
-                "8" => 24,
-                "9" => 26,
-                "10" => 28,
-                "11" => 30,
-                "12" => 32,
-                "13" => 35,
-                "14" => 37,
-                "15" => 44
-            ],
-            "5" => [
-                "0" => 9,
-                "1" => 11,
-                "2" => 14,
-                "3" => 16,
-                "4" => 19,
-                "5" => 21,
-                "6" => 23,
-                "7" => 26,
-                "8" => 28,
-                "9" => 31,
-                "10" => 33,
-                "11" => 35,
-                "12" => 38,
-                "13" => 40,
-                "14" => 43,
-                "15" => 51
-            ],
-            "6" => [
-                "0" => 12,
-                "1" => 15,
-                "2" => 18,
-                "3" => 21,
-                "4" => 24,
-                "5" => 27,
-                "6" => 30,
-                "7" => 33,
-                "8" => 36,
-                "9" => 39,
-                "10" => 42,
-                "11" => 45,
-                "12" => 48,
-                "13" => 51,
-                "14" => 54,
-                "15" => 64
-            ]
-        ];
-    };
-
-    /**
-     * Artifact types.
-     *
-     * The two types of artifacts.
-     */
-    final class ARTIFACT_TYPE{
-
-        /**
-         * Elemental attribute.
-         */
-        const ELEMENT = 0;
-
-        /**
-         * Type artifact.
-         */
-        const ARCHETYPE = 1;
-     }
-    
-    /**
-     * Artifact stat constants.
-     *
-     * The stats an artifact can have. For unit stats, see{@see $STAT_ID}.
-     *
-     * @category Data
-     */
-    final class ARTIFACT_STAT_ID{
-
-        /**
-         * HP.
-         */
-        const HP = 100;
-
-        /**
-         * ATK.
-         */
-        const ATK = 101;
-
-        /**
-         * DEF.
-         */
-        const DEF = 102;
-    }
-
-    /**
-     * Rune (and other items) quality constants.
-     *
-     * @category Data
-     */
-    final class QUALITY_ID{
-
-        /**
-         * Normal.
-         */
-        const NORMAL = 1;
-
-        /**
-         * Magic.
-         */
-        const MAGIC = 2;
-
-        /**
-         * Rare.
-         */
-        const RARE = 3;
-
-        /**
-         * Hero.
-         */
-        const HERO = 4;
-
-        /**
-         * Legend.
-         */
-        const LEGEND = 5;
-    };
-
-    /**
-     * Craft items constants.
-     *
-     * @category Data
-     */
-    final class CRAFT_ID{
-
-        /**
-         * Enchant Gem.
-         */
-        const ENCHANT_GEM = 1;
-
-        /**
-         * Grindstone.
-         */
-        const GRINDSTONE = 2;
-
-        /**
-         * Immemorial Gem.
-         */
-        const IMMEMORIAL_GEM = 3;
-
-        /**
-         * Immemorial Grindstone.
-         */
-        const IMMEMORIAL_GRINDSTONE = 4;
-    };
-
-    /**
-     * Guild member rank constants.
-     *
-     * @category Data
-     */
-    final class GUILD_MEMBER_GRADE_ID{
-
-        /**
-         * Leader.
-         */
-        const LEADER = 1;
-
-        /**
-         * Viceleader.
-         */
-        const VICELEADER = 3;
-
-        /**
-         * Normal member.
-         */
-        const NORMAL = 2;
-    };
-
-    /**
-     * Arena ranking constant.
-     *
-     * Each element contains the minimum points for a rank. To calculate rank,
-     * @{see ARENA_RANKING_RANK} is neeeded too.
-     *
-     * @category Data
-     */
-    final class ARENA_RANKING_POINTS{
-
-        /**
-         * Beginer.
-         */
-        const BEGINER = 0;
-
-        /**
-         * Challenger 1.
-         */
-        const CHALLENGER_1 = 900;
-
-        /**
-         * Challenger 2.
-         */
-        const CHALLENGER_2 = 1000;
-
-        /**
-         * Challenger 3.
-         */
-        const CHALLENGER_3 = 1100;
-
-        /**
-         * Fighter 1.
-         */
-        const FIGHTER_1 = 1200;
-
-        /**
-         * Fighter 2.
-         */
-        const FIGHTER_2 = 1300;
-
-        /**
-         * Fighter 3.
-         */
-        const FIGHTER_3 = 1400;
-
-        /**
-         * Conqueror 1.
-         */
-        const CONQUEROR_1 = 1500;
-
-        /**
-         * Conqueror 2.
-         */
-        const CONQUEROR_2 = 1600;
-
-        /**
-         * Conqueror 3.
-         */
-        const CONQUEROR_3 = 1700;
-
-        /**
-         * Guardian 1.
-         */
-        const GUARDIAN_1 = 1700;
-
-        /**
-         * Guardian 2.
-         */
-        const GUARDIAN_2 = 1700;
-
-        /**
-         * Guardian 3.
-         */
-        const GUARDIAN_3 = 1700;
-
-        /**
-         * Legend.
-         */
-        const LEGEND = 1700;
-    };
-
-    /**
-     * Arena ranking constant.
-     *
-     * Each element contains the minimum top needed for a rank. A null value
-     * indicates that there is no top requeriment.To calculate rank,
-     * @{see ARENA_RANKING_POINTS} is neeeded too.
-     *
-     * @category Data
-     */
-    final class ARENA_RANKING_RANK{
-
-        /**
-         * Beginer.
-         */
-        const BEGINER = null;
-
-        /**
-         * Challenger 1.
-         */
-        const CHALLENGER_1 = null;
-
-        /**
-         * Challenger 2.
-         */
-        const CHALLENGER_2 = null;
-
-        /**
-         * Challenger 3.
-         */
-        const CHALLENGER_3 = null;
-
-        /**
-         * Fighter 1.
-         */
-        const FIGHTER_1 = null;
-
-        /**
-         * Fighter 2.
-         */
-        const FIGHTER_2 = null;
-
-        /**
-         * Fighter 3.
-         */
-        const FIGHTER_3 = null;
-
-        /**
-         * Conqueror 1.
-         */
-        const CONQUEROR_1 = 10000;
-
-        /**
-         * Conqueror 2.
-         */
-        const CONQUEROR_2 = 3000;
-
-        /**
-         * Conqueror 3.
-         */
-        const CONQUEROR_3 = 1000;
-
-        /**
-         * Guardian 1.
-         */
-        const GUARDIAN_1 = 300;
-
-        /**
-         * Guardian 2.
-         */
-        const GUARDIAN_2 = 100;
-
-        /**
-         * Guardian 3.
-         */
-        const GUARDIAN_3 = 30;
-
-        /**
-         * Legend.
-         */
-        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;
-     * 
-     * @category Data
-     */
-    final class FILTER{
-
-        /**
-         * Default values for the fusion filters.
-         */
-        const FUSION = [
-            "PRODUCT" => 0
-        ];
-
-        /**
-         * Default values for the rune filters.
-         */
-        const RUNE = [
-            "TYPE" => [],
-            "MAIN" => [],
-            "SUB" => [],
-            "SLOT" => [],
-            "MIN_QUALITY" => QUALITY_ID::NORMAL,
-            "MAX_QUALITY" => QUALITY_ID::LEGEND,
-            "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
-            "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
-            "MIN_STARS" => 1,
-            "MAX_STARS" => 6,
-            "MIN_LEVEL" => 0,
-            "MAX_LEVEL" => 15,
-            "MIN_EFFICIENCY" => 0,
-            "MAX_EFFICIENCY" => 100,
-            "MIN_MAX_EFFICIENCY" => 0,
-            "MAX_MAX_EFFICIENCY" => 100,
-            "ASSIGNED" => 1,
-            "GROUP" => "SLOT"
-        ];
-
-        /**
-         * Default values for the artifact filters.
-         */
-        const ARTIFACT = [
-            "TYPE" => 0,
-            "ELEMENT" => [],
-            "ARCHETYPE" => [],
-            "MAIN" => [],
-            "MIN_QUALITY" => QUALITY_ID::NORMAL,
-            "MAX_QUALITY" => QUALITY_ID::LEGEND,
-            "MIN_ORIGINAL_QUALITY" => QUALITY_ID::NORMAL,
-            "MAX_ORIGINAL_QUALITY" => QUALITY_ID::LEGEND,
-            "MIN_LEVEL" => 0,
-            "MAX_LEVEL" => 15,
-            "MIN_EFFICIENCY" => 0,
-            "MAX_EFFICIENCY" => 100,
-            "MIN_MAX_EFFICIENCY" => 0,
-            "MAX_MAX_EFFICIENCY" => 100,
-            "ASSIGNED" => 1
-        ];
-
-        /**
-         * Default values for the enchantment filters.
-         */
-        const ENCHANTMENT = [
-            "TYPE" => [],
-            "RUNE" => [],
-            "STAT" => [],
-            "MIN_QUALITY" => QUALITY_ID::NORMAL,
-            "MAX_QUALITY" => QUALITY_ID::LEGEND,
-        ];
-
-        /**
-         * Default values for the run filters.
-         */
-        const RUN = [
-            "AREA_TYPE" => 0,
-            "AREA" => 0,
-            "STAGE" => 0,
-            "DIFFICULTY" => 0,
-            "DATE_MIN" => null,
-            "DATE_MAX" => null,
-            "DEFEAT" => false,
-            "HELPER" => false,
-            "NUMBER" => 20,
-        ];
-
-        /**
-         * Default values for the rune team filters.
-         */
-        const TEAM = [
-            "NAME" => "",
-            "AREA" => null
-        ];
-
-        /**
-         * Default values for the rune team filters.
-         */
-        const STATS = [
-            "AREA_TYPE" => null,
-            "AREA" => null,
-            "STAGE" => null,
-            "DIFFICULTY" => null,
-            "INCLUDE_HELPER" => false
-        ];
-    };
-
-?>
+    /**
+     * Default values for the rune team filters.
+     */
+    const STATS = [
+        "AREA_TYPE" => null,
+        "AREA" => null,
+        "STAGE" => null,
+        "DIFFICULTY" => null,
+        "INCLUDE_HELPER" => false
+    ];
+};

+ 99 - 80
application/Context.php

@@ -1,96 +1,115 @@
 <?php
+/**
+ * Context file.
+ *
+ * Provides a handy class with usefull data to be accessible from anywhere in the app.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+/**
+ * Application context.
+ *
+ * Stores usefull data to be retrieved anywhere in the app.
+ *
+ * @category Context
+ */
+class Context {
+
     /**
-     * Context file.
-     *
-     * Provides a class to retrieve a context.
-     *
-     * @category Context
+     * @var User Currently logged in user.
      */
+    private $user;
 
     /**
-     * Application context.
-     *
-     * Stores usefull data to be retrieved anywhere in the app.
-     *
-     * @category Context
+     * @var Player Currently selected player. Does not need to be owned by the logged-in user.
      */
-    class Context {
+    private $player;
 
-        private $user;
-        private $player;
-        private $db;
-        private $game_mode;
+    /**
+     * @var SQLITE3 Database connection.
+     */
+    private $db;
 
-        /**
-         * Retrieves the selected user.
-         *
-         * @return User The selected user, null if no specified.
-         */
-        public function get_user(){
-            return $this->user;
-        }
+    /**
+     * @var int Selected game mode.
+     * @see GAME_MODE_ID.
+     */
+    private $game_mode;
 
-        /**
-         * Retrieves the logged in player.
-         *
-         * @return Player The current player, null if not logged in.
-         */
-        public function get_player(){
-            return $this->player;
-        }
+    /**
+     * Retrieves the selected user.
+     *
+     * @return User The selected user, null if no specified.
+     */
+    public function get_user(){
+        return $this->user;
+    }
+
+    /**
+     * Retrieves the logged in player.
+     *
+     * @return Player The current player, null if not logged in.
+     */
+    public function get_player(){
+        return $this->player;
+    }
 
-        /**
-         * Retrieves the database connection.
-         *
-         * @return SQLITE3 The database connection.
-         */
-        public function get_db(){
-            return $this->db;
-        }
+    /**
+     * Retrieves the database connection.
+     *
+     * @return SQLITE3 The database connection.
+     */
+    public function get_db(){
+        return $this->db;
+    }
 
-        /**
-         * Retrieves the current game mode.
-         *
-         * @return int Game mode.
-         */
-        public function get_game_mode(){
-            return $this->game_mode;
-        }
+    /**
+     * Retrieves the current game mode.
+     *
+     * @see GAME_MODE_ID
+     * @return int Game mode.
+     */
+    public function get_game_mode(){
+        return $this->game_mode;
+    }
 
-        /**
-         * Sets the current user.
-         *
-         * @param The current user.s
-         */
-        protected function set_user($user){
-            $this->user = $user;
-        }
+    /**
+     * Sets the current user.
+     *
+     * @param The current user.
+     */
+    protected function set_user($user){
+        $this->user = $user;
+    }
 
-        /**
-         * Sets the currently logged-in player.
-         *
-         * @param Player Logged-in player.
-         */
-        protected function set_player($player){
-            $this->player = $player;
-        }
+    /**
+     * Sets the currently logged-in player.
+     *
+     * @param Player Logged-in player.
+     */
+    protected function set_player($player){
+        $this->player = $player;
+    }
 
-        /**
-         * Sets the database connection
-         *
-         * @param SQLITE3 Database connection.
-         */
-        protected function set_db($db){
-            $this->db = $db;
-        }
+    /**
+     * Sets the database connection
+     *
+     * @param SQLITE3 Database connection.
+     */
+    protected function set_db($db){
+        $this->db = $db;
+    }
 
-        /**
-         * Sets the game mode.
-         *
-         * @param int Game mode.
-         */
-        protected function set_game_mode($game_mode){
-            $this->game_mode = $game_mode;
-        }
+    /**
+     * Sets the game mode.
+     *
+     * @see GAME_MODE_ID
+     * @param int Game mode.
+     */
+    protected function set_game_mode($game_mode){
+        $this->game_mode = $game_mode;
     }
-?>
+}

+ 359 - 354
application/Controller.php

@@ -1,408 +1,413 @@
 <?php
 
+/**
+ * Controller file.
+ *
+ * Provides a class to handle all posible request.
+ * 
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+/**
+ * Include some required files.
+ */
+require_once(__DIR__ . "/config.php");
+require_once(PATH::HELPER . "DB_Helper.php");
+require_once(PATH::HELPER . "TEXT_Helper.php");
+require_once(PATH::HELPER . "NET_Helper.php");
+require_once(PATH::HELPER . "HTML_Helper.php");
+require_once(PATH::HELPER . "APPLICATION_Helper.php");
+require_once(PATH::ENTITY . "User.php");
+require_once(PATH::ENTITY . "Player.php");
+require_once(__DIR__ . "/Constant.php");
+require_once(__DIR__ . "/Context.php");
+
+/**
+ * Application controller.
+ *
+ * Handles every request, creating the required models and selecting the
+ * view.
+ *
+ * @category Controller
+ */
+class Controller extends Context{
+
     /**
-     * Controller file.
-     *
-     * Provides a class to handle all posible request.
+     * @var string[] GET parameters received by the controller.
+     */
+    private $params = [];
+
+    /**
+     * @var Context Publicly available context.
+     */
+    private $context;
+
+    /**
+     * Retrieves the application context.
      * 
-     * @category Constroller
+     * @return Context The context.
      */
+    public function get_context(){
+        return $this->context;
+    }
 
     /**
-     * Include some required files.
+     * Controller constructor.
+     *
+     * Initializes a database connection and sets up the public context.
      */
-    require_once(__DIR__ . "/config.php");
-    require_once(PATH::HELPER . "DB_Helper.php");
-    require_once(PATH::HELPER . "TEXT_Helper.php");
-    require_once(PATH::HELPER . "NET_Helper.php");
-    require_once(PATH::HELPER . "HTML_Helper.php");
-    require_once(PATH::HELPER . "APPLICATION_Helper.php");
-    require_once(PATH::ENTITY . "User.php");
-    require_once(PATH::ENTITY . "Player.php");
-    require_once(__DIR__ . "/Constant.php");
-    require_once(__DIR__ . "/Context.php");
+    public function __construct(){
+        $this->context = new Context();
+        session_start();
+        $this->db = DB::start();
+        $this->context->set_db($this->db);
+    }
 
     /**
-     * Application controller.
+     * Handles the request parameters.
      *
-     * Handles every request, creating the required models and selecting the
-     * view.
+     * Receives the request params and gets itself ready. Authenticates the user (if needed)
+     * and validates the URL.
      *
-     * @category Controller
+     * @param string[] $params GET parameters of the request.
      */
-    class Controller extends Context{
+    public function prepare($params){
 
-        private $player;
-        private $user;
-        private $mode;
-        private $page;
-        private $db;
-        private $component; // web, api, action
-        private $command;
-        private $source;
-        private $params = [];
-        private $context;
+        // Parse parameters.
+        foreach($params as $p){
+            if (strlen($p) > 0){
+                array_push($this->params, $p);
+            }
+        }
 
-        public function action(){
-            // API call: Use API controller
-            if (count($this->params) > 0 && strtoupper($this->params[0]) == "API"){
-                if (count($this->params) == 1){
-                    // TODO: API MAIN PAGE
+        if (
+          count($this->params) > 1 && 
+          (
+            strtoupper($this->params[0]) == "ACTION"
+          ) ||
+          strtoupper($this->params[0]) == "API"
+        ){
+            // For API calls, or login action calls, skip authentication
+            return;
+        }
+
+        // Authentication
+        if (array_key_exists("user_token", $_COOKIE) && array_key_exists("user_id", $_COOKIE)){
+            // Authenticated user, check token.
+            $statement = $this->db->prepare("
+              SELECT count(token) AS c
+              FROM token
+              WHERE
+                user = :user AND
+                token = :token AND
+                strftime('%s', datetime(expiry, 'unixepoch', 'localtime')) > strftime('%s','now')
+            ");
+            $statement->bindValue(":user", $_COOKIE["user_id"], SQLITE3_INTEGER);
+            $statement->bindValue(":token", hash('sha256', $_COOKIE["user_token"]), SQLITE3_TEXT);
+            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+            if ($r["c"] == 0){
+                // Token is invalid, expired, clear cookies, session, and logout.
+                require_once(PATH::ACTION . "logout.php");
+                action();
+                return;
+            }
+            else{
+                // Token is valid, renew session, and assign user.
+                $_SESSION["user_id"] = $_COOKIE["user_id"];
+                $_SESSION["session"] = true;
+                $this->user = new User($_COOKIE["user_id"]);
+                $this->context->set_user($this->user);
+            }
+
+        }
+        else{
+            // Unauthenticated user. Continue
+        }
+
+        // Validate URL (check if it has the player ID).
+        $this->player = null;
+        if (sizeof($this->params) > 0 && preg_match("/^[0-9]{6,12}$/", $this->params[0]) == 1){
+            // Player ID passed in URL. Check it in database
+            $statement = $this->db->prepare("
+              SELECT
+                id,
+                user,
+                public
+              FROM player
+              WHERE id = :id
+            ");
+            $statement->bindValue(":id", $this->params[0], SQLITE3_TEXT);
+            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+            if ($r){
+                // The player exists...
+                if (null != $this->user && $r["user"] == $this->user->get_id()){
+                    // ... and it belongs to the user. Proceed.
+                    $this->player = new Player($r["id"]);
+                    $this->context->set_player($this->player);
                 }
-                else{
-                    $version = strtolower($this->params[1]);
-                    $api_params = $this->params;
-                    array_shift($api_params);
-                    array_shift($api_params);
-                    switch ($version){
-                        case "v1":
-                            require_once(__DIR__ . "/API/v1/API_Controller.php");
-                            new API_Controller($this->params);
-                            break;
+                elseif (null == $this->user || $r["user"] != $this->user->get_id()){
+                    // ... and it doesn't belong to the user...
+                    if ($r["public"] == 1){
+                        // ... and it belongs to a public profile. Proceed.
+                        $this->player = new Player($r["id"]);
+                        $this->context->set_player($this->player);
+                    }
+                    else{
+                        // ... and it belongs to a private profile. Deny access.
+                        // TODO
                     }
                 }
+            }
+        }
+        else{
+            // Player ID is not passed as URL...
+            if (null == $this->user){
+                // ... and no user logged in. Go to the landing page.
+                require_once(PATH::PAGE . "Landing_Page.php");
+                $page = new Landing_Page();
+                require_once($page->view);
                 return;
             }
-            // Special case: Actions.
-            // Not redirecting to page, just execute a function
-            // TODO: Secure actions
-            elseif (count($this->params) > 1 && strtoupper($this->params[0]) == "ACTION"){
-                switch (strtoupper($this->params[1])){
-                    case "CHANGE_GAME_MODE":
-                        require_once(PATH::ACTION . "change_game_mode.php");
-                        action();
-                        return;
-                        break;
-                    case "LOGIN":
-                        require_once(PATH::ACTION . "login.php");
-                        action();
-                        return;
-                        break;
-                    case "LOGOUT":
-                        require_once(PATH::ACTION . "logout.php");
-                        action();
-                        return;
-                        break;
-                    case "NEW_TEAM":
-                        require_once(PATH::ACTION . "new_team.php");
-                        action();
-                        return;
-                        break;
-                    case "DELETE_TEAM":
-                        require_once(PATH::ACTION . "delete_team.php");
-                        action();
-                        return;
-                        break;
-                    case "RATE_TEAM":
-                        require_once(PATH::ACTION . "rate_team.php");
-                        action();
-                        return;
-                        break;
-                    case "SAVE_RUN_TEAM":
-                        require_once(PATH::ACTION . "save_run_team.php");
-                        action();
-                        return;
-                        break;
-                    case "OPTIMIZE_GET_RUNE_LIST":
-                        require_once(PATH::ACTION . "optimize_get_rune_list.php");
-                        $response = action();
-                        if (strlen($response) > 1){
-                            echo($response);
-                            return;
-                        }
-                        else{
-                            return;
-                        }
-                        break;
-                    case "OPTIMIZE_GET_OPTIONS":
-                        require_once(PATH::ACTION . "optimize_get_options.php");
-                        $response = action();
-                        if (strlen($response) > 1){
-                            echo($response);
-                            return;
-                        }
-                        else{
-                            return;
-                        }
-                        break;
-                    case "EDIT_PROFILE":
-                        require_once(PATH::ACTION . "edit_profile.php");
-                        $response = action();
-                        if (strlen($response) > 1){
-                            echo($response);
-                            return;
-                        }
-                        else{
-                            return;
-                        }
-                        break;
-                    default:
-                        require_once(PATH::PAGE . "Error_Page.php");
-                        $page = new Error_Page(404);
-                        http_response_code(404);
+            else{
+                // ... and the user is logged in. Get last accessed account.
+                $statement = $this->db->prepare("
+                  SELECT id
+                  FROM player
+                  WHERE user = :user
+                  ORDER BY last_access DESC
+                ");
+                $statement->bindValue(":user", $this->user->get_id(), SQLITE3_INTEGER);
+                $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+                if ($r){
+                    header("Location: /" . $r["id"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH));
+                    return;
+                }
+                else{
+                    require_once(PATH::PAGE . "Landing_Page.php");
+                    $page = new Landing_Page();
+                    require_once($page->view);
+                    return;
                 }
             }
-        
-            // Select the model to load.
-            array_shift($this->params); // Remove first one, should be player_id
-            if (sizeof($this->params) == 0){
-                require_once(PATH::PAGE . "Home_Page.php");
-                $page = new Home_Page();
+        }
+
+        // Get game mode
+        $statement = $this->db->prepare("SELECT mode FROM player WHERE id = :id;");
+        $statement->bindValue(":id", $this->player->get_id(), SQLITE3_INTEGER);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r && $r["mode"] == GAME_MODE_ID::RTA){
+            $this->mode = GAME_MODE_ID::RTA;
+        }
+        else{
+            $this->mode = GAME_MODE_ID::NORMAL;
+        }
+        $this->context->set_game_mode($this->mode);
+
+    }
+
+    /**
+     * Executes the required action.
+     *
+     * Must be called after {@see Controller::prepare()}.
+     * @return void|number
+     */
+    public function action(){
+        // API call: Use API controller
+        if (count($this->params) > 0 && strtoupper($this->params[0]) == "API"){
+            if (count($this->params) == 1){
+                // TODO: API MAIN PAGE
             }
             else{
-                if (strtoupper($this->params[0]) == "RUNES"){
-                    require_once(PATH::PAGE . "Runes_Page.php");
-                    $page = new Runes_Page();
-                }
-                elseif (strtoupper($this->params[0]) == "ENCHANTMENTS"){
-                    require_once(PATH::PAGE . "Enchantments_Page.php");
-                    $page = new Enchantments_Page();
-                }
-                elseif (strtoupper($this->params[0]) == "ARTIFACTS"){
-                    require_once(PATH::PAGE . "Artifacts_Page.php");
-                    $page = new Artifacts_Page();
-                }
-                elseif (strtoupper($this->params[0]) == "GUILD"){
-                    require_once(PATH::PAGE . "Guild_Page.php");
-                    $page = new Guild_Page();
-                }
-                elseif (strtoupper($this->params[0]) == "RUNS"){
-                    require_once(PATH::PAGE . "Runs_Page.php");
-                    $page = new Runs_Page();
-                }
-                elseif (strtoupper($this->params[0]) == "STATS"){
-                    require_once(PATH::PAGE . "Stats_Page.php");
-                    $page = new Stats_Page();
-                }
-                elseif (strtoupper($this->params[0]) == "TEAMS"){
-                    require_once(PATH::PAGE . "Teams_Page.php");
-                    $page = new Teams_Page();
-                }
-                elseif (strtoupper($this->params[0]) == "PROFILE"){
-                    require_once(PATH::PAGE . "Profile_Page.php");
-                    $page = new Profile_Page();
+                $version = strtolower($this->params[1]);
+                $api_params = $this->params;
+                array_shift($api_params);
+                array_shift($api_params);
+                switch ($version){
+                    case "v1":
+                        require_once(__DIR__ . "/API/v1/API_Controller.php");
+                        new API_Controller($this->params);
+                        break;
                 }
-                elseif (strtoupper($this->params[0]) == "UNITS"){
-                    if (count($this->params) == 1){
-                        require_once(PATH::PAGE . "Units_Page.php");
-                        $page = new Units_Page();
+            }
+            return;
+        }
+        // Special case: Actions.
+        // Not redirecting to page, just execute a function
+        // TODO: Secure actions
+        elseif (count($this->params) > 1 && strtoupper($this->params[0]) == "ACTION"){
+            switch (strtoupper($this->params[1])){
+                case "CHANGE_GAME_MODE":
+                    require_once(PATH::ACTION . "change_game_mode.php");
+                    action();
+                    return;
+                    break;
+                case "LOGIN":
+                    require_once(PATH::ACTION . "login.php");
+                    action();
+                    return;
+                    break;
+                case "LOGOUT":
+                    require_once(PATH::ACTION . "logout.php");
+                    action();
+                    return;
+                    break;
+                case "NEW_TEAM":
+                    require_once(PATH::ACTION . "new_team.php");
+                    action();
+                    return;
+                    break;
+                case "DELETE_TEAM":
+                    require_once(PATH::ACTION . "delete_team.php");
+                    action();
+                    return;
+                    break;
+                case "RATE_TEAM":
+                    require_once(PATH::ACTION . "rate_team.php");
+                    action();
+                    return;
+                    break;
+                case "SAVE_RUN_TEAM":
+                    require_once(PATH::ACTION . "save_run_team.php");
+                    action();
+                    return;
+                    break;
+                case "OPTIMIZE_GET_RUNE_LIST":
+                    require_once(PATH::ACTION . "optimize_get_rune_list.php");
+                    $response = action();
+                    if (strlen($response) > 1){
+                        echo($response);
+                        return;
                     }
                     else{
-                        require_once(PATH::PAGE . "Unit_Page.php");
-                        $page = new Unit_Page($this->params[1]);
+                        return;
                     }
-                }
-                elseif (strtoupper($this->params[0]) == "MONSTERS"){
-                    if (count($this->params) == 1){
-                        require_once(PATH::PAGE . "Monsters_Page.php");
-                        $page = new Monsters_Page();
+                    break;
+                case "OPTIMIZE_GET_OPTIONS":
+                    require_once(PATH::ACTION . "optimize_get_options.php");
+                    $response = action();
+                    if (strlen($response) > 1){
+                        echo($response);
+                        return;
                     }
                     else{
-                        require_once(PATH::PAGE . "Monster_Page.php");
-                        $page = new Monster_Page($this->params[1]);
-                    }
-                }
-                elseif (strtoupper($this->params[0]) == "REPORT"){
-                    if (count($this->params) == 1){
-                        require_once(PATH::PAGE . "Report_Page.php");
-                        $page = new Report_Page();
-                    }
-                    elseif (strtoupper($this->params[1]) == "SKILLUP"){
-                        require_once(PATH::PAGE . "Report_Skillup_Page.php");
-                        $page = new Report_Skillup_Page($this->params[1]);
-                    }
-                    elseif (strtoupper($this->params[1]) == "RUNE_ENCHANTMENT"){
-                        require_once(PATH::PAGE . "Report_Rune_Enchantment_Page.php");
-                        $page = new Report_Rune_Enchantment_Page($this->params[1]);
+                        return;
                     }
-                }
-                elseif (strtoupper($this->params[0]) == "OPTIMIZER"){
-                    if (count($this->params) == 1){
-                        require_once(PATH::PAGE . "Optimizer_Page.php");
-                        $page = new Optimizer_Page();
+                    break;
+                case "EDIT_PROFILE":
+                    require_once(PATH::ACTION . "edit_profile.php");
+                    $response = action();
+                    if (strlen($response) > 1){
+                        echo($response);
+                        return;
                     }
                     else{
-                        require_once(PATH::PAGE . "Optimizer_Unit_Page.php");
-                        $page = new Optimizer_Unit_Page($this->params[1]);
+                        return;
                     }
-                }
+                    break;
+                default:
+                    require_once(PATH::PAGE . "Error_Page.php");
+                    $page = new Error_Page(404);
+                    http_response_code(404);
             }
-
-            // Load the view, or set an error code.
-            if (isset($page)){
-                require_once($page->view);
-                return 200;
-            }
-            else{
-                require_once(PATH::PAGE . "Error_Page.php");
-                $page = new Error_Page(404);
-                http_response_code(404);
-                return 404;
-            }
-        }
-
-        public function get_context(){
-            return $this->context;
         }
 
-        /**
-         * Constructor.
-         *
-         * Handles every request, creating the required models and selecting the
-         * view.
-         *
-         * @param mixed[] $params POST parameters of the request.
-         * @return int HTTP status codes 200 or 404;
-         */
-        public function __construct(){
-            $this->context = new Context();
-            session_start();
-            $this->db = DB::start();
-            $this->context->set_db($this->db);
+        // Select the model to load.
+        array_shift($this->params); // Remove first one, should be player_id
+        if (sizeof($this->params) == 0){
+            require_once(PATH::PAGE . "Home_Page.php");
+            $page = new Home_Page();
         }
-
-        /**
-         * Constructor.
-         *
-         * Receives the request params and gets itself ready.
-         *
-         * @param mixed[] $params POST parameters of the request.
-         * @return int HTTP status codes 200 or 404;
-         */
-        public function prepare($params){
-
-            // Parse parameters.
-            foreach($params as $p){
-                if (strlen($p) > 0){
-                    array_push($this->params, $p);
-                }
+        else{
+            if (strtoupper($this->params[0]) == "RUNES"){
+                require_once(PATH::PAGE . "Runes_Page.php");
+                $page = new Runes_Page();
             }
-            
-            if (
-              count($this->params) > 1 && 
-              (
-                strtoupper($this->params[0]) == "ACTION"
-              ) ||
-              strtoupper($this->params[0]) == "API"
-            ){
-                // For API calls, or login action calls, skip authentication
-                return;
+            elseif (strtoupper($this->params[0]) == "ENCHANTMENTS"){
+                require_once(PATH::PAGE . "Enchantments_Page.php");
+                $page = new Enchantments_Page();
             }
-
-            // Authentication
-            if (array_key_exists("user_token", $_COOKIE) && array_key_exists("user_id", $_COOKIE)){
-                // Authenticated user, check token.
-                $statement = $this->db->prepare("
-                  SELECT count(token) AS c
-                  FROM token
-                  WHERE
-                    user = :user AND
-                    token = :token AND
-                    strftime('%s', datetime(expiry, 'unixepoch', 'localtime')) > strftime('%s','now')
-                ");
-                $statement->bindValue(":user", $_COOKIE["user_id"], SQLITE3_INTEGER);
-                $statement->bindValue(":token", hash('sha256', $_COOKIE["user_token"]), SQLITE3_TEXT);
-                $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-                if ($r["c"] == 0){
-                    // Token is invalid, expired, clear cookies, session, and logout.
-                    require_once(PATH::ACTION . "logout.php");
-                    action();
-                    return;
+            elseif (strtoupper($this->params[0]) == "ARTIFACTS"){
+                require_once(PATH::PAGE . "Artifacts_Page.php");
+                $page = new Artifacts_Page();
+            }
+            elseif (strtoupper($this->params[0]) == "GUILD"){
+                require_once(PATH::PAGE . "Guild_Page.php");
+                $page = new Guild_Page();
+            }
+            elseif (strtoupper($this->params[0]) == "RUNS"){
+                require_once(PATH::PAGE . "Runs_Page.php");
+                $page = new Runs_Page();
+            }
+            elseif (strtoupper($this->params[0]) == "STATS"){
+                require_once(PATH::PAGE . "Stats_Page.php");
+                $page = new Stats_Page();
+            }
+            elseif (strtoupper($this->params[0]) == "TEAMS"){
+                require_once(PATH::PAGE . "Teams_Page.php");
+                $page = new Teams_Page();
+            }
+            elseif (strtoupper($this->params[0]) == "PROFILE"){
+                require_once(PATH::PAGE . "Profile_Page.php");
+                $page = new Profile_Page();
+            }
+            elseif (strtoupper($this->params[0]) == "UNITS"){
+                if (count($this->params) == 1){
+                    require_once(PATH::PAGE . "Units_Page.php");
+                    $page = new Units_Page();
                 }
                 else{
-                    // Token is valid, renew session, and assign user.
-                    $_SESSION["user_id"] = $_COOKIE["user_id"];
-                    $_SESSION["session"] = true;
-                    $this->user = new User($_COOKIE["user_id"]);
-                    $this->context->set_user($this->user);
+                    require_once(PATH::PAGE . "Unit_Page.php");
+                    $page = new Unit_Page($this->params[1]);
                 }
-
             }
-            else{
-                // Unauthenticated user. Continue
+            elseif (strtoupper($this->params[0]) == "MONSTERS"){
+                if (count($this->params) == 1){
+                    require_once(PATH::PAGE . "Monsters_Page.php");
+                    $page = new Monsters_Page();
+                }
+                else{
+                    require_once(PATH::PAGE . "Monster_Page.php");
+                    $page = new Monster_Page($this->params[1]);
+                }
             }
-
-
-            // Validate URL (check if it has the player ID).
-            $this->player = null;
-            if (sizeof($this->params) > 0 && preg_match("/^[0-9]{6,12}$/", $this->params[0]) == 1){
-                // Player ID passed in URL. Check it in database
-                $statement = $this->db->prepare("
-                  SELECT
-                    id,
-                    user,
-                    public
-                  FROM player
-                  WHERE id = :id
-                ");
-                $statement->bindValue(":id", $this->params[0], SQLITE3_TEXT);
-                $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-                if ($r){
-                    // The player exists...
-                    if (null != $this->user && $r["user"] == $this->user->get_id()){
-                        // ... and it belongs to the user. Proceed.
-                        $this->player = new Player($r["id"]);
-                        $this->context->set_player($this->player);
-                    }
-                    elseif (null == $this->user || $r["user"] != $this->user->get_id()){
-                        // ... and it doesn't belong to the user...
-                        if ($r["public"] == 1){
-                            // ... and it belongs to a public profile. Proceed.
-                            $this->player = new Player($r["id"]);
-                            $this->context->set_player($this->player);
-                        }
-                        else{
-                            // ... and it belongs to a private profile. Deny access.
-                            // TODO
-                        }
-                    }
+            elseif (strtoupper($this->params[0]) == "REPORT"){
+                if (count($this->params) == 1){
+                    require_once(PATH::PAGE . "Report_Page.php");
+                    $page = new Report_Page();
+                }
+                elseif (strtoupper($this->params[1]) == "SKILLUP"){
+                    require_once(PATH::PAGE . "Report_Skillup_Page.php");
+                    $page = new Report_Skillup_Page($this->params[1]);
+                }
+                elseif (strtoupper($this->params[1]) == "RUNE_ENCHANTMENT"){
+                    require_once(PATH::PAGE . "Report_Rune_Enchantment_Page.php");
+                    $page = new Report_Rune_Enchantment_Page($this->params[1]);
                 }
             }
-            else{
-                // Player ID is not passed as URL...
-                if (null == $this->user){
-                    // ... and no user logged in. Go to the landing page.
-                    require_once(PATH::PAGE . "Landing_Page.php");
-                    $page = new Landing_Page();
-                    require_once($page->view);
-                    return;
+            elseif (strtoupper($this->params[0]) == "OPTIMIZER"){
+                if (count($this->params) == 1){
+                    require_once(PATH::PAGE . "Optimizer_Page.php");
+                    $page = new Optimizer_Page();
                 }
                 else{
-                    // ... and the user is logged in. Get last accessed account.
-                    $statement = $this->db->prepare("
-                      SELECT id
-                      FROM player
-                      WHERE user = :user
-                      ORDER BY last_access DESC
-                    ");
-                    $statement->bindValue(":user", $this->user->get_id(), SQLITE3_INTEGER);
-                    $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-                    if ($r){
-                        header("Location: /" . $r["id"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH));
-                        return;
-                    }
-                    else{
-                        require_once(PATH::PAGE . "Landing_Page.php");
-                        $page = new Landing_Page();
-                        require_once($page->view);
-                        return;
-                    }
+                    require_once(PATH::PAGE . "Optimizer_Unit_Page.php");
+                    $page = new Optimizer_Unit_Page($this->params[1]);
                 }
             }
+        }
 
-            // Get game mode
-            $statement = $this->db->prepare("SELECT mode FROM player WHERE id = :id;");
-            $statement->bindValue(":id", $this->player->get_id(), SQLITE3_INTEGER);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r && $r["mode"] == GAME_MODE_ID::RTA){
-                $this->mode = GAME_MODE_ID::RTA;
-            }
-            else{
-                $this->mode = GAME_MODE_ID::NORMAL;
-            }
-            $this->context->set_game_mode($this->mode);
-            
-            
+        // Load the view, or set an error code.
+        if (isset($page)){
+            require_once($page->view);
+            return 200;
+        }
+        else{
+            require_once(PATH::PAGE . "Error_Page.php");
+            $page = new Error_Page(404);
+            http_response_code(404);
+            return 404;
         }
     }
-?>
+}

+ 36 - 37
application/action/change_game_mode.php

@@ -1,41 +1,40 @@
 <?php
 
-    /**
-     * File for the team score modification.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     *
-     * @category Action
-     */
+/**
+ * File for changing the game mode.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @category Action
+ */
 
-    /**
-     * Sets the score for a team.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  player
-     *  team
-     *  score
-     * Validates the data and sets the score.
-     *
-     * @return int 0 on success, negative values on error.
-     * @category Action
-     */
-    function action(){
-        $player = filter_input(INPUT_GET, "player");
-        $mode = filter_input(INPUT_GET, "mode");
-        if (mode != GAME_MODE_ID::NORMAL && mode != GAME_MODE_ID::RTA){
-            return 400;
-        }
-        $statement = get_context()->get_db()->prepare("
-          UPDATE player
-          SET mode = :mode
-          WHERE id = :id;
-        ");
-        $statement->bindValue(":mode", $mode, SQLITE3_TEXT);
-        $statement->bindValue(":id", $player, SQLITE3_TEXT);
-        $statement->execute();
-        header("HTTP/1.1 201 OK");
-        die();
-        return 201;
+/**
+ * Sets the score for a team.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  player
+ *  team
+ *  score
+ * Validates the data and sets the score.
+ *
+      * @return int 201 on success, HTTP error codes on failure.
+ * @category Action
+ */
+function action(){
+    $player = filter_input(INPUT_GET, "player");
+    $mode = filter_input(INPUT_GET, "mode");
+    if (mode != GAME_MODE_ID::NORMAL && mode != GAME_MODE_ID::RTA){
+        return 400;
     }
-?>
+    $statement = get_context()->get_db()->prepare("
+      UPDATE player
+      SET mode = :mode
+      WHERE id = :id;
+    ");
+    $statement->bindValue(":mode", $mode, SQLITE3_TEXT);
+    $statement->bindValue(":id", $player, SQLITE3_TEXT);
+    $statement->execute();
+    header("HTTP/1.1 201 OK");
+    die();
+    return 201;
+}

+ 31 - 31
application/action/delete_team.php

@@ -1,34 +1,34 @@
 <?php
+/**
+ * File for the team deletion action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the team creation action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
+/**
+ * Deletes a team.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  player: the team owner's player id.
+ *  id: the team id.
+ * 
+      * @return int 201 on success, HTTP error status codes on failure.
+ * @category Action
+ */
+function action(){
 
-    /**
-     * Deletes a team.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  player
-     *  id
-     * 
-     * @return int 0 on success, negative values on error.
-     * @category Action
-     */
-    function action(){
-
-        $player = filter_input(INPUT_POST, 'player');
-        $id = filter_input(INPUT_POST, 'id');
-        $statement = get_context()->get_db()->prepare('DELETE FROM team WHERE player = :player AND id = :id;');
-        $statement->bindValue(':player', $player, SQLITE3_TEXT);
-        $statement->bindValue(':id', $id, SQLITE3_TEXT);
-        $statement->execute();
-        $statement = get_context()->get_db()->prepare('DELETE FROM team_unit WHERE team = :id;');
-        $statement->bindValue(':id', $id, SQLITE3_TEXT);
-        $statement->execute();
-        return 0;
-    }
-?>
+    $player = filter_input(INPUT_POST, 'player');
+    $id = filter_input(INPUT_POST, 'id');
+    $statement = get_context()->get_db()->prepare('DELETE FROM team WHERE player = :player AND id = :id;');
+    $statement->bindValue(':player', $player, SQLITE3_TEXT);
+    $statement->bindValue(':id', $id, SQLITE3_TEXT);
+    $statement->execute();
+    $statement = get_context()->get_db()->prepare('DELETE FROM team_unit WHERE team = :id;');
+    $statement->bindValue(':id', $id, SQLITE3_TEXT);
+    $statement->execute();
+    return 201;
+}

+ 76 - 75
application/action/edit_profile.php

@@ -1,88 +1,89 @@
 <?php
+/**
+ * File for the profile edit action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the profile edit action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
+/**
+ * Executes the profile update.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  mail: Optional, email to update.
+ *  pass: Optional, password to update.
+ *  currentPass: Mandatory for changing password, current one.
+ *  api: Any value, indicates that the api key is to be changed.
+ * Then it updates the selected info with the prameter vlue. Multiple itemss can be updated at the
+ * same time.
+ * 
+     * @return int|string 201 on success, HTTP error codes on failure. If the API key has been updated,
+ * the new key is returned instead.
+ * @category Action
+ */
+function action(){
 
-    /**
-     * Executes the profile update.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  mail
-     *  pass + currentPass
-     *  api
-     * Then it updates the selected info with the prameter vlue. Multiple
-     * itemas can be updated at the same time.
-     * 
-     * @return int|string 0 on success, negative values on error. If the API
-     * key has been updated, the new key.
-     * @category Action
-     */
-    function action(){
+    $response = null;
 
-        $response = null;
+    // Get the current user ID.
+    $user = get_context()->get_user()->get_id();
 
-        // TODO: Dont pass user as argument, use currently logged in one.
-        $user = filter_input(INPUT_POST, 'user');
-
-        if (filter_input(INPUT_POST, "mail")){
-            $mail = filter_input(INPUT_POST, 'mail');
-            if (!filter_var($mail, FILTER_VALIDATE_EMAIL)){
-                return -1;
-            }
-            $s = get_context()->get_db()->prepare('UPDATE user SET mail = :mail WHERE id = :user;');
-            $s->bindValue(':user', $user, SQLITE3_TEXT);
-            $s->bindValue(':mail', $mail, SQLITE3_TEXT);
-            if(!$s->execute()){
-                return -2;
-            }
+    if (filter_input(INPUT_POST, "mail")){
+        $mail = filter_input(INPUT_POST, 'mail');
+        if (!filter_var($mail, FILTER_VALIDATE_EMAIL)){
+            return -1;
         }
-
-        if (filter_input(INPUT_POST, "pass")){
-            $pass = sha1(filter_input(INPUT_POST, 'pass'));
-            $currentPass = sha1(filter_input(INPUT_POST, 'currentPass'));
-            $s = get_context()->get_db()->prepare('SELECT COUNT(id) AS count FROM user WHERE id = :id AND password = :currentPass;');
-            $s->bindValue(':id', $user, SQLITE3_TEXT);
-            $s->bindValue(':currentPass', $currentPass, SQLITE3_TEXT);
-            $q = $s->execute();
-            $r = $q->fetchArray(SQLITE3_ASSOC);
-            if ($r["count"] != 1){
-                return -3;
-            }
-            $s = get_context()->get_db()->prepare('UPDATE user SET password = :pass WHERE id = :id AND password = :currentPass;');
-            $s->bindValue(':id', $user, SQLITE3_TEXT);
-            $s->bindValue(':pass', $pass, SQLITE3_TEXT);
-            $s->bindValue(':currentPass', $currentPass, SQLITE3_TEXT);
-            if(!$s->execute()){
-                return -4;
-            }
+        $s = get_context()->get_db()->prepare('UPDATE user SET mail = :mail WHERE id = :user;');
+        $s->bindValue(':user', $user, SQLITE3_TEXT);
+        $s->bindValue(':mail', $mail, SQLITE3_TEXT);
+        if(!$s->execute()){
+            return 500;
         }
+    }
 
-        if (filter_input(INPUT_POST, "api")){
-            $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-            $charactersLength = 16;
-            $api = '';
-            for ($i = 0; $i < $charactersLength; $i++) {
-                $api .= $characters[rand(0, $charactersLength - 1)];
-            }
-            $s = get_context()->get_db()->prepare('UPDATE user SET api_key = :api WHERE id = :id;');
-            $s->bindValue(':id', $user, SQLITE3_TEXT);
-            $s->bindValue(':api', $api, SQLITE3_TEXT);
-            if(!$s->execute()){
-                return -5;
-            }
-            $response = $api;
+    if (filter_input(INPUT_POST, "pass")){
+        $pass = sha1(filter_input(INPUT_POST, 'pass'));
+        $currentPass = sha1(filter_input(INPUT_POST, 'currentPass'));
+        $s = get_context()->get_db()->prepare('SELECT COUNT(id) AS count FROM user WHERE id = :id AND password = :currentPass;');
+        $s->bindValue(':id', $user, SQLITE3_TEXT);
+        $s->bindValue(':currentPass', $currentPass, SQLITE3_TEXT);
+        $q = $s->execute();
+        $r = $q->fetchArray(SQLITE3_ASSOC);
+        if ($r["count"] != 1){
+            return -500;
+        }
+        $s = get_context()->get_db()->prepare('UPDATE user SET password = :pass WHERE id = :id AND password = :currentPass;');
+        $s->bindValue(':id', $user, SQLITE3_TEXT);
+        $s->bindValue(':pass', $pass, SQLITE3_TEXT);
+        $s->bindValue(':currentPass', $currentPass, SQLITE3_TEXT);
+        if(!$s->execute()){
+            return -4;
         }
+    }
 
-        if ($response == null){
-            return 0;
+    if (filter_input(INPUT_POST, "api")){
+        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+        $charactersLength = 16;
+        $api = '';
+        for ($i = 0; $i < $charactersLength; $i++) {
+            $api .= $characters[rand(0, $charactersLength - 1)];
         }
-        else{
-            return $response;
+        $s = get_context()->get_db()->prepare('UPDATE user SET api_key = :api WHERE id = :id;');
+        $s->bindValue(':id', $user, SQLITE3_TEXT);
+        $s->bindValue(':api', $api, SQLITE3_TEXT);
+        if(! $s->execute()){
+            return 500;
         }
+        $response = $api;
+    }
+
+    if ($response == null){
+        return 201;
+    }
+    else{
+        return $response;
     }
-?>
+}

+ 88 - 84
application/action/login.php

@@ -1,90 +1,94 @@
 <?php
+/**
+ * File for the login action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the login action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
+/**
+ * Logs the user in.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  uname: username or email.
+ *  password: password.
+ * If there is a match, it generates a token and sets cookies and session variablesand
+ * redirects to the user homepage.
+ *
+      * @return int 201 on success, HTTP error codes on failure.
+ * @category Action
+ */
+function action(){
 
-    /**
-     * Logs the user in.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  uname
-     *  password
-     * If there is a match, it sets cookies and session variables, and
-     * redirects to the user homepage.
-     *
-     * @return int 0 on success, negative values on error.
-     * @category Action
-     */
-    function action(){
-
-        if (!isset($_POST['uname'], $_POST['password'])){
-            header("Location: " . URL::BASE);
-            exit();
-        }
-        $uname = SQLite3::escapeString($_POST['uname']);
-        if (strlen($uname) == 0){
-            header("Location: " . URL::BASE);
-            exit();
-        }
-        $password = SQLite3::escapeString($_POST['password']);
-        if (strlen($password) == 0){
-            header("Location: " . URL::BASE);
-            exit();
-        }
-        $password = hash('sha256', $password);
-        $statement = get_context()->get_db()->prepare("
-          SELECT
-            id,
-            name
-          FROM user
-          WHERE
-            (
-              upper(name) = upper(:name) OR
-              upper(mail) = upper(:mail)
-            ) AND
-            password = :password;
-        ");
-        $statement->bindValue(":name", $uname, SQLITE3_TEXT);
-        $statement->bindValue(":mail", $uname, SQLITE3_TEXT);
-        $statement->bindValue(":password", $password, SQLITE3_TEXT);
-        $statement->execute();
-        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-        if (!$r){
-            header("Location: " . URL::BASE);
-            exit();
-            die();
-            return 401;
-        }
-        $user = $r["id"];
-
-        // Generate token
-        //$_COOKIE["user_token"]) && isset($COOKIE["user_id"])
-        $token = bin2hex(random_bytes(32));
-        $expiry = time() + 5 * 24 * 60 * 60; // 5 days
-        $statement = get_context()->get_db()->prepare("
-          INSERT INTO token (user, token, expiry) VALUES
-          (:user, :token, :expiry);
-        ");
-        $statement->bindValue(":user", $user, SQLITE3_INTEGER);
-        $statement->bindValue(":token", hash('sha256', $token), SQLITE3_TEXT);
-        $statement->bindValue(":expiry", $expiry, SQLITE3_INTEGER);
-        $statement->execute();
-
-        setcookie("user_id", $user, $expiry, "/");
-        setcookie("user_token", $token, $expiry, "/");
-        session_regenerate_id();
-        $_SESSION['session'] = true;
-        $_SESSION['user_id'] = $user;
-        //header("Location: " . URL::BASE . "/$user/");
-        // TODO: Get player ID here?
+    if (!isset($_POST['uname'], $_POST['password'])){
         header("Location: " . URL::BASE);
-        exit();
-        die();
-        return 0;
+        //exit();
+        return 400;
     }
+    $uname = SQLite3::escapeString($_POST['uname']);
+    if (strlen($uname) == 0){
+        header("Location: " . URL::BASE);
+        //exit();
+        return 400;
+    }
+    $password = SQLite3::escapeString($_POST['password']);
+    if (strlen($password) == 0){
+        header("Location: " . URL::BASE);
+        return 400;
+        //exit();
+    }
+    $password = hash('sha256', $password);
+    $statement = get_context()->get_db()->prepare("
+      SELECT
+        id,
+        name
+      FROM user
+      WHERE
+        (
+          upper(name) = upper(:name) OR
+          upper(mail) = upper(:mail)
+        ) AND
+        password = :password;
+    ");
+    $statement->bindValue(":name", $uname, SQLITE3_TEXT);
+    $statement->bindValue(":mail", $uname, SQLITE3_TEXT);
+    $statement->bindValue(":password", $password, SQLITE3_TEXT);
+    $statement->execute();
+    $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+    if (!$r){
+        header("Location: " . URL::BASE);
+        //exit();
+        //die();
+        return 400;
+    }
+    $user = $r["id"];
+
+    // Generate token
+    //$_COOKIE["user_token"]) && isset($COOKIE["user_id"])
+    $token = bin2hex(random_bytes(32));
+    $expiry = time() + 5 * 24 * 60 * 60; // 5 days
+    $statement = get_context()->get_db()->prepare("
+      INSERT INTO token (user, token, expiry) VALUES
+      (:user, :token, :expiry);
+    ");
+    $statement->bindValue(":user", $user, SQLITE3_INTEGER);
+    $statement->bindValue(":token", hash('sha256', $token), SQLITE3_TEXT);
+    $statement->bindValue(":expiry", $expiry, SQLITE3_INTEGER);
+    $statement->execute();
+
+    setcookie("user_id", $user, $expiry, "/");
+    setcookie("user_token", $token, $expiry, "/");
+    session_regenerate_id();
+    $_SESSION['session'] = true;
+    $_SESSION['user_id'] = $user;
+    //header("Location: " . URL::BASE . "/$user/");
+    // TODO: Get player ID here?
+    header("Location: " . URL::BASE);
+    exit();
+    die();
+    return 201;
+}
 ?>

+ 24 - 27
application/action/logout.php

@@ -1,29 +1,26 @@
 <?php
+/**
+ * File for the logout action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the login action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
-
-    /**
-     * Logs the user out and redirects to the login page.
-     *
-     * Invalidates cookies and session variables.
-     * 
-     * @return int 0.
-     * @category Action
-     */
-    function action(){
-        setcookie("user_id", null, time() - 3600);
-        setcookie("user_token", null, time() - 3600);
-        session_regenerate_id();
-        $_SESSION['session'] = false;
-        $_SESSION['user_id'] = "";
-        header("Location: /");
-        die();
-        return 0;
-    }
-?>
+/**
+ * Logs the user out and redirects to the login page.
+ *
+ * Invalidates cookies and session variables.
+ * 
+ * @category Action
+ */
+function action(){
+    setcookie("user_id", null, time() - 3600);
+    setcookie("user_token", null, time() - 3600);
+    session_regenerate_id();
+    $_SESSION['session'] = false;
+    $_SESSION['user_id'] = "";
+    header("Location: /");
+}

+ 221 - 221
application/action/new_team.php

@@ -1,231 +1,231 @@
 <?php
+/**
+ * File for the team creation action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the team creation action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
+/**
+ * Logs the user out and redirects to the login page.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  player: The owner's player ID.
+ *  area_type: The area type ID ({@see AREA_TYPE_ID}).
+ *  area: The area ID.
+ *  stage: Optional, the stage ID.
+ *  difficulty: Optional, the difficulty ID ({@see DIFFICULTY_ID})
+ *  ids: Unit IDs of the party.
+ *  name: Team name.
+ *  description: Optional, team description.
+ * Validates the data and creates the team in the database.
+ * 
+      * @return int 201 on success, HTTP error status codes on failure.
+ * @category Action
+ */
+function action(){
 
-    /**
-     * Logs the user out and redirects to the login page.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  player
-     *  area_type
-     *  area
-     *  stage
-     *  difficulty
-     *  ids
-     *  name
-     *  description
-     * Validates the data and creates the team in the database.
-     * 
-     * @return int 0 on success, negative values on error.
-     * @category Action
-     */
-    function action(){
-
-        $player = filter_input(INPUT_POST, 'player');
-        $area_type = filter_input(INPUT_POST, 'area_type');
-        $area = filter_input(INPUT_POST, 'area');
-        $stage = filter_input(INPUT_POST, 'stage');
-        $difficulty = filter_input(INPUT_POST, 'difficulty');
-        if ($difficulty == ''){
+    $player = filter_input(INPUT_POST, 'player');
+    $area_type = filter_input(INPUT_POST, 'area_type');
+    $area = filter_input(INPUT_POST, 'area');
+    $stage = filter_input(INPUT_POST, 'stage');
+    $difficulty = filter_input(INPUT_POST, 'difficulty');
+    if ($difficulty == ''){
+        $difficulty = null;
+    }
+    $ids = filter_input(INPUT_POST, 'ids');
+    $name = filter_input(INPUT_POST, 'name');
+    $leader_id = filter_input(INPUT_POST, 'leader');
+    $total_front = filter_input(INPUT_POST, 'front');
+    $description = filter_input(INPUT_POST, 'description');
+    $score = 0;
+    $id = preg_split("/[\s,]+/", $ids);
+    $id_count = sizeof($id);
+    if ($name == null || strlen($name) == 0){
+        return 400;
+    }
+    switch ($area_type){
+        case AREA_TYPE_ID::SCENARIO:
+            if ($stage < 0 || $stage > 7){
+                return 400;
+            }
+            if (!($difficulty == 0 || APPLICATION::valid_id("DIFFICULTY_ID", $difficulty) || $difficulty == DIFFICULTY_ID::EASY)){
+                return 400;
+            }
+            if ($id_count < 1 || $id_count > 4){
+                return 400;
+            }
+            if (!APPLICATION::valid_id("SCENARIO_ID", $area)){
+                return 400;
+            }
+            break;
+        case AREA_TYPE_ID::CAIROS_DUNGEON:
+            if ($stage < 0){
+                return 400;
+            }
+            if ($stage > 12 && (DUNGEON_ID::GIANTS_KEEP == $area || DUNGEON_ID::DRAGONS_LAIR == $area || DUNGEON_ID::NECROPOLIS == $area)){
+                return 400;
+            }
+            if ($stage > 10 && ($area != DUNGEON_ID::GIANTS_KEEP && $area != DUNGEON_ID::DRAGONS_LAIR && $area != DUNGEON_ID::NECROPOLIS)){
+                return 400;
+            }
             $difficulty = null;
-        }
-        $ids = filter_input(INPUT_POST, 'ids');
-        $name = filter_input(INPUT_POST, 'name');
-        $leader_id = filter_input(INPUT_POST, 'leader');
-        $total_front = filter_input(INPUT_POST, 'front');
-        $description = filter_input(INPUT_POST, 'description');
-        $score = 0;
-        $id = preg_split("/[\s,]+/", $ids);
-        $id_count = sizeof($id);
-        if ($name == null || strlen($name) == 0){
-            return -1;
-        }
-        switch ($area_type){
-            case AREA_TYPE_ID::SCENARIO:
-                if ($stage < 0 || $stage > 7){
-                    return -31;
-                }
-                if (!($difficulty == 0 || APPLICATION::valid_id("DIFFICULTY_ID", $difficulty) || $difficulty == DIFFICULTY_ID::EASY)){
-                    return -32;
-                }
-                if ($id_count < 1 || $id_count > 4){
-                    return -33;
-                }
-                if (!APPLICATION::valid_id("SCENARIO_ID", $area)){
-                    return -34;
-                }
-                break;
-            case AREA_TYPE_ID::CAIROS_DUNGEON:
-                if ($stage < 0){
-                    return -35;
-                }
-                if ($stage > 12 && (DUNGEON_ID::GIANTS_KEEP == $area || DUNGEON_ID::DRAGONS_LAIR == $area || DUNGEON_ID::NECROPOLIS == $area)){
-                    return -35;
-                }
-                if ($stage > 10 && ($area != DUNGEON_ID::GIANTS_KEEP && $area != DUNGEON_ID::DRAGONS_LAIR && $area != DUNGEON_ID::NECROPOLIS)){
-                    return -35;
-                }
-                $difficulty = null;
-                if ($id_count < 1 || $id_count > 5){
-                    return -36;
-                }
-                if (!APPLICATION::valid_id("DUNGEON_ID", $area)){
-                    return -37;
-                }
-                break;
-            case AREA_TYPE_ID::RIFT_DUNGEON:
-                $stage = null;
-                $difficulty = null;
-                if ($id_count < 1 || $id_count > 6){
-                    return -39;
-                }
-                if (!APPLICATION::valid_id("ELEMENTAL_RIFT_DUNGEON_ID", $area)){
-                    return -40;
-                }
-                break;
-            case AREA_TYPE_ID::RIFT_RAID:
-                if ($stage < 0 || $stage > 5){
-                    return -41;
-                }
-                $difficulty = null;
-                if ($id_count < 1 || $id_count > 6){
-                    return -42;
-                }
-                $area = null;
-                break;
-            case AREA_TYPE_ID::ARENA:
-                $area = null;
-                $stage = null;
-                $difficulty = null;
-                break;
-            case AREA_TYPE_ID::GUILD_WAR:
-                $area = null;
-                $stage = null;
-                $difficulty = null;
-                break;
-            case AREA_TYPE_ID::GUILD_SIEGE:
-                $area = null;
-                $stage = null;
-                $difficulty = null;
-                break;
-            case AREA_TYPE_ID::TARTARUS_LABYRINTH:
-                if ($difficulty != null && !APPLICATION::valid_id("DIFFICULTY_ID", $difficulty)){
-                    return -43;
-                }
-                if ($id_count < 1 || $id_count > 5){
-                    return -44;
-                }
-                if (!APPLICATION::valid_id("LABYRINTH_STAGES_ID", $stage)){
-                    return -45;
-                }
-                break;
-            case AREA_TYPE_ID::TRIAL_OF_ASCENSION:
-                if ($difficulty != null && $difficulty != DIFFICULTY_ID::NORMAL && $difficulty != DIFFICULTY_ID::HARD){
-                    $difficulty = null;
-                }
-                $stage = null;
-                if ($id_count < 1 || $id_count > 5){
-                    return -47;
-                }
-                $area = null;
-                break;
-            case AREA_TYPE_ID::DIMENSIONAL_HOLE:
-                if ($stage < 0 || $stage > 5){
-                    return -48;
-                }
+            if ($id_count < 1 || $id_count > 5){
+                return 400;
+            }
+            if (!APPLICATION::valid_id("DUNGEON_ID", $area)){
+                return 400;
+            }
+            break;
+        case AREA_TYPE_ID::RIFT_DUNGEON:
+            $stage = null;
+            $difficulty = null;
+            if ($id_count < 1 || $id_count > 6){
+                return 400;
+            }
+            if (!APPLICATION::valid_id("ELEMENTAL_RIFT_DUNGEON_ID", $area)){
+                return 400;
+            }
+            break;
+        case AREA_TYPE_ID::RIFT_RAID:
+            if ($stage < 0 || $stage > 5){
+                return 400;
+            }
+            $difficulty = null;
+            if ($id_count < 1 || $id_count > 6){
+                return 400;
+            }
+            $area = null;
+            break;
+        case AREA_TYPE_ID::ARENA:
+            $area = null;
+            $stage = null;
+            $difficulty = null;
+            break;
+        case AREA_TYPE_ID::GUILD_WAR:
+            $area = null;
+            $stage = null;
+            $difficulty = null;
+            break;
+        case AREA_TYPE_ID::GUILD_SIEGE:
+            $area = null;
+            $stage = null;
+            $difficulty = null;
+            break;
+        case AREA_TYPE_ID::TARTARUS_LABYRINTH:
+            if ($difficulty != null && !APPLICATION::valid_id("DIFFICULTY_ID", $difficulty)){
+                return 400;
+            }
+            if ($id_count < 1 || $id_count > 5){
+                return 400;
+            }
+            if (!APPLICATION::valid_id("LABYRINTH_STAGES_ID", $stage)){
+                return 400;
+            }
+            break;
+        case AREA_TYPE_ID::TRIAL_OF_ASCENSION:
+            if ($difficulty != null && $difficulty != DIFFICULTY_ID::NORMAL && $difficulty != DIFFICULTY_ID::HARD){
                 $difficulty = null;
-                if ($id_count < 1 || $id_count > 4){
-                    return -49;
-                }
-                if (!APPLICATION::valid_id("DUNGEON_ID", $area)){
-                    return -50;
-                }
-                break;
-            case AREA_TYPE_ID::DIMENSIONAL_RIFT:
-                if ($difficulty != 0 && $difficulty != DIFFICULTY_ID::NORMAL && $difficulty != DIFFICULTY_ID::HARD){
-                    return -51;
-                }
-                $stage = null;
-                if ($id_count < 1 || $id_count > 5){
-                    return -52;
-                }
-                $area = null;
-                break;
-            default:
-                return -3;
+            }
+            $stage = null;
+            if ($id_count < 1 || $id_count > 5){
+                return 400;
+            }
+            $area = null;
+            break;
+        case AREA_TYPE_ID::DIMENSIONAL_HOLE:
+            if ($stage < 0 || $stage > 5){
+                return 400;
+            }
+            $difficulty = null;
+            if ($id_count < 1 || $id_count > 4){
+                return 400;
+            }
+            if (!APPLICATION::valid_id("DUNGEON_ID", $area)){
+                return 400;
+            }
+            break;
+        case AREA_TYPE_ID::DIMENSIONAL_RIFT:
+            if ($difficulty != 0 && $difficulty != DIFFICULTY_ID::NORMAL && $difficulty != DIFFICULTY_ID::HARD){
+                return 400;
+            }
+            $stage = null;
+            if ($id_count < 1 || $id_count > 5){
+                return 400;
+            }
+            $area = null;
+            break;
+        default:
+            return 400;
+    }
+    $unique_id = array_unique($id);
+    if ($id_count != sizeof($unique_id)){
+        return 400;
+    }
+    $s = "SELECT CASE WHEN MAX(id) IS NULL THEN 1 ELSE MAX(id) + 1 END AS id FROM team;";
+    $q = get_context()->get_db()->query($s);
+    $r = $q->fetchArray(SQLITE3_ASSOC);
+    $team_id = $r["id"];
+    $statement = get_context()->get_db()->prepare("
+      INSERT INTO team (
+        player,
+        id,
+        name,
+        description,
+        area_type,
+        area,
+        stage,
+        difficulty,
+        score
+      ) VALUES (
+        :player,
+        :id,
+        :name,
+        :description,
+        :area_type,
+        :area,
+        :stage,
+        :difficulty,
+        :score
+      );
+    ");
+    $statement->bindValue(':player', $player, SQLITE3_TEXT);
+    $statement->bindValue(':id', $team_id, SQLITE3_TEXT);
+    $statement->bindValue(':name', $name, SQLITE3_TEXT);
+    $statement->bindValue(':description', $description, SQLITE3_TEXT);
+    $statement->bindValue(':area_type', $area_type, SQLITE3_TEXT);
+    $statement->bindValue(':area', $area, SQLITE3_TEXT);
+    $statement->bindValue(':stage', $stage, SQLITE3_TEXT);
+    $statement->bindValue(':difficulty', $difficulty, SQLITE3_TEXT);
+    $statement->bindValue(':score', $score, SQLITE3_TEXT);
+    $res = $statement->execute();
+    if (!$res){
+        return 500;
+    }
+
+    $j = 0;
+    foreach (explode(',', $ids) as $i){
+        $leader = 0;
+        if ((string) $i == (string) $leader_id){
+            $leader = 1;
         }
-        $unique_id = array_unique($id);
-        if ($id_count != sizeof($unique_id)){
-            return -4;
+        $front = 0;
+        if ($j < $total_front){
+            $front = 1;
         }
-        $s = "SELECT CASE WHEN MAX(id) IS NULL THEN 1 ELSE MAX(id) + 1 END AS id FROM team;";
-        $q = get_context()->get_db()->query($s);
-        $r = $q->fetchArray(SQLITE3_ASSOC);
-        $team_id = $r["id"];
         $statement = get_context()->get_db()->prepare("
-          INSERT INTO team (
-            player,
-            id,
-            name,
-            description,
-            area_type,
-            area,
-            stage,
-            difficulty,
-            score
-          ) VALUES (
-            :player,
-            :id,
-            :name,
-            :description,
-            :area_type,
-            :area,
-            :stage,
-            :difficulty,
-            :score
-          );
+          INSERT INTO team_unit (team, unit, leader, front)
+          VALUES (:team, :unit, :leader, :front);
         ");
-        $statement->bindValue(':player', $player, SQLITE3_TEXT);
-        $statement->bindValue(':id', $team_id, SQLITE3_TEXT);
-        $statement->bindValue(':name', $name, SQLITE3_TEXT);
-        $statement->bindValue(':description', $description, SQLITE3_TEXT);
-        $statement->bindValue(':area_type', $area_type, SQLITE3_TEXT);
-        $statement->bindValue(':area', $area, SQLITE3_TEXT);
-        $statement->bindValue(':stage', $stage, SQLITE3_TEXT);
-        $statement->bindValue(':difficulty', $difficulty, SQLITE3_TEXT);
-        $statement->bindValue(':score', $score, SQLITE3_TEXT);
-        $res = $statement->execute();
-        if (!$res){
-            return -5;
-        }
-
-        $j = 0;
-        foreach (explode(',', $ids) as $i){
-            $leader = 0;
-            if ((string) $i == (string) $leader_id){
-                $leader = 1;
-            }
-            $front = 0;
-            if ($j < $total_front){
-                $front = 1;
-            }
-            $statement = get_context()->get_db()->prepare("
-              INSERT INTO team_unit (team, unit, leader, front)
-              VALUES (:team, :unit, :leader, :front);
-            ");
-            $statement->bindValue(':team', $team_id, SQLITE3_TEXT);
-            $statement->bindValue(':unit', $i, SQLITE3_TEXT);
-            $statement->bindValue(':leader', $leader, SQLITE3_TEXT);
-            $statement->bindValue(':front', $front, SQLITE3_TEXT);
-            $statement->execute();
-            $j ++;
-        }
-        return 0;
+        $statement->bindValue(':team', $team_id, SQLITE3_TEXT);
+        $statement->bindValue(':unit', $i, SQLITE3_TEXT);
+        $statement->bindValue(':leader', $leader, SQLITE3_TEXT);
+        $statement->bindValue(':front', $front, SQLITE3_TEXT);
+        $statement->execute();
+        $j ++;
     }
-?>
+    return 201;
+}

+ 163 - 159
application/action/optimize_get_options.php

@@ -1,179 +1,183 @@
 <?php
+/**
+ * File for the team creation action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the optimization action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
+/**
+ * Executes the optimization action.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  player: The player ID.
+ *  unit: The unit ID.
+ *  tuning: {@todo Documentproperly}.
+ *  options: JSON with rune sets.
+ *
+     * @return int|string a JSON with the runes on success, negative integers on error. 0 if no errors
+ * ocurred, but no results were found.
+ * @category Action
+ */
+function action(){
 
-    /**
-     * Executes the optimization action.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  player
-     *  unit
-     *  ... TODO
-     *
-     * @return int|string 0 on success, negative values on error. If the API
-     * key has been updated, the new key.
-     * @category Action
-     */
-    function action(){
+    // Increase max execution time.
+    set_time_limit(60);
 
-        // Increase max execution time.
-        set_time_limit(60);
+    $runes = [];
 
-        $runes = [];
+    $response = null;
 
-        $response = null;
-
-        $player = filter_input(INPUT_POST, 'player');
-        if ($player == null){
-            return -1;
-        }
+    $player = filter_input(INPUT_POST, 'player');
+    if ($player == null){
+        return -1;
+    }
 
-        $unit_id = filter_input(INPUT_POST, 'unit');
-        if ($unit_id == null){
-            return -2;
-        }
-        $unit = new Unit($unit_id, true, $player);
+    $unit_id = filter_input(INPUT_POST, 'unit');
+    if ($unit_id == null){
+        return -2;
+    }
+    $unit = new Unit($unit_id, true, $player);
+    $base_stats = $unit->get_base_stats();
+    $building_stats = $unit->get_base_stats();
+    $artifact_stats = $unit->get_base_stats();
 
-        $tuning = filter_input(INPUT_POST, 'tuning');
-        if ($tuning == null){
-            return -1;
-        }
+    $tuning = filter_input(INPUT_POST, 'tuning');
+    if ($tuning == null){
+        return -1;
+    }
 
-        $options = json_decode(filter_input(INPUT_POST, 'options'), true);
-        if ($options == null){
-            return -2;
-        }
-        foreach ($options as $option){
-            $set = [
-                "runes" => [],
-                "stats" => [
-                    "attack" => $unit->attack,
-                    "defense" => $unit->defense,
-                    "hp" => $unit->hp,
-                    "speed" => $unit->speed,
-                    "crit_rate" => $unit->crit_rate,
-                    "crit_damage" => $unit->crit_damage,
-                    "accuracy" => $unit->accuracy,
-                    "resistance" => $unit->resistance,
-                    "ehp" => 0,
-                    "dmg" => 0
-                ]
+    $options = json_decode(filter_input(INPUT_POST, 'options'), true);
+    if ($options == null){
+        return -2;
+    }
+    foreach ($options as $option){
+        $set = [
+            "runes" => [],
+            "stats" => [
+                "atk" => $base_stats["atk"] + $building_stats["atk"] + $artifact_stats["atk"],
+                "def" => $base_stats["def"] + $building_stats["def"] + $artifact_stats["def"],
+                "hp"  => $base_stats["hp"]  + $building_stats["hp"]  + $artifact_stats["hp"],
+                "spd" => $base_stats["spd"] + $building_stats["spd"] + $artifact_stats["spd"],
+                "crr" => $base_stats["crr"] + $building_stats["crr"] + $artifact_stats["crr"],
+                "crd" => $base_stats["crd"] + $building_stats["crd"] + $artifact_stats["crd"],
+                "acc" => $base_stats["acc"] + $building_stats["acc"] + $artifact_stats["acc"],
+                "res" => $base_stats["res"] + $building_stats["res"] + $artifact_stats["res"],
+                "ehp" => 0,
+                "dmg" => 0
+            ]
+        ];
+        foreach ($option["runes"] as $rune_option){
+            $rune = new Rune($rune_option["ID"]);
+            $r = [
+                "id" => $rune_option["ID"],
+                "html" => HTML::rune_table($rune)
             ];
-            foreach ($option["runes"] as $rune_option){
-                $rune = new Rune($rune_option["ID"]);
-                $r = [
-                    "id" => $rune_option["ID"],
-                    "html" => HTML::rune_table($rune)
-                ];
 
-                // Calculate stat increment
-                // TODO: Main stat at level!
-                $stat_ids = [
-                    $rune->get_main_stat()->get_stat(),
-                    ($rune->get_innate_stat() != null ? $rune->get_innate_stat()->get_stat() : null),
-                    (sizeof($rune->get_substats() > 0 ? $rune->get_substats()[0]->get_stat() : null)),
-                    (sizeof($rune->get_substats() > 1 ? $rune->get_substats()[1]->get_stat() : null)),
-                    (sizeof($rune->get_substats() > 2 ? $rune->get_substats()[2]->get_stat() : null)),
-                    (sizeof($rune->get_substats() > 3 ? $rune->get_substats()[3]->get_stat() : null))
-                ];
-                $main_value = $rune->get_main_stat()->get_value();
-                switch ($tuning){
-                    case 1: // All +12
-                        if ($rune->get_level() < 12){
-                            $main_value = $rune->get_main_stat_at_level(12);
-                        }
+            // Calculate stat increment
+            // TODO: Main stat at level!
+            $stat_ids = [
+                $rune->get_main_stat()->get_stat(),
+                ($rune->get_innate_stat() != null ? $rune->get_innate_stat()->get_stat() : null),
+                (sizeof($rune->get_substats() > 0 ? $rune->get_substats()[0]->get_stat() : null)),
+                (sizeof($rune->get_substats() > 1 ? $rune->get_substats()[1]->get_stat() : null)),
+                (sizeof($rune->get_substats() > 2 ? $rune->get_substats()[2]->get_stat() : null)),
+                (sizeof($rune->get_substats() > 3 ? $rune->get_substats()[3]->get_stat() : null))
+            ];
+            $main_value = $rune->get_main_stat()->get_value();
+            switch ($tuning){
+                case 1: // All +12
+                    if ($rune->get_level() < 12){
+                        $main_value = $rune->get_main_stat_at_level(12);
+                    }
+                    break;
+                case 2: // Even +15, Odd + 12
+                    if ($rune->get_level() < 15 && $rune->get_slot() % 2 == 0){
+                        $main_value = $rune->get_main_stat_at_level(15);
+                    }
+                    elseif ($rune->get_level() < 12 && $rune->get_slot() % 2 != 0){
+                        $main_value = $rune->get_main_stat_at_level(12);
+                    }
+                    break;
+                case 3: // All +15
+                    if ($rune->get_level() < 15){
+                        $main_value = $rune->get_main_stat_at_level(15);
+                    }
+                    break;
+            }
+            $stat_values = [
+                $main_value,
+                ($stat_ids[1] != null ? $rune->get_innate_stat()->get_value() : 0),
+                ($stat_ids[2] != null ? $rune->get_substats()[0]->get_value() : 0),
+                ($stat_ids[3] != null ? $rune->get_substats()[1]->get_value() : 0),
+                ($stat_ids[4] != null ? $rune->get_substats()[2]->get_value() : 0),
+                ($stat_ids[5] != null ? $rune->get_substats()[3]->get_value() : 0)
+            ];
+            for ($i = 0; $i < 6; $i ++){
+                switch ($stat_ids[$i]){
+                    case RUNE_STAT_ID::ATK:
+                        $set["stats"]["atk"] += $stat_values[$i];
                         break;
-                    case 2: // Even +15, Odd + 12
-                        if ($rune->get_level() < 15 && $rune->get_slot() % 2 == 0){
-                            $main_value = $rune->get_main_stat_at_level(15);
-                        }
-                        elseif ($rune->get_level() < 12 && $rune->get_slot() % 2 != 0){
-                            $main_value = $rune->get_main_stat_at_level(12);
-                        }
+                    case RUNE_STAT_ID::ATK_P:
+                        $set["stats"]["atk"] += ceil($base_stats()["atk"] * $stat_values[$i] / 100);
                         break;
-                    case 3: // All +15
-                        if ($rune->get_level() < 15){
-                            $main_value = $rune->get_main_stat_at_level(15);
-                        }
+                    case RUNE_STAT_ID::DEF:
+                        $set["stats"]["def"] += $stat_values[$i];
+                        break;
+                    case RUNE_STAT_ID::DEF_P:
+                        $set["stats"]["def"] += ceil($base_stats["def"] * $stat_values[$i] / 100);
+                        break;
+                    case RUNE_STAT_ID::HP:
+                        $set["stats"]["hp"] += $stat_values[$i];
+                        break;
+                    case RUNE_STAT_ID::HP_P:
+                        $set["stats"]["hp"] += ceil($base_stats["hp"] * $stat_values[$i] / 100);
+                        break;
+                    case RUNE_STAT_ID::SPD:
+                        $set["stats"]["spd"] += $stat_values[$i];
+                        break;
+                    case RUNE_STAT_ID::CRR:
+                        $set["stats"]["crr"] += $stat_values[$i];
+                        break;
+                    case RUNE_STAT_ID::CRD:
+                        $set["stats"]["crd"] += $stat_values[$i];
+                        break;
+                    case RUNE_STAT_ID::ACC:
+                        $set["stats"]["acc"] += $stat_values[$i];
+                        break;
+                    case RUNE_STAT_ID::RES:
+                        $set["stats"]["res"] += $stat_values[$i];
                         break;
                 }
-                $stat_values = [
-                    $main_value,
-                    ($stat_ids[1] != null ? $rune->get_innate_stat()->get_value() : 0),
-                    ($stat_ids[2] != null ? $rune->get_substats()[0]->get_value() : 0),
-                    ($stat_ids[3] != null ? $rune->get_substats()[1]->get_value() : 0),
-                    ($stat_ids[4] != null ? $rune->get_substats()[2]->get_value() : 0),
-                    ($stat_ids[5] != null ? $rune->get_substats()[3]->get_value() : 0)
-                ];
-                for ($i = 0; $i < 6; $i ++){
-                    switch ($stat_ids[$i]){
-                        case RUNE_STAT_ID::ATK:
-                            $set["stats"]["attack"] += $stat_values[$i];
-                            break;
-                        case RUNE_STAT_ID::ATK_P:
-                            $set["stats"]["attack"] += ceil($unit->get_base_stats()["ATK"] * $stat_values[$i] / 100);
-                            break;
-                        case RUNE_STAT_ID::DEF:
-                            $set["stats"]["defense"] += $stat_values[$i];
-                            break;
-                        case RUNE_STAT_ID::DEF_P:
-                            $set["stats"]["defense"] += ceil($unit->get_base_stats()["DEF"] * $stat_values[$i] / 100);
-                            break;
-                        case RUNE_STAT_ID::HP:
-                            $set["stats"]["hp"] += $stat_values[$i];
-                            break;
-                        case RUNE_STAT_ID::HP_P:
-                            $set["stats"]["hp"] += ceil($unit->get_base_stats()["HP"] * $stat_values[$i] / 100);
-                            break;
-                        case RUNE_STAT_ID::SPD:
-                            $set["stats"]["speed"] += $stat_values[$i];
-                            break;
-                        case RUNE_STAT_ID::CRR:
-                            $set["stats"]["crit_rate"] += $stat_values[$i];
-                            break;
-                        case RUNE_STAT_ID::CRD:
-                            $set["stats"]["crit_damage"] += $stat_values[$i];
-                            break;
-                        case RUNE_STAT_ID::ACC:
-                            $set["stats"]["accuracy"] += $stat_values[$i];
-                            break;
-                        case RUNE_STAT_ID::CRR:
-                            $set["stats"]["resistance"] += $stat_values[$i];
-                            break;
-                    }
-                }
-
-                // Calculate EHP and DMG
-                $set["stats"]["ehp"] = ceil(((($set["stats"]["def"] * 3.5) + 1140) * $set["stats"]["hp"]) / 1000);
-                $atk = $set["stats"]["attack"];
-                $crr = $set["stats"]["crit_rate"];
-                if ($crr > 100){
-                    $crr = 100;
-                }
-                $crd = $set["stats"]["crit_damage"];
-                $edmg = ceil(($atk * (100 - $crr) / 100) + (($atk + ($atk * $crd / 100)) * $crr / 100));
-                $set["stats"]["dmg"] = $edmg;
+            }
 
-                // Add to the array
-                array_push($set["runes"], $r);
-                
+            // Calculate EHP and DMG
+            $set["stats"]["ehp"] = ceil(((($set["stats"]["def"] * 3.5) + 1140) * $set["stats"]["hp"]) / 1000);
+            $atk = $set["stats"]["atk"];
+            $crr = $set["stats"]["crr"];
+            if ($crr > 100){
+                $crr = 100;
             }
-            array_push($runes, $set);
-        }
+            $crd = $set["stats"]["crd"];
+            $edmg = ceil(($atk * (100 - $crr) / 100) + (($atk + ($atk * $crd / 100)) * $crr / 100));
+            $set["stats"]["dmg"] = $edmg;
+
+            // Add to the array
+            array_push($set["runes"], $r);
 
-        // Send back the response
-        $response = json_encode($runes);
-        if ($response == null){
-            return 0;
-        }
-        else{
-            return $response;
         }
+        array_push($runes, $set);
+    }
+
+    // Send back the response
+    $response = json_encode($runes);
+    if ($response == null){
+        return 0;
+    }
+    else{
+        return $response;
     }
-?>
+}

+ 328 - 328
application/action/optimize_get_rune_list.php

@@ -1,361 +1,361 @@
 <?php
+/**
+ * File for the rune optimization action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the optimization action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
+/**
+ * Selects the runes for optimization.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  player: Player ID.
+ *  mode: Game mode ({@see GAME_MODE_ID}).
+ *  unit: Unit ID.
+ *  source: Source of the runes to select (assigned, unassigned, ...).
+ *  limit: {@todo: Currently not in use. Implement or delete}.
+ *  tuning: {@todo Document properly}.
+ *  set[]: Selected rune sets ({@see RUNE_SET_ID}).
+ *  
+ * Then it selects all the runes matching the cryteria.
+ * 
+     * @return int|string a JSON with the runes on success, negative integers on error. 0 if no errors
+ * ocurred, but no results were found.
+ * @category Action
+ */
+function action(){
 
-    /**
-     * TODO
-     * Executes the optimization action.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  mail
-     *  pass + currentPass
-     *  api
-     * Then it updates the selected info with the prameter vlue. Multiple
-     * itemas can be updated at the same time.
-     * 
-     * @return int|string 0 on success, negative values on error. If the API
-     * key has been updated, the new key.
-     * @category Action
-     */
-    function action(){
-        
-        error_log("GETTING RUNE LIST");
+    // Increase max execution time.
+    set_time_limit(60);
 
-        // Increase max execution time.
-        set_time_limit(60);
-        
-        $candidates = [
-            1 => [],
-            2 => [],
-            3 => [],
-            4 => [],
-            5 => [],
-            6 => []
-        ];
+    $candidates = [
+        1 => [],
+        2 => [],
+        3 => [],
+        4 => [],
+        5 => [],
+        6 => []
+    ];
 
-        $response = null;
+    $response = null;
 
-        $player = filter_input(INPUT_POST, 'player');
-        if ($player == null){
-            return -1;
-        }
-        error_log("POST PLAYRER");
-        $game_mode = GAME_MODE_ID::NORMAL;
-        if (filter_input(INPUT_POST, 'mode') == GAME_MODE_ID::RTA){
-            $game_mode = GAME_MODE_ID::RTA;
-        }
+    $player = filter_input(INPUT_POST, 'player');
+    if ($player == null){
+        return -1;
+    }
+    $game_mode = GAME_MODE_ID::NORMAL;
+    if (filter_input(INPUT_POST, 'mode') == GAME_MODE_ID::RTA){
+        $game_mode = GAME_MODE_ID::RTA;
+    }
 
-        $unit_id = filter_input(INPUT_POST, 'unit');
-        if ($unit_id == null){
-            return -2;
-        }
+    $unit_id = filter_input(INPUT_POST, 'unit');
+    if ($unit_id == null){
+        return -2;
+    }
 
-        // Sets
-        $sets = [];
-        foreach ($_POST["set"] as $x){
-            array_push($sets, intval($x));
-        }
-        if (sizeof($sets) < 2 || sizeof($sets) > 3){
-            return -3;
-        }
+    // Sets
+    $sets = [];
+    foreach ($_POST["set"] as $x){
+        array_push($sets, intval($x));
+    }
+    if (sizeof($sets) < 2 || sizeof($sets) > 3){
+        return -3;
+    }
 
-        // Main stats in even slots.
-        $stats = [];
-        foreach ($_POST["stat"] as $x){
-            array_push($stats, intval($x));
-        }
+    // Main stats in even slots.
+    $stats = [];
+    foreach ($_POST["stat"] as $x){
+        array_push($stats, intval($x));
+    }
 
-        $source = filter_input(INPUT_POST, 'source');
-        if ($source == null){
-            return -4;
-        }
-        
-        $limit = intval(filter_input(INPUT_POST, 'limit'));
-        if ($limit == 0){
-            return -5;
-        }
+    $source = filter_input(INPUT_POST, 'source');
+    if ($source == null){
+        return -4;
+    }
 
-        $tuning = filter_input(INPUT_POST, 'tuning');
-        if ($tuning == null){
-            return -6;
-        }
+    $limit = intval(filter_input(INPUT_POST, 'limit'));
+    if ($limit == 0){
+        return -5;
+    }
 
-        // Instantiate the unit
-        $unit = new Unit($unit_id);
+    $tuning = filter_input(INPUT_POST, 'tuning');
+    if ($tuning == null){
+        return -6;
+    }
 
-        // Get build query:
-        $base_s = "
-          SELECT
-            id,
-            type,
-            slot,
-            level,
-            stars,
-            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat,
-            (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat_value,
-            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat,
-            (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat_value,
-            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1,
-            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1_value,
-            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2,
-            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2_value,
-            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3,
-            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3_value,
-            (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4,
-            (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4_value
-          FROM rune
-          WHERE
-            player = :player AND
-            type IN (
-        ";
-        foreach ($sets as $set){
-            $base_s .= ($set . ",");
-        }
-        $base_s .= "-1) AND ";
-        switch ($source){
-            case 0: // Storage only (or itself)
-                $base_s .= "
-                  (
-                    rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
-                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . ")
-                  )";
-                break;
-            case 1: // Units in no teams (or itself)
-                $base_s .= "
-                  (
-                    rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
-                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . ")
-                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . " AND unit NOT IN (SELECT DISTINCT unit FROM team_unit))
-                  )
-                ";
-                break;
-            case 2: // Units in teams with 0 score (or itself)
-                $base_s .= "
-                  (
-                    rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
-                    OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . ")
-                    OR rune.id NOT IN (
+    // Instantiate the unit
+    $unit = new Unit($unit_id);
+
+    // Get build query:
+    $base_s = "
+      SELECT
+        id,
+        type,
+        slot,
+        level,
+        stars,
+        (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat,
+        (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::MAIN . " ) AS main_stat_value,
+        (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat,
+        (SELECT value FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::INNATE . " ) AS innate_stat_value,
+        (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1,
+        (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_1 . " ) AS substat_1_value,
+        (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2,
+        (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_2 . " ) AS substat_2_value,
+        (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3,
+        (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_3 . " ) AS substat_3_value,
+        (SELECT stat FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4,
+        (SELECT value + grind FROM rune_stat WHERE rune = rune.id AND slot = " . RUNE_STAT_SLOT_ID::SUBSTAT_4 . " ) AS substat_4_value
+      FROM rune
+      WHERE
+        player = :player AND
+        type IN (
+    ";
+    foreach ($sets as $set){
+        $base_s .= ($set . ",");
+    }
+    $base_s .= "-1) AND ";
+    switch ($source){
+        case 0: // Storage only (or itself)
+            $base_s .= "
+              (
+                rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
+                OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . ")
+              )";
+            break;
+        case 1: // Units in no teams (or itself)
+            $base_s .= "
+              (
+                rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
+                OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . ")
+                OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . " AND unit NOT IN (SELECT DISTINCT unit FROM team_unit))
+              )
+            ";
+            break;
+        case 2: // Units in teams with 0 score (or itself)
+            $base_s .= "
+              (
+                rune.id IN (SELECT DISTINCT unit FROM unit_rune WHERE unit = :unit_id AND rta = " . $game_mode . ")
+                OR rune.id NOT IN (SELECT DISTINCT unit FROM unit_rune WHERE rta = " . $game_mode . ")
+                OR rune.id NOT IN (
+                  SELECT DISTINCT unit 
+                  FROM unit_rune 
+                  WHERE
+                    rta = " . $game_mode . "
+                    AND unit NOT IN (
                       SELECT DISTINCT unit 
-                      FROM unit_rune 
+                      FROM
+                        team,
+                        team_unit
                       WHERE
-                        rta = " . $game_mode . "
-                        AND unit NOT IN (
-                          SELECT DISTINCT unit 
-                          FROM
-                            team,
-                            team_unit
-                          WHERE
-                            team.id = team_unit.team
-                            AND team.score > 0
-                        )
+                        team.id = team_unit.team
+                        AND team.score > 0
                     )
-                  )
-                ";
-                break;
-            case 3: // Units with lower overall score (or itself)
-                // TODO
-                break;
-            case 4: // All runes - dont filter
-                $base_s .= " 1 = 1 ";
-                break;
-            default: // Invalid options - return nothing
-                $base_s .= " 1 = 0 ";
-        }
-        $s_order = " ORDER BY stars DESC, original_quality DESC, max_efficiency DESC, efficiency DESC, level DESC";
-        $s_in = " main_stat IN (:stat_0, :stat_1, :stat_2) ";
+                )
+              )
+            ";
+            break;
+        case 3: // Units with lower overall score (or itself)
+            // TODO
+            break;
+        case 4: // All runes - dont filter
+            $base_s .= " 1 = 1 ";
+            break;
+        default: // Invalid options - return nothing
+            $base_s .= " 1 = 0 ";
+    }
+    $s_order = " ORDER BY stars DESC, original_quality DESC, max_efficiency DESC, efficiency DESC, level DESC";
+    $s_in = " main_stat IN (:stat_0, :stat_1, :stat_2) ";
 
-        $s = ["", "", "", "", "", "", ""];
-        $s[1] = $base_s . " AND slot = 1 " . $s_order;
-        $s[3] = $base_s . " AND slot = 3 " . $s_order;
-        $s[5] = $base_s . " AND slot = 5 " . $s_order;
-        $s[2] = $base_s . " AND slot = 2 AND " . $s_in . $s_order;
-        $s[4] = $base_s . " AND slot = 4 AND " . $s_in . $s_order;
-        $s[6] = $base_s . " AND slot = 6 AND " . $s_in . $s_order;
+    $s = ["", "", "", "", "", "", ""];
+    $s[1] = $base_s . " AND slot = 1 " . $s_order;
+    $s[3] = $base_s . " AND slot = 3 " . $s_order;
+    $s[5] = $base_s . " AND slot = 5 " . $s_order;
+    $s[2] = $base_s . " AND slot = 2 AND " . $s_in . $s_order;
+    $s[4] = $base_s . " AND slot = 4 AND " . $s_in . $s_order;
+    $s[6] = $base_s . " AND slot = 6 AND " . $s_in . $s_order;
 
-        $total_candidates = 0;
-        for ($i = 1; $i <= 6; $i ++){
-            error_log($s[$i]);
-            $statement = get_context()->get_db()->prepare($s[$i]);
-            $statement->bindValue(':player', $player, SQLITE3_TEXT);
-            $statement->bindValue(':unit_id', $unit_id, SQLITE3_TEXT);
-            $statement->bindValue(':stat_0', $stats[0], SQLITE3_TEXT);
-            $statement->bindValue(':stat_1', $stats[1], SQLITE3_TEXT);
-            $statement->bindValue(':stat_2', $stats[2], SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $rune = create_rune_array($unit, $r, $tuning);
-                //array_push($candidates[$i], new Rune($r["id"]));
-                array_push($candidates[$i], $rune);
-                $total_candidates ++;
-            }
-        }
-        //$max_combinations = sizeof($candidates[1]) * sizeof($candidates[2]) * sizeof($candidates[3]) * sizeof($candidates[4]) * sizeof($candidates[5]) * sizeof($candidates[6]);
-        
-        // Build response
-        $response = json_encode($candidates);
-        if ($response == null){
-            return 0;
-        }
-        else{
-            return $response;
+    $total_candidates = 0;
+    for ($i = 1; $i <= 6; $i ++){
+        //error_log($s[$i]);
+        $statement = get_context()->get_db()->prepare($s[$i]);
+        $statement->bindValue(':player', $player, SQLITE3_TEXT);
+        $statement->bindValue(':unit_id', $unit_id, SQLITE3_TEXT);
+        $statement->bindValue(':stat_0', $stats[0], SQLITE3_TEXT);
+        $statement->bindValue(':stat_1', $stats[1], SQLITE3_TEXT);
+        $statement->bindValue(':stat_2', $stats[2], SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            $rune = create_rune_array($unit, $r, $tuning);
+            //array_push($candidates[$i], new Rune($r["id"]));
+            array_push($candidates[$i], $rune);
+            $total_candidates ++;
         }
     }
+    //$max_combinations = sizeof($candidates[1]) * sizeof($candidates[2]) * sizeof($candidates[3]) * sizeof($candidates[4]) * sizeof($candidates[5]) * sizeof($candidates[6]);
 
-    /**
-     * Creates an array with the stats provided by a rune on a unit.
-     *
-     * @param Unit $unit Target unit.
-     * @param int $r Rune main stat ID.
-     * @param int $stars Rune stars.
-     * @return int Value of the main stat at the selected level.
-     */
-    function create_rune_array($unit, $r, $tuning){
-        $rune = [
-            "ID" => $r["id"],
-            "TYPE" => $r["type"],
-            "ATK" => 0,
-            "DEF" => 0,
-            "HP" => 0,
-            "SPD" => 0,
-            "CRR" => 0,
-            "CRD" => 0,
-            "ACC" => 0,
-            "RES" => 0
-        ];
-        // Calculate main stat value based on requested level.
-        $level = $r["level"];
-        $main_value = $r["main_stat_value"];
-        switch ($tuning){
-            case 1: // All +12
-                if ($level < 12){
-                    $main_value = get_main_stat_at_level(12, $r["main_stat"], $r["stars"]);
-                }
-                break;
-            case 2: // Even +15, Odd + 12
-                if ($level < 15 && $r["slot"] % 2 == 0){
-                    $main_value = get_main_stat_at_level(15, $r["main_stat"], $r["stars"]);
-                }
-                elseif ($level < 12 && $r["slot"] % 2 != 0){
-                    $main_value = get_main_stat_at_level(12, $r["main_stat"], $r["stars"]);
-                }
-                break;
-            case 3: // All +15
-                if ($level < 15){
-                    $main_value = get_main_stat_at_level(15, $r["main_stat"], $r["stars"]);
-                }
-                break;
-        }
-        // Array to loop.
-        $stats = [
-            [
-                "STAT" => $r["main_stat"],
-                "VALUE" => $main_value
-            ],
-            [
-                "STAT" => $r["innate_stat"],
-                "VALUE" => $r["innate_stat_value"]
-            ],
-            [
-                "STAT" => $r["substat_1"],
-                "VALUE" => $r["substat_1_value"]
-            ],
-            [
-                "STAT" => $r["substat_2"],
-                "VALUE" => $r["substat_2_value"]
-            ],
-            [
-                "STAT" => $r["substat_3"],
-                "VALUE" => $r["substat_3_value"]
-            ],
-            [
-                "STAT" => $r["substat_4"],
-                "VALUE" => $r["substat_4_value"]
-            ]
-        ];
-        foreach ($stats as $stat){
-            switch ($stat["STAT"]){
-                case RUNE_STAT_ID::ATK:
-                    $rune["ATK"] += $stat["VALUE"];
-                    break;
-                case RUNE_STAT_ID::ATK_P:
-                    $rune["ATK"] += ($unit->get_base_stats()["atk"] * $stat["VALUE"] / 100);
-                    break;
-                case RUNE_STAT_ID::DEF:
-                    $rune["DEF"] += $stat["VALUE"];
-                    break;
-                case RUNE_STAT_ID::DEF_P:
-                    $rune["DEF"] += ($unit->get_base_stats()["def"] * $stat["VALUE"] / 100);
-                    break;
-                case RUNE_STAT_ID::HP:
-                    $rune["HP"] += $stat["VALUE"];
-                    break;
-                case RUNE_STAT_ID::HP_P:
-                    $rune["HP"] += ($unit->get_base_stats()["hp"] * $stat["VALUE"] / 100);
-                    break;
-                case RUNE_STAT_ID::SPD:
-                    $rune["SPD"] += $stat["VALUE"];
-                    break;
-                case RUNE_STAT_ID::CRR:
-                    $rune["CRR"] += $stat["VALUE"];
-                    break;
-                case RUNE_STAT_ID::CRD:
-                    $rune["CRD"] += $stat["VALUE"];
-                    break;
-                case RUNE_STAT_ID::ACC:
-                    $rune["ACC"] += $stat["VALUE"];
-                    break;
-                case RUNE_STAT_ID::RES:
-                    $rune["RES"] += $stat["VALUE"];
-                    break;
-            }
-        }
-        return $rune;
+    // Build response
+    $response = json_encode($candidates);
+    if ($response == null){
+        return 0;
+    }
+    else{
+        return $response;
     }
+}
 
-    /**
-     * Gets the value of the main stat at an arbitrary level.
-     *
-     * @param int $level Desired level.
-     * @param int $stat Rune main stat ID.
-     * @param int $stars Rune stars.
-     * @return int Value of the main stat at the selected level.
-     */
-    function get_main_stat_at_level($level, $stat, $stars){
-        $level = intval($level);
-        if ($level < 0 || $level > 15){
-            return 0;
-        }
-        switch ($stat){
-            case RUNE_STAT_ID::HP:
-                return RUNE_STAT_VALUES::HP[$stars][$level];
-            case RUNE_STAT_ID::HP_P:
-                return RUNE_STAT_VALUES::HP_P[$stars][$level];
+/**
+ * Creates an array with the stats provided by a rune on a unit.
+ *
+ * @param Unit $unit Target unit.
+ * @param int $r Rune main stat ID.
+ * @param int $stars Rune stars.
+      * @return int Value of the main stat at the selected level.
+ */
+function create_rune_array($unit, $r, $tuning){
+    $rune = [
+        "ID" => $r["id"],
+        "TYPE" => $r["type"],
+        "ATK" => 0,
+        "DEF" => 0,
+        "HP" => 0,
+        "SPD" => 0,
+        "CRR" => 0,
+        "CRD" => 0,
+        "ACC" => 0,
+        "RES" => 0
+    ];
+    // Calculate main stat value based on requested level.
+    $level = $r["level"];
+    $main_value = $r["main_stat_value"];
+    switch ($tuning){
+        case 1: // All +12
+            if ($level < 12){
+                $main_value = get_main_stat_at_level(12, $r["main_stat"], $r["stars"]);
+            }
+            break;
+        case 2: // Even +15, Odd + 12
+            if ($level < 15 && $r["slot"] % 2 == 0){
+                $main_value = get_main_stat_at_level(15, $r["main_stat"], $r["stars"]);
+            }
+            elseif ($level < 12 && $r["slot"] % 2 != 0){
+                $main_value = get_main_stat_at_level(12, $r["main_stat"], $r["stars"]);
+            }
+            break;
+        case 3: // All +15
+            if ($level < 15){
+                $main_value = get_main_stat_at_level(15, $r["main_stat"], $r["stars"]);
+            }
+            break;
+    }
+    // Array to loop.
+    $stats = [
+        [
+            "STAT" => $r["main_stat"],
+            "VALUE" => $main_value
+        ],
+        [
+            "STAT" => $r["innate_stat"],
+            "VALUE" => $r["innate_stat_value"]
+        ],
+        [
+            "STAT" => $r["substat_1"],
+            "VALUE" => $r["substat_1_value"]
+        ],
+        [
+            "STAT" => $r["substat_2"],
+            "VALUE" => $r["substat_2_value"]
+        ],
+        [
+            "STAT" => $r["substat_3"],
+            "VALUE" => $r["substat_3_value"]
+        ],
+        [
+            "STAT" => $r["substat_4"],
+            "VALUE" => $r["substat_4_value"]
+        ]
+    ];
+    foreach ($stats as $stat){
+        switch ($stat["STAT"]){
             case RUNE_STAT_ID::ATK:
-                return RUNE_STAT_VALUES::ATK[$stars][$level];
+                $rune["ATK"] += $stat["VALUE"];
+                break;
             case RUNE_STAT_ID::ATK_P:
-                return RUNE_STAT_VALUES::ATK_P[$stars][$level];
+                $rune["ATK"] += ($unit->get_base_stats()["atk"] * $stat["VALUE"] / 100);
+                break;
             case RUNE_STAT_ID::DEF:
-                return RUNE_STAT_VALUES::DEF[$stars][$level];
+                $rune["DEF"] += $stat["VALUE"];
+                break;
             case RUNE_STAT_ID::DEF_P:
-                return RUNE_STAT_VALUES::DEF_P[$stars][$level];
+                $rune["DEF"] += ($unit->get_base_stats()["def"] * $stat["VALUE"] / 100);
+                break;
+            case RUNE_STAT_ID::HP:
+                $rune["HP"] += $stat["VALUE"];
+                break;
+            case RUNE_STAT_ID::HP_P:
+                $rune["HP"] += ($unit->get_base_stats()["hp"] * $stat["VALUE"] / 100);
+                break;
             case RUNE_STAT_ID::SPD:
-                return RUNE_STAT_VALUES::SPD[$stars][$level];
+                $rune["SPD"] += $stat["VALUE"];
+                break;
             case RUNE_STAT_ID::CRR:
-                return RUNE_STAT_VALUES::CRR[$stars][$level];
+                $rune["CRR"] += $stat["VALUE"];
+                break;
             case RUNE_STAT_ID::CRD:
-                return RUNE_STAT_VALUES::CRD[$stars][$level];
-            case RUNE_STAT_ID::RES:
-                return RUNE_STAT_VALUES::RES[$stars][$level];
+                $rune["CRD"] += $stat["VALUE"];
+                break;
             case RUNE_STAT_ID::ACC:
-                return RUNE_STAT_VALUES::ACC[$stars][$level];
-            default:
-                return 0;
+                $rune["ACC"] += $stat["VALUE"];
+                break;
+            case RUNE_STAT_ID::RES:
+                $rune["RES"] += $stat["VALUE"];
+                break;
         }
     }
-?>
+    return $rune;
+}
+
+/**
+ * Gets the value of the main stat at an arbitrary level.
+ *
+ * @param int $level Desired level.
+ * @param int $stat Rune main stat ID.
+ * @param int $stars Rune stars.
+      * @return int Value of the main stat at the selected level.
+ */
+function get_main_stat_at_level($level, $stat, $stars){
+    $level = intval($level);
+    if ($level < 0 || $level > 15){
+        return 0;
+    }
+    switch ($stat){
+        case RUNE_STAT_ID::HP:
+            return RUNE_STAT_VALUES::HP[$stars][$level];
+        case RUNE_STAT_ID::HP_P:
+            return RUNE_STAT_VALUES::HP_P[$stars][$level];
+        case RUNE_STAT_ID::ATK:
+            return RUNE_STAT_VALUES::ATK[$stars][$level];
+        case RUNE_STAT_ID::ATK_P:
+            return RUNE_STAT_VALUES::ATK_P[$stars][$level];
+        case RUNE_STAT_ID::DEF:
+            return RUNE_STAT_VALUES::DEF[$stars][$level];
+        case RUNE_STAT_ID::DEF_P:
+            return RUNE_STAT_VALUES::DEF_P[$stars][$level];
+        case RUNE_STAT_ID::SPD:
+            return RUNE_STAT_VALUES::SPD[$stars][$level];
+        case RUNE_STAT_ID::CRR:
+            return RUNE_STAT_VALUES::CRR[$stars][$level];
+        case RUNE_STAT_ID::CRD:
+            return RUNE_STAT_VALUES::CRD[$stars][$level];
+        case RUNE_STAT_ID::RES:
+            return RUNE_STAT_VALUES::RES[$stars][$level];
+        case RUNE_STAT_ID::ACC:
+            return RUNE_STAT_VALUES::ACC[$stars][$level];
+        default:
+            return 0;
+    }
+}

+ 39 - 38
application/action/rate_team.php

@@ -1,40 +1,41 @@
 <?php
+/**
+ * File for the team score modification action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * File for the team score modification.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     *
-     * @category Action
-     */
-
-    /**
-     * Sets the score for a team.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  player
-     *  team
-     *  score
-     * Validates the data and sets the score.
-     *
-     * @return int 0 on success, negative values on error.
-     * @category Action
-     */
-    function action(){
-        $player = filter_input(INPUT_GET, "player");
-        $team = filter_input(INPUT_GET, "team");
-        $score = intval(filter_input(INPUT_GET, "score"));
-        $statement = get_context()->get_db()->prepare("
-          UPDATE team
-          SET score = :score
-          WHERE
-            player = :player AND
-            id = :team;
-        ");
-        $statement->bindValue(":score", $score, SQLITE3_TEXT);
-        $statement->bindValue(":player", $player, SQLITE3_TEXT);
-        $statement->bindValue(":team", $team, SQLITE3_TEXT);
-        $statement->execute();
-        return 0;
-    }
-?>
+/**
+ * Sets the score for a team.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  player: Owner's player ID.
+ *  team: Team ID.
+ *  score: New score.
+ * Validates the data and sets the score.
+ *
+ * @todo: Check that the user can rate this team.
+      * @return int 201 on success, HTTP erro status codes on error.
+ * @category Action
+ */
+function action(){
+    $player = filter_input(INPUT_GET, "player");
+    $team = filter_input(INPUT_GET, "team");
+    $score = intval(filter_input(INPUT_GET, "score"));
+    $statement = get_context()->get_db()->prepare("
+      UPDATE team
+      SET score = :score
+      WHERE
+        player = :player AND
+        id = :team;
+    ");
+    $statement->bindValue(":score", $score, SQLITE3_TEXT);
+    $statement->bindValue(":player", $player, SQLITE3_TEXT);
+    $statement->bindValue(":team", $team, SQLITE3_TEXT);
+    $statement->execute();
+    return 201;
+}

+ 102 - 98
application/action/save_run_team.php

@@ -1,104 +1,108 @@
 <?php
-    /**
-     * File for the run team saving action.
-     *
-     * Implements an action function to be called from the {@see Controller}.
-     * 
-     * @category Action
-     */
+/**
+ * File for the run team saving action.
+ *
+ * Implements an action function to be called from the {@see Controller}.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Saves a run party as a team.
-     *
-     * Reads the POST parameters looking for the following KEYS:
-     *  player
-     *  run
-     *  name
-     *  description
-     * Validates the data and creates the team in the database.
-     * 
-     * @return int 0 on success, negative values on error.
-     * @category Action
-     */
-    function action(){
-        $player = filter_input(INPUT_POST, 'player');
-        $run = filter_input(INPUT_POST, 'run');
-        $name = filter_input(INPUT_POST, 'name');
-        $description = filter_input(INPUT_POST, 'description');
-        if ($name == null || strlen($name) == 0){
-            return -1;
-        }
-        $s = "SELECT CASE WHEN MAX(id) IS NULL THEN 1 ELSE MAX(id) + 1 END AS id FROM team;";
-        $q = get_context()->get_db()->query($s);
-        $r = $q->fetchArray(SQLITE3_ASSOC);
-        $team_id = $r["id"];
+/**
+ * Saves a run party as a team.
+ *
+ * Reads the POST parameters looking for the following KEYS:
+ *  player: Player ID.
+ *  run: Run ID.
+ *  name: New team name.
+ *  description: New team description.
+ *  score: New team score {@todo implement}.
+ * Validates the data and creates the team in the database.
+ * 
+      * @return int 201 on success, HTTP erro status codes on error.
+ * @category Action
+ */
+function action(){
+    $player = filter_input(INPUT_POST, 'player');
+    $run = filter_input(INPUT_POST, 'run');
+    $name = filter_input(INPUT_POST, 'name');
+    $description = filter_input(INPUT_POST, 'description');
+    $score = intval(filter_input(INPUT_POST, 'score'));
+    if ($name == null || strlen($name) == 0){
+        return 400;
+    }
+    $s = "SELECT CASE WHEN MAX(id) IS NULL THEN 1 ELSE MAX(id) + 1 END AS id FROM team;";
+    $q = get_context()->get_db()->query($s);
+    $r = $q->fetchArray(SQLITE3_ASSOC);
+    $team_id = $r["id"];
+    $statement = get_context()->get_db()->prepare("
+      SELECT
+        run.area AS area,
+        run.stage AS stage,
+        run.difficulty AS difficulty,
+        area.type AS area_type
+      FROM
+        run,
+        area
+      WHERE
+        run.player = :player AND
+        run.id = :run AND
+        area.id = run.area AND
+        run.helper = 0;
+    ");
+    $statement->bindValue(':player', $player, SQLITE3_TEXT);
+    $statement->bindValue(':run', $run, SQLITE3_TEXT);
+    $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+    if (!$r){
+        return 404;
+    }
+    $statement = get_context()->get_db()->prepare("
+      INSERT INTO team (
+        player,
+        id,
+        name,
+        description,
+        area_type,
+        area,
+        stage,
+        difficulty,
+        score
+      ) VALUES (
+        :player,
+        :id,
+        :name,
+        :description,
+        :area_type,
+        :area,
+        :stage,
+        :difficulty,
+        :score);
+      ");
+    $statement->bindValue(':player', $player, SQLITE3_TEXT);
+    $statement->bindValue(':id', $team_id, SQLITE3_TEXT);
+    $statement->bindValue(':name', $name, SQLITE3_TEXT);
+    $statement->bindValue(':description', $description, SQLITE3_TEXT);
+    $statement->bindValue(':area_type', $r["area_type"], SQLITE3_TEXT);
+    $statement->bindValue(':area', $r["area"], SQLITE3_TEXT);
+    $statement->bindValue(':stage', $r["stage"], SQLITE3_TEXT);
+    $statement->bindValue(':difficulty', $r["difficulty"], SQLITE3_TEXT);
+    $statement->bindValue(':score', $score, SQLITE3_INTEGER);
+    $res = $statement->execute();
+    if (!$res){
+        return 500;
+    }
+    $s = "SELECT unit FROM data.run_party WHERE run = $run AND unit IS NOT NULL;";
+    $q = get_context()->get_db()->query($s);
+    while ($r = $q->fetchArray(SQLITE3_ASSOC)){
         $statement = get_context()->get_db()->prepare("
-          SELECT
-            run.area AS area,
-            run.stage AS stage,
-            run.difficulty AS difficulty,
-            area.type AS area_type
-          FROM
-            run,
-            area
-          WHERE
-            run.player = :player AND
-            run.id = :run AND
-            area.id = run.area AND
-            run.helper = 0;
+          INSERT INTO data.team_unit (team, unit)
+          VALUES (:team, :unit)
         ");
-        $statement->bindValue(':player', $player, SQLITE3_TEXT);
-        $statement->bindValue(':run', $run, SQLITE3_TEXT);
-        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-        if (!$r){
-            return -2;
-        }
-        $statement = get_context()->get_db()->prepare("
-          INSERT INTO team (
-            player,
-            id,
-            name,
-            description,
-            area_type,
-            area,
-            stage,
-            difficulty,
-            score
-          ) VALUES (
-            :player,
-            :id,
-            :name,
-            :description,
-            :area_type,
-            :area,
-            :stage,
-            :difficulty,
-            :score);
-          ");
-        $statement->bindValue(':player', $player, SQLITE3_TEXT);
-        $statement->bindValue(':id', $team_id, SQLITE3_TEXT);
-        $statement->bindValue(':name', $name, SQLITE3_TEXT);
-        $statement->bindValue(':description', $description, SQLITE3_TEXT);
-        $statement->bindValue(':area_type', $r["area_type"], SQLITE3_TEXT);
-        $statement->bindValue(':area', $r["area"], SQLITE3_TEXT);
-        $statement->bindValue(':stage', $r["stage"], SQLITE3_TEXT);
-        $statement->bindValue(':difficulty', $r["difficulty"], SQLITE3_TEXT);
-        $statement->bindValue(':score', 0, SQLITE3_TEXT);
-        $res = $statement->execute();
-        if (!$res){
-            return -3;
-        }
-        $s = "SELECT unit FROM data.run_party WHERE run = $run AND unit IS NOT NULL;";
-        $q = get_context()->get_db()->query($s);
-        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-            $statement = get_context()->get_db()->prepare("
-              INSERT INTO data.team_unit (team, unit)
-              VALUES (:team, :unit)
-            ");
-            $statement->bindValue(':team', $team_id, SQLITE3_TEXT);
-            $statement->bindValue(':unit', $r["unit"], SQLITE3_TEXT);
-            $statement->execute();
-        }
-        return 0;
+        $statement->bindValue(':team', $team_id, SQLITE3_TEXT);
+        $statement->bindValue(':unit', $r["unit"], SQLITE3_TEXT);
+        $statement->execute();
     }
+    return 201;
+}
 ?>

+ 157 - 153
application/config.php

@@ -1,167 +1,171 @@
 <?php
+/**
+ * Configuration variables.
+ *
+ * Not meant to be edited by the user.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+/**
+ * Application root directory.
+ */
+define('BASE_PATH', $_SERVER["DOCUMENT_ROOT"] . "/");
+
+require_once(__DIR__ . "/helper/NET_Helper.php");
+
+/**
+ * The site base URL.
+ */
+define('BASE_URL', NET::get_protocol() . $_SERVER["HTTP_HOST"] . "/");
+
+/**
+ * App related constants.
+ *
+ * @category Data
+ */
+final class APP{
+
     /**
-     * Configuration variables.
-     *
-     * Not meant to be edited by the user.
+     * App version.
      *
-     * @category Data
+     * Can be any string, not just numbers.
      */
+    const VERSION = "5.0.0";
+}
+
+/**
+ * In-app URLs.
+ *
+ * @category Data
+ */
+final class URL{
 
     /**
-     * Define constant and includesome helpers.
+     * Domain, with protcol (includes final '/').
      */
-    define('BASE_PATH', $_SERVER["DOCUMENT_ROOT"] . "/");
-    require_once(__DIR__ . "/helper/NET_Helper.php");
-    define('BASE_URL', NET::get_protocol() . $_SERVER["HTTP_HOST"] . "/");
+    const BASE = BASE_URL;
 
     /**
-     * App related constants.
-     *
-     * @category Data
+     * Fonts full url (includes final '/').
      */
-    final class APP{
+    const FONTS = BASE_URL . "/fonts/";
 
-        /**
-         * App version.
-         *
-         * Can be any string, not just numbers.
-         */
-        const VERSION = "5.0.0";
-    }
+    /**
+     * CSS full url (includes final '/').
+     */
+    const CSS = BASE_URL . "css/";
 
     /**
-     * In-app URLs.
-     *
-     * @category Data
-     */
-    final class URL{
-
-        /**
-         * Domain, with protcol (includes final '/').
-         */
-        const BASE = BASE_URL;
-
-        /**
-         * Fonts full url (includes final '/').
-         */
-        const FONTS = BASE_URL . "/fonts/";
-
-        /**
-         * CSS full url (includes final '/').
-         */
-        const CSS = BASE_URL . "css/";
-
-        /**
-         * URLs to image resources.
-         */
-        const IMG = array(
-            "BASE" => BASE_URL . "img/",
-            "UNKNOWN" => BASE_URL . "img/unknown.png",
-            "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/",
-            "ESSENCE" => BASE_URL . "img/essence/",
-            "RUNE" => BASE_URL . "img/rune/",
-            "ARTIFACT" => BASE_URL . "img/artifact/",
-            "GRIND" => BASE_URL . "img/grind/",
-            "ELEMENT" => BASE_URL . "img/element/",
-            "SKILL_GUILD" => BASE_URL . "img/skill_guild/",
-            "DECORATION" => BASE_URL . "img/decoration/",
-            "SOURCE" => BASE_URL . "img/source/",
-            "SKILL_LEADER" => BASE_URL . "img/skill_leader/",
-            "INVENTORY" => BASE_URL . "img/inventory/",
-            "EFFECT" => BASE_URL . "img/effect/",
-            "BUILDING" => BASE_URL . "img/building/",
-        );
-    }
-
-    /**
-     * In-app directories (filesystem, not url).
-     *
-     * @category Data
-     */
-    final class PATH{
-
-        /**
-         * Path to the application direcory.
-         */
-        const APPLICATION = BASE_PATH . "../application/";
-
-        /**
-         * Path to the public direcory.
-         */
-        const BASE = BASE_PATH;
-
-        /**
-         * Path to the controller file.
-         */
-        const CONTROLLER = BASE_PATH . "../application/Controller.php";
-
-        /**
-         * Path to the entity files.
-         */
-        const ENTITY = BASE_PATH . "../application/entity/";
-
-        /**
-         * Path to the page files.
-         */
-        const PAGE = BASE_PATH . "../application/page/";
-
-        /**
-         * Path to the action files.
-         */
-        const ACTION = BASE_PATH . "../application/action/";
-
-        /**
-         * Path to the view files.
-         */
-        const VIEW = BASE_PATH . "../application/view/";
-
-        /**
-         * Paths to image resources.
-         */
-        const IMG = array(
-            "BASE" => BASE_PATH . "img/",
-            "UNKNOWN" => BASE_PATH . "img/unknown.png",
-            "ICON" => BASE_PATH . "img/icon/",
-            "LOGO" => BASE_PATH . "img/logo/",
-            "CURRENCY" => BASE_PATH . "img/currency/",
-            "UNIT" => BASE_PATH . "img/unit/",
-            "AREA" => BASE_PATH . "img/area/",
-            "SKILL" => BASE_PATH . "img/skill/",
-            "ESSENCE" => BASE_PATH . "img/essence/",
-            "RUNE" => BASE_PATH . "img/rune/",
-            "GRIND" => BASE_PATH . "img/grind/",
-            "ELEMENT" => BASE_PATH . "img/element/",
-            "SKILL_GUILD" => BASE_PATH . "img/skill_guild/",
-            "DECORATION" => BASE_PATH . "img/decoration/",
-            "SOURCE" => BASE_PATH . "img/source/",
-            "SKILL_LEADER" => BASE_PATH . "img/skill_leader/",
-            "INVENTORY" => BASE_PATH . "img/inventory/",
-            "EFFECT" => BASE_PATH . "img/effect/",
-            "BUILDING" => BASE_PATH . "img/building/",
-        );
-
-        /**
-         * Path to the helper files.
-         */
-        const HELPER = BASE_PATH . "../application/helper/";
-
-        /**
-         * Path to the db_key files.
-         */
-        const DB_KEY = BASE_PATH . "../application/key.sqlite";
-
-        /**
-         * Path to the db_data files.
-         */
-        const DB_DATA = BASE_PATH . "../data/data.sqlite";
-
-    }
-
-?>
+     * URLs to image resources.
+     */
+    const IMG = array(
+        "BASE" => BASE_URL . "img/",
+        "UNKNOWN" => BASE_URL . "img/unknown.png",
+        "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/",
+        "ESSENCE" => BASE_URL . "img/essence/",
+        "RUNE" => BASE_URL . "img/rune/",
+        "ARTIFACT" => BASE_URL . "img/artifact/",
+        "GRIND" => BASE_URL . "img/grind/",
+        "ELEMENT" => BASE_URL . "img/element/",
+        "SKILL_GUILD" => BASE_URL . "img/skill_guild/",
+        "DECORATION" => BASE_URL . "img/decoration/",
+        "SOURCE" => BASE_URL . "img/source/",
+        "SKILL_LEADER" => BASE_URL . "img/skill_leader/",
+        "INVENTORY" => BASE_URL . "img/inventory/",
+        "EFFECT" => BASE_URL . "img/effect/",
+        "BUILDING" => BASE_URL . "img/building/",
+    );
+}
+
+/**
+ * In-app directories (filesystem, not url).
+ *
+ * @category Data
+ */
+final class PATH{
+
+    /**
+     * Path to the application direcory.
+     */
+    const APPLICATION = BASE_PATH . "../application/";
+
+    /**
+     * Path to the public direcory.
+     */
+    const BASE = BASE_PATH;
+
+    /**
+     * Path to the controller file.
+     */
+    const CONTROLLER = BASE_PATH . "../application/Controller.php";
+
+    /**
+     * Path to the entity files.
+     */
+    const ENTITY = BASE_PATH . "../application/entity/";
+
+    /**
+     * Path to the page files.
+     */
+    const PAGE = BASE_PATH . "../application/page/";
+
+    /**
+     * Path to the action files.
+     */
+    const ACTION = BASE_PATH . "../application/action/";
+
+    /**
+     * Path to the view files.
+     */
+    const VIEW = BASE_PATH . "../application/view/";
+
+    /**
+     * Paths to image resources.
+     */
+    const IMG = array(
+        "BASE" => BASE_PATH . "img/",
+        "UNKNOWN" => BASE_PATH . "img/unknown.png",
+        "ICON" => BASE_PATH . "img/icon/",
+        "LOGO" => BASE_PATH . "img/logo/",
+        "CURRENCY" => BASE_PATH . "img/currency/",
+        "UNIT" => BASE_PATH . "img/unit/",
+        "AREA" => BASE_PATH . "img/area/",
+        "SKILL" => BASE_PATH . "img/skill/",
+        "ESSENCE" => BASE_PATH . "img/essence/",
+        "RUNE" => BASE_PATH . "img/rune/",
+        "GRIND" => BASE_PATH . "img/grind/",
+        "ELEMENT" => BASE_PATH . "img/element/",
+        "SKILL_GUILD" => BASE_PATH . "img/skill_guild/",
+        "DECORATION" => BASE_PATH . "img/decoration/",
+        "SOURCE" => BASE_PATH . "img/source/",
+        "SKILL_LEADER" => BASE_PATH . "img/skill_leader/",
+        "INVENTORY" => BASE_PATH . "img/inventory/",
+        "EFFECT" => BASE_PATH . "img/effect/",
+        "BUILDING" => BASE_PATH . "img/building/",
+    );
+
+    /**
+     * Path to the helper files.
+     */
+    const HELPER = BASE_PATH . "../application/helper/";
+
+    /**
+     * Path to the db_key files.
+     */
+    const DB_KEY = BASE_PATH . "../application/key.sqlite";
+
+    /**
+     * Path to the db_data files.
+     */
+    const DB_DATA = BASE_PATH . "../data/data.sqlite";
 
+}

+ 347 - 338
application/entity/Area.php

@@ -1,367 +1,376 @@
 <?php
+/**
+ * Area entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * An area.
+ *
+ * Represents a playable area of the game.
+ *
+ * @category Entity
+ */
+class Area extends Entity{
+
     /**
-     * Area entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Area identifier (it may not be unique!).
      */
+    private $id;
 
-    /*
-     * Require entity dependencies if not present.
+    /**
+     * @var int Area type ID ({@see AREA_TYPE_ID}).
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $type;
 
+    /**
+     * @var string Area name.
+     */
+    private $name;
 
     /**
-     * An area.
+     * Constructor.
      *
-     * Represents an object from the table 'area'.
+     * Retrieves the area information from the database.
      *
-     * @category Entity
+     * @param int $id Area identifier.
+     * @param int $type Area type.
      */
-    class Area extends Entity{
-
-        private $id;
-        private $type;
-        private $name;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the area information from the database.
-         *
-         * @param int $id Area identifier.
-         * @param int $type Area type.
-         */
-        public function __construct($id, $type){
+    public function __construct($id, $type){
 
-            $this->id = $id;
-            $this->type = $type;
+        $this->id = $id;
+        $this->type = $type;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            type,
+            name
+          FROM area
+          WHERE
+            id = :id AND
+            type = :type
+          ORDER BY type DESC;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $statement->bindValue(':type', $type, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->name = HTML::e($r["name"]);
+        }
+        elseif($this->id > 1000){
+            $this->type = AREA_TYPE_ID::CAIROS_DUNGEON;
+            $this->name = "Hall of Heroes";
+        }
+        else{
             $statement = get_context()->get_db()->prepare("
-                SELECT
-                  id,
-                  type,
-                  name
-                FROM area
-                WHERE
-                  id = :id AND
-                  type = :type
-                ORDER BY type DESC;
+              SELECT name
+              FROM area_type
+              WHERE id = :type;
             ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
             $statement->bindValue(':type', $type, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
             if ($r){
                 $this->name = HTML::e($r["name"]);
             }
-            elseif($this->id > 1000){
-                $this->type = AREA_TYPE_ID::CAIROS_DUNGEON;
-                $this->name = "Hall of Heroes";
-            }
-            else{
-                $statement = get_context()->get_db()->prepare("
-                  SELECT name
-                  FROM area_type
-                  WHERE id = :type;
-                ");
-                $statement->bindValue(':type', $type, SQLITE3_TEXT);
-                if ($r){
-                    $this->name = HTML::e($r["name"]);
-                }
-            }
         }
+    }
+
+    /**
+     * Retrieves the area identifier.
+     *
+     * @return int Area ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Retrieves the area type identifier.
+     *
+     * @see AREA_TYPE_ID.
+     * @return int Area type ID
+     */
+    public function get_type(){
+        return $this->type;
+    }
 
-        /**
-         * Retrieves the area identifier.
-         *
-         * @return int Area ID.
-         */
-        public function get_id(){
-            return $this->id;
+    /**
+     * Retrieves the area name.
+     *
+     * @return string The area name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
+
+    /**
+     * Gets the URL to the area image.
+     *
+     * @param string $stage Stage number, for a more accurate image in Dimension Hole.
+     * @return string Image URL, or a fixed unknown image.
+     */
+    public function get_image($stage = null){
+        if ($this->id > 10000){
+            // Hall of Heroes
+            return APPLICATION::img("AREA", "HOH");
         }
-    
-        /**
-         * Retrieves Area type identifier.
-         *
-         * @return int Area type ID
-         */
-        public function get_type(){
-            return $this->type;
+        elseif ($this->type == AREA_TYPE_ID::RIFT_RAID){
+            return APPLICATION::img("UNIT", 44007);
         }
-    
-        /**
-         * Retrieves the area name.
-         *
-         * @return string The area name.
-         */
-        public function get_name(){
-            return $this->name;
+        elseif ($this->type == AREA_TYPE_ID::ARENA){
+            return APPLICATION::img("AREA", "ARENA");
         }
-    
-        /**
-         * Gets the URL to the area image.
-         *
-         * @param string $stage Stage number, for a more accurate image in Dimension Hole.
-         * @return string Image URL, or a fixed unknown image.
-         */
-        public function get_image($stage = null){
-            if ($this->id > 10000){
-                // Hall of Heroes
-                return APPLICATION::img("AREA", "HOH");
-            }
-            elseif ($this->type == AREA_TYPE_ID::RIFT_RAID){
-                return APPLICATION::img("UNIT", 44007);
-            }
-            elseif ($this->type == AREA_TYPE_ID::ARENA){
-                return APPLICATION::img("AREA", "ARENA");
-            }
-            elseif ($this->type == AREA_TYPE_ID::DIMENSIONAL_RIFT){
-                return APPLICATION::img("CURRENCY", "darkportalenergy");
-            }
-            elseif (
-                $this->type == AREA_TYPE_ID::SCENARIO ||
-                $this->type == AREA_TYPE_ID::GUILD_WAR ||
-                $this->type == AREA_TYPE_ID::GUILD_SIEGE ||
-                $this->type == AREA_TYPE_ID::WORLD_BOSS ||
-                $this->type == AREA_TYPE_ID::DIMENSIONAL_RIFT
-            ){
-                return APPLICATION::img("AREA", $this->id);
-            }
-            elseif ($this->type == AREA_TYPE_ID::CAIROS_DUNGEON && APPLICATION::valid_id("DUNGEON_ID", $this->id)){
-                switch ($this->id){
-                    case DUNGEON_ID::GIANTS_KEEP:
-                        return APPLICATION::img("UNIT", 60201);
-                        break;
-                    case DUNGEON_ID::DRAGONS_LAIR:
-                        return APPLICATION::img("UNIT", 60302);
-                        break;
-                    case DUNGEON_ID::NECROPOLIS:
-                        return APPLICATION::img("UNIT", 62105);
-                        break;
-                    case DUNGEON_ID::STEEL_FORTRESS:
-                        return APPLICATION::img("UNIT", 62403);
-                        break;
-                    case DUNGEON_ID::PUNISHERS_CRYPT:
-                        return APPLICATION::img("UNIT", 62403);
-                        break;
-                    case DUNGEON_ID::HALL_OF_WATER:
-                        return APPLICATION::img("UNIT", 60101);
-                        break;
-                    case DUNGEON_ID::HALL_OF_FIRE:
-                        return APPLICATION::img("UNIT", 60102);
-                        break;
-                    case DUNGEON_ID::HALL_OF_WIND:
-                        return APPLICATION::img("UNIT", 60103);
-                        break;
-                    case DUNGEON_ID::HALL_OF_LIGHT:
-                        return APPLICATION::img("UNIT", 60104);
-                        break;
-                    case DUNGEON_ID::HALL_OF_DARK:
-                        return APPLICATION::img("UNIT", 60105);
-                        break;
-                    case DUNGEON_ID::HALL_OF_MAGIC:
-                        return APPLICATION::img("UNIT", 62004);
-                        break;
-                    default:
-                        return APPLICATION::img("AREA", $this->id);
-                }
-            }
-            elseif ($this->type == AREA_TYPE_ID::RIFT_DUNGEON && APPLICATION::valid_id("ELEMENTAL_RIFT_DUNGEON_ID", $this->id)){
-                switch ($this->id){
-                    case ELEMENTAL_RIFT_DUNGEON_ID::ICE_BEAST:
-                        return APPLICATION::img("UNIT", 43001);
-                        break;
-                    case ELEMENTAL_RIFT_DUNGEON_ID::FIRE_BEAST:
-                        return APPLICATION::img("UNIT", 43002);
-                        break;
-                    case ELEMENTAL_RIFT_DUNGEON_ID::WIND_BEAST:
-                        return APPLICATION::img("UNIT", 43003);
-                        break;
-                    case ELEMENTAL_RIFT_DUNGEON_ID::LIGHT_BEAST:
-                        return APPLICATION::img("UNIT", 43004);
-                        break;
-                    case ELEMENTAL_RIFT_DUNGEON_ID::DARK_BEAST:
-                        return APPLICATION::img("UNIT", 43005);
-                        break;
-                    default:
-                        return APPLICATION::img("AREA", $this->id);
-                        break;
-                }
-            }
-            elseif ($this->type == AREA_TYPE_ID::DIMENSIONAL_HOLE){
-                switch ($this->id){
-                    case DUNGEON_ID::FOREST_OF_ROARING_BEASTS:
-                        return APPLICATION::img("UNIT", 47002);
-                        break;
-                    case DUNGEON_ID::SANCTUARY_OF_DREAMING_FAIRIES:
-                        return APPLICATION::img("UNIT", 47001);
-                        break;
-                    case DUNGEON_ID::CLIFF_OF_TOUGH_BEASTS_MEN:
-                        return APPLICATION::img("UNIT", 47002);
-                        break;
-                    case DUNGEON_ID::KARZHAN_REMAINS_WARBEAR:
-                        switch ($stage){
-                            case 1:
-                                return APPLICATION::img("UNIT", 10734);
-                                break;
-                            case 2:
-                                return APPLICATION::img("UNIT", 10733);
-                                break;
-                            case 3:
-                                return APPLICATION::img("UNIT", 10731);
-                                break;
-                            case 4:
-                                return APPLICATION::img("UNIT", 10735);
-                                break;
-                            case 5:
-                                return APPLICATION::img("UNIT", 10732);
-                                break;
-                            default:
-                                return APPLICATION::img("AREA", $this->id);
-                                break;
-                        }
-                        break;
-                    case DUNGEON_ID::KARZHAN_REMAINS_INUGAMI:
-                        switch ($stage){
-                            case 1:
-                                return APPLICATION::img("UNIT", 11031);
-                                break;
-                            case 2:
-                                return APPLICATION::img("UNIT", 11033);
-                                break;
-                            case 3:
-                                return APPLICATION::img("UNIT", 11032);
-                                break;
-                            case 4:
-                                return APPLICATION::img("UNIT", 11034);
-                                break;
-                            case 5:
-                                return APPLICATION::img("UNIT", 11035);
-                                break;
-                            default:
-                                return APPLICATION::img("AREA", $this->id);
-                                break;
-                        }
-                        break;
-                    case DUNGEON_ID::ELLUNIA_REMAINS_FAIRY:
-                        switch ($stage){
-                            case 1:
-                                return APPLICATION::img("UNIT", 10132);
-                                break;
-                            case 2:
-                                return APPLICATION::img("UNIT", 10134);
-                                break;
-                            case 3:
-                                return APPLICATION::img("UNIT", 10131);
-                                break;
-                            case 4:
-                                return APPLICATION::img("UNIT", 10133);
-                                break;
-                            case 5:
-                                return APPLICATION::img("UNIT", 10134);
-                                break;
-                            default:
-                                return APPLICATION::img("AREA", $this->id);
-                                break;
-                        }
-                        break;
-                    case DUNGEON_ID::ELLUNIA_REMAINS_PIXIE:
-                        switch ($stage){
-                            case 1:
-                                return APPLICATION::img("UNIT", 10334);
-                                break;
-                            case 2:
-                                return APPLICATION::img("UNIT", 10332);
-                                break;
-                            case 3:
-                                return APPLICATION::img("UNIT", 10335);
-                                break;
-                            case 4:
-                                return APPLICATION::img("UNIT", 10333);
-                                break;
-                            case 5:
-                                return APPLICATION::img("UNIT", 10331);
-                                break;
-                            default:
-                                return APPLICATION::img("AREA", $this->id);
-                                break;
-                        }
-                        break;
-                    case DUNGEON_ID::LUMEL_REMAINS_WEREWOLF:
-                        switch ($stage){
-                            case 1:
-                                return APPLICATION::img("UNIT", 14035);
-                                break;
-                            case 2:
-                                return APPLICATION::img("UNIT", 14033);
-                                break;
-                            case 3:
-                                return APPLICATION::img("UNIT", 14031);
-                                break;
-                            case 4:
-                                return APPLICATION::img("UNIT", 14034);
-                                break;
-                            case 5:
-                                return APPLICATION::img("UNIT", 14032);
-                                break;
-                            default:
-                                return APPLICATION::img("AREA", $this->id);
-                                break;
-                        }
-                        break;
-                    case DUNGEON_ID::LUMEL_REMAINS_MARTIAL_CAT:
-                        switch ($stage){
-                            case 1:
-                                return APPLICATION::img("UNIT", 15032);
-                                break;
-                            case 2:
-                                return APPLICATION::img("UNIT", 15034);
-                                break;
-                            case 3:
-                                return APPLICATION::img("UNIT", 15031);
-                                break;
-                            case 4:
-                                return APPLICATION::img("UNIT", 15035);
-                                break;
-                            case 5:
-                                return APPLICATION::img("UNIT", 15033);
-                                break;
-                            default:
-                                return APPLICATION::img("AREA", $this->id);
-                                break;
-                        }
-                        break;
-                    default:
-                        return APPLICATION::img("AREA", $this->id);
-                        break;
-                }
+        elseif ($this->type == AREA_TYPE_ID::DIMENSIONAL_RIFT){
+            return APPLICATION::img("CURRENCY", "darkportalenergy");
+        }
+        elseif (
+            $this->type == AREA_TYPE_ID::SCENARIO ||
+            $this->type == AREA_TYPE_ID::GUILD_WAR ||
+            $this->type == AREA_TYPE_ID::GUILD_SIEGE ||
+            $this->type == AREA_TYPE_ID::WORLD_BOSS ||
+            $this->type == AREA_TYPE_ID::DIMENSIONAL_RIFT
+        ){
+            return APPLICATION::img("AREA", $this->id);
+        }
+        elseif ($this->type == AREA_TYPE_ID::CAIROS_DUNGEON && APPLICATION::valid_id("DUNGEON_ID", $this->id)){
+            switch ($this->id){
+                case DUNGEON_ID::GIANTS_KEEP:
+                    return APPLICATION::img("UNIT", 60201);
+                    break;
+                case DUNGEON_ID::DRAGONS_LAIR:
+                    return APPLICATION::img("UNIT", 60302);
+                    break;
+                case DUNGEON_ID::NECROPOLIS:
+                    return APPLICATION::img("UNIT", 62105);
+                    break;
+                case DUNGEON_ID::STEEL_FORTRESS:
+                    return APPLICATION::img("UNIT", 62403);
+                    break;
+                case DUNGEON_ID::PUNISHERS_CRYPT:
+                    return APPLICATION::img("UNIT", 62403);
+                    break;
+                case DUNGEON_ID::HALL_OF_WATER:
+                    return APPLICATION::img("UNIT", 60101);
+                    break;
+                case DUNGEON_ID::HALL_OF_FIRE:
+                    return APPLICATION::img("UNIT", 60102);
+                    break;
+                case DUNGEON_ID::HALL_OF_WIND:
+                    return APPLICATION::img("UNIT", 60103);
+                    break;
+                case DUNGEON_ID::HALL_OF_LIGHT:
+                    return APPLICATION::img("UNIT", 60104);
+                    break;
+                case DUNGEON_ID::HALL_OF_DARK:
+                    return APPLICATION::img("UNIT", 60105);
+                    break;
+                case DUNGEON_ID::HALL_OF_MAGIC:
+                    return APPLICATION::img("UNIT", 62004);
+                    break;
+                default:
+                    return APPLICATION::img("AREA", $this->id);
             }
-            elseif ($this->type == AREA_TYPE_ID::TARTARUS_LABYRINTH){
-                switch ($stage){
-                    case LABYRINTH_STAGES_ID::TARTARUS:
-                        return APPLICATION::img("UNIT", 46001);
-                        break;
-                    case LABYRINTH_STAGES_ID::LEOS:
-                        return APPLICATION::img("UNIT", 46101);
-                        break;
-                    case LABYRINTH_STAGES_ID::KOTTOS:
-                        return APPLICATION::img("UNIT", 46102);
-                        break;
-                    case LABYRINTH_STAGES_ID::AQUILES:
-                        return APPLICATION::img("UNIT", 46103);
-                        break;
-                    default:
-                        return APPLICATION::img("AREA", $this->id);
-                }
+        }
+        elseif ($this->type == AREA_TYPE_ID::RIFT_DUNGEON && APPLICATION::valid_id("ELEMENTAL_RIFT_DUNGEON_ID", $this->id)){
+            switch ($this->id){
+                case ELEMENTAL_RIFT_DUNGEON_ID::ICE_BEAST:
+                    return APPLICATION::img("UNIT", 43001);
+                    break;
+                case ELEMENTAL_RIFT_DUNGEON_ID::FIRE_BEAST:
+                    return APPLICATION::img("UNIT", 43002);
+                    break;
+                case ELEMENTAL_RIFT_DUNGEON_ID::WIND_BEAST:
+                    return APPLICATION::img("UNIT", 43003);
+                    break;
+                case ELEMENTAL_RIFT_DUNGEON_ID::LIGHT_BEAST:
+                    return APPLICATION::img("UNIT", 43004);
+                    break;
+                case ELEMENTAL_RIFT_DUNGEON_ID::DARK_BEAST:
+                    return APPLICATION::img("UNIT", 43005);
+                    break;
+                default:
+                    return APPLICATION::img("AREA", $this->id);
+                    break;
             }
-            elseif ($this->type == AREA_TYPE_ID::TRIAL_OF_ASCENSION){
-                return APPLICATION::img("AREA", "TRIAL_OF_ASCENSION");
+        }
+        elseif ($this->type == AREA_TYPE_ID::DIMENSIONAL_HOLE){
+            switch ($this->id){
+                case DUNGEON_ID::FOREST_OF_ROARING_BEASTS:
+                    return APPLICATION::img("UNIT", 47002);
+                    break;
+                case DUNGEON_ID::SANCTUARY_OF_DREAMING_FAIRIES:
+                    return APPLICATION::img("UNIT", 47001);
+                    break;
+                case DUNGEON_ID::CLIFF_OF_TOUGH_BEASTS_MEN:
+                    return APPLICATION::img("UNIT", 47002);
+                    break;
+                case DUNGEON_ID::KARZHAN_REMAINS_WARBEAR:
+                    switch ($stage){
+                        case 1:
+                            return APPLICATION::img("UNIT", 10734);
+                            break;
+                        case 2:
+                            return APPLICATION::img("UNIT", 10733);
+                            break;
+                        case 3:
+                            return APPLICATION::img("UNIT", 10731);
+                            break;
+                        case 4:
+                            return APPLICATION::img("UNIT", 10735);
+                            break;
+                        case 5:
+                            return APPLICATION::img("UNIT", 10732);
+                            break;
+                        default:
+                            return APPLICATION::img("AREA", $this->id);
+                            break;
+                    }
+                    break;
+                case DUNGEON_ID::KARZHAN_REMAINS_INUGAMI:
+                    switch ($stage){
+                        case 1:
+                            return APPLICATION::img("UNIT", 11031);
+                            break;
+                        case 2:
+                            return APPLICATION::img("UNIT", 11033);
+                            break;
+                        case 3:
+                            return APPLICATION::img("UNIT", 11032);
+                            break;
+                        case 4:
+                            return APPLICATION::img("UNIT", 11034);
+                            break;
+                        case 5:
+                            return APPLICATION::img("UNIT", 11035);
+                            break;
+                        default:
+                            return APPLICATION::img("AREA", $this->id);
+                            break;
+                    }
+                    break;
+                case DUNGEON_ID::ELLUNIA_REMAINS_FAIRY:
+                    switch ($stage){
+                        case 1:
+                            return APPLICATION::img("UNIT", 10132);
+                            break;
+                        case 2:
+                            return APPLICATION::img("UNIT", 10134);
+                            break;
+                        case 3:
+                            return APPLICATION::img("UNIT", 10131);
+                            break;
+                        case 4:
+                            return APPLICATION::img("UNIT", 10133);
+                            break;
+                        case 5:
+                            return APPLICATION::img("UNIT", 10134);
+                            break;
+                        default:
+                            return APPLICATION::img("AREA", $this->id);
+                            break;
+                    }
+                    break;
+                case DUNGEON_ID::ELLUNIA_REMAINS_PIXIE:
+                    switch ($stage){
+                        case 1:
+                            return APPLICATION::img("UNIT", 10334);
+                            break;
+                        case 2:
+                            return APPLICATION::img("UNIT", 10332);
+                            break;
+                        case 3:
+                            return APPLICATION::img("UNIT", 10335);
+                            break;
+                        case 4:
+                            return APPLICATION::img("UNIT", 10333);
+                            break;
+                        case 5:
+                            return APPLICATION::img("UNIT", 10331);
+                            break;
+                        default:
+                            return APPLICATION::img("AREA", $this->id);
+                            break;
+                    }
+                    break;
+                case DUNGEON_ID::LUMEL_REMAINS_WEREWOLF:
+                    switch ($stage){
+                        case 1:
+                            return APPLICATION::img("UNIT", 14035);
+                            break;
+                        case 2:
+                            return APPLICATION::img("UNIT", 14033);
+                            break;
+                        case 3:
+                            return APPLICATION::img("UNIT", 14031);
+                            break;
+                        case 4:
+                            return APPLICATION::img("UNIT", 14034);
+                            break;
+                        case 5:
+                            return APPLICATION::img("UNIT", 14032);
+                            break;
+                        default:
+                            return APPLICATION::img("AREA", $this->id);
+                            break;
+                    }
+                    break;
+                case DUNGEON_ID::LUMEL_REMAINS_MARTIAL_CAT:
+                    switch ($stage){
+                        case 1:
+                            return APPLICATION::img("UNIT", 15032);
+                            break;
+                        case 2:
+                            return APPLICATION::img("UNIT", 15034);
+                            break;
+                        case 3:
+                            return APPLICATION::img("UNIT", 15031);
+                            break;
+                        case 4:
+                            return APPLICATION::img("UNIT", 15035);
+                            break;
+                        case 5:
+                            return APPLICATION::img("UNIT", 15033);
+                            break;
+                        default:
+                            return APPLICATION::img("AREA", $this->id);
+                            break;
+                    }
+                    break;
+                default:
+                    return APPLICATION::img("AREA", $this->id);
+                    break;
             }
-            else{
-                return APPLICATION::img("AREA", $this->id);
+        }
+        elseif ($this->type == AREA_TYPE_ID::TARTARUS_LABYRINTH){
+            switch ($stage){
+                case LABYRINTH_STAGES_ID::TARTARUS:
+                    return APPLICATION::img("UNIT", 46001);
+                    break;
+                case LABYRINTH_STAGES_ID::LEOS:
+                    return APPLICATION::img("UNIT", 46101);
+                    break;
+                case LABYRINTH_STAGES_ID::KOTTOS:
+                    return APPLICATION::img("UNIT", 46102);
+                    break;
+                case LABYRINTH_STAGES_ID::AQUILES:
+                    return APPLICATION::img("UNIT", 46103);
+                    break;
+                default:
+                    return APPLICATION::img("AREA", $this->id);
             }
         }
-
+        elseif ($this->type == AREA_TYPE_ID::TRIAL_OF_ASCENSION){
+            return APPLICATION::img("AREA", "TRIAL_OF_ASCENSION");
+        }
+        else{
+            return APPLICATION::img("AREA", $this->id);
+        }
     }
-?>
+
+}

+ 495 - 410
application/entity/Artifact.php

@@ -1,442 +1,527 @@
 <?php
+/**
+ * Artifact entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+require_once(PATH::ENTITY . "Artifact_Stat.php");
+require_once(PATH::ENTITY . "Artifact_Effect.php");
+
+/**
+ * Artifact.
+ *
+ * Represents a game artifact.
+ *
+ * @category Entity
+ */
+class Artifact extends Entity{
+
     /**
-     * Artifact entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int The owner's player ID.
+     */
+    private $player_id;
+
+    /**
+     * @var int The artifact ID.
+     */
+    private $id;
+
+    /**
+     * @var int The artifact type ({@see ARTIFACT_TYPE}).
+     */
+    private $type;
+
+    /**
+     * @var bool Indicates if is an elemental artifact.
+     */
+    private $elemental = false;
+
+    /**
+     * @var bool Indicates it the artifact is archetypal.
+     */
+    private $archetypal = false;
+
+    /**
+     * @var int Artifact element ID, null for archetypals ({@see ELEMENT_ID}).
+     */
+    private $element;
+
+    /**
+     * @var int Artifact archetype ID, null for elementals ({@see ARCHETYPE_ID}). 
+     */
+    private $archetype;
+
+    /**
+     * @var int Artifact level. 
+     */
+    private $level;
+
+    /**
+     * @var int Artifact quality ({@see QUALITY_ID}).
+     */
+    private $quality;
+
+    /**
+     * @var int Artifact original quality ({@see QUALITY_ID}).
+     */
+    private $original_quality;
+
+    /**
+     * @var string Artifact quality name.
+     */
+    private $quality_name;
+
+    /**
+     * @var string Artifact original quality name.
+     */
+    private $original_quality_name;
+
+    /**
+     * @var string Artifact value in mana stones.
      */
+    private $value;
 
     /**
-     * Require dependent entities if not present.
+     * @var float Artifact efficiency.
      */
-    require_once(PATH::ENTITY . "Entity.php");
-    require_once(PATH::ENTITY . "Artifact_Stat.php");
-    require_once(PATH::ENTITY . "Artifact_Effect.php");
+    private $efficiency;
 
     /**
-     * Owned artifact.
+     * @var float Artifact maximum efficiency.
+     */
+    private $max_efficiency;
+
+    /**
+     * @var bool Internal flag to check if the stat and effects have been loaded into the entity.
+     */
+    private $flag_stats = false;
+
+    /**
+     * @var Artifact_Stat The artifact main stat.
+     */
+    private $stat;
+
+    /**
+     * @var Artifact_Effect[] Every effect the artifact currently has.
+     */
+    private $effects = [];
+
+    /**
+     * @var bool Internal flag to check if the unit that equips the artifact (if any) has been
+     * loaded.
+     */
+    private $flag_unit = false;
+
+    /**
+     * @var Unit Unit that equips the artifact in the curent game mode.
+     */
+    private $unit;
+
+    /**
+     * Constructor.
      *
-     * Represents an object from the table 'artifact'.
+     * Searches the database and retrieves the information about the
+     * artifact, populating it and it's items.
      *
-     * @category Entity
-     */
-    class Artifact extends Entity{
-
-        private $player_id;
-        private $id;
-        private $type;
-        private $elemental = false;
-        private $archetypal = false;
-        private $element;
-        private $archetype;
-        private $level;
-        private $quality;
-        private $original_quality;
-        private $quality_name;
-        private $original_quality_name;
-        private $value;
-        private $efficiency;
-        private $max_efficiency;
-        private $flag_stats = false;
-        private $stat;
-        private $effects = [];
-        private $flag_unit = false;
-        private $unit_id;
-        private $unit;
-
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * artifact, populating it and it's items.
-         *
-         * @param int $id Artifact id.
-         */
-        public function __construct($id){
-
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                player,
-                id,
-                type,
-                attribute,
-                archetype,
-                level,
-                quality,
-                original_quality,
-                value,
-                efficiency,
-                max_efficiency,
-                locked
-              FROM artifact
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->player_id = $r["player"];
-                $this->id = $r["id"];
-                $this->type = $r["type"];
-                if ($r["type"] == ARTIFACT_TYPE::ARCHETYPE){
-                    $this->archetypal = true;
-                }
-                elseif ($r["type"] == ARTIFACT_TYPE::ELEMENT){
-                    $this->elemental = true;
-                }
-                $this->element = $r["attribute"];
-                $this->archetype = $r["archetype"];
-                $this->level = $r["level"];
-                $this->quality = $r["quality"];
-                $this->original_quality = $r["original_quality"];
-                $this->value = $r["value"];
-                $this->efficiency = $r["efficiency"];
-                $this->max_efficiency = $r["max_efficiency"];
-                $this->locked = $r["locked"];
-                $this->quality_name = $this->set_quality_name($this->quality);
-                $this->original_quality_name = $this->set_quality_name($this->original_quality);
-
-                // TODO: Get unit ID
-                // TODO: Move efficiencies to a separate method, but the profile API must read it so it's saved.
-                // Get efficiencies, or calculate them if not yet set.
-                if ($this->efficiency == null || $this->efficiency == "" || intval($this->efficiency) == 0){
-                    $this->efficiency = $this->calculate_efficiency();
-                    $this->max_efficiency = $this->calculate_maximum_efficiency();
-                    $statement = get_context()->get_db()->prepare("
-                      UPDATE artifact
-                      SET
-                        efficiency = :efficiency,
-                        max_efficiency = :max_efficiency
-                      WHERE id = :artifact
-                    ");
-                    $statement->bindValue(':efficiency', $this->efficiency, SQLITE3_FLOAT);
-                    $statement->bindValue(':max_efficiency', $this->max_efficiency, SQLITE3_FLOAT);
-                    $statement->bindValue(':artifact', $this->id, SQLITE3_INTEGER);
-                    $statement->execute();
-                }
-            }
-        }
+     * @param int $id Artifact id.
+     */
+    public function __construct($id){
 
-        /**
-         * Gets the quality name from the mappings.
-         *
-         * @param int $q Quality id.
-         * @return string Quality (Uppercase)
-         */
-        private function set_quality_name($q){
-            switch ($q){
-                case QUALITY_ID::NORMAL:
-                    return "NORMAL";
-                case QUALITY_ID::MAGIC:
-                    return "MAGIC";
-                case QUALITY_ID::RARE:
-                    return "RARE";
-                case QUALITY_ID::HERO:
-                    return "HERO";
-                case QUALITY_ID::LEGEND:
-                    return "LEGEND";
-                default:
-                    return "";
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            player,
+            id,
+            type,
+            attribute,
+            archetype,
+            level,
+            quality,
+            original_quality,
+            value,
+            efficiency,
+            max_efficiency,
+            locked
+          FROM artifact
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->player_id = $r["player"];
+            $this->id = $r["id"];
+            $this->type = $r["type"];
+            if ($r["type"] == ARTIFACT_TYPE::ARCHETYPE){
+                $this->archetypal = true;
             }
-        }
-
-        /**
-         * Calcuates the efficiency of the artifact.
-         *
-         * @return float Efficiency
-         */
-        private function calculate_efficiency(){
-            $eff = [0.0, 0.0, 0.0, 0.0];
-
-            $query = "
-              SELECT
-                min,
-                max
-              FROM
-                artifact_roll_type,
-                artifact_effect_roll
-              WHERE
-                artifact_roll_type.id = artifact_effect_roll.type AND
-                artifact_roll_type.initial = :initial AND
-                artifact_roll_type.upgrade = :upgrade AND
-                artifact_effect_roll.effect = :effect
-              ";
-
-            for ($i = 0; $i <= 3; $i ++){
-                if (sizeof($this->effects) > $i && $this->effects[$i] != null && $this->effects[$i]->value > 0){
-                    $value = $this->effects[$i]->value;
-                    $value = $this->effects[$i]->value;
-                    $statement = get_context()->get_db()->prepare($query);
-                    $statement->bindValue(':initial', 1, SQLITE3_TEXT);
-                    $statement->bindValue(':upgrade', 1, SQLITE3_TEXT);
-                    $statement->bindValue(':effect', $this->effects[$i]->effect, SQLITE3_TEXT);
-                    $r_roll = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-                    if ($r_roll ){
-                        $min_initial = 0;//$r_initial["min"];
-                        $max_initial = $r_roll["max"];
-                        $min_upgrade = 0;//$r_upgrade["min"];
-                        $max_upgrade = $r_roll["max"];
-                        $eff[$i] = ((5 * $value) - ( 4 * $min_upgrade + $min_initial)) / ( 8 * ($max_initial - $min_initial + (4 * ($max_upgrade + $min_upgrade))));
-                    }
-                }
+            elseif ($r["type"] == ARTIFACT_TYPE::ELEMENT){
+                $this->elemental = true;
             }
-            $efficiency = 0.0;
-            for ($i = 0; $i <= 3; $i ++){
-                $efficiency += $eff[$i];
-            }
-            $efficiency *= 100;
-            return $efficiency;
-        }
-        
-        private function load_unit(){
-            $statement = get_context()->get_db()->prepare("
-              SELECT unit
-              FROM unit_artifact
-              WHERE
-                artifact = :artifact AND
-                rta = :rta;
-            ");
-            $statement->bindValue(':artifact', $this->id, SQLITE3_TEXT);
-            $statement->bindValue(':rta', get_context()->get_game_mode(), SQLITE3_TEXT);
-            $q = $statement->execute();
-            $r = $q->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->unit_id = $r["unit"];
-                $this->unit = new Unit($r["unit"]);
+            $this->element = $r["attribute"];
+            $this->archetype = $r["archetype"];
+            $this->level = $r["level"];
+            $this->quality = $r["quality"];
+            $this->original_quality = $r["original_quality"];
+            $this->value = $r["value"];
+            $this->efficiency = $r["efficiency"];
+            $this->max_efficiency = $r["max_efficiency"];
+            $this->locked = $r["locked"];
+            $this->quality_name = $this->set_quality_name($this->quality);
+            $this->original_quality_name = $this->set_quality_name($this->original_quality);
+
+            // Get efficiencies, or calculate them if not yet set.
+            if ($this->efficiency == null || $this->efficiency == "" || intval($this->efficiency) == 0){
+                $this->efficiency = $this->calculate_efficiency();
+                $this->max_efficiency = $this->calculate_maximum_efficiency();
+                $statement = get_context()->get_db()->prepare("
+                  UPDATE artifact
+                  SET
+                    efficiency = :efficiency,
+                    max_efficiency = :max_efficiency
+                  WHERE id = :artifact
+                ");
+                $statement->bindValue(':efficiency', $this->efficiency, SQLITE3_FLOAT);
+                $statement->bindValue(':max_efficiency', $this->max_efficiency, SQLITE3_FLOAT);
+                $statement->bindValue(':artifact', $this->id, SQLITE3_INTEGER);
+                $statement->execute();
             }
-            $this->flag_unit = true;
         }
-        
-        private function load_stats(){
-            $this->stat = new Artifact_Stat($this->id);
-
-            // Get effects
-            $statement = get_context()->get_db()->prepare("
-              SELECT slot
-              FROM artifact_effect
-              WHERE artifact = :artifact
-              ORDER BY slot;
-            ");
-            $statement->bindValue(':artifact', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->effects, new Artifact_Effect($this->id, $r["slot"]));
-            }
-            $this->flag_stats = true;
+    }
+
+    /**
+     * Gets the quality name from the mappings.
+     *
+     * @param int $q Quality id.
+     * @return string Quality name (uppercase)
+     */
+    private function set_quality_name($q){
+        switch ($q){
+            case QUALITY_ID::NORMAL:
+                return "NORMAL";
+            case QUALITY_ID::MAGIC:
+                return "MAGIC";
+            case QUALITY_ID::RARE:
+                return "RARE";
+            case QUALITY_ID::HERO:
+                return "HERO";
+            case QUALITY_ID::LEGEND:
+                return "LEGEND";
+            default:
+                return "";
         }
+    }
 
-        /**
-         * Calcuates the maximum efficiency of the artifact.
-         *
-         * @return float Efficiency
-         */
-        private function calculate_maximum_efficiency(){
-            $max_efficiency = $this->efficiency;
-            if ($this->level < 12){
-                $max_efficiency += (1/8);
-            }
-            if ($this->level < 9){
-                $max_efficiency += (1/8);
-            }
-            if ($this->level < 6){
-                $max_efficiency += (1/8);
-            }
-            if ($this->level < 3){
-                $max_efficiency += (1/8);
+    /**
+     * Calcuates the efficiency of the artifact.
+     *
+     * @return float Efficiency
+     */
+    private function calculate_efficiency(){
+        $eff = [0.0, 0.0, 0.0, 0.0];
+
+        $query = "
+          SELECT
+            min,
+            max
+          FROM
+            artifact_roll_type,
+            artifact_effect_roll
+          WHERE
+            artifact_roll_type.id = artifact_effect_roll.type AND
+            artifact_roll_type.initial = :initial AND
+            artifact_roll_type.upgrade = :upgrade AND
+            artifact_effect_roll.effect = :effect
+          ";
+
+        for ($i = 0; $i <= 3; $i ++){
+            if (sizeof($this->effects) > $i && $this->effects[$i] != null && $this->effects[$i]->value > 0){
+                $value = $this->effects[$i]->value;
+                $value = $this->effects[$i]->value;
+                $statement = get_context()->get_db()->prepare($query);
+                $statement->bindValue(':initial', 1, SQLITE3_TEXT);
+                $statement->bindValue(':upgrade', 1, SQLITE3_TEXT);
+                $statement->bindValue(':effect', $this->effects[$i]->effect, SQLITE3_TEXT);
+                $r_roll = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+                if ($r_roll ){
+                    $min_initial = 0;//$r_initial["min"];
+                    $max_initial = $r_roll["max"];
+                    $min_upgrade = 0;//$r_upgrade["min"];
+                    $max_upgrade = $r_roll["max"];
+                    $eff[$i] = ((5 * $value) - ( 4 * $min_upgrade + $min_initial)) / ( 8 * ($max_initial - $min_initial + (4 * ($max_upgrade + $min_upgrade))));
+                }
             }
-            return $max_efficiency;
-        }
-        
-        /**
-         * Retrieves the owner's player identifier.
-         *
-         * @return int Player ID.
-         */
-        public function get_player_id(){
-            return $this->player_id;
-        }
-        
-        /**
-         * Retrieves the artifact identifier.
-         *
-         * @return string Artifact ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
-        
-        /**
-         * Checks if the artifact is elemental or archetiplal.
-         *
-         * @return int ARTIFACT_TYPE_ID::ELEMENT or ARTIFACT_TYPE:ARCHETYPE.
-         */
-        public function get_type(){
-            return $this->type;
-        }
-        
-        /**
-         * Cheks if the artifact is an elemental one.
-         *
-         * @return boolean True for elemental artifacts, false for archetipal ones.
-         */
-        public function is_elemental(){
-            return $this->elemental;
-        }
-        
-        /**
-         * Cheks if the artifact is an archetipal one.
-         *
-         * @return boolean True for archetipal artifacts, false for elemental ones.
-         */
-        public function is_archetypal(){
-            return $this->archetypal;
-        }
-        
-        /**
-         * Retrieves the element of an elemental artifact.
-         *
-         * @see ELEMENT_ID
-         *
-         * @return int Element ID, null for archetipal artifacts.
-         */
-        public function get_element(){
-            return $this->element;
-        }
-        
-        /**
-         * Retrieves the archetype of an archetipal artifact.
-         *
-         * @see ARCHETYPE_ID
-         *
-         * @return int Archetype ID, null for elemental artifacts.
-         */
-        public function get_archetype(){
-            return $this->archetype;
         }
-        
-        /**
-         * Retrieves the artifact level.
-         *
-         * @return int Artifact level (0-15).
-         */
-        public function get_level(){
-            return $this->level;
+        $efficiency = 0.0;
+        for ($i = 0; $i <= 3; $i ++){
+            $efficiency += $eff[$i];
         }
-        
-        /**
-         * Retrieves the quality of the artifact.
-         *
-         * @see QUALITY_ID
-         *
-         * @return int Quality of the artifact.
-         */
-        public function get_quality(){
-            return $this->quality;
-        }
-        
-        /**
-         * Retrieves the original quality of the artifact.
-         *
-         * @see QUALITY_ID
-         *
-         * @return int Original quality of the artifact.
-         */
-        public function get_original_quality(){
-            return $this->original_quality;
-        }
-        
-        /**
-         * Retrieves the quality name.
-         *
-         * @return string Quality name, uppercase.
-         */
-        public function get_quality_name(){
-            return $this->quality_name;
+        $efficiency *= 100;
+        return $efficiency;
+    }
+
+    /**
+     * Loads the unit that equips the artifact into the entity (if any).
+     * 
+     * Must be called only once before trying to get the unit. Sets the flag
+     * {@link Artifact:$flag_unit} to true.
+     */
+    private function load_unit(){
+        $statement = get_context()->get_db()->prepare("
+          SELECT unit
+          FROM unit_artifact
+          WHERE
+            artifact = :artifact AND
+            rta = :rta;
+        ");
+        $statement->bindValue(':artifact', $this->id, SQLITE3_TEXT);
+        $statement->bindValue(':rta', get_context()->get_game_mode(), SQLITE3_TEXT);
+        $q = $statement->execute();
+        $r = $q->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->unit_id = $r["unit"];
+            $this->unit = new Unit($r["unit"]);
         }
-        
-        /**
-         * Retrieves the original quality name.
-         *
-         * @return string Original quality name, uppercase.
-         */
-        public function get_original_quality_name(){
-            return $this->original_quality_name;
+        $this->flag_unit = true;
+    }
+
+    /**
+     * Loads the artifact main stat and effects into the entity.
+     *
+     * Must be called only once before trying to get the stat or effects. Sets the flag
+     * {@link Artifact:$flag_stats} to true.
+     */
+    private function load_stats(){
+        $this->stat = new Artifact_Stat($this->id);
+        $statement = get_context()->get_db()->prepare("
+          SELECT slot
+          FROM artifact_effect
+          WHERE artifact = :artifact
+          ORDER BY slot;
+        ");
+        $statement->bindValue(':artifact', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->effects, new Artifact_Effect($this->id, $r["slot"]));
         }
-        
-        /**
-         * Retrieves the value of the artifact.
-         *
-         * @return int artifact value.
-         */
-        public function get_value(){
-            return $this->value;
+        $this->flag_stats = true;
+    }
+
+    /**
+     * Calcuates the maximum efficiency of the artifact.
+     *
+     * @return float Efficiency.
+     */
+    private function calculate_maximum_efficiency(){
+        $max_efficiency = $this->efficiency;
+        if ($this->level < 12){
+            $max_efficiency += (1/8);
         }
-        
-        /**
-         * Retrieves the efficiency of the artifact.
-         *
-         * @return float Artifact efficiency (0-100).
-         */
-        public function get_efficiency(){
-            return $this->efficiency;
+        if ($this->level < 9){
+            $max_efficiency += (1/8);
         }
-        
-        /**
-         * Retrieves the maximum efficiency of the artifact.
-         *
-         * @return float Artifact maximum efficiency (0-100).
-         */
-        public function get_max_efficiency(){
-            return $this->max_efficiency;
+        if ($this->level < 6){
+            $max_efficiency += (1/8);
         }
-        
-        /**
-         * Retrieves the artifact's main stat.
-         *
-         * @return Artifact_Stat Artifact main stat.
-         */
-        public function get_stat(){
-            if (!$this->flag_stats){
-                $this->load_stats();
-            }
-            return $this->stat;
+        if ($this->level < 3){
+            $max_efficiency += (1/8);
         }
-        
-        /**
-         * Retrieves a list of the artifact's effects.
-         *
-         * @return Artifact_Effect[] List of effects.
-         */
-        public function get_effects(){
-            if (!$this->flag_stats){
-                $this->load_stats();
-            }
-            return $this->effects;
+        return $max_efficiency;
+    }
+
+    /**
+     * Retrieves the owner's player identifier.
+     *
+     * @return int Player ID.
+     */
+    public function get_player_id(){
+        return $this->player_id;
+    }
+
+    /**
+     * Retrieves the artifact identifier.
+     *
+     * @return string Artifact ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Checks if the artifact is elemental or archetiplal.
+     *
+     * @return int ARTIFACT_TYPE_ID::ELEMENT or ARTIFACT_TYPE:ARCHETYPE.
+     */
+    public function get_type(){
+        return $this->type;
+    }
+
+    /**
+     * Cheks if the artifact is an elemental one.
+     *
+     * @return bool True for elemental artifacts, false for archetipal ones.
+     */
+    public function is_elemental(){
+        return $this->elemental;
+    }
+
+    /**
+     * Cheks if the artifact is an archetipal one.
+     *
+     * @return bool True for archetipal artifacts, false for elemental ones.
+     */
+    public function is_archetypal(){
+        return $this->archetypal;
+    }
+
+    /**
+     * Retrieves the element of an elemental artifact.
+     *
+     * @see ELEMENT_ID
+     *
+     * @return int Element ID, null for archetipal artifacts.
+     */
+    public function get_element(){
+        return $this->element;
+    }
+
+    /**
+     * Retrieves the archetype of an archetipal artifact.
+     *
+     * @see ARCHETYPE_ID
+     *
+     * @return int Archetype ID, null for elemental artifacts.
+     */
+    public function get_archetype(){
+        return $this->archetype;
+    }
+
+    /**
+     * Retrieves the artifact level.
+     *
+     * @return int Artifact level (0-15).
+     */
+    public function get_level(){
+        return $this->level;
+    }
+
+    /**
+     * Retrieves the quality of the artifact.
+     *
+     * @see QUALITY_ID
+     *
+     * @return int Quality of the artifact.
+     */
+    public function get_quality(){
+        return $this->quality;
+    }
+
+    /**
+     * Retrieves the original quality of the artifact.
+     *
+     * @see QUALITY_ID
+     *
+     * @return int Original quality of the artifact.
+     */
+    public function get_original_quality(){
+        return $this->original_quality;
+    }
+
+    /**
+     * Retrieves the quality name.
+     *
+     * @return string Quality name, uppercase.
+     */
+    public function get_quality_name(){
+        return $this->quality_name;
+    }
+
+    /**
+     * Retrieves the original quality name.
+     *
+     * @return string Original quality name, uppercase.
+     */
+    public function get_original_quality_name(){
+        return $this->original_quality_name;
+    }
+
+    /**
+     * Retrieves the value of the artifact.
+     *
+     * @return int artifact value.
+     */
+    public function get_value(){
+        return $this->value;
+    }
+
+    /**
+     * Retrieves the efficiency of the artifact.
+     *
+     * @return float Artifact efficiency (0-100).
+     */
+    public function get_efficiency(){
+        return $this->efficiency;
+    }
+
+    /**
+     * Retrieves the maximum efficiency of the artifact.
+     *
+     * @return float Artifact maximum efficiency (0-100).
+     */
+    public function get_max_efficiency(){
+        return $this->max_efficiency;
+    }
+
+    /**
+     * Retrieves the artifact's main stat.
+     *
+     * @return Artifact_Stat Artifact main stat.
+     */
+    public function get_stat(){
+        if (!$this->flag_stats){
+            $this->load_stats();
         }
-        
-        /**
-         * Retrieves the identifier of the unit who has eqquiped the artifact.
-         *
-         * @return string Unit ID.
-         */
-        public function get_unit_id(){
-            if (!$this->flag_unit){
-                $this->load_unit();
-            }
-            return $this->unit_id;
+        return $this->stat;
+    }
+
+    /**
+     * Retrieves a list of the artifact's effects.
+     *
+     * @return Artifact_Effect[] List of effects.
+     */
+    public function get_effects(){
+        if (!$this->flag_stats){
+            $this->load_stats();
         }
+        return $this->effects;
+    }
 
-        /**
-         * Retrieves the unit who has eqquiped the artifact.
-         *
-         * @return Unit Unit who has equipped the artifact.
-         */
-        public function get_unit(){
-            if (!$this->flag_unit){
-                $this->load_unit();
-            }
-            return $this->unit;
+    /**
+     * Retrieves the identifier of the unit who has eqquiped the artifact.
+     *
+     * @return string Unit ID.
+     */
+    public function get_unit_id(){
+        if (!$this->flag_unit){
+            $this->load_unit();
         }
+        return $this->unit_id;
+    }
 
+    /**
+     * Retrieves the unit who has eqquiped the artifact.
+     *
+     * @return Unit Unit who has equipped the artifact.
+     */
+    public function get_unit(){
+        if (!$this->flag_unit){
+            $this->load_unit();
+        }
+        return $this->unit;
     }
-?>
+
+}

+ 132 - 112
application/entity/Artifact_Effect.php

@@ -1,132 +1,152 @@
 <?php
+/**
+ * Artifact effect entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Artifact effect.
+ *
+ * Represents each of the up to 4 artifact effects (not the main stat).
+ *
+ * @category Entity
+ */
+class Artifact_Effect extends Entity{
+
     /**
-     * Artifact effect entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int The effect slot ({@see ARTIFACT_EFFECT_SLOT_ID}).
+     */
+    private $slot;
+
+    /**
+     * @var int The effect ID.
+     */
+    private $effect;
+
+    /**
+     * @var string The effect name.
+     */
+    private $name;
+
+    /**
+     * @var float The value of the effect.
      */
+    private $value;
 
-    /*
-     * Require dependent entities if not present.
+    /**
+     * @var float The grinded value of the effect.
+     */
+    private $grind;
+
+    /**
+     * @var bool Indicates if the effect has been enchanted.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $enchant;
 
     /**
-     * Artifact effect.
+     * Constructor.
      *
-     * Represents an object from the table 'artifact_effect'.
+     * Retrieves the artifact effect information from the database.
      *
-     * @category Entity
+     * @param int $artifact Artifact id.
+     * @param int $slot Artifact effect slot id.
      */
-    class Artifact_Effect extends Entity{
-
-        private $slot;
-        private $effect;
-        private $name = "";
-        private $value;
-        private $grind;
-        private $enchant;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the artifact effect information from the database.
-         *
-         * @param int $artifact Artifact id.
-         * @param int $slot Artifact slot id.
-         */
-        public function __construct($artifact, $slot){
+    public function __construct($artifact, $slot){
 
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            slot,
+            effect,
+            value,
+            enchant,
+            grind
+          FROM artifact_effect
+          WHERE
+            artifact = :artifact AND
+            slot = :slot;
+        ");
+        $statement->bindValue(':artifact', $artifact, SQLITE3_TEXT);
+        $statement->bindValue(':slot', $slot, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->effect = $r["effect"];
+            $this->value = $r["value"];
+            $this->enchant = $r["enchant"];
+            $this->grind = $r["grind"];
             $statement = get_context()->get_db()->prepare("
-              SELECT
-                slot,
-                effect,
-                value,
-                enchant,
-                grind
-              FROM artifact_effect
-              WHERE
-                artifact = :artifact AND
-                slot = :slot;
+              SELECT name
+              FROM effect_artifact
+              WHERE id = :id;
             ");
-            $statement->bindValue(':artifact', $artifact, SQLITE3_TEXT);
-            $statement->bindValue(':slot', $slot, SQLITE3_TEXT);
+            $statement->bindValue(':id', $this->effect, SQLITE3_TEXT);
             $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
             if ($r){
-                $this->effect = $r["effect"];
-                $this->value = $r["value"];
-                $this->enchant = $r["enchant"];
-                $this->grind = $r["grind"];
-                $statement = get_context()->get_db()->prepare("
-                  SELECT name
-                  FROM effect_artifact
-                  WHERE id = :id;
-                ");
-                $statement->bindValue(':id', $this->effect, SQLITE3_TEXT);
-                $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-                if ($r){
-                    $this->name = str_replace("{}", $this->value, $r["name"]);
-                }
-
+                $this->name = str_replace("{}", $this->value, $r["name"]);
             }
-        }
 
-        /**
-         * Retrieves the artifact effect's slot identifier.
-         *
-         * @see ARTIFACT_EFFECT_SLOT_ID
-         *
-         * @return int Effect slot ID.
-         */
-        public function get_slot(){
-            return $this->slot;
-        }
-        
-        /**
-         * Artifact effect identifier.
-         *
-         * @return int Effect ID.
-         */
-        public function get_effect(){
-            return $this->effect;
-        }
-        
-        /**
-         * Retrieves the artifact effect name.
-         *
-         * @return string The effect name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
-        
-        /**
-         * Retrieves the value of the artifact effect, excluding grinds.
-         *
-         * @return number Effect value.
-         */
-        public function get_value(){
-            return $this->value;
-        }
-        
-        /**
-         * Retrieves the grinded value on the effect.
-         *
-         * @return number Effect grinded value.
-         */
-        public function get_grind(){
-            return $this->grind;
-        }
-        
-        /**
-         * Checks if the effect has been enchanted.
-         *
-         * @return boolean True if the effect was enchanted, false otherwise
-         */
-        public function is_enchanted(){
-            return filter_var($this->enchant, FILTER_VALIDATE_BOOLEAN);
         }
+    }
 
+    /**
+     * Retrieves the artifact effect's slot identifier.
+     *
+     * @see ARTIFACT_EFFECT_SLOT_ID
+     * @return int Effect slot ID.
+     */
+    public function get_slot(){
+        return $this->slot;
+    }
+
+    /**
+     * Artifact effect identifier.
+     *
+     * @return int Effect ID.
+     */
+    public function get_effect(){
+        return $this->effect;
+    }
+
+    /**
+     * Retrieves the artifact effect name.
+     *
+     * @return string The effect name.
+     */
+    public function get_name(){
+        return $this->name;
     }
-?>
+
+    /**
+     * Retrieves the value of the artifact effect, excluding grinds.
+     *
+     * @return float Effect value.
+     */
+    public function get_value(){
+        return $this->value;
+    }
+
+    /**
+     * Retrieves the grinded value on the effect.
+     *
+     * @return float Effect grinded value.
+     */
+    public function get_grind(){
+        return $this->grind;
+    }
+
+    /**
+     * Checks if the effect has been enchanted.
+     *
+     * @return bool True if the effect was enchanted, false otherwise
+     */
+    public function is_enchanted(){
+        return filter_var($this->enchant, FILTER_VALIDATE_BOOLEAN);
+    }
+
+}

+ 86 - 77
application/entity/Artifact_Stat.php

@@ -1,93 +1,102 @@
 <?php
+/**
+ * Artifact stat entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Artifact stat.
+ *
+ * Represents the artifact main stat.
+ *
+ * @category Entity
+ */
+class Artifact_Stat extends Entity{
+
     /**
-     * Artifact stat entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Artifact stat ID ({@see ARTIFACT_STAT_ID}).
+     */
+    private $stat;
+
+    /**
+     * @var string Artifact stat name.
      */
+    private $name;
 
-    /*
-     * Require dependent entities if not present.
+    /**
+     * @var int The value of the artifact stat.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $value;
 
     /**
-     * Artifact_stat.
+     * Constructor.
      *
-     * Represents an object from the table 'artifact_stat'.
+     * Retrieves the artifact stat information from the database.
      *
-     * @category Entity
+     * @param int $artifact_id Artifact id.
      */
-    class Artifact_Stat extends Entity{
-
-        private $stat;
-        private $name = "";
-        private $value;
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the artifact stat information from the database.
-         *
-         * @param int $artifact_id Artifact id.
-         */
-        public function __construct($artifact_id){
+    public function __construct($artifact_id){
 
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                stat,
-                value
-              FROM artifact_stat
-              WHERE
-                artifact = :artifact
-            ");
-            $statement->bindValue(':artifact', $artifact_id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->stat = $r["stat"];
-                $this->value = $r["value"];
-                switch ($this->stat){
-                    case ARTIFACT_STAT_ID::HP:
-                        $this->name = "HP";
-                        break;
-                    case ARTIFACT_STAT_ID::ATK:
-                        $this->name = "ATK";
-                        break;
-                    case ARTIFACT_STAT_ID::DEF:
-                        $this->name = "DEF";
-                        break;
-                }
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            stat,
+            value
+          FROM artifact_stat
+          WHERE
+            artifact = :artifact
+        ");
+        $statement->bindValue(':artifact', $artifact_id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->stat = $r["stat"];
+            $this->value = $r["value"];
+            switch ($this->stat){
+                case ARTIFACT_STAT_ID::HP:
+                    $this->name = "HP";
+                    break;
+                case ARTIFACT_STAT_ID::ATK:
+                    $this->name = "ATK";
+                    break;
+                case ARTIFACT_STAT_ID::DEF:
+                    $this->name = "DEF";
+                    break;
             }
         }
-        /**
-         * Retrieves the artifact stat identifier.
-         * 
-         * @see ARTIFACT_STAT_ID
-         *
-         * @return int Artifact stat ID.
-         */
-        public function get_stat(){
-            return $this->stat;
-        }
-
-        /**
-         * Retrieves the artifact stat name.
-         *
-         * @return string Artifact stat name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
+    }
+    /**
+     * Retrieves the artifact stat identifier.
+     * 
+     * @see ARTIFACT_STAT_ID
+     *
+     * @return int Artifact stat ID.
+     */
+    public function get_stat(){
+        return $this->stat;
+    }
 
-        /**
-         * Retrieves the value of the artifact stat value.
-         *
-         * @return number Stat value.
-         */
-        public function get_value(){
-            return $this->value;
-        }
+    /**
+     * Retrieves the artifact stat name.
+     *
+     * @return string Artifact stat name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
 
+    /**
+     * Retrieves the value of the artifact stat value.
+     *
+     * @return int Stat value.
+     */
+    public function get_value(){
+        return $this->value;
     }
-?>
+
+}

+ 86 - 75
application/entity/Buildable.php

@@ -1,93 +1,104 @@
 <?php
+/**
+ * Buildable entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Buildable.
+ *
+ * Represents any of the available buildings in the game.
+ * 
+ * Buildings that can be built and leveled up are not considered buildables, but {@link Decorative}.
+ * It does not represent a building owned by the player.
+ *
+ * @category Entity
+ */
+class Buildable extends Entity{
+
     /**
-     * Buildable key entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Buildable ID.
      */
+    private $id;
 
     /**
-     * Require dependent entities if not present.
+     * @var string Buildable name.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $name;
 
+    /**
+     * @var string Buildable description.
+     */
+    private $description;
 
     /**
-     * Buildable.
+     * Constructor.
      *
-     * Represents an object from the table 'buildable'.
+     * Searches the database and retrieves the information about the
+     * building, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Buildable identifier.
      */
-    class Buildable extends Entity{
+    public function __construct($id){
 
-        private $id;
-        private $name;
-        private $description;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            name,
+            description
+          FROM buildable
+           WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->name = HTML::e($r["name"]);
+            $this->description = HTML::e($r["description"]);
+        }
+    }
 
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * building, populating it and it's items.
-         *
-         * @param int $id Buildable identifier.
-         */
-        public function __construct($id){
+    /**
+     * Retrieves the buildable identifier.
+     *
+     * @return int Buildable ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
 
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                name,
-                description
-              FROM buildable
-               WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->id = $r["id"];
-                $this->name = HTML::e($r["name"]);
-                $this->description = HTML::e($r["description"]);
-            }
-        }
+    /**
+     * Retrieves the buildable name.
+     *
+     * @return string Buildable name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
 
-        /**
-         * Retrieves the buildable identifier.
-         *
-         * @return int Buildable ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
-    
-        /**
-         * Retrieves the buildable name.
-         *
-         * @return string Buildable name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
-    
-        /**
-         * Retrieves the buildable description.
-         *
-         * @return string Buildable description.
-         */
-        public function get_description(){
-            return $this->description;
-        }
-    
-        /**
-         * Gets the path to the building image. 
-         *
-         * @return string Image URL, or a fixed unknown image.
-         */
-        public function get_image(){
-            return APPLICATION::img("BUILDING", $this->id);
-        }
+    /**
+     * Retrieves the buildable description.
+     *
+     * @return string Buildable description.
+     */
+    public function get_description(){
+        return $this->description;
+    }
 
+    /**
+     * Gets the path to the building image. 
+     *
+     * @return string Image URL, or a fixed unknown image.
+     */
+    public function get_image(){
+        return APPLICATION::img("BUILDING", $this->id);
     }
-?>
+
+}

+ 78 - 68
application/entity/Building.php

@@ -1,84 +1,94 @@
 <?php
 
+/**
+ * Building entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+require_once(PATH::ENTITY . "Buildable.php");
+
+/**
+ * A building.
+ *
+ * Represents an building owned by a player.
+ * Buildings that can be built and leveled up are not considered buildings, but {@link Decoration}s.
+ *
+ * @category Entity
+ */
+class Building extends Entity{
+
     /**
-     * Building entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Owner's player ID.
      */
+    private $player_id;
 
     /**
-     * Require dependent entities if not present.
+     * @var Buildable The base buildable.
      */
-    require_once(PATH::ENTITY . "Entity.php");
-    require_once(PATH::ENTITY . "Buildable.php");
+    private $buildable;
 
     /**
-     * A Building.
+     * @var int The gain per hour, on whatever bonus the building provides.
+     */
+    private $gain;
+
+    /**
+     * Constructor.
      *
-     * Represents an object from the table 'building'.
+     * Searches the database and retrieves the information about the
+     * building, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Building identifier.
      */
-    class Building extends Entity{
+    public function __construct($id){
 
-        private $player_id;
-        private $buildable;
-        private $gain;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            player,
+            buildable,
+            gain
+          FROM building
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->player = $r["player"];
+            $this->buildable = new Buildable($r["buildable"]);
+            $this->gain = $r["gain"];
+        }
+    }
+    /**
+     * Retrieves the player identifier of the owner
+     *
+     * @return int Player ID.
+     */
+    public function get_player(){
+        return $this->player_id;
+    }
 
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * building, populating it and it's items.
-         *
-         * @param int $id Building identifier.
-         */
-        public function __construct($id){
+    /**
+     * Retrieves the base buildable.
+     *
+     * @return Buildable Base buildable.
+     */
+    public function get_buildable(){
+        return $this->buildable;
+    }
 
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                player,
-                buildable,
-                gain
-              FROM building
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->player = $r["player"];
-                $this->buildable = new Buildable($r["buildable"]);
-                $this->gain = $r["gain"];
-            }
-        }
-        /**
-         * Retrieves the player identifier of the owner
-         *
-         * @return int Player ID.
-         */
-        public function get_player(){
-            return $this->player_id;
-        }
-    
-        /**
-         * Retrieves the base buildable.
-         *
-         * @return Buildable Base buildable.
-         */
-        public function get_buildable(){
-            return $this->buildable;
-        }
-    
-        /**
-         * Retrieves the gain per hour, on whatever the building provides.
-         *
-         * @return number Gain per hour.
-         */
-        public function get_gain(){
-            return $this->gain;
-        }
-    
+    /**
+     * Retrieves the gain per hour, on whatever the building provides.
+     *
+     * @return int Gain per hour.
+     */
+    public function get_gain(){
+        return $this->gain;
     }
-?>
+
+}

+ 79 - 68
application/entity/Decoration.php

@@ -1,83 +1,94 @@
 <?php
+/**
+ * Decoration entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+require_once(PATH::ENTITY . "Decorative.php");
+
+/**
+ * A decoration.
+ *
+ * Represents a decoration owned by a player.
+ * Decorations are buildings that can be built and leveled up. If it can't be leveled up, it's not
+ * a decoration, but a {@link Building}.
+ *
+ * @category Entity
+ */
+class Decoration extends Entity{
+
     /**
-     * Decoration entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Owner's player ID.
      */
+    private $player_id;
 
     /**
-     * Require dependent entities if not present.
+     * @var Decorative Base decorative.
      */
-    require_once(PATH::ENTITY . "Entity.php");
-    require_once(PATH::ENTITY . "Decorative.php");
+    private $decorative;
 
     /**
-     * A Decoration.
+     * @var int Current level. 
+     */
+    private $level;
+
+    /**
+     * Constructor.
      *
-     * Represents an object from the table 'decoration'.
+     * Searches the database and retrieves the information about the
+     * decoration, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Building identifier.
      */
-    class Decoration extends Entity{
+    public function __construct($id){
 
-        private $player_id;
-        private $decorative;
-        private $level;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            player,
+            decorative,
+            level
+          FROM decoration
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->player = $r["player"];
+            $this->decorative = new Decorative($r["decorative"]);
+            $this->level = $r["level"];
+        }
+    }
+    /**
+     * Retrieves the owner's player id.
+     *
+     * @return int Player ID.
+     */
+    public function get_player_id(){
+        return $this->player_id;
+    }
 
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * decoration, populating it and it's items.
-         *
-         * @param int $id Building identifier.
-         */
-        public function __construct($id){
+    /**
+     * Retrieves the base decorative structure.
+     *
+     * @return Decorative Base decorative.
+     */
+    public function get_decorative(){
+        return $this->decorative;
+    }
 
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                player,
-                decorative,
-                level
-              FROM decoration
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->player = $r["player"];
-                $this->decorative = new Decorative($r["decorative"]);
-                $this->level = $r["level"];
-            }
-        }
-        /**
-         * Retrieves the owner's player id.
-         *
-         * @return int Player ID.
-         */
-        public function get_player_id(){
-            return $this->player_id;
-        }
-    
-        /**
-         * Retrieves the base decorative structure.
-         *
-         * @return Decorative Base decorative.
-         */
-        public function get_decorative(){
-            return $this->decorative;
-        }
-    
-        /**
-         * Retrieves the decoration level.
-         *
-         * @return int Decoration level.
-         */
-        public function get_level(){
-            return $this->level;
-        }
-    
+    /**
+     * Retrieves the decoration level.
+     *
+     * @return int Decoration level.
+     */
+    public function get_level(){
+        return $this->level;
     }
-?>
+
+}

+ 196 - 198
application/entity/Decorative.php

@@ -1,218 +1,216 @@
 <?php
+/**
+ * Decorative entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Decorative.
+ *
+ * Represents any of the available decorations in the game.
+ * Decorations are buildings that can be built and leveled up. If it can't be leveled up, it's not
+ * a decorative, but a {@link Buildable}.
+ *
+ * @category Entity
+ */
+class Decorative extends Entity{
+
     /**
-     * Decorative key entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Decorative identifier.
+     */
+    private $id;
+
+    /**
+     * @var string Decorative name.
+     */
+    private $name;
+
+    /**
+     * @var string Decorative description.
+     */
+    private $description;
+
+    /**
+     * @var int Area of effect identifier (if any).
+     */
+    private $area;
+
+    /**
+     * @var int Affected stat id (if any).
+     */
+    private $stat;
+
+    /**
+     * @var int Affected element  id(if any).
+     */
+    private $element;
+
+    /**
+     * @var int Max. level.
+     */
+    private $max_level;
+
+    /**
+     * @var int[] Effect bonus per level.
      */
+    private $level_bonus = [];
 
     /**
-     * Require dependent entities if not present.
+     * Cost per level.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $level_cost = [];
 
 
     /**
-     * Decorative.
+     * Constructor.
      *
-     * Represents an object from the table 'k_decorative'.
+     * Searches the database and retrieves the information about the
+     * decoration, populating it and it's items.
      *
-     * @category Entity
-     */
-    class Decorative extends Entity{
-
-        /**
-         * @var int Decorative identifier.
-         */
-        public $id;
-
-        /**
-         * @var string Decorative name.
-         */
-        public $name;
-
-        /**
-         * @var string Decorative description.
-         */
-        public $description;
-
-        /**
-         * @var int Area of effect identifier (if any).
-         */
-        public $area;
-
-        /**
-         * @var int Affected stat id (if any).
-         */
-        public $stat;
-
-        /**
-         * @var int Affected element  id(if any).
-         */
-        public $element;
-
-        /**
-         * @var int Max. level.
-         */
-        public $max_level;
-
-        /**
-         * @var int[] Effect bonus per level.
-         */
-        public $level_bonus = [];
-
-        /**
-         * Cost per level.
-         */
-        public $level_cost = [];
-
-        
-    
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * decoration, populating it and it's items.
-         *
-         * @param int $id Decorative identifier.
-         */
-        public function __construct($id){
-
+     * @param int $id Decorative identifier.
+     */
+    public function __construct($id){
+
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              id,
+              name,
+              description,
+              area,
+              affected_stat,
+              element,
+              max_level
+            FROM decorative
+           WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->name = HTML::e($r["name"]);
+            $this->description = HTML::e($r["description"]);
+            $this->area = $r["area"];
+            $this->stat = $r["affected_stat"];
+            $this->element = $r["element"];
+            $this->max_level = $r["max_level"];
             $statement = get_context()->get_db()->prepare("
                 SELECT
-                  id,
-                  name,
-                  description,
-                  area,
-                  affected_stat,
-                  element,
-                  max_level
-                FROM decorative
-               WHERE id = :id;
+                  level,
+                  bonus,
+                  cost
+                FROM decorative_level
+                WHERE decorative = :id
             ");
             $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->id = $r["id"];
-                $this->name = HTML::e($r["name"]);
-                $this->description = HTML::e($r["description"]);
-                $this->area = $r["area"];
-                $this->stat = $r["affected_stat"];
-                $this->element = $r["element"];
-                $this->max_level = $r["max_level"];
-                $statement = get_context()->get_db()->prepare("
-                    SELECT
-                      level,
-                      bonus,
-                      cost
-                    FROM decorative_level
-                    WHERE decorative = :id
-                ");
-                $statement->bindValue(':id', $id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    $this->level_bonus[$r["level"]] = $r["bonus"];
-                    $this->level_cost[$r["level"]] = $r["cost"];
-                }
+            $q = $statement->execute();
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                $this->level_bonus[$r["level"]] = $r["bonus"];
+                $this->level_cost[$r["level"]] = $r["cost"];
             }
         }
-        
-        /**
-         * Retrieves the decorative identifier.
-         *
-         * @return int Decorative ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
-        
-        /**
-         * Retrieves the name of the decorative.
-         *
-         * @return string Decorative name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
-        
-        /**
-         * Retrieves $the decorative description.
-         *
-         * @return string Decorative description.
-         */
-        public function get_description(){
-            return $this->description;
-        }
-        
-        /**
-         * Retrieves the identifier of the area where the decorative has an effect
-         *
-         * @see AREA_TYPE_ID
-         *
-         * @return int Area type ID, null if the decorative has a global effect.
-         */
-        public function get_area_type(){
-            return $this->area;
-        }
-        
-        /**
-         * Retrieves the stat raised by the decorative, if any.
-         *
-         * @see STAT_ID
-         *
-         * @return int Stat ID, null if non applicable.
-         */
-        public function get_stat(){
-            return $this->stat;
-        }
-        
-        /**
-         * Retrieves the element the effect applies to, if any.
-         *
-         * @see ELEMENT_ID
-         *
-         * @return int Element ID, null if not an elemental decorative.
-         */
-        public function get_element(){
-            return $this->element;
-        }
-        
-        /**
-         * Retrieves the maximum level of the decorative.
-         *
-         * @return int Maximum level.
-         */
-        public function get_max_level(){
-            return $this->max_level;
-        }
-        
-        /**
-         * Retrieves a list of bonuses indexed by the decorative level.
-         *
-         * @return number[] Array of bonuses by level.
-         */
-        public function get_level_bonus(){
-            return $this->level_bonus;
-        }
-        
-        /**
-         * Retrieves a list of prices indexed by the decorative level.
-         *
-         * @return number[] Array of prices by level.
-         */
-        public function get_level_cost(){
-            return $this->level_cost;
-        }
+    }
 
-        /**
-         * Gets the path to the decorative image.
-         *
-         * @return string Image URL, or a fixed unknown image.
-         */
-        public function get_image(){
-            return APPLICATION::img("DECORATION", $this->id);
-        }
+    /**
+     * Retrieves the decorative identifier.
+     *
+     * @return int Decorative ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Retrieves the name of the decorative.
+     *
+     * @return string Decorative name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
+
+    /**
+     * Retrieves $the decorative description.
+     *
+     * @return string Decorative description.
+     */
+    public function get_description(){
+        return $this->description;
+    }
+
+    /**
+     * Retrieves the identifier of the area where the decorative has an effect
+     *
+     * @see AREA_TYPE_ID
+     *
+     * @return int Area type ID, null if the decorative has a global effect.
+     */
+    public function get_area_type(){
+        return $this->area;
+    }
+
+    /**
+     * Retrieves the stat raised by the decorative, if any.
+     *
+     * @see STAT_ID
+     *
+     * @return int Stat ID, null if non applicable.
+     */
+    public function get_stat(){
+        return $this->stat;
+    }
+
+    /**
+     * Retrieves the element the effect applies to, if any.
+     *
+     * @see ELEMENT_ID
+     *
+     * @return int Element ID, null if not an elemental decorative.
+     */
+    public function get_element(){
+        return $this->element;
+    }
+
+    /**
+     * Retrieves the maximum level of the decorative.
+     *
+     * @return int Maximum level.
+     */
+    public function get_max_level(){
+        return $this->max_level;
+    }
+
+    /**
+     * Retrieves a list of bonuses indexed by the decorative level.
+     *
+         * @return int[] Array of bonuses by level.
+     */
+    public function get_level_bonus(){
+        return $this->level_bonus;
+    }
 
+    /**
+     * Retrieves a list of prices indexed by the decorative level.
+     *
+         * @return int[] Array of prices by level.
+     */
+    public function get_level_cost(){
+        return $this->level_cost;
     }
-?>
+
+    /**
+     * Gets the path to the decorative image.
+     *
+     * @return string Image URL, or a fixed unknown image.
+     */
+    public function get_image(){
+        return APPLICATION::img("DECORATION", $this->id);
+    }
+
+}

+ 107 - 94
application/entity/Effect.php

@@ -1,111 +1,124 @@
 <?php
+/**
+ * Effect entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Skill effect.
+ *
+ * Represents an effect a skill can induce.
+ *
+ * @category Entity
+ */
+class Effect extends Entity{
+
+    /**
+     * @var int Effect ID.
+     */
+    private $id;
+
+    /**
+     * @var string Effect name.
+     */
+    private $name;
+
+    /**
+     * @var bool Indicates if the effect is a buff.
+     */
+    private $is_buff;
+
+    /**
+     * @var string Effect description.
+     */
+    private $description;
+
     /**
-     * Effect key entity file.
+     * Constructor.
      *
-     * Creates the entity and makes it available.
+     * Searches the database and retrieves the information about the
+     * skill level, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Effect identifier.
      */
+    public function __construct($id){
+
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            name,
+            is_buff,
+            description
+          FROM effect
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->name = HTML::e($r["name"]);
+            $this->is_buff = $r["is_buff"];
+            $this->description = HTML::e($r["description"]);
+        }
+    }
 
     /**
-     * Require dependent entities if not present.
+     * Retrieves the effect identifier.
+     *
+     * @return int Effect ID.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    public function get_id(){
+        return $this->id;
+    }
 
     /**
-     * Skill effect.
+     * Retrieves the effect name.
      *
-     * Represents an object from the table 'effect'.
-     *
-     * @category Entity
+     * @return string Effect name.
      */
-    class Effect extends Entity{
+    public function get_name(){
+        return $this->name;
+    }
 
-        private $id;
-        private $name;
-        private $is_buff;
-        private $description;
+    /**
+     * Checks if the effect is a a buff (a good effect).
+     *
+     * @return bool True if buff, false if not.
+     */
+    public function is_buff(){
+        return $this->is_buff;
+    }
 
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * skill level, populating it and it's items.
-         *
-         * @param int $id Effect identifier.
-         */
-        public function __construct($id){
+    /**
+     * Checks if the efect is a a debuff (a bad effect).
+     *
+     * @return bool True if buff, false if not.
+     */
+    public function is_debuff(){
+        return ! $this->is_buff;
+    }
 
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                name,
-                is_buff,
-                description
-              FROM effect
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->id = $r["id"];
-                $this->name = HTML::e($r["name"]);
-                $this->is_buff = $r["is_buff"];
-                $this->description = HTML::e($r["description"]);
-            }
-        }
+    /**
+     * Retrieves the effect description.
+     *
+     * @return string Effect description.
+     */
+    public function get_description(){
+        return $this->description;
+    }
 
-        /**
-         * Retrieves the effect identifier.
-         *
-         * @return int Effect ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
-    
-        /**
-         * Retrieves the effect name.
-         *
-         * @return string Effect name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
-    
-        /**
-         * Checks if the efect is a a buff
-         *
-         * @return boolean
-         */
-        public function is_buff(){
-            return $this->is_buff;
-        }
-        
-        /**
-         * Checks if the efect is a a debuff
-         *
-         * @return boolean
-         */
-        public function is_debuff(){
-            return ! $this->is_buff;
-        }
-    
-        /**
-         * Retrieves the effect description.
-         *
-         * @return string Effect description.
-         */
-        public function get_description(){
-            return $this->description;
-        }
-    
-        /**
-         * Gets the pathto the monster image. 
-         * @return string Image URL, or a fixed unknown image.
-         */
-        public function get_image(){
-            return APPLICATION::img("EFFECT", $this->id);
-        }
+    /**
+     * Gets the pathto the monster image. 
+     * @return string Image URL, or a fixed unknown image.
+     */
+    public function get_image(){
+        return APPLICATION::img("EFFECT", $this->id);
     }
-?>
+}

+ 360 - 320
application/entity/Enchantment.php

@@ -1,341 +1,381 @@
 <?php
+/**
+ * Enchantments items entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+require_once(PATH::ENTITY . "Rune_Set.php");
+
+/**
+ * Owned enchantments.
+ *
+ * Represent an enchantment, both grindstones and gems.
+ *
+ * @category Entity
+ */
+class Enchantment extends Entity{
+
     /**
-     * Enchantments items entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Owner's player ID.
+     */
+    private $player_id;
+
+    /**
+     * @var int Enchantment ID.
+     */
+    private $id;
+
+    /**
+     * @var int Quality ID ({@see QUALITY_ID}).
+     */
+    private $quality;
+
+    /**
+     * @var string Quality name.
+     */
+    private $quality_name;
+
+    /**
+     * @var int Rune set ID ({@see RUNE_SET_ID}).
+     */
+    private $rune_set;
+
+    /**
+     * @var int ID of the stat affeced by the enchantmentt ({@see RUNE_STAT_ID}).
+     */
+    private $stat;
+
+    /**
+     * @var string Name of the affected stat.
+     */
+    private $stat_name;
+
+    /**
+     * @var bool Indicates if the enchantment is a gem.
+     */
+    private $gem;
+
+    /**
+     * @var bool Indicates if the enchantment is ancient.
+     */
+    private $ancient;
+
+    /**
+     * @var bool Indicates if the enchantment is inmemorial.
+     */
+    private $inmemorial;
+
+    /**
+     * @var string Enchantment name.
+     */
+    private $name;
+
+    /**
+     * @var int Minimal effect of the enchantment.
+     */
+    private $min;
+
+    /**
+     * @var int Maximum effect of the enchantment.
      */
+    private $max;
 
     /**
-     * Require dependent entities if not present.
+     * @var int Value of the enchantment in mana stones.
      */
-    require_once(PATH::ENTITY . "Entity.php");
-    require_once(PATH::ENTITY . "Rune_Set.php");
+    private $value;
 
     /**
-     * Owned enchantments.
+     * @var int Owned amount of the same enchantment.
+     */
+    private $amount;
+
+    /**
+     * Constructor.
      *
-     * Represents an object from the table 'enchantment'.
+     * Searches the database and retrieves the information about the
+     * rune, populating it and it's items.
      *
-     * @category Entity
-     */
-    class Enchantment extends Entity{
-
-        private $player_id;
-        private $id;
-        private $quality;
-        private $quality_name;
-        private $rune_set;
-        private $stat;
-        private $stat_name;
-        private $gem;
-        private $ancient;
-        private $inmemorial;
-        private $name;
-        private $min;
-        private $max;
-        private $value;
-        private $amount;
-
-        
-    
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * rune, populating it and it's items.
-         *
-         * @param int $id Enchantment id.
-         */
-        public function __construct($id){
-
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                enchantment.player AS player,
-                enchantment.id AS id,
-                enchantment.quality As quality,
-                enchantment.rune AS rune,
-                enchantment.stat AS stat,
-                enchantment.value AS value,
-                enchantment.amount AS amount,
-                enchantment_type.name AS name,
-                enchantment_type.gem AS gem,
-                enchantment_type.inmemorial AS inmemorial,
-                enchantment_type.ancient AS ancient,
-                enchantment_range.min AS min,
-                enchantment_range.max AS max
-              FROM
-                enchantment,
-                enchantment_type,
-                enchantment_range
-              WHERE
-                enchantment.id = :id AND
-                enchantment.type = enchantment_type.id AND
-                enchantment_type.gem = enchantment_range.gem AND
-                enchantment_type.gem = enchantment_range.gem AND
-                enchantment_type.ancient = enchantment_range.ancient AND
-                enchantment.quality = enchantment_range.quality AND
-                enchantment.stat = enchantment_range.stat;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->player_id = $r["player"];
-                $this->id = $r["id"];
-                if ($r["gem"] == 0){
-                    $this->gem = false;
-                }
-                else{
-                    $this->gem = true;
-                }
-                $this->quality = $r["quality"];
-                $this->quality_name = $this->quality_name($r["quality"]);
-                $this->stat = $r["stat"];
-                $this->stat_name = $this->stat_name($r["stat"]);
-                if ($r["ancient"] == 0){
-                    $this->ancient = false;
-                }
-                else{
-                    $this->ancient = true;
-                }
-                $this->inmemorial = $r["inmemorial"];
-                if ($r["inmemorial"] == 0){
-                    $this->rune_set = new Rune_Set($r["rune"]);
-                    $this->name = $this->rune_set->get_name() . " " . $r["stat"];
-                    $this->inmemorial = false;
-                }
-                else{
-                    $this->inmemorial = true;
-                    $this->name = "Inmemorial " . $r["stat"];
-                }
-                $this->min = $r["min"];
-                $this->max = $r["max"];
-                $this->value = $r["value"];
-                $this->amount = $r["amount"];
-            }
-        }
+     * @param int $id Enchantment id.
+     */
+    public function __construct($id){
 
-        /**
-         * Gets a stat name from the maps.
-         *
-         * @param int $stat Stat id.
-         * @return string Stat name (Uppercase)
-         */
-        private function stat_name($stat){
-            switch ($stat){
-                case RUNE_STAT_ID::HP:
-                    return "HP";
-                case RUNE_STAT_ID::HP_P:
-                    return "HP%";
-                case RUNE_STAT_ID::ATK:
-                    return "ATK";
-                case RUNE_STAT_ID::ATK_P:
-                    return "ATK%";
-                case RUNE_STAT_ID::DEF:
-                    return "DEF";
-                case RUNE_STAT_ID::DEF_P:
-                    return "DEF%";
-                case RUNE_STAT_ID::SPD:
-                    return "SPD";
-                case RUNE_STAT_ID::CRR:
-                    return "CRR";
-                case RUNE_STAT_ID::CRD:
-                    return "CRD";
-                case RUNE_STAT_ID::RES:
-                    return "RES";
-                case RUNE_STAT_ID::ACC:
-                    return "ACC";
-                default:
-                    return "";
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            enchantment.player AS player,
+            enchantment.id AS id,
+            enchantment.quality As quality,
+            enchantment.rune AS rune,
+            enchantment.stat AS stat,
+            enchantment.value AS value,
+            enchantment.amount AS amount,
+            enchantment_type.name AS name,
+            enchantment_type.gem AS gem,
+            enchantment_type.inmemorial AS inmemorial,
+            enchantment_type.ancient AS ancient,
+            enchantment_range.min AS min,
+            enchantment_range.max AS max
+          FROM
+            enchantment,
+            enchantment_type,
+            enchantment_range
+          WHERE
+            enchantment.id = :id AND
+            enchantment.type = enchantment_type.id AND
+            enchantment_type.gem = enchantment_range.gem AND
+            enchantment_type.gem = enchantment_range.gem AND
+            enchantment_type.ancient = enchantment_range.ancient AND
+            enchantment.quality = enchantment_range.quality AND
+            enchantment.stat = enchantment_range.stat;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->player_id = $r["player"];
+            $this->id = $r["id"];
+            if ($r["gem"] == 0){
+                $this->gem = false;
             }
-        }
-
-        /**
-         * Gets a stat name from the maps.
-         *
-         * @param int $q Quality id.
-         * @return string Quality (Uppercase)
-         */
-        private function quality_name($q){
-            switch ($q){
-                case QUALITY_ID::NORMAL:
-                    return "NORMAL";
-                case QUALITY_ID::MAGIC:
-                    return "MAGIC";
-                case QUALITY_ID::RARE:
-                    return "RARE";
-                case QUALITY_ID::HERO:
-                    return "HERO";
-                case QUALITY_ID::LEGEND:
-                    return "LEGEND";
-                default:
-                    return "";
+            else{
+                $this->gem = true;
             }
-        }
-
-        /**
-         * Calculates name variables.
-         */
-        public function refresh_names(){
-            $this->stat_name = $this->stat_name($this->stat);
-            $this->quality_name = $this->quality_name($this->quality);
-            $this->name = $this->rune->name . " " . $this->stat;
-            if ($this->inmemorial == 0){
-                $this->name = $this->rune->name . " " . $this->stat;
+            $this->quality = $r["quality"];
+            $this->quality_name = $this->quality_name($r["quality"]);
+            $this->stat = $r["stat"];
+            $this->stat_name = $this->stat_name($r["stat"]);
+            if ($r["ancient"] == 0){
+                $this->ancient = false;
             }
             else{
-                $this->name = "Inmemorial " . $this->stat;
+                $this->ancient = true;
             }
+            $this->inmemorial = $r["inmemorial"];
+            if ($r["inmemorial"] == 0){
+                $this->rune_set = new Rune_Set($r["rune"]);
+                $this->name = $this->rune_set->get_name() . " " . $r["stat"];
+                $this->inmemorial = false;
+            }
+            else{
+                $this->inmemorial = true;
+                $this->name = "Inmemorial " . $r["stat"];
+            }
+            $this->min = $r["min"];
+            $this->max = $r["max"];
+            $this->value = $r["value"];
+            $this->amount = $r["amount"];
         }
-        
-        /**
-         * Retrieves the owner's player identifier.
-         *
-         * @return int player identifier.
-         */
-        public function get_player_id(){
-            return $this->player_id;
-        }
-        
-        /**
-         * Retrieves the enchantment identifier.
-         *
-         * @return string Enchantment ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
-        
-        /**
-         * Retrieves the quality of the enchantment.
-         *
-         * @see QUALITY_ID
-         *
-         * @return int Quality.
-         */
-        public function get_quality(){
-            return $this->quality;
-        }
-        
-        /**
-         * Retrieves the quality name of the enchantment.
-         *
-         * @return string Quality name.
-         */
-        public function get_quality_name(){
-            return $this->quality_name;
-        }
-        
-        /**
-         * Retrieves the rune set the enchantment can be used on.
-         *
-         * @return Rune_Set The set the enchantment can be used on, null for inmemorials.
-         */
-        public function get_rune_set(){
-            return $this->rune_set;
-        }
-        
-        /**
-         * Retrieves the stat affected by the enchantment.
-         *
-         * @see RUNE_STAT_ID
-         *
-         * @return int Stat ID.
-         */
-        public function get_stat(){
-            return $this->stat;
-        }
-        
-        /**
-         * Retrieves the name of the affected stat.
-         *
-         * @return string Stat name
-         */
-        public function get_stat_name(){
-            return $this->stat_name;
-        }
-        
-        /**
-         * Checks if the enchantment is a enchanted gem.
-         *
-         * @return boolean true for enchanted gems, false for grindstones.
-         */
-        public function is_gem(){
-            return $this->gem;
-        }
-        
-        /**
-         * Checks if the enchantment is a grindstone.
-         *
-         * @return boolean true for grindstones, false enchanted gems.
-         */
-        public function is_grind(){
-            return ! $this->gem;
-        }
-        
-        /**
-         * Checks if it's an ancient enchantment.
-         *
-         * @return boolean Tur if anciend, false if normal.
-         */
-        public function is_ancient(){
-            return $this->ancient;
-        }
-        
-        /**
-         * Checks if the enchantment is inmemorial.
-         *
-         * @return boolean True for inmemorial, false otherwise.
-         */
-        public function is_inmemorial(){
-            return $this->inmemorial;
-        }
-        
-        /**
-         * Retrieves the enchantment name.
-         *
-         * @return string Enchantment name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
-        
-        /**
-         * Retrieves the minumum value for the enchantment.
-         *
-         * @return int Minimum enchant outcome.
-         */
-        public function get_min(){
-            return $this->min;
-        }
-        
-        /**
-         * Retrieves the maximum value for the enchantment.
-         *
-         * @return int maximum enchant outcome.
-         */
-        public function get_max(){
-            return $this->max;
-        }
-        
-        /**
-         * Retrieves the value of the enchantment in mana stones.
-         *
-         * @return int Value of the enchantment.
-         */
-        public function get_value(){
-            return $this->value;
+    }
+
+    /**
+     * Gets a stat name from the maps.
+     *
+     * @param int $stat Stat id.
+     * @return string Stat name (Uppercase)
+     */
+    private function stat_name($stat){
+        switch ($stat){
+            case RUNE_STAT_ID::HP:
+                return "HP";
+            case RUNE_STAT_ID::HP_P:
+                return "HP%";
+            case RUNE_STAT_ID::ATK:
+                return "ATK";
+            case RUNE_STAT_ID::ATK_P:
+                return "ATK%";
+            case RUNE_STAT_ID::DEF:
+                return "DEF";
+            case RUNE_STAT_ID::DEF_P:
+                return "DEF%";
+            case RUNE_STAT_ID::SPD:
+                return "SPD";
+            case RUNE_STAT_ID::CRR:
+                return "CRR";
+            case RUNE_STAT_ID::CRD:
+                return "CRD";
+            case RUNE_STAT_ID::RES:
+                return "RES";
+            case RUNE_STAT_ID::ACC:
+                return "ACC";
+            default:
+                return "";
         }
-        
-        /**
-         * Retrieves the amount of the same enchantment owned by the user.
-         *
-         * @return int Number of the enchantments owned.
-         */
-        public function get_amount(){
-            return $this->amount;
+    }
+
+    /**
+     * Gets a stat name from the maps.
+     *
+     * @param int $q Quality id.
+     * @return string Quality (Uppercase)
+     */
+    private function quality_name($q){
+        switch ($q){
+            case QUALITY_ID::NORMAL:
+                return "NORMAL";
+            case QUALITY_ID::MAGIC:
+                return "MAGIC";
+            case QUALITY_ID::RARE:
+                return "RARE";
+            case QUALITY_ID::HERO:
+                return "HERO";
+            case QUALITY_ID::LEGEND:
+                return "LEGEND";
+            default:
+                return "";
         }
+    }
 
+    /**
+     * Retrieves the owner's player identifier.
+     *
+     * @return int player identifier.
+     */
+    public function get_player_id(){
+        return $this->player_id;
+    }
+
+    /**
+     * Retrieves the enchantment identifier.
+     *
+     * @return string Enchantment ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Retrieves the quality of the enchantment.
+     *
+     * @see QUALITY_ID
+     *
+     * @return int Quality.
+     */
+    public function get_quality(){
+        return $this->quality;
+    }
+
+    /**
+     * Retrieves the quality name of the enchantment.
+     *
+     * @return string Quality name.
+     */
+    public function get_quality_name(){
+        return $this->quality_name;
+    }
+
+    /**
+     * Retrieves the rune set the enchantment can be used on.
+     *
+     * @return Rune_Set The set the enchantment can be used on, null for inmemorials.
+     */
+    public function get_rune_set(){
+        return $this->rune_set;
+    }
+
+    /**
+     * Retrieves the stat affected by the enchantment.
+     *
+     * @see RUNE_STAT_ID
+     *
+     * @return int Stat ID.
+     */
+    public function get_stat(){
+        return $this->stat;
+    }
+
+    /**
+     * Retrieves the name of the affected stat.
+     *
+     * @return string Stat name
+     */
+    public function get_stat_name(){
+        return $this->stat_name;
+    }
+
+    /**
+     * Checks if the enchantment is a enchanted gem.
+     *
+     * @return bool true for enchanted gems, false for grindstones.
+     */
+    public function is_gem(){
+        return $this->gem;
+    }
+
+    /**
+     * Checks if the enchantment is a grindstone.
+     *
+     * @return bool true for grindstones, false enchanted gems.
+     */
+    public function is_grind(){
+        return ! $this->gem;
+    }
+
+    /**
+     * Checks if it's an ancient enchantment.
+     *
+     * @return bool True if ancient, false if normal.
+     */
+    public function is_ancient(){
+        return $this->ancient;
+    }
+
+    /**
+     * Checks if the enchantment is inmemorial.
+     *
+     * @return bool True for inmemorial, false otherwise.
+     */
+    public function is_inmemorial(){
+        return $this->inmemorial;
+    }
+
+    /**
+     * Retrieves the enchantment name.
+     *
+     * @return string Enchantment name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
+
+    /**
+     * Retrieves the minumum value for the enchantment.
+     *
+     * @return int Minimum enchant outcome.
+     */
+    public function get_min(){
+        return $this->min;
+    }
+
+    /**
+     * Retrieves the maximum value for the enchantment.
+     *
+     * @return int Maximum enchant outcome.
+     */
+    public function get_max(){
+        return $this->max;
+    }
+
+    /**
+     * Retrieves the value of the enchantment in mana stones.
+     *
+     * @return int Value of the enchantment.
+     */
+    public function get_value(){
+        return $this->value;
+    }
+
+    /**
+     * Retrieves the amount of the same enchantment owned by the user.
+     *
+     * @return int Number of the enchantments owned.
+     */
+    public function get_amount(){
+        return $this->amount;
     }
-?>
+
+}

+ 17 - 27
application/entity/Entity.php

@@ -1,30 +1,20 @@
 <?php
-    /**
-     * Base entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
-     */
+/**
+ * Base entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
 
-    /**
-     * Entity superclass.
-     *
-     * Every other entity must inherit from this one. It represents a database
-     * entity.
-     * 
-     * @abstract
-     * @category Entity
-     */
-    abstract class Entity{
-
-        /**
-         * Constructor.
-         *
-         * Empty.
-         */
-        public function __construct(){
-
-        }
-    }
+/**
+ * Entity superclass.
+ *
+ * Every other entity must inherit from this one.
+ * 
+ * @category Entity
+ */
+abstract class Entity{}
 ?>

+ 55 - 52
application/entity/Guild.php

@@ -4,80 +4,78 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Guild_Member.php");
 
 /**
  * Guild.
  *
- * Represents an object from the table 'guild'.
+ * Represents a guild in the game.
  *
  * @category Entity
  */
 class Guild extends Entity{
-    
+
     /**
-     * @var int @var int Guild identifier.
+     * @var int Guild identifier.
      */
     private $id;
-    
+
     /**
-     * @var int @var string Guild name.
+     * @var string Guild name.
      */
     private $name;
-    
+
     /**
-     * @var int @var int Guild level.
+     * @var int Guild level.
      */
     private $level;
-    
+
     /**
-     * @var int Guild total experience.
+     * Guild total experience.
      */
     private $experience;
-    
+
     /**
-     * @var bool Indicates if the guild is ecruiting.
+     * @var bool Indicates if the guild is recruiting.
      */
     private $recruiting;
-    
+
     /**
      * @var int Number of members.
      */
     private $total_members;
-    
+
     /**
      * @var Guild_Member Guild Leader.
      */
     private $leader;
-    
+
     /**
      * @var string Guild comment.
      */
     private $comment;
-    
+
     /**
      * @var string Guild notice.
      */
     private $notice;
-    
+
     /**
      * @var Guild_Member[] List of {@see Guild_Member}s.
      */
     private $members = [];
-    
-    
+
     /**
-     * @var boolean Indicates if guild members have been loaded.
+     * @var bool Internal flag that indicates if guild members have been loaded.
      */
     private $flag_members = false;
-    
+
     /**
      * Constructor.
      *
@@ -87,22 +85,22 @@ class Guild extends Entity{
      * @param int $id Guild identifier.
      */
     public function __construct($id){
-        
+
         $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                name,
-                name,
-                level,
-                experience,
-                recruiting,
-                members,
-                leader,
-                comment,
-                notice
-              FROM guild
-              WHERE id = :id;
-            ");
+          SELECT
+            id,
+            name,
+            name,
+            level,
+            experience,
+            recruiting,
+            members,
+            leader,
+            comment,
+            notice
+          FROM guild
+          WHERE id = :id;
+        ");
         $statement->bindValue(':id', $id, SQLITE3_TEXT);
         $q = $statement->execute();
         $r = $q->fetchArray(SQLITE3_ASSOC);
@@ -118,7 +116,13 @@ class Guild extends Entity{
             $this->notice = HTML::e($r["notice"]);
         }
     }
-    
+
+    /**
+     * Loads the members of the guild into the entity.
+     *
+     * Must be called only once before trying to get the members, the leader, or the member count.
+     * Sets the flag {@link Guild:$flag_members} to true.
+     */
     private function load_members(){
         $statement = get_context()->get_db()->prepare("
           SELECT
@@ -144,7 +148,7 @@ class Guild extends Entity{
         $this->total_members = count($this->members);
         $this->flag_members = true;
     }
-    
+
     /**
      * Retrieves the guild identifier.
      *
@@ -153,7 +157,7 @@ class Guild extends Entity{
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the guild name.
      *
@@ -162,7 +166,7 @@ class Guild extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the guild level.
      *
@@ -171,7 +175,7 @@ class Guild extends Entity{
     public function get_level(){
         return $this->level;
     }
-    
+
     /**
      * Retrieves the total experience earned by the guild.
      *
@@ -180,16 +184,16 @@ class Guild extends Entity{
     public function get_experience(){
         return $this->experience;
     }
-    
+
     /**
      * Checks if the guild is recruiting.
      *
-     * @return boolean True if recruiting, false if not.
+     * @return bool True if recruiting, false if not.
      */
     public function is_recruiting(){
         return $this->recruiting;
     }
-    
+
     /**
      * Retrieves the guild's public notice.
      *
@@ -198,7 +202,7 @@ class Guild extends Entity{
     public function get_comment(){
         return $this->comment;
     }
-    
+
     /**
      * Retrieves the guild's private notice.
      *
@@ -207,7 +211,7 @@ class Guild extends Entity{
     public function get_notice(){
         return $this->notice;
     }
-    
+
     /**
      * Retrieves the number of members in the guild.
      *
@@ -219,7 +223,7 @@ class Guild extends Entity{
         }
         return $this->total_members;
     }
-    
+
     /**
      * Retrieves the leader member of the guild.
      *
@@ -231,7 +235,7 @@ class Guild extends Entity{
         }
         return $this->leader;
     }
-    
+
     /**
      * Retrieves a list of members$members
      *
@@ -244,4 +248,3 @@ class Guild extends Entity{
         return $this->members;
     }
 }
-?>

+ 72 - 31
application/entity/Guild_Member.php

@@ -4,44 +4,77 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 
 /**
- * Guild.
+ * Guild member.
  *
- * Represents an object from the table 'guild'.
+ * Represents amember of a guild.
  *
  * @category Entity
  */
 class Guild_Member extends Entity{
-    
+
+    /**
+     * @var int Member's player ID.
+     */
     private $id;
+
+    /**
+     * @var int Guild ID.
+     */
     private $guild;
+
+    /**
+     * @var string Member's player name.
+     */
     private $name;
+
+    /**
+     * @var int Member's level.
+     */
     private $level;
+
+    /**
+     * @var int Member's grade in the guild ({@see GUILD_MEMBER_GRADE_ID}).
+     */
     private $grade;
+
+    /**
+     * @var int Member's rating.
+     */
     private $rating;
+
+    /**
+     * @var int Member's arena score.
+     */
     private $arena_score;
+
+    /**
+     * @var DateTime Date the member joined the guild.
+     */
     private $joined;
+
+    /**
+     * @var DateTime The time the user last loged in.
+     */
     private $last_login;
+
+    /**
+     * @var bool Indicates if the member is in the Guild Wars.
+     */
     private $in_war;
-    private $has_defense;
-    
+
     /**
-     * Checks if the member has defenses set in Guild War.
-     *
-     * @return boolean True if defenses are set, false otherwise.
+     * @var bool Indicates if the member has set up defenses in the Guild War.
      */
-    public function has_defense(){
-        return $this->has_defense;
-    }
-    
+    private $has_defense;
+
     /**
      * Constructor.
      *
@@ -51,7 +84,7 @@ class Guild_Member extends Entity{
      * @param int $id Guild identifier.
      */
     public function __construct($id){
-        
+
         $statement = get_context()->get_db()->prepare("
               SELECT
                 member,
@@ -96,7 +129,7 @@ class Guild_Member extends Entity{
             }
         }
     }
-    
+
     /**
      * Retrieves the player identifier of the member.
      *
@@ -105,7 +138,7 @@ class Guild_Member extends Entity{
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the guild identifier.
      *
@@ -114,7 +147,7 @@ class Guild_Member extends Entity{
     public function get_guild_id(){
         return $this->guild;
     }
-    
+
     /**
      * Retrieves the member name.
      *
@@ -123,7 +156,7 @@ class Guild_Member extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the member's level.
      *
@@ -132,7 +165,7 @@ class Guild_Member extends Entity{
     public function get_level(){
         return $this->level;
     }
-    
+
     /**
      * Retrieves the grade of the member in the guild.
      *
@@ -141,7 +174,7 @@ class Guild_Member extends Entity{
     public function get_grade(){
         return $this->grade;
     }
-    
+
     /**
      * Retrieves the member's rating.
      *
@@ -150,7 +183,7 @@ class Guild_Member extends Entity{
     public function get_rating(){
         return $this->rating;
     }
-    
+
     /**
      * Retrieves the member's arena score.
      *
@@ -159,7 +192,7 @@ class Guild_Member extends Entity{
     public function get_arena_score(){
         return $this->arena_score;
     }
-    
+
     /**
      * Retrieves $joined
      *
@@ -168,7 +201,7 @@ class Guild_Member extends Entity{
     public function get_joined(){
         return $this->joined;
     }
-    
+
     /**
      * Gets the date the member joined the guild.
      *
@@ -186,7 +219,7 @@ class Guild_Member extends Entity{
             return $this->joined->format($format);
         }
     }
-    
+
     /**
      * Gets the time the member las logged in.
      *
@@ -204,15 +237,23 @@ class Guild_Member extends Entity{
             return $this->last_login->format($format);
         }
     }
-    
+
     /**
      * Checks if the member is inscribed in Guild Wars.
      *
-     * @return boolean Tue if inscribed, false otherwise.
+     * @return bool True if inscribed, false otherwise.
      */
     public function is_in_war(){
         return $this->in_war;
     }
-    
+
+    /**
+     * Checks if the member has defenses set in Guild War.
+     *
+     * @return bool True if defenses are set, false otherwise.
+     */
+    public function has_defense(){
+        return $this->has_defense;
+    }
+
 }
-?>

+ 92 - 79
application/entity/Guild_Skill.php

@@ -1,95 +1,108 @@
 <?php
+/**
+ * Guild skill entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Guild skill.
+ *
+ * Represents one of the guild skills aquired by leveling the guild up.
+ *
+ * @category Entity
+ */
+class Guild_Skill extends Entity{
+
     /**
-     * Guild skill entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Skill ID.
+     */
+    private $id;
+
+    /**
+     * @var int Skill group ID.
+     */
+    private $group;
+
+    /**
+     * @var int Reached skil level.
      */
+    private $level;
 
     /**
-     * Require dependent entities if not present.
+     * @var string Skill bonus, human readable.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $effect;
 
     /**
-     * Guild skill.
+     * Constructor.
      *
-     * Represents an object from the table 'guild_skill'.
+     * Searches the database and retrieves the information about the
+     * skill, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Skill identifier.
      */
-    class Guild_Skill extends Entity{
+    public function __construct($id){
 
-        private $id;
-        private $group;
-        private $level;
-        private $effect;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            skill_group,
+            level,
+            effect
+          FROM key.guild_skill
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->group = $r["skill_group"];
+            $this->level = $r["level"];
+            $this->effect = HTML::e($r["effect"]);
+        }
+    }
 
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * skill, populating it and it's items.
-         *
-         * @param int $id Skill identifier.
-         */
-        public function __construct($id){
+    /**
+     * Retrieves the guild skill identifier.
+     *
+     * @return int Skill ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
 
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                skill_group,
-                level,
-                effect
-              FROM key.guild_skill
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->id = $r["id"];
-                $this->group = $r["skill_group"];
-                $this->level = $r["level"];
-                $this->effect = HTML::e($r["effect"]);
-            }
-        }
-        
-        /**
-         * Retrieves the guild skill identifier.
-         *
-         * @return int Skill ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
-        
-        /**
-         * Retrieves the skill group identifier.
-         *
-         * @return int Group ID.
-         */
-        public function get_group(){
-            return $this->group;
-        }
-        
-        /**
-         * Retrieves the skill level.
-         *
-         * @return int Skill level.
-         */
-        public function get_level(){
-            return $this->level;
-        }
-        
-        /**
-         * Retrieves the skill efect description.
-         *
-         * @return string Skill description.
-         */
-        public function get_effect(){
-            return $this->effect;
-        }
+    /**
+     * Retrieves the skill group identifier.
+     *
+     * @return int Group ID.
+     */
+    public function get_group(){
+        return $this->group;
+    }
 
+    /**
+     * Retrieves the skill level.
+     *
+     * @return int Skill level.
+     */
+    public function get_level(){
+        return $this->level;
+    }
+
+    /**
+     * Retrieves the skill efect description.
+     *
+     * @return string Skill description.
+     */
+    public function get_effect(){
+        return $this->effect;
     }
-?>
+
+}

+ 127 - 106
application/entity/Guild_Skill_Group.php

@@ -1,123 +1,144 @@
 <?php
+/**
+ * Guild skill group entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+require_once(PATH::ENTITY . "Guild_Skill.php");
+
+/**
+ * Guild skill group.
+ *
+ * Represents a category of guild skills.
+ *
+ * @category Entity
+ */
+class Guild_Skill_Group extends Entity{
+
     /**
-     * Guild skill group entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Group ID.
+     */
+    private $id;
+
+    /**
+     * @var string Group name.
+     */
+    private $name;
+
+    /**
+     * @var string Group description.
+     */
+    private $description;
+
+    /**
+     * @var bool Internal flag to check if the group skills have been loaded into the entity.
      */
+    private $flag_skills = false;
 
     /**
-     * Require dependent entities if not present.
+     * @var Guild_Skill[] Skills in the group.
      */
-    require_once(PATH::ENTITY . "Entity.php");
-    require_once(PATH::ENTITY . "Guild_Skill.php");
+    private $skills = [];
 
     /**
-     * Guild skill group.
+     * Constructor.
      *
-     * Represents an object from the table 'guild_skill_group'.
+     * Searches the database and retrieves the information about the
+     * skill group, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Skill group identifier.
      */
-    class Guild_Skill_Group extends Entity{
-
-        private $id;
-        private $name;
-        private $description;
-        private $flag_skills = false;
-        private $skills = [];
-
-        /**
-         * Retrieves the identifier of the skill group.
-         *
-         * @return int Group ID
-         */
-        public function get_id(){
-            return $this->id;
-        }
-    
-        /**
-         * Retrieves the name of the skill_group.
-         *
-         * @return string Group name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
-    
-        /**
-         * Retrieves the description of the skill group.
-         *
-         * @return string Group description.
-         */
-        public function get_description(){
-            return $this->description;
-        }
-    
-        /**
-         * Retrieves the skills in the group.
-         *
-         * @return Guild_Skill[] Skills in the group.
-         */
-        public function get_skills(){
-            if (! $this->flag_skills){
-                $this->load_skills();
-            }
-            return $this->skills;
-        }
-    
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * skill group, populating it and it's items.
-         *
-         * @param int $id Skill group identifier.
-         */
-        public function __construct($id){
-
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                name,
-                description
-              FROM guild_skill_group
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->id = $r["id"];
-                $this->name = HTML::e($r["name"]);
-                $this->description = HTML::e($r["description"]);
-            }
+    public function __construct($id){
+
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            name,
+            description
+          FROM guild_skill_group
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->name = HTML::e($r["name"]);
+            $this->description = HTML::e($r["description"]);
         }
-        
-        private function load_skills(){
-            $statement = get_context()->get_db()->prepare("
-              SELECT id
-              FROM guild_skill
-              WHERE skill_group = :id;
-            ");
-            $statement->bindValue(':id', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->skills, new Guild_Skill($r["id"]));
-            }
-            $this->flag_skills = true;
+    }
+
+    /**
+     * Loads the skills in the group.
+     *
+     * Must be called only once before trying to get the skills. Sets the flag
+     * {@link Guild_Skill_Group:$flag_skills} to true.
+     */
+    private function load_skills(){
+        $statement = get_context()->get_db()->prepare("
+          SELECT id
+          FROM guild_skill
+          WHERE skill_group = :id;
+        ");
+        $statement->bindValue(':id', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->skills, new Guild_Skill($r["id"]));
         }
+        $this->flag_skills = true;
+    }
+
+    /**
+     * Retrieves the identifier of the skill group.
+     *
+     * @return int Group ID
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Retrieves the name of the skill_group.
+     *
+     * @return string Group name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
+
+    /**
+     * Retrieves the description of the skill group.
+     *
+     * @return string Group description.
+     */
+    public function get_description(){
+        return $this->description;
+    }
 
-        /**
-         * Gets the pathto the monster image. The image must be in the
-         * img/skill_guild/ directory, and its name must be the monster id,
-         * padded with '0' to 1 digits, and the extension must be '.png'.
-         *
-         * @return string Image URL, or a fixed unknown image.
-         */
-        public function get_image(){
-            return APPLICATION::img("SKILL_GUILD", $this->id);
+    /**
+     * Retrieves the skills in the group.
+     *
+     * @return Guild_Skill[] Skills in the group.
+     */
+    public function get_skills(){
+        if (! $this->flag_skills){
+            $this->load_skills();
         }
+        return $this->skills;
+    }
 
+    /**
+     * Gets the pathto the skill group image.
+     *
+     * @return string Image URL, or a fixed unknown image.
+     */
+    public function get_image(){
+        return APPLICATION::img("SKILL_GUILD", $this->id);
     }
-?>
+
+}

+ 16 - 18
application/entity/Inventory.php

@@ -4,43 +4,42 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 
 /**
- * An in -game existing item.
+ * An in-game existing item.
  *
- * Represents an object from the table 'inventory'.
+ * Represents an object that exist in the game.
  *
  * @category Entity
  */
 class Inventory extends Entity{
-    
+
     /**
      * @var int Item identifier.
      */
     private $id;
-    
+
     /**
      * @var string Item name.
      */
     private $name;
-    
+
     /**
-     * @var string Item type name.
+     * @var string Item type.
      */
     private $type;
-    
+
     /**
      * @var string Item description.
      */
     private $description;
-    
+
     /**
      * Constructor.
      *
@@ -78,7 +77,7 @@ class Inventory extends Entity{
             $this->description = HTML::e($r["description"]);
         }
     }
-    
+
     /**
      * Retrieves the owned item identifier.
      *
@@ -87,7 +86,7 @@ class Inventory extends Entity{
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the item name.
      *
@@ -96,7 +95,7 @@ class Inventory extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the item type.
      *
@@ -105,7 +104,7 @@ class Inventory extends Entity{
     public function get_type(){
         return $this->type;
     }
-    
+
     /**
      * Retrieves the item description.
      *
@@ -114,7 +113,7 @@ class Inventory extends Entity{
     public function get_description(){
         return $this->description;
     }
-    
+
     /**
      * Gets the path to the item image. 
      *
@@ -124,4 +123,3 @@ class Inventory extends Entity{
         return APPLICATION::img("INVENTORY", $this->id);
     }
 }
-?>

+ 21 - 23
application/entity/Item.php

@@ -4,54 +4,53 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Monster.php");
 
 /**
  * An item in the players inventory inventory item.
  *
- * Represents an object from the table 'item'.
+ * Represents an object owned by the player in any amount.
  *
  * @category Entity
  */
 class Item extends Entity{
-    
+
     /**
      * @var string Owner's player identifier.
      */
     private $player;
-    
+
     /**
      * @var int|Monster Item identifier. If its a monster piece, a Monster entity.
      */
     private $id;
-    
+
     /**
      * @var string Item name.
      */
     private $name;
-    
+
     /**
      * @var string Item type name.
      */
     private $type;
-    
+
     /**
      * @var int Item owned amount.
      */
     private $amount;
-    
+
     /**
      * @var bool Indicates if the item are monster pieces.
      */
     private $is_monster_pieces;
-    
+
     /**
      * Constructor.
      *
@@ -63,7 +62,7 @@ class Item extends Entity{
      * @param int $type Item type identifier. Optional, will try to guess if null.
      */
     public function __construct($player, $id, $type = null){
-        
+
         $s = "
           SELECT
             item.player AS player,
@@ -112,7 +111,7 @@ class Item extends Entity{
             }
         }
     }
-    
+
     /**
      * Retrieves the owner's player identifier
      *
@@ -121,17 +120,17 @@ class Item extends Entity{
     public function get_player(){
         return $this->player;
     }
-    
+
     /**
      * Retrieves the item identifier.
      * If the item is a monster piece, the unit instance will be returned instead
      *
-     * @return int|Monster Item ID or monster instance
+         * @return int|Monster Item ID or monster instance
      */
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the item name.
      *
@@ -140,7 +139,7 @@ class Item extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the item type.
      *
@@ -149,7 +148,7 @@ class Item extends Entity{
     public function get_type(){
         return $this->type;
     }
-    
+
     /**
      * Retrieves the owned amount of the item.
      *
@@ -158,16 +157,16 @@ class Item extends Entity{
     public function get_amount(){
         return $this->amount;
     }
-    
+
     /**
      * Checks if the item is a monste piece.
      *
-     * @return boolean True for monster pieces, false otherwise.
+     * @return bool True for monster pieces, false otherwise.
      */
     public function is_monster_pieces(){
         return $this->is_monster_pieces;
     }
-    
+
     /**
      * Gets the path to the item image. 
      *
@@ -177,4 +176,3 @@ class Item extends Entity{
         return APPLICATION::img("INVENTORY", $this->id);
     }
 }
-?>

+ 29 - 31
application/entity/Leader_Skill.php

@@ -4,50 +4,52 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 
 /**
  * Monster leader skill.
  *
- * Represents an object from the table 'leader_skill'.
+ * Represents a leader skill
  *
  * @category Entity
  */
 class Leader_Skill extends Entity{
-    
+
     /**
      * @var int Leader skill identifier.
      */
     private $id;
-    
+
     /**
      * @var int ID of the stat augmented by the leader skill.
      */
     private $stat;
-    
+
     /**
      * @var int Amount the stat is increased by.
      */
     private $amount;
-    
+
     /**
      * @var int Effect area id (if any).
      */
     private $area;
-    
+
     /**
      * @var int Affected element id (if any).
      */
     private $element;
-    
+
+    /**
+     * @var string Human readable description of the skill.
+     */
     private $description;
-    
+
     /**
      * Constructor.
      *
@@ -57,7 +59,7 @@ class Leader_Skill extends Entity{
      * @param int $id Skill identifier.
      */
     public function __construct($id){
-        
+
         $statement = get_context()->get_db()->prepare("
               SELECT
                 id,
@@ -79,7 +81,7 @@ class Leader_Skill extends Entity{
             $this->description = $this->create_description();
         }
     }
-    
+
     /**
      * Retrieves the leader skill identifier.
      *
@@ -88,43 +90,43 @@ class Leader_Skill extends Entity{
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves $stat
      *
-     * @return number
+         * @return int
      */
     public function get_stat(){
         return $this->stat;
     }
-    
+
     /**
      * Retrieves $amount
      *
-     * @return number
+         * @return int
      */
     public function get_amount(){
         return $this->amount;
     }
-    
+
     /**
      * Retrieves $area
      *
-     * @return number
+         * @return int
      */
     public function get_area(){
         return $this->area;
     }
-    
+
     /**
      * Retrieves $element
      *
-     * @return number
+         * @return int
      */
     public function get_element(){
         return $this->element;
     }
-    
+
     /**
      * Retrieves the skill description.
      *
@@ -133,18 +135,15 @@ class Leader_Skill extends Entity{
     public function get_description(){
         return $this->description;
     }
-    
+
     /**
-     * Gets the path to the skill image. The image must be in the
-     * img/skill_leader/ directory, and its name must be the skill id,
-     * padded with '0' to 4 digites, and the extension must be '.png'.
-     *
+     * Gets the path to the skill image. 
      * @return string Image URL, or a fixed unknown image.
      */
     public function get_image(){
         return APPLICATION::img("SKILL_LEADER", $this->id);
     }
-    
+
     /**
      * Composes a human readable description of the skill.
      *
@@ -211,6 +210,5 @@ class Leader_Skill extends Entity{
         $s = str_replace("  ", " ", $s) . ".";
         return $s;
     }
-    
+
 }
-?>

+ 761 - 612
application/entity/Monster.php

@@ -1,640 +1,789 @@
 <?php
+/**
+ * Base monster entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+require_once(PATH::ENTITY . "Skill.php");
+require_once(PATH::ENTITY . "Leader_Skill.php");
+require_once(PATH::ENTITY . "Source.php");
+require_once(PATH::ENTITY . "Inventory.php");
+require_once(PATH::ENTITY . "Monster_Transformation.php");
+
+/**
+ * A monster.
+ *
+ * Represents an object from the table 'monster'.
+ *
+ * @category Entity
+ */
+class Monster extends Entity{
+
+    /**
+     * @var int Monster ID
+     */
+    private $id;
+
+    /**
+     * @var int Monster family ID.
+     */
+    private $family;
+
+    /**
+     * @var string Monster name.
+     */
+    private $name;
+
+    /**
+     * @var int Monster element ID ({@see ELEMENT_ID}).
+     */
+    private $element;
+
+    /**
+     * @var string Monster element name.
+     */
+    private $element_name;
+
+    /**
+     * @var int Monster archetype ID ({@see ARCHETYPE_ID}).
+     */
+    private $archetype;
+
+    /**
+     * @var string Monster archetype name.
+     */
+    private $archetype_name;
+
+    /**
+     * @var int Stars of the monster in it's current form (1-6)
+     */
+    private $base_stars;
+
+    /**
+     * @var int Stars of the monster in it's base form (1-5).
+     */
+    private $natural_stars;
+
+    /**
+     * @var bool Indicates if the monster is obtainable.
+     */
+    private $obtainable;
+
+    /**
+     * @var bool Indicates if the monster can awaken.
+     */
+    private $can_awaken;
+
+    /**
+     * @var string The bonus the monster obtains when awakening.
+     */
+    private $awaken_bonus;
+
     /**
-     * Base monster 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 . "Skill.php");
-    require_once(PATH::ENTITY . "Leader_Skill.php");
-    require_once(PATH::ENTITY . "Source.php");
-    require_once(PATH::ENTITY . "Inventory.php");
-    require_once(PATH::ENTITY . "Monster_Transformation.php");
-
-    /**
-     * A monster.
-     *
-     * Represents an object from the table 'monster'.
-     *
-     * @category Entity
-     */
-    class Monster extends Entity{
-
-        private $id;
-        private $family;
-        private $name;
-        private $element;
-        private $element_name;
-        private $archetype;
-        private $archetype_name;
-        private $base_stars;
-        private $natural_stars;
-        private $obtainable;
-        private $can_awaken;
-        private $awaken_bonus;
-        private $skill_ups_to_max;
-        private $stats = array(
-            "hp"  => 0,
-            "atk" => 0,
-            "def" => 0,
-            "spd" => 0,
-            "crr" => 0,
-            "crd" => 0,
-            "acc" => 0,
-            "res" => 0,
-        );
-        private $raw_stats = array(
-            "hp"  => 0,
-            "atk" => 0,
-            "def" => 0,
-            "spd" => 0,
-            "crr" => 0,
-            "crd" => 0,
-            "acc" => 0,
-            "res" => 0,
-        );
-        private $max_level_statss = array(
-            "hp"  => 0,
-            "atk" => 0,
-            "def" => 0,
-            "spd" => 0,
-            "crr" => 0,
-            "crd" => 0,
-            "acc" => 0,
-            "res" => 0,
-        );
-        private $awakens_from;
-        private $awakens_to;
-        private $fusion_food;
-        private $homunculus;
-        private $craft_cost;
-        private $flag_skills = false;
-        private $leader_skill;
-        private $leader_skill_id;
-        private $skill = [];
-        private $flag_essences = false;
-        private $essences = [];
-        private $flag_sources = false;
-        private $sources = [];
-        private $title;
-        private $flag_transformation = false;
-        private $transformation;
-
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * monster, populating it and it's items.
-         *
-         * @param int $id Monster identifier.
-         */
-        public function __construct($id){
-            $this->id = $id;
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                family,
-                name,
-                element,
-                archetype,
-                base_stars,
-                natural_stars,
-                obtainable,
-                can_awaken,
-                awaken_bonus,
-                skill_ups_to_max,
-                leader_skill,
-                hp,
-                attack,
-                defense,
-                speed,
-                crit_rate,
-                crit_damage,
-                resistance,
-                accuracy,
-                raw_hp,
-                raw_attack,
-                raw_defense,
-                max_lvl_hp,
-                max_lvl_attack,
-                max_lvl_defense,
-                awakens_from,
-                awakens_to,
-                fusion_food,
-                homunculus,
-                craft_cost
-              FROM monster
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->family = $r["family"];
-                $this->name = HTML::e($r["name"]);
-                $this->element = $r["element"];
-                switch($this->element){
-                    case ELEMENT_ID::WATER:
-                        $this->element_name = "Water";
-                        break;
-                    case ELEMENT_ID::FIRE:
-                        $this->element_name = "Fire";
-                        break;
-                    case ELEMENT_ID::WIND:
-                        $this->element_name = "Wind";
-                        break;
-                    case ELEMENT_ID::LIGHT:
-                        $this->element_name = "Light";
-                        break;
-                    case ELEMENT_ID::DARK:
-                        $this->element_name = "Dark";
-                        break;
-                }
-                $this->archetype = $r["archetype"];
-                switch($this->archetype){
-                    case ARCHETYPE_ID::ATTACK:
-                        $this->archetype_name = "Attack";
-                        break;
-                    case ARCHETYPE_ID::DEFENSE:
-                        $this->archetype_name = "Defense";
-                        break;
-                    case ARCHETYPE_ID::HP:
-                        $this->archetype_name = "HP";
-                        break;
-                    case ARCHETYPE_ID::SUPPORT:
-                        $this->archetype_name = "Support";
-                        break;
-                    case ARCHETYPE_ID::MATERIAL:
-                        $this->archetype_name = "Material";
-                        break;
-                }
-                $this->base_stars = $r["base_stars"];
-                $this->natural_stars = $r["natural_stars"];
-                $this->obtainable = $r["obtainable"];
-                if ($r["can_awaken"] == 1){
-                    $this->can_awaken = true;
-                }
-                else{
-                    $this->can_awaken = false;
-                }
-                $this->awaken_bonus = HTML::e($r["awaken_bonus"]);
-                $this->skill_ups_to_max = $r["skill_ups_to_max"];
-                if (strlen($r["leader_skill"]) > 0){
-                    $this->leader_skill_id = $r["leader_skill"];
-                }
-                $this->stats["hp"]  = $r["hp"];
-                $this->stats["atk"] = $r["attack"];
-                $this->stats["def"] = $r["defense"];
-                $this->stats["spd"] = $r["speed"];
-                $this->stats["crr"] = $r["crit_rate"];
-                $this->stats["crd"] = $r["crit_damage"];
-                $this->stats["res"] = $r["resistance"];
-                $this->stats["acc"] = $r["accuracy"];
-                $this->min_stats["hp"]  = $r["raw_hp"];
-                $this->min_stats["atk"] = $r["raw_attack"];
-                $this->min_stats["def"] = $r["raw_defense"];
-                $this->min_stats["spd"] = $r["speed"];
-                $this->min_stats["crr"] = $r["crit_rate"];
-                $this->min_stats["crd"] = $r["crit_damage"];
-                $this->min_stats["res"] = $r["resistance"];
-                $this->min_stats["acc"] = $r["accuracy"];
-                $this->max_stats["hp"]  = $r["max_lvl_hp"];
-                $this->max_stats["atk"] = $r["max_lvl_attack"];
-                $this->max_stats["def"] = $r["max_lvl_defense"];
-                $this->max_stats["spd"] = $r["speed"];
-                $this->max_stats["crr"] = $r["crit_rate"];
-                $this->max_stats["crd"] = $r["crit_damage"];
-                $this->max_stats["res"] = $r["resistance"];
-                $this->max_stats["acc"] = $r["accuracy"];
-
-                $this->awakens_from = $r["awakens_from"];
-                $this->awakens_to = $r["awakens_to"];
-                if ($r["fusion_food"] == 1){
-                    $this->fusion_food = true;
-                }
-                else{
-                    $this->fusion_food = false;
-                }
-                if ($r["homunculus"] == 1){
-                    $this->homunculus = true;
-                }
-                else{
-                    $this->homunculus = false;
-                }
-                $this->craft_cost = $r["craft_cost"];
+     * @var int Total skill ups to ma all skills.
+     */
+    private $skill_ups_to_max;
+
+    /**
+     * @var int[] Stats of the monster in it's base grade at max level.
+     */
+    private $stats = array(
+        "hp"  => 0,
+        "atk" => 0,
+        "def" => 0,
+        "spd" => 0,
+        "crr" => 0,
+        "crd" => 0,
+        "acc" => 0,
+        "res" => 0,
+    );
+
+    /**
+     * @var int[] Stats of the monster in it's base grade at level 1.
+     */
+    private $min_stats = array(
+        "hp"  => 0,
+        "atk" => 0,
+        "def" => 0,
+        "spd" => 0,
+        "crr" => 0,
+        "crd" => 0,
+        "acc" => 0,
+        "res" => 0,
+    );
+
+    /**
+     * @var int[] Stats of the monster at 6 stars and max level.
+     */
+    private $max_stats = array(
+        "hp"  => 0,
+        "atk" => 0,
+        "def" => 0,
+        "spd" => 0,
+        "crr" => 0,
+        "crd" => 0,
+        "acc" => 0,
+        "res" => 0,
+    );
+
+    /**
+     * @var int ID of the monster this awakens from.
+     */
+    private $awakens_from;
+
+    /**
+     * @var int ID of the monster this awakens to.
+     */
+    private $awakens_to;
+
+    /**
+     * @var bool Indicates if the monster can be skilled up with fusion monsters.
+     */
+    private $fusion_food;
+
+    /**
+     * @var bool Indicates if the monster is an Homunculus.
+     */
+    private $homunculus;
+
+    /**
+     * @var mixed[] Crafting cost
+     * @todo Unimplemented, do not use.
+     */
+    private $craft_cost;
+
+    /**
+     * @var bool internal flag to check if the monster skills, including the leader skill, have
+     * been loaded into the entity.
+     */
+    private $flag_skills = false;
+
+    /**
+     * @var Leader_Skill Monster's leader skill.
+     */
+    private $leader_skill;
+
+    /**
+     * @var int Leader skill ID.
+     */
+    private $leader_skill_id;
+
+    /**
+     * @var Skill[] Monster skills.
+     */
+    private $skill = [];
+
+    /**
+     * @var bool Internal flag to check if the essences have been loaded into the entity.
+     */
+    private $flag_essences = false;
+
+    /**
+     * @var mixed[] Essences required to awaken the monster.
+     */
+    private $essences = [];
+
+    /**
+     * @var bool Internal flag to check if the monster sources have been loaded.
+     */
+    private $flag_sources = false;
+
+    /**
+     * @var Source[] List of sources the monster can be obtained from.
+     */
+    private $sources = [];
+
+    /**
+     * @var string Monster title.
+     */
+    private $title;
+
+    /**
+     * @var bool Internal flag to check if the monsters transformation have been checked.
+     */
+    private $flag_transformation = false;
+
+    /**
+     * @var Monster_Transformation The monster this one can transform into in battle.
+     */
+    private $transformation;
+
+    /**
+     * Constructor.
+     *
+     * Searches the database and retrieves the information about the
+     * monster, populating it and it's items.
+     *
+     * @param int $id Monster identifier.
+     */
+    public function __construct($id){
+        $this->id = $id;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            family,
+            name,
+            element,
+            archetype,
+            base_stars,
+            natural_stars,
+            obtainable,
+            can_awaken,
+            awaken_bonus,
+            skill_ups_to_max,
+            leader_skill,
+            hp,
+            attack,
+            defense,
+            speed,
+            crit_rate,
+            crit_damage,
+            resistance,
+            accuracy,
+            raw_hp,
+            raw_attack,
+            raw_defense,
+            max_lvl_hp,
+            max_lvl_attack,
+            max_lvl_defense,
+            awakens_from,
+            awakens_to,
+            fusion_food,
+            homunculus,
+            craft_cost
+          FROM monster
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->family = $r["family"];
+            $this->name = HTML::e($r["name"]);
+            $this->element = $r["element"];
+            switch($this->element){
+                case ELEMENT_ID::WATER:
+                    $this->element_name = "Water";
+                    break;
+                case ELEMENT_ID::FIRE:
+                    $this->element_name = "Fire";
+                    break;
+                case ELEMENT_ID::WIND:
+                    $this->element_name = "Wind";
+                    break;
+                case ELEMENT_ID::LIGHT:
+                    $this->element_name = "Light";
+                    break;
+                case ELEMENT_ID::DARK:
+                    $this->element_name = "Dark";
+                    break;
             }
-            
-            // Guess monster name
-            if ($this->awakens_from == "" && $this->awakens_to == ""){
-                // No to, no from. Silver monster.
-                if ($this->base_stars >= 4){
-                    // SFV Collab event monsters, always awakened.
-                    $this->title = $this->name;
-                }
-                elseif($this->archetype == ARCHETYPE_ID::MATERIAL && $this->element == ELEMENT_ID::LIGHT){
-                    // Rainbowmon, always awakened
-                    $this->title = $this->name;
-                }
-                elseif($this->archetype == ARCHETYPE_ID::MATERIAL && $this->element == ELEMENT_ID::DARK){
-                    // Devilmon, always unawakened, but dont include element
-                    $this->title = $this->name;
-                }
-                else{
-                    // Unawakeable monster
-                    $this->title = $this->element_name . " " . $this->name;
-                }
+            $this->archetype = $r["archetype"];
+            switch($this->archetype){
+                case ARCHETYPE_ID::ATTACK:
+                    $this->archetype_name = "Attack";
+                    break;
+                case ARCHETYPE_ID::DEFENSE:
+                    $this->archetype_name = "Defense";
+                    break;
+                case ARCHETYPE_ID::HP:
+                    $this->archetype_name = "HP";
+                    break;
+                case ARCHETYPE_ID::SUPPORT:
+                    $this->archetype_name = "Support";
+                    break;
+                case ARCHETYPE_ID::MATERIAL:
+                    $this->archetype_name = "Material";
+                    break;
             }
-            // Awakened
-            elseif ($this->awakens_from != ""){
-                $this->title = $this->name;
+            $this->base_stars = $r["base_stars"];
+            $this->natural_stars = $r["natural_stars"];
+            $this->obtainable = $r["obtainable"];
+            if ($r["can_awaken"] == 1){
+                $this->can_awaken = true;
             }
-            // Gold
-            elseif (strlen($this->awakens_to) > 0){
-                $this->title = $this->element_name . " " . $this->name;
+            else{
+                $this->can_awaken = false;
             }
-        }
-        
-        private function load_skills(){
-            $statement = get_context()->get_db()->prepare("
-              SELECT skill.id AS skill
-              FROM
-                skill,
-                monster_skill
-              WHERE
-                skill.id = monster_skill.skill AND
-                monster_skill.monster = :monster
-              ORDER BY slot;
-            ");
-            $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->skill, new Skill($r["skill"]));
+            $this->awaken_bonus = HTML::e($r["awaken_bonus"]);
+            $this->skill_ups_to_max = $r["skill_ups_to_max"];
+            if (strlen($r["leader_skill"]) > 0){
+                $this->leader_skill_id = $r["leader_skill"];
             }
-            if ($this->leader_skill_id != null){
-                $this->leader_skill = new Leader_Skill($this->leader_skill_id);
+            $this->stats["hp"]  = $r["hp"];
+            $this->stats["atk"] = $r["attack"];
+            $this->stats["def"] = $r["defense"];
+            $this->stats["spd"] = $r["speed"];
+            $this->stats["crr"] = $r["crit_rate"];
+            $this->stats["crd"] = $r["crit_damage"];
+            $this->stats["res"] = $r["resistance"];
+            $this->stats["acc"] = $r["accuracy"];
+            $this->min_stats["hp"]  = $r["raw_hp"];
+            $this->min_stats["atk"] = $r["raw_attack"];
+            $this->min_stats["def"] = $r["raw_defense"];
+            $this->min_stats["spd"] = $r["speed"];
+            $this->min_stats["crr"] = $r["crit_rate"];
+            $this->min_stats["crd"] = $r["crit_damage"];
+            $this->min_stats["res"] = $r["resistance"];
+            $this->min_stats["acc"] = $r["accuracy"];
+            $this->max_stats["hp"]  = $r["max_lvl_hp"];
+            $this->max_stats["atk"] = $r["max_lvl_attack"];
+            $this->max_stats["def"] = $r["max_lvl_defense"];
+            $this->max_stats["spd"] = $r["speed"];
+            $this->max_stats["crr"] = $r["crit_rate"];
+            $this->max_stats["crd"] = $r["crit_damage"];
+            $this->max_stats["res"] = $r["resistance"];
+            $this->max_stats["acc"] = $r["accuracy"];
+
+            $this->awakens_from = $r["awakens_from"];
+            $this->awakens_to = $r["awakens_to"];
+            if ($r["fusion_food"] == 1){
+                $this->fusion_food = true;
             }
-            $this->flag_skills = true;
-        }
-        
-        private function load_sources(){
-            $statement = get_context()->get_db()->prepare("
-              SELECT source
-              FROM monster_source
-              WHERE monster = :monster;
-            ");
-            $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->sources, new Source($r["source"]));
+            else{
+                $this->fusion_food = false;
             }
-            $this->flag_sources = true;
-        }
-        
-        private function load_essences(){
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                item,
-                amount
-              FROM monster_essence
-              WHERE
-                monster = :monster
-              ORDER BY item;
-            ");
-            $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $e = [
-                    "item" => new Inventory($r["item"], INVENTORY_TYPE_ID::ESSENCES),
-                    "amount" => $r["amount"]
-                ];
-                array_push($this->essences, $e);
+            if ($r["homunculus"] == 1){
+                $this->homunculus = true;
             }
-            $this->flag_essences = true;
-        }
-        
-        private function load_transformation(){
-            $statement = get_context()->get_db()->prepare("
-              SELECT id
-              FROM monster_transformation
-              WHERE monster = :monster;
-            ");
-            $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->transformation = new Monster_Transformation($r["id"]);
+            else{
+                $this->homunculus = false;
             }
-            $this->flag_transformation = true;
-        }
-        
-        /**
-         * Retrieves the monster identifier.
-         *
-         * @return string Monster ID
-         */
-        public function get_id(){
-            return $this->id;
-        }
-    
-        /**
-         * Retrieves the monsters family identifier.
-         *
-         * @return string Family ID.
-         */
-        public function get_family(){
-            return $this->family;
-        }
-    
-        /**
-         * Retrieves the monster name.
-         *
-         * @return string Monster name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
-    
-        /**
-         * Retrieves the monster's element.
-         * 
-         * @see ELEMENT_ID
-         *
-         * @return int Element ID.
-         */
-        public function get_element(){
-            return $this->element;
-        }
-    
-        /**
-         * Retrieves the monster's element name.
-         *
-         * @return string Element name.
-         */
-        public function get_element_name(){
-            return $this->element_name;
-        }
-    
-        /**
-         * Retrieves the monster's archetype.
-         * 
-         * @see ARCHETYPE_ID
-         *
-         * @return int Monster's archetype ID.
-         */
-        public function get_archetype(){
-            return $this->archetype;
+            $this->craft_cost = $r["craft_cost"];
         }
-    
-        /**
-         * Retrieves the monster's archetype name.
-         *
-         * @return string Archetype name.
-         */
-        public function get_archetype_name(){
-            return $this->archetype_name;
-        }
-    
-        /**
-         * Retrieves the monster's base stars.
-         * Base stars are the default stars of the monsters in it's current form. I.E awakened
-         * monsters have always one more base stars than their unawakened forms, and second awaken
-         * monster always have 6 stars.
-         *
-         * @return int Monster base stars (1-6).
-         */
-        public function get_base_stars(){
-            return $this->base_stars;
-        }
-    
-        /**
-         * Retrieves the monster's natural stars.
-         * Natural stars are the default stars of the monsters in it's unawakened form.
-         *
-         * @return int Monster natural stars (1-5).
-         */
-        public function get_natural_stars(){
-            return $this->natural_stars;
-        }
-    
-        /**
-         * Checks if the monster is obtainable.
-         * Non obtainable monster are usually enemies (boses, towers, pure units...) 
-         *
-         * @return boolean True for obtainable monsters, false for unobtainable.
-         */
-        public function is_obtainable(){
-            return $this->obtainable;
-        }
-    
-        /**
-         * Checks if the monster can be awakened.
-         * It also includes monsters that can second awaken.
-         *
-         * @return boolean True if the monster can awaken, false otherwise.
-         */
-        public function can_awaken(){
-            return $this->can_awaken;
+
+        // Guess monster name
+        if ($this->awakens_from == "" && $this->awakens_to == ""){
+            // No to, no from. Silver monster.
+            if ($this->base_stars >= 4){
+                // SFV Collab event monsters, always awakened.
+                $this->title = $this->name;
+            }
+            elseif($this->archetype == ARCHETYPE_ID::MATERIAL && $this->element == ELEMENT_ID::LIGHT){
+                // Rainbowmon, always awakened
+                $this->title = $this->name;
+            }
+            elseif($this->archetype == ARCHETYPE_ID::MATERIAL && $this->element == ELEMENT_ID::DARK){
+                // Devilmon, always unawakened, but dont include element
+                $this->title = $this->name;
+            }
+            else{
+                // Unawakeable monster
+                $this->title = $this->element_name . " " . $this->name;
+            }
         }
-    
-        /**
-         * Retrieves the awakening bonus description.
-         * Note that for second awakenings, the bonus always is described as "Secondary Awakening".
-         * For units that can't awaken, it will return an empty string.
-         *
-         * @return string Awaken bonus.
-         */
-        public function get_awaken_bonus(){
-            return $this->awaken_bonus;
+        // Awakened
+        elseif ($this->awakens_from != ""){
+            $this->title = $this->name;
         }
-    
-        /**
-         * Retrieves the number of skill-ups needed to fully skill-up the monster.
-         *
-         * @return int Required skill-ups
-         */
-        public function get_skill_ups_to_max(){
-            return $this->skill_ups_to_max;
+        // Gold
+        elseif (strlen($this->awakens_to) > 0){
+            $this->title = $this->element_name . " " . $this->name;
         }
-    
-        /**
-         * Retrieves the monster's leader skill.
-         *
-         * @return Leader_Skill The leader skill.
-         */
-        public function get_leader_skill(){
-            if (! $this->flag_skills){
-                $this->load_skills();
-            }
-            return $this->leader_skill;
+    }
+
+    /**
+     * Loads the monster skills into the entity.
+     *
+     * Must be called only once before trying to get the skills (including the leader one). Sets
+     * the flag {@link Monster:$flag_skills} to true.
+     */
+    private function load_skills(){
+        $statement = get_context()->get_db()->prepare("
+          SELECT skill.id AS skill
+          FROM
+            skill,
+            monster_skill
+          WHERE
+            skill.id = monster_skill.skill AND
+            monster_skill.monster = :monster
+          ORDER BY slot;
+        ");
+        $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->skill, new Skill($r["skill"]));
+        }
+        if ($this->leader_skill_id != null){
+            $this->leader_skill = new Leader_Skill($this->leader_skill_id);
+        }
+        $this->flag_skills = true;
+    }
+
+    /**
+     * Loads the monster sources into the entity.
+     *
+     * Must be called only once before trying to get the sources. Sets the flag 
+     * {@link Monster:$flag_sources} to true.
+     */
+    private function load_sources(){
+        $statement = get_context()->get_db()->prepare("
+          SELECT source
+          FROM monster_source
+          WHERE monster = :monster;
+        ");
+        $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->sources, new Source($r["source"]));
+        }
+        $this->flag_sources = true;
+    }
+
+    /**
+     * Loads the essences to awaken the monster into the entity.
+     *
+     * Must be called only once before trying to get the essences. Sets the flag
+     * {@link Monster:$flag_essences} to true.
+     */
+    private function load_essences(){
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            item,
+            amount
+          FROM monster_essence
+          WHERE
+            monster = :monster
+          ORDER BY item;
+        ");
+        $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            $e = [
+                "item" => new Inventory($r["item"], INVENTORY_TYPE_ID::ESSENCES),
+                "amount" => $r["amount"]
+            ];
+            array_push($this->essences, $e);
+        }
+        $this->flag_essences = true;
+    }
+
+    /**
+     * Loads the monster transformation into the entity.
+     *
+     * Must be called only once before trying to get the transformation. Sets the flag
+     * {@link Monster:$flag_transformation} to true.
+     */
+    private function load_transformation(){
+        $statement = get_context()->get_db()->prepare("
+          SELECT id
+          FROM monster_transformation
+          WHERE monster = :monster;
+        ");
+        $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->transformation = new Monster_Transformation($r["id"]);
+        }
+        $this->flag_transformation = true;
+    }
+
+    /**
+     * Retrieves the monster identifier.
+     *
+     * @return string Monster ID
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Retrieves the monsters family identifier.
+     *
+     * @return string Family ID.
+     */
+    public function get_family(){
+        return $this->family;
+    }
+
+    /**
+     * Retrieves the monster name.
+     *
+     * @return string Monster name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
+
+    /**
+     * Retrieves the monster's element.
+     * 
+     * @see ELEMENT_ID
+     *
+     * @return int Element ID.
+     */
+    public function get_element(){
+        return $this->element;
+    }
+
+    /**
+     * Retrieves the monster's element name.
+     *
+     * @return string Element name.
+     */
+    public function get_element_name(){
+        return $this->element_name;
+    }
+
+    /**
+     * Retrieves the monster's archetype.
+     * 
+     * @see ARCHETYPE_ID
+     *
+     * @return int Monster's archetype ID.
+     */
+    public function get_archetype(){
+        return $this->archetype;
+    }
+
+    /**
+     * Retrieves the monster's archetype name.
+     *
+     * @return string Archetype name.
+     */
+    public function get_archetype_name(){
+        return $this->archetype_name;
+    }
+
+    /**
+     * Retrieves the monster's base stars.
+     * Base stars are the default stars of the monsters in it's current form. I.E awakened
+     * monsters have always one more base stars than their unawakened forms, and second awaken
+     * monster always have 6 stars.
+     *
+     * @return int Monster base stars (1-6).
+     */
+    public function get_base_stars(){
+        return $this->base_stars;
+    }
+
+    /**
+     * Retrieves the monster's natural stars.
+     * Natural stars are the default stars of the monsters in it's unawakened form.
+     *
+     * @return int Monster natural stars (1-5).
+     */
+    public function get_natural_stars(){
+        return $this->natural_stars;
+    }
+
+    /**
+     * Checks if the monster is obtainable.
+     * Non obtainable monster are usually enemies (boses, towers, pure units...) 
+     *
+      * @return bool True for obtainable monsters, false for unobtainable.
+     */
+    public function is_obtainable(){
+        return $this->obtainable;
+    }
+
+    /**
+     * Checks if the monster can be awakened.
+     * It also includes monsters that can second awaken.
+     *
+      * @return bool True if the monster can awaken, false otherwise.
+     */
+    public function can_awaken(){
+        return $this->can_awaken;
+    }
+
+    /**
+     * Retrieves the awakening bonus description.
+     * Note that for second awakenings, the bonus always is described as "Secondary Awakening".
+     * For units that can't awaken, it will return an empty string.
+     *
+     * @return string Awaken bonus.
+     */
+    public function get_awaken_bonus(){
+        return $this->awaken_bonus;
+    }
+
+    /**
+     * Retrieves the number of skill-ups needed to fully skill-up the monster.
+     *
+     * @return int Required skill-ups
+     */
+    public function get_skill_ups_to_max(){
+        return $this->skill_ups_to_max;
+    }
+
+    /**
+     * Retrieves the monster's leader skill.
+     *
+     * @return Leader_Skill The leader skill.
+     */
+    public function get_leader_skill(){
+        if (! $this->flag_skills){
+            $this->load_skills();
         }
+        return $this->leader_skill;
+    }
 
-        /**
-         * Retrieves the monster stats.
-         * These stats are the ones for the monster in it's base grade, at max level.
-         *
-         * It's an associative array with the following keys:
-         * atk, def, hp, spd, crr, crd, acc, res
-         *
-         * @see get_min_stats()
-         * @see get_max_stats()
-         *
+    /**
+     * Retrieves the monster stats.
+     * These stats are the ones for the monster in it's base grade, at max level.
+     *
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res
+     *
+     * @see get_min_stats()
+     * @see get_max_stats()
+     *
          * @return int[] Monster stats.
-         */
-        public function get_stats(){
-            return $this->stats;
-        }
+     */
+    public function get_stats(){
+        return $this->stats;
+    }
 
-        /**
-         * Retrieves the monster stats.
-         * These stats are the ones for the monster in it's base grade, at level 1.
-         *
-         * It's an associative array with the following keys:
-         * atk, def, hp, spd, crr, crd, acc, res
-         *
-         * @see get_stats()
-         * @see get_max_stats()
-         *
+    /**
+     * Retrieves the monster stats.
+     * These stats are the ones for the monster in it's base grade, at level 1.
+     *
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res
+     *
+     * @see get_stats()
+     * @see get_max_stats()
+     *
          * @return int[] Monster stats.
-         */
-        public function get_min_stats(){
-            return $this->stats();
-        }
-        
-        /**
-         * Retrieves the monster stats.
-         * These stats are the ones for the monster with 6 stars at level 40.
-         *
-         * It's an associative array with the following keys:
-         * atk, def, hp, spd, crr, crd, acc, res
-         *
+     */
+    public function get_min_stats(){
+        return $this->min_stats;
+    }
+
+    /**
+     * Retrieves the monster stats.
+     * These stats are the ones for the monster with 6 stars at level 40.
+     *
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res
+     *
          * @return int[] Monster stats.
-         *
-         * @see get_stats()
-         * @see get_min_stats()
-         */
-        public function get_max_stats(){
-            return $this->stats();
-        }
-    
-        /**
-         * Retrieves the identifier of the monster who awakens to this one.
-         *
-         * @return string Unawakened monster identifier, null for unawakened monsters.
-         */
-        public function get_awakens_from(){
-            return $this->awakens_from;
-        }
-    
-        /**
-         * Retrieves the identifier of the monster this one awakens to.
-         *
-         * @return string Next awaken monster identifier, null for fully awakened monsters.
-         */
-        public function get_awakens_to(){
-            return $this->awakens_to;
-        }
-    
-        /**
-         * Checks if skill-ups can be created by fussion.
-         *
-         * @return boolean True if skill-us can be fused, false otherwise.
-         */
-        public function has_fusion_food(){
-            return $this->fusion_food;
-        }
-    
-        /**
-         * Checks if the monster is an Homunculus.
-         *
-         * @return boolean True if Homunculus, false otherwise.
-         */
-        public function is_homunculus(){
-            return $this->homunculus;
-        }
-    
-        /**
-         * // TODO: Unimplemented.
-         * Retrieves $craft_cost
-         *
-         * @return number
-         */
-        public function get_craft_cost(){
-            return $this->craft_cost;
-        }
-    
-        /**
-         * Retrieves the monster skills
-         *
-         * @return Skill[] Monster skills.
-         */
-        public function get_skills(){
-            if (! $this->flag_skills){
-                $this->load_skills();
-            }
-            return $this->skill;
-        }
-    
-        /**
-         * Retrieves the essences required to awaken the monster.
-         *
-         * @return [[Inventory][int]] Essences required to awaken the monster.s
-         */
-        public function get_essences(){
-            if (! $this->flag_essences){
-                $this->load_essences();
-            }
-            return $this->essences;
-        }
-    
-        /**
-         * Retrieves the sources the monster can be obtained from.
-         *
-         * @return Source[] Array of sources.s
-         */
-        public function get_sources(){
-            if (! $this->flag_sources){
-                $this->load_sources();
-            }
-            return $this->sources;
+     *
+     * @see get_stats()
+     * @see get_min_stats()
+     */
+    public function get_max_stats(){
+        return $this->max_stats;
+    }
+
+    /**
+     * Retrieves the identifier of the monster who awakens to this one.
+     *
+     * @return string Unawakened monster identifier, null for unawakened monsters.
+     */
+    public function get_awakens_from(){
+        return $this->awakens_from;
+    }
+
+    /**
+     * Retrieves the identifier of the monster this one awakens to.
+     *
+     * @return string Next awaken monster identifier, null for fully awakened monsters.
+     */
+    public function get_awakens_to(){
+        return $this->awakens_to;
+    }
+
+    /**
+     * Checks if skill-ups can be created by fussion.
+     *
+      * @return bool True if skill-us can be fused, false otherwise.
+     */
+    public function has_fusion_food(){
+        return $this->fusion_food;
+    }
+
+    /**
+     * Checks if the monster is an Homunculus.
+     *
+      * @return bool True if Homunculus, false otherwise.
+     */
+    public function is_homunculus(){
+        return $this->homunculus;
+    }
+
+    /**
+     * // TODO: Unimplemented.
+     * Retrieves $craft_cost
+     *
+         * @return int
+     */
+    public function get_craft_cost(){
+        return $this->craft_cost;
+    }
+
+    /**
+     * Retrieves the monster skills
+     *
+     * @return Skill[] Monster skills.
+     */
+    public function get_skills(){
+        if (! $this->flag_skills){
+            $this->load_skills();
         }
-    
-        /**
-         * Retrieves the unit's $title
-         * If awakened, it will be the awakened from name.
-         * If unawakened, it will be <element> <name>.
-         *
-         * @return string Units title.
-         */
-        public function get_title(){
-            return $this->title;
+        return $this->skill;
+    }
+
+    /**
+     * Retrieves the essences required to awaken the monster.
+     *
+     * @return [[Inventory][int]] Essences required to awaken the monster.s
+     */
+    public function get_essences(){
+        if (! $this->flag_essences){
+            $this->load_essences();
         }
-    
-        /**
-         * Retrieves the unit this ne can transform to.
-         *
-         * @return Monster_Transformation The transformation, null if none.
-         */
-        public function get_transformation(){
-            if (! $this->flag_transformation){
-                $this->load_transformation();
-            }
-            return $this->transformation;
+        return $this->essences;
+    }
+
+    /**
+     * Retrieves the sources the monster can be obtained from.
+     *
+     * @return Source[] Array of sources.s
+     */
+    public function get_sources(){
+        if (! $this->flag_sources){
+            $this->load_sources();
         }
+        return $this->sources;
+    }
 
-        /**
-         * Gets the path to the monster image. The image must be in the
-         * img/monster/ directory, and it's name must be the monster id,
-         * padded with '0' to 8 digits, and the extension must be '.png'.
-         *
-         * @return string Image URL, or a fixed unknown image.
-         */
-        public function get_image(){
-            return APPLICATION::img("UNIT", $this->id);
+    /**
+     * Retrieves the unit's $title
+     * If awakened, it will be the awakened from name.
+     * If unawakened, it will be <element> <name>.
+     *
+     * @return string Units title.
+     */
+    public function get_title(){
+        return $this->title;
+    }
+
+    /**
+     * Retrieves the unit this ne can transform to.
+     *
+     * @return Monster_Transformation The transformation, null if none.
+     */
+    public function get_transformation(){
+        if (! $this->flag_transformation){
+            $this->load_transformation();
         }
+        return $this->transformation;
+    }
 
+    /**
+     * Gets the path to the monster image. 
+     *
+     * @return string Image URL, or a fixed unknown image.
+     */
+    public function get_image(){
+        return APPLICATION::img("UNIT", $this->id);
     }
-?>
+
+}

+ 32 - 29
application/entity/Monster_Transformation.php

@@ -4,48 +4,49 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Skill.php");
 require_once(PATH::ENTITY . "Leader_Skill.php");
 require_once(PATH::ENTITY . "Source.php");
 
-
 /**
  * Monster transformation.
  *
- * Represents an object from the table 'monster_transformation'.
+ * Represents a transformation that a monster can achive in battle.
  *
  * @category Entity
  */
 class Monster_Transformation extends Entity{
-    
+
     /**
      * @var int Transformed monster identifier.
      */
     private $id;
-    
+
     /**
      * @var int Transformed monster family id.
      */
     private $family;
-    
+
     /**
      * @var int ID of the monster that transformes into this.
      */
     private $monster;
-    
+
+    /**
+     * @var bool Internal flag to check if the skills have been loaded into the entity.
+     */
     private $flag_skills = false;
     /**
-     * @var \Skill[] Skills in the transformed form.
+     * @var Skill[] Skills in the transformed form.
      */
     private $skill = [];
-    
+
     /**
      * Constructor.
      *
@@ -56,13 +57,13 @@ class Monster_Transformation extends Entity{
      */
     public function __construct($id){
         $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                family,
-                monster
-              FROM monster_transformation
-               WHERE id = :id;
-            ");
+          SELECT
+            id,
+            family,
+            monster
+          FROM monster_transformation
+           WHERE id = :id;
+        ");
         $statement->bindValue(':id', $id, SQLITE3_TEXT);
         $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
         if ($r){
@@ -71,9 +72,12 @@ class Monster_Transformation extends Entity{
             $this->monster = $r["monster"];
         }
     }
-    
+
     /**
      * Loads the information about the monster skills in the transformed form.
+     * 
+     * Must be called only once before trying to get the skills. Sets the flag
+     * {@link Monster_Transformation:$flag_skills} to true.
      */
     private function load_skills(){
         $this->skill = [];
@@ -94,7 +98,7 @@ class Monster_Transformation extends Entity{
         }
         $this->flag_skills = true;
     }
-    
+
     /**
      * Retrieves the identifier of the transformed monster.
      *
@@ -103,25 +107,25 @@ class Monster_Transformation extends Entity{
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the transofmred monster family identifier.
      *
-     * @return number Family ID.
+     * @return int Family ID.
      */
     public function get_family(){
         return $this->family;
     }
-    
+
     /**
      * Retrieves the identifier of the monster that transforms into this one.
      *
-     * @return number Base monster ID.
+     * @return int Base monster ID.
      */
     public function get_base_id(){
         return $this->monster;
     }
-    
+
     /**
      * Retrieves the skills of the transformed monster.
      *
@@ -133,7 +137,7 @@ class Monster_Transformation extends Entity{
         }
         return $this->skill;
     }
-    
+
     /**
      * Gets the path to the monster image.
      *
@@ -142,6 +146,5 @@ class Monster_Transformation extends Entity{
     public function get_image(){
         return APPLICATION::img("UNIT", $this->id);
     }
-    
+
 }
-?>

+ 798 - 631
application/entity/Player.php

@@ -1,687 +1,854 @@
 <?php
+/**
+ * Player entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::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 . "Item.php");
+require_once(PATH::ENTITY . "Record.php");
+require_once(PATH::ENTITY . "Server.php");
+
+/**
+ * A Player.
+ *
+ * Represents a game account.
+ *
+ * @category Entity
+ */
+class Player extends Entity{
+
     /**
-     * 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 . "Item.php");
-    require_once(PATH::ENTITY . "Record.php");
-    require_once(PATH::ENTITY . "Server.php");
-
-    /**
-     * A Player.
-     *
-     * Represents an object from the table 'player'.
-     *
-     * @category Entity
-     */
-    class Player extends Entity{
-
-        private $id;
-        private $server;
-        private $country;
-        private $language;
-        private $level;
-        private $name;
-        private $experience;
-        private $rep = null;
-        private $rep_id = null;
-        private $joined = 0;
-        private $top_rank_arena = 0;
-        private $top_rank_world_arena = 0;
-        private $top_rank_special_league = 0;
-        private $top_rank_gw = 0;
-        private $top_rank_siege = 0;
-        private $top_rank_wboss = 0;
-        private $top_rank_toan = 0;
-        private $top_rank_toah = 0;
-        private $top_rank_toal = 0;
-        private $flag_defense = false;
-        private $arena_defense = [];
-        private $gw_defense = [[], []];
-        private $siege_defense = [];
-        private $currency = [
-            "mana" => 0,
-            "crystal" => 0,
-            "energy" => 0,
-            "energy_max" => 0,
-            "arena_energy" => 0,
-            "darkportal_energy" => 0,
-            "dimension_energy" => 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,
-        ];
-        private $flag_building = false;
-        private $building = [];
-        private $decoration = [];
-        private $flag_item = false;
-        private $item_scroll = [];
-        private $item_craft_rune = [];
-        private $item_craft = [];
-        private $item_essence = [];
-        private $flag_record = false;
-        private $record = [];
-        private $public = false;
-
-
-        /**
-         * 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.
-         */
-        public function __construct($id, $complete = true){
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                server,
-                country,
-                lang,
-                name,
-                level,
-                experience,
-                rep,
-                mana,
-                crystal,
-                energy,
-                energy_max,
-                arena_energy,
-                darkportal_energy,
-                dimension_energy,
-                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,
-                top_rank_toal,
-                public
-              FROM player
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->id = $r["id"];
-                $this->server = new Server($r["server"]);
-                $this->country = $r["country"];
-                $this->lang = $r["lang"];
-                $this->name = $r["name"];
-                $this->level = $r["level"];
-                $this->experience = $r["experience"];
-                if (strlen($r["rep"]) > 0){
-                    $this->rep_id = $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["darkportal_energy"] = $r["darkportal_energy"];
-                $this->currency["dimension_energy"] = $r["dimension_energy"];
-                $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 = new Datetime();
-                $this->joined->setTimestamp($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"];
-                $this->top_rank_toal = $r["top_rank_toal"];
-                if (strlen($r["public"]) == 1){
-                    $this->public = true;
-                }
-            }
-        }
+     * @var int In-game player ID.
+     */
+    private $id;
 
-        private function load_defenses(){
-            $statement = get_context()->get_db()->prepare("
-                SELECT unit
-                FROM defense
-                WHERE
-                  player = :player AND
-                  area_type = :area_type
-                ORDER BY position;
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $statement->bindValue(':area_type', AREA_TYPE_ID::ARENA, SQLITE3_INTEGER);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->arena_defense, new Unit($r["unit"], false));
-            }
-            $statement = get_context()->get_db()->prepare("
-                SELECT
-                  unit,
-                  position
-                FROM defense
-                WHERE
-                  player = :player AND
-                  area_type = :area_type
-                ORDER BY position;
-            ");
-            $statement->bindValue(':id', $this->id, SQLITE3_TEXT);
-            $statement->bindValue(':area_type', AREA_TYPE_ID::GUILD_WAR, SQLITE3_INTEGER);
-            $q = $statement->execute();
-            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));
-                }
-            }
-            // TODO: Siege defenses
-            $this->flag_defense = true;
-        }
+    /**
+     * @var int Account server ID.
+     */
+    private $server;
 
-        private function load_buildings(){
-            $statement = get_context()->get_db()->prepare("
-                SELECT
-                  building.id AS id,
-                  min(building.buildable) AS min
-                FROM
-                  building,
-                  buildable
-                WHERE
-                  player = :player AND
-                  building.buildable = buildable.id
-                GROUP BY building.buildable;
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->building, new Building($r["id"]));
-            }
-            $statement = get_context()->get_db()->prepare("
-                SELECT id
-                FROM decoration
-                WHERE player = :player;
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->decoration, new Decoration($r["id"]));
-            }
-            $this->flag_building = true;
-        }
+    /**
+     * @var string Account country code.
+     */
+    private $country;
 
-        private function load_items(){
-            $statement = get_context()->get_db()->prepare("
-                SELECT
-                  id,
-                  type
-                FROM item
-                WHERE
-                  player = :player AND
-                  type = :type AND
-                  amount > 0
-                ORDER BY item.type;
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $statement->bindValue(':type', INVENTORY_TYPE_ID::SCROLL, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->item_scroll, new Item($this->id, $r["id"], $r["type"]));
-            }
-            // Rune crafting items are marked as generic crafting.
-            $statement = get_context()->get_db()->prepare("
-                SELECT
-                  id,
-                  type
-                FROM item
-                WHERE
-                  player = :player AND
-                  type = :type AND
-                  amount > 0
-                ORDER BY id;
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $statement->bindValue(':type', INVENTORY_TYPE_ID::ENCHANTMENT, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->item_craft_rune, new Item($this->id, $r["id"], $r["type"]));
-            }
-            $statement = get_context()->get_db()->prepare("
-                SELECT
-                  id,
-                  type
-                FROM item
-                WHERE
-                  player = :player AND
-                  type = :type AND
-                  amount > 0
-                ORDER BY id;
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $statement->bindValue(':type', INVENTORY_TYPE_ID::CRAFT_STUFF, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->item_craft, new Item($this->id, $r["id"], $r["type"]));
-            }
-            $statement = get_context()->get_db()->prepare("
-                SELECT
-                  item.id AS id,
-                  item.type AS type
-                FROM
-                  item,
-                  inventory
-                WHERE
-                  item.id = inventory.id AND
-                  item.type = inventory.type AND
-                  item.player = :player AND
-                  item.type = :type AND
-                  amount > 0
-                ORDER BY
-                  upper(inventory.name) NOT LIKE '%MAGIC%',
-                  upper(inventory.name) NOT LIKE '%FIRE%',
-                  upper(inventory.name) NOT LIKE '%WATER%',
-                  upper(inventory.name) NOT LIKE '%WIND%',
-                  upper(inventory.name) NOT LIKE '%LIGHT%',
-                  upper(inventory.name) NOT LIKE '%DARK%',
-                  upper(inventory.name) NOT LIKE '%LOW%',
-                  upper(inventory.name) NOT LIKE '%MID%',
-                  upper(inventory.name) NOT LIKE '%HIGH%'
-                ;
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $statement->bindValue(':type', INVENTORY_TYPE_ID::ESSENCES, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->item_essence, new Item($this->id, $r["id"], $r["type"]));
-            }
-            $this->flag_item = true;
-        }
+    /**
+     * @var string Account language code.
+     */
+    private $language;
 
-        private function load_records(){
-            $statement = get_context()->get_db()->prepare("
-                SELECT
-                  player,
-                  area_type,
-                  area
-                FROM record
-                WHERE player = :player
-                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
-            ");
-            $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->record, new Record($r["player"], $r["area_type"], $r["area"]));
-            }
-            $this->flag_record = true;
-        }
+    /**
+     * @var int Player level.
+     */
+    private $level;
 
-        /**
-         * Retrieves the player identifier
-         *
-         * @return int Plyaer ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
+    /**
+     * @var string Player name.
+     */
+    private $name;
 
-        /**
-         * Retrieves the player server.
-         *
-         * @return Server The player's account server.
-         */
-        public function get_server(){
-            return $this->server;
-        }
+    /**
+     * @var int Total experience.
+     */
+    private $experience;
 
-        /**
-         * Retrieves the player's country.
-         *
-         * @return string Two digit country code.
-         */
-        public function get_country(){
-            return $this->country;
-        }
+    /**
+     * @var Unit Player's representative unit.
+     */
+    private $rep;
 
-        /**
-         * Retrieves the player's language.
-         *
-         * @return string Two digit language code.
-         */
-        public function get_language(){
-            return $this->language;
-        }
+    /**
+     * @var int Player's representative unit ID.
+     */
+    private $rep_id;
 
-        /**
-         * Retrieves the player's level,
-         *
-         * @return int Player's level
-         */
-        public function get_level(){
-            return $this->level;
-        }
+    /**
+     * @var DateTime Time the player joined the game.
+     */
+    private $joined = 0;
 
-        /**
-         * Retrieves the player's name
-         *
-         * @return string The playe's name.
-         */
-        public function get_name(){
-            return $this->name;
-        }
+    /**
+     * @var int Player's top rank in the Arena.
+     * @see ARENA_RANK_ID
+     */
+    private $top_rank_arena = 0;
 
-        /**
-         * Retrieves the total experience earned by the user.
-         *
-         * @return number Total experience.
-         */
-        public function get_experience(){
-            return $this->experience;
-        }
+    /**
+     * @var int Player's top rank in the World Arena.
+     * @see ARENA_RANK_ID
+     */
+    private $top_rank_world_arena = 0;
+
+    /**
+     * @var int Player's top rank in the Special League.
+     * @see ARENA_RANK_ID
+     */
+    private $top_rank_special_league = 0;
+
+    /**
+     * @var int Player's top rank in Guild War.
+     * @see ARENA_RANK_ID
+     */
+    private $top_rank_gw = 0;
+
+    /**
+     * @var int Player's top rank in the Siege Battle.
+     * @see ARENA_RANK_ID
+     */
+    private $top_rank_siege = 0;
+
+    /**
+     * @var int Player's top rank in World Boss
+     * @see WORLD_BOSS_RANK_ID
+     */
+    private $top_rank_wboss = 0;
+
+    /**
+     * @var int Top floor reached in the Trial of Ascension Normal.
+     */
+    private $top_rank_toan = 0;
+
+    /**
+     * @var int Top floor reached in the Trial of Ascension Hard.
+     */
+    private $top_rank_toah = 0;
+
+    /**
+     * @var int Maximum stars achieved in the Trial of Ascension Hell.
+     */
+    private $top_rank_toal = 0;
+
+    /**
+     * @var bool Internal flag to chek if Arena, GW and Siege defenses have been read.
+     */
+    private $flag_defense = false;
+
+    /**
+     * @var Unit[] Arena defense.
+     */
+    private $arena_defense = [];
 
-        /**
-         * Retrieves the player's representative unit.
-         *
-         * @return Unit Player's representative
-         */
-        public function get_rep(){
-            if ($this->rep_id != null && $this->rep == null){
-                $this->rep = new Unit($this->rep_id);
+    /**
+     * @var Unit[][] Guild War defenses.
+     */
+    private $gw_defense = [[], []];
+
+    /**
+     * @var Unit[] Siege defenses.
+     * @todo Implement
+     */
+    private $siege_defense = [];
+
+    /**
+     * @var int[] Various currencies.
+     */
+    private $currency = [
+        "mana" => 0,
+        "crystal" => 0,
+        "energy" => 0,
+        "energy_max" => 0,
+        "arena_energy" => 0,
+        "darkportal_energy" => 0,
+        "dimension_energy" => 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 bool Internal flag to check if the buildings and decorations have been loaded into the
+     * entity.
+     */
+    private $flag_building = false;
+
+    /**
+     * @var Building[] Player's buildings.
+     */
+    private $building = [];
+
+    /**
+     * @var Decoration[] Player's decorations.
+     */
+    private $decoration = [];
+
+    /**
+     * @var bool Internal flags to check if various types of inventory items have been loaded into
+     * the entity; 
+     */
+    private $flag_item = false;
+
+    /**
+     * @var Item[] Player's scrolls.
+     */
+    private $item_scroll = [];
+
+    /**
+     * @var Item[] Player's rune craft materials..
+     */
+    private $item_craft_rune = [];
+
+    /**
+     * @var Item[] Player's craft materials.
+     */
+    private $item_craft = [];
+
+    /**
+     * @var Item[] Player's essences.
+     */
+    private $item_essence = [];
+
+    /**
+     * @var bool Internal flag to check if the player records have been loaded into the entity.
+     */
+    private $flag_record = false;
+
+    /**
+     * @var Record[] Player records.
+     */
+    private $record = [];
+
+    /**
+     * @var bool Indicates the profile visibility.
+     */
+    private $public = false;
+
+    /**
+     * Constructor.
+     *
+     * Searches the database and retrieves the information about the
+     * player, populating it and it's items.
+     *
+     * @param int $id Player identifier.
+     */
+    public function __construct($id){
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            server,
+            country,
+            lang,
+            name,
+            level,
+            experience,
+            rep,
+            mana,
+            crystal,
+            energy,
+            energy_max,
+            arena_energy,
+            darkportal_energy,
+            dimension_energy,
+            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,
+            top_rank_toal,
+            public
+          FROM player
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->server = new Server($r["server"]);
+            $this->country = $r["country"];
+            $this->lang = $r["lang"];
+            $this->name = $r["name"];
+            $this->level = $r["level"];
+            $this->experience = $r["experience"];
+            if (strlen($r["rep"]) > 0){
+                $this->rep_id = $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["darkportal_energy"] = $r["darkportal_energy"];
+            $this->currency["dimension_energy"] = $r["dimension_energy"];
+            $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 = new Datetime();
+            $this->joined->setTimestamp($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"];
+            $this->top_rank_toal = $r["top_rank_toal"];
+            if (strlen($r["public"]) == 1){
+                $this->public = true;
             }
-            return $this->rep;
         }
+    }
 
-        /**
-         * Gets the date the user joined the game.
-         *
-         * If $format is supplied, a string in the desired format will be returned. If not, the raw
-         * DateTime object will e returned.
-         *
-         * @param string $format A date format (optional).
-         * @return DateTime | string The raw date, or a formatted version.
-         */
-        public function get_joined($format = null){
-            if (null == $format){
-                return $this->joined;
+    /**
+     * Loads the defenses into the entity.
+     *
+     * Must be called only once before trying to get the units in Arena, Guild War or Siege
+     * defenses. Sets the flag {@link Player:$flag_defenses} to true.
+     */
+    private function load_defenses(){
+        $statement = get_context()->get_db()->prepare("
+            SELECT unit
+            FROM defense
+            WHERE
+              player = :player AND
+              area_type = :area_type
+            ORDER BY position;
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $statement->bindValue(':area_type', AREA_TYPE_ID::ARENA, SQLITE3_INTEGER);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->arena_defense, new Unit($r["unit"], false));
+        }
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              unit,
+              position
+            FROM defense
+            WHERE
+              player = :player AND
+              area_type = :area_type
+            ORDER BY position;
+        ");
+        $statement->bindValue(':id', $this->id, SQLITE3_TEXT);
+        $statement->bindValue(':area_type', AREA_TYPE_ID::GUILD_WAR, SQLITE3_INTEGER);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            if ($r["position"] <= 3){
+                array_push($this->gw_defense[0], new Unit($r["unit"], false));
             }
             else{
-                return $this->joined->format($format);
+                array_push($this->gw_defense[1], new Unit($r["unit"], false));
             }
         }
+        // TODO: Siege defenses
+        $this->flag_defense = true;
+    }
 
-        /**
-         * Retrieves the user's top rank in the Arena.
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_arena(){
-            return $this->top_rank_arena;
-        }
+    /**
+     * Loads buildings and decorations into the entity.
+     *
+     * Must be called only once before trying to get the buildings or decorations. Sets the flag
+     * {@link Player:$flag_defenses} to true.
+     */
+    private function load_buildings(){
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              building.id AS id,
+              min(building.buildable) AS min
+            FROM
+              building,
+              buildable
+            WHERE
+              player = :player AND
+              building.buildable = buildable.id
+            GROUP BY building.buildable;
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->building, new Building($r["id"]));
+        }
+        $statement = get_context()->get_db()->prepare("
+            SELECT id
+            FROM decoration
+            WHERE player = :player;
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->decoration, new Decoration($r["id"]));
+        }
+        $this->flag_building = true;
+    }
 
-        /**
-         * Retrieves the user's top rank in the WorldArena.
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_world_arena(){
-            return $this->top_rank_world_arena;
-        }
+    /**
+     * Loads items into the entity.
+     *
+     * Must be called only once before trying to get any of the items in the inventory. Sets the
+     * flag {@link Player:$flag_defenses} to true.
+     */
+    private function load_items(){
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              id,
+              type
+            FROM item
+            WHERE
+              player = :player AND
+              type = :type AND
+              amount > 0
+            ORDER BY item.type;
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $statement->bindValue(':type', INVENTORY_TYPE_ID::SCROLL, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->item_scroll, new Item($this->id, $r["id"], $r["type"]));
+        }
+        // Rune crafting items are marked as generic crafting.
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              id,
+              type
+            FROM item
+            WHERE
+              player = :player AND
+              type = :type AND
+              amount > 0
+            ORDER BY id;
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $statement->bindValue(':type', INVENTORY_TYPE_ID::ENCHANTMENT, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->item_craft_rune, new Item($this->id, $r["id"], $r["type"]));
+        }
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              id,
+              type
+            FROM item
+            WHERE
+              player = :player AND
+              type = :type AND
+              amount > 0
+            ORDER BY id;
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $statement->bindValue(':type', INVENTORY_TYPE_ID::CRAFT_STUFF, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->item_craft, new Item($this->id, $r["id"], $r["type"]));
+        }
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              item.id AS id,
+              item.type AS type
+            FROM
+              item,
+              inventory
+            WHERE
+              item.id = inventory.id AND
+              item.type = inventory.type AND
+              item.player = :player AND
+              item.type = :type AND
+              amount > 0
+            ORDER BY
+              upper(inventory.name) NOT LIKE '%MAGIC%',
+              upper(inventory.name) NOT LIKE '%FIRE%',
+              upper(inventory.name) NOT LIKE '%WATER%',
+              upper(inventory.name) NOT LIKE '%WIND%',
+              upper(inventory.name) NOT LIKE '%LIGHT%',
+              upper(inventory.name) NOT LIKE '%DARK%',
+              upper(inventory.name) NOT LIKE '%LOW%',
+              upper(inventory.name) NOT LIKE '%MID%',
+              upper(inventory.name) NOT LIKE '%HIGH%'
+            ;
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $statement->bindValue(':type', INVENTORY_TYPE_ID::ESSENCES, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->item_essence, new Item($this->id, $r["id"], $r["type"]));
+        }
+        $this->flag_item = true;
+    }
 
-        /**
-         * Retrieves the user's top rank in the Arena.
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_special_league(){
-            return $this->top_rank_special_league;
-        }
+    /**
+     * Loads the records into the entity.
+     *
+     * Must be called only once before trying to get records. Sets the flag
+     * {@link Player:$flag_defenses} to true.
+     */
+    private function load_records(){
+        $statement = get_context()->get_db()->prepare("
+            SELECT
+              player,
+              area_type,
+              area
+            FROM record
+            WHERE player = :player
+            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
+        ");
+        $statement->bindValue(':player', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->record, new Record($r["player"], $r["area_type"], $r["area"]));
+        }
+        $this->flag_record = true;
+    }
 
-        /**
-         * Retrieves the user's top rank in Guild War.
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_gw(){
-            return $this->top_rank_gw;
-        }
+    /**
+     * Retrieves the player identifier
+     *
+     * @return int Plyaer ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
 
-        /**
-         * Retrieves the user's top rank in Siege battle.
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_siege(){
-            return $this->top_rank_siege;
-        }
+    /**
+     * Retrieves the player server.
+     *
+     * @return Server The player's account server.
+     */
+    public function get_server(){
+        return $this->server;
+    }
 
-        /**
-         * Retrieves the user's top rank in the World Boss.
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_wboss(){
-            return $this->top_rank_wboss;
-        }
+    /**
+     * Retrieves the player's country.
+     *
+     * @return string Two digit country code.
+     */
+    public function get_country(){
+        return $this->country;
+    }
 
-        /**
-         * Retrieves the user's top rank in the Trial of Ascension (normal difficulty).
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_toan(){
-            return $this->top_rank_toan;
-        }
+    /**
+     * Retrieves the player's language.
+     *
+     * @return string Two digit language code.
+     */
+    public function get_language(){
+        return $this->language;
+    }
 
-        /**
-         * Retrieves the user's top rank in the Trial of Ascension (hard difficulty).
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_toah(){
-            return $this->top_rank_toah;
-        }
+    /**
+     * Retrieves the player's level,
+     *
+     * @return int Player's level
+     */
+    public function get_level(){
+        return $this->level;
+    }
 
-        /**
-         * Retrieves the user's top rank in the Trial of Ascension (hell difficulty).
-         *
-         * @return int Top rank.
-         */
-        public function get_top_rank_toal(){
-            return $this->top_rank_toal;
-        }
+    /**
+     * Retrieves the player's name
+     *
+     * @return string The playe's name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
 
-        /**
-         * Retrieves the Arena defense units.
-         *
-         * @return \Unit[] Units in the arena defense.
-         */
-        public function get_arena_defense(){
-            if (!$this->flag_defense){
-                $this->load_defenses();
-            }
-            return $this->arena_defense;
-        }
+    /**
+     * Retrieves the total experience earned by the user.
+     *
+     * @return int Total experience.
+     */
+    public function get_experience(){
+        return $this->experience;
+    }
 
-        /**
-         * Retrieves the Guild War defenses.
-         *
-         * @return Unit[][]: Units in Guild War defense, grouped by team.
-         */
-        public function get_gw_defense(){
-            if (!$this->flag_defense){
-                $this->load_defenses();
-            }
-            return $this->gw_defense;
+    /**
+     * Retrieves the player's representative unit.
+     *
+     * @return Unit Player's representative
+     */
+    public function get_rep(){
+        if ($this->rep_id != null && $this->rep == null){
+            $this->rep = new Unit($this->rep_id);
         }
+        return $this->rep;
+    }
 
-        /**
-         * Retrieves the Guild War defenses.
-         *
-         * @return Unit[][]: Units in Siege Battle defense, grouped by team.
-         */
-        public function get_siege_defense(){
-            if (!$this->flag_defense){
-                $this->load_defenses();
-            }
-            return $this->siege_defense;
+    /**
+     * Gets the date the user joined the game.
+     *
+     * If $format is supplied, a string in the desired format will be returned. If not, the raw
+     * DateTime object will e returned.
+     *
+     * @param string $format A date format (optional).
+     * @return DateTime | string The raw date, or a formatted version.
+     */
+    public function get_joined($format = null){
+        if (null == $format){
+            return $this->joined;
         }
+        else{
+            return $this->joined->format($format);
+        }
+    }
 
-        /**
-         * Retrieves various currencies.
-         *
-         * @return int[] Array with the keys: mana, crystal, energy, energy_max, arena_energy,
-         * darkportal_energy, dimension_energy, honor_point, guild_point, honor_medal, honor_mark,
-         * event_coin, social_point, ancient_stone, costume_point,
-         */
-        public function get_currencies(){
-            return $this->currency;
+    /**
+     * Retrieves the user's top rank in the Arena.
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_arena(){
+        return $this->top_rank_arena;
+    }
+
+    /**
+     * Retrieves the user's top rank in the WorldArena.
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_world_arena(){
+        return $this->top_rank_world_arena;
+    }
+
+    /**
+     * Retrieves the user's top rank in the Arena.
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_special_league(){
+        return $this->top_rank_special_league;
+    }
+
+    /**
+     * Retrieves the user's top rank in Guild War.
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_gw(){
+        return $this->top_rank_gw;
+    }
+
+    /**
+     * Retrieves the user's top rank in Siege battle.
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_siege(){
+        return $this->top_rank_siege;
+    }
+
+    /**
+     * Retrieves the user's top rank in the World Boss.
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_wboss(){
+        return $this->top_rank_wboss;
+    }
+
+    /**
+     * Retrieves the user's top rank in the Trial of Ascension (normal difficulty).
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_toan(){
+        return $this->top_rank_toan;
+    }
+
+    /**
+     * Retrieves the user's top rank in the Trial of Ascension (hard difficulty).
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_toah(){
+        return $this->top_rank_toah;
+    }
+
+    /**
+     * Retrieves the user's top rank in the Trial of Ascension (hell difficulty).
+     *
+     * @return int Top rank.
+     */
+    public function get_top_rank_toal(){
+        return $this->top_rank_toal;
+    }
+
+    /**
+     * Retrieves the Arena defense units.
+     *
+     * @return \Unit[] Units in the arena defense.
+     */
+    public function get_arena_defense(){
+        if (!$this->flag_defense){
+            $this->load_defenses();
         }
+        return $this->arena_defense;
+    }
 
-        /**
-         * Retrieves the list of buildings owned by the user.
-         *
-         * @return \Building[] Buildings owned.
-         */
-        public function get_buildings(){
-            if (!$this->flag_building){
-                $this->load_buildings();
-            }
-            return $this->building;
+    /**
+     * Retrieves the Guild War defenses.
+     *
+     * @return Unit[][]: Units in Guild War defense, grouped by team.
+     */
+    public function get_gw_defense(){
+        if (!$this->flag_defense){
+            $this->load_defenses();
         }
+        return $this->gw_defense;
+    }
 
-        /**
-         * Retrieves the list of decorations owned by the user.
-         *
-         * @return \Decoration[] Owned decorations.
-         */
-        public function get_decorations(){
-            if (!$this->flag_building){
-                $this->load_buildings();
-            }
-            return $this->decoration;
+    /**
+     * Retrieves the Guild War defenses.
+     *
+     * @return Unit[][]: Units in Siege Battle defense, grouped by team.
+     */
+    public function get_siege_defense(){
+        if (!$this->flag_defense){
+            $this->load_defenses();
         }
+        return $this->siege_defense;
+    }
 
-        /**
-         * Retrieves the list of owned scrolls.
-         *
-         * @return \Item[] Scrolls.
-         */
-        public function get_scrolls(){
-            if (!$this->flag_item){
-                $this->load_items();
-            }
-            return $this->item_scroll;
+    /**
+     * Retrieves various currencies.
+     *
+         * @return int[] Array with the keys: mana, crystal, energy, energy_max, arena_energy,
+     * darkportal_energy, dimension_energy, honor_point, guild_point, honor_medal, honor_mark,
+     * event_coin, social_point, ancient_stone, costume_point,
+     */
+    public function get_currencies(){
+        return $this->currency;
+    }
+
+    /**
+     * Retrieves the list of buildings owned by the user.
+     *
+     * @return \Building[] Buildings owned.
+     */
+    public function get_buildings(){
+        if (!$this->flag_building){
+            $this->load_buildings();
         }
+        return $this->building;
+    }
 
-        /**
-         * Retrieves the list of rune crafting mateials.
-         *
-         * @return \Item[] Rune craft materials.
-         */
-        public function get_rune_craft_materials(){
-            if (!$this->flag_item){
-                $this->load_items();
-            }
-            return $this->item_craft_rune;
+    /**
+     * Retrieves the list of decorations owned by the user.
+     *
+     * @return \Decoration[] Owned decorations.
+     */
+    public function get_decorations(){
+        if (!$this->flag_building){
+            $this->load_buildings();
         }
+        return $this->decoration;
+    }
 
-        /**
-         * Retrieves the list of crafting materials.
-         *
-         * @return \Item[] Crafting materials
-         */
-        public function get_craft_materials(){
-            if (!$this->flag_item){
-                $this->load_items();
-            }
-            return $this->item_craft;
+    /**
+     * Retrieves the list of owned scrolls.
+     *
+     * @return \Item[] Scrolls.
+     */
+    public function get_scrolls(){
+        if (!$this->flag_item){
+            $this->load_items();
         }
+        return $this->item_scroll;
+    }
 
-        /**
-         * Retrieves the list of essences owned by the player.
-         *
-         * @return \Item[] Essences.
-         */
-        public function get_essences(){
-            if (!$this->flag_item){
-                $this->load_items();
-            }
-            return $this->item_essence;
+    /**
+     * Retrieves the list of rune crafting mateials.
+     *
+     * @return \Item[] Rune craft materials.
+     */
+    public function get_rune_craft_materials(){
+        if (!$this->flag_item){
+            $this->load_items();
         }
+        return $this->item_craft_rune;
+    }
 
-        /**
-         * Retrieves the list of the player's records in the logbook.
-         *
-         * @return \Record[] List of records.
-         */
-        public function get_records(){
-            if (!$this->flag_record){
-                $this->load_records();
-            }
-            return $this->record;
+    /**
+     * Retrieves the list of crafting materials.
+     *
+     * @return \Item[] Crafting materials
+     */
+    public function get_craft_materials(){
+        if (!$this->flag_item){
+            $this->load_items();
         }
+        return $this->item_craft;
+    }
 
-        /**
-         * Checks if the player profile is public.
-         *
-         * @return bool True for public profile, false otherwise.
-         */
-        public function is_public(){
-            return $this->public;
+    /**
+     * Retrieves the list of essences owned by the player.
+     *
+     * @return \Item[] Essences.
+     */
+    public function get_essences(){
+        if (!$this->flag_item){
+            $this->load_items();
         }
+        return $this->item_essence;
+    }
 
+    /**
+     * Retrieves the list of the player's records in the logbook.
+     *
+     * @return \Record[] List of records.
+     */
+    public function get_records(){
+        if (!$this->flag_record){
+            $this->load_records();
+        }
+        return $this->record;
+    }
 
+    /**
+     * Checks if the player profile is public.
+     *
+     * @return bool True for public profile, false otherwise.
+     */
+    public function is_public(){
+        return $this->public;
     }
-?>
+
+}

+ 45 - 40
application/entity/Record.php

@@ -4,76 +4,77 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Unit.php");
 require_once(PATH::ENTITY . "Monster.php");
 require_once(PATH::ENTITY . "Area.php");
 
-
 /**
  * A record run.
  *
- * Represents an object from the table 'record'.
+ * Represents the best run in an area, as in the in-game log book.
  *
  * @category Entity
  */
 class Record extends Entity{
-    
+
     /**
      * @var int Player identifier.
      */
-    public $player;
-    
+    private $player;
+
     /**
      * @var Area Area.
      */
-    public $area;
-    
+    private $area;
+
     /**
      * @var int Stage.
      */
     private $stage;
-    
+
     /**
      * @var int Clear time, milliseconds.
      */
     private $time;
-    
+
     /**
      * @var int Score in battles that are rated (WB, rift dungeons...).
      */
     private $score;
-    
+
     /**
      * @var String Rank in battles that are rated (WB, rift dungeons...).
      */
     private $rank;
-    
+
+    /**
+     * @var bool Internal flag to check if the run party has been loaded into the entity.
+     */
     private $flag_party = false;
-    
+
     /**
-     * @var \Unit[]|\Monster[] Units or monsters used.
+     * @var Unit[]|Monster[] Units or monsters used.
      * If the unit is still owned, it will be a instance of Unit.
      * If not, it will be a instance of Monster.
      */
     private $party = [];
-    
+
     /**
      * @var int ID of the leader unit or monster.
      */
     private $leader;
-    
+
     /**
      * @var int[] List of IDs of the frontline units or monsters.
      */
     private $frontline = [];
-    
+
     /**
      * Constructor.
      *
@@ -85,7 +86,7 @@ class Record extends Entity{
      * @param int $area Area identifier.
      */
     public function __construct($player_id, $area_type, $area){
-        
+
         $statement = get_context()->get_db()->prepare("
           SELECT
             player,
@@ -118,7 +119,13 @@ class Record extends Entity{
             }
         }
     }
-    
+
+    /**
+     * Loads the record units into the entity.
+     *
+     * Must be called only once before trying to get the party units, leader or positions. Sets
+     * the flag {@link Record:$flag_party} to true.
+     */
     private function load_party(){
         $statement = get_context()->get_db()->prepare("
           SELECT
@@ -159,18 +166,18 @@ class Record extends Entity{
                     array_push($this->frontline, $r["monster"]);
                 }
             }
-            
+
         }
     }
     /**
      * Retrieves the record holder's player identifier.
      *
-     * @return number Player ID.
+     * @return int Player ID.
      */
     public function get_player(){
         return $this->player;
     }
-    
+
     /**
      * Retrieves the area of the record
      *
@@ -179,34 +186,34 @@ class Record extends Entity{
     public function get_area(){
         return $this->area;
     }
-    
+
     /**
      * Retrieves the stage of the record.
      *
-     * @return number Record stage.
+     * @return int Record stage.
      */
     public function get_stage(){
         return $this->stage;
     }
-    
+
     /**
      * Retrieves the time of the record.
      *
-     * @return number record time, in milliseconds.
+     * @return int record time, in milliseconds.
      */
     public function get_time(){
         return $this->time;
     }
-    
+
     /**
      * Retrieves the score of the record.
      *
-     * @return number Record score. Null if it's not a score based record.
+     * @return int Record score. Null if it's not a score based record.
      */
     public function get_score(){
         return $this->score;
     }
-    
+
     /**
      * Retrieves the rank reached on the record.
      *
@@ -215,7 +222,7 @@ class Record extends Entity{
     public function get_rank(){
         return $this->rank;
     }
-    
+
     /**
      * Retrieves the party used in the record. If one of the units is not still owned, it will get
      * the base monster instead.
@@ -228,12 +235,12 @@ class Record extends Entity{
         }
         return $this->party;
     }
-    
+
     /**
      * Retrieves the party leader identifier. If the leader unit is not still owned, it will get
      * the base monster identifierinstead.
      *
-     * @return number Leader unit or monster ID.
+     * @return int Leader unit or monster ID.
      */
     public function get_leader(){
         if (! $this->flag_party){
@@ -241,12 +248,12 @@ class Record extends Entity{
         }
         return $this->leader;
     }
-    
+
     /**
      * Retrieves the identifiers of the party members in the frontline. If one of the units is not
      * still owned, it will get the base monster instead.
      *
-     * @return number Unit or Monster identifiers.
+     * @return int Unit or Monster identifiers.
      */
     public function get_frontline(){
         if (! $this->flag_party){
@@ -254,7 +261,5 @@ class Record extends Entity{
         }
         return $this->frontline;
     }
-    
-    
+
 }
-?>

+ 494 - 496
application/entity/Run.php

@@ -1,529 +1,527 @@
 <?php
+/**
+ * Saved run entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+require_once(PATH::ENTITY . "Unit.php");
+require_once(PATH::ENTITY . "Monster.php");
+require_once(PATH::ENTITY . "Rune.php");
+require_once(PATH::ENTITY . "Enchantment.php");
+require_once(PATH::ENTITY . "Item.php");
+require_once(PATH::ENTITY . "Area.php");
+require_once(PATH::ENTITY . "Rune_Set.php");
+
+/**
+ * A run.
+ *
+ * Represent a saved run in a playable area.
+ *
+ * @category Entity
+ * @todo Consider artifact drops.
+ * @todo Currently not working, fix.
+ */
+class Run extends Entity{
+
     /**
-     * Saved run entity file.
-     *
-     * Creates the entity and makes it available.
+     * @var int Owner's player identifier.
+     */
+    public $player;
+
+    /**
+     * @var int Run identifier.
+     */
+    public $id;
+
+    /**
+     * @var DateTime Run start datestamp.
+     */
+    public $dtime;
+
+    /**
+     * @var Area Area.
+     */
+    public $area;
+
+    /**
+     * @var int Stage.
+     */
+    public $stage;
+
+    /**
+     * @var int Difficulty (only scenario and dimension hole)
+     */
+    public $difficulty;
+
+    /**
+     * @var bool Win or lost run.
+     */
+    public $win;
+
+    /**
+     * @var int Clear time, milliseconds.
+     */
+    public $time;
+
+    /**
+     * @var int Reward mana.
+     */
+    public $mana = 0;
+
+    /**
+     * @var int Reward energy.
+     */
+    public $energy = 0;
+
+    /**
+     * @var int Reward crystal.
+     */
+    public $crystal = 0;
+
+    /**
+     * @var int Reward Honor Points (Arena).
+     */
+    public $honor_points = 0;
+
+    /**
+     * @var int Reward Guild Points.
+     */
+    public $guild_points = 0;
+
+    /**
+     * @var bool Indicates if a frind/mentor helped.
+     */
+    public $helper;
+
+    /**
+     * @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[]|Monster[] Units or monsters used.
+     * If the unit is still owned, it will be a instance of Unit.
+     * If not, it will be a instance of monster.
+     */
+    public $party = [];
+
+    /**
+     * @var int ID of the leader unit or monster.
+     */
+    public $leader;
+
+    /**
+     * @var int[] List of IDs of the frontline units or monsters.
+     */
+    public $frontline = [];
+
+    /**
+     * @var Item[] Dropped items.
+     */
+    public $item = [];
+
+    /**
+     * @var Monster[] Units dropped.
+     */
+    public $monster = [];
+
+    /**
+     * @var int Monster[] Units whose secret dungeons were found on the run.
+     */
+    public $sd = [];
+
+    /**
+     * @var mixed[] List of dropped summon pieces.
      *
-     * @category Entity
-     * // TODO Artifact drops.
+     * Formated as:
+     *  [@{see Monster}, amount]
      */
+    public $unit_piece = [];
 
     /**
-     * Require dependent entities if not present.
+     * @var int Number of shapeshifting stones dropped;
      */
-    require_once(PATH::ENTITY . "Entity.php");
-    require_once(PATH::ENTITY . "Unit.php");
-    require_once(PATH::ENTITY . "Monster.php");
-    require_once(PATH::ENTITY . "Rune.php");
-    require_once(PATH::ENTITY . "Enchantment.php");
-    require_once(PATH::ENTITY . "Item.php");
-    require_once(PATH::ENTITY . "Area.php");
-    require_once(PATH::ENTITY . "Rune_Set.php");
+    public $shapeshifting = 0;
 
+    /**
+     * @var Rune[] List of Runes dropped.
+     */
+    public $rune = [];
+
+    /**
+     * @var Enchantment[] List of Enchantments dropped.
+     */
+    public $enchantment = [];
 
     /**
-     * A run.
+     * Constructor.
      *
-     * Represents an object from the table 'run'.
+     * Searches the database and retrieves the information about the
+     * run, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Run identifier.
      */
-    class Run extends Entity{
-
-        /**
-         * @var int Owner's player identifier.
-         */
-        public $player;
-
-        /**
-         * @var int Run identifier.
-         */
-        public $id;
-
-        /**
-         * @var DateTime Run start datestamp.
-         */
-        public $dtime;
-
-        /**
-         * @var Area Area.
-         */
-        public $area;
-
-        /**
-         * @var int Stage.
-         */
-        public $stage;
-
-        /**
-         * @var int Difficulty (only scenario and dimension hole)
-         */
-        public $difficulty;
-
-        /**
-         * @var bool Win or lost run.
-         */
-        public $win;
-
-        /**
-         * @var int Clear time, milliseconds.
-         */
-        public $time;
-
-        /**
-         * @var int Reward mana.
-         */
-        public $mana = 0;
-
-        /**
-         * @var int Reward energy.
-         */
-        public $energy = 0;
-
-        /**
-         * @var int Reward crystal.
-         */
-        public $crystal = 0;
-
-        /**
-         * @var int Reward Honor Points (Arena).
-         */
-        public $honor_points = 0;
-
-        /**
-         * @var int Reward Guild Points.
-         */
-        public $guild_points = 0;
-
-        /**
-         * @var bool Indicates if a frind/mentor helped.
-         */
-        public $helper;
-
-        /**
-         * @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[]|\Monster[] Units or monsters used.
-         * If the unit is still owned, it will be a instance of Unit.
-         * If not, it will be a instance of monster.
-         */
-        public $party = [];
-
-        /**
-         * @var int ID of the leader unit or monster.
-         */
-        public $leader;
-
-        /**
-         * @var int[] List of IDs of the frontline units or monsters.
-         */
-        public $frontline = [];
-
-        /**
-         * @var \Item[] Dropped items.
-         */
-        public $item = [];
-
-        /**
-         * @var \Monster[] Units dropped.
-         */
-        public $monster = [];
-
-        /**
-         * @var int Monster[] Units whose secret dungeons were found on the run.
-         */
-        public $sd = [];
-
-        /**
-         * @var mixed[] List of dropped summon pieces.
-         *
-         * Formated as:
-         *  [@{see Monster}, amount]
-         */
-        public $unit_piece = [];
-
-        /**
-         * @var int Number of shapeshifting stones dropped;
-         */
-        public $shapeshifting = 0;
-
-        /**
-         * @var \Rune[] List of Runes dropped.
-         */
-        public $rune = [];
-
-        /**
-         * @var \Enchantment[] List of Enchantments dropped.
-         */
-        public $enchantment = [];
-
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * run, populating it and it's items.
-         *
-         * @param int $id Run identifier.
-         */
-        public function __construct($id){
-
+    public function __construct($id){
+
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            player,
+            dtime,
+            area_type,
+            area,
+            stage,
+            difficulty,
+            win,
+            time,
+            mana,
+            energy,
+            crystal,
+            honor_points,
+            guild_points,
+            helper,
+            score,
+            rank
+          FROM run
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->player = $r["player"];
+            $this->dtime = $r["dtime"];
+            $this->area = new Area($r["area"], $r["area_type"]);
+            $this->stage = $r["stage"];
+            $this->difficulty = $r["difficulty"];
+            $this->win = $r["win"];
+            $this->time = $r["time"];
+            $this->mana = $r["mana"];
+            $this->energy = $r["energy"];
+            $this->crystal = $r["crystal"];
+            $this->honor_points = $r["honor_points"];
+            $this->guild_points = $r["guild_points"];
+            $this->helper = $r["helper"];
+            $this->score = $r["score"];
+            $this->rank = $r["rank"];
             $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                player,
-                dtime,
-                area_type,
-                area,
-                stage,
-                difficulty,
-                win,
-                time,
-                mana,
-                energy,
-                crystal,
-                honor_points,
-                guild_points,
-                helper,
-                score,
-                rank
-              FROM run
-              WHERE id = :id;
+                SELECT
+                  unit,
+                  monster,
+                  (SELECT count(id) FROM unit WHERE unit.id = run_party.unit) AS owned,
+                  leader,
+                  front
+                FROM run_party
+                WHERE run = :run
+                ORDER BY
+                  front DESC,
+                  leader DESC;
+            ");
+            $statement->bindValue(':run', $id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            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 Monster($r["monster"], false));
+                }
+                if ($r["leader"] == 1){
+                    $this->leader = $r["unit"];
+                }
+                if ($r["front"] == 1){
+                    array_push($this->frontline, $r["unit"]);
+                }
+            }
+            $statement = get_context()->get_db()->prepare("
+                SELECT
+                  item,
+                  amount
+                FROM run_drop_item
+                WHERE run = :run;
+            ");
+            $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                $i = new Item($r["item"]);
+                $i->amount =  $r["amount"];
+                array_push($this->item, $i);
+            }
+            $statement = get_context()->get_db()->prepare("
+                SELECT monster
+                FROM run_drop_monster
+                WHERE run = :run;
+            ");
+            $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->monster, new Monster($r["monster"]));
+            }
+            $statement = get_context()->get_db()->prepare("
+                SELECT monster
+                FROM run_drop_sd
+                WHERE run = :run;
+            ");
+            $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->sd, new Monster($r["monster"]));
+            }
+            $statement = get_context()->get_db()->prepare("
+                SELECT
+                  monster,
+                  amount
+                FROM run_drop_monster_pieces
+                WHERE run = :run;
             ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+            $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                $i = [
+                    "monster" => new Monster($r["monster"]),
+                    "amount" => $r["amount"]
+                ];
+                array_push($this->unit_piece, $i);
+            }
+            $statement = get_context()->get_db()->prepare("
+                SELECT amount
+                FROM run_drop_shapeshifting
+                WHERE run = :run;
+            ");
+            $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            $r = $q->fetchArray(SQLITE3_ASSOC);
             if ($r){
-                $this->id = $r["id"];
-                $this->player = $r["player"];
-                $this->dtime = $r["dtime"];
-                $this->area = new Area($r["area"], $r["area_type"]);
-                $this->stage = $r["stage"];
-                $this->difficulty = $r["difficulty"];
-                $this->win = $r["win"];
-                $this->time = $r["time"];
-                $this->mana = $r["mana"];
-                $this->energy = $r["energy"];
-                $this->crystal = $r["crystal"];
-                $this->honor_points = $r["honor_points"];
-                $this->guild_points = $r["guild_points"];
-                $this->helper = $r["helper"];
-                $this->score = $r["score"];
-                $this->rank = $r["rank"];
-                $statement = get_context()->get_db()->prepare("
-                    SELECT
-                      unit,
-                      monster,
-                      (SELECT count(id) FROM unit WHERE unit.id = run_party.unit) AS owned,
-                      leader,
-                      front
-                    FROM run_party
-                    WHERE run = :run
-                    ORDER BY
-                      front DESC,
-                      leader DESC;
-                ");
-                $statement->bindValue(':run', $id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    if ($r["owned"] > 0){
-                        array_push($this->party, new Unit($r["unit"], false));
+                $this->shapeshifting = $r["amount"];
+            }
+            $statement = get_context()->get_db()->prepare("
+                SELECT
+                  id,
+                  type,
+                  slot,
+                  stars,
+                  ancient,
+                  quality,
+                  value,
+                  efficiency,
+                  main_stat,
+                  main_stat_value,
+                  innate_stat,
+                  innate_stat_value,
+                  substat_1,
+                  substat_1_value,
+                  substat_2,
+                  substat_2_value,
+                  substat_3,
+                  substat_3_value,
+                  substat_4,
+                  substat_4_value
+                FROM run_drop_rune
+                WHERE run = :run;
+            ");
+            $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                $rune = new Rune($r["id"]);
+                if (!isset($rune->id)){
+                    $rune->id = $r["id"];
+                    $rune->level = 0;
+                    $rune->assigned_to = null;
+                    $rune->type = new Rune_Set($r["type"]);
+                    $rune->slot = $r["slot"];
+                    $rune->stars = $r["stars"];
+                    $rune->ancient = $r["ancient"];
+                    $rune->quality = $r["quality"];
+                    $rune->original_quality = $r["quality"];
+                    $rune->quality_name = $this->get_rune_quality_name($r["quality"]);
+                    $rune->original_quality_name = $this->get_rune_quality_name($r["quality"]);
+                    $rune->value = $r["value"];
+                    $rune->value = 0;
+                    $rune->efficiency = $r["efficiency"];
+                    // TODO: Calculate?
+                    $rune->max_efficiency = $r["efficiency"];
+                    $rune->main_stat = new Rune_Stat(null, null);
+                    $rune->main_stat->slot = RUNE_STAT_SLOT_ID::MAIN;
+                    $rune->main_stat->stat = $r["main_stat"];
+                    $rune->main_stat->stat_name = $this->get_stat_name($r["main_stat"]);
+                    $rune->main_stat->value = $r["main_stat_value"];
+                    if ($r["innate_stat"] != null){
+                        $rune->innate_stat = new Rune_Stat(null, null);
+                        $rune->innate_stat->slot = RUNE_STAT_SLOT_ID::INNATE;
+                        $rune->innate_stat->stat = $r["innate_stat"];
+                        $rune->innate_stat->stat_name = $this->get_stat_name($r["innate_stat"]);
+                        $rune->innate_stat->value = $r["innate_stat_value"];
                     }
-                    else{
-                        array_push($this->party, new Monster($r["monster"], false));
+                    if ($r["substat_1"] != null){
+                        $substat = new Rune_Stat(null, null);
+                        $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_1;
+                        $substat->stat = $r["substat_1"];
+                        $substat->stat_name = $this->get_stat_name($r["substat_1"]);
+                        $substat->value = $r["substat_1_value"];
+                        array_push($rune->substats, $substat);
                     }
-                    if ($r["leader"] == 1){
-                        $this->leader = $r["unit"];
+                    if ($r["substat_2"] != null){
+                        $substat = new Rune_Stat(null, null);
+                        $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_2;
+                        $substat->stat = $r["substat_2"];
+                        $substat->stat_name = $this->get_stat_name($r["substat_2"]);
+                        $substat->value = $r["substat_2_value"];
+                        array_push($rune->substats, $substat);
                     }
-                    if ($r["front"] == 1){
-                        array_push($this->frontline, $r["unit"]);
+                    if ($r["substat_3"] != null){
+                        $substat = new Rune_Stat(null, null);
+                        $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_3;
+                        $substat->stat = $r["substat_3"];
+                        $substat->stat_name = $this->get_stat_name($r["substat_3"]);
+                        $substat->value = $r["substat_3_value"];
+                        array_push($rune->substats, $substat);
                     }
-                }
-                $statement = get_context()->get_db()->prepare("
-                    SELECT
-                      item,
-                      amount
-                    FROM run_drop_item
-                    WHERE run = :run;
-                ");
-                $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    $i = new Item($r["item"]);
-                    $i->amount =  $r["amount"];
-                    array_push($this->item, $i);
-                }
-                $statement = get_context()->get_db()->prepare("
-                    SELECT monster
-                    FROM run_drop_monster
-                    WHERE run = :run;
-                ");
-                $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    array_push($this->monster, new Monster($r["monster"]));
-                }
-                $statement = get_context()->get_db()->prepare("
-                    SELECT monster
-                    FROM run_drop_sd
-                    WHERE run = :run;
-                ");
-                $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    array_push($this->sd, new Monster($r["monster"]));
-                }
-                $statement = get_context()->get_db()->prepare("
-                    SELECT
-                      monster,
-                      amount
-                    FROM run_drop_monster_pieces
-                    WHERE run = :run;
-                ");
-                $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    $i = [
-                        "monster" => new Monster($r["monster"]),
-                        "amount" => $r["amount"]
-                    ];
-                    array_push($this->unit_piece, $i);
-                }
-                $statement = get_context()->get_db()->prepare("
-                    SELECT amount
-                    FROM run_drop_shapeshifting
-                    WHERE run = :run;
-                ");
-                $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                $r = $q->fetchArray(SQLITE3_ASSOC);
-                if ($r){
-                    $this->shapeshifting = $r["amount"];
-                }
-                $statement = get_context()->get_db()->prepare("
-                    SELECT
-                      id,
-                      type,
-                      slot,
-                      stars,
-                      ancient,
-                      quality,
-                      value,
-                      efficiency,
-                      main_stat,
-                      main_stat_value,
-                      innate_stat,
-                      innate_stat_value,
-                      substat_1,
-                      substat_1_value,
-                      substat_2,
-                      substat_2_value,
-                      substat_3,
-                      substat_3_value,
-                      substat_4,
-                      substat_4_value
-                    FROM run_drop_rune
-                    WHERE run = :run;
-                ");
-                $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    $rune = new Rune($r["id"]);
-                    if (!isset($rune->id)){
-                        $rune->id = $r["id"];
-                        $rune->level = 0;
-                        $rune->assigned_to = null;
-                        $rune->type = new Rune_Set($r["type"]);
-                        $rune->slot = $r["slot"];
-                        $rune->stars = $r["stars"];
-                        $rune->ancient = $r["ancient"];
-                        $rune->quality = $r["quality"];
-                        $rune->original_quality = $r["quality"];
-                        $rune->quality_name = $this->get_rune_quality_name($r["quality"]);
-                        $rune->original_quality_name = $this->get_rune_quality_name($r["quality"]);
-                        $rune->value = $r["value"];
-                        $rune->value = 0;
-                        $rune->efficiency = $r["efficiency"];
-                        // TODO: Calculate?
-                        $rune->max_efficiency = $r["efficiency"];
-                        $rune->main_stat = new Rune_Stat(null, null);
-                        $rune->main_stat->slot = RUNE_STAT_SLOT_ID::MAIN;
-                        $rune->main_stat->stat = $r["main_stat"];
-                        $rune->main_stat->stat_name = $this->get_stat_name($r["main_stat"]);
-                        $rune->main_stat->value = $r["main_stat_value"];
-                        if ($r["innate_stat"] != null){
-                            $rune->innate_stat = new Rune_Stat(null, null);
-                            $rune->innate_stat->slot = RUNE_STAT_SLOT_ID::INNATE;
-                            $rune->innate_stat->stat = $r["innate_stat"];
-                            $rune->innate_stat->stat_name = $this->get_stat_name($r["innate_stat"]);
-                            $rune->innate_stat->value = $r["innate_stat_value"];
-                        }
-                        if ($r["substat_1"] != null){
-                            $substat = new Rune_Stat(null, null);
-                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_1;
-                            $substat->stat = $r["substat_1"];
-                            $substat->stat_name = $this->get_stat_name($r["substat_1"]);
-                            $substat->value = $r["substat_1_value"];
-                            array_push($rune->substats, $substat);
-                        }
-                        if ($r["substat_2"] != null){
-                            $substat = new Rune_Stat(null, null);
-                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_2;
-                            $substat->stat = $r["substat_2"];
-                            $substat->stat_name = $this->get_stat_name($r["substat_2"]);
-                            $substat->value = $r["substat_2_value"];
-                            array_push($rune->substats, $substat);
-                        }
-                        if ($r["substat_3"] != null){
-                            $substat = new Rune_Stat(null, null);
-                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_3;
-                            $substat->stat = $r["substat_3"];
-                            $substat->stat_name = $this->get_stat_name($r["substat_3"]);
-                            $substat->value = $r["substat_3_value"];
-                            array_push($rune->substats, $substat);
-                        }
-                        if ($r["substat_4"] != null){
-                            $substat = new Rune_Stat(null, null);
-                            $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_4;
-                            $substat->stat = $r["substat_4"];
-                            $substat->stat_name = $this->get_stat_name($r["substat_4"]);
-                            $substat->value = $r["substat_4_value"];
-                            array_push($rune->substats, $substat);
-                        }
+                    if ($r["substat_4"] != null){
+                        $substat = new Rune_Stat(null, null);
+                        $substat->slot = RUNE_STAT_SLOT_ID::SUBSTAT_4;
+                        $substat->stat = $r["substat_4"];
+                        $substat->stat_name = $this->get_stat_name($r["substat_4"]);
+                        $substat->value = $r["substat_4_value"];
+                        array_push($rune->substats, $substat);
                     }
-                    array_push($this->rune, $rune);
                 }
-                $statement = get_context()->get_db()->prepare("
-                  SELECT
-                    run_drop_enchantment.id AS id,
-                    type,
-                    run_drop_enchantment.quality AS quality,
-                    rune,
-                    run_drop_enchantment.stat AS stat,
-                    value,
-                    enchantment_type.inmemorial AS inmemorial,
-                    enchantment_type.ancient AS ancient,
-                    enchantment_range.min AS min,
-                    enchantment_range.max AS max
-                  FROM
-                    run_drop_enchantment,
-                    enchantment_type,
-                    enchantment_range
-                  WHERE
-                    run = :run AND
-                    run_drop_enchantment.type = enchantment_type.id AND
-                    enchantment_type.gem = enchantment_range.gem AND
-                    enchantment_type.gem = enchantment_range.gem AND
-                    enchantment_type.ancient = enchantment_range.ancient AND
-                    run_drop_enchantment.quality = enchantment_range.quality AND
-                    run_drop_enchantment.stat = enchantment_range.stat;
-                ");
-                $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
-                $q = $statement->execute();
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    $enchantment = new Enchantment($r["id"]);
-                    if (!isset($enchantment->id)){
-                        $enchantment->id = $r["id"];
-                        if ($r["type"] == CRAFT_ID::ENCHANT_GEM || $r["type"] == CRAFT_ID::IMMEMORIAL_GEM){
-                                $enchantment->gem = 1;
-                        }
-                        else{
-                                $enchantment->gem = 0;
-                        }
-                        $enchantment->quality = $r["quality"];
-                        $enchantment->value = 0;
-                        $enchantment->stat = $r["stat"];
-                        $enchantment->ancient = $r["ancient"];
-                        $enchantment->inmemorial = $r["inmemorial"];
-                        $enchantment->rune = new Rune_Set($r["rune"]);
-                        $enchantment->min = $r["min"];
-                        $enchantment->max = $r["max"];
-                        $enchantment->value = $r["value"];
-                        $enchantment->amount = 0;
-                        $enchantment->refresh_names();
+                array_push($this->rune, $rune);
+            }
+            $statement = get_context()->get_db()->prepare("
+              SELECT
+                run_drop_enchantment.id AS id,
+                type,
+                run_drop_enchantment.quality AS quality,
+                rune,
+                run_drop_enchantment.stat AS stat,
+                value,
+                enchantment_type.inmemorial AS inmemorial,
+                enchantment_type.ancient AS ancient,
+                enchantment_range.min AS min,
+                enchantment_range.max AS max
+              FROM
+                run_drop_enchantment,
+                enchantment_type,
+                enchantment_range
+              WHERE
+                run = :run AND
+                run_drop_enchantment.type = enchantment_type.id AND
+                enchantment_type.gem = enchantment_range.gem AND
+                enchantment_type.gem = enchantment_range.gem AND
+                enchantment_type.ancient = enchantment_range.ancient AND
+                run_drop_enchantment.quality = enchantment_range.quality AND
+                run_drop_enchantment.stat = enchantment_range.stat;
+            ");
+            $statement->bindValue(':run', $this->id, SQLITE3_TEXT);
+            $q = $statement->execute();
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                $enchantment = new Enchantment($r["id"]);
+                if (!isset($enchantment->id)){
+                    $enchantment->id = $r["id"];
+                    if ($r["type"] == CRAFT_ID::ENCHANT_GEM || $r["type"] == CRAFT_ID::IMMEMORIAL_GEM){
+                            $enchantment->gem = 1;
                     }
                     else{
-                        $enchantment->amount = 0;
+                            $enchantment->gem = 0;
                     }
-                    array_push($this->enchantment, $enchantment);
+                    $enchantment->quality = $r["quality"];
+                    $enchantment->value = 0;
+                    $enchantment->stat = $r["stat"];
+                    $enchantment->ancient = $r["ancient"];
+                    $enchantment->inmemorial = $r["inmemorial"];
+                    $enchantment->rune = new Rune_Set($r["rune"]);
+                    $enchantment->min = $r["min"];
+                    $enchantment->max = $r["max"];
+                    $enchantment->value = $r["value"];
+                    $enchantment->amount = 0;
+                    $enchantment->refresh_names();
                 }
+                else{
+                    $enchantment->amount = 0;
+                }
+                array_push($this->enchantment, $enchantment);
             }
         }
+    }
 
-        /**
-         * Gets a quality name frm the mappings.
-         *
-         * @param int $quality Quality id.
-         * @return string Quality name (Uppercase)
-         */
-        private function get_rune_quality_name($quality){
-            switch ($quality){
-                case QUALITY_ID::NORMAL:
-                    return "NORMAL";
-                case QUALITY_ID::MAGIC:
-                    return "MAGIC";
-                case QUALITY_ID::RARE:
-                    return "RARE";
-                case QUALITY_ID::HERO:
-                    return "HERO";
-                case QUALITY_ID::LEGEND:
-                    return "LEGEND";
-                default:
-                    return "";
-            }
+    /**
+     * Gets a quality name frm the mappings.
+     *
+     * @param int $quality Quality id.
+     * @return string Quality name (Uppercase)
+     */
+    private function get_rune_quality_name($quality){
+        switch ($quality){
+            case QUALITY_ID::NORMAL:
+                return "NORMAL";
+            case QUALITY_ID::MAGIC:
+                return "MAGIC";
+            case QUALITY_ID::RARE:
+                return "RARE";
+            case QUALITY_ID::HERO:
+                return "HERO";
+            case QUALITY_ID::LEGEND:
+                return "LEGEND";
+            default:
+                return "";
         }
+    }
 
-        /**
-         * Gets a stat name from the mappings.
-         *
-         * @param int $stat Stat id.
-         * @return string Stat name (Uppercase)
-         */
-        private function get_stat_name($stat){
-            switch ($stat){
-                case RUNE_STAT_ID::HP:
-                    return "HP";
-                    break;
-                case RUNE_STAT_ID::HP_P:
-                    return "HP%";
-                    break;
-                case RUNE_STAT_ID::ATK:
-                    return "ATK";
-                    break;
-                case RUNE_STAT_ID::ATK_P:
-                    return "ATK%";
-                    break;
-                case RUNE_STAT_ID::DEF:
-                    return "DEF";
-                    break;
-                case RUNE_STAT_ID::DEF_P:
-                    return "DEF%";
-                    break;
-                case RUNE_STAT_ID::SPD:
-                    return "SPD";
-                    break;
-                case RUNE_STAT_ID::CRR:
-                    return "CRR";
-                    break;
-                case RUNE_STAT_ID::CRD:
-                    return "CRD";
-                    break;
-                case RUNE_STAT_ID::RES:
-                    return "RES";
-                    break;
-                case RUNE_STAT_ID::ACC:
-                    return "ACC";
-                    break;
-                default:
-                    return "";
-            }
+    /**
+     * Gets a stat name from the mappings.
+     *
+     * @param int $stat Stat id.
+     * @return string Stat name (Uppercase)
+     */
+    private function get_stat_name($stat){
+        switch ($stat){
+            case RUNE_STAT_ID::HP:
+                return "HP";
+                break;
+            case RUNE_STAT_ID::HP_P:
+                return "HP%";
+                break;
+            case RUNE_STAT_ID::ATK:
+                return "ATK";
+                break;
+            case RUNE_STAT_ID::ATK_P:
+                return "ATK%";
+                break;
+            case RUNE_STAT_ID::DEF:
+                return "DEF";
+                break;
+            case RUNE_STAT_ID::DEF_P:
+                return "DEF%";
+                break;
+            case RUNE_STAT_ID::SPD:
+                return "SPD";
+                break;
+            case RUNE_STAT_ID::CRR:
+                return "CRR";
+                break;
+            case RUNE_STAT_ID::CRD:
+                return "CRD";
+                break;
+            case RUNE_STAT_ID::RES:
+                return "RES";
+                break;
+            case RUNE_STAT_ID::ACC:
+                return "ACC";
+                break;
+            default:
+                return "";
         }
-
     }
-?>
+
+}

+ 113 - 96
application/entity/Rune.php

@@ -4,12 +4,11 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Rune_Set.php");
 require_once(PATH::ENTITY . "Rune_Stat.php");
@@ -17,113 +16,120 @@ require_once(PATH::ENTITY . "Rune_Stat.php");
 /**
  * Owned rune.
  *
- * Represents an object from the table 'rune'.
+ * Represents a rune.
  *
  * @category Entity
  */
 class Rune extends Entity{
-    
+
     /**
      * @var int Owner identifier.
      */
     private $player;
-    
+
     /**
      * @var int Rune identifier.
      */
     private $id;
-    
+
     /**
      * @var Rune_Set Rune set.
      */
     private $type;
-    
+
     /**
      * @var int Position of the rune type (1-6).
      */
     private $slot;
-    
+
     /**
      * @var int Rune stars.
      */
     private $stars;
-    
+
     /**
      * @var bool Indicates if the rune is ancient.
      */
     private $ancient;
-    
+
     /**
      * @var int Level of the rune.
      */
     private $level;
-    
+
     /**
      * @var int Rune quality.
-     *
      * @see QUALITY_ID
      */
     private $quality;
-    
+
     /**
      * @var int Rune original quality.
-     *
      * @see QUALITY_ID
      */
     private $original_quality;
-    
+
     /**
      * @var string Rune quality name (uppercase).
      */
     private $quality_name;
-    
+
     /**
      * @var string Rune original quality name (uppercase).
      */
     private $original_quality_name;
-    
+
     /**
      * @var int Price of the rune.
      */
     private $value;
-    
+
     /**
      * @var float Current efficiency of the rune.
      */
     private $efficiency;
-    
+
     /**
      * @var float Maximum potential efficiency of the rune.
      */
     private $max_efficiency;
-    
+
     /**
      * @var int Indicates if the rune is locked.
      */
     private $locked;
-    private $flag_stats;
+
+    /**
+     * @var bool Internal flag to check if the rune stats have been loaded into the entity.
+     */
+    private $flag_stats = false;
     /**
      * @var Rune_Stat Main stat of the rune.
      */
     private $main_stat;
-    
+
     /**
      * @var Rune_Stat Extra stat of the rune.
      */
     private $innate_stat;
-    
+
     /**
-     * @var \Rune_Stat[] Substats of the rune.
+     * @var Rune_Stat[] Substats of the rune.
      */
     private $substats = [];
-    
+
     /**
-     * @var \Rune_Stat[] All stats.
+     * @var Rune_Stat[] All stats.
      *
      * Includes main, innate and substats
      */
     private $stats = [];
-    
+
+    /**
+     * @var bool Internal flag to check if the unit who equips the rune has been loaded.
+     */
+    private $flag_unit = false;
+
     /**
      * @var Unit Unit the rune is assigned to.
      */
@@ -138,24 +144,24 @@ class Rune extends Entity{
      * @param int $id Rune id.
      */
     public function __construct($id){
-        
+
         $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                type,
-                slot,
-                stars,
-                level,
-                ancient,
-                quality,
-                original_quality,
-                value,
-                efficiency,
-                max_efficiency,
-                locked
-              FROM rune
-              WHERE id = :id;
-            ");
+          SELECT
+            id,
+            type,
+            slot,
+            stars,
+            level,
+            ancient,
+            quality,
+            original_quality,
+            value,
+            efficiency,
+            max_efficiency,
+            locked
+          FROM rune
+          WHERE id = :id;
+        ");
         $statement->bindValue(':id', $id, SQLITE3_TEXT);
         $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
         if ($r){
@@ -171,21 +177,21 @@ class Rune extends Entity{
             $this->efficiency = $r["efficiency"];
             $this->max_efficiency = $r["max_efficiency"];
             $this->locked = filter_var($r["locked"], FILTER_VALIDATE_BOOLEAN);
-            
+
             $this->quality_name = $this->map_quality_name($this->quality);
             $this->original_quality_name = $this->map_quality_name($this->original_quality);
-            
+
             // Read efficiencies. If not set in DB, calculate and update.
             if ($this->efficiency == null || $this->efficiency == "" || intval($this->efficiency) == 0){
                 $this->efficiency = $this->calculate_efficiency();
                 $this->max_efficiency = $this->calculate_maximum_efficiency();
                 $statement = get_context()->get_db()->prepare("
-                      UPDATE rune
-                      SET
-                        efficiency = :efficiency,
-                        max_efficiency = :max_efficiency
-                      WHERE id = :rune
-                    ");
+                  UPDATE rune
+                  SET
+                    efficiency = :efficiency,
+                    max_efficiency = :max_efficiency
+                  WHERE id = :rune
+                ");
                 $statement->bindValue(':efficiency', $this->efficiency, SQLITE3_FLOAT);
                 $statement->bindValue(':max_efficiency', $this->max_efficiency, SQLITE3_FLOAT);
                 $statement->bindValue(':rune', $this->id, SQLITE3_INTEGER);
@@ -193,7 +199,13 @@ class Rune extends Entity{
             }
         }
     }
-    
+
+    /**
+     * Loads the stats.
+     *
+     * Must be called only once before trying to get any of the stats (main, innate or subs) or
+     * efficiencies. Sets the flag {@link Rune:$flag_stats} to true.
+     */
     private function load_stats(){
         $statement = get_context()->get_db()->prepare("
           SELECT slot
@@ -220,7 +232,13 @@ class Rune extends Entity{
         }
         $this->flag_stats = true;
     }
-    
+
+    /**
+     * Loads the unit into the entity.
+     *
+     * Must be called only once before trying to get the unit. Sets the flag
+     * {@link Rune:$flag_unit} to true.
+     */
     private function load_unit(){
         $statement = get_context()->get_db()->prepare("
           SELECT unit
@@ -237,25 +255,25 @@ class Rune extends Entity{
         }
         $this->flag_unit = true;
     }
-    
+
     /**
      * Retrieves the owner's player identifier.
      *
-     * @return number Player ID.
+     * @return int Player ID.
      */
     public function get_player(){
         return $this->player;
     }
-    
+
     /**
      * Retrieves the rune identifier.
      *
-     * @return number Rune ID.
+     * @return int Rune ID.
      */
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the rune set.
      *
@@ -264,65 +282,65 @@ class Rune extends Entity{
     public function get_set(){
         return $this->type;
     }
-    
+
     /**
      * Retrieves the rune slot.
      * 
-     * @return number Rune slot (1-6).
+     * @return int Rune slot (1-6).
      */
     public function get_slot(){
         return $this->slot;
     }
-    
+
     /**
      * Retrieves the rune stars (the grade).
      *
-     * @return number Rune stars (1-6).
+     * @return int Rune stars (1-6).
      */
     public function get_stars(){
         return $this->stars;
     }
-    
+
     /**
      * Checks if it's an ancient rune.
      *
-     * @return boolean True for ancient, false for normal.
+      * @return bool True for ancient, false for normal.
      */
     public function is_ancient(){
         return $this->ancient;
     }
-    
+
     /**
      * Retrieves the rune level
      *
-     * @return number Rune level (0-15).
+     * @return int Rune level (0-15).
      */
     public function get_level(){
         return $this->level;
     }
-    
+
     /**
      * Retrieves the rune quality identifier.
      * 
      * @see QUALITY_ID
      *
-     * @return number Quality identifier.
+     * @return int Quality identifier.
      */
     public function get_quality(){
         return $this->quality;
     }
-    
+
     /**
      * Retrieves the rune original quality identifier.
      * 
      * @see QUALITY_ID
      *
-     * @return number Original quality identifier.
+     * @return int Original quality identifier.
      */
     public function get_original_quality(){
         return $this->original_quality;
     }
-    
+
     /**
      * Retrieves the rune quality name.
      *
@@ -331,7 +349,7 @@ class Rune extends Entity{
     public function get_quality_name(){
         return $this->quality_name;
     }
-    
+
     /**
      * Retrieves the rune original quality name.
      *
@@ -340,34 +358,34 @@ class Rune extends Entity{
     public function get_original_quality_name(){
         return $this->original_quality_name;
     }
-    
+
     /**
      * Retrieves the rune value.
      *
-     * @return number Rune value in mana stones.
+     * @return int Rune value in mana stones.
      */
     public function get_value(){
         return $this->value;
     }
-    
+
     /**
      * Retrieves the rune efficiency.
      *
-     * @return number Rune efficiency (0-100)
+     * @return int Rune efficiency (0-100)
      */
     public function get_efficiency(){
         return $this->efficiency;
     }
-    
+
     /**
      * Retrieves the rune efficiency.
      *
-     * @return number Rune efficiency (0-100)
+     * @return int Rune efficiency (0-100)
      */
     public function get_max_efficiency(){
         return $this->max_efficiency;
     }
-    
+
     /**
      * Checks if the rune is locked.
      *
@@ -376,7 +394,7 @@ class Rune extends Entity{
     public function is_locked(){
         return $this->locked;
     }
-    
+
     /**
      * Retrieves the rune main_stat.
      *
@@ -388,7 +406,7 @@ class Rune extends Entity{
         }
         return $this->main_stat;
     }
-    
+
     /**
      * Retrieves the rune innate stat.
      *
@@ -400,7 +418,7 @@ class Rune extends Entity{
         }
         return $this->innate_stat;
     }
-    
+
     /**
      * Retrieves as many substats as the rune has, sorted.
      *
@@ -412,7 +430,7 @@ class Rune extends Entity{
         }
         return $this->substats;
     }
-    
+
     /**
      * Retrieves all the rune stats, including main, innate and substats, in an unsorted array.
      *
@@ -424,7 +442,7 @@ class Rune extends Entity{
         }
         return $this->stats;
     }
-    
+
     /**
      * Retrieves the unit that has equipped the rune in the current game mode.
      *
@@ -436,7 +454,7 @@ class Rune extends Entity{
         }
         return $this->unit;
     }
-    
+
     /**
      * Gets the value of the main stat at an arbitrary level.
      *
@@ -475,7 +493,7 @@ class Rune extends Entity{
                 return 0;
         }
     }
-    
+
     /**
      * Gets a stat name frm the mappings.
      *
@@ -498,7 +516,7 @@ class Rune extends Entity{
                 return "";
         }
     }
-    
+
     /**
      * Calcuates the efficiency of the rune.
      *
@@ -506,7 +524,7 @@ class Rune extends Entity{
      */
     private function calculate_efficiency(){
         $eff = [0.0, 0.0, 0.0, 0.0, 0.0];
-        
+
         $query = "
               SELECT
                 min,
@@ -522,7 +540,7 @@ class Rune extends Entity{
                 rune_stat_roll.stars = :stars AND
                 rune_stat_roll.stat = :stat
               ";
-        
+
         // Fixed stat
         if ($this->innate_stat != null && $this->innate_stat->get_value() > 0){
             $value = $this->innate_stat->get_value();
@@ -573,11 +591,11 @@ class Rune extends Entity{
         $efficiency *= 100;
         return $efficiency;
     }
-    
+
     /**
      * Calcuates the maximum efficiency of the rune.
      *
-     * @return float Efficiency
+     * @return float Max efficiency
      */
     private function calculate_maximum_efficiency(){
         $max_efficiency = $this->efficiency;
@@ -595,6 +613,5 @@ class Rune extends Entity{
         }
         return $max_efficiency;
     }
-    
+
 }
-?>

+ 17 - 19
application/entity/Rune_Set.php

@@ -4,43 +4,42 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 
 /**
  * A rune set.
  *
- * Represents an object from the table 'rune_set'.
+ * Represents an in-game available rune sets.
  *
  * @category Entity
  */
 class Rune_Set extends Entity{
-    
+
     /**
      * @var int Set identifier.
      */
     private $id;
-    
+
     /**
      * @var string Set name.
      */
     private $name;
-    
+
     /**
      * @var int Required number of runes to activate the set.
      */
     private $amount;
-    
+
     /**
      * @var string Set description.
      */
     private $description;
-    
+
     /**
      * Constructor.
      *
@@ -50,7 +49,7 @@ class Rune_Set extends Entity{
      * @param int $id Set identifier.
      */
     public function __construct($id){
-        
+
         $statement = get_context()->get_db()->prepare("
           SELECT
             id,
@@ -69,16 +68,16 @@ class Rune_Set extends Entity{
             $this->description = HTML::e($r["description"]);
         }
     }
-    
+
     /**
      * Retrieves the set identifier
      *
-     * @return number Rune set ID.
+     * @return int Rune set ID.
      */
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the set name.
      *
@@ -87,16 +86,16 @@ class Rune_Set extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the amount of runes required to complete a set.
      *
-     * @return number Number of runes in the set (2|4).
+     * @return int Number of runes in the set (2|4).
      */
     public function get_amount(){
         return $this->amount;
     }
-    
+
     /**
      * Retrieves the set description.
      *
@@ -105,7 +104,7 @@ class Rune_Set extends Entity{
     public function get_description(){
         return $this->description;
     }
-    
+
     /**
      * Gets the path to the set image. 
      *
@@ -115,4 +114,3 @@ class Rune_Set extends Entity{
         return APPLICATION::img("RUNE", $this->id);
     }
 }
-?>

+ 73 - 78
application/entity/Rune_Stat.php

@@ -4,115 +4,54 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 
 /**
  * Rune_stat.
  *
- * Represents an object from the table 'rune_stat'.
+ * Represents any of the stats of a rune.
  *
  * @category Entity
  */
 class Rune_Stat extends Entity{
-    
+
     /**
      * @var int Stat slot.
-     *
      * @see RUNE_STAT_SLOT_ID
      */
     private $slot;
-    
+
     /**
-     * @var int Substat 1 of the rune.
-     *
+     * @var int Substat type.
      * @see RUNE_STAT_ID
      */
     private $stat;
-    
+
     /**
-     * @var string Substat 1 name (uppercase).
+     * @var string Substat name (uppercase).
      */
     private $stat_name = "";
-    
+
     /**
-     * @var int Substat 1 value of the rune.
+     * @var int Substat value.
      */
     private $value;
-    
+
     /**
-     * @var int Ammount gained by the substat 1 enchant.
+     * @var int Grinded value of the stat.
      */
     private $grind;
-    
+
     /**
      * @var bool Indicates if a gem has been used.
      */
     private $enchant;
-    
-    /**
-     * Retrieves the slot of the stat.
-     *
-     * @see RUNE_STAT_SLOT_ID
-     *
-     * @return number Slot number.
-     */
-    public function get_slot(){
-        return $this->slot;
-    }
-    
-    /**
-     * Retrieves the stat identifier.
-     * 
-     * @see RUNE_STAT_ID
-     *
-     * @return number Stat ID.
-     */
-    public function get_stat(){
-        return $this->stat;
-    }
-    
-    /**
-     * Retrieves the stat name.
-     *
-     * @return string Stat name.
-     */
-    public function get_stat_name(){
-        return $this->stat_name;
-    }
-    
-    /**
-     * Retrieves the stat value, without grinds.
-     *
-     * @return number Stat value.
-     */
-    public function get_value(){
-        return $this->value;
-    }
-    
-    /**
-     * Retrieves the grinded value of the stat.
-     *
-     * @return number Grinded value.
-     */
-    public function get_grind(){
-        return $this->grind;
-    }
-    
-    /**
-     * Checks if the stat has been changed by gems.
-     *
-     * @return bool True if the stat was enchanted, false otherwise.
-     */
-    public function is_enchanted(){
-        return $this->enchant;
-    }
-    
+
     /**
      * Constructor.
      *
@@ -122,7 +61,7 @@ class Rune_Stat extends Entity{
      * @param int $id Rune id.
      */
     public function __construct($rune, $slot){
-        
+
         $statement = get_context()->get_db()->prepare("
               SELECT
                 slot,
@@ -186,6 +125,62 @@ class Rune_Stat extends Entity{
             }
         }
     }
-    
+
+    /**
+     * Retrieves the slot of the stat.
+     *
+     * @see RUNE_STAT_SLOT_ID
+     * @return int Slot number.
+     */
+    public function get_slot(){
+        return $this->slot;
+    }
+
+    /**
+     * Retrieves the stat identifier.
+     *
+     * @see RUNE_STAT_ID
+     * @return int Stat ID.
+     */
+    public function get_stat(){
+        return $this->stat;
+    }
+
+    /**
+     * Retrieves the stat name.
+     *
+     * @return string Stat name.
+     */
+    public function get_stat_name(){
+        return $this->stat_name;
+    }
+
+    /**
+     * Retrieves the stat value, without grinds.
+     *
+     * @return int Stat value.
+     */
+    public function get_value(){
+        return $this->value;
+    }
+
+    /**
+     * Retrieves the grinded value of the stat.
+     *
+     * @return int Grinded value.
+     */
+    public function get_grind(){
+        return $this->grind;
+    }
+
+    /**
+     * Checks if the stat has been changed by gems.
+     *
+     * @return bool True if the stat was enchanted, false otherwise.
+     */
+    public function is_enchanted(){
+        return $this->enchant;
+    }
+
 }
 ?>

+ 61 - 63
application/entity/Server.php

@@ -1,77 +1,75 @@
 <?php
+/**
+ * Game Server entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Game Server.
+ *
+ * Represent a game server for an account
+ *
+ * @category Entity
+ */
+class Server extends Entity{
+
     /**
-     * Game Server key entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Server identifier.
      */
+    private $id;
 
     /**
-     * Require dependent entities if not present.
+     * @var string Server name.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $name;
 
     /**
-     * Game Server.
+     * Constructor.
      *
-     * Represents an object from the table 'server'.
+     * Searches the database and retrieves the information about the
+     * server, populating it and it's items.
      *
-     * @category Entity
+     * @param int $id Server identifier.
      */
-    class Server extends Entity{
+    public function __construct($id){
 
-        /**
-         * @var int Server identifier.
-         */
-        public $id;
-
-        /**
-         * @var string Server name.
-         */
-        public $name;
-
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * server, populating it and it's items.
-         *
-         * @param int $id Server identifier.
-         */
-        public function __construct($id){
-
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                name
-              FROM server
-              WHERE id = :id;
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->id = $r["id"];
-                $this->name = HTML::e($r["name"]);
-            }
-        }
-        /**
-         * Retrieves the server identifier.
-         *
-         * @return number Server ID.
-         */
-        public function get_id(){
-            return $this->id;
-        }
-    
-        /**
-         * Retrieves the server name name.
-         *
-         * @return string Server name.
-         */
-        public function get_name(){
-            return $this->name;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            id,
+            name
+          FROM server
+          WHERE id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->id = $r["id"];
+            $this->name = HTML::e($r["name"]);
         }
-    
     }
-?>
+    /**
+     * Retrieves the server identifier.
+     *
+     * @return int Server ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Retrieves the server name name.
+     *
+     * @return string Server name.
+     */
+    public function get_name(){
+        return $this->name;
+    }
+
+}

+ 63 - 47
application/entity/Skill.php

@@ -4,93 +4,98 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Skill_Level.php");
 require_once(PATH::ENTITY . "Effect.php");
 
-
 /**
  * Monster skill.
  *
- * Represents an object from the table 'skill'.
+ * Represents a monster skill.
  *
  * @category Entity
  */
 class Skill extends Entity{
-    
+
     /**
      * @var int Skill identifier.
      */
     private $id;
-    
+
     /**
      * @var string Skill name.
      */
     private $name;
-    
+
     /**
      * @var string Skill description.
      */
     private $description;
-    
+
     /**
      * @var int Skill order.
      */
     private $slot;
-    
+
     /**
      * @var int Skill cooldown turns.
      */
     private $cooltime;
-    
+
     /**
      * @var int Number of hits.
      */
     private $hits;
-    
+
     /**
      * @var bool Wether the skill is passive or not.
      */
     private $passive;
-    
+
     /**
      * @var bool Wether the skill is AOE.
      */
     private $aoe;
-    
+
     /**
      * @var int Skill max level.
      */
     private $max_level;
-    
+
     /**
      * @var string Skill formula.
      */
     private $multiplier_formula;
-    
+
     /**
      * @var Skill The skill upgrading this one.
      */
     private $upgrade;
-    
+
+    /**
+     * @var bool Internal flag to check if the levels have been loaded into the entity.
+     */
     private $flag_levels = false;
+
     /**
-     * @var \Skill_Level[] Available skill levels.
+     * @var Skill_Level[] Available skill levels.
      */
     private $level = [];
-    
+
+    /**
+     * @var bool Internal flag to check if the skill effects have been loaded into the entity.
+     */
     private $flag_effects = false;
     /**
-     * @var \Effect[] Associated eeffects.
+     * @var Effect[] Associated eeffects.
      */
     private $effect = [];
-    
+
     /**
      * Constructor.
      *
@@ -100,7 +105,7 @@ class Skill extends Entity{
      * @param int $id Skill identifier.
      */
     public function __construct($id){
-        
+
         $statement = get_context()->get_db()->prepare("
           SELECT
             id,
@@ -131,7 +136,13 @@ class Skill extends Entity{
             $this->multiplier_formula = HTML::e($r["multiplier_formula"]);
         }
     }
-    
+
+    /**
+     * Loads the levels into the entity.
+     *
+     * Must be called only once before trying to access the levels. Sets the flag
+     * {@link Skill:$flag_levels} to true.
+     */
     private function load_levels(){
         $statement = get_context()->get_db()->prepare("
           SELECT
@@ -148,7 +159,13 @@ class Skill extends Entity{
         }
         $this->flag_levels = true;
     }
-    
+
+    /**
+     * Loads the effects into the entity.
+     *
+     * Must be called only once before trying to access the effects. Sets the flag
+     * {@link Skill:$flag_effects} to true.
+     */
     private function load_effects(){
         $statement = get_context()->get_db()->prepare("
           SELECT DISTINCT effect
@@ -162,16 +179,16 @@ class Skill extends Entity{
         }
         $this->flag_effects = true;
     }
-    
+
     /**
      * Retrieves the skill identifier.
      *
-     * @return number Skill id.
+     * @return int Skill id.
      */
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the skill name.
      *
@@ -180,7 +197,7 @@ class Skill extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the skill description.
      *
@@ -189,61 +206,61 @@ class Skill extends Entity{
     public function get_description(){
         return $this->description;
     }
-    
+
     /**
      * Retrieves the skill slot.
      *
-     * @return number The skill slot (1-4);
+     * @return int The skill slot (1-4);
      */
     public function get_slot(){
         return $this->slot;
     }
-    
+
     /**
      * Retrieves the skill cooldown time
      *
-     * @return number Skill cooltime.
+     * @return int Skill cooltime.
      */
     public function get_cooltime(){
         return $this->cooltime;
     }
-    
+
     /**
      * Retrieves the number of times the skill hist.
      *
-     * @return number Number of hits.
+     * @return int Number of hits.
      */
     public function get_hits(){
         return $this->hits;
     }
-    
+
     /**
      * Checks if the skill is passive.
      *
-     * @return boolean True for passive skills, false for active.
+     * @return bool True for passive skills, false for active.
      */
     public function is_passive(){
         return $this->passive;
     }
-    
+
     /**
      * Checks if the skills affects a group instead of a unit.
      *
-     * @return boolean True for AOE skills, false for single-target skills.
+     * @return bool True for AOE skills, false for single-target skills.
      */
     public function is_aoe(){
         return $this->aoe;
     }
-    
+
     /**
      * Retrieves the maximum level of the skill.
      *
-     * @return number Skill max level.
+     * @return int Skill max level.
      */
     public function get_max_level(){
         return $this->max_level;
     }
-    
+
     /**
      * Retrieves the skills mathematical formula.
      *
@@ -252,7 +269,7 @@ class Skill extends Entity{
     public function get_multiplier_formula(){
         return $this->multiplier_formula;
     }
-    
+
     /**
      * Retrieves the skill this one upgrades to (ie, on awakening).
      *
@@ -261,7 +278,7 @@ class Skill extends Entity{
     public function get_upgrade(){
         return $this->upgrade;
     }
-    
+
     /**
      * Retrieves information about the skill levels.
      *
@@ -273,7 +290,7 @@ class Skill extends Entity{
         }
         return $this->level;
     }
-    
+
     /**
      * Retrieves the effects caused by the skill.
      *
@@ -285,7 +302,7 @@ class Skill extends Entity{
         }
         return $this->effect;
     }
-    
+
     /**
      * Gets the path to the skill image. 
      *
@@ -295,4 +312,3 @@ class Skill extends Entity{
         return APPLICATION::img("SKILL", $this->id);
     }
 }
-?>

+ 79 - 81
application/entity/Skill_Level.php

@@ -1,97 +1,95 @@
 <?php
+/**
+ * Skill level entity file.
+ *
+ * Creates the entity and makes it available.
+ *
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
+ */
+
+require_once(PATH::ENTITY . "Entity.php");
+
+/**
+ * Monster skill level.
+ *
+ * Represents an upgrade of a skill
+ *
+ * @category Entity
+ */
+class Skill_Level extends Entity{
+
     /**
-     * Skill level entity file.
-     *
-     * Creates the entity and makes it available.
-     *
-     * @category Entity
+     * @var int Skill identifier.
      */
+    private $skill;
 
     /**
-     * Require dependent entities if not present.
+     * @var int Skill level.
      */
-    require_once(PATH::ENTITY . "Entity.php");
+    private $level;
 
     /**
-     * Monster skill level.
+     * @var string Upgrade description.
+     */
+    private $description;
+
+    /**
+     * Constructor.
      *
-     * Represents an object from the table 'skill_level'.
+     * Searches the database and retrieves the information about the
+     * skill level, populating it and it's items.
      *
-     * @category Entity
+     * @param int $skill Skill identifier.
+     * @param int $level Skill level.
      */
-    class Skill_Level extends Entity{
-
-        /**
-         * @var int Skill identifier.
-         */
-        private $skill;
+    public function __construct($skill, $level){
 
-        /**
-         * @var int Skill level.
-         */
-        private $level;
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            skill,
+            level,
+            description
+          FROM skill_level
+          WHERE
+            skill = :skill AND
+            level = :level;
+        ");
+        $statement->bindValue(':skill', $skill, SQLITE3_TEXT);
+        $statement->bindValue(':level', $level, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->skill = $r["skill"];
+            $this->level = $r["level"];
+            $this->description = HTML::e($r["description"]);
+        }
+    }
 
-        /**
-         * @var string Upgrade description.
-         */
-        private $description;
+    /**
+     * Retrieves the skill identifier.
+     *
+     * @return int Skill ID.
+     */
+    public function get_skill(){
+        return $this->skill;
+    }
 
-        /**
-         * Retrieves the skill identifier.
-         *
-         * @return number Skill ID.
-         */
-        public function get_skill(){
-            return $this->skill;
-        }
-    
-        /**
-         * Retrieves the skill level.
-         *
-         * @return number Skill level.
-         */
-        public function get_level(){
-            return $this->level;
-        }
-    
-        /**
-         * Retrieves the upgrade at this level.
-         *
-         * @return string Skill level description.
-         */
-        public function get_description(){
-            return $this->description;
-        }
-    
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * skill level, populating it and it's items.
-         *
-         * @param int $skill Skill identifier.
-         * @param int $level Skill level.
-         */
-        public function __construct($skill, $level){
+    /**
+     * Retrieves the skill level.
+     *
+     * @return int Skill level.
+     */
+    public function get_level(){
+        return $this->level;
+    }
 
-            $statement = get_context()->get_db()->prepare("
-              SELECT
-                skill,
-                level,
-                description
-              FROM skill_level
-              WHERE
-                skill = :skill AND
-                level = :level;
-            ");
-            $statement->bindValue(':skill', $skill, SQLITE3_TEXT);
-            $statement->bindValue(':level', $level, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            if ($r){
-                $this->skill = $r["skill"];
-                $this->level = $r["level"];
-                $this->description = HTML::e($r["description"]);
-            }
-        }
+    /**
+     * Retrieves the upgrade at this level.
+     *
+     * @return string Skill level description.
+     */
+    public function get_description(){
+        return $this->description;
     }
-?>
+}

+ 25 - 28
application/entity/Source.php

@@ -4,44 +4,42 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 
-
 /**
  * Monster source.
  *
- * Represents an object from the table 'source'.
+ * Represesnts a source where a monster can be obtained.
  *
  * @category Entity
  */
 class Source extends Entity{
-    
+
     /**
      * @var int Source identifier.
      */
     private $id;
-    
+
     /**
      * @var string Source name.
      */
     private $name;
-    
+
     /**
      * @var string Source description.
      */
     private $description;
-    
+
     /**
      * @var bool Indicates if the source is farmable.
      */
     private $farmable;
-    
+
     /**
      * Constructor.
      *
@@ -52,33 +50,33 @@ class Source extends Entity{
      */
     public function __construct($id){
         $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                name,
-                description,
-                farmable
-              FROM source
-              WHERE id = :id;
-            ");
+          SELECT
+            id,
+            name,
+            description,
+            farmable
+          FROM source
+          WHERE id = :id;
+        ");
         $statement->bindValue(':id', $id, SQLITE3_TEXT);
         $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
         if ($r){
             $this->id = $r["id"];
             $this->name = HTML::e($r["name"]);
             $this->description = HTML::e($r["description"]);
-            $this->farmable_source = $r["farmable"];
+            $this->farmable = filter_var($r["farmable"], FILTER_VALIDATE_BOOLEAN);
         }
     }
-    
+
     /**
      * Retrieves the source identifier.
      *
-     * @return number Source ID.
+     * @return int Source ID.
      */
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the source name.
      *
@@ -87,7 +85,7 @@ class Source extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the source description.
      *
@@ -96,16 +94,16 @@ class Source extends Entity{
     public function get_description(){
         return $this->description;
     }
-    
+
     /**
      * Checks if the osurce is farmable.
      *
-     * @return boolean True if the source is farmable, false otherwise.
+     * @return bool True if the source is farmable, false otherwise.
      */
     public function is_farmable(){
         return $this->farmable;
     }
-    
+
     /**
      * Gets the path to the source image. 
      *
@@ -116,4 +114,3 @@ class Source extends Entity{
     }
 
 }
-?>

+ 48 - 40
application/entity/Team.php

@@ -4,7 +4,9 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
 /**
@@ -21,76 +23,77 @@ require_once(PATH::ENTITY . "Unit.php");
  * @category Entity
  */
 class Team extends Entity{
-    
+
     /**
      * @var int Owner's player identifier.
      */
     private $player;
-    
+
     /**
      * @var int Team identifier.
      */
     private $id;
-    
+
     /**
      * @var string Team name.
      */
     private $name;
-    
+
     /**
      * @var string Team description.
      */
     private $description;
-    
+
+    /**
+     * @var bool Internal flag to check if the team units have been loaded into the entity.
+     */
     private $flag_units = false;
     /**
-     * @var \Unit[] Units in the team.
+     * @var Unit[] Units in the team.
      */
     private $unit = [];
-    
+
     /**
      * @var int ID of the leader unit.
      */
     private $leader;
-    
+
     /**
      * @var int[] List of IDs of the frontline units.
      */
     private $frontline = [];
-    
+
     /**
      * @var Area Area the team is designed for.
      */
     private $area;
-    
+
     /**
      * @var int Stage the team is designed for. It can be null.
      */
     private $stage;
-    
+
     /**
      * @var int difficulty the team is designed for. It can be null.
-     *
      * @see DIFFICULTY_ID
      */
     private $difficulty;
-    
+
     /**
      * @var int Team score for the optmizer
      */
     private $score;
-    
+
     /**
      * Constructor.
      *
      * Searches the database and retrieves the information about the
-     * monster, populating it and it's items.
+     * team, populating it and it's items.
      *
-     * @param int $id Monster identifier.
-     * @param bool $complete If false, it won't load the units.
+     * @param int $id Team identifier.
      */
     public function __construct($id){
-        
+
         $statement = get_context()->get_db()->prepare("
           SELECT
             player,
@@ -117,7 +120,13 @@ class Team extends Entity{
             $this->score = $r["score"];
         }
     }
-    
+
+    /**
+     * Loads the team units into the entity.
+     *
+     * Must be called only once before trying to get the party units, leader or positions. Sets
+     * the flag {@link Team:$flag_units} to true.
+     */
     private function load_units(){
         $statement = get_context()->get_db()->prepare("
           SELECT
@@ -143,24 +152,25 @@ class Team extends Entity{
         }
         $this->flag_units = true;
     }
+
     /**
      * Retrieves the account's player identifier.
      *
-     * @return number Player ID.
+     * @return int Player ID.
      */
     public function get_player(){
         return $this->player;
     }
-    
+
     /**
      * Retrieves the team identifier.
      *
-     * @return number Team ID.
+     * @return int Team ID.
      */
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the team name.
      *
@@ -169,7 +179,7 @@ class Team extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the team description.
      *
@@ -178,7 +188,7 @@ class Team extends Entity{
     public function get_description(){
         return $this->description;
     }
-    
+
     /**
      * Retrieves the units in the team.
      *
@@ -190,25 +200,25 @@ class Team extends Entity{
         }
         return $this->unit;
     }
-    
+
     /**
      * Retrieves the leader unit's identifier.
      *
-     * @return number Leader unit ID.
+     * @return int Leader unit ID.
      */
     public function get_leader(){
         return $this->leader;
     }
-    
+
     /**
      * Retrieves the identifiers of the units in the frontline.
      *
-     * @return number[] ID of units in the frontline.
+     * @return int[] ID of units in the frontline.
      */
     public function get_frontline(){
         return $this->frontline;
     }
-    
+
     /**
      * Retrieves the area the team is set for.
      *
@@ -217,35 +227,33 @@ class Team extends Entity{
     public function get_area(){
         return $this->area;
     }
-    
+
     /**
      * Retrieves the stage the team is intended to.
      *
-     * @return number Team stage, can be null.
+     * @return int Team stage, can be null.
      */
     public function get_stage(){
         return $this->stage;
     }
-    
+
     /**
      * Retrieves the difficulty of the area the team is intended for.
      * 
      * @see DIFFICULTY_ID
-     *
-     * @return number Difficulty ID, can be null.
+     * @return int Difficulty ID, can be null.
      */
     public function get_difficulty(){
         return $this->difficulty;
     }
-    
+
     /**
      * Retrieves the score of the team for the optimizer.
      *
-     * @return number Team score.
+     * @return int Team score.
      */
     public function get_score(){
         return $this->score;
     }
-    
+
 }
-?>

+ 636 - 459
application/entity/Unit.php

@@ -4,12 +4,11 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Monster.php");
 require_once(PATH::ENTITY . "Team.php");
@@ -20,34 +19,126 @@ require_once(PATH::ENTITY . "Building.php");
 /**
  * A Unit.
  *
- * Represents an object from the table 'unit'.
+ * Represents an unit owned by the player.
  *
  * @category Entity
  */
 class Unit extends Entity{
-    
+
+    /**
+     * @var int Owner's player ID.
+     */
     private $player;
+
+    /**
+     * @var int Unit ID.
+     */
     private $id;
+
+    /**
+     * @var int ID of the building the unit is in, if any.
+     */
     private $building;
+
+    /**
+     * @var Monster Base monster
+     */
     private $monster;
+
+    /**
+     * @var int Unit's current stars.
+     */
     private $stars;
+
+    /**
+     * @var int Unit's current stars.
+     */
     private $level;
+
+    /**
+     * @var int Total gained experience.
+     */
     private $experience;
+
+    /**
+     * @var int Gainex experience in the curent level.
+     */
     private $exp_gained;
+
+    /**
+     * @var int Experience gained by the hour, if in an EXP building.
+     */
     private $exp_gain_rate;
+
+    /**
+     * @var bool Internal flag to check if current level experience parameters have been loaded.
+     */
     private $flag_experience = false;
+
+    /**
+     * @var int Total experience for the current level.
+     */
     private $experience_level = 0;
+
+    /**
+     * @var int Experience remaining until next level.
+     */
     private $experience_level_up = 0;
+
+    /**
+     * @var bool Internal flag to inidicate if it has been checked that the unit is in the storage
+     * building. 
+     */
     private $flag_storage = false;
+
+    /**
+     * @var bool Indicates if the unit is in storage.
+     */
     private $in_storage = false;
+
+    /**
+     * @var string Unit's title.
+     */
     private $title;
+
+    /**
+     * @var int Transmogification ID.
+     */
     private $costume;
+
+    /**
+     * @var bool Internal flag to check if the source has been loaded into the entity.
+     */
     private $flag_source = false;
+
+    /**
+     * @var int Unit source ID.
+     */
     private $source_id;
+
+    /**
+     * @var Source Unit source.
+     */
     private $source;
+
+    /**
+     * @var DateTime Unit creation time.
+     */
     private $create_time;
+
+    /**
+     * @var string Name for Homunculus units.
+     */
     private $homunculus_name;
+
+    /**
+     * @var bool Indicates if the unit is locked.
+     */
     private $lock;
+
+    /**
+     * @var int[] The unit's base stats.
+     */
     private $base_stats = array(
         "hp"  => 0,
         "atk" => 0,
@@ -60,6 +151,10 @@ class Unit extends Entity{
         "ehp" => 0,
         "dmg" => 0,
     );
+
+    /**
+     * @var int[] The unit's stat bonus gained from runes.
+     */
     private $rune_stats = array(
         "hp"  => 0,
         "atk" => 0,
@@ -72,6 +167,10 @@ class Unit extends Entity{
         "ehp" => 0,
         "dmg" => 0,
     );
+
+    /**
+     * @var int[] The unit's stat bonus gained from artifacts.
+     */
     private $artifact_stats = array(
         "hp"  => 0,
         "atk" => 0,
@@ -84,7 +183,15 @@ class Unit extends Entity{
         "ehp" => 0,
         "dmg" => 0,
     );
+
+    /**
+     * @var bool Internal flag to check if building stats have been loaded.
+     */
     private $flag_buildings = false;
+
+    /**
+     * @var int[] The unit's stat bonus gained from buildings.
+     */
     private $building_stats = array(
         "hp"  => 0,
         "atk" => 0,
@@ -97,7 +204,15 @@ class Unit extends Entity{
         "ehp" => 0,
         "dmg" => 0,
     );
+
+    /**
+     * @var bool Internal flag to check if all the stats have been loaded.
+     */
     private $flag_stats = false;
+
+    /**
+     * @var int[] The unit's total stats.
+     */
     private $stats = array(
         "hp"  => 0,
         "atk" => 0,
@@ -110,455 +225,175 @@ class Unit extends Entity{
         "ehp" => 0,
         "dmg" => 0,
     );
+
+    /**
+     * @var bool Internal flag to check if runes and artifacts have been loaded.
+     */
     private $flag_runes = false;
-    private $avg_rune_efficiency = 0.0;
-    private $rune = [];
-    private $artifact_type;
-    private $artifact_element;
-    private $flag_teams = false;
-    private $teams = [];
-    private $flag_skills = false;
-    private $skill_levels = [];
-    
+
     /**
-     * Retrieves the owner's player identifier.
-     *
-     * @return int Player ID.
+     * @var float Average rune eficiency.
      */
-    public function get_player(){
-        return $this->player;
-    }
-    
+    private $avg_rune_efficiency = 0.0;
+
     /**
-     * Retrieves the unit identifier.
-     *
-     * @return int Unit ID.
+     * @var Rune[] Equipped runes.
      */
-    public function get_id(){
-        return $this->id;
-    }
-    
+    private $rune = [];
+
     /**
-     * Retrieves the identifier of the building the unit is in, if any.
-     *
-     * @return int Building ID, null if unit not in building.
+     * @var Artifact Equiped archetype artifact.
      */
-    public function get_building_id(){
-        return $this->building;
-    }
-    
+    private $artifact_type;
+
     /**
-     * Retrieves the base monster.
-     *
-     * @return Monster The base monster.
+     * @var Artifact Equipped elemental artifact.
      */
-    public function get_monster(){
-        return $this->monster;
-    }
-    
+    private $artifact_element;
+
     /**
-     * Retrieves the unit stars (grade).
-     *
-     * @return int Unit stars (1-6).
+     * @var bool Internla flag to check if the teams have been loaded into the entity.
      */
-    public function get_stars(){
-        return $this->stars;
-    }
-    
+    private $flag_teams = false;
+
     /**
-     * Retrieves the unit current level.
-     *
-     * @return int Unit level.
+     * @var Team [] The teams the unit is in.
      */
-    public function get_level(){
-        return $this->level;
-    }
-    
+    private $teams = [];
+
     /**
-     * Retrieves the unit's base stats.
-     * 
-     * It's an associative array with the following keys:
-     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
-     *
-     * @return int[] Unit stats.
+     * @var bool Internal flag to check if the skill levels have been loded.
      */
-    public function get_base_stats(){
-        return $this->base_stats;
-    }
+    private $flag_skills = false;
 
     /**
-     * Retrieves the unit's stats provided by runes.
-     *
-     * It's an associative array with the following keys:
-     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
-     *
-     * @return int[] Rune stats.
+     * @var int[] Skill levels.
      */
-    public function get_rune_stats(){
-        if (! $this->flag_runes){
-            $this->load_runes();
-        }
-        return $this->rune_stats;
-    }
-    
+    private $skill_levels = [];
+
     /**
-     * Retrieves the unit's stats provided by artifacts.
+     * Constructor.
      *
-     * It's an associative array with the following keys:
-     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
-     * Note that only "atk", "def", "hp", "dmg" and "ehp" can me non-zero.
+     * Searches the database and retrieves the information about the
+     * unit, populating it and it's items.
      *
-     * @return int[] Artifact stats.
+     * @param int $id Unit identifier.
      */
-    public function get_artifact_stats(){
-        if (! $this->flag_runes){
-            $this->load_runes();
+    public function __construct($id){
+        $player = get_context()->get_player()->get_id();
+        $statement = get_context()->get_db()->prepare("
+          SELECT
+            player,
+            id,
+            building,
+            monster,
+            stars,
+            level,
+            hp,
+            attack,
+            defense,
+            speed,
+            crit_rate,
+            crit_damage,
+            resistance,
+            accuracy,
+            experience,
+            exp_gained,
+            exp_gain_rate,
+            costume,
+            source,
+            create_time,
+            homunculus_name,
+            lock
+          FROM unit
+          WHERE
+            id = :id;
+        ");
+        $statement->bindValue(':id', $id, SQLITE3_TEXT);
+        $statement->bindValue(':player', $player, SQLITE3_TEXT);
+        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
+        if ($r){
+            $this->player = $r["player"];
+            $this->id = $r["id"];
+            if ($r["building"] != null && $r["building"] > 0){
+                $this->building = $r["building"];
+            }
+            if (strlen($r["monster"]) > 0){
+                $this->monster = new Monster($r["monster"]);
+            }
+            $this->stars = $r["stars"];
+            $this->level = $r["level"];
+            $this->base_stats["hp"] = $r["hp"];
+            $this->base_stats["atk"] = $r["attack"];
+            $this->base_stats["def"] = $r["defense"];
+            $this->base_stats["spd"] = $r["speed"];
+            $this->base_stats["crr"] = $r["crit_rate"];
+            $this->base_stats["crd"] = $r["crit_damage"];
+            $this->base_stats["res"] = $r["resistance"];
+            $this->base_stats["acc"] = $r["accuracy"];
+            $this->base_stats["ehp"] = APPLICATION::calculate_ehp($r["hp"], $r["defense"]);
+            $this->base_stats["dmg"] = APPLICATION::calculate_dmg($r["attack"], $r["crit_rate"], $r["crit_damage"]);
+
+            $this->experience = $r["experience"];
+            $this->exp_gained = $r["exp_gained"];
+            $this->exp_gain_rate = $r["exp_gain_rate"];
+            $this->costume = $r["costume"];
+            if ($r["source"]){
+                $this->source_id = $r["source"];
+            }
+            $this->create_time = new Datetime();
+            $this->create_time->setTimestamp($r["create_time"]);
+            $this->homunculus_name = $r["homunculus_name"];
+            if ($this->monster->is_homunculus()){
+                $this->title = $this->homunculus_name;
+            }
+            else{
+                $this->title = $this->monster->get_title();
+            }
+            $this->lock = $r["lock"];
+
         }
-        return $this->artifact_stats;
     }
 
     /**
-     * Retrieves the unit's stat bonus provided by buildings.
-     * Only building bonuses are considered.
-     *
-     * It's an associative array with the following keys:
-     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
+     * Loads the unit skills into the entity.
      *
-     * @return int[] Building stats.
+     * Must be called only once before trying to get the skills. Sets the flag
+     * {@link Unit:$flag_skills} to true.
      */
-    public function get_building_stats(){
-        if (! $this->flag_buildings){
-            $this->load_buildings();
+    private function load_skills(){
+        $statement = get_context()->get_db()->prepare("
+          SELECT level
+          FROM
+            unit_skill,
+            skill
+          WHERE
+            skill.id = unit_skill.skill AND
+            unit_skill.unit = :unit
+          ORDER BY slot;
+        ");
+        $statement->bindValue(':unit', $this->id, SQLITE3_TEXT);
+        $q = $statement->execute();
+        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+            array_push($this->skill_levels, $r["level"]);
         }
-        return $this->building_stats;
+        $this->flag_skills = true;
     }
 
     /**
-     * Retrieves the unit's stats.
+     * Loads the unit's current level experience parameters into the entity.
      *
-     * It's an associative array with the following keys:
-     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
-     * 
-     * Includes the unit base stats, the runes and artifact increases and the building bonuses.
-     *
-     * @return int[] Unit stats.
-     */
-    public function get_stats(){
-        if (! $this->flag_stats){
-            $this->load_stats();
-        }
-        return $this->stats;
-    }
-    
-    /**
-     * Retrieves the total experience earned by the unit.
-     * 
-     * @return int Total experience.
-     */
-    public function get_experience(){
-        return $this->experience;
-    }
-    
-    /**
-     * Retrieves the total experience earned by the unit since it's level is the current one..
-     * 
-     * @return int Current level experience.
-     */
-    public function get_current_level_experience(){
-        return $this->exp_gained;
-    }
-    
-    /**
-     * Retrieves the experience being gained by the hour from a building.
-     *
-     * @return int Experience by the hour, 0 if not in an exp building.
-     */
-    public function get_exp_gain_rate(){
-        return $this->exp_gain_rate;
-    }
-    
-    /**
-     * Retrieves the current transmogrification identifier.
-     *
-     * @return int Transmogification ID, null if none.
-     */
-    public function get_costume(){
-        return $this->costume;
-    }
-    
-    /**
-     * Retrieves the $source the unit was obtained from.
-     *
-     * @return Source Unit source.
-     */
-    public function get_source(){
-        if (! $this->flag_source){
-            $this->load_source();
-        }
-        return $this->source;
-    }
-    
-    /**
-     * Gets the date the unit was obtained.
-     *
-     * If $format is supplied, a string in the desired format will be returned. If not, the raw
-     * DateTime object will e returned.
-     *
-     * @param string $format A date format (optional).
-     * @return DateTime | string The raw date, or a formatted version.
-     */
-    public function get_creation_time($format = null){
-        if (null == $format){
-            return $this->create_time;
-        }
-        else{
-            return $this->create_time->format($format);
-        }
-    }
-    
-    /**
-     * Retrieves the name if the unit is an homunculus.
-     *
-     * @return string Homunculus name, null if not Homunculus.
-     */
-    public function get_homunculus_name(){
-        return $this->homunculus_name;
-    }
-    
-    /**
-     * Checks if the unit is locked.
-     *
-     * @return boolean True if locked, false if unlocked.
-     */
-    public function is_locked(){
-        return $this->lock;
-    }
-    
-    /**
-     * Retrieves the average rune efficiency.
-     *
-     * @return number Average efficiency of the runes.
-     */
-    public function get_avg_rune_efficiency(){
-        if (! $this->flag_runes){
-            $this->load_runes();
-        }
-        return $this->avg_rune_efficiency;
-    }
-    
-    /**
-     * Retrieves the currently equipped runes.
-     *
-     * @return Rune[]
-     */
-    public function get_runes(){
-        if (! $this->flag_runes){
-            $this->load_runes();
-        }
-        return $this->rune;
-    }
-    
-    /**
-     * Retrieves equipped artifacts.
-     * Can be read with the indexes ARTIFACT_TYPE:ELEMENT and ARTIFACT_TYPE:ARCHETYPE. 
-     *  
-     * @see ARTIFACT_TYPE
-     *
-     * @return Artifact[] Equiped artifact array. Null positions if not equipped.
-     */
-    public function get_artifacts(){
-        if (! $this->flag_runes){
-            $this->load_runes();
-        }
-        return [$this->artifact_element, $this->artifact_type];
-    }
-    
-    /**
-     * Retrieves $teams
-     *
-     * @return multitype:Team
-     */
-    public function get_teams(){
-        if (! $this->flag_teams){
-            $this->load_teams();
-        }
-        return $this->teams;
-    }
-    
-    /**
-     * Retrieves $skill_levels
-     *
-     * @return multitype:number
+     * Must be called only once before trying to get experience parameters. Sets the flag
+     * {@link Unit:$flag_experience} to true.
      */
-    public function get_skill_levels(){
-        if (! $this->flag_skills){
-            $this->load_skill();
-        }
-        return $this->skill_levels;
-    }
-    
-    /**
-     * Retrieves the total experience required for the current level.
-     *
-     * @return int Level experience.
-     */
-    public function get_experience_level(){
-        if (! $this->flag_experience){
-            $this->load_experience();
-        }
-        return $this->experience_level;
-    }
-    
-    /**
-     * Retrieves the experience required to level-up.
-     *
-     * @return int Experience to level-up.
-     */
-    public function get_experience_level_up(){
-        if (! $this->flag_experience){
-            $this->load_experience();
-        }
-        return $this->experience_level_up;
-    }
-    
-    /**
-     * Checks if the unit is in storage.
-     *
-     * @return boolean True if in storage, false otherwise.
-     */
-    public function is_in_storage(){
-        if (! $this->flag_storage){
-            $this->load_storage();
-        }
-        return $this->in_storage;
-    }
-    
-    /**
-     * Retrieves the unit's title.
-     * If Homunculus,it will be it's name.
-     * If awakened, it will be the awakened from name.
-     * If unawakened, it will be <element> <name>.
-     *
-     * @return string The unit's title.
-     */
-    public function get_title(){
-        return $this->title;
-    }
-    
-    /**
-     * Constructor.
-     *
-     * Searches the database and retrieves the information about the
-     * monster, populating it and it's items.
-     *
-     * @param int $id Monster identifier.
-     * @param bool $complete If false, query only unit and monster.
-     */
-    public function __construct($id, $complete = true, $player = -1){
-        if ($player == -1 && null != get_context()->get_player()){
-            $player = get_context()->get_player()->get_id();
-        }
-        $statement = get_context()->get_db()->prepare("
-              SELECT
-                player,
-                id,
-                building,
-                monster,
-                stars,
-                level,
-                hp,
-                attack,
-                defense,
-                speed,
-                crit_rate,
-                crit_damage,
-                resistance,
-                accuracy,
-                experience,
-                exp_gained,
-                exp_gain_rate,
-                costume,
-                source,
-                create_time,
-                homunculus_name,
-                lock
-              FROM unit
-              WHERE
-                id = :id;
-            ");
-        $statement->bindValue(':id', $id, SQLITE3_TEXT);
-        $statement->bindValue(':player', $player, SQLITE3_TEXT);
-        $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-        if ($r){
-            $this->player = $r["player"];
-            $this->id = $r["id"];
-            if ($r["building"] != null && $r["building"] > 0){
-                $this->building = $r["building"];
-            }
-            if (strlen($r["monster"]) > 0){
-                $this->monster = new Monster($r["monster"]);
-            }
-            $this->stars = $r["stars"];
-            $this->level = $r["level"];
-            $this->base_stats["hp"] = $r["hp"];
-            $this->base_stats["atk"] = $r["attack"];
-            $this->base_stats["def"] = $r["defense"];
-            $this->base_stats["spd"] = $r["speed"];
-            $this->base_stats["crr"] = $r["crit_rate"];
-            $this->base_stats["crd"] = $r["crit_damage"];
-            $this->base_stats["res"] = $r["resistance"];
-            $this->base_stats["acc"] = $r["accuracy"];
-            $this->base_stats["ehp"] = APPLICATION::calculate_ehp($r["hp"], $r["defense"]);
-            $this->base_stats["dmg"] = APPLICATION::calculate_dmg($r["attack"], $r["crit_rate"], $r["crit_damage"]);
-            
-            $this->experience = $r["experience"];
-            $this->exp_gained = $r["exp_gained"];
-            $this->exp_gain_rate = $r["exp_gain_rate"];
-            $this->costume = $r["costume"];
-            if ($r["source"]){
-                $this->source_id = $r["source"];
-            }
-            $this->create_time = new Datetime();
-            $this->create_time->setTimestamp($r["create_time"]);
-            $this->homunculus_name = $r["homunculus_name"];
-            if ($this->monster->is_homunculus()){
-                $this->title = $this->homunculus_name;
-            }
-            else{
-                $this->title = $this->monster->get_title();
-            }
-            $this->lock = $r["lock"];
-            
-        }
-    }
-    
-    private function load_skills(){
-        $statement = get_context()->get_db()->prepare("
-              SELECT level
-              FROM
-                unit_skill,
-                skill
-              WHERE
-                skill.id = unit_skill.skill AND
-                unit_skill.unit = :unit
-              ORDER BY slot;
-            ");
-        $statement->bindValue(':unit', $this->id, SQLITE3_TEXT);
-        $q = $statement->execute();
-        while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-            array_push($this->skill_levels, $r["level"]);
-        }
-        $this->flag_skills = true;
-    }
-    
     private function load_experience(){
         $statement = get_context()->get_db()->prepare("
-              SELECT exp
-              FROM experience
-              WHERE
-                stars = :stars AND
-                level = :level;
-            ");
+          SELECT exp
+          FROM experience
+          WHERE
+            stars = :stars AND
+            level = :level;
+        ");
         $statement->bindValue(':stars', $this->stars, SQLITE3_TEXT);
         $statement->bindValue(':level', $this->level, SQLITE3_TEXT);
         $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
@@ -568,24 +403,26 @@ class Unit extends Entity{
         }
         $this->flag_experience = true;
     }
-    
+
     /**
-     * Checks if the monster is in storage and sets {@see $in_storage} to
-     * true or false.
+     * Loads the unit storage status into the entity.
+     *
+     * Must be called only once before trying to get the skills. Sets the flag
+     * {@link Unit:$flag_storage} to true.
      */
     private function load_storage(){
         $statement = get_context()->get_db()->prepare("
-              SELECT 1
-              FROM
-                unit,
-                building
-              WHERE
-                unit.id = :id AND
-                unit.player = :player AND
-                building.player = :player AND
-                unit.building = building.id AND
-                building.buildable = :buildable;
-            ");
+          SELECT 1
+          FROM
+            unit,
+            building
+          WHERE
+            unit.id = :id AND
+            unit.player = :player AND
+            building.player = :player AND
+            unit.building = building.id AND
+            building.buildable = :buildable;
+        ");
         $statement->bindValue(':id', $this->id, SQLITE3_TEXT);
         $statement->bindValue(':player', $this->player, SQLITE3_TEXT);
         $statement->bindValue(':buildable', BUILDING_ID::MONSTER_STORAGE, SQLITE3_TEXT);
@@ -598,7 +435,13 @@ class Unit extends Entity{
         }
         $this->flag_storage = true;
     }
-    
+
+    /**
+     * Loads the building stats into the entity.
+     *
+     * Must be called only once before trying to get the building or total stats. Sets the flag
+     * {@link Unit:$flag_buildings} to true.
+     */
     private function load_buildings(){
         $statement = get_context()->get_db()->prepare("
           SELECT
@@ -657,14 +500,26 @@ class Unit extends Entity{
         $this->building_stats["dmg"] = APPLICATION::calculate_dmg($this->building_stats["atk"], $this->building_stats["crr"], $this->building_stats["crd"]);
         $this->flag_buildings = true;
     }
-    
+
+    /**
+     * Loads the unit source into the entity.
+     *
+     * Must be called only once before trying to get the source. Sets the flag
+     * {@link Unit:$flag_source} to true.
+     */
     private function load_source(){
         if ($this->source_id != null){
             $this->source = new Source($this->source_id);
         }
         $this->flag_source = true;
     }
-    
+
+    /**
+     * Loads the unit runes and artifacts into the entity.
+     *
+     * Must be called only once before trying to the runes or artifact or their stats. Sets the
+     * flag {@link Unit:$flag_skills} to true.
+     */
     private function load_runes(){
         // Runes
         $statement = get_context()->get_db()->prepare("
@@ -690,7 +545,7 @@ class Unit extends Entity{
         $this->rune_stats["hp"] = ceil($this->rune_stats["hp"]);
         $this->rune_stats["ehp"] = APPLICATION::calculate_ehp($this->rune_stats["hp"], $this->rune_stats["def"]);
         $this->rune_stats["dmg"] = APPLICATION::calculate_dmg($this->rune_stats["atk"], $this->rune_stats["crr"], $this->rune_stats["crd"]);
-        
+
         // Artifacts
         $this->artifact = [];
         $statement = get_context()->get_db()->prepare("
@@ -725,43 +580,40 @@ class Unit extends Entity{
         }
         $this->artifact_stats["ehp"] = APPLICATION::calculate_ehp($this->artifact_stats["hp"], $this->artifact_stats["def"]);
         $this->artifact_stats["dmg"] = APPLICATION::calculate_dmg($this->artifact_stats["atk"], $this->artifact_stats["crr"], $this->artifact_stats["crd"]);
-        
+
         $this->flag_runes = true;
     }
-    
-    // TODO: Other loaders??
-    
-    
+
     /**
-     * Calculates the stats gained from runes, artifacts and buildings.
-     * Calculates the totalls and the effective stats.
+     * Calculates the unit's total stats.
      *
-     * @gobal Player Currently selected player.
-     * @gobal int Game mode (Normal/RTA).
+     * Must be called only once before trying to get the stats. Sets the flag
+     * {@link Unit:$flag_stats} to true.
      */
     private function load_stats(){
-        
+
         if (! $this->flag_buildings){
             $this->load_buildings();
         }
         if (! $this->flag_runes){
             $this->load_runes();
         }
-        
-        
+
         $keys = ["atk", "def", "hp", "spd", "crr", "crd", "res", "acc", "ehp", "dmg"];
-        
+
         foreach ($keys as $key){
             $this->stats[$key] = $this->base_stats[$key] + $this->rune_stats[$key] + $this->artifact_stats[$key] + $this->building_stats[$key];
-            
+
         }
-        
+
         $this->flag_stats = true;
     }
-    
-    
+
     /**
-     * Loads the {@see teams} array, with the teams the unit is on.
+     * Loads the unit teams into the entity.
+     *
+     * Must be called only once before trying to get the teams. Sets the flag
+     * {@link Unit:$flag_teams} to true.
      */
     private function load_teams(){
         $statement = get_context()->get_db()->prepare("
@@ -782,12 +634,12 @@ class Unit extends Entity{
         }
         $this->flag_teams = true;
     }
-    
-    
+
     /**
      * Calculates the stat increase by a rune property.
      *
      * @param string $stat Stat type.
+     * @param int $value Stat value.
      * @param int $value Stat increase value.
      */
     private function sum_rune_stat($stat, $value){
@@ -827,7 +679,7 @@ class Unit extends Entity{
                 break;
         }
     }
-    
+
     /**
      * Checks if the unit skills are completly maxed.
      *
@@ -847,5 +699,330 @@ class Unit extends Entity{
         }
         return $maxed;
     }
+
+    /**
+     * Retrieves the owner's player identifier.
+     *
+     * @return int Player ID.
+     */
+    public function get_player(){
+        return $this->player;
+    }
+
+    /**
+     * Retrieves the unit identifier.
+     *
+     * @return int Unit ID.
+     */
+    public function get_id(){
+        return $this->id;
+    }
+
+    /**
+     * Retrieves the identifier of the building the unit is in, if any.
+     *
+     * @return int Building ID, null if unit not in building.
+     */
+    public function get_building_id(){
+        return $this->building;
+    }
+
+    /**
+     * Retrieves the base monster.
+     *
+     * @return Monster The base monster.
+     */
+    public function get_monster(){
+        return $this->monster;
+    }
+
+    /**
+     * Retrieves the unit stars (grade).
+     *
+     * @return int Unit stars (1-6).
+     */
+    public function get_stars(){
+        return $this->stars;
+    }
+
+    /**
+     * Retrieves the unit current level.
+     *
+     * @return int Unit level.
+     */
+    public function get_level(){
+        return $this->level;
+    }
+
+    /**
+     * Retrieves the unit's base stats.
+     *
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
+     *
+     * @return int[] Unit stats.
+     */
+    public function get_base_stats(){
+        return $this->base_stats;
+    }
+
+    /**
+     * Retrieves the unit's stats provided by runes.
+     *
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
+     *
+     * @return int[] Rune stats.
+     */
+    public function get_rune_stats(){
+        if (! $this->flag_runes){
+            $this->load_runes();
+        }
+        return $this->rune_stats;
+    }
+
+    /**
+     * Retrieves the unit's stats provided by artifacts.
+     *
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
+     * Note that only "atk", "def", "hp", "dmg" and "ehp" can me non-zero.
+     *
+     * @return int[] Artifact stats.
+     */
+    public function get_artifact_stats(){
+        if (! $this->flag_runes){
+            $this->load_runes();
+        }
+        return $this->artifact_stats;
+    }
+
+    /**
+     * Retrieves the unit's stat bonus provided by buildings.
+     * 
+     * Only building bonuses are considered.
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
+     *
+     * @return int[] Building stats.
+     */
+    public function get_building_stats(){
+        if (! $this->flag_buildings){
+            $this->load_buildings();
+        }
+        return $this->building_stats;
+    }
+
+    /**
+     * Retrieves the unit's stats.
+     *
+     * It's an associative array with the following keys:
+     * atk, def, hp, spd, crr, crd, acc, res, ehp, dmg
+     *
+     * Includes the unit base stats, the runes and artifact increases and the building bonuses.
+     *
+     * @return int[] Unit stats.
+     */
+    public function get_stats(){
+        if (! $this->flag_stats){
+            $this->load_stats();
+        }
+        return $this->stats;
+    }
+
+    /**
+     * Retrieves the total experience earned by the unit.
+     *
+     * @return int Total experience.
+     */
+    public function get_experience(){
+        return $this->experience;
+    }
+
+    /**
+     * Retrieves the total experience earned by the unit since it's level is the current one..
+     *
+     * @return int Current level experience.
+     */
+    public function get_current_level_experience(){
+        return $this->exp_gained;
+    }
+
+    /**
+     * Retrieves the experience being gained by the hour from a building.
+     *
+     * @return int Experience by the hour, 0 if not in an exp building.
+     */
+    public function get_exp_gain_rate(){
+        return $this->exp_gain_rate;
+    }
+
+    /**
+     * Retrieves the current transmogrification identifier.
+     *
+     * @return int Transmogification ID, null if none.
+     */
+    public function get_costume(){
+        return $this->costume;
+    }
+
+    /**
+     * Retrieves the $source the unit was obtained from.
+     *
+     * @return Source Unit source.
+     */
+    public function get_source(){
+        if (! $this->flag_source){
+            $this->load_source();
+        }
+        return $this->source;
+    }
+
+    /**
+     * Gets the date the unit was obtained.
+     *
+     * If $format is supplied, a string in the desired format will be returned. If not, the raw
+     * DateTime object will e returned.
+     *
+     * @param string $format A date format (optional).
+     * @return DateTime | string The raw date, or a formatted version.
+     */
+    public function get_creation_time($format = null){
+        if (null == $format){
+            return $this->create_time;
+        }
+        else{
+            return $this->create_time->format($format);
+        }
+    }
+
+    /**
+     * Retrieves the name if the unit is an homunculus.
+     *
+     * @return string Homunculus name, null if not Homunculus.
+     */
+    public function get_homunculus_name(){
+        return $this->homunculus_name;
+    }
+
+    /**
+     * Checks if the unit is locked.
+     *
+     * @return bool True if locked, false if unlocked.
+     */
+    public function is_locked(){
+        return $this->lock;
+    }
+
+    /**
+     * Retrieves the average rune efficiency.
+     *
+     * @return int Average efficiency of the runes.
+     */
+    public function get_avg_rune_efficiency(){
+        if (! $this->flag_runes){
+            $this->load_runes();
+        }
+        return $this->avg_rune_efficiency;
+    }
+
+    /**
+     * Retrieves the currently equipped runes.
+     *
+     * @return Rune[] Equipped runes.
+     */
+    public function get_runes(){
+        if (! $this->flag_runes){
+            $this->load_runes();
+        }
+        return $this->rune;
+    }
+
+    /**
+     * Retrieves equipped artifacts.
+     * 
+     * Can be read with the indexes ARTIFACT_TYPE:ELEMENT and ARTIFACT_TYPE:ARCHETYPE.
+     *
+     * @see ARTIFACT_TYPE
+     * @return Artifact[] Equiped artifact array. Null positions if not equipped.
+     */
+    public function get_artifacts(){
+        if (! $this->flag_runes){
+            $this->load_runes();
+        }
+        return [$this->artifact_element, $this->artifact_type];
+    }
+
+    /**
+     * Retrieves the teams the unit is in.
+     *
+     * @return Team[] Teams the unit is in.
+     */
+    public function get_teams(){
+        if (! $this->flag_teams){
+            $this->load_teams();
+        }
+        return $this->teams;
+    }
+
+    /**
+     * Retrieves the skill levels.
+     *
+     * @return int[] Skill levels, ordered by skill slot.
+     */
+    public function get_skill_levels(){
+        if (! $this->flag_skills){
+            $this->load_skill();
+        }
+        return $this->skill_levels;
+    }
+
+    /**
+     * Retrieves the total experience required for the current level.
+     *
+     * @return int Level experience.
+     */
+    public function get_experience_level(){
+        if (! $this->flag_experience){
+            $this->load_experience();
+        }
+        return $this->experience_level;
+    }
+
+    /**
+     * Retrieves the experience required to level-up.
+     *
+     * @return int Experience to level-up.
+     */
+    public function get_experience_level_up(){
+        if (! $this->flag_experience){
+            $this->load_experience();
+        }
+        return $this->experience_level_up;
+    }
+
+    /**
+     * Checks if the unit is in storage.
+     *
+     * @return bool True if in storage, false otherwise.
+     */
+    public function is_in_storage(){
+        if (! $this->flag_storage){
+            $this->load_storage();
+        }
+        return $this->in_storage;
+    }
+
+    /**
+     * Retrieves the unit's title.
+     * 
+     * If Homunculus,it will be it's name.
+     * If awakened, it will be the awakened from name.
+     * If unawakened, it will be <element> <name>.
+     *
+     * @return string The unit's title.
+     */
+    public function get_title(){
+        return $this->title;
+    }
 }
-?>

+ 42 - 35
application/entity/User.php

@@ -4,55 +4,57 @@
  *
  * Creates the entity and makes it available.
  *
- * @category Entity
+ * @author Iñigo Valentin <i@inigovalentin.com>
+ * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
+ * @package SWDB
  */
 
-/**
- * Require dependent entities if not present.
- */
 require_once(PATH::ENTITY . "Entity.php");
 require_once(PATH::ENTITY . "Player.php");
 
 /**
  * A User.
  *
- * Represents an object from the table 'user'.
+ * Represents an application user.
  *
  * @category Entity
  */
 class User extends Entity{
-    
+
     /**
      * @var int User ID.
      */
     private $id;
-    
+
     /**
      * @var string User name.
      */
     private $name;
-    
+
     /**
      * @var string User email.
      */
     private $mail;
-    
+
     /**
      * @var string User API key.
      */
     private $api_key;
-    
+
     /**
-     * @var boolean Indicates if the user is an administrator.
+     * @var bool Indicates if the user is an administrator.
      */
     private $admin = false;
-    
+
+    /**
+     * @var bool Internal flag to check if the user's accounts have been loaded.
+     */
     private $flag_accounts = false;
     /**
-     * @var \Player[] All of the players accounts.
+     * @var Player[] All of the players accounts.
      */
     private $account = [];
-    
+
     /**
      * Constructor.
      *
@@ -63,15 +65,15 @@ class User extends Entity{
      */
     public function __construct($id){
         $statement = get_context()->get_db()->prepare("
-              SELECT
-                id,
-                name,
-                mail,
-                api_key,
-                admin
-              FROM user
-              WHERE id = :id;
-            ");
+          SELECT
+            id,
+            name,
+            mail,
+            api_key,
+            admin
+          FROM user
+          WHERE id = :id;
+        ");
         $statement->bindValue(':id', $id, SQLITE3_TEXT);
         $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
         if ($r){
@@ -80,10 +82,16 @@ class User extends Entity{
             $this->mail = $r["mail"];
             $this->api_key = $r["api_key"];
             $this->admin = $r["admin"];
-            
+
         }
     }
-    
+
+    /**
+     * Loads the users accounts into the entity.
+     *
+     * Must be called only once before trying to get the acoounts. Sets the flag
+     * {@link User:$flag_accounts} to true.
+     */
     private function load_accounts(){
         $statement = get_context()->get_db()->prepare("
           SELECT id
@@ -98,16 +106,16 @@ class User extends Entity{
         }
         $this->flag_accounts = true;
     }
-    
+
     /**
      * Retrieves the user identifier.
      *
-     * @return number User ID.
+     * @return int User ID.
      */
     public function get_id(){
         return $this->id;
     }
-    
+
     /**
      * Retrieves the user name.
      *
@@ -116,7 +124,7 @@ class User extends Entity{
     public function get_name(){
         return $this->name;
     }
-    
+
     /**
      * Retrieves the user email address.
      *
@@ -125,7 +133,7 @@ class User extends Entity{
     public function get_mail(){
         return $this->mail;
     }
-    
+
     /**
      * Retrieves the user's API key.
      *
@@ -134,16 +142,16 @@ class User extends Entity{
     public function get_api_key(){
         return $this->api_key;
     }
-    
+
     /**
      * Checks if the user is a site administrator.
      *
-     * @return boolean True if the user is administrator, false otherwise.
+      * @return bool True if the user is administrator, false otherwise.
      */
     public function is_admin(){
         return $this->admin;
     }
-    
+
     /**
      * Retrieves the user's accounts, sorted by the last account date in descending order.
      *
@@ -155,6 +163,5 @@ class User extends Entity{
         }
         return $this->account;
     }
-    
+
 }
-?>

+ 2 - 2
application/helper/APPLICATION_Helper.php

@@ -73,7 +73,7 @@
             }
             return $url;
         }
-        
+
         /**
          * Calculates the effective damage.
          * 
@@ -92,7 +92,7 @@
             $edmg = ceil(($atk * (100 - $crr) / 100) + (($atk + ($atk * $crd / 100)) * $crr / 100));
             return $edmg;
         }
-        
+
         /**
          *  Calculates the effective HP of a unit.
          * @param int $hp HP stat

+ 1 - 1
application/helper/HTML_Helper.php

@@ -613,7 +613,7 @@
             if (!($item instanceof Inventory) && !($item instanceof Item)){
                 return "";
             }
-            
+
             if ($item instanceof Item){
                 $html = "<div class='item_panel'>\n";
                 $html .= "<img title='" . $item->get_name() . "' class='item' src='" . $item->get_image() . "'/>\n";

+ 2 - 2
application/page/Artifacts_Page.php

@@ -1,5 +1,5 @@
  <?php
- 
+
     /**
      * Artifact list page file.
      *
@@ -23,7 +23,7 @@
     class Artifacts_Page extends Page{
 
         /**
-         * @var \Artifact[] Artiffacts to show.
+         * @var Artifact[] Artiffacts to show.
          *
          * In this case, the monster member is not the id, but a monster
          * instance.

+ 4 - 5
application/page/Enchantments_Page.php

@@ -1,5 +1,5 @@
  <?php
- 
+
     /**
      * Enchantment list page file.
      *
@@ -22,12 +22,12 @@
     class Enchantments_Page extends Page{
 
         /**
-         * @var \Enchantment[] Owned enchantment gems.
+         * @var Enchantment[] Owned enchantment gems.
          */
         public $gems = [];
 
         /**
-         * @var \Enchantment[] Owned enchantment grindstones.
+         * @var Enchantment[] Owned enchantment grindstones.
          */
         public $grindstones = [];
 
@@ -93,7 +93,7 @@
                     array_push($this->filters["ARCHETYPE"], intval($archetype));
                 }
             }
-            
+
             if (isset($_GET["min_level"]) && intval($_GET["min_level"]) >= 0 && intval($_GET["min_level"]) <= 15){
                 $this->filters["MIN_LEVEL"] = $_GET["min_level"];
             }
@@ -111,7 +111,6 @@
             }*/
         }
 
-
         /**
          * Builds the query to the artifact table using the selected or default
          * filters.

+ 1 - 1
application/page/Error_Page.php

@@ -36,7 +36,7 @@
         public function __construct($code = null){
             $this->view = PATH::VIEW . "error.php";
             $this->title = "Error - SWDB";
-            
+
             if (null == $code || intval($code) < 200 || intval($code) > 599){
                 $code = 500;
             }

+ 1 - 1
application/page/Guild_Page.php

@@ -27,7 +27,7 @@
         public $guild;
 
         /**
-         * @var \Guild_Skill_Group[] List of Guild skill groups.
+         * @var Guild_Skill_Group[] List of Guild skill groups.
          */
         public $skill_groups = [];
 

+ 0 - 1
application/page/Home_Page.php

@@ -13,7 +13,6 @@
     require_once(PATH::PAGE . "Page.php");
     require_once(PATH::ENTITY . "Player.php");
 
-
     /**
      * Home page model.
      *

+ 1 - 2
application/page/Monster_Page.php

@@ -13,7 +13,6 @@
     require_once(PATH::PAGE . "Page.php");
     require_once(PATH::ENTITY . "Monster.php");
 
-
     /**
      * Monster details page model.
      *
@@ -22,7 +21,7 @@
     class Monster_Page extends Page{
 
         /**
-         * @var \Monster[] Selected unit array.
+         * @var Monster[] Selected unit array.
          *
          * [0]: Unawakened monster (null if default purple).
          * [1]: Awakened monster (null if silver).

+ 1 - 2
application/page/Monsters_Page.php

@@ -13,7 +13,6 @@
     require_once(PATH::PAGE . "Page.php");
     require_once(PATH::ENTITY . "Monster.php");
 
-
     /**
      * Catalog page model.
      *
@@ -22,7 +21,7 @@
     class Monsters_Page extends Page{
 
         /**
-         * @var \Monster[] List of monsters to show.
+         * @var Monster[] List of monsters to show.
          */
         public $monsters = [];
 

+ 3 - 3
application/page/Optimizer_Page.php

@@ -21,7 +21,7 @@
     class Optimizer_Page extends Page{
 
         /**
-         * @var \Team[] Teams to show.
+         * @Team[] Teams to show.
          */
         public $teams = [];
 
@@ -42,9 +42,9 @@
               FROM unit
               WHERE player = '" . get_context()->get_player()->get_id() . "';
             ";
-            $this->title = "Optmizer - SWDB";
+            $this->title = "Optimizer - SWDB";
             $this->description = "Optimizer";
-            $this->canonical = URL::BASE . "optmizer/";
+            $this->canonical = URL::BASE . "optimizer/";
         }
 
         /**

+ 0 - 1
application/page/Profile_Page.php

@@ -12,7 +12,6 @@
      */
     require_once(PATH::PAGE . "Page.php");
 
-
     /**
      * User profile page model.
      *

+ 1 - 1
application/page/Report_Page.php

@@ -20,7 +20,7 @@
     class Report_Page extends Page{
 
         /**
-         * @var \Filter[] Custom filters for thie rune upgrade form.
+         * @var Filter[] Custom filters for thie rune upgrade form.
          */
         public $custom_filters_runeupgrade = [];
 

+ 1 - 1
application/page/Report_Skillup_Page.php

@@ -21,7 +21,7 @@
     class Report_Skillup_Page extends Page{
 
         /**
-         * @var \Unit[] Sorted list of units.
+         * @var Unit[] Sorted list of units.
          */
         public $units = [];
 

+ 2 - 2
application/page/Runes_Page.php

@@ -1,5 +1,5 @@
  <?php
- 
+
     /**
      * Rune list page file.
      *
@@ -23,7 +23,7 @@
     class Runes_Page extends Page{
 
         /**
-         * @var \Rune[] Runes to show.
+         * @var Rune[] Runes to show.
          *
          * In this case, the monster member is not the id, but a monster
          * instance.

+ 1 - 1
application/page/Runs_Page.php

@@ -21,7 +21,7 @@
     class Runs_Page extends Page{
 
         /**
-         * @var \Run[] Runs to show.
+         * @var Run[] Runs to show.
          */
         public $runs = [];
 

+ 2 - 3
application/page/Teams_Page.php

@@ -21,16 +21,15 @@
     class Teams_Page extends Page{
 
         /**
-         * @var \Team[] Teams to show.
+         * @var Team[] Teams to show.
          */
         public $teams = [];
 
         /**
-         * @var \Unit[] List of all units for team creation.
+         * @var Unit[] List of all units for team creation.
          */
         public $units = [];
 
-
         /**
          * Constructor.
          *

+ 0 - 1
application/page/Unit_Page.php

@@ -25,7 +25,6 @@
          */
         public $unit;
 
-
         /**
          * Constructor.
          *

+ 1 - 1
application/page/Units_Page.php

@@ -22,7 +22,7 @@
     class Units_Page extends Page{
 
         /**
-         * @var \Unit[] Units to show.
+         * @var Unit[] Units to show.
          */
         public $units = [];
 

+ 2 - 2
application/view/home.php

@@ -449,7 +449,7 @@ $                           $half = sizeof(get_context()->get_player()->get_deco
                                                             break;
                                                         case AREA_TYPE_ID::RIFT_RAID:
                                                             $title = $record->area->name;
-                                                        
+
                                                     }
 ?>
                                                     <?=$title?>
@@ -530,7 +530,7 @@ $                           $half = sizeof(get_context()->get_player()->get_deco
 ?>
                                             </td>
                                         </tr>
-                                    
+
 <?php
                                     }
 ?>

+ 2 - 2
application/view/monster.php

@@ -262,7 +262,7 @@
                                                     <?=$skill->get_multiplier_formula()?>
                                                 </span>
                                             </p>
-                                            
+
                                             <div class='effects'>
 <?php
                                                 foreach ($skill->get_effects() as $effect){
@@ -349,7 +349,7 @@
                                                         <?=$skill->get_multiplier_formula()?>
                                                     </span>
                                                 </p>
-                                                
+
                                                 <div class='effects'>
 <?php
                                                     foreach ($skill->get_effects() as $effect){

+ 15 - 16
application/view/optimizer_unit.php

@@ -62,7 +62,7 @@
                 "ehp": <?=$page->unit->get_stats()["ehp"]?>,
                 "dmg": <?=$page->unit->get_stats()["dmg"]?>
             }
-            
+
             var set_stats = {
                 "atk": 0,
                 "def": 0,
@@ -73,7 +73,7 @@
                 "acc": 0,
                 "res": 0
             }
-            
+
             var base_stats = {
                 "atk": <?=$page->unit->get_base_stats()["atk"]?>,
                 "def": <?=$page->unit->get_base_stats()["def"]?>,
@@ -139,7 +139,7 @@
              * To calculate time.
              */
             var timestamp = 0;
-            
+
             /**
              * Enables or disables a new search.
              *
@@ -178,7 +178,7 @@
                 document.getElementById('lbl_min_' + stat).value = value;
                 document.getElementById('min_' + stat).value = value;
             }
-            
+
             /**
              * Resets filter to the unit's current stat status.
              *
@@ -214,7 +214,7 @@
                     element.remove(); 
                 });
             }
-            
+
             /**
              * Starts the optimization.
              *
@@ -318,7 +318,7 @@
                 if (Number(document.getElementById('min_dmg').value) > 0){
                     params += '&min_dmg=' + document.getElementById('min_dmg').value;
                 }
-                
+
                 // Clear and calculate new requested sets
                 requested_sets['RUNE_SET_<?=RUNE_SET_ID::ENERGY?>'] = 0; // ENERGY
                 requested_sets['RUNE_SET_<?=RUNE_SET_ID::GUARD?>'] = 0; // GUARD
@@ -393,7 +393,7 @@
                     Number(document.getElementById('set_2').options[document.getElementById('set_2').selectedIndex].value),
                     Number(document.getElementById('set_3').options[document.getElementById('set_3').selectedIndex].value)
                 ];
-                
+
                 for (var i = 0; i < rune_sets.length; i ++){
                     switch (rune_sets[i]){
                         case <?=RUNE_SET_ID::ENERGY?>:
@@ -451,7 +451,7 @@
                             enableNewSearch(true);
                             var time = ((+ new Date()) - timestamp) / 1000;
                             log('Error ' + this.status + '(' + time + 's)');
-                            
+
                             showMessage('Error', 'Unexpected error ' + this.status);
                         }
                     }
@@ -460,7 +460,6 @@
                 // DEBUG
                 //params = 'player=8114048&unit=6441802832&limit=6&set[]=1&set[]=1&set[]=1&stat[]=2&stat[]=2&stat[]=2&source=0&tuning=2&min_def=800';
 
-
                 // Clear result table, disable button and show spinner
                 var container = document.getElementById('optimizations');
                 while (container.firstChild) {
@@ -540,7 +539,7 @@
                                 return false;
                             }
                             break;
-                        
+
                         case <?=RUNE_SET_ID::DESPAIR?>:
                         case <?=RUNE_SET_ID::SWIFT?>:
                         case <?=RUNE_SET_ID::RAGE?>:
@@ -553,7 +552,7 @@
                             break;
                     }
                 }*/
-                
+
                 // Its a valid set, but does it match the requested sets?
                 if (JSON.stringify(sets) !== JSON.stringify(requested_sets)){
                     return false;
@@ -584,7 +583,7 @@
                 }
                 new_stats["HP"] = Math.floor(new_stats["HP"]);
                 //console.log("CANDIDATES NEW HP: " + new_stats["HP"]);
-                
+
                 new_stats["EHP"] = Math.ceil((((new_stats["DEF"] * 3.5) + 1140) * new_stats["HP"]) / 1000);
                 new_stats["DMG"] = Math.ceil((new_stats["ATK"] * (100 - new_stats["CRR"]) / 100) + ((new_stats["ATK"] + (new_stats["ATK"] * new_stats["CRD"] / 100)) * new_stats["CRR"] / 100));
                 if (
@@ -636,7 +635,7 @@
                 log(total_runes + ' runes found (' + total_combinations + ' combinations) (' + time + 's)');
                 // TODO Prevent user on high numbers
                 var checked_combinations = 0;
-                
+
                 // Valid combinations that match the minimum requeriments
                 var valid_combinations = [];
 
@@ -693,7 +692,7 @@
                     if (counters[0] >= candidates[0].length){
                         break;
                     }
-                    
+
                     /*if (checked_combinations % 1000 == 0){
                         console.log("COMBINATIONS CHECKED: " + checked_combinations + " / " + total_combinations + "(" + (checked_combinations * 100 / total_combinations) + "%)");
                         console.log("  0:  " + counters[0] + "/" + candidates[0].length);
@@ -1177,7 +1176,7 @@
                 log('Done in ' + time + ' seconds');
                 enableNewSearch(true);
             }
-            
+
             /**
              * Function to sort rune combinations based on their score.
              *
@@ -1207,7 +1206,7 @@
             function closeMessage(){
                 document.getElementById('message_container').style.display = 'none';
             }
-            
+
             /**
              * DEBUG FUNCTION
              *

+ 0 - 1
application/view/stats.php

@@ -198,7 +198,6 @@
 ?>
             }
 
-
             /**
              * Calls all required functions to draw all diagrams.
              */

+ 13 - 14
application/view/teams.php

@@ -226,7 +226,7 @@
                 xhttp.send(request);
 
             }
-            
+
             /**
              * Generates the request to delete a team.
              *
@@ -779,26 +779,26 @@
                             <tr>
                                 <td class='team <?=$odd?>'>
                                     <h4>
-                                        <img title='<?=$team->area->get_name()?>' class='area' src='<?=$team->area->get_image($team->stage)?>'/>
+                                        <img title='<?=$team->get_area()->get_name()?>' class='area' src='<?=$team->get_area()->get_image($team->get_stage())?>'/>
 <?php
-                                        if ($team->stage > 0 && $team->area->get_type() != AREA_TYPE_ID::TARTARUS_LABYRINTH){
+                                        if ($team->get_stage() > 0 && $team->get_area()->get_type() != AREA_TYPE_ID::TARTARUS_LABYRINTH){
 ?>
-                                            <span class='stage'><?=$team->stage?></span>
+                                            <span class='stage'><?=$team->get_stage()?></span>
 <?php
                                         }
 ?>
-                                        <span class='team_name'><?=$team->name?></span>
+                                        <span class='team_name'><?=$team->get_name()?></span>
                                     </h4>
                                 </td>
                                 <td class='description <?=$odd?>'>
-                                    <?=$team->description?>
+                                    <?=$team->get_description()?>
                                 </td>
                                 <td class='units <?=$odd?>'>
 <?php
                                     $prev_front = false;
                                     $front = "undefined";
-                                    foreach ($team->unit as $unit){
-                                        $front = in_array($unit->get_id(), $team->frontline);
+                                    foreach ($team->get_units() as $unit){
+                                        $front = in_array($unit->get_id(), $team->get_frontline());
                                         if ($front != "undefined" && $prev_front != $front){
 ?>
                                             <hr class='frontline'/>
@@ -809,7 +809,7 @@
                                             <div class='monster_panel'>
                                                 <?=HTML::unit_panel($unit)?>
 <?php
-                                                if ($unit->get_id() == $team->leader){
+                                                if ($unit->get_id() == $team->get_leader()){
 ?>
                                                     <img alt='Leader' class='leader' src='<?=URL::IMG["ICON"]?>leader.png'/>
 <?php
@@ -823,13 +823,13 @@
 ?>
                                 </td>
                                 <td class='score <?=$odd?>'>
-                                    <input type='number' min='0' max='20' value='<?=$team->score?>' onChange='rateTeam(<?=$team->id?>, this.value);'/>
+                                    <input type='number' min='0' max='20' value='<?=$team->get_score()?>' onChange='rateTeam(<?=$team->get_id()?>, this.value);'/>
                                 </td>
                                 <td class='action <?=$odd?>'>
-                                    <a title='Edit team' class='a_button' onclick='editTeam(<?=$team->id?>)'>
+                                    <a title='Edit team' class='a_button' onclick='editTeam(<?=$team->get_id()?>)'>
                                         <img alt='Edit team' src='<?=URL::IMG["ICON"]?>edit.png'/>
                                     </a>
-                                    <a title='Remove team' class='a_button' onclick='deleteTeam(<?=$team->id?>)'>
+                                    <a title='Remove team' class='a_button' onclick='deleteTeam(<?=$team->get_id()?>)'>
                                         <img alt='Remove team' src='<?=URL::IMG["ICON"]?>nok.png'/>
                                     </a>
                                 </td>
@@ -967,8 +967,7 @@
                         <td class='new_title'>
                             Units:
                             <!--<div class='new_unit' id='new_unit'>
-                                
-                                
+
                             </div>-->
                         </td>
                         <td id='new_units' class='new_values'>

+ 2 - 2
application/view/unit.php

@@ -494,7 +494,7 @@
 <?php
                         $l_skill = $page->unit->get_monster()->get_leader_skill();
                         if ($l_skill != null){
-                            
+
 ?>
                             <tr>
                                 <td class='skill_img'>
@@ -552,7 +552,7 @@
                                             <?=$skill->get_multiplier_formula()?>
                                         </span>
                                     </p>
-                                    
+
                                     <div class='effects'>
 <?php
                                         foreach ($skill->get_effects() as $effect){