| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- /*
- * This file is part of RuneOptimizer.
- *
- * RuneOptimizer is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option)
- * any later version.
- *
- * RuneOptimizer is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * RuneOptimizer. If not, see <https://www.gnu.org/licenses/>.
- */
- /**
- * @file update_json.c
- *
- * Implementation of {@link update_json}.
- *
- * This file implements the funciton {@link update_json} declared in
- * {@link update.h}. It also defines and implements some static functions used
- * by it.
- */
- #include <stdio.h>
- #include <string.h>
- #include <sqlite3.h>
- #include <json-c/json.h>
- #include "../runeoptimizer.h"
- #include "../error/error.h"
- #include "../db/db.h"
- #include "update.h"
- /**
- * Saves a single rune to the database obtaining data from its json object.
- *
- * Saves data to the tables 'runes' and 'rune_stats'. In case of error, a
- * description will be printed to stderr.
- *
- * @param[in] rune_json Rune json fragment.
- * @param[in] unit_id ID of the unit the rune is assigned to. To leave it
- * unassigned, pass an empty string, not NULL.
- * @return The number of stats saved to the database, including the main stat,
- * innate stat (if any), and all the normal stats. -1 in case of error.
- */
- static int update_json_rune(json_object *rune_json, unsigned char *unit_id);
- /**
- * Saves a single unit to the database obtaining data from its json object.
- *
- * Saves data to the tables 'units'. If the unit has any rune assigned, it will
- * also be saved to 'runes'. In case of error, a description will be printed to
- * stderr.
- *
- * @param[in] unit_json Unit json fragment.
- * @param[in] six_stars Indicator to import only 6* units. Units with runes will
- * be saved anyway.
- * @param[in] with_runes Indicator to import only units with runes.
- * @param[out] total_runes Cunter for runes. Will be increased for each saved
- * rune.
- * @param[out] total_stats Cunter for rune stats. Will be increased for each
- * stat on each saved rune.
- * @return 1 if the unit was saved to the database. 0 If everything was OK but
- * the unit was not saved because it did not match the criteria. -1 on error.
- */
- static int update_json_unit(
- json_object *unit_json, unsigned char six_stars,
- unsigned char with_runes, unsigned int *total_runes, unsigned int *total_stats
- );
- extern int update_json(
- char file[], unsigned char six_stars,
- unsigned char with_runes, unsigned char clear_teams, unsigned char gui
- ){
- // Counters for objcts saved
- unsigned int total_units = 0;
- unsigned int total_runes = 0;
- unsigned int total_stats = 0;
- if (gui == FALSE) printf("Updating from json file: %s\n", file);
- // Read the JSON content
- json_object *root = json_object_from_file(file);
- if (!root){
- fprintf(stderr, "Cant access file: %s\n", file);
- return(ERROR_INPUT_UPDATE_UNKNOWN_SOURCE);
- }
- json_object *wizard_id = json_object_object_get(root, "wizard_id");
- json_object *wizard_info = json_object_object_get(root, "wizard_info");
- json_object *wizard_name =
- json_object_object_get(wizard_info, "wizard_name");
- json_object *wizard_level =
- json_object_object_get(wizard_info, "wizard_level");
- printf("Player ID: %s\n", json_object_get_string(wizard_id));
- printf("Player name: %s\n", json_object_get_string(wizard_name));
- printf("Player level: %s\n", json_object_get_string(wizard_level));
- fflush(stdout); // To refresh GUI output.
- // Recreate the database tables
- int status = update_db_tables(clear_teams);
- if (SUCCESS != status) return(status);
- // Parse runes
- json_object *runes = json_object_object_get(root, "runes");
- int rune_count = json_object_array_length(runes);
- json_object *idx;
- for (int i = 0; i < rune_count; i++){
- total_runes ++;
- idx = json_object_array_get_idx(runes, i);
- status = update_json_rune(idx, (unsigned char *) "");
- if (status != -1) total_stats += status;
- }
- // Parse units
- json_object *unit_list = json_object_object_get(root, "unit_list");
- int unit_count = json_object_array_length(unit_list);
- for (int i = 0; i < unit_count; i++){
- idx = json_object_array_get_idx(unit_list, i);
- status = update_json_unit(
- idx, six_stars, with_runes, &total_runes, &total_stats
- );
- if (status == 1) total_units ++;
- }
- status = update_current_stats();
- if (SUCCESS != status) return(status);
- // Insert into table info
- status = update_info(
- json_object_get_string(wizard_id),
- json_object_get_string(wizard_name),
- json_object_get_string(wizard_level)
- );
- if (SUCCESS != status) return(status);
- // All parsed
- printf("%u units saved.\n", total_units);
- printf("%u runes saved.\n", total_runes);
- printf("%u rune stats saved.\n", total_stats);
- printf("Player info updated\n");
- return(SUCCESS);
- }
- static int update_json_rune(json_object *rune_json, unsigned char *unit_id){
- int total_stats = 0;
- DB_Rune rune;
- char *query_parameters[43];
- for (int i = 1; i < 43; i ++) query_parameters[i] = malloc(35);
- // Rune ID
- json_object *rune_id = json_object_object_get(rune_json, "rune_id");
- strcpy((char *) rune.id, json_object_get_string(rune_id));
- // Rune unit
- strcpy((char *) rune.unit, (const char *) unit_id);
- // Rune slot
- json_object *slot_no = json_object_object_get(rune_json, "slot_no");
- rune.slot = json_object_get_int(slot_no);
- // Rune quality (extra)
- json_object *extra = json_object_object_get(rune_json, "extra");
- rune.quality = json_object_get_int(extra);
- // Rune stars (class)
- json_object *class = json_object_object_get(rune_json, "class");
- rune.stars = json_object_get_int(class);
- // Ancient runes have stars + 10.
- if (rune.stars > 10) rune.stars -= 10;
- // Rune set
- json_object *set_id = json_object_object_get(rune_json, "set_id");
- rune.set = json_object_get_int(set_id);
- // Rune level (upgrade_curr)
- json_object *upgrade_curr =
- json_object_object_get(rune_json, "upgrade_curr");
- rune.level = json_object_get_int(upgrade_curr);
- // Rune value
- json_object *base_value = json_object_object_get(rune_json, "base_value");
- rune.buy_value = json_object_get_int(base_value);
- // Rune sell value
- json_object *sell_value = json_object_object_get(rune_json, "sell_value");
- rune.sell_value = json_object_get_int(sell_value);
- // Main stat
- json_object *pri_eff = json_object_object_get(rune_json, "pri_eff");
- json_object *pri_stat = json_object_array_get_idx(pri_eff, 0);
- rune.main.stat = json_object_get_int(pri_stat);
- json_object *pri_value = json_object_array_get_idx(pri_eff, 1);
- rune.main.value = json_object_get_int(pri_value);
- // Innate stat
- json_object *prefix_eff = json_object_object_get(rune_json, "prefix_eff");
- json_object *prefix_stat = json_object_array_get_idx(prefix_eff, 0);
- rune.innate.stat = json_object_get_int(prefix_stat);
- json_object *prefix_value = json_object_array_get_idx(prefix_eff, 1);
- rune.innate.value = json_object_get_int(prefix_value);
- json_object *sec_eff = json_object_object_get(rune_json, "sec_eff");
- // Loop stats
- int stat_count = json_object_array_length(sec_eff);
- rune.stat_count = 0;
- for (int i = 0; i < stat_count && i < 4; i++){
- rune.stat_count ++;
- json_object *stat_json = json_object_array_get_idx(sec_eff, i);
- json_object *stat = json_object_array_get_idx(stat_json, 0);
- rune.stats[i].stat = json_object_get_int(stat);
- json_object *value = json_object_array_get_idx(stat_json, 1);
- rune.stats[i].value = json_object_get_int(value);
- json_object *enchant = json_object_array_get_idx(stat_json, 2);
- rune.stats[i].enchant = json_object_get_int(enchant);
- json_object *grind = json_object_array_get_idx(stat_json, 3);
- rune.stats[i].grind = json_object_get_int(grind);
- }
- // All the rune info has been loaded. Now, calculate the rest of stats
- update_rune_totals(&rune);
- // Insert the rune into the database
- query_parameters[0] = (char *) rune.id;
- query_parameters[1] = (char *) unit_id;
- sprintf(query_parameters[2], "%d", rune.set);
- sprintf(query_parameters[3], "%d", rune.slot);
- sprintf(query_parameters[4], "%d", rune.stars);
- sprintf(query_parameters[5], "%d", rune.level);
- sprintf(query_parameters[6], "%d", rune.quality);
- sprintf(query_parameters[7], "%f", rune.efficiency);
- sprintf(query_parameters[8], "%f", rune.max_efficiency);
- sprintf(query_parameters[9], "%d", rune.main.stat);
- sprintf(query_parameters[10], "%u", rune.current_hp_percent);
- sprintf(query_parameters[11], "%u", rune.current_atk_percent);
- sprintf(query_parameters[12], "%u", rune.current_def_percent);
- sprintf(query_parameters[13], "%u", rune.current_hp_flat);
- sprintf(query_parameters[14], "%u", rune.current_atk_flat);
- sprintf(query_parameters[15], "%u", rune.current_def_flat);
- sprintf(query_parameters[16], "%u", rune.current_spd);
- sprintf(query_parameters[17], "%u", rune.current_crr);
- sprintf(query_parameters[18], "%u", rune.current_crd);
- sprintf(query_parameters[19], "%u", rune.current_acc);
- sprintf(query_parameters[20], "%u", rune.current_res);
- sprintf(query_parameters[21], "%u", rune.lv12_hp_percent);
- sprintf(query_parameters[22], "%u", rune.lv12_atk_percent);
- sprintf(query_parameters[23], "%u", rune.lv12_def_percent);
- sprintf(query_parameters[24], "%u", rune.lv12_hp_flat);
- sprintf(query_parameters[25], "%u", rune.lv12_atk_flat);
- sprintf(query_parameters[26], "%u", rune.lv12_def_flat);
- sprintf(query_parameters[27], "%u", rune.lv12_spd);
- sprintf(query_parameters[28], "%u", rune.lv12_crr);
- sprintf(query_parameters[29], "%u", rune.lv12_crd);
- sprintf(query_parameters[30], "%u", rune.lv12_acc);
- sprintf(query_parameters[31], "%u", rune.lv12_res);
- sprintf(query_parameters[32], "%u", rune.lv15_hp_percent);
- sprintf(query_parameters[33], "%u", rune.lv15_atk_percent);
- sprintf(query_parameters[34], "%u", rune.lv15_def_percent);
- sprintf(query_parameters[35], "%u", rune.lv15_hp_flat);
- sprintf(query_parameters[36], "%u", rune.lv15_atk_flat);
- sprintf(query_parameters[37], "%u", rune.lv15_def_flat);
- sprintf(query_parameters[38], "%u", rune.lv15_spd);
- sprintf(query_parameters[39], "%u", rune.lv15_crr);
- sprintf(query_parameters[40], "%u", rune.lv15_crd);
- sprintf(query_parameters[41], "%u", rune.lv15_acc);
- sprintf(query_parameters[42], "%u", rune.lv15_res);
- if (
- SUCCESS !=
- db_execute(
- "INSERT INTO runes ("
- " id, unit, type,"
- " slot, stars, level,"
- " quality, efficiency, max_efficiency,"
- " main_stat, current_hp_percent, current_atk_percent,"
- " current_def_percent, current_hp_flat, current_atk_flat,"
- " current_def_flat, current_spd, current_crr,"
- " current_crd, current_acc, current_res,"
- " lv12_hp_percent, lv12_atk_percent, lv12_def_percent,"
- " lv12_hp_flat, lv12_atk_flat, lv12_def_flat,"
- " lv12_spd, lv12_crr, lv12_crd,"
- " lv12_acc, lv12_res, lv15_hp_percent,"
- " lv15_atk_percent, lv15_def_percent, lv15_hp_flat,"
- " lv15_atk_flat, lv15_def_flat, lv15_spd,"
- " lv15_crr, lv15_crd, lv15_acc,"
- " lv15_res"
- ") VALUES ("
- " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
- " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"
- ")",
- query_parameters
- )
- ){
- fprintf(stderr, "Unable to insert rune: %s\n", sqlite3_errmsg(db));
- return(-1);
- }
- // Insert main stat
- total_stats ++;
- //query_parameters[0] = rune.id; // No need, already has id
- query_parameters[1] = "-1"; // Main stat
- sprintf(query_parameters[2], "%d", rune.main.stat);
- sprintf(query_parameters[3], "%u", rune.main.value);
- query_parameters[4] = "0"; // Mains can't be grinded.
- query_parameters[5] = "0"; // Mains can't be enchanted.
- if (
- SUCCESS !=
- db_execute(
- "INSERT INTO rune_stats(rune, slot, stat, value, grind, enchant) "
- "VALUES (?, ?, ?, ?, ?, ?)",
- query_parameters
- )
- ){
- fprintf(
- stderr, "Unable to insert rune main stat: %s\n", sqlite3_errmsg(db)
- );
- return(-1);
- }
- // Insert innate stat
- if (rune.innate.stat != 0){
- total_stats ++;
- //query_parameters[0] = rune.id; // No need, already has id
- query_parameters[1] = "0"; // Main stat
- sprintf(query_parameters[2], "%d", rune.innate.stat);
- sprintf(query_parameters[3], "%u", rune.innate.value);
- query_parameters[4] = "0"; // Innates can't be grinded.
- query_parameters[5] = "0"; // Innates can't be enchanted.
- if (
- SUCCESS !=
- db_execute(
- "INSERT INTO rune_stats "
- "(rune, slot, stat, value, grind, enchant) "
- "VALUES (?, ?, ?, ?, ?, ?)",
- query_parameters
- )
- ){
- fprintf(
- stderr,
- "Unable to insert rune innate stat: %s\n", sqlite3_errmsg(db)
- );
- return(-1);
- }
- }
- // Insert normal stats
- for (int s = 0; s < rune.stat_count; s ++){
- total_stats ++;
- //query_parameters[0] = rune.id; // No need, already has id
- query_parameters[1] = malloc(5);
- sprintf(query_parameters[1], "%d", s + 1); // 1-4
- query_parameters[2] = malloc(5);
- sprintf(query_parameters[2], "%d", rune.stats[s].stat);
- sprintf(query_parameters[3], "%u", rune.stats[s].value);
- query_parameters[4] = malloc(5);
- sprintf(query_parameters[4], "%u", rune.stats[s].grind);
- query_parameters[5] = malloc(5);
- sprintf(query_parameters[5], "%d", rune.stats[s].enchant);
- if (
- SUCCESS !=
- db_execute(
- "INSERT INTO rune_stats"
- "(rune, slot, stat, value, grind, enchant) "
- "VALUES (?, ?, ?, ?, ?, ?)",
- query_parameters
- )
- ){
- fprintf(
- stderr, "Unable to insert rune stat: %s\n", sqlite3_errmsg(db)
- );
- return(-1);
- }
- }
- // Now that everything is in the database, I can calculate efficiencies
- float efficiency = 0.0f;
- float max_efficiency = 0.0f;
- update_efficiency(query_parameters[0], &efficiency, &max_efficiency);
- strcpy(query_parameters[2], query_parameters[0]); //ID
- query_parameters[0] = malloc(35);
- query_parameters[1] = malloc(35);
- sprintf(query_parameters[0], "%3.2f", efficiency);
- sprintf(query_parameters[1], "%3.2f", max_efficiency);
- if (
- SUCCESS !=
- db_execute(
- "UPDATE runes SET efficiency = ?, max_efficiency = ? WHERE id = ?",
- query_parameters
- )
- ){
- fprintf(
- stderr, "Unable to update rune efficiency: %s\n", sqlite3_errmsg(db)
- );
- return(-1);
- }
- return(total_stats);
- }
- static int update_json_unit(
- json_object *unit_json, unsigned char six_stars,
- unsigned char with_runes, unsigned int *total_runes, unsigned int *total_stats
- ){
- int ret_val = 0;
- unsigned char unit_has_runes = FALSE;
- struct DB_Unit unit;
- char *query_parameters[23];
- for (int i = 1; i < 23; i ++) query_parameters[i] = malloc(5);
- // Unit ID
- json_object *unit_id = json_object_object_get(unit_json, "unit_id");
- strcpy((char *) unit.id, json_object_get_string(unit_id));
- // Unit monster ID
- json_object *unit_master_id =
- json_object_object_get(unit_json, "unit_master_id");
- unit.monster= json_object_get_int(unit_master_id);
- // Unit name
- update_get_monster_name(unit.monster, (char *) unit.name);
- json_object *unit_level = json_object_object_get(unit_json, "unit_level");
- unit.level = json_object_get_int(unit_level);
- // Unit stars (class)
- json_object *class = json_object_object_get(unit_json, "class");
- unit.stars = json_object_get_int(class);
- // Unit base HP (con * 15)
- json_object *con = json_object_object_get(unit_json, "con");
- unit.base_hp = json_object_get_int(con) * 15;
- // Unit base ATK
- json_object *atk = json_object_object_get(unit_json, "atk");
- unit.base_atk = json_object_get_int(atk);
- // Unit base DEF
- json_object *def = json_object_object_get(unit_json, "def");
- unit.base_def = json_object_get_int(def);
- // Unit base SPD
- json_object *spd = json_object_object_get(unit_json, "spd");
- unit.base_spd = json_object_get_int(spd);
- // Unit base RES
- json_object *resist = json_object_object_get(unit_json, "resist");
- unit.base_res = json_object_get_int(resist);
- // Unit base ACC
- json_object *accuracy = json_object_object_get(unit_json, "accuracy");
- unit.base_acc = json_object_get_int(accuracy);
- // Unit base CRR
- json_object *critical_rate =
- json_object_object_get(unit_json, "critical_rate");
- unit.base_crr = json_object_get_int(critical_rate);
- // Unit base CRD
- json_object *critical_damage =
- json_object_object_get(unit_json, "critical_damage");
- unit.base_crd = json_object_get_int(critical_damage);
- // Homunculus name (if is Homunculus)
- json_object *homunculus_name =
- json_object_object_get(unit_json, "homunculus_name");
- if (strlen(json_object_get_string(homunculus_name)) > 0){
- strcpy((char *) unit.name, json_object_get_string(homunculus_name));
- }
- // Parse unit runes
- json_object *unit_runes = json_object_object_get(unit_json, "runes");
- int rune_count = json_object_array_length(unit_runes);
- for (int i = 0; i < rune_count; i++){
- unit_has_runes = TRUE;
- // TODO: Test this: reference or value?
- total_runes ++;
- json_object *idx = json_object_array_get_idx(unit_runes, i);
- int status = update_json_rune(idx, unit.id);
- if (status != -1) *total_stats += status;
- }
- // Insert unit, depending on flags and status
- if (
- unit_has_runes == TRUE ||
- (six_stars == FALSE && with_runes == FALSE) ||
- (six_stars == TRUE && unit.stars == TRUE)
- ){
- ret_val = 1;
- query_parameters[0] = (char *) unit.id;
- query_parameters[1] = (char *) unit.name;
- sprintf(query_parameters[2], "%d", unit.stars);
- sprintf(query_parameters[3], "%d", unit.level);
- sprintf(query_parameters[4], "%u", unit.base_hp);
- sprintf(query_parameters[5], "%u", unit.base_atk);
- sprintf(query_parameters[6], "%u", unit.base_def);
- sprintf(query_parameters[7], "%u", unit.base_spd);
- sprintf(query_parameters[8], "%u", unit.base_crr);
- sprintf(query_parameters[9], "%u", unit.base_crd);
- sprintf(query_parameters[10], "%u", unit.base_res);
- sprintf(query_parameters[11], "%u", unit.base_acc);
- // Insert current stats as base stats.
- // They will be updated later.
- sprintf(query_parameters[12], "%u", unit.base_hp);
- sprintf(query_parameters[13], "%u", unit.base_atk);
- sprintf(query_parameters[14], "%u", unit.base_def);
- sprintf(query_parameters[15], "%u", unit.base_spd);
- sprintf(query_parameters[16], "%u", unit.base_crr);
- sprintf(query_parameters[17], "%u", unit.base_crd);
- sprintf(query_parameters[18], "%u", unit.base_res);
- sprintf(query_parameters[19], "%u", unit.base_acc);
- // TODO: Get storage status. But how??
- sprintf(query_parameters[20], "%d", 0);
- sprintf(query_parameters[21], "%u", unit.monster);
- if (
- SUCCESS !=
- db_execute(
- "INSERT INTO units ("
- " id, name, stars, level,"
- " base_hp, base_atk, base_def, base_spd,"
- " base_crr, base_crd, base_res, base_acc,"
- " current_hp, current_atk, current_def, current_spd,"
- " current_crr, current_crd, current_res, current_acc,"
- " storage, monster"
- ") VALUES ("
- " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?"
- ")",
- query_parameters
- )
- ){
- fprintf(stderr, "Unable to insert unit: %s\n", sqlite3_errmsg(db));
- return(-1);
- }
- }
- return(ret_val);
- }
|