upload_profile.py 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338
  1. #!/usr/bin/python3
  2. import sys
  3. import os
  4. import sqlite3
  5. import json
  6. import math
  7. """
  8. Reads the API KEY, that must be passed as first command line argument.
  9. :returns: Recovered API KEY.
  10. :raises Exception: Th KEY couldn't be red.
  11. """
  12. def readKey():
  13. try:
  14. key = sys.argv[1]
  15. return key
  16. except Exception as e:
  17. print("Error parsing API KEY: " + str(e))
  18. raise
  19. """
  20. Reads the JSON data, that must be passed as second command line argument.
  21. :returns: Recovered data, in JSON format.
  22. :raises Exception: The data couldn't be red or converted to JSON.
  23. """
  24. def readData():
  25. try:
  26. #print(sys.argv[1])
  27. #data = json.loads(sys.argv[1])
  28. with open(sys.argv[2], 'r') as f:
  29. content = f.read()
  30. data = json.loads(content)
  31. return data
  32. except Exception as e:
  33. print("Error parsing data: " + str(e))
  34. raise
  35. """
  36. Verifies that the API key matches the player data and that it exists in th DB.
  37. :param db: Connection to the database.
  38. :returns: Connection to the database.
  39. :param data: Data in json format.
  40. :param key: API KEY.
  41. :returns: True if key and player match, False otherwise.
  42. :raises IntegrityError: The queryes couldn't bre executed.
  43. """
  44. def verifyKey(db, data, key):
  45. print('Verifying KEY...')
  46. status = False
  47. try:
  48. uid = data["wizard_info"]["wizard_id"]
  49. cursor = db.cursor()
  50. cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
  51. if cursor.fetchone()[0] == 1:
  52. status = True
  53. cursor.close()
  54. except sqlite3.IntegrityError as e:
  55. print("Error executing statement: " + str(e))
  56. raise
  57. return status
  58. """
  59. Opens the database file and cleans the user tables.
  60. It also disables referencial integrity.
  61. :param name: The path to the sqlite database.
  62. :returns: Connection to the database.
  63. :raises IntegrityError: The queryes couldn't bre executed.
  64. :raises IOError: The sqlite file couldn't be created.
  65. """
  66. def openDatabase():
  67. kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite'
  68. udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite'
  69. print('Configuring database...')
  70. try:
  71. db = sqlite3.connect(kdb)
  72. cursor = db.cursor()
  73. cursor.execute("attach '" + udb + "' as data;")
  74. cursor.close()
  75. return db
  76. except sqlite3.IntegrityError as e:
  77. print("Error executing statement: " + str(e))
  78. raise
  79. except IOError as e:
  80. print("I/O Error creating database " + name + ": " + str(e))
  81. raise
  82. """
  83. Clears the user tables.
  84. It also disables referencial integrity.
  85. :param db: Sqlite database connection.
  86. :param data: Data in json format.
  87. :raises IntegrityError: The queryes couldn't bre executed.
  88. """
  89. def clearData(db, data):
  90. print('Clearing previous data...')
  91. try:
  92. uid = str(data["wizard_info"]["wizard_id"])
  93. cursor = db.cursor()
  94. cursor.execute('PRAGMA foreign_keys = OFF;')
  95. cursor.execute('DELETE FROM scenario WHERE uid = ?', [uid])
  96. cursor.execute('DELETE FROM defense WHERE uid = ?', [uid])
  97. cursor.execute('DELETE FROM gw_defense WHERE uid = ?', [uid])
  98. cursor.execute('DELETE FROM unit_skill WHERE unit IN (SELECT id FROM unit WHERE uid = ?)', [uid])
  99. cursor.execute('DELETE FROM unit WHERE uid = ?', [uid])
  100. cursor.execute('DELETE FROM rune WHERE uid = ?', [uid])
  101. cursor.execute('DELETE FROM artifact WHERE uid = ?', [uid])
  102. cursor.execute('DELETE FROM building WHERE uid = ?', [uid])
  103. cursor.execute('DELETE FROM decoration WHERE uid = ?', [uid])
  104. cursor.execute('DELETE FROM inventory WHERE uid = ?', [uid])
  105. cursor.execute('DELETE FROM summon_special') # For every player, will be reloaded.
  106. cursor.execute('DELETE FROM rune_craft WHERE uid = ?', [uid])
  107. # 'guild' and 'guild_member' tables are cleared before inserting.
  108. db.commit()
  109. cursor.close();
  110. except sqlite3.IntegrityError as e:
  111. print("Error executing statement: " + str(e))
  112. raise
  113. return
  114. """
  115. Closes the database.
  116. Before doing so, it also disables referencial integrity.
  117. :param db: Connection to the database.
  118. :returns: Connection to the database.
  119. :raises IntegrityError: The queryes couldn't bre executed.
  120. """
  121. def closeDatabase(name):
  122. print('Closing database connection...')
  123. try:
  124. cursor = db.cursor()
  125. cursor.execute('PRAGMA foreign_keys = ON;')
  126. cursor.close()
  127. db.commit()
  128. db.close()
  129. except sqlite3.IntegrityError as e:
  130. print("Error executing statement: " + str(e))
  131. raise
  132. """
  133. Inserts a row into the database.
  134. :param db: Connection to the database.
  135. :param table: Name of the table to insert into.
  136. :param values: List of values to insert.
  137. :raises IntegrityError: The insert query was unsuccesfull.
  138. """
  139. def insert(db, table, values):
  140. cursor = db.cursor()
  141. db.execute('PRAGMA foreign_keys = OFF;')
  142. placeholders = ''
  143. for x in range(0, len(values)):
  144. placeholders = placeholders + '?, '
  145. placeholders = placeholders[:len(placeholders) - 2]
  146. query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
  147. try:
  148. cursor.execute(query, values)
  149. except sqlite3.IntegrityError as e:
  150. print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
  151. raise
  152. cursor.close;
  153. """
  154. Parses player (table player).
  155. :param db: Sqlite database connection.
  156. :param data: Data in json format.
  157. """
  158. def parsePlayer(db, data):
  159. print("Parsing player...")
  160. cursor = db.cursor()
  161. uid = data["wizard_info"]["wizard_id"]
  162. name = data["wizard_info"]["wizard_name"]
  163. # TODO: Generate data
  164. mail = data["wizard_info"]["wizard_name"]
  165. password = data["wizard_info"]["wizard_name"]
  166. api_key = data["wizard_info"]["wizard_name"]
  167. mana = data["wizard_info"]["wizard_mana"]
  168. crystal = data["wizard_info"]["wizard_crystal"]
  169. country = data["wizard_info"]["wizard_last_country"]
  170. lang = data["wizard_info"]["wizard_last_lang"]
  171. level = data["wizard_info"]["wizard_level"]
  172. experience = data["wizard_info"]["experience"]
  173. energy = data["wizard_info"]["wizard_energy"]
  174. energy_max = data["wizard_info"]["energy_max"]
  175. energy_per_min = data["wizard_info"]["energy_per_min"]
  176. arena_energy = data["wizard_info"]["arena_energy"]
  177. arena_energy_max = data["wizard_info"]["arena_energy_max"]
  178. rep = data["wizard_info"]["rep_unit_id"]
  179. social_point = data["wizard_info"]["social_point_current"]
  180. honor_point = data["wizard_info"]["honor_point"]
  181. guild_point = data["wizard_info"]["guild_point"]
  182. darkportal_energy = data["wizard_info"]["darkportal_energy"]
  183. darkportal_energy_max = data["wizard_info"]["darkportal_energy_max"]
  184. dimension_energy = data["dimension_hole_info"]["energy"]
  185. dimension_energy_max = data["dimension_hole_info"]["energy_max"]
  186. costume_point = data["wizard_info"]["costume_point"]
  187. costume_point_max = data["wizard_info"]["costume_point_max"]
  188. honor_medal = data["wizard_info"]["honor_medal"]
  189. honor_mark = data["wizard_info"]["honor_mark"]
  190. event_coin = data["wizard_info"]["event_coin"]
  191. storage_slots = data["unit_depository_slots"]["number"]
  192. island_upgrade = 0
  193. for island in data["island_info"]:
  194. if island["id"] <= 7 and island["open"] == 1:
  195. island_upgrade = island["id"]
  196. query = '''
  197. UPDATE player
  198. SET mana = ?,
  199. crystal = ?,
  200. country = ?,
  201. lang = ?,
  202. level = ?,
  203. experience = ?,
  204. energy = ?,
  205. energy_max = ?,
  206. energy_per_min = ?,
  207. arena_energy = ?,
  208. arena_energy_max = ?,
  209. rep = ?,
  210. social_point = ?,
  211. honor_point = ?,
  212. guild_point = ?,
  213. darkportal_energy = ?,
  214. darkportal_energy_max = ?,
  215. dimension_energy = ?,
  216. dimension_energy_max = ?,
  217. costume_point = ?,
  218. costume_point_max = ?,
  219. honor_medal = ?,
  220. honor_medal = ?,
  221. event_coin = ?,
  222. storage_slots = ?,
  223. island = ?
  224. WHERE uid = ?;
  225. '''
  226. values = (
  227. mana, crystal, country,
  228. lang, level, experience,
  229. energy, energy_max, energy_per_min,
  230. arena_energy, arena_energy_max, rep,
  231. social_point, honor_point, guild_point,
  232. darkportal_energy, darkportal_energy_max, dimension_energy,
  233. dimension_energy_max, costume_point, costume_point_max,
  234. honor_medal, honor_medal, event_coin,
  235. storage_slots, island_upgrade, uid
  236. )
  237. try:
  238. cursor.execute(query, values)
  239. db.commit()
  240. except sqlite3.IntegrityError as e:
  241. print('Error updating player table with: ' + str(query) + ' <== ' + str(values) + ' || Error message:' + str(e))
  242. raise
  243. """
  244. Parses scenarios (table scenario).
  245. :param db: Sqlite database connection.
  246. :param data: Data in json format.
  247. """
  248. def parseScenarios(db, data):
  249. print("Parsing scenarios...")
  250. uid = data["wizard_info"]["wizard_id"]
  251. for sce in data["scenario_list"]:
  252. region = sce["region_id"]
  253. difficulty = sce["difficulty"]
  254. cleared = sce["cleared"]
  255. max_cleared = 0
  256. for stage in sce["stage_list"]:
  257. if stage["cleared"] == 1:
  258. max_cleared = stage["stage_no"]
  259. insert(db, "scenario", (uid, region, difficulty, cleared, max_cleared))
  260. db.commit()
  261. """
  262. Parses arena defense units (table defense).
  263. :param db: Sqlite database connection.
  264. :param data: Data in json format.
  265. """
  266. def parseDefense(db, data):
  267. print("Parsing arena defense...")
  268. uid = data["wizard_info"]["wizard_id"]
  269. for defense in data["defense_unit_list"]:
  270. unit = defense["unit_id"]
  271. position = defense["pos_id"]
  272. insert(db, "defense", (uid, unit, position))
  273. db.commit()
  274. """
  275. Parses guild war defense units (table gw_defense).
  276. :param db: Sqlite database connection.
  277. :param data: Data in json format.
  278. """
  279. def parseGWDefense(db, data):
  280. print("Parsing guild war defense...")
  281. uid = data["wizard_info"]["wizard_id"]
  282. if data["guildwar_defense_unit_list"][0]:
  283. position = 1
  284. for defense in data["guildwar_defense_unit_list"][0]:
  285. unit = defense["unit_id"]
  286. insert(db, "gw_defense", (uid, unit, position))
  287. position = position + 1
  288. if data["guildwar_defense_unit_list"][1]:
  289. position = 4
  290. for defense in data["guildwar_defense_unit_list"][1]:
  291. unit = defense["unit_id"]
  292. insert(db, "gw_defense", (uid, unit, position))
  293. position = position + 1
  294. db.commit()
  295. """
  296. Parses buildings (table building).
  297. :param db: Sqlite database connection.
  298. :param data: Data in json format.
  299. """
  300. def parseBuildings(db, data):
  301. print("Parsing buildings...")
  302. uid = data["wizard_info"]["wizard_id"]
  303. for bui in data["building_list"]:
  304. id = bui["building_id"]
  305. building = bui["building_master_id"]
  306. gain = bui["gain_per_hour"]
  307. insert(db, "building", (uid, id, building, gain))
  308. db.commit()
  309. """
  310. Parses decoration buildings (table dcoration).
  311. :param db: Sqlite database connection.
  312. :param data: Data in json format.
  313. """
  314. def parseDecorations(db, data):
  315. print("Parsing decorations...")
  316. uid = data["wizard_info"]["wizard_id"]
  317. for bui in data["deco_list"]:
  318. id = bui["deco_id"]
  319. building = bui["master_id"]
  320. level = bui["level"]
  321. insert(db, "decoration", (uid, id, building, level))
  322. db.commit()
  323. """
  324. Parses unit data (tables unit, unit_skill).
  325. :param db: Sqlite database connection.
  326. :param data: Data in json format.
  327. """
  328. def parseUnits(db, data):
  329. print("Parsing monsters...")
  330. uid = data["wizard_info"]["wizard_id"]
  331. lock_list = data["unit_lock_list"]
  332. for mon in data["unit_list"]:
  333. id = mon["unit_id"]
  334. building = mon["building_id"]
  335. monster = mon["unit_master_id"]
  336. level = mon["unit_level"]
  337. stars = mon["class"]
  338. hp = mon["con"] * 15 # Always x15
  339. attack = mon["atk"]
  340. defense = mon["def"]
  341. speed = mon["spd"]
  342. crit_rate = mon["critical_rate"]
  343. crit_damage = mon["critical_damage"]
  344. resistance = mon["resist"]
  345. accuracy = mon["accuracy"]
  346. experience = mon["experience"]
  347. exp_gained = mon["exp_gained"]
  348. exp_gain_rate = mon["exp_gain_rate"]
  349. costume = mon["costume_master_id"]
  350. attribute = -1; # TODO: Attribute?
  351. source = mon["source"]
  352. create_time = mon["create_time"]
  353. homunculus = mon["homunculus"]
  354. homunculus_name = mon["homunculus_name"]
  355. lock = 0
  356. if id in lock_list:
  357. lock = 1
  358. 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))
  359. for skill in mon["skills"]:
  360. skill_id = skill[0]
  361. skill_level = skill[1]
  362. insert(db, "unit_skill", (id, skill_id, skill_level))
  363. db.commit()
  364. """
  365. Parses inventory data (table inventory).
  366. :param db: Sqlite database connection.
  367. :param data: Data in json format.
  368. """
  369. def parseInventory(db, data):
  370. print("Parsing inventory...")
  371. uid = data["wizard_info"]["wizard_id"]
  372. for item in data["inventory_info"]:
  373. id = item["item_master_id"]
  374. type = item["item_master_type"]
  375. amount = item["item_quantity"]
  376. insert(db, "inventory", (uid, id, type, amount))
  377. # Fix rune craft item type.
  378. cursor = db.cursor()
  379. cursor.execute("UPDATE inventory SET type = 27 WHERE type = 29 AND id IN (2001, 4001, 4002, 4003, 9001, 9002, 9003, 8001);")
  380. cursor.close()
  381. """
  382. Parses summon stone list (table summon_special).
  383. :param db: Sqlite database connection.
  384. :param data: Data in json format.
  385. """
  386. def parseSummonSpecial(db, data):
  387. print("Parsing Summon stone monster list...")
  388. uid = data["wizard_info"]["wizard_id"]
  389. for unit in data["summon_special_info"]["this"]:
  390. insert(db, "summon_special", (0, unit))
  391. for unit in data["summon_special_info"]["next"]:
  392. insert(db, "summon_special", (1, unit))
  393. for unit in data["summon_special_info"]["third"]:
  394. insert(db, "summon_special", (2, unit))
  395. for unit in data["summon_special_info"]["fourth"]:
  396. insert(db, "summon_special", (3, unit))
  397. """
  398. Parses rune data (table rune).
  399. :param db: Sqlite database connection.
  400. :param data: Data in json format.
  401. """
  402. def parseRunes(db, data):
  403. print("Parsing runes...")
  404. STAT_HP = 1
  405. STAT_HP_PCT = 2
  406. STAT_ATK = 3
  407. STAT_ATK_PCT = 4
  408. STAT_DEF = 5
  409. STAT_DEF_PCT = 6
  410. STAT_SPD = 8
  411. STAT_CRIT_RATE_PCT = 9
  412. STAT_CRIT_DMG_PCT = 10
  413. STAT_RESIST_PCT = 11
  414. STAT_ACCURACY_PCT = 12
  415. MAIN_STAT_VALUES = {
  416. # [stat][stars][level]: value
  417. STAT_HP: {
  418. 1: [40, 85, 130, 175, 220, 265, 310, 355, 400, 445, 490, 535, 580, 625, 670, 804],
  419. 2: [70, 130, 190, 250, 310, 370, 430, 490, 550, 610, 670, 730, 790, 850, 910, 1092],
  420. 3: [100, 175, 250, 325, 400, 475, 550, 625, 700, 775, 850, 925, 1000, 1075, 1150, 1380],
  421. 4: [160, 250, 340, 430, 520, 610, 700, 790, 880, 970, 1060, 1150, 1240, 1330, 1420, 1704],
  422. 5: [270, 375, 480, 585, 690, 795, 900, 1005, 1110, 1215, 1320, 1425, 1530, 1635, 1740, 2088],
  423. 6: [360, 480, 600, 720, 840, 960, 1080, 1200, 1320, 1440, 1560, 1680, 1800, 1920, 2040, 2448],
  424. },
  425. STAT_HP_PCT: {
  426. 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
  427. 2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  428. 3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
  429. 4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
  430. 5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
  431. 6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
  432. },
  433. STAT_ATK: {
  434. 1: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 54],
  435. 2: [5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 73],
  436. 3: [7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 92],
  437. 4: [10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 112],
  438. 5: [15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 135],
  439. 6: [22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 160],
  440. },
  441. STAT_ATK_PCT: {
  442. 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
  443. 2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  444. 3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
  445. 4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
  446. 5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
  447. 6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
  448. },
  449. STAT_DEF: {
  450. 1: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 54],
  451. 2: [5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 73],
  452. 3: [7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 92],
  453. 4: [10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 112],
  454. 5: [15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 135],
  455. 6: [22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 160],
  456. },
  457. STAT_DEF_PCT: {
  458. 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
  459. 2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  460. 3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
  461. 4: [5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 43],
  462. 5: [8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 51],
  463. 6: [11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 63],
  464. },
  465. STAT_SPD: {
  466. 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
  467. 2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  468. 3: [3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 19, 21, 25],
  469. 4: [4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 30],
  470. 5: [5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 39],
  471. 6: [7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 42],
  472. },
  473. STAT_CRIT_RATE_PCT: {
  474. 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
  475. 2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  476. 3: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 37],
  477. 4: [4, 6, 8, 11, 13, 15, 17, 19, 22, 24, 26, 28, 30, 33, 35, 41],
  478. 5: [5, 7, 10, 12, 15, 17, 19, 22, 24, 27, 29, 31, 34, 36, 39, 47],
  479. 6: [7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 58],
  480. },
  481. STAT_CRIT_DMG_PCT: {
  482. 1: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  483. 2: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 37],
  484. 3: [4, 6, 9, 11, 13, 16, 18, 20, 22, 25, 27, 29, 32, 34, 36, 43],
  485. 4: [6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 57],
  486. 5: [8, 11, 15, 18, 21, 25, 28, 31, 34, 38, 41, 44, 48, 51, 54, 65],
  487. 6: [11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 80],
  488. },
  489. STAT_RESIST_PCT: {
  490. 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
  491. 2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  492. 3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
  493. 4: [6, 8, 10, 13, 15, 17, 19, 21, 24, 26, 28, 30, 32, 35, 37, 44],
  494. 5: [9, 11, 14, 16, 19, 21, 23, 26, 28, 31, 33, 35, 38, 40, 43, 51],
  495. 6: [12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 64],
  496. },
  497. STAT_ACCURACY_PCT: {
  498. 1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18],
  499. 2: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19],
  500. 3: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 38],
  501. 4: [6, 8, 10, 13, 15, 17, 19, 21, 24, 26, 28, 30, 32, 35, 37, 44],
  502. 5: [9, 11, 14, 16, 19, 21, 23, 26, 28, 31, 33, 35, 38, 40, 43, 51],
  503. 6: [12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 64],
  504. },
  505. }
  506. SUBSTAT_INCREMENTS = {
  507. # [stat][stars]: value
  508. # Max possible substat value can be found by multiplying by 5
  509. STAT_HP: {
  510. 1: 60,
  511. 2: 105,
  512. 3: 165,
  513. 4: 225,
  514. 5: 300,
  515. 6: 375,
  516. },
  517. STAT_HP_PCT: {
  518. 1: 2,
  519. 2: 3,
  520. 3: 5,
  521. 4: 6,
  522. 5: 7,
  523. 6: 8,
  524. },
  525. STAT_ATK: {
  526. 1: 4,
  527. 2: 5,
  528. 3: 8,
  529. 4: 10,
  530. 5: 15,
  531. 6: 20,
  532. },
  533. STAT_ATK_PCT: {
  534. 1: 2,
  535. 2: 3,
  536. 3: 5,
  537. 4: 6,
  538. 5: 7,
  539. 6: 8,
  540. },
  541. STAT_DEF: {
  542. 1: 4,
  543. 2: 5,
  544. 3: 8,
  545. 4: 10,
  546. 5: 15,
  547. 6: 20,
  548. },
  549. STAT_DEF_PCT: {
  550. 1: 2,
  551. 2: 3,
  552. 3: 5,
  553. 4: 6,
  554. 5: 7,
  555. 6: 8,
  556. },
  557. STAT_SPD: {
  558. 1: 1,
  559. 2: 2,
  560. 3: 3,
  561. 4: 4,
  562. 5: 5,
  563. 6: 6,
  564. },
  565. STAT_CRIT_RATE_PCT: {
  566. 1: 1,
  567. 2: 2,
  568. 3: 3,
  569. 4: 4,
  570. 5: 5,
  571. 6: 6,
  572. },
  573. STAT_CRIT_DMG_PCT: {
  574. 1: 2,
  575. 2: 3,
  576. 3: 4,
  577. 4: 5,
  578. 5: 6,
  579. 6: 7,
  580. },
  581. STAT_RESIST_PCT: {
  582. 1: 2,
  583. 2: 3,
  584. 3: 5,
  585. 4: 6,
  586. 5: 7,
  587. 6: 8,
  588. },
  589. STAT_ACCURACY_PCT: {
  590. 1: 2,
  591. 2: 3,
  592. 3: 5,
  593. 4: 6,
  594. 5: 7,
  595. 6: 8,
  596. },
  597. }
  598. uid = data["wizard_info"]["wizard_id"]
  599. # Unequipped runes
  600. for rune in data["runes"]:
  601. id = rune["rune_id"]
  602. assigned_to = rune["occupied_id"]
  603. if assigned_to == 0:
  604. assigned_to = None
  605. runeset = rune["set_id"]
  606. slot = rune["slot_no"]
  607. stars = rune["class"]
  608. ancient = 0
  609. level = rune["upgrade_curr"]
  610. original_quality = rune["extra"]
  611. value = rune["sell_value"]
  612. if stars > 10:
  613. ancient = 1
  614. stars = stars - 10
  615. original_quality = original_quality - 10
  616. if level >= 12:
  617. quality = 5
  618. elif level >= 9:
  619. quality = 4
  620. elif level >= 6:
  621. quality = 3
  622. elif level >= 3:
  623. quality = 2
  624. else:
  625. quality = 1
  626. if original_quality > quality:
  627. quality = original_quality
  628. efficiency = 0
  629. max_efficiency = 0
  630. main_stat = rune["pri_eff"][0]
  631. main_stat_value = rune["pri_eff"][1]
  632. if rune["prefix_eff"][0] > 0:
  633. innate_stat = rune["prefix_eff"][0]
  634. innate_stat_value = rune["prefix_eff"][1]
  635. else:
  636. innate_stat = None
  637. innate_stat_value = 0
  638. if len(rune["sec_eff"]) > 0:
  639. substat_1 = rune["sec_eff"][0][0]
  640. substat_1_value = rune["sec_eff"][0][1]
  641. substat_1_enchant = rune["sec_eff"][0][2]
  642. substat_1_grind = rune["sec_eff"][0][3]
  643. else:
  644. substat_1 = None
  645. substat_1_value = 0
  646. substat_1_enchant = 0
  647. substat_1_grind = 0
  648. if len(rune["sec_eff"]) > 1:
  649. substat_2 = rune["sec_eff"][1][0]
  650. substat_2_value = rune["sec_eff"][1][1]
  651. substat_2_enchant = rune["sec_eff"][1][2]
  652. substat_2_grind = rune["sec_eff"][1][3]
  653. else:
  654. substat_2 = None
  655. substat_2_value = 0
  656. substat_2_enchant = 0
  657. substat_2_grind = 0
  658. if len(rune["sec_eff"]) > 2:
  659. substat_3 = rune["sec_eff"][2][0]
  660. substat_3_value = rune["sec_eff"][2][1]
  661. substat_3_enchant = rune["sec_eff"][2][2]
  662. substat_3_grind = rune["sec_eff"][2][3]
  663. else:
  664. substat_3 = None
  665. substat_3_value = 0
  666. substat_3_enchant = 0
  667. substat_3_grind = 0
  668. if len(rune["sec_eff"]) > 3:
  669. substat_4 = rune["sec_eff"][3][0]
  670. substat_4_value = rune["sec_eff"][3][1]
  671. substat_4_enchant = rune["sec_eff"][3][2]
  672. substat_4_grind = rune["sec_eff"][3][3]
  673. else:
  674. substat_4 = None
  675. substat_4_value = 0
  676. substat_4_enchant = 0
  677. substat_4_grind = 0
  678. # Calculate efficiences
  679. efficiency = 0
  680. substats = []
  681. efficiency += float(MAIN_STAT_VALUES[main_stat][stars][15]) / float(MAIN_STAT_VALUES[main_stat][6][15])
  682. if innate_stat is not None:
  683. efficiency += innate_stat_value / float(SUBSTAT_INCREMENTS[innate_stat][6] * 5)
  684. if substat_1 is not None:
  685. substats.append(substat_1)
  686. efficiency += substat_1_value / float(SUBSTAT_INCREMENTS[substat_1][6] * 5)
  687. if substat_2 is not None:
  688. substats.append(substat_2)
  689. efficiency += substat_2_value / float(SUBSTAT_INCREMENTS[substat_2][6] * 5)
  690. if substat_3 is not None:
  691. substats.append(substat_3)
  692. efficiency += substat_3_value / float(SUBSTAT_INCREMENTS[substat_3][6] * 5)
  693. if substat_4 is not None:
  694. substats.append(substat_4)
  695. efficiency += substat_4_value / float(SUBSTAT_INCREMENTS[substat_4][6] * 5)
  696. efficiency = efficiency / 2.8 * 100
  697. max_efficiency = get_max_efficiency(substats, efficiency, level, stars, original_quality)
  698. if efficiency > 100:
  699. efficiency = 100;
  700. if max_efficiency > 100:
  701. max_efficiency = 100;
  702. # TODO: Locked status not in JSO file.
  703. locked = 0
  704. 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))
  705. # Equipped runes
  706. for mon in data["unit_list"]:
  707. for rune in mon["runes"]:
  708. id = rune["rune_id"]
  709. assigned_to = rune["occupied_id"]
  710. if assigned_to == 0:
  711. assigned_to = None
  712. runeset = rune["set_id"]
  713. slot = rune["slot_no"]
  714. stars = rune["class"]
  715. ancient = 0
  716. level = rune["upgrade_curr"]
  717. original_quality = rune["extra"]
  718. value = rune["sell_value"]
  719. if stars > 10:
  720. ancient = 1
  721. stars = stars - 10
  722. original_quality = original_quality - 10
  723. if level >= 12:
  724. quality = 5
  725. elif level >= 9:
  726. quality = 5
  727. elif level >= 6:
  728. quality = 3
  729. elif level >= 3:
  730. quality = 2
  731. else:
  732. quality = 1
  733. if original_quality > quality:
  734. quality = original_quality
  735. efficiency = 0
  736. max_efficiency = 0
  737. main_stat = rune["pri_eff"][0]
  738. main_stat_value = rune["pri_eff"][1]
  739. if rune["prefix_eff"][0] > 0:
  740. innate_stat = rune["prefix_eff"][0]
  741. innate_stat_value = rune["prefix_eff"][1]
  742. else:
  743. innate_stat = None
  744. innate_stat_value = 0
  745. if len(rune["sec_eff"]) > 0:
  746. substat_1 = rune["sec_eff"][0][0]
  747. substat_1_value = rune["sec_eff"][0][1]
  748. substat_1_enchant = rune["sec_eff"][0][2]
  749. substat_1_grind = rune["sec_eff"][0][3]
  750. else:
  751. substat_1 = None
  752. substat_1_value = 0
  753. substat_1_enchant = 0
  754. substat_1_grind = 0
  755. if len(rune["sec_eff"]) > 1:
  756. substat_2 = rune["sec_eff"][1][0]
  757. substat_2_value = rune["sec_eff"][1][1]
  758. substat_2_enchant = rune["sec_eff"][1][2]
  759. substat_2_grind = rune["sec_eff"][1][3]
  760. else:
  761. substat_2 = None
  762. substat_2_value = 0
  763. substat_2_enchant = 0
  764. substat_2_grind = 0
  765. if len(rune["sec_eff"]) > 2:
  766. substat_3 = rune["sec_eff"][2][0]
  767. substat_3_value = rune["sec_eff"][2][1]
  768. substat_3_enchant = rune["sec_eff"][2][2]
  769. substat_3_grind = rune["sec_eff"][2][3]
  770. else:
  771. substat_3 = None
  772. substat_3_value = 0
  773. substat_3_enchant = 0
  774. substat_3_grind = 0
  775. if len(rune["sec_eff"]) > 3:
  776. substat_4 = rune["sec_eff"][3][0]
  777. substat_4_value = rune["sec_eff"][3][1]
  778. substat_4_enchant = rune["sec_eff"][3][2]
  779. substat_4_grind = rune["sec_eff"][3][3]
  780. else:
  781. substat_4 = None
  782. substat_4_value = 0
  783. substat_4_enchant = 0
  784. substat_4_grind = 0
  785. # Calculate efficiences
  786. efficiency = 0
  787. substats = []
  788. efficiency += float(MAIN_STAT_VALUES[main_stat][stars][15]) / float(MAIN_STAT_VALUES[main_stat][6][15])
  789. if innate_stat is not None:
  790. efficiency += innate_stat_value / float(SUBSTAT_INCREMENTS[innate_stat][6] * 5)
  791. if substat_1 is not None:
  792. substats.append(substat_1)
  793. efficiency += substat_1_value / float(SUBSTAT_INCREMENTS[substat_1][6] * 5)
  794. if substat_2 is not None:
  795. substats.append(substat_2)
  796. efficiency += substat_2_value / float(SUBSTAT_INCREMENTS[substat_2][6] * 5)
  797. if substat_3 is not None:
  798. substats.append(substat_3)
  799. efficiency += substat_3_value / float(SUBSTAT_INCREMENTS[substat_3][6] * 5)
  800. if substat_4 is not None:
  801. substats.append(substat_4)
  802. efficiency += substat_4_value / float(SUBSTAT_INCREMENTS[substat_4][6] * 5)
  803. efficiency = efficiency / 2.8 * 100
  804. max_efficiency = get_max_efficiency(substats, efficiency, level, stars, original_quality)
  805. if efficiency > 100:
  806. efficiency = 100;
  807. if max_efficiency > 100:
  808. max_efficiency = 100;
  809. # TODO: Locked status not in JSO file.
  810. locked = 0
  811. 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))
  812. db.commit()
  813. """
  814. Parses artifact data (table artifact).
  815. :param db: Sqlite database connection.
  816. :param data: Data in json format.
  817. """
  818. def parseArtifacts(db, data):
  819. print("Parsing artifacts...")
  820. uid = data["wizard_info"]["wizard_id"]
  821. # Unequipped artifacts
  822. for artifact in data["artifacts"]:
  823. id = artifact["rid"]
  824. assigned_to = None
  825. type = artifact["type"]
  826. attribute = artifact["attribute"]
  827. if attribute == 0:
  828. attribute = None
  829. archetype = artifact["unit_style"]
  830. if archetype == 0:
  831. archetype = None
  832. level = artifact["level"]
  833. quality = artifact["rank"]
  834. original_quality = artifact["natural_rank"]
  835. # TODO: Vaue not in JSON file. Can it be calculated?
  836. value = 0;
  837. main_stat = artifact["pri_effect"][0]
  838. main_stat_value = artifact["pri_effect"][1]
  839. locked = artifact["locked"]
  840. if len(artifact["sec_effects"]) > 0:
  841. effect_1 = artifact["sec_effects"][0][0]
  842. effect_1_value = artifact["sec_effects"][0][1]
  843. effect_1_enchant = artifact["sec_effects"][0][2]
  844. effect_1_grind = artifact["sec_effects"][0][3]
  845. else:
  846. effect_1 = None
  847. effect_1_value = 0
  848. effect_1_enchant = 0
  849. effect_1_grind = 0
  850. if len(artifact["sec_effects"]) > 1:
  851. effect_2 = artifact["sec_effects"][1][0]
  852. effect_2_value = artifact["sec_effects"][1][1]
  853. effect_2_enchant = artifact["sec_effects"][1][2]
  854. effect_2_grind = artifact["sec_effects"][1][3]
  855. else:
  856. effect_2 = None
  857. effect_2_value = 0
  858. effect_2_enchant = 0
  859. effect_2_grind = 0
  860. if len(artifact["sec_effects"]) > 2:
  861. effect_3 = artifact["sec_effects"][2][0]
  862. effect_3_value = artifact["sec_effects"][2][1]
  863. effect_3_enchant = artifact["sec_effects"][2][2]
  864. effect_3_grind = artifact["sec_effects"][2][3]
  865. else:
  866. effect_3 = None
  867. effect_3_value = 0
  868. effect_3_enchant = 0
  869. effect_3_grind = 0
  870. if len(artifact["sec_effects"]) > 3:
  871. effect_4 = artifact["sec_effects"][3][0]
  872. effect_4_value = artifact["sec_effects"][3][1]
  873. effect_4_enchant = artifact["sec_effects"][3][2]
  874. effect_4_grind = artifact["sec_effects"][3][3]
  875. else:
  876. effect_4 = None
  877. effect_4_value = 0
  878. effect_4_enchant = 0
  879. effect_4_grind = 0
  880. # TODO: efficiences
  881. efficiency = 0
  882. max_efficiency = 0
  883. 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))
  884. # Equipped artifacts
  885. for mon in data["unit_list"]:
  886. for artifact in mon["artifacts"]:
  887. id = artifact["rid"]
  888. assigned_to = artifact["occupied_id"]
  889. if assigned_to == 0:
  890. assigned_to = None
  891. type = artifact["type"]
  892. attribute = artifact["attribute"]
  893. if attribute == 0:
  894. attribute = None
  895. archetype = artifact["unit_style"]
  896. if archetype == 0:
  897. archetype = None
  898. level = artifact["level"]
  899. quality = artifact["rank"]
  900. original_quality = artifact["natural_rank"]
  901. # TODO: Vaue not in JSON file. Can it be calculated?
  902. value = 0;
  903. main_stat = artifact["pri_effect"][0]
  904. main_stat_value = artifact["pri_effect"][1]
  905. locked = artifact["locked"]
  906. if len(artifact["sec_effects"]) > 0:
  907. effect_1 = artifact["sec_effects"][0][0]
  908. effect_1_value = artifact["sec_effects"][0][1]
  909. effect_1_enchant = artifact["sec_effects"][0][2]
  910. effect_1_grind = artifact["sec_effects"][0][3]
  911. else:
  912. effect_1 = None
  913. effect_1_value = 0
  914. effect_1_enchant = 0
  915. effect_1_grind = 0
  916. if len(artifact["sec_effects"]) > 1:
  917. effect_2 = artifact["sec_effects"][1][0]
  918. effect_2_value = artifact["sec_effects"][1][1]
  919. effect_2_enchant = artifact["sec_effects"][1][2]
  920. effect_2_grind = artifact["sec_effects"][1][3]
  921. else:
  922. effect_2 = None
  923. effect_2_value = 0
  924. effect_2_enchant = 0
  925. effect_2_grind = 0
  926. if len(artifact["sec_effects"]) > 2:
  927. effect_3 = artifact["sec_effects"][2][0]
  928. effect_3_value = artifact["sec_effects"][2][1]
  929. effect_3_enchant = artifact["sec_effects"][2][2]
  930. effect_3_grind = artifact["sec_effects"][2][3]
  931. else:
  932. effect_3 = None
  933. effect_3_value = 0
  934. effect_3_enchant = 0
  935. effect_3_grind = 0
  936. if len(artifact["sec_effects"]) > 3:
  937. effect_4 = artifact["sec_effects"][3][0]
  938. effect_4_value = artifact["sec_effects"][3][1]
  939. effect_4_enchant = artifact["sec_effects"][3][2]
  940. effect_4_grind = artifact["sec_effects"][3][3]
  941. else:
  942. effect_4 = None
  943. effect_4_value = 0
  944. effect_4_enchant = 0
  945. effect_4_grind = 0
  946. # TODO: efficiences
  947. efficiency = 0
  948. max_efficiency = 0
  949. 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))
  950. """
  951. calculates the max efficiency of a rune.
  952. :param substats: Array of substat types, dont include empty ones.
  953. :param efficiency: Current rune efficiency.
  954. :param level: Current rune level.
  955. :param stars: Rune stars.
  956. :param quality: Rune original quality.
  957. :return Max. efficiency.
  958. """
  959. def get_max_efficiency(substats, efficiency, level, stars, quality):
  960. STAT_HP = 1
  961. STAT_HP_PCT = 2
  962. STAT_ATK = 3
  963. STAT_ATK_PCT = 4
  964. STAT_DEF = 5
  965. STAT_DEF_PCT = 6
  966. STAT_SPD = 8
  967. STAT_CRIT_RATE_PCT = 9
  968. STAT_CRIT_DMG_PCT = 10
  969. STAT_RESIST_PCT = 11
  970. STAT_ACCURACY_PCT = 12
  971. SUBSTAT_INCREMENTS = {
  972. # [stat][stars]: value
  973. STAT_HP: {
  974. 1: 60,
  975. 2: 105,
  976. 3: 165,
  977. 4: 225,
  978. 5: 300,
  979. 6: 375,
  980. },
  981. STAT_HP_PCT: {
  982. 1: 2,
  983. 2: 3,
  984. 3: 5,
  985. 4: 6,
  986. 5: 7,
  987. 6: 8,
  988. },
  989. STAT_ATK: {
  990. 1: 4,
  991. 2: 5,
  992. 3: 8,
  993. 4: 10,
  994. 5: 15,
  995. 6: 20,
  996. },
  997. STAT_ATK_PCT: {
  998. 1: 2,
  999. 2: 3,
  1000. 3: 5,
  1001. 4: 6,
  1002. 5: 7,
  1003. 6: 8,
  1004. },
  1005. STAT_DEF: {
  1006. 1: 4,
  1007. 2: 5,
  1008. 3: 8,
  1009. 4: 10,
  1010. 5: 15,
  1011. 6: 20,
  1012. },
  1013. STAT_DEF_PCT: {
  1014. 1: 2,
  1015. 2: 3,
  1016. 3: 5,
  1017. 4: 6,
  1018. 5: 7,
  1019. 6: 8,
  1020. },
  1021. STAT_SPD: {
  1022. 1: 1,
  1023. 2: 2,
  1024. 3: 3,
  1025. 4: 4,
  1026. 5: 5,
  1027. 6: 6,
  1028. },
  1029. STAT_CRIT_RATE_PCT: {
  1030. 1: 1,
  1031. 2: 2,
  1032. 3: 3,
  1033. 4: 4,
  1034. 5: 5,
  1035. 6: 6,
  1036. },
  1037. STAT_CRIT_DMG_PCT: {
  1038. 1: 2,
  1039. 2: 3,
  1040. 3: 4,
  1041. 4: 5,
  1042. 5: 6,
  1043. 6: 7,
  1044. },
  1045. STAT_RESIST_PCT: {
  1046. 1: 2,
  1047. 2: 3,
  1048. 3: 5,
  1049. 4: 6,
  1050. 5: 7,
  1051. 6: 8,
  1052. },
  1053. STAT_ACCURACY_PCT: {
  1054. 1: 2,
  1055. 2: 3,
  1056. 3: 5,
  1057. 4: 6,
  1058. 5: 7,
  1059. 6: 8,
  1060. },
  1061. }
  1062. UPGRADE_VALUES = {
  1063. rune_type: {
  1064. stars: value/level_data[6]
  1065. for stars, value in level_data.items()
  1066. }
  1067. for rune_type, level_data in SUBSTAT_INCREMENTS.items()
  1068. }
  1069. #substat_upgrades_remaining = (4 - math.floor((min(level, 12) / 3))) - (3 - quality)
  1070. substat_upgrades_remaining = (4 - math.floor((min(level, 12) / 3))) - max((3 - quality), 0)
  1071. new_stats = max(min(4 - len(substats), substat_upgrades_remaining), 0)
  1072. old_stats = substat_upgrades_remaining - new_stats
  1073. if old_stats > 0:
  1074. # we can repeatedly upgrade the most value of the existing stats
  1075. best_stat = max(
  1076. 0, # ensure max() doesn't error if we only have one stat
  1077. *[UPGRADE_VALUES[stat][stars] for stat in substats]
  1078. )
  1079. efficiency += best_stat * old_stats * 0.2 / 2.8 * 100
  1080. if new_stats:
  1081. # add the top N stats
  1082. available_upgrades = sorted(
  1083. [
  1084. upgrade_value[stars]
  1085. for stat, upgrade_value in UPGRADE_VALUES.items()
  1086. if stat not in substats
  1087. ],
  1088. reverse=True
  1089. )
  1090. efficiency += sum(available_upgrades[:new_stats]) * 0.2 / 2.8 * 100
  1091. return efficiency
  1092. """
  1093. Parses rune craft item data (table rune_craft).
  1094. :param db: Sqlite database connection.
  1095. :param data: Data in json format.
  1096. """
  1097. def parseRuneCraft(db, data):
  1098. print("Parsing rune craft itmes...")
  1099. uid = data["wizard_info"]["wizard_id"]
  1100. for item in data["rune_craft_item_list"]:
  1101. id = item["craft_item_id"]
  1102. type = item["craft_type"]
  1103. value = item["sell_value"]
  1104. amount = str(item["amount"])
  1105. """
  1106. info : 5 or 6 digit number: RRSSQ
  1107. RR: Rune
  1108. SS: Stat
  1109. Q: Quality
  1110. """
  1111. info = str(item["craft_type_id"])
  1112. quality = int(info[-1:])
  1113. stat = int(info[-4:-2])
  1114. rune = int(info[:-4])
  1115. insert(db, "rune_craft", (uid, id, type, quality, rune, stat, value, amount))
  1116. """
  1117. Parses guild data (tables guild, guild_member).
  1118. :param db: Sqlite database connection.
  1119. :param data: Data in json format.
  1120. """
  1121. def parseGuild(db, data):
  1122. print("Parsing guild...")
  1123. cursor = db.cursor()
  1124. if (data["guild"]["guild_info"] == None):
  1125. # No guild
  1126. return
  1127. if len(data["guild"]["guild_info"]) < 1:
  1128. return
  1129. guild = data["guild"]["guild_info"]
  1130. id = guild["guild_id"]
  1131. name = guild["name"]
  1132. level = guild["level"]
  1133. experience = guild["experience"]
  1134. recruiting = guild["recruit_status"]
  1135. members = guild["member_now"]
  1136. leader = guild["master_wizard_id"]
  1137. comment = guild["comment"]
  1138. notice = guild["notice"]
  1139. # Delete selected guild before inserting
  1140. cursor.execute("DELETE FROM guild WHERE id = ?", [id])
  1141. cursor.execute("DELETE FROM guild_member WHERE guild = ?", [id])
  1142. db.commit()
  1143. insert(db, "guild", (id, name, level, experience, recruiting, members, leader, comment, notice))
  1144. # Single quates ahead, dirty fix
  1145. for k, member in data["guild"]["guild_members"].items():
  1146. m = json.loads(str(member).replace("'", '"'))
  1147. id = m["wizard_id"]
  1148. guild = member["guild_id"]
  1149. grade = member["grade"]
  1150. name = member["wizard_name"]
  1151. level = member["wizard_level"]
  1152. rating = member["rating_id"]
  1153. arena_score = member["arena_score"]
  1154. joined = member["join_timestamp"]
  1155. last_login = member["last_login_timestamp"]
  1156. in_war = 0 # Checked later
  1157. has_defense = 0 # Checked later
  1158. insert(db, "guild_member", (id, guild, grade, name, level, rating, arena_score, joined, last_login, in_war, has_defense))
  1159. for war in data["guildwar_member_list"]:
  1160. cursor.execute("UPDATE guild_member SET in_war = 1 WHERE guild = ? AND id = ?;", (war["guild_id"], war["wizard_id"]))
  1161. for defense in data["guild_member_defense_list"]:
  1162. if len(defense["unit_list"]) > 0:
  1163. cursor.execute("UPDATE guild_member SET has_defense = 1 WHERE id = ?", [defense["wizard_id"]])
  1164. db.commit()
  1165. cursor.close()
  1166. """
  1167. Deletes teams whose members no longer exists.
  1168. :param db: Sqlite database connection.
  1169. """
  1170. def reconfigureTeams(db):
  1171. print("Fixing teams...")
  1172. uid = data["wizard_info"]["wizard_id"]
  1173. cursor = db.cursor()
  1174. 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))
  1175. cursor.execute("DELETE FROM team_unit WHERE unit NOT IN (SELECT DISTINCT id FROM unit) OR team NOT IN (SELECT DISTINCT id FROM team);")
  1176. db.commit()
  1177. cursor.close()
  1178. """
  1179. Begin script
  1180. """
  1181. try:
  1182. data = readData()
  1183. except Exception as e:
  1184. print("Error reading data: " + str(e))
  1185. sys.exit(400)
  1186. try:
  1187. key = readKey()
  1188. except Exception as e:
  1189. print("Error fetching API key: " + str(e))
  1190. sys.exit(400)
  1191. try:
  1192. db = openDatabase()
  1193. except Exception as e:
  1194. print("Error opening database: " + str(e))
  1195. sys.exit(500)
  1196. if verifyKey(db, data, key) == False:
  1197. print("Invalid API KEY...")
  1198. sys.exit(401)
  1199. else:
  1200. try:
  1201. clearData(db, data)
  1202. except Exception as e:
  1203. print("Error clearing data: " + str(e))
  1204. sys.exit(500)
  1205. try:
  1206. parsePlayer(db, data)
  1207. except Exception as e:
  1208. print("Error parsing player data: " + str(e))
  1209. sys.exit(400)
  1210. try:
  1211. parseScenarios(db, data)
  1212. except Exception as e:
  1213. print("Error parsing scenario data: " + str(e))
  1214. sys.exit(400)
  1215. try:
  1216. parseDefense(db, data)
  1217. except Exception as e:
  1218. print("Error parsing defense data: " + str(e))
  1219. sys.exit(400)
  1220. try:
  1221. parseGWDefense(db, data)
  1222. except Exception as e:
  1223. print("Error parsing guild war defense data: " + str(e))
  1224. sys.exit(400)
  1225. try:
  1226. parseBuildings(db, data)
  1227. except Exception as e:
  1228. print("Error parsing building data: " + str(e))
  1229. sys.exit(400)
  1230. try:
  1231. parseDecorations(db, data)
  1232. except Exception as e:
  1233. print("Error parsing decoration data: " + str(e))
  1234. sys.exit(400)
  1235. # TODO homunculus_skill_list
  1236. try:
  1237. parseUnits(db, data)
  1238. except Exception as e:
  1239. print("Error parsing unit data: " + str(e))
  1240. sys.exit(400)
  1241. try:
  1242. parseSummonSpecial(db, data)
  1243. except Exception as e:
  1244. print("Error parsing special summon data: " + str(e))
  1245. sys.exit(400)
  1246. try:
  1247. parseInventory(db, data)
  1248. except Exception as e:
  1249. print("Error parsing inventory data: " + str(e))
  1250. sys.exit(400)
  1251. try:
  1252. parseRunes(db, data)
  1253. except Exception as e:
  1254. print("Error parsing rune data: " + str(e))
  1255. sys.exit(400)
  1256. try:
  1257. parseArtifacts(db, data)
  1258. except Exception as e:
  1259. print("Error parsing artifact data: " + str(e))
  1260. sys.exit(400)
  1261. try:
  1262. parseRuneCraft(db, data)
  1263. except Exception as e:
  1264. print("Error parsing rune craft data: " + str(e))
  1265. sys.exit(400)
  1266. try:
  1267. parseGuild(db, data)
  1268. except Exception as e:
  1269. print("Error parsing guild data: " + str(e))
  1270. sys.exit(400)
  1271. try:
  1272. reconfigureTeams(db)
  1273. except Exception as e:
  1274. print("Error reconfiguring teams: " + str(e))
  1275. sys.exit(400)
  1276. try:
  1277. closeDatabase(db)
  1278. except Exception as e:
  1279. print("Error closing database: " + str(e))
  1280. # No error
  1281. sys.exit(200);