Kaynağa Gözat

Fusion section removed. API v1 and v2 removed, v3 renamed to v1. Bug fixes, lots of TODO still in code.

Iñigo Valentin 5 yıl önce
ebeveyn
işleme
74803a2b4d
46 değiştirilmiş dosya ile 176 ekleme ve 7453 silme
  1. 32 10
      application/API/v1/API_Controller.php
  2. 0 1093
      application/API/v1/bin/log-profile.py
  3. 0 197
      application/API/v1/bin/log-run.py
  4. 1 1
      application/API/v1/help/api.php
  5. 10 10
      application/API/v1/help/index.php
  6. 0 54
      application/API/v1/log-profile/index.php
  7. 0 46
      application/API/v1/log-run/index.php
  8. 17 0
      application/API/v1/main.php
  9. 15 7
      application/API/v1/profile/DELETE.php
  10. 7 7
      application/API/v1/profile/GET.php
  11. 14 14
      application/API/v1/profile/POST.php
  12. 12 12
      application/API/v1/profile/PUT.php
  13. 53 52
      application/API/v1/run/POST.php
  14. 11 11
      application/API/v1/units/GET.php
  15. 0 75
      application/API/v2/API_Controller.php
  16. 0 382
      application/API/v2/bin/MAPPING.py
  17. 0 156
      application/API/v2/bin/update_collection.py
  18. 0 283
      application/API/v2/bin/update_logbook.py
  19. 0 1338
      application/API/v2/bin/upload_profile.py
  20. 0 249
      application/API/v2/bin/upload_run_dimension.py
  21. 0 256
      application/API/v2/bin/upload_run_dungeon.py
  22. 0 274
      application/API/v2/bin/upload_run_rift.py
  23. 0 209
      application/API/v2/bin/upload_run_scenario.py
  24. 0 228
      application/API/v2/bin/upload_run_toa.py
  25. 0 127
      application/API/v2/help/api.php
  26. 0 513
      application/API/v2/help/index.php
  27. 0 54
      application/API/v2/log-profile/index.php
  28. 0 46
      application/API/v2/log-run/index.php
  29. 0 17
      application/API/v2/main.php
  30. 0 106
      application/API/v2/units.php
  31. 0 87
      application/API/v2/update_collection.php
  32. 0 77
      application/API/v2/update_logbook.php
  33. 0 94
      application/API/v2/upload_profile.php
  34. 0 82
      application/API/v2/upload_run_dimension.php
  35. 0 82
      application/API/v2/upload_run_dungeon.php
  36. 0 99
      application/API/v2/upload_run_rift.php
  37. 0 80
      application/API/v2/upload_run_scenario.php
  38. 0 82
      application/API/v2/upload_run_toa.php
  39. 0 98
      application/API/v3/API_Controller.php
  40. 0 17
      application/API/v3/main.php
  41. 0 202
      application/entity/Fusion.php
  42. 0 96
      application/page/Fusion_Page.php
  43. 0 444
      application/view/fusion.php
  44. 2 5
      application/view/inc/header.php
  45. 0 79
      public/css/fusion.css
  46. 2 2
      swex-plugin/swdb.js

+ 32 - 10
application/API/v1/API_Controller.php

@@ -4,7 +4,7 @@
      * v1 API Controller file.
      *
      * Provides a class to handle all posible API requests.
-     * 
+     *
      * @category Constroller
      */
 
@@ -23,22 +23,44 @@
          * Handles every request, creating the required models and selecting the
          * view.
          *
-         * @param mixed[] $params GET parameters of the request.
+         * @param mixed[] $query GET parameters of the request.
          */
