Эх сурвалжийг харах

Unlocked units shown in the catalog. SWEX plugin updated to read that info.

Iñigo Valentin 5 жил өмнө
parent
commit
b9329e1707

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

@@ -38,6 +38,7 @@
                 switch ($command){
                     case "help":
                         require_once(__DIR__ . "/help/index.php");
+                        break;
                     case "upload_profile":
                         require_once(__DIR__ . "/upload_profile.php");
                         break;
@@ -59,6 +60,9 @@
                     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;

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

@@ -0,0 +1,156 @@
+#!/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)
+
+

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

@@ -0,0 +1,87 @@
+<?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;
+    }
+?>

+ 3 - 3
application/API/v2/update_logbook.php

@@ -48,7 +48,7 @@
             exec($cmd, $out, $ret);
         }
         catch(Exception $e) {
-            error_log("Error running scenario run script '$cmd': " . $e->getMessage());
+            error_log("Error running logbook update script '$cmd': " . $e->getMessage());
             http_response_code(500);
             return 500;
         }
@@ -59,7 +59,7 @@
                 return $ret;
             }
             catch(Exception $e) {
-                error_log("Dungeon run script '$cmd' returned an unexpected value $ret: " . $e->getMessage());
+                error_log("Logbook update script '$cmd' returned an unexpected value $ret: " . $e->getMessage());
                 http_response_code(500);
                 return 500;
             }
@@ -70,7 +70,7 @@
         return $ret;
     }
     catch(Exception $e) {
-        error_log("Unknown error parsing scenario run: " . $e->getMessage());
+        error_log("Unknown error parsing logbook update: " . $e->getMessage());
         http_response_code(500);
         return 500;
     }

+ 17 - 0
application/page/Catalog_Page.php

@@ -26,6 +26,11 @@
          */
         public $units = [];
 
+        /**
+         * @var int[] IDs of the units marked in the catalog.
+         */
+        public $units_open = [];
+
         /**
          * @var mixed[] Default filter values.
          */
@@ -45,6 +50,7 @@
          */
         public function __construct(){
             global $db;
+            global $UID;
             $this->view = PATH::VIEW . "catalog.php";
             $this->parse_filters();
             $s_mon = $this->build_query();
@@ -52,6 +58,17 @@
             while ($r_mon = $q_mon->fetchArray(SQLITE3_ASSOC)){
                 array_push($this->units, new K_Unit($r_mon["id"], false));
             }
+            $s_open = "
+              SELECT unit
+              FROM collection
+              WHERE
+                uid = $UID AND
+                open = 1
+            ";
+            $q_open = $db->query($s_open);
+            while ($r_open = $q_open->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->units_open, $r_open["unit"]);
+            }
             $this->title = "Catalog - SWDB";
             $this->description = "Catalog of all monsters";
             $this->canonical = URL::BASE . "catalog/";

BIN
application/sw.sqlite


+ 7 - 1
application/view/catalog.php

@@ -112,8 +112,14 @@
                             }
                             $element = $mon->element;
                         }
+                        if (!in_array($mon->id, $page->units_open)){
+                            $closed = "closed";
+                        }
+                        else{
+                            $closed = "";
+                        }
 ?>
-                        <div class='monster'>
+                        <div class='monster <?=$closed?>'>
                             <a href='/<?=$UID?>/catalog/<?=$mon->id?>'>
                                 <div class='monster_panel'>
                                     <?=HTML::unit_panel($mon)?>

+ 5 - 0
install_data/install_data.sql

@@ -60,6 +60,11 @@ CREATE TABLE record_party(
     leader INT NOT NULL DEFAULT 0,
     front INT NOT NULL DEFAULT 0
 );
+CREATE TABLE collection(
+    uid INT NOT NULL REFERENCES player(id),
+    unit INT NOT NULL REFERENCES k_unit(id),
+    open INT CHECK(open IN (0, 1))
+);
 CREATE TABLE scenario(
     uid INT NOT NULL REFERENCES player(id),
     region INT NOT NULL REFERENCES k_area(id),

+ 4 - 0
public/css/catalog.css

@@ -6,3 +6,7 @@ section#list article div.monster{
     font-size: 60%;
     margin: 0.2em;
 }
+
+section#list article div.closed{
+    filter: brightness(50%);
+}

+ 5 - 1
swex-plugin/swdb.js

@@ -100,7 +100,11 @@ module.exports = {
                 apiCommand = "upload_profile";
                 success = "Profile uploaded sucesfully!"
                 break;
-                
+            // Catalog status
+            case 'GetUnitCollection':
+                apiCommand = "update_collection";
+                success = "Collection updated sucesfully!"
+                break;
             // Profile logbook
             case 'GetLobbyWizardLog':
                 apiCommand = "update_logbook";