Selaa lähdekoodia

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 vuotta sitten
vanhempi
sitoutus
8e945466fc
73 muutettua tiedostoa jossa 12162 lisäystä ja 11338 poistoa
  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){