-        public function __construct($params){
+        public function __construct($query){
 
+            // Remove host
+            array_shift($query);
+            // Remove /API/
+            array_shift($query);
+            // Remove /v1/
+            array_shift($query);
             // API call: Use API controller
-            if (count($params) == 0){
-                require_once(__DIR__ . "main.php");
+            $method = $_SERVER["REQUEST_METHOD"];
+            if (!in_array($method, ["GET", "POST", "PUT", "DELETE"])){
+                $method = "GET";
+            }
+            if (count($query) == 0 || $query[0] == null || $query[0] == ""){
+                require_once(__DIR__ . "/main.php");
             }
             else{
-                $command = strtoupper($params[1]);
+                $command = strtolower($query[0]);
+                // Remove /<command>/
+                array_shift($query);
                 switch ($command){
-                    case "log-profile":
-                        require_once(__DIR__ . "log-profile/index.php");
+                    case "help":
+                        require_once(__DIR__ . "/help/index.php");
                         break;
-                    case "log-run":
-                        require_once(__DIR__ . "log-run/index.php");
+                    case "profile":
+                    case "run":
+                    case "logbook":
+                    case "collection":
+                    case "run":
+                    case "units":
+                        if (file_exists(__DIR__ . "/$command/$method.php")){
+                            require_once(__DIR__ . "/$command/$method.php");
+                        }
+                        else{
+                            header("HTTP/1.1 404");
+                        }
                         break;
                     default:
                         header("HTTP/1.1 404");

+ 0 - 1093
application/API/v1/bin/log-profile.py

@@ -1,1093 +0,0 @@
-#!/usr/bin/python3
-
-import sys
-import os
-import sqlite3
-import json
-import math
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        #print(sys.argv[1])
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData():
-    try:
-        #print(sys.argv[1])
-        #data = json.loads(sys.argv[1])
-        with open(sys.argv[2], 'r') as f:
-            content = f.read()
-        data = json.loads(content)
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_info"]["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and cleans the user tables.
-
-It also disables referencial integrity.
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute("attach '" + udb + "' as data;")
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Clears the user tables.
-
-It also disables referencial integrity.
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def clearData(db, data):
-    print('Clearing previous data...')
-    try:
-        uid = str(data["wizard_info"]["wizard_id"])
-        print('UID: ' + str(uid))
-        cursor = db.cursor()
-        cursor.execute('PRAGMA foreign_keys = OFF;')
-        cursor.execute('DELETE FROM scenario WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM defense WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM unit_skill WHERE unit IN (SELECT id FROM unit WHERE uid = ?)', [uid])
-        cursor.execute('DELETE FROM unit WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM rune WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM building WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM decoration WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM inventory WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM summon_special') # For every player
-        cursor.execute('DELETE FROM guild') # TODO: Dont delete all guilds
-        cursor.execute('DELETE FROM guild_member') # TODO: Dont delete all guilds, fix table
-        cursor.execute('DELETE FROM rune_craft WHERE uid = ?', [uid])
-        db.commit()
-        cursor.close();
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return
-
-
-"""
-Closes the database.
-
-Before doing so, it also disables referencial integrity.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def closeDatabase(name):
-    print('Closing database connection...')
-    try:
-        cursor = db.cursor()
-        cursor.execute('PRAGMA foreign_keys = ON;')
-        cursor.close()
-        db.commit()
-        db.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    db.execute('PRAGMA foreign_keys = OFF;')
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses player (table player).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parsePlayer(db, data):
-    print("Parsing player...")
-    cursor = db.cursor()
-    uid = data["wizard_info"]["wizard_id"]
-    name = data["wizard_info"]["wizard_name"]
-    # TODO: Generate data
-    mail = data["wizard_info"]["wizard_name"]
-    password = data["wizard_info"]["wizard_name"]
-    api_key = data["wizard_info"]["wizard_name"]
-    mana = data["wizard_info"]["wizard_mana"]
-    crystal = data["wizard_info"]["wizard_crystal"]
-    country = data["wizard_info"]["wizard_last_country"]
-    lang = data["wizard_info"]["wizard_last_lang"]
-    level = data["wizard_info"]["wizard_level"]
-    experience = data["wizard_info"]["experience"]
-    energy = data["wizard_info"]["wizard_energy"]
-    energy_max = data["wizard_info"]["energy_max"]
-    energy_per_min = data["wizard_info"]["energy_per_min"]
-    arena_energy = data["wizard_info"]["arena_energy"]
-    arena_energy_max = data["wizard_info"]["arena_energy_max"]
-    rep = data["wizard_info"]["rep_unit_id"]
-    social_point = data["wizard_info"]["social_point_current"]
-    honor_point = data["wizard_info"]["honor_point"]
-    guild_point = data["wizard_info"]["guild_point"]
-    darkportal_energy = data["wizard_info"]["darkportal_energy"]
-    darkportal_energy_max = data["wizard_info"]["darkportal_energy_max"]
-    dimension_energy = data["dimension_hole_info"]["energy"]
-    dimension_energy_max = data["dimension_hole_info"]["energy_max"]
-    costume_point = data["wizard_info"]["costume_point"]
-    costume_point_max = data["wizard_info"]["costume_point_max"]
-    honor_medal = data["wizard_info"]["honor_medal"]
-    honor_mark = data["wizard_info"]["honor_mark"]
-    event_coin = data["wizard_info"]["event_coin"]
-    storage_slots = data["unit_depository_slots"]["number"]
-    island_upgrade = 0
-    for island in data["island_info"]:
-        if island["id"] <= 7 and island["open"] == 1:
-            island_upgrade = island["id"]
-    query = '''
-        UPDATE player
-        SET mana = ?,
-            crystal = ?,
-            country = ?,
-            lang = ?,
-            level = ?,
-            experience = ?,
-            energy = ?,
-            energy_max = ?,
-            energy_per_min = ?,
-            arena_energy = ?,
-            arena_energy_max = ?,
-            rep = ?,
-            social_point = ?,
-            honor_point = ?,
-            guild_point = ?,
-            darkportal_energy = ?,
-            darkportal_energy_max = ?,
-            dimension_energy = ?,
-            dimension_energy_max = ?,
-            costume_point = ?,
-            costume_point_max = ?,
-            honor_medal = ?,
-            honor_medal = ?,
-            event_coin = ?,
-            storage_slots = ?,
-            island = ?
-        WHERE uid = ?;
-    '''
-    values = (
-        mana,                 crystal,               country,
-        lang,                 level,                 experience,
-        energy,               energy_max,            energy_per_min,
-        arena_energy,         arena_energy_max,      rep,
-        social_point,         honor_point,           guild_point,
-        darkportal_energy,    darkportal_energy_max, dimension_energy,
-        dimension_energy_max, costume_point,         costume_point_max,
-        honor_medal,          honor_medal,           event_coin,
-        storage_slots,        island_upgrade,        uid
-    )
-    try:
-        cursor.execute(query, values)
-        db.commit()
-    except sqlite3.IntegrityError as e:
-        print('Error updating player table with: ' + str(query) + ' <== ' + str(values) + ' || Error message:' +  str(e))
-        raise
-
-"""
-Parses scenarios (table scenario).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseScenarios(db, data):
-    print("Parsing scenarios...")
-    uid = data["wizard_info"]["wizard_id"]
-    for sce in data["scenario_list"]:
-        region = sce["region_id"]
-        difficulty = sce["difficulty"]
-        cleared = sce["cleared"]
-        max_cleared = 0
-        for stage in sce["stage_list"]:
-            if stage["cleared"] == 1:
-                max_cleared = stage["stage_no"]
-        insert(db, "scenario", (uid, region, difficulty, cleared, max_cleared))
-    db.commit()
-
-"""
-Parses arena defense units (table defense).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseDefense(db, data):
-    print("Parsing arena defense...")
-    uid = data["wizard_info"]["wizard_id"]
-    for defense in data["defense_unit_list"]:
-        unit = defense["unit_id"]
-        position = defense["pos_id"]
-        insert(db, "defense", (uid, unit, position))
-    db.commit()
-
-"""
-Parses buildings (table building).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseBuildings(db, data):
-    print("Parsing buildings...")
-    uid = data["wizard_info"]["wizard_id"]
-    for bui in data["building_list"]:
-        id = bui["building_id"]
-        building = bui["building_master_id"]
-        gain = bui["gain_per_hour"]
-        insert(db, "building", (uid, id, building, gain))
-    db.commit()
-
-"""
-Parses decoration buildings (table dcoration).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseDecorations(db, data):
-    print("Parsing decorations...")
-    uid = data["wizard_info"]["wizard_id"]
-    for bui in data["deco_list"]:
-        id = bui["deco_id"]
-        building = bui["master_id"]
-        level = bui["level"]
-        insert(db, "decoration", (uid, id, building, level))
-    db.commit()
-
-"""
-Parses unit data (tables unit, unit_skill).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseUnits(db, data):
-    print("Parsing monsters...")
-    uid = data["wizard_info"]["wizard_id"]
-    lock_list = data["unit_lock_list"]
-    for mon in data["unit_list"]:
-        id = mon["unit_id"]
-        building = mon["building_id"]
-        monster = mon["unit_master_id"]
-        level = mon["unit_level"]
-        stars = mon["class"]
-        hp = mon["con"] * 15 # Always x15
-        attack = mon["atk"]
-        defense = mon["def"]
-        speed = mon["spd"]
-        crit_rate = mon["critical_rate"]
-        crit_damage = mon["critical_damage"]
-        resistance = mon["resist"]
-        accuracy = mon["accuracy"]
-        experience = mon["experience"]
-        exp_gained = mon["exp_gained"]
-        exp_gain_rate = mon["exp_gain_rate"]
-        costume = mon["costume_master_id"]
-        source = mon["source"]
-        create_time = mon["create_time"]
-        homunculus_name = mon["homunculus_name"]
-        lock = 0
-        if id in lock_list:
-            lock = 1
-        insert(db, "unit", (uid, id, building, monster, level, stars, hp, attack, defense, speed, crit_rate, crit_damage, resistance, accuracy, experience, exp_gained, exp_gain_rate, costume, source, create_time, homunculus_name, lock))
-        for skill in mon["skills"]:
-            skill_id = skill[0]
-            skill_level = skill[1]
-            insert(db, "unit_skill", (id, skill_id, skill_level))
-    db.commit()
-
-"""
-Parses inventory data (table inventory).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseInventory(db, data):
-    print("Parsing inventory...")
-    uid = data["wizard_info"]["wizard_id"]
-    for item in data["inventory_info"]:
-        id = item["item_master_id"]
-        type = item["item_master_type"]
-        # TODO: Master id?
-        amount = item["item_quantity"]
-        insert(db, "inventory", (uid, id, type, amount))
-    # Fix rune craft item type.
-    cursor = db.cursor()
-    cursor.execute("UPDATE inventory SET type = 27 WHERE type = 29 AND id IN (2001, 4001, 4002, 4003, 9001, 9002, 9003, 8001);")
-    cursor.close()
-
-"""
-Parses summon stone list (table summon_special).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseSummonSpecial(db, data):
-    print("Parsing Summon stone monster list...")
-    uid = data["wizard_info"]["wizard_id"]
-    for unit in data["summon_special_info"]["this"]:
-        insert(db, "summon_special", (0, unit))
-    for unit in data["summon_special_info"]["next"]:
-        insert(db, "summon_special", (1, unit))
-    for unit in data["summon_special_info"]["third"]:
-        insert(db, "summon_special", (2, unit))
-    for unit in data["summon_special_info"]["fourth"]:
-        insert(db, "summon_special", (3, unit))
-
-"""
-Parses rune data (table rune).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseRunes(db, data):
-    print("Parsing runes...")
-    STAT_HP = 1
-    STAT_HP_PCT = 2
-    STAT_ATK = 3
-    STAT_ATK_PCT = 4
-    STAT_DEF = 5
-    STAT_DEF_PCT = 6
-    STAT_SPD = 8
-    STAT_CRIT_RATE_PCT = 9
-    STAT_CRIT_DMG_PCT = 10
-    STAT_RESIST_PCT = 11
-    STAT_ACCURACY_PCT = 12
-    MAIN_STAT_VALUES = {
-        # [stat][stars][level]: value
-        STAT_HP: {
-            1: [40, 85, 130, 175, 220, 265, 310, 355, 400, 445, 490, 535, 580, 625, 670, 804],
-            2: [70, 130, 190, 250, 310, 370, 430, 490, 550, 610, 670, 730, 790, 850, 910, 1092],
-            3: [100, 175, 250, 325, 400, 475, 550, 625, 700, 775, 850, 925, 1000, 1075, 1150, 1380],
-            4: [160, 250, 340, 430, 520, 610, 700, 790, 880, 970, 1060, 1150, 1240, 1330, 1420, 1704],
-            5: [270, 375, 480, 585, 690, 795, 900, 1005, 1110, 1215, 1320, 1425, 1530, 1635, 1740, 2088],
-            6: [360, 480, 600, 720, 840, 960, 1080, 1200, 1320, 1440, 1560, 1680, 1800, 1920, 2040, 2448],
-        },
-        STAT_HP_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
-            5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
-            6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
-        },
-        STAT_ATK: {
-            1: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 54],
-            2: [5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 73],
-            3: [7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 92],
-            4: [10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 112],
-            5: [15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 135],
-            6: [22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 160],
-        },
-        STAT_ATK_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
-            5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
-            6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
-        },
-        STAT_DEF: {
-            1: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 54],
-            2: [5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 73],
-            3: [7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 92],
-            4: [10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 112],
-            5: [15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 135],
-            6: [22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 160],
-        },
-        STAT_DEF_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
-            5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
-            6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
-        },
-        STAT_SPD: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 19, 21, 25],
-            4: [4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 30],
-            5: [5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 39],
-            6: [7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 42],
-        },
-        STAT_CRIT_RATE_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 37],
-            4: [4, 6, 8, 11, 13, 15, 17, 19, 22, 24, 26, 28, 30, 33, 35, 41],
-            5: [5, 7, 10, 12, 15, 17, 19, 22, 24, 27, 29, 31, 34, 36, 39, 47],
-            6: [7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 58],
-        },
-        STAT_CRIT_DMG_PCT: {
-            1: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            2: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 37],
-            3: [4, 6, 9, 11, 13, 16, 18, 20, 22, 25, 27, 29, 32, 34, 36, 43],
-            4: [6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 57],
-            5: [8, 11, 15, 18, 21, 25, 28, 31, 34, 38, 41, 44, 48, 51, 54, 65],
-            6: [11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 80],
-        },
-        STAT_RESIST_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [6, 8, 10, 13, 15, 17, 19, 21, 24, 26, 28, 30, 32, 35, 37, 44],
-            5: [9, 11, 14, 16, 19, 21, 23, 26, 28, 31, 33, 35, 38, 40, 43, 51],
-            6: [12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 64],
-        },
-        STAT_ACCURACY_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [6, 8, 10, 13, 15, 17, 19, 21, 24, 26, 28, 30, 32, 35, 37, 44],
-            5: [9, 11, 14, 16, 19, 21, 23, 26, 28, 31, 33, 35, 38, 40, 43, 51],
-            6: [12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 64],
-        },
-    }
-    SUBSTAT_INCREMENTS = {
-        # [stat][stars]: value
-        # Max possible substat value can be found by multiplying by 5
-        STAT_HP: {
-            1: 60,
-            2: 105,
-            3: 165,
-            4: 225,
-            5: 300,
-            6: 375,
-        },
-        STAT_HP_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ATK: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_ATK_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_DEF: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_DEF_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_SPD: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_RATE_PCT: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_DMG_PCT: {
-            1: 2,
-            2: 3,
-            3: 4,
-            4: 5,
-            5: 6,
-            6: 7,
-        },
-        STAT_RESIST_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ACCURACY_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-    }
-    uid = data["wizard_info"]["wizard_id"]
-    # Unequipped runes
-    for rune in data["runes"]:
-        id = rune["rune_id"]
-        assigned_to = rune["occupied_id"]
-        if assigned_to == 0:
-            assigned_to = None
-        runeset = rune["set_id"]
-        slot = rune["slot_no"]
-        stars = rune["class"]
-        ancient = 0
-        level = rune["upgrade_curr"]
-        original_quality = rune["extra"]
-        value = rune["sell_value"]
-        if stars > 10:
-            ancient = 1
-            stars = stars - 10
-            original_quality = original_quality - 10
-        if level >= 12:
-            quality = 5
-        elif level >= 9:
-            quality = 4
-        elif level >= 6:
-            quality = 3
-        elif level >= 3:
-            quality = 2
-        else:
-            quality = 1
-        if original_quality > quality:
-            quality = original_quality
-        # TODO: Calculate
-        #efficiency = rune["efficiency"]
-        #max_efficiency = rune["max_efficiency"]
-        efficiency = 0
-        max_efficiency = 0
-        main_stat = rune["pri_eff"][0]
-        main_stat_value = rune["pri_eff"][1]
-        if rune["prefix_eff"][0] > 0:
-            innate_stat = rune["prefix_eff"][0]
-            innate_stat_value = rune["prefix_eff"][1]
-        else:
-            innate_stat = None
-            innate_stat_value = 0
-        if len(rune["sec_eff"]) > 0:
-            substat_1 = rune["sec_eff"][0][0]
-            substat_1_value = rune["sec_eff"][0][1]
-            substat_1_enchant = rune["sec_eff"][0][2]
-            substat_1_grind = rune["sec_eff"][0][3]
-        else:
-            substat_1 = None
-            substat_1_value = 0
-            substat_1_enchant = 0
-            substat_1_grind = 0
-        if len(rune["sec_eff"]) > 1:
-            substat_2 = rune["sec_eff"][1][0]
-            substat_2_value = rune["sec_eff"][1][1]
-            substat_2_enchant = rune["sec_eff"][1][2]
-            substat_2_grind = rune["sec_eff"][1][3]
-        else:
-            substat_2 = None
-            substat_2_value = 0
-            substat_2_enchant = 0
-            substat_2_grind = 0
-        if len(rune["sec_eff"]) > 2:
-            substat_3 = rune["sec_eff"][2][0]
-            substat_3_value = rune["sec_eff"][2][1]
-            substat_3_enchant = rune["sec_eff"][2][2]
-            substat_3_grind = rune["sec_eff"][2][3]
-        else:
-            substat_3 = None
-            substat_3_value = 0
-            substat_3_enchant = 0
-            substat_3_grind = 0
-        if len(rune["sec_eff"]) > 3:
-            substat_4 = rune["sec_eff"][3][0]
-            substat_4_value = rune["sec_eff"][3][1]
-            substat_4_enchant = rune["sec_eff"][3][2]
-            substat_4_grind = rune["sec_eff"][3][3]
-        else:
-            substat_4 = None
-            substat_4_value = 0
-            substat_4_enchant = 0
-            substat_4_grind = 0
-
-        # Calculate efficiences
-        efficiency = 0
-        substats = []
-        efficiency += float(MAIN_STAT_VALUES[main_stat][stars][15]) / float(MAIN_STAT_VALUES[main_stat][6][15])
-        if innate_stat is not None:
-            efficiency += innate_stat_value / float(SUBSTAT_INCREMENTS[innate_stat][6] * 5)
-        if substat_1 is not None:
-            substats.append(substat_1)
-            efficiency += substat_1_value / float(SUBSTAT_INCREMENTS[substat_1][6] * 5)
-        if substat_2 is not None:
-            substats.append(substat_2)
-            efficiency += substat_2_value / float(SUBSTAT_INCREMENTS[substat_2][6] * 5)
-        if substat_3 is not None:
-            substats.append(substat_3)
-            efficiency += substat_3_value / float(SUBSTAT_INCREMENTS[substat_3][6] * 5)
-        if substat_4 is not None:
-            substats.append(substat_4)
-            efficiency += substat_4_value / float(SUBSTAT_INCREMENTS[substat_4][6] * 5)
-        efficiency = efficiency / 2.8 * 100
-        max_efficiency = get_max_efficiency(substats, efficiency, level, stars, original_quality)
-        if efficiency > 100:
-            efficiency = 100;
-        if max_efficiency > 100:
-            max_efficiency = 100;
-        insert(db, "rune", (uid, id, assigned_to, runeset, slot, stars, ancient, level, quality, original_quality, value, efficiency, max_efficiency, main_stat, main_stat_value, innate_stat, innate_stat_value, substat_1, substat_1_value, substat_1_enchant, substat_1_grind, substat_2, substat_2_value, substat_2_enchant, substat_2_grind, substat_3, substat_3_value, substat_3_enchant, substat_3_grind, substat_4, substat_4_value, substat_4_enchant, substat_4_grind))
-    # Equipped runes
-    for mon in data["unit_list"]:
-        for rune in mon["runes"]:
-            id = rune["rune_id"]
-            assigned_to = rune["occupied_id"]
-            if assigned_to == 0:
-                assigned_to = None
-            runeset = rune["set_id"]
-            slot = rune["slot_no"]
-            stars = rune["class"]
-            ancient = 0
-            level = rune["upgrade_curr"]
-            original_quality = rune["extra"]
-            value = rune["sell_value"]
-            if stars > 10:
-                ancient = 1
-                stars = stars - 10
-                original_quality = original_quality - 10
-            if level >= 12:
-                quality = 4
-            elif level >= 9:
-                quality = 3
-            elif level >= 6:
-                quality = 2
-            elif level >= 3:
-                quality = 1
-            else:
-                quality = 0
-            if original_quality > quality:
-                quality = original_quality
-            # TODO: Calculate
-            #efficiency = rune["efficiency"]
-            #max_efficiency = rune["max_efficiency"]
-            efficiency = 0
-            max_efficiency = 0
-            main_stat = rune["pri_eff"][0]
-            main_stat_value = rune["pri_eff"][1]
-            if rune["prefix_eff"][0] > 0:
-                innate_stat = rune["prefix_eff"][0]
-                innate_stat_value = rune["prefix_eff"][1]
-            else:
-                innate_stat = None
-                innate_stat_value = 0
-            if len(rune["sec_eff"]) > 0:
-                substat_1 = rune["sec_eff"][0][0]
-                substat_1_value = rune["sec_eff"][0][1]
-                substat_1_enchant = rune["sec_eff"][0][2]
-                substat_1_grind = rune["sec_eff"][0][3]
-            else:
-                substat_1 = None
-                substat_1_value = 0
-                substat_1_enchant = 0
-                substat_1_grind = 0
-            if len(rune["sec_eff"]) > 1:
-                substat_2 = rune["sec_eff"][1][0]
-                substat_2_value = rune["sec_eff"][1][1]
-                substat_2_enchant = rune["sec_eff"][1][2]
-                substat_2_grind = rune["sec_eff"][1][3]
-            else:
-                substat_2 = None
-                substat_2_value = 0
-                substat_2_enchant = 0
-                substat_2_grind = 0
-            if len(rune["sec_eff"]) > 2:
-                substat_3 = rune["sec_eff"][2][0]
-                substat_3_value = rune["sec_eff"][2][1]
-                substat_3_enchant = rune["sec_eff"][2][2]
-                substat_3_grind = rune["sec_eff"][2][3]
-            else:
-                substat_3 = None
-                substat_3_value = 0
-                substat_3_enchant = 0
-                substat_3_grind = 0
-            if len(rune["sec_eff"]) > 3:
-                substat_4 = rune["sec_eff"][3][0]
-                substat_4_value = rune["sec_eff"][3][1]
-                substat_4_enchant = rune["sec_eff"][3][2]
-                substat_4_grind = rune["sec_eff"][3][3]
-            else:
-                substat_4 = None
-                substat_4_value = 0
-                substat_4_enchant = 0
-                substat_4_grind = 0
-
-            # Calculate efficiences
-            efficiency = 0
-            substats = []
-            efficiency += float(MAIN_STAT_VALUES[main_stat][stars][15]) / float(MAIN_STAT_VALUES[main_stat][6][15])
-            if innate_stat is not None:
-                efficiency += innate_stat_value / float(SUBSTAT_INCREMENTS[innate_stat][6] * 5)
-            if substat_1 is not None:
-                substats.append(substat_1)
-                efficiency += substat_1_value / float(SUBSTAT_INCREMENTS[substat_1][6] * 5)
-            if substat_2 is not None:
-                substats.append(substat_2)
-                efficiency += substat_2_value / float(SUBSTAT_INCREMENTS[substat_2][6] * 5)
-            if substat_3 is not None:
-                substats.append(substat_3)
-                efficiency += substat_3_value / float(SUBSTAT_INCREMENTS[substat_3][6] * 5)
-            if substat_4 is not None:
-                substats.append(substat_4)
-                efficiency += substat_4_value / float(SUBSTAT_INCREMENTS[substat_4][6] * 5)
-            efficiency = efficiency / 2.8 * 100
-            max_efficiency = get_max_efficiency(substats, efficiency, level, stars, original_quality)
-            if efficiency > 100:
-                efficiency = 100;
-            if max_efficiency > 100:
-                max_efficiency = 100;
-            insert(db, "rune", (uid, id, assigned_to, runeset, slot, stars, ancient, level, quality, original_quality, value, efficiency, max_efficiency, main_stat, main_stat_value, innate_stat, innate_stat_value, substat_1, substat_1_value, substat_1_enchant, substat_1_grind, substat_2, substat_2_value, substat_2_enchant, substat_2_grind, substat_3, substat_3_value, substat_3_enchant, substat_3_grind, substat_4, substat_4_value, substat_4_enchant, substat_4_grind))
-    db.commit()
-
-"""
-calculates the max efficiency of a rune.
-
-:param substats: Array of substat types, dont include empty ones.
-:param efficiency: Current rune efficiency.
-:param level: Current rune level.
-:param stars: Rune stars.
-:param quality: Rune original quality.
-:return Max. efficiency.
-"""
-def get_max_efficiency(substats, efficiency, level, stars, quality):
-    STAT_HP = 1
-    STAT_HP_PCT = 2
-    STAT_ATK = 3
-    STAT_ATK_PCT = 4
-    STAT_DEF = 5
-    STAT_DEF_PCT = 6
-    STAT_SPD = 8
-    STAT_CRIT_RATE_PCT = 9
-    STAT_CRIT_DMG_PCT = 10
-    STAT_RESIST_PCT = 11
-    STAT_ACCURACY_PCT = 12
-    SUBSTAT_INCREMENTS = {
-        # [stat][stars]: value
-        STAT_HP: {
-            1: 60,
-            2: 105,
-            3: 165,
-            4: 225,
-            5: 300,
-            6: 375,
-        },
-        STAT_HP_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ATK: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_ATK_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_DEF: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_DEF_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_SPD: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_RATE_PCT: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_DMG_PCT: {
-            1: 2,
-            2: 3,
-            3: 4,
-            4: 5,
-            5: 6,
-            6: 7,
-        },
-        STAT_RESIST_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ACCURACY_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-    }
-    UPGRADE_VALUES = {
-        rune_type: {
-            stars: value/level_data[6]
-            for stars, value in level_data.items()
-        }
-        for rune_type, level_data in SUBSTAT_INCREMENTS.items()
-    }
-    #substat_upgrades_remaining = (4 - math.floor((min(level, 12) / 3))) - (3 - quality)
-    substat_upgrades_remaining = (4 - math.floor((min(level, 12) / 3))) - max((3 - quality), 0)
-    new_stats = max(min(4 - len(substats), substat_upgrades_remaining), 0)
-    old_stats = substat_upgrades_remaining - new_stats
-
-    if old_stats > 0:
-        # we can repeatedly upgrade the most value of the existing stats
-        best_stat = max(
-            0,  # ensure max() doesn't error if we only have one stat
-            *[UPGRADE_VALUES[stat][stars] for stat in substats]
-        )
-        efficiency += best_stat * old_stats * 0.2 / 2.8 * 100
-    if new_stats:
-        # add the top N stats
-        available_upgrades = sorted(
-            [
-                upgrade_value[stars]
-                for stat, upgrade_value in UPGRADE_VALUES.items()
-                if stat not in substats
-            ],
-            reverse=True
-        )
-        efficiency += sum(available_upgrades[:new_stats]) * 0.2 / 2.8 * 100
-
-    return efficiency
-
-"""
-Parses rune craft item data (table rune_craft).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseRuneCraft(db, data):
-    print("Parsing rune craft itmes...")
-    uid = data["wizard_info"]["wizard_id"]
-    for item in data["rune_craft_item_list"]:
-        id = item["craft_item_id"]
-        type = item["craft_type"]
-        value = item["sell_value"]
-        info = str(item["craft_type_id"])
-        """
-        info : 5 or 6 digit number: RRSSQ
-          RR: Rune
-          SS: Stat
-          Q:  Quality
-        """
-        quality = int(info[-1:])
-        stat = int(info[-4:-2])
-        rune = int(info[:-4])
-        insert(db, "rune_craft", (uid, id, type, quality, rune, stat, value))
-
-"""
-Parses guild data (tables guild, guild_member).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseGuild(db, data):
-    print("Parsing guild...")
-    if (data["guild"]["guild_info"] == None):
-        # No guild
-        return
-    if len(data["guild"]["guild_info"]) < 1:
-        return
-    guild = data["guild"]["guild_info"]
-    id = guild["guild_id"]
-    name = guild["name"]
-    level = guild["level"]
-    experience = guild["experience"]
-    recruiting = guild["recruit_status"]
-    members = guild["member_now"]
-    leader = guild["master_wizard_id"]
-    comment = guild["comment"]
-    notice = guild["notice"]
-    insert(db, "guild", (id, name, level, experience, recruiting, members, leader, comment, notice))
-    # Single quates ahead, dirty fix
-    for k, member in data["guild"]["guild_members"].items():
-        m = json.loads(str(member).replace("'", '"'))
-        id = m["wizard_id"]
-        guild = member["guild_id"]
-        grade = member["grade"]
-        name = member["wizard_name"]
-        level = member["wizard_level"]
-        rating = member["rating_id"]
-        arena_score = member["arena_score"]
-        joined = member["join_timestamp"]
-        last_login = member["last_login_timestamp"]
-        in_war = 0 # Checked later
-        has_defense = 0 # Checked later
-        insert(db, "guild_member", (id, guild, grade, name, level, rating, arena_score, joined, last_login, in_war, has_defense))
-    cursor = db.cursor()
-    for war in data["guildwar_member_list"]:
-        cursor.execute("UPDATE guild_member SET in_war = 1 WHERE guild = ? AND id = ?;", (war["guild_id"], war["wizard_id"]))
-    for defense in data["guild_member_defense_list"]:
-        if len(defense["unit_list"]) > 0:
-            cursor.execute("UPDATE guild_member SET has_defense = 1 WHERE id = '" + str(defense["wizard_id"]) + "';")
-    db.commit()
-    cursor.close()
-
-"""
-Deletes teams whose members no longer exists.
-
-:param db: Sqlite database connection.
-"""
-def reconfigureTeams(db):
-    print("Fixing teams...")
-    uid = data["wizard_info"]["wizard_id"]
-    cursor = db.cursor()
-    cursor.execute("DELETE FROM team WHERE id IN (SELECT DISTINCT team FROM team_unit WHERE unit NOT IN (SELECT DISTINCT id FROM unit WHERE uid = " + str(uid) + ")) AND uid = " + str(uid) + ";")
-    cursor.execute("DELETE FROM team_unit WHERE unit NOT IN (SELECT DISTINCT id FROM unit) OR team NOT IN (SELECT DISTINCT id FROM team);")
-    db.commit()
-    cursor.close()
-
-"""
-Begin script
-"""
-data = readData()
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(-1)
-else:
-    clearData(db, data)
-    parsePlayer(db, data)
-    parseScenarios(db, data)
-    parseDefense(db, data)
-    parseBuildings(db, data)
-    parseDecorations(db, data)
-    # TODO homunculus_skill_list
-    parseUnits(db, data)
-    parseSummonSpecial(db, data)
-    parseInventory(db, data)
-    parseRunes(db, data)
-    parseRuneCraft(db, data)
-    parseGuild(db, data)
-    reconfigureTeams(db)
-    closeDatabase(db)
-sys.exit(0);
-

+ 0 - 197
application/API/v1/bin/log-run.py

@@ -1,197 +0,0 @@
-#!/usr/bin/python3
-
-import sqlite3
-import json
-import sys
-import os
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        #print(sys.argv[0])
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData():
-    try:
-        print(sys.argv[2])
-        data = json.loads(sys.argv[2])
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["uid"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and deletes from the user tables
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute('attach "' + udb + '" as data;')
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
-run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
-run_drop_shapeshifting).
-
-:param db: Sqlite database connection.
-:param data: JSON data.
-"""
-def parseRun(db, data):
-    print("Parsing run...")
-    cursor = db.cursor()
-    uid = data["uid"]
-    dtime = data["dtime"]
-    # Check if run has already been inserted.
-    cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime))
-    if (cursor.fetchone()[0] > 0):
-        print("    Run already in database. Stopping....")
-        return;
-    area = data["area"]
-    stage = data["stage"]
-    difficulty = data["difficulty"]
-    win = data["win"]
-    time = data["time"]
-    mana = data["mana"]
-    energy = data["energy"]
-    crystal = data["crystal"]
-    helper = data["helper"]
-    cursor.execute("SELECT max(id) + 1 AS id FROM run;")
-    id = cursor.fetchone()[0]
-    if id == None:
-        id = 1
-    insert(db, "run", (uid, id, dtime, area, stage, difficulty, win, time, mana, energy, crystal, helper))
-    if data["shapeshifting"] > 0:
-        insert(db, "run_drop_shapeshifting", (id, data["shapeshifting"]))
-    if data["sd"] > 0:
-        insert(db, "run_drop_sd", (id, data["sd"]))
-    if data["sd"] > 0:
-        insert(db, "run_drop_unit", (id, data["unit"]))
-    for rune in data["rune"]:
-        rune_id = rune["id"]
-        rune_type = rune["type"]
-        slot = rune["slot"]
-        stars = rune["stars"]
-        ancient = rune["ancient"]
-        quality = rune["quality"]
-        value = rune["value"]
-        efficiency = rune["efficiency"]
-        main_stat = rune["main_stat"]
-        main_stat_value = rune["main_stat_value"]
-        innate_stat = rune["innate_stat"]
-        innate_stat_value = rune["innate_stat_value"]
-        substat_1 = rune["substat_1"]
-        substat_1_value = rune["substat_1_value"]
-        substat_2 = rune["substat_2"]
-        substat_2_value = rune["substat_2_value"]
-        substat_3 = rune["substat_3"]
-        substat_3_value = rune["substat_3_value"]
-        substat_4 = rune["substat_4"]
-        substat_4_value = rune["substat_4_value"]
-        insert(db, "run_drop_rune", (id, rune_id, rune_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))
-    for item in data["item"]:
-        item_id = item["id"]
-        quantity = item["quantity"]
-        insert(db, "run_drop_item", (id, item_id, quantity))
-    for pieces in data["unit_pieces"]:
-        pieces_id = pieces["id"]
-        quantity = pieces["quantity"]
-        insert(db, "run_drop_unit_pieces", (id, pieces_id, quantity))
-    for party in data["party"]:
-        unit_id = party["unit_id"]
-        unit_master_id = party["unit_master_id"]
-        insert(db, "run_party", (id, unit_master_id, unit_id))
-    db.commit()
-
-"""
-Begin script
-"""
-data = readData()
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(-1)
-else:
-    parseRun(db, data)
-sys.exit(0)
-
-

+ 1 - 1
application/API/v3/help/api.php → application/API/v1/help/api.php

@@ -4,7 +4,7 @@
      * @var mixed[] $API API help structure.
      */
     $API = [
-        "version" => 2,
+        "version" => 1,
         "category" => [
             [ // BEGIN CATEGORY Units
                 "name" => "Units",

+ 10 - 10
application/API/v3/help/index.php → application/API/v1/help/index.php

@@ -16,7 +16,7 @@
     <head>
         <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
         <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title>SWDB APIv3</title>
+        <title>SWDB APIv1</title>
         <link rel='shortcut icon' href='<?=URL::IMG["LOGO"]?>sw.png'/>
         <!-- CSS -->
         <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
@@ -266,22 +266,22 @@
             }
         </script>
         <!-- Meta tags -->
-        <link rel='canonical' href='<?=URL::BASE?>API/v3/help/'/>
+        <link rel='canonical' href='<?=URL::BASE?>API/v1/help/'/>
         <link rel='author' href='SWDB'/>
         <link rel='publisher' href='SWDB'/>
-        <meta name='description' content='SWDB API v3 Documentation'/>
-        <meta property='og:title' content='SWDB APIv3'/>
-        <meta property='og:url' content='<?=URL::BASE?>API/v3/help/'/>
-        <meta property='og:description' content='SWDB API v3 Documentation'/>
+        <meta name='description' content='SWDB API v1 Documentation'/>
+        <meta property='og:title' content='SWDB APIv1'/>
+        <meta property='og:url' content='<?=URL::BASE?>API/v1/help/'/>
+        <meta property='og:description' content='SWDB API v1 Documentation'/>
         <meta property='og:image' content='<?=URL::IMG["LOGO"]?>sw.png'/>
         <meta property='og:site_name' content='SWDB'/>
         <meta property='og:type' content='website'/>
         <meta property='og:locale' content='en'/>
         <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='SWDB APIv3'/>
-        <meta name='twitter:description' content='SWDB API v3 Documentation'/>
+        <meta name='twitter:title' content='SWDB APIv1'/>
+        <meta name='twitter:description' content='SWDB API v1 Documentation'/>
         <meta name='twitter:image' content='<?=URL::IMG["LOGO"]?>sw.png'/>
-        <meta name='twitter:url' content='<?=URL::BASE?>API/v3/help/'/>
+        <meta name='twitter:url' content='<?=URL::BASE?>API/v1/help/'/>
         <meta name='robots' content='index follow'/>
     </head>
     <body>
@@ -298,7 +298,7 @@
         </header>
         <aside>
             <h2>
-                API v3 endopoints:
+                API v1 endopoints:
             </h2>
 <?php
             foreach ($API["category"] as $category){

+ 0 - 54
application/API/v1/log-profile/index.php

@@ -1,54 +0,0 @@
-<?php
-    /**
-     * Profile uploader script.
-     *
-     * Exposes an API to save a run to the database.
-     * Reads post data and calls the log-profile.py script.
-     * It also saves the data to a JSON file in the da directory.
-     * Mandatory POST parameters are:
-     *  - data: Received JSON file after a run.
-     *  - key: User API key.
-     *
-     * @category API
-     */
-
-    $status = 200;
-    if (isset($_POST["data"]) && isset($_POST["key"])){
-        $data = $_POST["data"];
-        $key = $_POST["key"];
-        if (json_decode($data) === null){
-            error_log("ERROR: API v1 log-profile: Invalid JSON");
-            $status = 400;
-        }
-        else{
-            $json = json_decode($data);
-            $winfo = $json->{"wizard_info"};
-            $uname = $winfo->{"wizard_name"};
-            $uid = $winfo->{"wizard_id"};
-            $dtime = (new DateTime())->format('Y-m-dTH:i:s');
-            $fname = ($_SERVER["DOCUMENT_ROOT"] . "/../data/profile_" . $uid . "_" . $uname . "_" . $dtime . ".json");
-            file_put_contents($fname, $data);
-            $cmd =  __DIR__ . "../bin/log-profile.py " . $key . " " . $fname;
-            $out = [];
-            $ret = 0;
-            exec($cmd, $out, $ret);
-            if ($ret != 0){
-                error_log("ERROR: API v1 log-profile exited with status: " . $ret);
-                error_log("====================");
-                error_log("|| SCRIPT OUTPUT: ||");
-                error_log("===============================================================================");
-                foreach($out as $line){
-                    error_log("|| " . $line);
-                }
-                error_log("===============================================================================");
-                $status = 400;
-            }
-        }
-    }
-    else{
-        error_log("ERROR: API v1 log-profile: Invalid JSON");
-        $status = 400;
-    }
-    http_response_code($status);
-    return $status;
-?>

+ 0 - 46
application/API/v1/log-run/index.php

@@ -1,46 +0,0 @@
-<?php
-    /**
-     * Run logger script.
-     *
-     * Exposes an API to save a run to the database.
-     * Reads post data and calls the log-run.py script.
-     * Mandatory POST parameters are:
-     *  - data: Received JSON file after a run.
-     *  - key: User API key.
-     *
-     * @category API
-     */
-
-    $status = 200;
-    if (isset($_POST["data"]) && isset($_POST["key"])){
-        $data = $_POST["data"];
-        $key = $_POST["key"];
-        if (json_decode($data) === null){
-            error_log("ERROR: API v1 log-run: Invalid JSON");
-            $status = 400;
-        }
-        else{
-            $cmd = __DIR__ . "../bin/log-run.py " . $key . " " . escapeshellarg($data);
-            $out = [];
-            $ret = 0;
-            exec($cmd, $out, $ret);
-            if ($ret != 0){
-                error_log("ERROR: API v1 log-run exited with status: " . $ret);
-                error_log("====================");
-                error_log("|| SCRIPT OUTPUT: ||");
-                error_log("===============================================================================");
-                foreach($out as $line){
-                    error_log("|| " . $line);
-                }
-                error_log("===============================================================================");
-                $status = 400;
-            }
-        }
-    }
-    else{
-        error_log("ERROR: API v1 log-run: Invalid JSON");
-        $status = 400;
-    }
-    http_response_code($status);
-    return $status;
-?>

+ 17 - 0
application/API/v1/main.php

@@ -0,0 +1,17 @@
+<?php
+    header("Content-Type:application/json");
+    $links = [
+        "Archetypes" => URL::BASE . "/API/v1/archetypes",
+        "Area types" => URL::BASE . "/API/v1/area_types",
+        "Areas types" => URL::BASE . "/API/v1/areas",
+        "Buildings" => URL::BASE . "/API/v1/buildings",
+        "Decorations" => URL::BASE . "/API/v1/decorations",
+        "Areas types" => URL::BASE . "/API/v1/areas",
+        "Units" => URL::BASE . "/API/v1/units",
+        "Skills" => URL::BASE . "/API/v1/skills",
+        "Skill effects" => URL::BASE . "/API/v1/skill_efects",
+    ];
+    header("HTTP/1.1 200");
+    $json_response = json_encode($links);
+    echo $json_response;
+?>

+ 15 - 7
application/API/v3/profile/DELETE.php → application/API/v1/profile/DELETE.php

@@ -33,7 +33,7 @@
         else{
             // ID is mandatory
             header("HTTP/1.1 400 User ID not received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 User ID not received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User ID not received.");
             return 400;
         }
 
@@ -41,7 +41,7 @@
         $api_key = $_DELETE["key"];
         if ($api_key == null || $api_key == false){
             header("HTTP/1.1 400 API key not received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 API key not received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
             return 400;
         }
 
@@ -51,27 +51,35 @@
         $statement->bindValue(":api_key", $api_key, SQLITE3_TEXT);
         if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
             header("HTTP/1.1 401 Invalid credentials.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
             return 401;
         }
 
         $statement = $db->prepare("
-          DELETE FROM player
+          DELETE FROM data.player
           WHERE
             uid = :uid AND
-            api_key, = :api_key;
+            id IN (
+              SELECT player.id
+              FROM
+                data.player player,
+                data.user user
+              WHERE
+                player.user = user.id AND
+                user.api_key = :api_key
+            );
         ");
         $statement->bindValue(":uid", $id, SQLITE3_INTEGER);
         $statement->bindValue(":api_key", $api_key, SQLITE3_TEXT);
         $statement->execute();
 
         header("HTTP/1.1 204 Profile deleted.");
-        syslog(LOG_INFO, "[APIv3] HTTP/1.1 204 Profile deleted.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 204 Profile deleted.");
         return 204;
     }
     catch(Exception $e) {
         header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
         return 500;
     }
 ?>

+ 7 - 7
application/API/v3/profile/GET.php → application/API/v1/profile/GET.php

@@ -28,23 +28,23 @@
         else{
             // Id is mandatory, a list can be retrieved
             header("HTTP/1.1 403 A list of profiles cant be retrieved. Please specify a profile ID or player name.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 403 A list of profiles cant be retrieved. Please specify a profile ID or player name.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 403 A list of profiles cant be retrieved. Please specify a profile ID or player name.");
             return 403;
         }
 
         // Get player
-        $statement = $db->prepare("SELECT * FROM player WHERE uid = :uid OR upper(name) = upper(:uid);");
-        $statement->bindValue(":uid", $id, SQLITE3_INTEGER);
+        $statement = $db->prepare("SELECT * FROM player WHERE id = :uid OR upper(name) = upper(:id);");
+        $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
         if ($r == null){
             // No player found
             header("HTTP/1.1 404 Player not found.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 404 Player not found.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 404 Player not found.");
             return 403;
         }
         if ($r["public"] != 1 && $r["key"] != filter_input(INPUT_GET, "key")){
             header("HTTP/1.1 403 The profile is not public.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 403 The profile is not public.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 403 The profile is not public.");
             return 403;
         }
 
@@ -56,12 +56,12 @@
         ];
         echo(json_encode($player));
         header("HTTP/1.1 200 Success.");
-        syslog(LOG_INFO, "[APIv3] HTTP/1.1 200 Success.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 200 Success.");
         return 200;
     }
     catch(Exception $e) {
         header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
         return 500;
     }
 ?>

+ 14 - 14
application/API/v3/profile/POST.php → application/API/v1/profile/POST.php

@@ -35,7 +35,7 @@
         else{
             // ID is mandatory
             header("HTTP/1.1 400 User ID not received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 User ID not received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User ID not received.");
             return 400;
         }
 
@@ -43,19 +43,19 @@
         $mail = $_POST["email"];
         if ($mail == null || $mail == false){
             header("HTTP/1.1 400 User email not received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 User email not received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User email not received.");
             return 400;
         }
         if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) {
             header("HTTP/1.1 400 Invalid email.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 Invalid email.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Invalid email.");
             return 400;
         }
         // Check user password.
         $password = $_POST["password"];
         if ($password == null || $password == false){
             header("HTTP/1.1 400 User password not received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 User password not received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 User password not received.");
             return 400;
         }
         // Check user name.
@@ -70,11 +70,11 @@
         }
 
         // Check if player exists
-        $statement = $db->prepare("SELECT COUNT(uid) AS c FROM player WHERE uid = :uid;");
-        $statement->bindValue(":uid", $id, SQLITE3_INTEGER);
+        $statement = $db->prepare("SELECT COUNT(uid) AS c FROM data.player WHERE id = :id;");
+        $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
             header("HTTP/1.1 400 Existing user.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 Existing user.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Existing user.");
             return 400;
         }
 
@@ -88,9 +88,11 @@
         }
 
         // Insert
+        // TODO: Get user ID, check fields
         $statement = $db->prepare("
-          INSERT INTO player (
-            uid,
+          INSERT INTO data.player (
+            id,
+            user,
             name,
             mail,
             password,
@@ -157,7 +159,7 @@
             :public
           );
         ");
-        $statement->bindValue(":uid", $id, SQLITE3_INTEGER);
+        $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $statement->bindValue(":name", $name, SQLITE3_TEXT);
         $statement->bindValue(":mail", $mail, SQLITE3_TEXT);
         $statement->bindValue(":password", $password, SQLITE3_TEXT);
@@ -194,18 +196,16 @@
         // Build array
         $player = [
             "username" => $name,
-            "email" => $mail,
-            "api_key" => $api_key,
             "public" => "1"
         ];
         echo(json_encode($player));
         header("HTTP/1.1 201 Created.");
-        syslog(LOG_INFO, "[APIv3] HTTP/1.1 201 Created.");
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 201 Created.");
         return 201;
     }
     catch(Exception $e) {
         header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
         return 500;
     }
 ?>

+ 12 - 12
application/API/v3/profile/PUT.php → application/API/v1/profile/PUT.php

@@ -403,7 +403,7 @@
         }
         catch(Exception $e) {
             header("HTTP/1.1 500 Unable to save profile file: " . $e->getMessage());
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 500 Unable to save profile file: " . $e->getMessage());
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 500 Unable to save profile file: " . $e->getMessage());
             return 500;
         }
 
@@ -1419,7 +1419,7 @@
         $key = $_PUT["key"];
         if ($key == null || $key == false){
             header("HTTP/1.1 400 API key not received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 API key not received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
             return 400;
         }
 
@@ -1427,7 +1427,7 @@
         $data = $_PUT["response"];
         if ($data == null || $data == false){
             header("HTTP/1.1 400 No data received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 No data received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 No data received.");
             return 400;
         }
 
@@ -1435,7 +1435,7 @@
         $json = json_decode($data);
         if ($json === null){
             header("HTTP/1.1 400 Data is no valid JSON.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 Data is no valid JSON.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Data is no valid JSON.");
             return 400;
         }
 
@@ -1448,7 +1448,7 @@
         ];
         if (!in_array($command, $accepted_commands)){
             header("HTTP/1.1 405 Command not implemented.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 405 Command not implemented.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 405 Command not implemented.");
             return 405;
         }
 
@@ -1469,7 +1469,7 @@
                 $statement->bindValue(":api_key", $key, SQLITE3_TEXT);
                 if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
                     header("HTTP/1.1 401 Invalid credentials.");
-                    syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
+                    syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
                     return 401;
                 }
                 break;
@@ -1484,7 +1484,7 @@
                 }
                 else{
                     header("HTTP/1.1 401 Invalid credentials.");
-                    syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
+                    syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
                     return 401;
                 }
                 break;
@@ -1503,7 +1503,7 @@
                 $statement->bindValue(":api_key", $key, SQLITE3_TEXT);
                 if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
                     header("HTTP/1.1 401 Invalid credentials.");
-                    syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
+                    syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
                     return 401;
                 }
                 break;
@@ -1515,7 +1515,7 @@
             $statement->bindValue(":api_key", $key, SQLITE3_TEXT);
             if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
                 header("HTTP/1.1 401 Invalid credentials.");
-                syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
+                syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
                 return 401;
             }
         }
@@ -1539,18 +1539,18 @@
         $status_message = substr($result, 4);
         if ($status_code == 0 || $status_code < 100 || $status_code > 599){
             header("HTTP/1.1 500 Unknown error.");
-            syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unknown error.");
+            syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unknown error.");
             return 500;
         }
         else{
             header("HTTP/1.1 $status_code $status_message");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 $status_code $status_message");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 $status_code $status_message");
             return $status_code;
         }
     }
     catch(Exception $e) {
         header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_INFO, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+        syslog(LOG_INFO, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
         return 500;
     }
 ?>

+ 53 - 52
application/API/v3/run/POST.php → application/API/v1/run/POST.php

@@ -166,18 +166,18 @@
      * Parses the JSONs relateds to an Arena run and saves the data.
      *
      * @param resource $db Database connection.
-     * @param int $uid Player UID.
+     * @param int $player_id Player ID.
      * @param int $id Run ID.
      * @param mixed[] $json List of received JSONs.
      */
-    function log_arena_run($db, $id, $uid, $json){
+    function log_arena_run($db, $id, $player_id, $json){
         // Only the result request and response JSONs are needed:
         $response = $json["result_res"];
 
         // Prepare the "run" insert.
         $statement = $db->prepare("
           INSERT INTO run (
-            uid,
+            player,
             id,
             dtime,
             area_type,
@@ -195,7 +195,7 @@
             score,
             rank
           ) VALUES (
-            :uid,
+            :player,
             :id,
             :dtime,
             :area_type,
@@ -216,7 +216,7 @@
         ");
 
         // Bind data and insert
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
         $statement->bindValue(":area_type", AREA_TYPE_ID::ARENA, SQLITE3_INTEGER);
@@ -281,18 +281,18 @@
      * Parses the JSONs relateds to a Dimensional Rift run and saves the data.
      *
      * @param resource $db Database connection.
-     * @param int $uid Player UID.
+     * @param int $player_id Player ID.
      * @param int $id Run ID.
      * @param mixed[] $json List of received JSONs.
      */
-    function log_dark_portal_run($db, $id, $uid, $json){
+    function log_dark_portal_run($db, $id, $player_id, $json){
         // Only the result request and response JSONs are needed:
         $response = $json["result_res"];
 
         // Prepare the "run" insert.
         $statement = $db->prepare("
           INSERT INTO run (
-            uid,
+            player,
             id,
             dtime,
             area_type,
@@ -310,7 +310,7 @@
             score,
             rank
           ) VALUES (
-            :uid,
+            :player,
             :id,
             :dtime,
             :area_type,
@@ -331,7 +331,7 @@
         ");
 
         // Bind data and insert
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_INTEGER);
         $statement->bindValue(":area_type", AREA_TYPE_ID::DIMENSIONAL_RIFT, SQLITE3_INTEGER);
@@ -392,11 +392,11 @@
      * Parses the JSONs relateds to a scenario run and saves the data.
      *
      * @param resource $db Database connection.
-     * @param int $uid Player UID.
+     * @param int $player_id Player ID.
      * @param int $id Run ID.
      * @param mixed[] $json List of received JSONs.
      */
-    function log_scenario_run($db, $id, $uid, $json){
+    function log_scenario_run($db, $id, $player_id, $json){
         // Only the result request and response JSONs are needed:
         $response = $json["result_res"];
 
@@ -408,7 +408,7 @@
         // Prepare the "run" insert.
         $statement = $db->prepare("
           INSERT INTO run (
-            uid,
+            player,
             id,
             dtime,
             area_type,
@@ -426,7 +426,7 @@
             score,
             rank
           ) VALUES (
-            :uid,
+            :player,
             :id,
             :dtime,
             :area_type,
@@ -447,7 +447,7 @@
         ");
 
         // Bind data and insert
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
         $statement->bindValue(":area_type", AREA_TYPE_ID::SCENARIO, SQLITE3_INTEGER);
@@ -656,11 +656,11 @@
      * Parses the JSONs relateds to a cairos run and saves the data.
      *
      * @param resource $db Database connection.
-     * @param int $uid Player UID.
+     * @param int $player_id Player ID.
      * @param int $id Run ID.
      * @param mixed[] $json List of received JSONs.
      */
-    function log_rift_raid_run($db, $id, $uid, $json){
+    function log_rift_raid_run($db, $id, $player_id, $json){
         // Only the start and result requests JSONs are needed:
         $result = $json["result_res"];
         if ($json["start_res"] === null){
@@ -671,7 +671,7 @@
         // Prepare the "run" insert.
         $statement = $db->prepare("
           INSERT INTO run (
-            uid,
+            player,
             id,
             dtime,
             area_type,
@@ -689,7 +689,7 @@
             score,
             rank
           ) VALUES (
-            :uid,
+            :player,
             :id,
             :dtime,
             :area_type,
@@ -710,7 +710,7 @@
         ");
 
         // Bind data and insert
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $statement->bindValue(":dtime", $result->{"tvaluelocal"}, SQLITE3_TEXT);
         $statement->bindValue(":area_type", AREA_TYPE_ID::RIFT_RAID, SQLITE3_INTEGER);
@@ -737,7 +737,7 @@
         // Parse various types of reward
         if ($result->{"win_lose"} == 1 && array_key_exists("battle_reward_list", $result)){
             foreach ($result->{"battle_reward_list"} as $reward_list){
-                if ($reward_list->{"wizard_id"} == $uid){
+                if ($reward_list->{"wizard_id"} == $player_id){
                     $reward = $reward_list->{"reward_list"}[0];
                     $reward_type = $reward->{"item_master_type"};
                     switch ($reward_type){
@@ -782,7 +782,7 @@
 
         // Parse party
         foreach ($start->{"battle_info"}->{"user_list"} as $user){
-            if ($user->{"wizard_id"} == $uid){
+            if ($user->{"wizard_id"} == $player_id){
                 foreach ($user->{"deck_list"} as $unit){
                     $statement = $db->prepare("
                       INSERT INTO run_party 
@@ -813,11 +813,11 @@
      * Parses the JSONs relateds to a cairos run and saves the data.
      *
      * @param resource $db Database connection.
-     * @param int $uid Player UID.
+     * @param int $player_id Player ID.
      * @param int $id Run ID.
      * @param mixed[] $json List of received JSONs.
      */
-    function log_cairos_run($db, $id, $uid, $json){
+    function log_cairos_run($db, $id, $player_id, $json){
         // Only the result request and response JSONs are needed:
         $response = $json["result_res"];
         if ($json["result_req"] === null){
@@ -828,7 +828,7 @@
         // Prepare the "run" insert.
         $statement = $db->prepare("
           INSERT INTO run (
-            uid,
+            player,
             id,
             dtime,
             area_type,
@@ -846,7 +846,7 @@
             score,
             rank
           ) VALUES (
-            :uid,
+            :player,
             :id,
             :dtime,
             :area_type,
@@ -867,7 +867,7 @@
         ");
 
         // Bind data and insert
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
         $statement->bindValue(":area_type", AREA_TYPE_ID::CAIROS_DUNGEON, SQLITE3_INTEGER);
@@ -1064,11 +1064,11 @@
      * Parses the JSONs relateds to a Dimension Hole run and saves the data.
      *
      * @param resource $db Database connection.
-     * @param int $uid Player UID.
+     * @param int $player_id Player ID.
      * @param int $id Run ID.
      * @param mixed[] $json List of received JSONs.
      */
-    function log_dimension_hole_run($db, $id, $uid, $json){
+    function log_dimension_hole_run($db, $id, $player_id, $json){
         // Only the result request and response JSONs are needed:
         $response = $json["result_res"];
         if ($json["result_req"] === null){
@@ -1078,7 +1078,7 @@
         // Prepare the "run" insert.
         $statement = $db->prepare("
           INSERT INTO run (
-            uid,
+            player,
             id,
             dtime,
             area_type,
@@ -1096,7 +1096,7 @@
             score,
             rank
           ) VALUES (
-            :uid,
+            :player,
             :id,
             :dtime,
             :area_type,
@@ -1117,7 +1117,7 @@
         ");
 
         // Bind data and insert
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":id", $id, SQLITE3_INTEGER);
         $statement->bindValue(":dtime", $response->{"tvaluelocal"}, SQLITE3_TEXT);
         $statement->bindValue(":area_type", AREA_TYPE_ID::DIMENSIONAL_HOLE, SQLITE3_INTEGER);
@@ -1316,7 +1316,7 @@
         // Check API key.
         if (!array_key_exists("key", $_POST)){
             header("HTTP/1.1 400 API key not received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 API key not received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 API key not received.");
             return 400;
         }
         $key = $_POST["key"];
@@ -1332,13 +1332,13 @@
         // Result response - mandatory
         if (!array_key_exists("result_response", $_POST)){
             header("HTTP/1.1 400 No result response data received.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 No result response data received.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 No result response data received.");
             return 400;
         }
         $data_json = json_decode($_POST["result_response"]);
         if ($data_json === null){
             header("HTTP/1.1 400 Result response data is no valid JSON.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 400 Result response data is no valid JSON.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 400 Result response data is no valid JSON.");
             return 400;
         }
         $json["result_res"] = $data_json;
@@ -1375,16 +1375,17 @@
         }
 
         // Extract basic data
-        $uid = $json["result_res"]->{"wizard_info"}->{"wizard_id"};
+        $player_id = $json["result_res"]->{"wizard_info"}->{"wizard_id"};
         $command = $json["result_res"]->{"command"};
 
         // Authenticate
-        $statement = $db->prepare("SELECT COUNT(uid) AS c FROM player WHERE uid = :uid AND api_key = :api_key;");
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        // TODO: Table user
+        $statement = $db->prepare("SELECT COUNT(id) AS c FROM data.player WHERE id = :player AND api_key = :api_key;");
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":api_key", $key, SQLITE3_TEXT);
         if (1 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
             header("HTTP/1.1 401 Invalid credentials.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 401 Invalid credentials.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 401 Invalid credentials.");
             return 401;
         }
 
@@ -1399,18 +1400,18 @@
         ];
         if (!in_array($command, $accepted_commands)){
             header("HTTP/1.1 405 Command not implemented.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 405 Command not implemented.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 405 Command not implemented.");
             return 405;
         }
 
         // Check if already in DB
         $dtime = $json["result_res"]->{"tvaluelocal"};
-        $statement = $db->prepare("SELECT count(id) AS c FROM run WHERE uid = :uid AND dtime = :dtime;");
-        $statement->bindValue(":uid", $uid, SQLITE3_INTEGER);
+        $statement = $db->prepare("SELECT count(id) AS c FROM run WHERE player = :player AND dtime = :dtime;");
+        $statement->bindValue(":player", $player_id, SQLITE3_INTEGER);
         $statement->bindValue(":dtime", $dtime, SQLITE3_TEXT);
         if (0 != $statement->execute()->fetchArray(SQLITE3_ASSOC)["c"]){
             header("HTTP/1.1 409 Run already in database.");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 409 Run already in database.");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 409 Run already in database.");
             return 409;
         }
 
@@ -1428,22 +1429,22 @@
         $result = "500 Unknown Error";
         switch($command){
             case "BattleDungeonResult_V2":
-                $result = log_cairos_run($db, $id, $uid, $json);
+                $result = log_cairos_run($db, $id, $player_id, $json);
                 break;
             case "BattleDimensionHoleDungeonResult_v2":
-                $result = log_dimension_hole_run($db, $id, $uid, $json);
+                $result = log_dimension_hole_run($db, $id, $player_id, $json);
                 break;
             case "BattleRiftOfWorldsRaidResult":
-                $result = log_rift_raid_run($db, $id, $uid, $json);
+                $result = log_rift_raid_run($db, $id, $player_id, $json);
                 break;
             case "BattleScenarioResult":
-                $result = log_scenario_run($db, $id, $uid, $json);
+                $result = log_scenario_run($db, $id, $player_id, $json);
                 break;
             case "BattleArenaResult":
-                $result = log_arena_run($db, $id, $uid, $json);
+                $result = log_arena_run($db, $id, $player_id, $json);
                 break;
             case "BattleDarkPortalResult":
-                $result = log_dark_portal_run($db, $id, $uid, $json);
+                $result = log_dark_portal_run($db, $id, $player_id, $json);
                 break;
         }
 
@@ -1452,18 +1453,18 @@
         $status_message = substr($result, 4);
         if ($status_code == 0 || $status_code < 100 || $status_code > 599){
             header("HTTP/1.1 500 Unknown error.");
-            syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unknown error.");
+            syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unknown error.");
             return 500;
         }
         else{
             header("HTTP/1.1 $status_code $status_message");
-            syslog(LOG_INFO, "[APIv3] HTTP/1.1 $status_code $status_message");
+            syslog(LOG_INFO, "[APIv1] HTTP/1.1 $status_code $status_message");
             return $status_code;
         }
     }
     catch(Exception $e) {
         header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
         return 500;
     }
 ?>

+ 11 - 11
application/API/v3/units/GET.php → application/API/v1/units/GET.php

@@ -50,9 +50,9 @@
             k_unit.resistance AS resistance,
             k_unit.leader_skill AS leader_skill
           FROM
-            k_unit,
-            k_element,
-            k_archetype
+            key.unit k_unit,
+            key.element k_element,
+            key.archetype k_archetype
           WHERE
             k_unit.element = k_element.id AND
             k_unit.archetype = k_archetype.id AND
@@ -64,7 +64,7 @@
         if ($r){
             $unit = [
                 "id" => $r["id"],
-                "url" => URL::BASE . "API/v3/units/" . $r["id"] . "/",
+                "url" => URL::BASE . "API/v1/units/" . $r["id"] . "/",
                 "name" => $r["name"],
                 "family" => $r["family"],
                 "image" => APPLICATION::img("UNIT", $r["id"]),
@@ -103,10 +103,10 @@
                     k_leader_skill.element AS element,
                     k_element.name AS element_name
                 FROM
-                    k_leader_skill,
-                    k_stat,
-                    k_effect_area,
-                    k_element
+                    key.leader_skill k_leader_skill,
+                    key.stat k_stat,
+                    key.effect_area k_effect_area,
+                    key.element k_element
                 WHERE
                     k_leader_skill.id = :id AND
                     k_leader_skill.stat = k_stat.id AND
@@ -409,10 +409,10 @@
             $url_prev = null;
         }
         else{
-            $url_prev = URL::BASE . "API/v3/units/?page=" . ($filters["page"] - 1) . $parameters;
+            $url_prev = URL::BASE . "API/v1/units/?page=" . ($filters["page"] - 1) . $parameters;
         }
         if ($filters["page"] < ceil($total / $filters["per_page"])){
-            $url_next = URL::BASE . "API/v3/units/?page=" . ($filters["page"] + 1) . $parameters;
+            $url_next = URL::BASE . "API/v1/units/?page=" . ($filters["page"] + 1) . $parameters;
         }
         else{
             $url_next = null;
@@ -450,6 +450,6 @@
     }
     catch(Exception $e) {
         header("HTTP/1.1 500 Unexpeced error: " . $e->getMessage());
-        syslog(LOG_ERR, "[APIv3] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
+        syslog(LOG_ERR, "[APIv1] HTTP/1.1 500 Unexpected error: " . $e->getMessage());
         return 500;
     }

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

@@ -1,75 +0,0 @@
-<?php
-
-    /**
-     * v2 API Controller file.
-     *
-     * Provides a class to handle all posible API requests.
-     *
-     * @category Constroller
-     */
-
-    /**
-     * v2 API controller.
-     *
-     * Handles every API request.
-     *
-     * @category Controller
-     */
-    class API_Controller {
-
-        /**
-         * Constructor.
-         *
-         * Handles every request, creating the required models and selecting the
-         * view.
-         *
-         * @param mixed[] $params GET parameters of the request.
-         */
-        public function __construct($params){
-            array_shift($params);
-            array_shift($params);
-            array_shift($params);
-            // API call: Use API controller
-            if (count($params) == 0){
-                require_once(__DIR__ . "main.php");
-            }
-            else{
-                $command = strtolower($params[0]);
-                switch ($command){
-                    case "help":
-                        require_once(__DIR__ . "/help/index.php");
-                        break;
-                    case "upload_profile":
-                        require_once(__DIR__ . "/upload_profile.php");
-                        break;
-                    case "upload_run_dungeon":
-                        require_once(__DIR__ . "/upload_run_dungeon.php");
-                        break;
-                    case "upload_run_dimension":
-                        require_once(__DIR__ . "/upload_run_dimension.php");
-                        break;
-                    case "upload_run_scenario":
-                        require_once(__DIR__ . "/upload_run_scenario.php");
-                        break;
-                    case "upload_run_toa":
-                        require_once(__DIR__ . "/upload_run_toa.php");
-                        break;
-                    case "upload_run_rift":
-                        require_once(__DIR__ . "/upload_run_rift.php");
-                        break;
-                    case "update_logbook":
-                        require_once(__DIR__ . "/update_logbook.php");
-                        break;
-                    case "update_collection":
-                        require_once(__DIR__ . "/update_collection.php");
-                        break;
-                    case "units":
-                        require_once(__DIR__ . "/units.php");
-                        break;
-                    default:
-                        header("HTTP/1.1 404");
-                }
-            }
-        }
-    }
-?>

+ 0 - 382
application/API/v2/bin/MAPPING.py

@@ -1,382 +0,0 @@
-import json
-import math
-
-MAINSTAT = json.loads("""
-{
-  "mainstat": {
-    "1": {
-      "max": {
-        "1": 804,
-        "2": 1092,
-        "3": 1380,
-        "4": 1704,
-        "5": 2088,
-        "6": 2448
-      }
-    },
-    "2": {
-      "max": {
-        "1": 18,
-        "2": 20,
-        "3": 38,
-        "4": 43,
-        "5": 51,
-        "6": 63
-      }
-    },
-    "3": {
-      "max": {
-        "1": 54,
-        "2": 74,
-        "3": 93,
-        "4": 113,
-        "5": 135,
-        "6": 160
-      }
-    },
-    "4": {
-      "max": {
-        "1": 18,
-        "2": 20,
-        "3": 38,
-        "4": 43,
-        "5": 51,
-        "6": 63
-      }
-    },
-    "5": {
-      "max": {
-        "1": 54,
-        "2": 74,
-        "3": 93,
-        "4": 113,
-        "5": 135,
-        "6": 160
-      }
-    },
-    "6": {
-      "max": {
-        "1": 18,
-        "2": 20,
-        "3": 38,
-        "4": 43,
-        "5": 51,
-        "6": 63
-      }
-    },
-    "8": {
-      "max": {
-        "1": 18,
-        "2": 19,
-        "3": 25,
-        "4": 30,
-        "5": 39,
-        "6": 42
-      }
-    },
-    "9": {
-      "max": {
-        "1": 18,
-        "2": 20,
-        "3": 37,
-        "4": 41,
-        "5": 47,
-        "6": 58
-      }
-    },
-    "10": {
-      "max": {
-        "1": 20,
-        "2": 37,
-        "3": 43,
-        "4": 58,
-        "5": 65,
-        "6": 80
-      }
-    },
-    "11": {
-      "max": {
-        "1": 18,
-        "2": 20,
-        "3": 38,
-        "4": 44,
-        "5": 51,
-        "6": 64
-      }
-    },
-    "12": {
-      "max": {
-        "1": 18,
-        "2": 20,
-        "3": 38,
-        "4": 44,
-        "5": 51,
-        "6": 64
-      }
-    }
-  },
-  "substat": {
-    "1": {
-      "max": {
-        "1": 300,
-        "2": 525,
-        "3": 825,
-        "4": 1125,
-        "5": 1500,
-        "6": 1875
-      }
-    },
-    "2": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 25,
-        "4": 30,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "3": {
-      "max": {
-        "1": 20,
-        "2": 25,
-        "3": 40,
-        "4": 50,
-        "5": 75,
-        "6": 100
-      }
-    },
-    "4": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 25,
-        "4": 30,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "5": {
-      "max": {
-        "1": 20,
-        "2": 25,
-        "3": 40,
-        "4": 50,
-        "5": 75,
-        "6": 100
-      }
-    },
-    "6": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 25,
-        "4": 30,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "8": {
-      "max": {
-        "1": 5,
-        "2": 10,
-        "3": 15,
-        "4": 20,
-        "5": 25,
-        "6": 30
-      }
-    },
-    "9": {
-      "max": {
-        "1": 5,
-        "2": 10,
-        "3": 15,
-        "4": 20,
-        "5": 25,
-        "6": 30
-      }
-    },
-    "10": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 20,
-        "4": 25,
-        "5": 25,
-        "6": 35
-      }
-    },
-    "11": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 20,
-        "4": 25,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "12": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 20,
-        "4": 25,
-        "5": 35,
-        "6": 40
-      }
-    }
-  }
-}
-""")
-
-SUBSTAT = json.loads("""
-{
-  "substat": {
-    "1": {
-      "max": {
-        "1": 300,
-        "2": 525,
-        "3": 825,
-        "4": 1125,
-        "5": 1500,
-        "6": 1875
-      }
-    },
-    "2": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 25,
-        "4": 30,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "3": {
-      "max": {
-        "1": 20,
-        "2": 25,
-        "3": 40,
-        "4": 50,
-        "5": 75,
-        "6": 100
-      }
-    },
-    "4": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 25,
-        "4": 30,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "5": {
-      "max": {
-        "1": 20,
-        "2": 25,
-        "3": 40,
-        "4": 50,
-        "5": 75,
-        "6": 100
-      }
-    },
-    "6": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 25,
-        "4": 30,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "8": {
-      "max": {
-        "1": 5,
-        "2": 10,
-        "3": 15,
-        "4": 20,
-        "5": 25,
-        "6": 30
-      }
-    },
-    "9": {
-      "max": {
-        "1": 5,
-        "2": 10,
-        "3": 15,
-        "4": 20,
-        "5": 25,
-        "6": 30
-      }
-    },
-    "10": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 20,
-        "4": 25,
-        "5": 25,
-        "6": 35
-      }
-    },
-    "11": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 20,
-        "4": 25,
-        "5": 35,
-        "6": 40
-      }
-    },
-    "12": {
-      "max": {
-        "1": 10,
-        "2": 15,
-        "3": 20,
-        "4": 25,
-        "5": 35,
-        "6": 40
-      }
-    }
-  }
-}
-""")
-
-"""
-Calculates a rune current and max efficiency.
-
-:param rune: JSON woth rune info.
-:return: current, max efficiency.
-"""
-def calculate_efficiency(rune):
-    #getRuneEfficiency(rune, toFixed = 2) {
-    ratio = 0.0;
-
-    # Get actual stars (ancient are +10)
-    r_class = rune["class"]
-    if r_class > 10:
-        r_class -= 10
-    r_class = str(r_class)
-
-    # Main stat
-    ratio += MAINSTAT["mainstat"][str(rune["pri_eff"][0])]["max"][r_class] / MAINSTAT["mainstat"][str(rune["pri_eff"][0])]["max"]["6"]
-
-    # Innate stat
-    if (rune["prefix_eff"] and rune["prefix_eff"][0] > 0):
-      ratio += rune["prefix_eff"][1] / SUBSTAT["substat"][str(rune["prefix_eff"][0])]["max"]["6"];
-
-    # Sub stats
-    for substat in rune["sec_eff"]:
-        value = substat[1]
-        if "3" in substat and substat[3] > 0:
-            value += substat[3]
-        ratio += (value / SUBSTAT["substat"][str(substat[0])]["max"]["6"])
-
-    efficiency = (ratio / 2.8) * 100;
-
-    return ((ratio / 2.8) * 100), (efficiency + ((max(math.ceil((12 - rune["upgrade_curr"]) / 3.0), 0) * 0.2) / 2.8) * 100)

+ 0 - 156
application/API/v2/bin/update_collection.py

@@ -1,156 +0,0 @@
-#!/usr/bin/python3
-
-import sqlite3
-import json
-import sys
-import os
-
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        #print(sys.argv[0])
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:param: index 2 for request data, 3 for response data
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData(index):
-    try:
-        data = json.loads(sys.argv[index])
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and deletes from the user tables
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute('attach "' + udb + '" as data;')
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
-run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
-run_drop_shapeshifting).
-
-:param db: Sqlite database connection.
-:param data: JSON data.
-"""
-def parseData(db, data_request, data_response):
-
-    cursor = db.cursor()
-
-    # Page 1: Cairos non-elemental, rift raid, rift dungeon.
-    print("Parsing collection data...")
-    
-    uid = data_request["wizard_id"]
-    collection = data_response["collection"]
-    cursor.execute("""
-            DELETE FROM collection
-            WHERE uid = ?;
-        """,
-        [uid]
-    )
-
-    # Loop Cairos records
-    for u in collection:
-        unit = u["unit_master_id"]
-        open = u["open"]
-        insert(db, "collection", (uid, unit, open))
-    db.commit()
-
-"""
-Begin script
-"""
-data_request = readData(2)
-data_response = readData(3)
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data_request, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(-1)
-else:
-    parseData(db, data_request, data_response)
-sys.exit(0)
-
-

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

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

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

@@ -1,1338 +0,0 @@
-#!/usr/bin/python3
-
-import sys
-import os
-import sqlite3
-import json
-import math
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData():
-    try:
-        #print(sys.argv[1])
-        #data = json.loads(sys.argv[1])
-        with open(sys.argv[2], 'r') as f:
-            content = f.read()
-        data = json.loads(content)
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_info"]["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and cleans the user tables.
-
-It also disables referencial integrity.
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute("attach '" + udb + "' as data;")
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Clears the user tables.
-
-It also disables referencial integrity.
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def clearData(db, data):
-    print('Clearing previous data...')
-    try:
-        uid = str(data["wizard_info"]["wizard_id"])
-        cursor = db.cursor()
-        cursor.execute('PRAGMA foreign_keys = OFF;')
-        cursor.execute('DELETE FROM scenario WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM defense WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM gw_defense WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM unit_skill WHERE unit IN (SELECT id FROM unit WHERE uid = ?)', [uid])
-        cursor.execute('DELETE FROM unit WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM rune WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM artifact WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM building WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM decoration WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM inventory WHERE uid = ?', [uid])
-        cursor.execute('DELETE FROM summon_special') # For every player, will be reloaded.
-        cursor.execute('DELETE FROM rune_craft WHERE uid = ?', [uid])
-        # 'guild' and 'guild_member' tables are cleared before inserting.
-        db.commit()
-        cursor.close();
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return
-
-
-"""
-Closes the database.
-
-Before doing so, it also disables referencial integrity.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def closeDatabase(name):
-    print('Closing database connection...')
-    try:
-        cursor = db.cursor()
-        cursor.execute('PRAGMA foreign_keys = ON;')
-        cursor.close()
-        db.commit()
-        db.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    db.execute('PRAGMA foreign_keys = OFF;')
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses player (table player).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parsePlayer(db, data):
-    print("Parsing player...")
-    cursor = db.cursor()
-    uid = data["wizard_info"]["wizard_id"]
-    name = data["wizard_info"]["wizard_name"]
-    # TODO: Generate data
-    mail = data["wizard_info"]["wizard_name"]
-    password = data["wizard_info"]["wizard_name"]
-    api_key = data["wizard_info"]["wizard_name"]
-    mana = data["wizard_info"]["wizard_mana"]
-    crystal = data["wizard_info"]["wizard_crystal"]
-    country = data["wizard_info"]["wizard_last_country"]
-    lang = data["wizard_info"]["wizard_last_lang"]
-    level = data["wizard_info"]["wizard_level"]
-    experience = data["wizard_info"]["experience"]
-    energy = data["wizard_info"]["wizard_energy"]
-    energy_max = data["wizard_info"]["energy_max"]
-    energy_per_min = data["wizard_info"]["energy_per_min"]
-    arena_energy = data["wizard_info"]["arena_energy"]
-    arena_energy_max = data["wizard_info"]["arena_energy_max"]
-    rep = data["wizard_info"]["rep_unit_id"]
-    social_point = data["wizard_info"]["social_point_current"]
-    honor_point = data["wizard_info"]["honor_point"]
-    guild_point = data["wizard_info"]["guild_point"]
-    darkportal_energy = data["wizard_info"]["darkportal_energy"]
-    darkportal_energy_max = data["wizard_info"]["darkportal_energy_max"]
-    dimension_energy = data["dimension_hole_info"]["energy"]
-    dimension_energy_max = data["dimension_hole_info"]["energy_max"]
-    costume_point = data["wizard_info"]["costume_point"]
-    costume_point_max = data["wizard_info"]["costume_point_max"]
-    honor_medal = data["wizard_info"]["honor_medal"]
-    honor_mark = data["wizard_info"]["honor_mark"]
-    event_coin = data["wizard_info"]["event_coin"]
-    storage_slots = data["unit_depository_slots"]["number"]
-    island_upgrade = 0
-    for island in data["island_info"]:
-        if island["id"] <= 7 and island["open"] == 1:
-            island_upgrade = island["id"]
-    query = '''
-        UPDATE player
-        SET mana = ?,
-            crystal = ?,
-            country = ?,
-            lang = ?,
-            level = ?,
-            experience = ?,
-            energy = ?,
-            energy_max = ?,
-            energy_per_min = ?,
-            arena_energy = ?,
-            arena_energy_max = ?,
-            rep = ?,
-            social_point = ?,
-            honor_point = ?,
-            guild_point = ?,
-            darkportal_energy = ?,
-            darkportal_energy_max = ?,
-            dimension_energy = ?,
-            dimension_energy_max = ?,
-            costume_point = ?,
-            costume_point_max = ?,
-            honor_medal = ?,
-            honor_medal = ?,
-            event_coin = ?,
-            storage_slots = ?,
-            island = ?
-        WHERE uid = ?;
-    '''
-    values = (
-        mana,                 crystal,               country,
-        lang,                 level,                 experience,
-        energy,               energy_max,            energy_per_min,
-        arena_energy,         arena_energy_max,      rep,
-        social_point,         honor_point,           guild_point,
-        darkportal_energy,    darkportal_energy_max, dimension_energy,
-        dimension_energy_max, costume_point,         costume_point_max,
-        honor_medal,          honor_medal,           event_coin,
-        storage_slots,        island_upgrade,        uid
-    )
-    try:
-        cursor.execute(query, values)
-        db.commit()
-    except sqlite3.IntegrityError as e:
-        print('Error updating player table with: ' + str(query) + ' <== ' + str(values) + ' || Error message:' +  str(e))
-        raise
-
-"""
-Parses scenarios (table scenario).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseScenarios(db, data):
-    print("Parsing scenarios...")
-    uid = data["wizard_info"]["wizard_id"]
-    for sce in data["scenario_list"]:
-        region = sce["region_id"]
-        difficulty = sce["difficulty"]
-        cleared = sce["cleared"]
-        max_cleared = 0
-        for stage in sce["stage_list"]:
-            if stage["cleared"] == 1:
-                max_cleared = stage["stage_no"]
-        insert(db, "scenario", (uid, region, difficulty, cleared, max_cleared))
-    db.commit()
-
-"""
-Parses arena defense units (table defense).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseDefense(db, data):
-    print("Parsing arena defense...")
-    uid = data["wizard_info"]["wizard_id"]
-    for defense in data["defense_unit_list"]:
-        unit = defense["unit_id"]
-        position = defense["pos_id"]
-        insert(db, "defense", (uid, unit, position))
-    db.commit()
-
-"""
-Parses guild war defense units (table gw_defense).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseGWDefense(db, data):
-    print("Parsing guild war defense...")
-    uid = data["wizard_info"]["wizard_id"]
-    if data["guildwar_defense_unit_list"][0]:
-        position = 1
-        for defense in data["guildwar_defense_unit_list"][0]:
-            unit = defense["unit_id"]
-            insert(db, "gw_defense", (uid, unit, position))
-            position = position + 1
-    if data["guildwar_defense_unit_list"][1]:
-        position = 4
-        for defense in data["guildwar_defense_unit_list"][1]:
-            unit = defense["unit_id"]
-            insert(db, "gw_defense", (uid, unit, position))
-            position = position + 1
-        
-    db.commit()
-
-"""
-Parses buildings (table building).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseBuildings(db, data):
-    print("Parsing buildings...")
-    uid = data["wizard_info"]["wizard_id"]
-    for bui in data["building_list"]:
-        id = bui["building_id"]
-        building = bui["building_master_id"]
-        gain = bui["gain_per_hour"]
-        insert(db, "building", (uid, id, building, gain))
-    db.commit()
-
-"""
-Parses decoration buildings (table dcoration).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseDecorations(db, data):
-    print("Parsing decorations...")
-    uid = data["wizard_info"]["wizard_id"]
-    for bui in data["deco_list"]:
-        id = bui["deco_id"]
-        building = bui["master_id"]
-        level = bui["level"]
-        insert(db, "decoration", (uid, id, building, level))
-    db.commit()
-
-"""
-Parses unit data (tables unit, unit_skill).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseUnits(db, data):
-    print("Parsing monsters...")
-    uid = data["wizard_info"]["wizard_id"]
-    lock_list = data["unit_lock_list"]
-    for mon in data["unit_list"]:
-        id = mon["unit_id"]
-        building = mon["building_id"]
-        monster = mon["unit_master_id"]
-        level = mon["unit_level"]
-        stars = mon["class"]
-        hp = mon["con"] * 15 # Always x15
-        attack = mon["atk"]
-        defense = mon["def"]
-        speed = mon["spd"]
-        crit_rate = mon["critical_rate"]
-        crit_damage = mon["critical_damage"]
-        resistance = mon["resist"]
-        accuracy = mon["accuracy"]
-        experience = mon["experience"]
-        exp_gained = mon["exp_gained"]
-        exp_gain_rate = mon["exp_gain_rate"]
-        costume = mon["costume_master_id"]
-        attribute = -1; # TODO: Attribute?
-        source = mon["source"]
-        create_time = mon["create_time"]
-        homunculus = mon["homunculus"]
-        homunculus_name = mon["homunculus_name"]
-        lock = 0
-        if id in lock_list:
-            lock = 1
-        insert(db, "unit", (uid, id, building, monster, level, stars, hp, attack, defense, speed, crit_rate, crit_damage, resistance, accuracy, experience, exp_gained, exp_gain_rate, costume, attribute, source, create_time, homunculus, homunculus_name, lock))
-        for skill in mon["skills"]:
-            skill_id = skill[0]
-            skill_level = skill[1]
-            insert(db, "unit_skill", (id, skill_id, skill_level))
-    db.commit()
-
-"""
-Parses inventory data (table inventory).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseInventory(db, data):
-    print("Parsing inventory...")
-    uid = data["wizard_info"]["wizard_id"]
-    for item in data["inventory_info"]:
-        id = item["item_master_id"]
-        type = item["item_master_type"]
-        amount = item["item_quantity"]
-        insert(db, "inventory", (uid, id, type, amount))
-    # Fix rune craft item type.
-    cursor = db.cursor()
-    cursor.execute("UPDATE inventory SET type = 27 WHERE type = 29 AND id IN (2001, 4001, 4002, 4003, 9001, 9002, 9003, 8001);")
-    cursor.close()
-
-"""
-Parses summon stone list (table summon_special).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseSummonSpecial(db, data):
-    print("Parsing Summon stone monster list...")
-    uid = data["wizard_info"]["wizard_id"]
-    for unit in data["summon_special_info"]["this"]:
-        insert(db, "summon_special", (0, unit))
-    for unit in data["summon_special_info"]["next"]:
-        insert(db, "summon_special", (1, unit))
-    for unit in data["summon_special_info"]["third"]:
-        insert(db, "summon_special", (2, unit))
-    for unit in data["summon_special_info"]["fourth"]:
-        insert(db, "summon_special", (3, unit))
-
-"""
-Parses rune data (table rune).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseRunes(db, data):
-    print("Parsing runes...")
-    STAT_HP = 1
-    STAT_HP_PCT = 2
-    STAT_ATK = 3
-    STAT_ATK_PCT = 4
-    STAT_DEF = 5
-    STAT_DEF_PCT = 6
-    STAT_SPD = 8
-    STAT_CRIT_RATE_PCT = 9
-    STAT_CRIT_DMG_PCT = 10
-    STAT_RESIST_PCT = 11
-    STAT_ACCURACY_PCT = 12
-    MAIN_STAT_VALUES = {
-        # [stat][stars][level]: value
-        STAT_HP: {
-            1: [40, 85, 130, 175, 220, 265, 310, 355, 400, 445, 490, 535, 580, 625, 670, 804],
-            2: [70, 130, 190, 250, 310, 370, 430, 490, 550, 610, 670, 730, 790, 850, 910, 1092],
-            3: [100, 175, 250, 325, 400, 475, 550, 625, 700, 775, 850, 925, 1000, 1075, 1150, 1380],
-            4: [160, 250, 340, 430, 520, 610, 700, 790, 880, 970, 1060, 1150, 1240, 1330, 1420, 1704],
-            5: [270, 375, 480, 585, 690, 795, 900, 1005, 1110, 1215, 1320, 1425, 1530, 1635, 1740, 2088],
-            6: [360, 480, 600, 720, 840, 960, 1080, 1200, 1320, 1440, 1560, 1680, 1800, 1920, 2040, 2448],
-        },
-        STAT_HP_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
-            5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
-            6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
-        },
-        STAT_ATK: {
-            1: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 54],
-            2: [5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 73],
-            3: [7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 92],
-            4: [10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 112],
-            5: [15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 135],
-            6: [22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 160],
-        },
-        STAT_ATK_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
-            5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
-            6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
-        },
-        STAT_DEF: {
-            1: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 54],
-            2: [5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 73],
-            3: [7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 92],
-            4: [10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 112],
-            5: [15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 135],
-            6: [22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 160],
-        },
-        STAT_DEF_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
-            5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
-            6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
-        },
-        STAT_SPD: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 19, 21, 25],
-            4: [4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 30],
-            5: [5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 39],
-            6: [7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 42],
-        },
-        STAT_CRIT_RATE_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 37],
-            4: [4, 6, 8, 11, 13, 15, 17, 19, 22, 24, 26, 28, 30, 33, 35, 41],
-            5: [5, 7, 10, 12, 15, 17, 19, 22, 24, 27, 29, 31, 34, 36, 39, 47],
-            6: [7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 58],
-        },
-        STAT_CRIT_DMG_PCT: {
-            1: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            2: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 37],
-            3: [4, 6, 9, 11, 13, 16, 18, 20, 22, 25, 27, 29, 32, 34, 36, 43],
-            4: [6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 57],
-            5: [8, 11, 15, 18, 21, 25, 28, 31, 34, 38, 41, 44, 48, 51, 54, 65],
-            6: [11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 80],
-        },
-        STAT_RESIST_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [6, 8, 10, 13, 15, 17, 19, 21, 24, 26, 28, 30, 32, 35, 37, 44],
-            5: [9, 11, 14, 16, 19, 21, 23, 26, 28, 31, 33, 35, 38, 40, 43, 51],
-            6: [12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 64],
-        },
-        STAT_ACCURACY_PCT: {
-            1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
-            2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
-            3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
-            4: [6, 8, 10, 13, 15, 17, 19, 21, 24, 26, 28, 30, 32, 35, 37, 44],
-            5: [9, 11, 14, 16, 19, 21, 23, 26, 28, 31, 33, 35, 38, 40, 43, 51],
-            6: [12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 64],
-        },
-    }
-    SUBSTAT_INCREMENTS = {
-        # [stat][stars]: value
-        # Max possible substat value can be found by multiplying by 5
-        STAT_HP: {
-            1: 60,
-            2: 105,
-            3: 165,
-            4: 225,
-            5: 300,
-            6: 375,
-        },
-        STAT_HP_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ATK: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_ATK_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_DEF: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_DEF_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_SPD: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_RATE_PCT: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_DMG_PCT: {
-            1: 2,
-            2: 3,
-            3: 4,
-            4: 5,
-            5: 6,
-            6: 7,
-        },
-        STAT_RESIST_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ACCURACY_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-    }
-    uid = data["wizard_info"]["wizard_id"]
-    # Unequipped runes
-    for rune in data["runes"]:
-        id = rune["rune_id"]
-        assigned_to = rune["occupied_id"]
-        if assigned_to == 0:
-            assigned_to = None
-        runeset = rune["set_id"]
-        slot = rune["slot_no"]
-        stars = rune["class"]
-        ancient = 0
-        level = rune["upgrade_curr"]
-        original_quality = rune["extra"]
-        value = rune["sell_value"]
-        if stars > 10:
-            ancient = 1
-            stars = stars - 10
-            original_quality = original_quality - 10
-        if level >= 12:
-            quality = 5
-        elif level >= 9:
-            quality = 4
-        elif level >= 6:
-            quality = 3
-        elif level >= 3:
-            quality = 2
-        else:
-            quality = 1
-        if original_quality > quality:
-            quality = original_quality
-        efficiency = 0
-        max_efficiency = 0
-        main_stat = rune["pri_eff"][0]
-        main_stat_value = rune["pri_eff"][1]
-        if rune["prefix_eff"][0] > 0:
-            innate_stat = rune["prefix_eff"][0]
-            innate_stat_value = rune["prefix_eff"][1]
-        else:
-            innate_stat = None
-            innate_stat_value = 0
-        if len(rune["sec_eff"]) > 0:
-            substat_1 = rune["sec_eff"][0][0]
-            substat_1_value = rune["sec_eff"][0][1]
-            substat_1_enchant = rune["sec_eff"][0][2]
-            substat_1_grind = rune["sec_eff"][0][3]
-        else:
-            substat_1 = None
-            substat_1_value = 0
-            substat_1_enchant = 0
-            substat_1_grind = 0
-        if len(rune["sec_eff"]) > 1:
-            substat_2 = rune["sec_eff"][1][0]
-            substat_2_value = rune["sec_eff"][1][1]
-            substat_2_enchant = rune["sec_eff"][1][2]
-            substat_2_grind = rune["sec_eff"][1][3]
-        else:
-            substat_2 = None
-            substat_2_value = 0
-            substat_2_enchant = 0
-            substat_2_grind = 0
-        if len(rune["sec_eff"]) > 2:
-            substat_3 = rune["sec_eff"][2][0]
-            substat_3_value = rune["sec_eff"][2][1]
-            substat_3_enchant = rune["sec_eff"][2][2]
-            substat_3_grind = rune["sec_eff"][2][3]
-        else:
-            substat_3 = None
-            substat_3_value = 0
-            substat_3_enchant = 0
-            substat_3_grind = 0
-        if len(rune["sec_eff"]) > 3:
-            substat_4 = rune["sec_eff"][3][0]
-            substat_4_value = rune["sec_eff"][3][1]
-            substat_4_enchant = rune["sec_eff"][3][2]
-            substat_4_grind = rune["sec_eff"][3][3]
-        else:
-            substat_4 = None
-            substat_4_value = 0
-            substat_4_enchant = 0
-            substat_4_grind = 0
-
-        # Calculate efficiences
-        efficiency = 0
-        substats = []
-        efficiency += float(MAIN_STAT_VALUES[main_stat][stars][15]) / float(MAIN_STAT_VALUES[main_stat][6][15])
-        if innate_stat is not None:
-            efficiency += innate_stat_value / float(SUBSTAT_INCREMENTS[innate_stat][6] * 5)
-        if substat_1 is not None:
-            substats.append(substat_1)
-            efficiency += substat_1_value / float(SUBSTAT_INCREMENTS[substat_1][6] * 5)
-        if substat_2 is not None:
-            substats.append(substat_2)
-            efficiency += substat_2_value / float(SUBSTAT_INCREMENTS[substat_2][6] * 5)
-        if substat_3 is not None:
-            substats.append(substat_3)
-            efficiency += substat_3_value / float(SUBSTAT_INCREMENTS[substat_3][6] * 5)
-        if substat_4 is not None:
-            substats.append(substat_4)
-            efficiency += substat_4_value / float(SUBSTAT_INCREMENTS[substat_4][6] * 5)
-        efficiency = efficiency / 2.8 * 100
-        max_efficiency = get_max_efficiency(substats, efficiency, level, stars, original_quality)
-        if efficiency > 100:
-            efficiency = 100;
-        if max_efficiency > 100:
-            max_efficiency = 100;
-        # TODO: Locked status not in JSO file.
-        locked = 0
-        insert(db, "rune", (uid, id, assigned_to, runeset, slot, stars, ancient, level, quality, original_quality, value, efficiency, max_efficiency, main_stat, main_stat_value, innate_stat, innate_stat_value, substat_1, substat_1_value, substat_1_enchant, substat_1_grind, substat_2, substat_2_value, substat_2_enchant, substat_2_grind, substat_3, substat_3_value, substat_3_enchant, substat_3_grind, substat_4, substat_4_value, substat_4_enchant, substat_4_grind, locked))
-    # Equipped runes
-    for mon in data["unit_list"]:
-        for rune in mon["runes"]:
-            id = rune["rune_id"]
-            assigned_to = rune["occupied_id"]
-            if assigned_to == 0:
-                assigned_to = None
-            runeset = rune["set_id"]
-            slot = rune["slot_no"]
-            stars = rune["class"]
-            ancient = 0
-            level = rune["upgrade_curr"]
-            original_quality = rune["extra"]
-            value = rune["sell_value"]
-            if stars > 10:
-                ancient = 1
-                stars = stars - 10
-                original_quality = original_quality - 10
-            if level >= 12:
-                quality = 5
-            elif level >= 9:
-                quality = 5
-            elif level >= 6:
-                quality = 3
-            elif level >= 3:
-                quality = 2
-            else:
-                quality = 1
-            if original_quality > quality:
-                quality = original_quality
-            efficiency = 0
-            max_efficiency = 0
-            main_stat = rune["pri_eff"][0]
-            main_stat_value = rune["pri_eff"][1]
-            if rune["prefix_eff"][0] > 0:
-                innate_stat = rune["prefix_eff"][0]
-                innate_stat_value = rune["prefix_eff"][1]
-            else:
-                innate_stat = None
-                innate_stat_value = 0
-            if len(rune["sec_eff"]) > 0:
-                substat_1 = rune["sec_eff"][0][0]
-                substat_1_value = rune["sec_eff"][0][1]
-                substat_1_enchant = rune["sec_eff"][0][2]
-                substat_1_grind = rune["sec_eff"][0][3]
-            else:
-                substat_1 = None
-                substat_1_value = 0
-                substat_1_enchant = 0
-                substat_1_grind = 0
-            if len(rune["sec_eff"]) > 1:
-                substat_2 = rune["sec_eff"][1][0]
-                substat_2_value = rune["sec_eff"][1][1]
-                substat_2_enchant = rune["sec_eff"][1][2]
-                substat_2_grind = rune["sec_eff"][1][3]
-            else:
-                substat_2 = None
-                substat_2_value = 0
-                substat_2_enchant = 0
-                substat_2_grind = 0
-            if len(rune["sec_eff"]) > 2:
-                substat_3 = rune["sec_eff"][2][0]
-                substat_3_value = rune["sec_eff"][2][1]
-                substat_3_enchant = rune["sec_eff"][2][2]
-                substat_3_grind = rune["sec_eff"][2][3]
-            else:
-                substat_3 = None
-                substat_3_value = 0
-                substat_3_enchant = 0
-                substat_3_grind = 0
-            if len(rune["sec_eff"]) > 3:
-                substat_4 = rune["sec_eff"][3][0]
-                substat_4_value = rune["sec_eff"][3][1]
-                substat_4_enchant = rune["sec_eff"][3][2]
-                substat_4_grind = rune["sec_eff"][3][3]
-            else:
-                substat_4 = None
-                substat_4_value = 0
-                substat_4_enchant = 0
-                substat_4_grind = 0
-
-            # Calculate efficiences
-            efficiency = 0
-            substats = []
-            efficiency += float(MAIN_STAT_VALUES[main_stat][stars][15]) / float(MAIN_STAT_VALUES[main_stat][6][15])
-            if innate_stat is not None:
-                efficiency += innate_stat_value / float(SUBSTAT_INCREMENTS[innate_stat][6] * 5)
-            if substat_1 is not None:
-                substats.append(substat_1)
-                efficiency += substat_1_value / float(SUBSTAT_INCREMENTS[substat_1][6] * 5)
-            if substat_2 is not None:
-                substats.append(substat_2)
-                efficiency += substat_2_value / float(SUBSTAT_INCREMENTS[substat_2][6] * 5)
-            if substat_3 is not None:
-                substats.append(substat_3)
-                efficiency += substat_3_value / float(SUBSTAT_INCREMENTS[substat_3][6] * 5)
-            if substat_4 is not None:
-                substats.append(substat_4)
-                efficiency += substat_4_value / float(SUBSTAT_INCREMENTS[substat_4][6] * 5)
-            efficiency = efficiency / 2.8 * 100
-            max_efficiency = get_max_efficiency(substats, efficiency, level, stars, original_quality)
-            if efficiency > 100:
-                efficiency = 100;
-            if max_efficiency > 100:
-                max_efficiency = 100;
-            # TODO: Locked status not in JSO file.
-            locked = 0
-            insert(db, "rune", (uid, id, assigned_to, runeset, slot, stars, ancient, level, quality, original_quality, value, efficiency, max_efficiency, main_stat, main_stat_value, innate_stat, innate_stat_value, substat_1, substat_1_value, substat_1_enchant, substat_1_grind, substat_2, substat_2_value, substat_2_enchant, substat_2_grind, substat_3, substat_3_value, substat_3_enchant, substat_3_grind, substat_4, substat_4_value, substat_4_enchant, substat_4_grind, locked))
-    db.commit()
-
-"""
-Parses artifact data (table artifact).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseArtifacts(db, data):
-    print("Parsing artifacts...")
-    uid = data["wizard_info"]["wizard_id"]
-    # Unequipped artifacts
-    for artifact in data["artifacts"]:
-        id = artifact["rid"]
-        assigned_to = None
-        type = artifact["type"]
-        attribute = artifact["attribute"]
-        if attribute == 0:
-            attribute = None
-        archetype = artifact["unit_style"]
-        if archetype == 0:
-            archetype = None
-        level = artifact["level"]
-        quality = artifact["rank"]
-        original_quality = artifact["natural_rank"]
-        # TODO: Vaue not in JSON file. Can it be calculated?
-        value = 0;
-        main_stat = artifact["pri_effect"][0]
-        main_stat_value = artifact["pri_effect"][1]
-        locked = artifact["locked"]
-        if len(artifact["sec_effects"]) > 0:
-            effect_1 = artifact["sec_effects"][0][0]
-            effect_1_value = artifact["sec_effects"][0][1]
-            effect_1_enchant = artifact["sec_effects"][0][2]
-            effect_1_grind = artifact["sec_effects"][0][3]
-        else:
-            effect_1 = None
-            effect_1_value = 0
-            effect_1_enchant = 0
-            effect_1_grind = 0
-        if len(artifact["sec_effects"]) > 1:
-            effect_2 = artifact["sec_effects"][1][0]
-            effect_2_value = artifact["sec_effects"][1][1]
-            effect_2_enchant = artifact["sec_effects"][1][2]
-            effect_2_grind = artifact["sec_effects"][1][3]
-        else:
-            effect_2 = None
-            effect_2_value = 0
-            effect_2_enchant = 0
-            effect_2_grind = 0
-        if len(artifact["sec_effects"]) > 2:
-            effect_3 = artifact["sec_effects"][2][0]
-            effect_3_value = artifact["sec_effects"][2][1]
-            effect_3_enchant = artifact["sec_effects"][2][2]
-            effect_3_grind = artifact["sec_effects"][2][3]
-        else:
-            effect_3 = None
-            effect_3_value = 0
-            effect_3_enchant = 0
-            effect_3_grind = 0
-        if len(artifact["sec_effects"]) > 3:
-            effect_4 = artifact["sec_effects"][3][0]
-            effect_4_value = artifact["sec_effects"][3][1]
-            effect_4_enchant = artifact["sec_effects"][3][2]
-            effect_4_grind = artifact["sec_effects"][3][3]
-        else:
-            effect_4 = None
-            effect_4_value = 0
-            effect_4_enchant = 0
-            effect_4_grind = 0
-        # TODO: efficiences
-        efficiency = 0
-        max_efficiency = 0
-        insert(db, "artifact", (uid, id, assigned_to, type, attribute, archetype, level, quality, original_quality, value, efficiency, max_efficiency, main_stat, main_stat_value, effect_1, effect_1_value, effect_1_enchant, effect_1_grind, effect_2, effect_2_value, effect_2_enchant, effect_2_grind, effect_3, effect_3_value, effect_3_enchant, effect_3_grind, effect_4, effect_4_value, effect_4_enchant, effect_4_grind, locked))
-    # Equipped artifacts
-    for mon in data["unit_list"]:
-        for artifact in mon["artifacts"]:
-            id = artifact["rid"]
-            assigned_to = artifact["occupied_id"]
-            if assigned_to == 0:
-                assigned_to = None
-            type = artifact["type"]
-            attribute = artifact["attribute"]
-            if attribute == 0:
-                attribute = None
-            archetype = artifact["unit_style"]
-            if archetype == 0:
-                archetype = None
-            level = artifact["level"]
-            quality = artifact["rank"]
-            original_quality = artifact["natural_rank"]
-            # TODO: Vaue not in JSON file. Can it be calculated?
-            value = 0;
-            main_stat = artifact["pri_effect"][0]
-            main_stat_value = artifact["pri_effect"][1]
-            locked = artifact["locked"]
-            if len(artifact["sec_effects"]) > 0:
-                effect_1 = artifact["sec_effects"][0][0]
-                effect_1_value = artifact["sec_effects"][0][1]
-                effect_1_enchant = artifact["sec_effects"][0][2]
-                effect_1_grind = artifact["sec_effects"][0][3]
-            else:
-                effect_1 = None
-                effect_1_value = 0
-                effect_1_enchant = 0
-                effect_1_grind = 0
-            if len(artifact["sec_effects"]) > 1:
-                effect_2 = artifact["sec_effects"][1][0]
-                effect_2_value = artifact["sec_effects"][1][1]
-                effect_2_enchant = artifact["sec_effects"][1][2]
-                effect_2_grind = artifact["sec_effects"][1][3]
-            else:
-                effect_2 = None
-                effect_2_value = 0
-                effect_2_enchant = 0
-                effect_2_grind = 0
-            if len(artifact["sec_effects"]) > 2:
-                effect_3 = artifact["sec_effects"][2][0]
-                effect_3_value = artifact["sec_effects"][2][1]
-                effect_3_enchant = artifact["sec_effects"][2][2]
-                effect_3_grind = artifact["sec_effects"][2][3]
-            else:
-                effect_3 = None
-                effect_3_value = 0
-                effect_3_enchant = 0
-                effect_3_grind = 0
-            if len(artifact["sec_effects"]) > 3:
-                effect_4 = artifact["sec_effects"][3][0]
-                effect_4_value = artifact["sec_effects"][3][1]
-                effect_4_enchant = artifact["sec_effects"][3][2]
-                effect_4_grind = artifact["sec_effects"][3][3]
-            else:
-                effect_4 = None
-                effect_4_value = 0
-                effect_4_enchant = 0
-                effect_4_grind = 0
-            # TODO: efficiences
-            efficiency = 0
-            max_efficiency = 0
-            insert(db, "artifact", (uid, id, assigned_to, type, attribute, archetype, level, quality, original_quality, value, efficiency, max_efficiency, main_stat, main_stat_value, effect_1, effect_1_value, effect_1_enchant, effect_1_grind, effect_2, effect_2_value, effect_2_enchant, effect_2_grind, effect_3, effect_3_value, effect_3_enchant, effect_3_grind, effect_4, effect_4_value, effect_4_enchant, effect_4_grind, locked))
-        
-
-"""
-calculates the max efficiency of a rune.
-
-:param substats: Array of substat types, dont include empty ones.
-:param efficiency: Current rune efficiency.
-:param level: Current rune level.
-:param stars: Rune stars.
-:param quality: Rune original quality.
-:return Max. efficiency.
-"""
-def get_max_efficiency(substats, efficiency, level, stars, quality):
-    STAT_HP = 1
-    STAT_HP_PCT = 2
-    STAT_ATK = 3
-    STAT_ATK_PCT = 4
-    STAT_DEF = 5
-    STAT_DEF_PCT = 6
-    STAT_SPD = 8
-    STAT_CRIT_RATE_PCT = 9
-    STAT_CRIT_DMG_PCT = 10
-    STAT_RESIST_PCT = 11
-    STAT_ACCURACY_PCT = 12
-    SUBSTAT_INCREMENTS = {
-        # [stat][stars]: value
-        STAT_HP: {
-            1: 60,
-            2: 105,
-            3: 165,
-            4: 225,
-            5: 300,
-            6: 375,
-        },
-        STAT_HP_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ATK: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_ATK_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_DEF: {
-            1: 4,
-            2: 5,
-            3: 8,
-            4: 10,
-            5: 15,
-            6: 20,
-        },
-        STAT_DEF_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_SPD: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_RATE_PCT: {
-            1: 1,
-            2: 2,
-            3: 3,
-            4: 4,
-            5: 5,
-            6: 6,
-        },
-        STAT_CRIT_DMG_PCT: {
-            1: 2,
-            2: 3,
-            3: 4,
-            4: 5,
-            5: 6,
-            6: 7,
-        },
-        STAT_RESIST_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-        STAT_ACCURACY_PCT: {
-            1: 2,
-            2: 3,
-            3: 5,
-            4: 6,
-            5: 7,
-            6: 8,
-        },
-    }
-    UPGRADE_VALUES = {
-        rune_type: {
-            stars: value/level_data[6]
-            for stars, value in level_data.items()
-        }
-        for rune_type, level_data in SUBSTAT_INCREMENTS.items()
-    }
-    #substat_upgrades_remaining = (4 - math.floor((min(level, 12) / 3))) - (3 - quality)
-    substat_upgrades_remaining = (4 - math.floor((min(level, 12) / 3))) - max((3 - quality), 0)
-    new_stats = max(min(4 - len(substats), substat_upgrades_remaining), 0)
-    old_stats = substat_upgrades_remaining - new_stats
-
-    if old_stats > 0:
-        # we can repeatedly upgrade the most value of the existing stats
-        best_stat = max(
-            0,  # ensure max() doesn't error if we only have one stat
-            *[UPGRADE_VALUES[stat][stars] for stat in substats]
-        )
-        efficiency += best_stat * old_stats * 0.2 / 2.8 * 100
-    if new_stats:
-        # add the top N stats
-        available_upgrades = sorted(
-            [
-                upgrade_value[stars]
-                for stat, upgrade_value in UPGRADE_VALUES.items()
-                if stat not in substats
-            ],
-            reverse=True
-        )
-        efficiency += sum(available_upgrades[:new_stats]) * 0.2 / 2.8 * 100
-
-    return efficiency
-
-"""
-Parses rune craft item data (table rune_craft).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseRuneCraft(db, data):
-    print("Parsing rune craft itmes...")
-    uid = data["wizard_info"]["wizard_id"]
-    for item in data["rune_craft_item_list"]:
-        id = item["craft_item_id"]
-        type = item["craft_type"]
-        value = item["sell_value"]
-        amount = str(item["amount"])
-        """
-        info : 5 or 6 digit number: RRSSQ
-          RR: Rune
-          SS: Stat
-          Q:  Quality
-        """
-        info = str(item["craft_type_id"])
-        quality = int(info[-1:])
-        stat = int(info[-4:-2])
-        rune = int(info[:-4])
-        insert(db, "rune_craft", (uid, id, type, quality, rune, stat, value, amount))
-
-"""
-Parses guild data (tables guild, guild_member).
-
-:param db: Sqlite database connection.
-:param data: Data in json format.
-"""
-def parseGuild(db, data):
-    print("Parsing guild...")
-    cursor = db.cursor()
-    if (data["guild"]["guild_info"] == None):
-        # No guild
-        return
-    if len(data["guild"]["guild_info"]) < 1:
-        return
-    guild = data["guild"]["guild_info"]
-    id = guild["guild_id"]
-    name = guild["name"]
-    level = guild["level"]
-    experience = guild["experience"]
-    recruiting = guild["recruit_status"]
-    members = guild["member_now"]
-    leader = guild["master_wizard_id"]
-    comment = guild["comment"]
-    notice = guild["notice"]
-    # Delete selected guild before inserting
-    cursor.execute("DELETE FROM guild WHERE id = ?", [id])
-    cursor.execute("DELETE FROM guild_member WHERE guild = ?", [id])
-    db.commit()
-    insert(db, "guild", (id, name, level, experience, recruiting, members, leader, comment, notice))
-    # Single quates ahead, dirty fix
-    for k, member in data["guild"]["guild_members"].items():
-        m = json.loads(str(member).replace("'", '"'))
-        id = m["wizard_id"]
-        guild = member["guild_id"]
-        grade = member["grade"]
-        name = member["wizard_name"]
-        level = member["wizard_level"]
-        rating = member["rating_id"]
-        arena_score = member["arena_score"]
-        joined = member["join_timestamp"]
-        last_login = member["last_login_timestamp"]
-        in_war = 0 # Checked later
-        has_defense = 0 # Checked later
-        insert(db, "guild_member", (id, guild, grade, name, level, rating, arena_score, joined, last_login, in_war, has_defense))
-    for war in data["guildwar_member_list"]:
-        cursor.execute("UPDATE guild_member SET in_war = 1 WHERE guild = ? AND id = ?;", (war["guild_id"], war["wizard_id"]))
-    for defense in data["guild_member_defense_list"]:
-        if len(defense["unit_list"]) > 0:
-            cursor.execute("UPDATE guild_member SET has_defense = 1 WHERE id = ?", [defense["wizard_id"]])
-    db.commit()
-    cursor.close()
-
-"""
-Deletes teams whose members no longer exists.
-
-:param db: Sqlite database connection.
-"""
-def reconfigureTeams(db):
-    print("Fixing teams...")
-    uid = data["wizard_info"]["wizard_id"]
-    cursor = db.cursor()
-    cursor.execute("DELETE FROM team WHERE id IN (SELECT DISTINCT team FROM team_unit WHERE unit NOT IN (SELECT DISTINCT id FROM unit WHERE uid = ?)) AND uid = ?",  (uid, uid))
-    cursor.execute("DELETE FROM team_unit WHERE unit NOT IN (SELECT DISTINCT id FROM unit) OR team NOT IN (SELECT DISTINCT id FROM team);")
-    db.commit()
-    cursor.close()
-
-"""
-Begin script
-"""
-try:
-    data = readData()
-except Exception as e:
-    print("Error reading data: " + str(e))
-    sys.exit(400)
-try:
-    key = readKey()
-except Exception as e:
-    print("Error fetching API key: " + str(e))
-    sys.exit(400)
-try:
-    db = openDatabase()
-except Exception as e:
-    print("Error opening database: " + str(e))
-    sys.exit(500)
-if verifyKey(db, data, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(401)
-else:
-    try:
-        clearData(db, data)
-    except Exception as e:
-        print("Error clearing data: " + str(e))
-        sys.exit(500)
-    try:
-        parsePlayer(db, data)
-    except Exception as e:
-        print("Error parsing player data: " + str(e))
-        sys.exit(400)
-    try:
-        parseScenarios(db, data)
-    except Exception as e:
-        print("Error parsing scenario data: " + str(e))
-        sys.exit(400)
-    try:
-        parseDefense(db, data)
-    except Exception as e:
-        print("Error parsing defense data: " + str(e))
-        sys.exit(400)
-    try:
-        parseGWDefense(db, data)
-    except Exception as e:
-        print("Error parsing guild war defense data: " + str(e))
-        sys.exit(400)
-    try:
-        parseBuildings(db, data)
-    except Exception as e:
-        print("Error parsing building data: " + str(e))
-        sys.exit(400)
-    try:
-        parseDecorations(db, data)
-    except Exception as e:
-        print("Error parsing decoration data: " + str(e))
-        sys.exit(400)
-    # TODO homunculus_skill_list
-    try:
-        parseUnits(db, data)
-    except Exception as e:
-        print("Error parsing unit data: " + str(e))
-        sys.exit(400)
-    try:
-        parseSummonSpecial(db, data)
-    except Exception as e:
-        print("Error parsing special summon data: " + str(e))
-        sys.exit(400)
-    try:
-        parseInventory(db, data)
-    except Exception as e:
-        print("Error parsing inventory data: " + str(e))
-        sys.exit(400)
-    try:
-        parseRunes(db, data)
-    except Exception as e:
-        print("Error parsing rune data: " + str(e))
-        sys.exit(400)
-    try:
-        parseArtifacts(db, data)
-    except Exception as e:
-        print("Error parsing artifact data: " + str(e))
-        sys.exit(400)
-    try:
-        parseRuneCraft(db, data)
-    except Exception as e:
-        print("Error parsing rune craft data: " + str(e))
-        sys.exit(400)
-    try:
-        parseGuild(db, data)
-    except Exception as e:
-        print("Error parsing guild data: " + str(e))
-        sys.exit(400)
-    try:
-        reconfigureTeams(db)
-    except Exception as e:
-        print("Error reconfiguring teams: " + str(e))
-        sys.exit(400)
-    try:
-        closeDatabase(db)
-    except Exception as e:
-        print("Error closing database: " + str(e))
-        # No error
-sys.exit(200);
-

+ 0 - 249
application/API/v2/bin/upload_run_dimension.py

@@ -1,249 +0,0 @@
-#!/usr/bin/python3
-
-import sqlite3
-import json
-import sys
-import os
-
-import MAPPING
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:param: index 2 for start data, 3 for result data
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData(index):
-    try:
-        data = json.loads(sys.argv[index])
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_info"]["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and deletes from the user tables
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute('attach "' + udb + '" as data;')
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
-run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
-run_drop_shapeshifting).
-
-:param db: Sqlite database connection.
-:param data_start: JSON data of the run start.
-:param data_result: JSON data of the run result.
-"""
-def parseRun(db, data_request, data_response):
-    print("Parsing run...")
-    cursor = db.cursor()
-
-    # Read basic data
-    uid = data_request["wizard_id"]
-    dtime = data_response["tvaluelocal"]
-
-    # Check if run has already been inserted.
-    cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime))
-    if (cursor.fetchone()[0] > 0):
-        print("    Run already in database. Stopping....")
-        return 409;
-
-    # We are inserting, get aditional info
-    area_type = 5 # Dimension Hole Dungeon
-    area = data_request["dungeon_id"]
-    stage = data_request["difficulty"] # Stage is difficulty
-    difficulty = None
-    win = data_response["win_lose"]
-    time = data_response["clear_time"]["current_time"]
-    if ("mana" in data_response["reward"]):
-        mana = data_response["reward"]["mana"]
-    else:
-        mana = 0
-    if ("energy" in data_response["reward"]):
-        energy = mana = data_response["reward"]["energy"]
-    else:
-        energy = 0
-    if ("crystal" in data_response["reward"]):
-        crystal = mana = data_response["reward"]["crystal"]
-    else:
-        crystal = 0
-    helper = 0
-
-    # Get the new ID and insert
-    cursor.execute("SELECT max(id) + 1 AS id FROM run;")
-    id = cursor.fetchone()[0]
-    if id == None:
-        id = 1
-
-    score = None
-    rank = None
-    insert(db, "run", (uid, id, dtime, area_type, area, stage, difficulty, win, time, mana, energy, crystal, helper, score, rank))
-
-    # Parse various types of reward
-    crate = data_response["reward"]["crate"]
-
-    if "item" in crate:
-        for item in crate["item"]:
-            insert(db, "run_drop_item", (id, item["item_id"], item["item_quantity"]))
-    if "craft_stuff" in crate:
-        for item in crate["craft_stuff"]:
-            insert(db, ".run_drop_rune_craft", (id, item["item_id"], item["item_quantity"]))
-
-    # Parse rune reward
-    if "rune" in crate:
-        rune = crate["rune"]
-        rune_id = rune["rune_id"]
-        rune_type = rune["set_id"]
-        slot = rune["slot_no"]
-        stars = rune["class"]
-        ancient = 0
-        quality = rune["rank"]
-        value = rune["sell_value"]
-        efficiency, max_efficiency = MAPPING.calculate_efficiency(rune)
-        main_stat = rune["pri_eff"][0]
-        main_stat_value = rune["pri_eff"][1]
-        if "prefix_eff" in rune:
-            innate_stat = rune["prefix_eff"][0]
-            innate_stat_value = rune["prefix_eff"][1]
-        else:
-            innate_stat = 0
-            innate_stat_value = 0
-        substat_1 = 0
-        substat_1_value = 0
-        substat_2 = 0
-        substat_2_value = 0
-        substat_3 = 0
-        substat_3_value = 0
-        substat_4 = 0
-        substat_4_value = 0
-        if "0" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["0"]["0"]
-            substat_1_value = rune["sec_eff"]["0"]["1"]
-        if "1" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["1"]["0"]
-            substat_1_value = rune["sec_eff"]["1"]["1"]
-        if "2" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["2"]["0"]
-            substat_1_value = rune["sec_eff"]["2"]["1"]
-        if "3" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["3"]["0"]
-            substat_1_value = rune["sec_eff"]["3"]["1"]
-        insert(db, "run_drop_rune", (id, rune_id, rune_type, slot, stars, ancient, quality, value, efficiency, max_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))
-
-    # Parse units
-    for unit in data_request["unit_id_list"]:
-        unit_id = unit["unit_id"]
-        unit_master_id = None
-        for k_unit in data_response["unit_list"]:
-            if k_unit["unit_id"] == unit["unit_id"]:
-                unit_master_id = k_unit["unit_master_id"];
-                break;
-        #unit_master_id = data_response["unit_list"][attribute]["unit_master_id"]
-        leader = unit["is_leader"]
-        front = 0
-        insert(db, "run_party", (id, unit_master_id, unit_id, leader, front))
-    db.commit()
-
-
-"""
-Begin script
-"""
-data_request = readData(2)
-data_response = readData(3)
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data_response, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(401)
-else:
-    try:
-        parseRun(db, data_request, data_response)
-    except Exception as e:
-        print("Error parsing Dimension Hole Dungeon run: " + str(e))
-        sys.exit(400)
-sys.exit(201)
-
-

+ 0 - 256
application/API/v2/bin/upload_run_dungeon.py

@@ -1,256 +0,0 @@
-#!/usr/bin/python3
-
-import sqlite3
-import json
-import sys
-import os
-
-import MAPPING
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:param: index 2 for start data, 3 for result data
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData(index):
-    try:
-        data = json.loads(sys.argv[index])
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_info"]["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and deletes from the user tables
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute('attach "' + udb + '" as data;')
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
-run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
-run_drop_shapeshifting).
-
-:param db: Sqlite database connection.
-:param data_start: JSON data of the run start.
-:param data_result: JSON data of the run result.
-"""
-def parseRun(db, data_request, data_response):
-    print("Parsing run...")
-    cursor = db.cursor()
-
-    # Read basic data
-    uid = data_request["wizard_id"]
-    dtime = data_response["tvaluelocal"]
-
-    # Check if run has already been inserted.
-    cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime))
-    if (cursor.fetchone()[0] > 0):
-        print("    Run already in database. Stopping....")
-        return 409;
-
-    # We are inserting, get aditional info
-    area_type = 2 # Cairos Dungeon
-    area = data_request["dungeon_id"]
-    stage = data_request["stage_id"]
-    difficulty = None
-    win = data_response["win_lose"]
-    time = data_response["clear_time"]["current_time"]
-    if ("mana" in data_response["reward"]):
-        mana = data_response["reward"]["mana"]
-    else:
-        mana = 0
-    if ("energy" in data_response["reward"]):
-        energy = mana = data_response["reward"]["energy"]
-    else:
-        energy = 0
-    if ("crystal" in data_response["reward"]):
-        crystal = mana = data_response["reward"]["crystal"]
-    else:
-        crystal = 0
-    guild_points = 0
-    # TODO Read helper. Do a test with SWBD-debug
-    helper = 0
-
-    # GEt the new ID and insert
-    cursor.execute("SELECT max(id) + 1 AS id FROM run;")
-    id = cursor.fetchone()[0]
-    if id == None:
-        id = 1
-
-    score = None
-    rank = None
-    insert(db, "run", (uid, id, dtime, area_type, area, stage, difficulty, win, time, mana, energy, crystal, guild_points, helper, score, rank))
-
-    # Parse various types of reward
-    crate = data_response["reward"]["crate"]
-    if "costume_point" in crate and crate["costume_point"] > 0:
-        insert(db, "run_drop_shapeshifting", (id, crate["costume_point"]))
-    if "instance_info" in data_response:
-        insert(db, "run_drop_sd", (id, data_response["instance_info"]))
-    if "unit_info" in crate:
-        insert(db, "run_drop_unit", (id, crate["unit_info"]["unit_master_id"]))
-    if "summon_pieces" in crate:
-        insert(db, "run_drop_unit_pieces", (id, crate["summon_pieces"]["item_master_id"], crate["summon_pieces"]["item_quantity"]))
-    if "item" in crate:
-        for item in crate["item"]:
-            insert(db, "run_drop_item", (id, item["item_id"], item["item_quantity"]))
-
-    # Parse rune reward
-    if "rune" in crate:
-        rune = crate["rune"]
-        rune_id = rune["rune_id"]
-        rune_type = rune["set_id"]
-        slot = rune["slot_no"]
-        stars = rune["class"]
-        ancient = 0
-        quality = rune["rank"]
-        value = rune["sell_value"]
-        efficiency, max_efficiency = MAPPING.calculate_efficiency(rune)
-        main_stat = rune["pri_eff"][0]
-        main_stat_value = rune["pri_eff"][1]
-        if "prefix_eff" in rune:
-            innate_stat = rune["prefix_eff"][0]
-            innate_stat_value = rune["prefix_eff"][1]
-        else:
-            innate_stat = 0
-            innate_stat_value = 0
-        substat_1 = 0
-        substat_1_value = 0
-        substat_2 = 0
-        substat_2_value = 0
-        substat_3 = 0
-        substat_3_value = 0
-        substat_4 = 0
-        substat_4_value = 0
-        if "0" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["0"]["0"]
-            substat_1_value = rune["sec_eff"]["0"]["1"]
-        if "1" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["1"]["0"]
-            substat_1_value = rune["sec_eff"]["1"]["1"]
-        if "2" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["2"]["0"]
-            substat_1_value = rune["sec_eff"]["2"]["1"]
-        if "3" in rune["sec_eff"]:
-            substat_1 = rune["sec_eff"]["3"]["0"]
-            substat_1_value = rune["sec_eff"]["3"]["1"]
-        insert(db, "run_drop_rune", (id, rune_id, rune_type, slot, stars, ancient, quality, value, efficiency, max_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))
-
-    # Parse units
-    #for attribute, value in data_request["unit_id_list"]:
-    for unit in data_request["unit_id_list"]:
-        unit_id = unit["unit_id"]
-        unit_master_id = None
-        for k_unit in data_response["unit_list"]:
-            if k_unit["unit_id"] == unit["unit_id"]:
-                unit_master_id = k_unit["unit_master_id"];
-                break;
-        #unit_master_id = data_response["unit_list"][attribute]["unit_master_id"]
-        leader = unit["is_leader"]
-        front = 0
-        insert(db, "run_party", (id, unit_master_id, unit_id, leader, front))
-    db.commit()
-
-
-"""
-Begin script
-"""
-data_request = readData(2)
-data_response = readData(3)
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data_response, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(401)
-else:
-    #try:
-        parseRun(db, data_request, data_response)
-    #except Exception as e:
-    #    print("Error parsing dungeon run: " + str(e))
-    #    sys.exit(400)
-sys.exit(201)
-
-

+ 0 - 274
application/API/v2/bin/upload_run_rift.py

@@ -1,274 +0,0 @@
-#!/usr/bin/python3
-
-import sqlite3
-import json
-import sys
-import os
-
-import MAPPING
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:param: index 2 for start data, 3 for result data, 4 for event start request, 5
-for event start response.
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData(index):
-    try:
-        data = json.loads(sys.argv[index])
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_info"]["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and deletes from the user tables
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute('attach "' + udb + '" as data;')
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
-run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
-run_drop_shapeshifting).
-
-:param db: Sqlite database connection.
-:param data_request: JSON data of the run result request.
-:param data_response: JSON data of the run result response.
-:param data_start_request: JSON data of the run start request.
-:param data_start_response: JSON data of the run start response.
-"""
-def parseRun(db, data_request, data_response, data_start_request, data_start_response):
-    print("Parsing run...")
-    cursor = db.cursor()
-
-    # Read basic data
-    uid = data_request["wizard_id"]
-    dtime = data_response["tvaluelocal"]
-
-    # Check if run has already been inserted.
-    cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime))
-    if (cursor.fetchone()[0] > 0):
-        print("    Run already in database. Stopping....")
-        return 409;
-
-    # We are inserting, get aditional info
-    area_type = 3 # Rift Dungeon
-    area = data_request["dungeon_id"]
-    stage = None
-    difficulty = None
-    score = data_response["total_damage"]
-    rank = "F"
-    raw_rank = data_response["rift_dungeon_box_id"]
-    win = 1
-    if raw_rank == 0:
-        rank = "F"
-        win = 0
-    elif raw_rank == 1:
-        rank = "D"
-    elif raw_rank == 2:
-        rank = "C"
-    elif raw_rank == 3:
-        rank = "B-"
-    elif raw_rank == 4:
-        rank = "B"
-    elif raw_rank == 5:
-        rank = "B+"
-    elif raw_rank == 6:
-        rank = "A-"
-    elif raw_rank == 7:
-        rank = "A"
-    elif raw_rank == 8:
-        rank = "A+"
-    elif raw_rank == 9:
-        rank = "S"
-    elif raw_rank == 10:
-        rank = "SS"
-    elif raw_rank == 11:
-        rank = "SSS"
-    # TODO
-    time = 1
-    #time = data_response["clear_time"]
-
-    # Get the new ID and insert
-    cursor.execute("SELECT max(id) + 1 AS id FROM run;")
-    id = cursor.fetchone()[0]
-    if id == None:
-        id = 1
-    mana = 0
-    energy = 0
-    crystal = 0
-    helper = 0
-    insert(db, "run", (uid, id, dtime, area_type, area, stage, difficulty, win, time, mana, energy, crystal, helper, score, rank))
-
-
-    for item in data_response["item_list"]:
-        type = item["type"]
-
-        if type == 29: # Craft material
-            insert(db, "run_drop_item", (id, item["id"], item["quantity"]))
-
-        elif type == 8: # Rune
-            rune = item["info"]
-            rune_id = rune["rune_id"]
-            rune_type = rune["set_id"]
-            slot = rune["slot_no"]
-            stars = rune["class"]
-            ancient = 0
-            quality = rune["rank"]
-            value = rune["sell_value"]
-            efficiency, max_efficiency = MAPPING.calculate_efficiency(rune)
-            main_stat = rune["pri_eff"][0]
-            main_stat_value = rune["pri_eff"][1]
-            if "prefix_eff" in rune:
-                innate_stat = rune["prefix_eff"][0]
-                innate_stat_value = rune["prefix_eff"][1]
-            else:
-                innate_stat = 0
-                innate_stat_value = 0
-            substat_1 = 0
-            substat_1_value = 0
-            substat_2 = 0
-            substat_2_value = 0
-            substat_3 = 0
-            substat_3_value = 0
-            substat_4 = 0
-            substat_4_value = 0
-            if "0" in rune["sec_eff"]:
-                substat_1 = rune["sec_eff"]["0"]["0"]
-                substat_1_value = rune["sec_eff"]["0"]["1"]
-            if "1" in rune["sec_eff"]:
-                substat_1 = rune["sec_eff"]["1"]["0"]
-                substat_1_value = rune["sec_eff"]["1"]["1"]
-            if "2" in rune["sec_eff"]:
-                substat_1 = rune["sec_eff"]["2"]["0"]
-                substat_1_value = rune["sec_eff"]["2"]["1"]
-            if "3" in rune["sec_eff"]:
-                substat_1 = rune["sec_eff"]["3"]["0"]
-                substat_1_value = rune["sec_eff"]["3"]["1"]
-            insert(db, "run_drop_rune", (id, rune_id, rune_type, slot, stars, ancient, quality, value, efficiency, max_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))
-
-        # TODO: Grindstones and gems
-        # TODO: Unit
-
-    # Parse party
-    leader_slot = data_start_request["leader_index"]
-    for unit in data_start_request["unit_id_list"]:
-        unit_id = unit["unit_id"]
-        slot = unit["slot_index"]
-        leader = 0
-        front = 0
-        if slot == leader_slot:
-            leader = 1
-        if slot <= 3:
-            front = 1
-        cursor.execute("SELECT unit FROM unit WHERE uid = ? AND id = ?;", (uid, unit_id))
-        unit_master_id = cursor.fetchone()[0]
-        insert(db, "run_party", (id, unit_id, unit_master_id, leader, front))
-
-    db.commit()
-
-
-"""
-Begin script
-"""
-data_request = readData(2)
-data_response = readData(3)
-data_start_request = readData(4)
-data_start_response = readData(5)
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data_response, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(401)
-else:
-    try:
-        parseRun(db, data_request, data_response, data_start_request, data_start_response)
-    except Exception as e:
-        print("Error parsing Rift Dungeon run: " + str(e))
-        sys.exit(400)
-sys.exit(201)
-
-

+ 0 - 209
application/API/v2/bin/upload_run_scenario.py

@@ -1,209 +0,0 @@
-#!/usr/bin/python3
-
-import sqlite3
-import json
-import sys
-import os
-
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        #print(sys.argv[0])
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData():
-    try:
-        data = json.loads(sys.argv[2])
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_info"]["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and deletes from the user tables
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute('attach "' + udb + '" as data;')
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error creating database " + name + ": " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
-run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
-run_drop_shapeshifting).
-
-:param db: Sqlite database connection.
-:param data: JSON data.
-"""
-def parseRun(db, data):
-    print("Parsing run...")
-    cursor = db.cursor()
-    uid = data["wizard_info"]["wizard_id"]
-    dtime = data["tvaluelocal"]
-    # Check if run has already been inserted.
-    cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime))
-    if (cursor.fetchone()[0] > 0):
-        print("    Run already in database. Stopping....")
-        return;
-    area_type = 1 #scenario 
-    area = data["scenario_info"]["region_id"]
-    stage = data["scenario_info"]["stage_no"]
-    difficulty = data["scenario_info"]["difficulty"]
-    win = data["win_lose"]
-    time = data["clear_time"]["current_time"]
-    if ("mana" in data["reward"]):
-        mana = data["reward"]["mana"]
-    else:
-        mana = 0
-    if ("energy" in data["reward"]):
-        energy = mana = data["reward"]["energy"]
-    else:
-        energy = 0
-    if ("crystal" in data["reward"]):
-        crystal = mana = data["reward"]["crystal"]
-    else:
-        crystal = 0
-    helper = data["helper"]
-    cursor.execute("SELECT max(id) + 1 AS id FROM run;")
-    id = cursor.fetchone()[0]
-    if id == None:
-        id = 1
-    score = None
-    rank = None
-    insert(db, "run", (uid, id, dtime, area_type, area, stage, difficulty, win, time, mana, energy, crystal, helper, score, rank))
-    if data["shapeshifting"] > 0:
-        insert(db, "run_drop_shapeshifting", (id, data["shapeshifting"]))
-    if data["sd"] > 0:
-        insert(db, "run_drop_sd", (id, data["sd"]))
-    if data["sd"] > 0:
-        insert(db, "run_drop_unit", (id, data["unit"]))
-    for rune in data["rune"]:
-        rune_id = rune["id"]
-        rune_type = rune["type"]
-        slot = rune["slot"]
-        stars = rune["stars"]
-        ancient = rune["ancient"]
-        quality = rune["quality"]
-        value = rune["value"]
-        efficiency = rune["efficiency"]
-        main_stat = rune["main_stat"]
-        main_stat_value = rune["main_stat_value"]
-        innate_stat = rune["innate_stat"]
-        innate_stat_value = rune["innate_stat_value"]
-        substat_1 = rune["substat_1"]
-        substat_1_value = rune["substat_1_value"]
-        substat_2 = rune["substat_2"]
-        substat_2_value = rune["substat_2_value"]
-        substat_3 = rune["substat_3"]
-        substat_3_value = rune["substat_3_value"]
-        substat_4 = rune["substat_4"]
-        substat_4_value = rune["substat_4_value"]
-        insert(db, "run_drop_rune", (id, rune_id, rune_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))
-    for item in data["item"]:
-        item_id = item["id"]
-        quantity = item["quantity"]
-        insert(db, "run_drop_item", (id, item_id, quantity))
-    for pieces in data["unit_pieces"]:
-        pieces_id = pieces["id"]
-        quantity = pieces["quantity"]
-        insert(db, "run_drop_unit_pieces", (id, pieces_id, quantity))
-    for party in data["party"]:
-        unit_id = party["unit_id"]
-        unit_master_id = party["unit_master_id"]
-        insert(db, "run_party", (id, unit_master_id, unit_id))
-    db.commit()
-
-"""
-Begin script
-"""
-data = readData()
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(-1)
-else:
-    parseRun(db, data)
-sys.exit(0)
-
-

+ 0 - 228
application/API/v2/bin/upload_run_toa.py

@@ -1,228 +0,0 @@
-#!/usr/bin/python3
-
-import sqlite3
-import json
-import sys
-import os
-import math
-
-"""
-Reads the API KEY, that must be passed as first command line argument.
-
-:returns: Recovered API KEY.
-:raises Exception: Th KEY couldn't be red.
-"""
-def readKey():
-    try:
-        key = sys.argv[1]
-        return key
-    except Exception as e:
-        print("Error parsing API KEY: " + str(e))
-        raise
-
-"""
-Reads the JSON data, that must be passed as second command line argument.
-
-:param: index 2 for start data, 3 for result data
-:returns: Recovered data, in JSON format.
-:raises Exception: The data couldn't be red or converted to JSON.
-"""
-def readData(index):
-    try:
-        data = json.loads(sys.argv[index])
-        return data
-    except Exception as e:
-        print("Error parsing data: " + str(e))
-        raise
-
-"""
-Verifies that the API key matches the player data and that it exists in th DB.
-
-:param db: Connection to the database.
-:returns: Connection to the database.
-:param data: Data in json format.
-:param key: API KEY.
-:returns: True if key and player match, False otherwise.
-:raises IntegrityError: The queryes couldn't bre executed.
-"""
-def verifyKey(db, data, key):
-    print('Verifying KEY...')
-    status = False
-    try:
-        uid = data["wizard_info"]["wizard_id"]
-        cursor = db.cursor()
-        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
-        if cursor.fetchone()[0] == 1:
-            status = True
-        cursor.close()
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    return status
-
-"""
-Opens the database file and deletes from the user tables
-
-:param name: The path to the sqlite database.
-:returns: Connection to the database.
-:raises IntegrityError: The queryes couldn't bre executed.
-:raises IOError: The sqlite file couldn't be created.
-"""
-def openDatabase():
-    kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
-    udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
-    print('Configuring database...')
-    try:
-        db = sqlite3.connect(kdb)
-        cursor = db.cursor()
-        cursor.execute('attach "' + udb + '" as data;')
-        cursor.close()
-        return db
-    except sqlite3.IntegrityError as e:
-        print("Error executing statement: " + str(e))
-        raise
-    except IOError as e:
-        print("I/O Error opening database " + name + ": " + str(e))
-        raise
-
-"""
-Inserts a row into the database.
-
-:param db: Connection to the database.
-:param table: Name of the table to insert into.
-:param values: List of values to insert.
-:raises IntegrityError: The insert query was unsuccesfull.
-"""
-def insert(db, table, values):
-    cursor = db.cursor()
-    placeholders = ''
-    for x in range(0, len(values)):
-        placeholders = placeholders + '?, '
-    placeholders = placeholders[:len(placeholders) - 2]
-    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
-    try:
-        cursor.execute(query, values)
-    except sqlite3.IntegrityError as e:
-        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
-        raise
-    cursor.close;
-
-"""
-Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
-run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
-run_drop_shapeshifting).
-
-:param db: Sqlite database connection.
-:param data_start: JSON data of the run start.
-:param data_result: JSON data of the run result.
-"""
-def parseRun(db, data_request, data_response):
-    print("Parsing run...")
-    cursor = db.cursor()
-
-    # Read basic data
-    uid = data_request["wizard_id"]
-    dtime = data_response["tvaluelocal"]
-
-    # Check if run has already been inserted.
-    cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime))
-    if (cursor.fetchone()[0] > 0):
-        print("    Run already in database. Stopping....")
-        return 409;
-
-    # We are inserting, get aditional info
-    area_type = 10 # TOA
-    area = 10 # TOA
-    stage = data_request["floor_id"]
-    difficulty = data_request["difficulty"]
-    win = data_response["win_lose"]
-    time = data_request["clear_time"]
-    helper = 0
-
-    # Get the new ID and insert
-    cursor.execute("SELECT max(id) + 1 AS id FROM run;")
-    id = cursor.fetchone()[0]
-    if id == None:
-        id = 1
-
-    # Calculate rewards
-    mana = 0
-    energy = 0
-    crystal = 0
-    if stage == 10:
-        energy = 50
-    elif stage == 20:
-        # Rainbowmon 3* MAX
-        insert(db, "run_drop_item", (id, 143140325, 1))
-    elif stage == 30:
-        # Mystical Scroll
-        insert(db, "run_drop_item", (id, 3, 1))
-    elif stage == 40:
-        crystal = 100
-    elif stage == 50:
-        # Mystical Scroll
-        insert(db, "run_drop_item", (id, 3, 2))
-    elif stage == 60:
-        # Rainbowmon 4* MAX
-        insert(db, "run_drop_item", (id, 143140430, 1))
-    elif stage == 70:
-        # Devilmon
-        insert(db, "run_drop_item", (id, 151050101, 1))
-    elif stage == 80:
-        crystal = 300
-    elif stage == 90:
-        # Light and Dark Scroll
-        insert(db, "run_drop_item", (id, 11, 1))
-    elif stage == 100:
-        # Legendary Scroll
-        insert(db, "run_drop_item", (id, 10, 1))
-    elif stage / 5 == 0:
-        crystal = 10 * int(math.ceil((stage / 2) / 10) + 1)
-    else:
-        # Summon stone
-        insert(db, "run_drop_item", (id, 8, 1))
-
-    # Insert
-    score = None
-    rank = None
-    insert(db, "run", (uid, id, dtime, area_type, area, stage, difficulty, win, time, mana, energy, crystal, helper, score, rank))
-
-    # Parse units
-    i = 0
-    for unit in data_request["unit_id_list"]:
-        unit_id = unit["unit_id"]
-        cursor.execute("SELECT unit FROM unit WHERE uid = ? AND id = ?;", (uid, unit_id))
-        unit_master_id = cursor.fetchone()[0]
-        for k_unit in data_response["unit_list"]:
-            if k_unit["unit_id"] == unit["unit_id"]:
-                unit_master_id = k_unit["unit_master_id"];
-                break;
-        if i == 0:
-            leader = 1 # TODO UNKNOWABLE? Check event start
-        else:
-            leader = 0
-        front = 0
-        insert(db, "run_party", (id, unit_master_id, unit_id, leader, front))
-        i += 1
-    db.commit()
-
-
-"""
-Begin script
-"""
-data_request = readData(2)
-data_response = readData(3)
-key = readKey()
-db = openDatabase()
-if verifyKey(db, data_response, key) == False:
-    print("Invalid API KEY...")
-    sys.exit(401)
-else:
-    try:
-        parseRun(db, data_request, data_response)
-    except Exception as e:
-        print("Error parsing TOA run: " + str(e))
-        sys.exit(400)
-sys.exit(201)
-
-

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 127
application/API/v2/help/api.php


+ 0 - 513
application/API/v2/help/index.php

@@ -1,513 +0,0 @@
-<?php
-    /**
-     * API Help view.
-     *
-     * Shows API documentation.
-     *
-     * @category View
-     * @var mixed[] $API API help structure.
-     */
-?>
-<?php
-    include __DIR__ . "/api.php";
-?>
-<!DOCTYPE html>
-<html lang='en'>
-    <head>
-        <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
-        <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title>SWDB APIv2</title>
-        <link rel='shortcut icon' href='<?=URL::IMG["LOGO"]?>sw.png'/>
-        <!-- CSS -->
-        <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
-        <style>
-
-            section#navbar{
-                text-align: left;
-                position: fixed;
-                top: 0;
-                left: 0;
-                width: 15%;
-                height: 100%;
-                border-radius: 0;
-                margin: 0 1em 0 0;
-                padding: 0em 0.4em 0.1em 0.4em;
-                border-left: 0;
-                border-top: 0;
-                border-bottom: 0;
-            }
-
-            section#navbar hr{
-                height: 0em;
-                padding: 0;
-                margin: 0 1em;
-                border: 0.01em solid #3105;
-                border-radius: 1em;
-            }
-
-            section#navbar h1{
-                text-align: center;
-                margin-top: 0;
-            }
-
-            section#navbar h1 img{
-                max-width: 100%;
-                display: block;
-                margin: auto auto -1em auto;
-            }
-
-            section#navbar h1 div{
-                text-shadow: 0 0 0.5em #000000, 0 0 0.5em #000000, 0 0 0.2em #000000, 0 0 0.2em #000000;
-                font-family: monospace, monospace;
-            }
-
-            section#navbar h1 div#swdb{
-                font-weight: bold;
-                font-size: 160%;
-                margin-bottom: -0.2em;
-            }
-
-            section#navbar h1 div#api{
-                font-style: italic;
-                font-size: 110%;
-            }
-
-            section#navbar h3 {
-                margin: 0.4em 0 0.2em 1em;
-                border-left: 0.5em solid #3105;
-                border-radius: 0.2em;
-                padding-left: 0.3em;
-                background-color: #00000000;
-                transition: all .3s ease-in-out;
-            }
-
-            section#navbar h3:hover{
-                background-color: #3105;
-            }
-
-            section#navbar h3 a{
-                color: #cccccc
-            }
-
-            section#navbar h3:hover a{
-                color: #ffffff
-            }
-
-            section#navbar ul {
-                margin: 0.2em 0;
-                list-style: none;
-            }
-
-            section#navbar ul li{
-                border-left: 0.5em solid #3105;
-                border-radius: 0.2em;
-                padding-left: 0.3em;
-                margin-bottom: 0.2em;
-                background-color: #00000000;
-                transition: all .3s ease-in-out;
-            }
-
-            section#navbar ul li:hover{
-                background-color: #3105;
-            }
-
-            section#navbar ul li a{
-                color: #cccccc
-            }
-
-            section#navbar ul li:hover a{
-                color: #ffffff
-            }
-
-            section#navbar div#copyright{
-                text-align: center;
-                font-size: 70%;
-                position: absolute;
-                bottom: 1em;
-            }
-
-            section.category{
-                margin: 2em 1em 1em 18%;
-            }
-
-            section.category h2{
-                padding: 0.5em 3em;
-            }
-
-            section.category article{
-                margin: 1.5em;
-                padding-left: 1em;
-                padding-right: 1em;
-                text-align: left;
-            }
-
-            section.category article h3{
-                vertical-align: bottom;
-            }
-
-            section.category article h3 span.description{
-                font-style: italic;
-                font-size: 90%;
-            }
-
-            section.category article:not(:last-child){
-                padding-bottom: 1em;
-                margin-bottom: 1em;
-                border-bottom: 0.1em solid #ffffff66;
-            }
-
-            section.category article div.command span{
-                display: inline-block;
-                border-radius: 0.6em;
-                padding: 0.3em 0.5em;
-                border-width: 0.15em;
-                border-style: solid;
-                color: #ffffff;
-                font-family: monospace, monospace;
-                font-weight: bold;
-            }
-
-            section.category article div.command span.url{
-                background-color: #292b36;
-                border-color: #4b4d57;
-            }
-
-            section.category article div.command span.type{
-                text-transform: uppercase;
-            }
-
-            section.category article div.command span.type_GET {
-                background-color: #008000;
-                border-color: #22a222;
-            }
-
-            section.category article div.command span.type_PUT {
-                background-color: #e5c500;
-                border-color: #f7e722;
-            }
-
-            section.category article div.command span.type_POST {
-                background-color: #4070ec;
-                border-color: #6292fe;
-            }
-
-            section.category article div.command span.type_DELETE {
-                background-color: #ed0039;
-                border-color: #ff225b;
-            }
-
-            section.category article table{
-                border-collapse: collapse;
-                width: 80%;
-                border-radius: 0.5em;
-                margin: 0.5em auto 1em auto;
-            }
-
-            section.category article table th {
-                background-color: #331100;
-                text-align: left;
-                font-weight: bold;
-                padding: 0.5em 1em;
-                border: 0.1px solid #e0e0e0;
-            }
-
-            section.category article table td {
-                background-color: #352413;
-                vertical-align: top;
-                padding: 0.2em 0.4em;
-                border: #e0e0e0 1px solid;
-            }
-
-            section.category article table td.name {
-                font-family: monospace, monospace;
-                font-weight: bold;
-            }
-
-            section.category article table td.type {
-                font-family: monospace, monospace;
-                font-weight: bold;
-            }
-
-            section.category article table td.status {
-                font-family: monospace, monospace;
-                font-weight: bold;
-            }
-
-            section.category article table td.description span.optional {
-                font-size: 90%;
-                color: #bbbbbb;
-                font-style: italic;
-            }
-
-            section#example{
-                position: fixed;
-                display: none;
-                top: 15%;
-                left: 20%;
-                width: 60%;
-                max-width: 90em;
-                height: 70%;
-                max-height: 30em;
-                text-align: right;
-            }
-
-            section#example article{
-                text-align: right;
-            }
-
-            section#example article pre#example_content{
-                text-align: left;
-                background-color: #292b36;
-                border: 0.3em solid #4b4d57;
-                border-radius: 0.8em;
-                padding: 1em;
-                max-height: 20em;
-                overflow: scroll;
-            }
-
-        </style>
-        <!-- Javascript -->
-        <script>
-            function showExample(command, status, example){
-                document.getElementById('example_title').innerHTML = command + " HTTP status " + status + " response example";
-                document.getElementById('example_content').innerHTML = JSON.stringify(JSON.parse(example), null, 4);
-                document.getElementById('example').style.display = 'block';
-            }
-            function closeExample(command, status, example){
-                document.getElementById('example').style.display = 'none';
-            }
-        </script>
-        <!-- Meta tags -->
-        <link rel='canonical' href='<?=URL::BASE?>API/v2/help/'/>
-        <link rel='author' href='SWDB'/>
-        <link rel='publisher' href='SWDB'/>
-        <meta name='description' content='SWDB API v2 Documentation'/>
-        <meta property='og:title' content='SWDB APIv2'/>
-        <meta property='og:url' content='<?=URL::BASE?>API/v2/help/'/>
-        <meta property='og:description' content='SWDB API v2 Documentation'/>
-        <meta property='og:image' content='<?=URL::IMG["LOGO"]?>sw.png'/>
-        <meta property='og:site_name' content='SWDB'/>
-        <meta property='og:type' content='website'/>
-        <meta property='og:locale' content='en'/>
-        <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='SWDB APIv2'/>
-        <meta name='twitter:description' content='SWDB API v2 Documentation'/>
-        <meta name='twitter:image' content='<?=URL::IMG["LOGO"]?>sw.png'/>
-        <meta name='twitter:url' content='<?=URL::BASE?>API/v2/help/'/>
-        <meta name='robots' content='index follow'/>
-    </head>
-    <body>
-        <section id='navbar' class='content'>
-            <h1>
-                <div id='swdb'>
-                    <img alt=' ' src='<?=URL::IMG["LOGO"]?>sw.png'/>
-                    SWDB
-                </div>
-                <div id='api'>
-                    API v2
-                </div>
-            </h1>
-            <hr/>
-<?php
-            foreach ($API["category"] as $category){
-?>
-                <h3>
-                    <a href='#category_<?=$category["name"]?>'>
-                        <?=$category["name"]?>
-                    </a>
-                </h3>
-                <ul>
-<?php
-                    foreach ($category["command"] as $command){
-?>
-                        <li>
-                            <a href='#command_<?=$command["name"]?>' title='<?=$command["description"]?>'>
-                                <?=$command["name"]?>
-                            </a>
-                        </li>
-<?php
-                    }
-?>
-                </ul>
-                <hr/>
-<?php
-            }
-?>
-            <div id='copyright'>
-                Version 2.1. Developed by <a href="https://inigovalentin.com">Iñigo Valentin</a>.
-                <br/>
-                <br/>
-                Source code available on <a href="https://github.com">Github</a> under the GPLv3.
-                <br/>
-                <br/>
-                Neither I nor this tool are affiliated with or endorsed by <a href="http://com2us.com/">Com2uS</a> in any way. The Summoners War logo and the monster images are property of their respective owners (Com2US, probably). Monsters images and info are parsed from <a href="https://swarfarm.com">https://swarfarm.com</a>.
-            </div>
-        </section>
-<?php
-        foreach ($API["category"] as $category){
-?>
-            <section id='category_<?=$category["name"]?>' class='category content'>
-                <h2>
-                    <?=$category["name"]?>
-                </h2>
-<?php
-                foreach ($category["command"] as $command){
-?>
-                    <article id='command_<?=$command["name"]?>'>
-                        <h3>
-                            <?=$command["name"]?>
-                            <span class='description'>
-                                - <?=$command["description"]?>
-                            </span>
-                        </h3>
-                        <div class='command'>
-                            <span class='type type_<?=$command["type"]?>'>
-                                <?=$command["type"]?>
-                            </span>
-                            <span class='url'>
-                                <?=htmlspecialchars($command["url"])?>
-                            </span>
-                        </div>
-                        <table class='params'>
-                            <thead>
-                                <tr>
-                                    <th class='header' colspan='3'>
-                                        Parameters
-                                    </th>
-                                </tr>
-                                <tr>
-                                    <th class='name'>
-                                        Parameter
-                                    </th>
-                                    <th class='type'>
-                                        Type
-                                    </th>
-                                    <th class='description'>
-                                        Description
-                                    </th>
-                                </tr>
-                            </thead>
-                            <tbody>
-<?php
-                                foreach ($command["parameter"] as $param){
-?>
-                                    <tr>
-                                        <td class='name'>
-                                            <?=$param["key"]?>
-                                        </td>
-                                        <td class='type'>
-                                            <?=$param["type"]?>
-                                        </td>
-                                        <td class='description'>
-                                            <?=($param["optional"] ? "<span class='optional'>[Optional] </span>" : "")?>
-                                            <?=$param["description"]?>
-                                        </td>
-                                    </tr>
-<?php
-                                }
-?>
-                            </tbody>
-                        </table>
-                        <table class='success'>
-                            <thead>
-                                <tr>
-                                    <th class='header' colspan='2'>
-                                        Sucessfull Responses
-                                    </th>
-                                </tr>
-                                <tr>
-                                    <th class='status'>
-                                        Status
-                                    </th>
-                                    <th class='description'>
-                                        Description
-                                    </th>
-                                </tr>
-                            </thead>
-                            <tbody>
-<?php
-                                foreach ($command["success"] as $status){
-?>
-                                    <tr>
-                                        <td class='status'>
-                                            HTTP/1.1 <?=$status["status"]?>
-                                        </td>
-                                        <td class='description'>
-                                            <?=$status["description"]?>
-<?php
-                                            if ($status["example"] != null){
-?>
-                                                <span class='fake_a' onclick="showExample('<?=$command["name"]?>', <?=$status["status"]?>, '<?=htmlspecialchars(json_decode($status["example"]), ENT_QUOTES)?>')">
-                                                    View example.
-                                                </span>
-<?php
-                                            }
-?>
-                                        </td>
-                                    </tr>
-<?php
-                                }
-?>
-                            </tbody>
-                        </table>
-                        <table class='error'>
-                            <thead>
-                                <tr>
-                                    <th class='header' colspan='2'>
-                                        Error Responses
-                                    </th>
-                                </tr>
-                                <tr>
-                                    <th class='status'>
-                                        Status
-                                    </th>
-                                    <th class='description'>
-                                        Description
-                                    </th>
-                                </tr>
-                            </thead>
-                            <tbody>
-<?php
-                                foreach ($command["error"] as $status){
-?>
-                                    <tr>
-                                        <td class='status'>
-                                            HTTP/1.1 <?=$status["status"]?>
-                                        </td>
-                                        <td class='description'>
-                                            <?=$status["description"]?>
-<?php
-                                            if ($status["example"] != null){
-?>
-                                                <span class='fake_a' onclick="showExample('<?=$command["name"]?>', '<?=htmlspecialchars(json_decode($status["example"]), ENT_QUOTES)?>')">
-                                                    View example.
-                                                </span>
-<?php
-                                            }
-?>
-                                        </td>
-                                    </tr>
-<?php
-                                }
-?>
-                            </tbody>
-                        </table>
-                    </article>
-<?php
-                }
-?>
-            </section>
-            <section id='example' class='content'>
-                <h2 id='example_title'>
-                </h2>
-                <article>
-                    <pre id='example_content'>
-                    </pre>
-                    <input type='button' value='Close' onClick='closeExample();'>
-                </article>
-            </section>
-<?php
-        }
-?>
-    </body>
-</html>

+ 0 - 54
application/API/v2/log-profile/index.php

@@ -1,54 +0,0 @@
-<?php
-    /**
-     * Profile uploader script.
-     *
-     * Exposes an API to save a run to the database.
-     * Reads post data and calls the log-profile.py script.
-     * It also saves the data to a JSON file in the da directory.
-     * Mandatory POST parameters are:
-     *  - data: Received JSON file after a run.
-     *  - key: User API key.
-     *
-     * @category API
-     */
-
-    $status = 200;
-    if (isset($_POST["data"]) && isset($_POST["key"])){
-        $data = $_POST["data"];
-        $key = $_POST["key"];
-        if (json_decode($data) === null){
-            error_log("ERROR: API v1 log-profile: Invalid JSON");
-            $status = 400;
-        }
-        else{
-            $json = json_decode($data);
-            $winfo = $json->{"wizard_info"};
-            $uname = $winfo->{"wizard_name"};
-            $uid = $winfo->{"wizard_id"};
-            $dtime = (new DateTime())->format('Y-m-dTH:i:s');
-            $fname = ($_SERVER["DOCUMENT_ROOT"] . "/../data/profile_" . $uid . "_" . $uname . "_" . $dtime . ".json");
-            file_put_contents($fname, $data);
-            $cmd = $_SERVER["DOCUMENT_ROOT"] . "/../application/bin/log-profile.py " . $key . " " . $fname;
-            $out = [];
-            $ret = 0;
-            exec($cmd, $out, $ret);
-            if ($ret != 0){
-                error_log("ERROR: API v1 log-profile exited with status: " . $ret);
-                error_log("====================");
-                error_log("|| SCRIPT OUTPUT: ||");
-                error_log("===============================================================================");
-                foreach($out as $line){
-                    error_log("|| " . $line);
-                }
-                error_log("===============================================================================");
-                $status = 400;
-            }
-        }
-    }
-    else{
-        error_log("ERROR: API v1 log-profile: Invalid JSON");
-        $status = 400;
-    }
-    http_response_code($status);
-    return $status;
-?>

+ 0 - 46
application/API/v2/log-run/index.php

@@ -1,46 +0,0 @@
-<?php
-    /**
-     * Run logger script.
-     *
-     * Exposes an API to save a run to the database.
-     * Reads post data and calls the log-run.py script.
-     * Mandatory POST parameters are:
-     *  - data: Received JSON file after a run.
-     *  - key: User API key.
-     *
-     * @category API
-     */
-
-    $status = 200;
-    if (isset($_POST["data"]) && isset($_POST["key"])){
-        $data = $_POST["data"];
-        $key = $_POST["key"];
-        if (json_decode($data) === null){
-            error_log("ERROR: API v1 log-run: Invalid JSON");
-            $status = 400;
-        }
-        else{
-            $cmd = $_SERVER["DOCUMENT_ROOT"] . "/../application/bin/log-run.py " . $key . " " . escapeshellarg($data);
-            $out = [];
-            $ret = 0;
-            exec($cmd, $out, $ret);
-            if ($ret != 0){
-                error_log("ERROR: API v1 log-run exited with status: " . $ret);
-                error_log("====================");
-                error_log("|| SCRIPT OUTPUT: ||");
-                error_log("===============================================================================");
-                foreach($out as $line){
-                    error_log("|| " . $line);
-                }
-                error_log("===============================================================================");
-                $status = 400;
-            }
-        }
-    }
-    else{
-        error_log("ERROR: API v1 log-run: Invalid JSON");
-        $status = 400;
-    }
-    http_response_code($status);
-    return $status;
-?>

+ 0 - 17
application/API/v2/main.php

@@ -1,17 +0,0 @@
-<?php
-    header("Content-Type:application/json");
-    $links = [
-        "Archetypes" => URL::BASE . "/API/v2/archetypes",
-        "Area types" => URL::BASE . "/API/v2/area_types",
-        "Areas types" => URL::BASE . "/API/v2/areas",
-        "Buildings" => URL::BASE . "/API/v2/buildings",
-        "Decorations" => URL::BASE . "/API/v2/decorations",
-        "Areas types" => URL::BASE . "/API/v2/areas",
-        "Units" => URL::BASE . "/API/v2/units",
-        "Skills" => URL::BASE . "/API/v2/skills",
-        "Skill effects" => URL::BASE . "/API/v2/skill_efects",
-    ];
-    header("HTTP/1.1 200");
-    $json_response = json_encode($links);
-    echo $json_response;
-?>

+ 0 - 106
application/API/v2/units.php

@@ -1,106 +0,0 @@
-<?php
-    /**
-     * Unit api.
-     *
-     * Exposes an API to get a list of units of a player, or a unit details.
-     * Used POST parameters are:
-     *  - key: User API key. If not, only public user's unit can be seen.
-     *
-     * @category API
-     * @var mixed[] $params URL parameters.
-     */
-
-    global $db;
-
-    try{
-
-        if (count($params) <= 1){
-            http_response_code(400);
-            return 400;
-        }
-        $uid = $params[1];
-        $id = null;
-
-        if (count($params) > 2){
-            $id = $params[2];
-        }
-
-        // Check API key or public profile.
-        if (isset($_POST['key'])){
-            $key = filter_input(INPUT_POST, 'key');
-        }
-        else{
-            $key = "";
-        }
-        $s = "SELECT COUNT(uid) AS c FROM player WHERE uid = $uid AND (public = 1 OR api_key = '$key');";
-        if (1 != $db->query($s)->fetchArray(SQLITE3_ASSOC)["c"]){
-            http_response_code(401);
-            return 401;
-        }
-
-        // No unit ID specified, show a list.
-        if ($id == null){
-            $units = [];
-            $s = "SELECT id, '" . URL::BASE . "API/v2/units/$uid/' || id AS uri FROM unit WHERE uid = '$uid'";
-            $q = $db->query($s);
-            $content = false;
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($units, $r);
-                $content = true;
-            }
-            if ($content == true){
-                header('Content-Type: application/json');
-                echo json_encode($units);
-                http_response_code(200);
-                return 200;
-            }
-            else{
-                http_response_code(204);
-                return 204;
-            }
-        }
-
-        // Specific unit, show details.
-        else{
-            $s = "SELECT * FROM unit WHERE uid = '$uid' AND id = '$id'";
-            $q = $db->query($s);
-            if($r = $q->fetchArray(SQLITE3_ASSOC)){
-                $unit = $r;
-
-                // Runes
-                $unit["runes"] = [];
-                $s = "SELECT * FROM rune WHERE assigned_to = '" . $unit["id"] . "' ORDER BY slot;";
-                $q = $db->query($s);
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    $rune = $r;
-                    unset($rune["uid"]); # Not needed
-                    unset($rune["assigned_to"]); # Not needed
-                    array_push($unit["runes"], $rune);
-                }
-
-                // Skills
-                $unit["skills"] = [];
-                $s = "SELECT skill, level FROM unit_skill WHERE unit = '" . $unit["id"] . "';";
-                $q = $db->query($s);
-                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                    array_push($unit["skills"], $r);
-                }
-
-                header('Content-Type: application/json');
-                echo json_encode($unit);
-                http_response_code(200);
-                return 200;
-            }
-            else{
-                http_response_code(404);
-                return 404;
-            }
-        }
-
-    }
-    catch(Exception $e) {
-        error_log("Unknown error fetching units: " . $e->getMessage());
-        http_response_code(500);
-        return 500;
-    }
-?>

+ 0 - 87
application/API/v2/update_collection.php

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

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

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

+ 0 - 94
application/API/v2/upload_profile.php

@@ -1,94 +0,0 @@
-<?php
-    /**
-     * Profile uploader script.
-     *
-     * Exposes an API to save a run to the database.
-     * Reads post data and calls the upload_profile.py script.
-     * It also saves the data to a JSON file in the data directory.
-     * Mandatory POST parameters are:
-     *  - data: Received JSON file.
-     *  - key: User API key.
-     *
-     * @category API
-     */
-
-    global $db;
-
-    try{
-        // Check data
-        $data = filter_input(INPUT_POST, 'response');
-        if ($data == null || $data == false){
-            http_response_code(400);
-            return 400;
-        }
-
-        // Check API key.
-        $key = filter_input(INPUT_POST, 'key');
-        if ($key == null || $key == false){
-            http_response_code(401);
-            return 401;
-        }
-
-        // Check data format.
-        $json = json_decode($data);
-        if ($json === null){
-            http_response_code(400);
-            return 400;
-        }
-
-        // Authenticate
-        $uid = $json->{"wizard_id"};
-        $uname = $json->{"wizard_info"}->{"wizard_name"};
-        $s = "SELECT COUNT(uid) AS c FROM player WHERE uid = $uid AND api_key = '$key';";
-        if (1 != $db->query($s)->fetchArray(SQLITE3_ASSOC)["c"]){
-            http_response_code(401);
-            return 401;
-        }
-
-        // Write data file
-        $dtime = (new DateTime())->format('Y-m-dTH:i:s');
-        $fname = ($_SERVER["DOCUMENT_ROOT"] . "/../data/profile_" . $uid . "_" . $uname . "_" . $dtime . ".json");
-        try{
-            file_put_contents($fname, $data);
-        }
-        catch(Exception $e) {
-            error_log("Unable to write profile data to '$fname': " . $e->getMessage());
-            http_response_code(500);
-            return 500;
-        }
-
-        // Run profile parser script
-        $cmd = __DIR__ . "/bin/upload_profile.py " . $key . " " . $fname;
-        $out = [];
-        $ret = 0;
-        try{
-            exec($cmd, $out, $ret);
-        }
-        catch(Exception $e) {
-            error_log("Error running profile script '$cmd': " . $e->getMessage());
-            http_response_code(500);
-            return 500;
-        }
-
-        if ($ret != 204){
-            try{
-                http_response_code($ret);
-                return $ret;
-            }
-            catch(Exception $e) {
-                error_log("Profile script '$cmd' returned an unexpected value $ret: " . $e->getMessage());
-                http_response_code(500);
-                return 500;
-            }
-        }
-
-        // At this point, status code should be 200
-        http_response_code($ret);
-        return $ret;
-    }
-    catch(Exception $e) {
-        error_log("Unknown error parsing profile: " . $e->getMessage());
-        http_response_code(500);
-        return 500;
-    }
-?>

+ 0 - 82
application/API/v2/upload_run_dimension.php

@@ -1,82 +0,0 @@
-<?php
-    /**
-     * Dimension Hole Dungeon run logger script.
-     *
-     * Exposes an API to save a run to the database.
-     * Reads post data and calls the upload_run_dimension.py script.
-     * Mandatory POST parameters are:
-     *  - request: Intercepted game request.
-     *  - response: Intercepted game response.
-     *  - key: User API key.
-     *
-     * @category API
-     */
-
-    global $db;
-
-    try{
-        // Check data
-        $data_request = filter_input(INPUT_POST, 'request');
-        $data_response= filter_input(INPUT_POST, 'response');
-        if ($data_request == null || $data_request == false || $data_response == null || $data_response == false){
-            http_response_code(400);
-            return 400;
-        }
-
-        // Check API key.
-        $key = filter_input(INPUT_POST, 'key');
-        if ($key == null || $key == false){
-            http_response_code(401);
-            return 401;
-        }
-
-        // Check data format.
-        $json_request = json_decode($data_request);
-        $json_response = json_decode($data_response);
-        if ($json_response === null | $json_request === null){
-            http_response_code(400);
-            return 400;
-        }
-
-        // Authenticate
-        $uid = $json_request->{"wizard_id"};
-        $s = "SELECT COUNT(uid) AS c FROM player WHERE uid = $uid AND api_key = '$key';";
-        if (1 != $db->query($s)->fetchArray(SQLITE3_ASSOC)["c"]){
-            http_response_code(401);
-            return 401;
-        }
-
-        // Run TOA run parser script
-        $cmd = __DIR__ . "/bin/upload_run_dimension.py " . $key . " " . escapeshellarg($data_request) . " " . escapeshellarg($data_response);
-        $out = [];
-        $ret = 0;
-        try{
-            exec($cmd, $out, $ret);
-        }
-        catch(Exception $e) {
-            error_log("Error running Dimension Hole Dungeon run script: " . $e->getMessage());
-            http_response_code(500);
-            return 500;
-        }
-
-        if ($ret != 201){
-            try{
-                http_response_code($ret);
-                return $ret;
-            }
-            catch(Exception $e) {
-                error_log("Dimension Hole Dungeon run script returned an unexpected value $ret: " . $e->getMessage());
-                http_response_code(500);
-                return 500;
-            }
-        }
-        // At this point, status code should be 200
-        http_response_code($ret);
-        return $ret;
-    }
-    catch(Exception $e) {
-        error_log("Unknown error parsing Dimension Hole Dungeon run: " . $e->getMessage());
-        http_response_code(500);
-        return 500;
-    }
-?>

+ 0 - 82
application/API/v2/upload_run_dungeon.php

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

+ 0 - 99
application/API/v2/upload_run_rift.php

@@ -1,99 +0,0 @@
-<?php
-    /**
-     * Dungeon run logger script.
-     *
-     * Exposes an API to save a run to the database.
-     * Reads post data and calls the upload_dungeon_run.py script.
-     * Mandatory POST parameters are:
-     *  - request: Intercepted game request.
-     *  - response: Intercepted game response.
-     *  - key: User API key.
-     *
-     * @category API
-     */
-
-    global $db;
-
-    try{
-        // Check data
-        $data_request = filter_input(INPUT_POST, 'request');
-        $data_response = filter_input(INPUT_POST, 'response');
-        $data_start_request = filter_input(INPUT_POST, 'start_request');
-        $data_start_response = filter_input(INPUT_POST, 'start_response');
-        if (
-          $data_request == null ||
-          $data_request == false ||
-          $data_response == null ||
-          $data_response == false ||
-          $data_start_request == null ||
-          $data_start_request == false ||
-          $data_start_response == null ||
-          $data_start_response == false
-        ){
-            http_response_code(400);
-            return 400;
-        }
-
-        // Check API key.
-        $key = filter_input(INPUT_POST, 'key');
-        if ($key == null || $key == false){
-            http_response_code(401);
-            return 401;
-        }
-
-        // Check data format.
-        $json_request = json_decode($data_request);
-        $json_response = json_decode($data_response);
-        if ($json_response === null | $json_request === null){
-            http_response_code(400);
-            return 400;
-        }
-
-        // Authenticate
-        $uid = $json_request->{"wizard_id"};
-        $s = "SELECT COUNT(uid) AS c FROM player WHERE uid = $uid AND api_key = '$key';";
-        if (1 != $db->query($s)->fetchArray(SQLITE3_ASSOC)["c"]){
-            http_response_code(401);
-            return 401;
-        }
-
-        // Run dungeon run parser script
-        $cmd = __DIR__ . "/bin/upload_run_rift.py " .
-          $key . " " .
-          escapeshellarg($data_request) . " " .
-          escapeshellarg($data_response) . " " .
-          escapeshellarg($data_start_request) . " " .
-          escapeshellarg($data_start_response);
-        $out = [];
-        $ret = 0;
-        try{
-            exec($cmd, $out, $ret);
-        }
-        catch(Exception $e) {
-            error_log("Error running Rift Dungeon run script: " . $e->getMessage());
-            http_response_code(500);
-            return 500;
-        }
-
-        if ($ret != 201){
-            try{
-                error_log("Rift Dungeon run script returned an unexpected value $ret: ");
-                http_response_code($ret);
-                return $ret;
-            }
-            catch(Exception $e) {
-                error_log("Rift Dungeon run script returned an unexpected value $ret: " . $e->getMessage());
-                http_response_code(500);
-                return 500;
-            }
-        }
-        // At this point, status code should be 201
-        http_response_code($ret);
-        return $ret;
-    }
-    catch(Exception $e) {
-        error_log("Unknown error parsing Rift Dungeon run: " . $e->getMessage());
-        http_response_code(500);
-        return 500;
-    }
-?>

+ 0 - 80
application/API/v2/upload_run_scenario.php

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

+ 0 - 82
application/API/v2/upload_run_toa.php

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

+ 0 - 98
application/API/v3/API_Controller.php

@@ -1,98 +0,0 @@
-<?php
-
-    /**
-     * v3 API Controller file.
-     *
-     * Provides a class to handle all posible API requests.
-     *
-     * @category Constroller
-     */
-
-    /**
-     * v3 API controller.
-     *
-     * Handles every API request.
-     *
-     * @category Controller
-     */
-    class API_Controller {
-
-        /**
-         * Constructor.
-         *
-         * Handles every request, creating the required models and selecting the
-         * view.
-         *
-         * @param mixed[] $query GET parameters of the request.
-         */
-        public function __construct($query){
-
-            // Remove host
-            array_shift($query);
-            // Remove /API/
-            array_shift($query);
-            // Remove /v3/
-            array_shift($query);
-            // API call: Use API controller
-            $method = $_SERVER["REQUEST_METHOD"];
-            if (!in_array($method, ["GET", "POST", "PUT", "DELETE"])){
-                $method = "GET";
-            }
-            if (count($query) == 0 || $query[0] == null || $query[0] == ""){
-                require_once(__DIR__ . "/main.php");
-            }
-            else{
-                $command = strtolower($query[0]);
-                // Remove /<command>/
-                array_shift($query);
-                switch ($command){
-                    case "help":
-                        require_once(__DIR__ . "/help/index.php");
-                        break;
-                    case "profile":
-                    case "run":
-                    case "logbook":
-                    case "collection":
-                    case "run":
-                    case "units":
-                        if (file_exists(__DIR__ . "/$command/$method.php")){
-                            require_once(__DIR__ . "/$command/$method.php");
-                        }
-                        else{
-                            header("HTTP/1.1 404");
-                        }
-                        break;
-                    /*case "update_profile":
-                        require_once(__DIR__ . "/update_profile.php");
-                        break;
-                    case "update_logbook":
-                        require_once(__DIR__ . "/update_logbook.php");
-                        break;
-                    case "update_collection":
-                        require_once(__DIR__ . "/update_collection.php");
-                        break;
-                    case "log_run_dungeon":
-                        require_once(__DIR__ . "/log_run_dungeon.php");
-                        break;
-                    case "log_run_dh":
-                        require_once(__DIR__ . "/log_run_dh.php");
-                        break;
-                    case "log_run_scenario":
-                        require_once(__DIR__ . "/log_run_scenario.php");
-                        break;
-                    case "log_run_toa":
-                        require_once(__DIR__ . "/log_run_toa.php");
-                        break;
-                    case "log_run_rift_dungeon":
-                        require_once(__DIR__ . "/log_run_rift_dungeon.php");
-                        break;
-                    case "units":
-                        require_once(__DIR__ . "/units.php");
-                        break;*/
-                    default:
-                        header("HTTP/1.1 404");
-                }
-            }
-        }
-    }
-?>

+ 0 - 17
application/API/v3/main.php

@@ -1,17 +0,0 @@
-<?php
-    header("Content-Type:application/json");
-    $links = [
-        "Archetypes" => URL::BASE . "/API/v2/archetypes",
-        "Area types" => URL::BASE . "/API/v2/area_types",
-        "Areas types" => URL::BASE . "/API/v2/areas",
-        "Buildings" => URL::BASE . "/API/v2/buildings",
-        "Decorations" => URL::BASE . "/API/v2/decorations",
-        "Areas types" => URL::BASE . "/API/v2/areas",
-        "Units" => URL::BASE . "/API/v2/units",
-        "Skills" => URL::BASE . "/API/v2/skills",
-        "Skill effects" => URL::BASE . "/API/v2/skill_efects",
-    ];
-    header("HTTP/1.1 200");
-    $json_response = json_encode($links);
-    echo $json_response;
-?>

+ 0 - 202
application/entity/Fusion.php

@@ -1,202 +0,0 @@
-<?php
-    /**
-     * Fusion 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 . "K_Unit.php");
-    require_once(PATH::ENTITY . "Unit.php");
-
-    /**
-     * Extension of K_Unit that also stores information about owned
-     * monsters.
-     *
-     * @category Entity
-     */
-    class Monster_Fusion extends K_Unit{
-
-        /**
-         * @var \Unit[] All owned units of this type.
-         */
-        public $owned = [];
-
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * fusion, populating it and it's items.
-         *
-         * @param int $id Unit id.
-         * @param int $player_id Player id.
-         * @global resource Database connection.
-         */
-        public function __construct($id, $player_id){
-            global $db;
-            parent::__construct($id, true);
-            $statement = $db->prepare("
-              SELECT unit.id AS id
-              FROM
-                data.unit unit,
-                key.unit k_unit
-              WHERE
-                k_unit.id = unit.unit AND
-                unit.player = :player AND
-                (
-                  k_unit.id = :id OR
-                  k_unit.awakens_from = :id OR
-                  k_unit.awakens_to = :id
-                );
-            ");
-            $statement->bindValue(':player', $player_id, SQLITE3_TEXT);
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $q = $statement->execute();
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->owned, new Unit($r["id"], false));
-            }
-        }
-    }
-
-
-    /**
-     * Fusion.
-     *
-     * Represents an object from the table 'fusion'.
-     *
-     * @category Entity
-     */
-    class Fusion extends Entity{
-
-        /**
-         * @var K_Unit K_Unit to fuse.
-         */
-        public $product;
-
-        /**
-         * @var K_Unit K_Unit to fuse (awakened).
-         */
-        public $product_awaken;
-
-        /**
-         * @var K_Unit K_Unit to fuse (unawakened).
-         */
-        public $product_unawaken;
-
-        /**
-         * @var Monster_Fusion Fusions required to create ingredients.
-         */
-        public $fusion = [];
-
-        /**
-         * @var \K_Unit[] List of unfuseable K_Unit material.
-         */
-        public $ingredient = [];
-
-        /**
-         * @var \K_Unit[] List of unfuseable K_Unit material. (unawakened).
-         */
-        public $ingredient_unawaken = [];
-
-        /**
-         * @var int Stars of the monster to fuse.
-         */
-        public $stars;
-
-        /**
-         * @var int Fusion cost.
-         */
-        public $cost;
-
-        /**
-         * Constructor.
-         *
-         * Searches the database and retrieves the information about the
-         * fusion, populating it and it's items.
-         *
-         * @param int $id Product monster id.
-         * @param int $player_id Player ID (optional).
-         * @global resource Database connection.
-         */
-        public function __construct($id, $player_id = null){
-
-            global $db;
-
-            $statement = $db->prepare("
-              SELECT DISTINCT
-                product,
-                stars,
-                cost
-              FROM key.fusion
-              WHERE
-                product = $id OR
-                product = (SELECT awakens_to FROM key.unit WHERE id = $id) OR
-                product = (SELECT awakens_from FROM key.unit WHERE id = $id);
-            ");
-            $statement->bindValue(':id', $id, SQLITE3_TEXT);
-            $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
-            $this->product = new Monster_Fusion($r["product"], $player_id);
-            $this->product_awaken = new Monster_Fusion($this->product->awakens_to, $player_id);
-            $this->stars = $r["stars"];
-            $this->cost = $r["cost"];
-            $statement = $db->prepare("
-              SELECT DISTINCT ingredient
-              FROM key.fusion
-              WHERE
-                product = :product AND
-                ingredient IN (
-                  SELECT DISTINCT k_unit.id
-                  FROM
-                    key.fusion k_fusion,
-                    key.unit k_unit
-                  WHERE
-                    k_fusion.product = k_unit.awakens_from OR
-                    k_fusion.product = k_unit.awakens_to OR
-                    k_fusion.product = k_unit.id
-                );
-            ");
-            $statement->bindValue(':product', $this->product->id, SQLITE3_TEXT);
-            $q_f = $statement->execute();
-            while ($r_f = $q_f->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->fusion, new Fusion($r_f["ingredient"], $player_id));
-            }
-            $statement = $db->prepare("
-              SELECT
-                id,
-                awakens_from
-              FROM key.unit
-              WHERE id IN (
-                SELECT DISTINCT
-                  ingredient
-                FROM key.fusion
-                WHERE
-                  product = :product AND
-                  ingredient NOT IN (
-                    SELECT DISTINCT k_unit.id
-                    FROM
-                      key.fusion k_fusion,
-                      key.unit k_unit
-                    WHERE
-                      k_fusion.product = k_unit.awakens_from OR
-                      k_fusion.product = k_unit.awakens_to OR
-                      k_fusion.product = k_unit.id
-                  )
-                );
-            ");
-            $statement->bindValue(':product', $this->product->id, SQLITE3_TEXT);
-            $q_m = $statement->execute();
-            while ($r_m = $q_m->fetchArray(SQLITE3_ASSOC)){
-                $m = new Monster_Fusion($r_m["id"], $player_id);
-                array_push($this->ingredient, $m);
-                $m = new Monster_Fusion($r_m["awakens_from"], $player_id);
-                $m->load_essences();
-                array_push($this->ingredient_unawaken, $m);
-            }
-        }
-    }
-?>

+ 0 - 96
application/page/Fusion_Page.php

@@ -1,96 +0,0 @@
-<?php
-    /**
-     * Fusion page file.
-     *
-     * Provides a class with all the properties and methods to display the page.
-     *
-     * @category Page
-     */
-
-    /**
-     * Require dependent files if not present.
-     */
-    require_once(PATH::PAGE . "Page.php");
-    require_once(PATH::ENTITY . "Fusion.php");
-    require_once(PATH::ENTITY . "K_Unit.php");
-
-
-    /**
-     * Fusion page model.
-     */
-    class Fusion_Page extends Page{
-
-        /**
-         * @var \Fusion[] List of top-level fusions to display.
-         */
-        public $fusion = [];
-
-        /**
-         * @var \K_Unit[] List of top-level fuseable units (for filter).
-         */
-        public $products = [];
-
-
-        /**
-         * Constructor.
-         *
-         * Retrieves the data and initializes the variables.
-         *
-         * @global resource Connection to the database.
-         * @global Player Currently selected player.
-         */
-        public function __construct(){
-            global $db;
-            global $PLAYER;
-            $this->view = PATH::VIEW . "fusion.php";
-            $this->parse_filters();
-            $s =
-              "SELECT DISTINCT product " .
-              "FROM key.fusion " .
-              "WHERE stars = 5 " .
-              "ORDER BY stars DESC; ";
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->products, new K_Unit($r["product"], false));
-            }
-            $s = $this->build_query();
-            $q = $db->query($s);
-            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
-                array_push($this->fusion, new Fusion($r["product"], $PLAYER->id));
-            }
-            $this->title = "Fusion - SWDB";
-            $this->description = "Fusion chart";
-            $this->canonical = URL::BASE . "fusion/";
-        }
-
-        /**
-         * Parses the request looking for the selected filters, validates them
-         * and adds them to the $filters array.
-         */
-        private function parse_filters(){
-            $this->filters = FILTER::FUSION;
-            if (isset($_GET["product"]) && intval($_GET["product"]) > 0){
-                $this->filters["PRODUCT"] = $_GET["product"];
-            }
-            return;
-        }
-
-        /**
-         * Builds the query to the rune table using the selected or default
-         * filters.
-         *
-         * @return string The query to be executed.
-         */
-        private function build_query(){
-            $s =
-              "SELECT DISTINCT product " .
-              "FROM key.fusion " .
-              "WHERE stars = 5 ";
-            if ($this->filters["PRODUCT"] > 0){
-                $s = $s . " AND product = " . $this->filters["PRODUCT"] . " ";
-            }
-            $s = $s . "ORDER BY stars DESC;";
-            return $s;
-        }
-    }
-?>

+ 0 - 444
application/view/fusion.php

@@ -1,444 +0,0 @@
-<?php
-    /**
-     * Fusion view.
-     *
-     * Contains the view layout and some code to present the data.
-     *
-     * @category View
-     * @var Fusion_Page $page The page model.
-     */
-?>
-<!DOCTYPE html>
-<html lang='en'>
-    <head>
-        <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
-        <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
-        <title><?=$page->title?></title>
-        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
-        <!-- CSS files -->
-        <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
-<?php
-        if ($MODE == GAME_MODE_ID::RTA){
-?>
-            <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
-<?php
-        }
-?>
-        <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>fusion.css'/>
-        <!-- Meta tags -->
-        <link rel='canonical' href='<?=$page->canonical?>'/>
-        <link rel='author' href='<?=$page->author?>'/>
-        <link rel='publisher' href='<?=$page->author?>'/>
-        <meta name='description' content='<?=$page->description?>'/>
-        <meta property='og:title' content='<?=$page->title?>'/>
-        <meta property='og:url' content='<?=$page->canonical?>'/>
-        <meta property='og:description' content='<?=$page->description?>'/>
-        <meta property='og:image' content='<?=$page->icon?>'/>
-        <meta property='og:site_name' content='<?=$page->name?>'/>
-        <meta property='og:type' content='website'/>
-        <meta property='og:locale' content='en'/>
-        <meta name='twitter:card' content='summary'/>
-        <meta name='twitter:title' content='<?=$page->title?>'/>
-        <meta name='twitter:description' content='<?=$page->description?>'/>
-        <meta name='twitter:image' content='<?=$page->icon?>'/>
-        <meta name='twitter:url' content='<?=$page->canonical?>'/>
-        <meta name='robots' content='index follow'/>
-    </head>
-    <body>
-<?php
-        include __DIR__ . "/inc/header.php";
-?>
-        <aside>
-            <h2>
-                Fusion filters
-            </h2>
-            <p>
-                Monster fusion tree
-            </p>
-            <form action='/<?=$PLAYER->id?>/fusion/' method='get' id='filter_fusion' class='filter'>
-                <table>
-                    <tr>
-                        <td class='label'>
-                            Target:
-                        </td>
-                        <td>
-                            <select name='product' id='filter_product'>
-                                <option value=''>All</option>
-<?php
-                                foreach ($page->products as $product){
-                                    if ($product->id == $page->filters["PRODUCT"]){
-                                        $selected = "selected";
-                                    }
-                                    else{
-                                        $selected = "";
-                                    }
-?>
-                                        <option value='<?=$product->id?>' <?=$selected?>><?=$product->element_name?> <?=$product->name?></option>
-<?php
-                                }
-?>
-                            </select>
-                        </td>
-                    </tr>
-                </table>
-                <input type='submit' value='Apply'/>
-            </form>
-        </aside> <!-- #filters -->
-        <main>
-            <section id='fusions' class='list'>
-                <h2>
-                    Fusions
-                </h2>
-                <article>
-<?php
-                    foreach ($page->fusion as $fusion){
-?>
-                            <table>
-                            <tr>
-                                <td class='f5' colspan='16'>
-                                    <a target='_blank' title='<?=$fusion->product->name?>' href='/<?=$PLAYER->id?>/catalog/<?=$fusion->product->id?>'>
-                                        <div class='monster_panel'>
-                                            <span class='stars'>
-                                                <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                            </span>
-                                            <img title='<?=$fusion->product->name?>' class='monster border_<?=$fusion->product->element_name?>' src='<?=$fusion->product->get_image()?>'/>
-                                            <span class='level'>
-                                                1
-                                            </span>
-                                        </div><!-- .monster_panel -->
-                                    </a>
-                                </td>
-                            </tr>
-                            <tr>
-<?php
-                                foreach ($fusion->fusion as $sub_fusion){
-?>
-                                    <td class='f4' colspan='4'>
-                                        <a target='_blank' title='<?=$sub_fusion->product_awaken->name?>' href='/<?=$PLAYER->id?>/catalog/<?=$sub_fusion->product_awaken->id?>'>
-                                            <div class='awakened monster_panel'>
-                                                <span class='stars'>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                </span>
-                                                <img title='<?=$sub_fusion->product_awaken->name?>' class='monster border_<?=$sub_fusion->product_awaken->element_name?>' src='<?=$sub_fusion->product_awaken->get_image()?>'/>
-                                                <span class='level'>
-                                                    35
-                                                </span>
-                                            </div><!-- .awakened .monster_panel -->
-                                        </a>
-                                        <!-- TODO FIX -->
-                                        <div class='essences'>
-<?php
-                                            foreach ($sub_fusion->product->essences as $essence){
-?>
-                                                <div class='essence border_<?=explode(" ", $essence["item"]->name)[2]?>'>
-                                                    <img alt='<?=$essence["item"]->name?>' title='<?=$essence["amount"]?>x <?=$essence["item"]->name?>' class='essence' src='<?=$essence["item"]->get_image()?>'/>
-                                                    <span>
-                                                        <?=$essence["amount"]?>
-                                                    </span>
-                                                </div>
-<?php
-                                            }
-?>
-                                        </div><!-- .essences -->
-                                        <a target='_blank' title='<?=$sub_fusion->product->name?>' href='/<?=$PLAYER->id?>/catalog/<?=$sub_fusion->product->id?>'>
-                                            <div class='unawakened monster_panel'>
-                                                <span class='stars'>
-<?php
-                                                    for ($i = 0; $i < $sub_fusion->product->base_stars; $i ++){
-?>
-                                                        <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-<?php
-                                                    }
-?>
-                                                </span>
-                                                <img title='<?=$sub_fusion->product->name?>' class='monster border_<?=$sub_fusion->product->element_name?>' src='<?=$sub_fusion->product->get_image()?>'/>
-                                                <span class='level'>
-                                                    1
-                                                </span>
-                                            </div><!-- .unawakened .monster_panel -->
-                                        </a>
-                                        <div class='owned'>
-                                            <span class='owned'>
-                                                Collection:
-                                            </span>
-<?php
-                                            foreach ($sub_fusion->product->owned as $owned){
-                                                if ($owned->unit->awakens_from == "" && $owned->unit->awakens_to == ""){
-                                                    // No to, no from, silver monster.
-                                                    $star_class ="star_silver";
-                                                    $mon_title = $owned->unit->element_name . " " . $owned->unit->name;
-                                                }
-                                                elseif ($owned->unit->awakens_from != "" && $owned->unit->awakens_to == ""){
-                                                    // Already awakened
-                                                    if ($owned->unit->base_stars - $owned->unit->natural_stars == 1){
-                                                        // Normal awaken.
-                                                        $star_class ="star_purple";
-                                                    }
-                                                    else{
-                                                        // Second awaken.
-                                                        $star_class ="star_red";
-                                                    }
-                                                    $mon_title = $owned->unit->name;
-                                                }
-                                                elseif ($owned->unit->awakens_to != ""){
-                                                    // Awakeable.
-                                                    $star_class ="star_gold";
-                                                    $mon_title = $owned->unit->element_name . " " . $owned->unit->name;
-                                                }
-                                                $mon_title = $mon_title . " - " . $owned->stars . "* - Lv." . $owned->level;
-?>
-                                                <a target="_blank" title='<?=$mon_title?>' href='/<?=$PLAYER->id?>/monsters/<?=$owned->id?>'>
-                                                    <div class='monster_panel'>
-                                                        <span class='stars'>
-<?php
-                                                            for ($i = 0; $i < $owned->stars; $i ++){
-?>
-                                                                <img class='star <?=$star_class?>' src='<?=URL::IMG["ICON"]?>star.png'/>
-<?php
-                                                            }
-?>
-                                                        </span>
-                                                        <img title='<?=$mon_title?>' class='monster border_<?=$owned->unit->element_name?>' src='<?=$owned->unit->get_image()?>'/>
-                                                        <span class='level'>
-                                                            <?=$owned->level?>
-                                                        </span>
-                                                    </div>
-                                                </a>
-<?php
-                                            }
-?>
-                                        </div><!-- .owned -->
-                                    </td>
-<?php
-                                }
-?>
-                                    <td class='f4 extra' colspan='4'>
-                                        <a target='_blank' title='<?=$fusion->ingredient[0]->name?>' href='/<?=$PLAYER->id?>/catalog/<?=$fusion->ingredient[0]->id?>'>
-                                            <div class='awakened monster_panel'>
-                                                <span class='stars'>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                </span>
-                                                <img title='<?=$fusion->ingredient[0]->name?>' class='monster border_<?=$fusion->ingredient[0]->element_name?>' src='<?=$fusion->ingredient[0]->get_image()?>'/>
-                                                <span class='level'>
-                                                    35
-                                                </span>
-                                            </div><!-- .awakened .monster_panel -->
-                                        </a>
-                                        <div class='essences'>
-<?php
-                                            foreach ($fusion->ingredient_unawaken[0]->essences as $essence){
-?>
-                                                <div class='essence border_<?=explode(" ", $essence["item"]->name)[2]?>'>
-                                                    <img alt='<?=$essence["item"]->name?>' title='<?=$essence["amount"]?>x <?=$essence["item"]->name?>' class='essence' src='<?=$essence["item"]->get_image()?>'/>
-                                                    <span>
-                                                        <?=$essence["amount"]?>
-                                                    </span>
-                                                </div>
-<?php
-                                            }
-?>
-                                        </div><!-- .essences -->
-                                        <a target='_blank' title='<?=$fusion->ingredient_unawaken[0]->name?>' href='/<?=$PLAYER->id?>/catalog/<?=$fusion->ingredient_unawaken[0]->id?>'>
-                                            <div class='unawakened monster_panel'>
-                                                <span class='stars'>
-<?php
-                                                    for ($i = 0; $i < $fusion->ingredient[0]->base_stars; $i ++){
-?>
-                                                        <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-<?php
-                                                    }
-?>
-                                                </span>
-                                                <img title='<?=$fusion->ingredient_unawaken[0]->name?>' class='monster border_<?=$fusion->ingredient_unawaken[0]->element_name?>' src='<?=$fusion->ingredient_unawaken[0]->get_image()?>'/>
-                                                <span class='level'>
-                                                    1
-                                                </span>
-                                            </div><!-- .unawakened .monster_panel -->
-                                        </a>
-                                        <div class='owned'>
-                                            <span class='owned'>
-                                                Collection:
-                                            </span>
-<?php
-                                            foreach ($fusion->ingredient[0]->owned as $owned){
-?>
-                                                <div class='monster_panel'>
-                                                    <span class='stars'>
-<?php
-                                                        if ($owned->unit->awakens_from == "" && $owned->unit->awakens_to == ""){
-                                                            // No to, no from, silver monster.
-                                                            $star_class ="star_silver";
-                                                            $mon_title = $owned->unit->element_name . " " . $owned->unit->name;
-                                                        }
-                                                        elseif ($owned->unit->awakens_from != "" && $owned->unit->awakens_to == ""){
-                                                            // Already awakened
-                                                            if ($owned->unit->base_stars - $owned->unit->natural_stars == 1){
-                                                                // Normal awaken.
-                                                                $star_class ="star_purple";
-                                                            }
-                                                            else{
-                                                                // Second awaken.
-                                                                $star_class ="star_red";
-                                                            }
-                                                            $mon_title = $owned->unit->name;
-                                                        }
-                                                        elseif ($owned->unit->awakens_to != ""){
-                                                            // Awakeable.
-                                                            $star_class ="star_gold";
-                                                            $mon_title = $owned->unit->element_name . " " . $owned->unit->name;
-                                                        }
-                                                        for ($i = 0; $i < $owned->stars; $i ++){
-?>
-                                                        <img class='star <?=$star_class?>' src='<?=URL::IMG["ICON"]?>star.png'/>
-<?php
-                                                        }
-?>
-                                                    </span>
-                                                    <img title='<?=$mon_title?>' class='monster border_<?=$owned->unit->element_name?>' src='<?=$owned->unit->get_image()?>'/>
-                                                    <span class='level'>
-                                                        <?=$owned->level?>
-                                                    </span>
-                                                </div>
-<?php
-                                            }
-?>
-                                        </div><!-- .owned -->
-                                    </td>
-                                </tr>
-                                <tr>
-<?php
-                                foreach ($fusion->fusion as $sub_fusion){
-                                    $num = 0;
-                                    foreach ($sub_fusion->ingredient as $sub_monster){
-?>
-                                        <td class='f3'>
-                                            <a target='_blank' title='<?=$sub_monster->name?>' href='/<?=$PLAYER->id?>/catalog/<?=$sub_monster->id?>'>
-                                                <div class='awakened monster_panel'>
-                                                    <span class='stars'>
-                                                        <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                        <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                        <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                        <img class='star star_purple' src='<?=URL::IMG["ICON"]?>star.png'/>
-                                                    </span>
-                                                    <img title='<?=$sub_monster->name?>' class='monster border_<?=$sub_monster->element_name?>' src='<?=$sub_monster->get_image()?>'/>
-                                                    <span class='level'>
-                                                        30
-                                                    </span>
-                                                </div><!-- .awakened .monster_panel -->
-                                            </a>
-                                            <div class='essences'>
-<?php
-                                                foreach ($sub_fusion->ingredient_unawaken[$num]->essences as $essence){
-?>
-                                                    <div class='essence border_<?=explode(" ", $essence["item"]->name)[2]?>'>
-                                                        <img alt='<?=$essence["item"]->name?>' title='<?=$essence["amount"]?>x <?=$essence["item"]->name?>' class='essence' src='<?=$essence["item"]->get_image()?>'/>
-                                                        <span>
-                                                            <?=$essence["amount"]?>
-                                                        </span>
-                                                    </div>
-<?php
-                                                }
-?>
-                                            </div><!-- .essences -->
-                                            <a target='_blank' title='<?=$sub_fusion->ingredient_unawaken[$num]->name?>' href='/<?=$PLAYER->id?>/catalog/<?=$sub_fusion->ingredient_unawaken[$num]->id?>'>
-                                                <div class='unawakened monster_panel'>
-                                                    <span class='stars'>
-<?php
-                                                        for ($i = 0; $i < $sub_fusion->ingredient_unawaken[$num]->base_stars; $i ++){
-?>
-                                                            <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
-<?php
-                                                        }
-?>
-                                                    </span>
-                                                    <img title='<?=$sub_fusion->ingredient_unawaken[$num]->name?>' class='monster border_<?=$sub_fusion->ingredient_unawaken[$num]->element_name?>' src='<?=$sub_fusion->ingredient_unawaken[$num]->get_image()?>'/>
-                                                    <span class='level'>
-                                                        1
-                                                    </span>
-                                                </div><!-- .unawakened .monster_panel -->
-                                            </a>
-                                            <div class='owned'>
-                                                <span class='owned'>
-                                                    Collection:
-                                                </span>
-<?php
-                                                foreach ($sub_monster->owned as $owned){
-                                                    if ($owned->unit->awakens_from == "" && $owned->unit->awakens_to == ""){
-                                                        // No to, no from, silver monster.
-                                                        $star_class ="star_silver";
-                                                        $mon_title = $owned->unit->element_name . " " . $owned->unit->name;
-                                                    }
-                                                    elseif ($owned->unit->awakens_from != "" && $owned->unit->awakens_to == ""){
-                                                        // Already awakened
-                                                        if ($owned->unit->base_stars - $owned->unit->natural_stars == 1){
-                                                            // Normal awaken.
-                                                            $star_class ="star_purple";
-                                                        }
-                                                        else{
-                                                            // Second awaken.
-                                                            $star_class ="star_red";
-                                                        }
-                                                        $mon_title = $owned->unit->name;
-                                                    }
-                                                    elseif ($owned->unit->awakens_to != ""){
-                                                        // Awakeable.
-                                                        $star_class ="star_gold";
-                                                        $mon_title = $owned->unit->element_name . " " . $owned->unit->name;
-                                                    }
-                                                    $mon_title = $mon_title . " - " . $owned->stars . "* - Lv." . $owned->level;
-?>
-                                                    <a target="_blank" title='<?=$mon_title?>' href='/<?=$PLAYER->id?>/monsters/<?=$owned->id?>'>
-                                                        <div class='monster_panel'>
-                                                            <span class='stars'>
-<?php
-                                                                for ($i = 0; $i < $owned->stars; $i ++){
-?>
-                                                                    <img class='star <?=$star_class?>' src='<?=URL::IMG["ICON"]?>star.png'/>
-<?php
-                                                                }
-?>
-                                                            </span>
-                                                            <img title='<?=$mon_title?>' class='monster border_<?=$owned->unit->element_name?>' src='<?=$owned->unit->get_image()?>'/>
-                                                            <span class='level'>
-                                                                <?=$owned->level?>
-                                                            </span>
-                                                        </div>
-                                                    </a>
-<?php
-                                                }
-?>
-                                            </div><!-- .owned -->
-                                        </td>
-<?php
-                                        $num ++;
-                                    }
-                                }
-?>
-                                <td class='empty' colspan='4'>
-                                </td>
-                            </tr>
-                        </table>
-<?php
-                    }
-?>
-                    
-                </article>
-            </section>
-        </main>
-<?php
-        include __DIR__ . "/inc/footer.php";
-?>
-    </body>
-</html>

+ 2 - 5
application/view/inc/header.php

@@ -95,11 +95,6 @@
                             Catalog
                         </a>
                     </td>
-                    <td class='item'>
-                        <a href='/<?=$PLAYER->id?>/fusion/'>
-                            Fusion
-                        </a>
-                    </td>
                     <td class='item'>
                         <a href='/<?=$PLAYER->id?>/guild/'>
                             Guild
@@ -120,6 +115,8 @@
                             Optimizer
                         </a>
                     </td>
+                    <td class='no_item'>
+                    </td>
                     <!--<td class='item'>
                         <a href='/<?=$PLAYER->id?>/stats/'>
                             Stats

+ 0 - 79
public/css/fusion.css

@@ -1,79 +0,0 @@
-section#fusions table{
-    border-collapse: collapse;
-    width: 100%;
-    display: block;
-    margin: 0.5em auto 1.5em auto;
-    border: 0.1em solid black;
-    background: var(--section-background-content);
-}
-section#fusions table td{
-    border-right: 0.1em solid #00000088;
-    border-left: 0.1em solid #00000088;
-    border-top: 0.2em solid #00000088;
-    border-bottom: 0.2em solid #00000088;
-    padding: 0;
-}
-section#fusions table td a{
-    display: inline-block;
-    vertical-align: middle;
-}
-section#fusions table td div.essences{
-    display: inline-block;
-    width: 6.5em;
-    height: 6.5em;
-    vertical-align: middle;
-}
-section#fusions table td div.essence img{
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 2.5em;
-    height: 2.5em;
-}
-section#fusions table td div.essence span{
-    position: absolute;
-    top: 1.4em;
-    text-align: right;
-    right: 0.2em;
-    color: #ffffff;
-    font-weight: bold;
-    text-shadow: 0 0 0.1em #000000, 0 0 0.1em #000000, 0 0 0.2em #000000, 0 0 0.2em #000000;
-}
-section#fusions table td div.owned{
-    border-top: 0.1em solid #00000066;
-    background-color: #555555;
-    border-radius: 0.2em;
-    padding: 0 0.1em;
-    opacity: 0.7;
-    display: block;
-    height: 6.5em;
-    overflow: auto;
-    scrollbar-width: thin;
-    margin: 0;
-}
-section#fusions table td div.owned span.owned{
-    display: block;
-    text-align: center;
-    margin: 0.1em 0.3em;
-    font-size: 90%;
-    color: #ffffff;
-}
-section#fusions table td div.owned div.monster_panel{
-    display: inline-block;
-    font-size: 50%;
-}
-section#fusions table td.f5{
-    background-color: #00000066;
-    padding-top: 0.8em;
-}
-section#fusions table td.f4{
-    font-size: 60%;
-    width: 25%;
-}
-section#fusions table td.f3{
-    font-size: 40%;
-    width: 6.25%;
-}
-section#fusions table td.f3.empty{
-    width: 25%;
-}

+ 2 - 2
swex-plugin/swdb.js

@@ -165,7 +165,7 @@ module.exports = {
     },
 
     /**
-     * Calls an arbitrary command on the SWDB APIv3.
+     * Calls an arbitrary command on the SWDB APIv1.
      *
      * @param command Command nade.
      * @param req The full request data.
@@ -187,7 +187,7 @@ module.exports = {
         var post_options = {
             host: config.Config.Plugins[this.pluginName].host,
             port: config.Config.Plugins[this.pluginName].port,
-            path: '/API/v3/' + command,
+            path: '/API/v1/' + command,
             method: method,
             headers: {
                 'Content-Type': 'application/x-www-form-urlencoded',

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor