From e6b4ecdaf701fb85920399b644eb88292057c08c Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 27 Jan 2017 13:37:51 -0800 Subject: [PATCH 01/18] Additional cleanup for orphaned records --- eos/db/saveddata/databaseRepair.py | 39 ++++++++++++++++++++++++++++++ service/prefetch.py | 2 ++ 2 files changed, 41 insertions(+) diff --git a/eos/db/saveddata/databaseRepair.py b/eos/db/saveddata/databaseRepair.py index e9685381a..53f6ae29f 100644 --- a/eos/db/saveddata/databaseRepair.py +++ b/eos/db/saveddata/databaseRepair.py @@ -160,3 +160,42 @@ class DatabaseCleanup: query = "UPDATE 'targetResists' SET 'name' = 'Unknown' WHERE name IS NULL OR name = ''" delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + + @staticmethod + def OrphanedFitIDItemID(saveddata_engine): + # Orphaned items that are missing the fit ID or item ID. + # See issue #954 + for table in ['drones', 'cargo', 'fighters', 'modules']: + logger.debug("Running database cleanup for orphaned %s items.", table) + query = "SELECT COUNT(*) AS num FROM " + table + " WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num']: + query = "DELETE FROM " + table + " WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + + @staticmethod + def NullDamageTargetPatternValues(saveddata_engine): + # Find patterns that have null values + # See issue #954 + for profileType in ['damagePatterns', 'targetResists']: + for damageType in ['em', 'thermal', 'kinetic', 'explosive']: + logger.debug("Running database cleanup for null %s values. (%s)", profileType, damageType) + query = "SELECT COUNT(*) AS num FROM " + profileType + " WHERE " + damageType + "Amount IS NULL OR " + damageType + "Amount = ''" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num']: + query = "UPDATE '" + profileType + "' SET '" + damageType + "Amount' = '0' WHERE " + damageType + "Amount IS NULL OR emAmount = ''" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) diff --git a/service/prefetch.py b/service/prefetch.py index 46f9cf5f5..9990fea10 100644 --- a/service/prefetch.py +++ b/service/prefetch.py @@ -67,6 +67,8 @@ if os.path.isfile(config.saveDB): database_cleanup_instance.OrphanedCharacterSkills(eos.db.saveddata_engine) database_cleanup_instance.OrphanedFitCharacterIDs(eos.db.saveddata_engine) database_cleanup_instance.OrphanedFitDamagePatterns(eos.db.saveddata_engine) + database_cleanup_instance.OrphanedFitIDItemID(eos.db.saveddata_engine) + database_cleanup_instance.NullDamageTargetPatternValues(eos.db.saveddata_engine) logging.debug("Completed database validation.") else: From fc99d6f0a6be36de72dbb0743655cf23a3bd2057 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 27 Jan 2017 13:46:20 -0800 Subject: [PATCH 02/18] catch duplicate selected ammo --- eos/db/saveddata/databaseRepair.py | 18 ++++++++++++++++++ service/prefetch.py | 1 + 2 files changed, 19 insertions(+) diff --git a/eos/db/saveddata/databaseRepair.py b/eos/db/saveddata/databaseRepair.py index 53f6ae29f..074730fe0 100644 --- a/eos/db/saveddata/databaseRepair.py +++ b/eos/db/saveddata/databaseRepair.py @@ -199,3 +199,21 @@ class DatabaseCleanup: query = "UPDATE '" + profileType + "' SET '" + damageType + "Amount' = '0' WHERE " + damageType + "Amount IS NULL OR emAmount = ''" delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + + @staticmethod + def DuplicateSelectedAmmoName(saveddata_engine): + # Orphaned items that are missing the fit ID or item ID. + # See issue #954 + logger.debug("Running database cleanup for duplicated selected ammo profiles.") + query = "SELECT COUNT(*) AS num FROM damagePatterns WHERE name = 'Selected Ammo'" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num'] > 1: + query = "DELETE FROM damagePatterns WHERE name = 'Selected Ammo'" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) diff --git a/service/prefetch.py b/service/prefetch.py index 9990fea10..f04220b3c 100644 --- a/service/prefetch.py +++ b/service/prefetch.py @@ -69,6 +69,7 @@ if os.path.isfile(config.saveDB): database_cleanup_instance.OrphanedFitDamagePatterns(eos.db.saveddata_engine) database_cleanup_instance.OrphanedFitIDItemID(eos.db.saveddata_engine) database_cleanup_instance.NullDamageTargetPatternValues(eos.db.saveddata_engine) + database_cleanup_instance.DuplicateSelectedAmmoName(eos.db.saveddata_engine) logging.debug("Completed database validation.") else: From 200023234cf75081d3f12859963867d15ea49848 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 27 Jan 2017 14:49:30 -0800 Subject: [PATCH 03/18] Give modules the special snowflake experience Modules can legitimately have a null item value. So don't catch null or '', only 0's (which would be an invalid item ID). --- eos/db/saveddata/databaseRepair.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/eos/db/saveddata/databaseRepair.py b/eos/db/saveddata/databaseRepair.py index 074730fe0..3a48cc40a 100644 --- a/eos/db/saveddata/databaseRepair.py +++ b/eos/db/saveddata/databaseRepair.py @@ -165,7 +165,7 @@ class DatabaseCleanup: def OrphanedFitIDItemID(saveddata_engine): # Orphaned items that are missing the fit ID or item ID. # See issue #954 - for table in ['drones', 'cargo', 'fighters', 'modules']: + for table in ['drones', 'cargo', 'fighters']: logger.debug("Running database cleanup for orphaned %s items.", table) query = "SELECT COUNT(*) AS num FROM " + table + " WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) @@ -180,6 +180,21 @@ class DatabaseCleanup: delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + for table in ['modules']: + logger.debug("Running database cleanup for orphaned %s items.", table) + query = "SELECT COUNT(*) AS num FROM " + table + " WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + + if results is None: + return + + row = results.first() + + if row and row['num']: + query = "DELETE FROM " + table + " WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + @staticmethod def NullDamageTargetPatternValues(saveddata_engine): # Find patterns that have null values From 88125634d23de0ea08b77e0ea53a994aa5a83e5f Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sat, 28 Jan 2017 21:47:58 -0800 Subject: [PATCH 04/18] Add extra info for misc column for fueled boosters --- eos/gamedata.py | 6 +++- gui/builtinViewColumns/misc.py | 53 ++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/eos/gamedata.py b/eos/gamedata.py index e4a4afa1c..a23ed0d8a 100644 --- a/eos/gamedata.py +++ b/eos/gamedata.py @@ -243,9 +243,13 @@ class Item(EqBase): return self.__attributes - def getAttribute(self, key): + def getAttribute(self, key, default=None): if key in self.attributes: return self.attributes[key].value + elif default: + return default + else: + return None def isType(self, type): for effect in self.effects.itervalues(): diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 080614a3b..4ffa64405 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -450,30 +450,71 @@ class Miscellanea(ViewColumn): return text, item.name else: return "", None - elif itemGroup in ("Ancillary Armor Repairer", "Ancillary Shield Booster"): + elif itemGroup in ( + "Ancillary Armor Repairer", + "Ancillary Shield Booster", + "Capacitor Booster", + "Ancillary Remote Armor Repairer", + "Ancillary Remote Shield Booster", + ): + if "Armor" in itemGroup or "Shield" in itemGroup: + boosted_attribute = "HP" + elif "Capacitor" in itemGroup: + boosted_attribute = "Cap" + else: + boosted_attribute = None + hp = stuff.hpBeforeReload cycles = stuff.numShots cycleTime = stuff.rawCycleTime + + if boosted_attribute == "Cap": + if hp is None: + local_booster = stuff.charge.getAttribute("capacitorBonus",0) + hp = max(local_booster, 0) * cycles + reload_time = 10 + elif boosted_attribute == "HP": + if hp is None: + armor_repairer = item.getAttribute("armorDamageAmount", None) + shield_booster = item.getAttribute("shieldBonus", None) + hp = max(armor_repairer, shield_booster, 0) + reload_time = item.getAttribute("reloadTime", 0) / 1000 + else: + reload_time = 0 + if not hp or not cycleTime or not cycles: return "", None + fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit()) ehpTotal = fit.ehp hpTotal = fit.hp useEhp = self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective - tooltip = "HP restored over duration using charges" - if useEhp: - if itemGroup == "Ancillary Armor Repairer": + tooltip = "{0} restored over duration using charges (plus reload)".format(boosted_attribute) + + if useEhp and boosted_attribute == "HP" and "Remote" not in itemGroup: + if "Ancillary Armor Repairer" in itemGroup: hpRatio = ehpTotal["armor"] / hpTotal["armor"] else: hpRatio = ehpTotal["shield"] / hpTotal["shield"] tooltip = "E{0}".format(tooltip) else: hpRatio = 1 - if itemGroup == "Ancillary Armor Repairer": + + if ("Ancillary" and "Armor") in itemGroup: hpRatio *= 3 + + ehp = hp * hpRatio + duration = cycles * cycleTime / 1000 - text = "{0} / {1}s".format(formatAmount(ehp, 3, 0, 9), formatAmount(duration, 3, 0, 3)) + for number_of_cycles in {5, 10, 25}: + tooltip = "{0}\n{1} charges lasts {2} seconds ({3} cycles)".format( + tooltip, + formatAmount(number_of_cycles*cycles, 3, 0, 3), + formatAmount((duration+reload_time)*number_of_cycles, 3, 0, 3), + formatAmount(number_of_cycles, 3, 0, 3) + ) + text = "{0} / {1}s (+{2}s)".format(formatAmount(ehp, 3, 0, 9), formatAmount(duration, 3, 0, 3), formatAmount(reload_time, 3, 0, 3)) return text, tooltip elif itemGroup == "Armor Resistance Shift Hardener": From 34c69cf10f883775579b5ced583ea9331d806498 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sat, 28 Jan 2017 21:56:03 -0800 Subject: [PATCH 05/18] Some pep8 stuff --- gui/builtinViewColumns/misc.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 4ffa64405..5a27bab55 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -470,7 +470,7 @@ class Miscellanea(ViewColumn): if boosted_attribute == "Cap": if hp is None: - local_booster = stuff.charge.getAttribute("capacitorBonus",0) + local_booster = stuff.charge.getAttribute("capacitorBonus", 0) hp = max(local_booster, 0) * cycles reload_time = 10 elif boosted_attribute == "HP": @@ -503,7 +503,6 @@ class Miscellanea(ViewColumn): if ("Ancillary" and "Armor") in itemGroup: hpRatio *= 3 - ehp = hp * hpRatio duration = cycles * cycleTime / 1000 @@ -514,7 +513,11 @@ class Miscellanea(ViewColumn): formatAmount((duration+reload_time)*number_of_cycles, 3, 0, 3), formatAmount(number_of_cycles, 3, 0, 3) ) - text = "{0} / {1}s (+{2}s)".format(formatAmount(ehp, 3, 0, 9), formatAmount(duration, 3, 0, 3), formatAmount(reload_time, 3, 0, 3)) + text = "{0} / {1}s (+{2}s)".format( + formatAmount(ehp, 3, 0, 9), + formatAmount(duration, 3, 0, 3), + formatAmount(reload_time, 3, 0, 3) + ) return text, tooltip elif itemGroup == "Armor Resistance Shift Hardener": From 1a0ac7bb352475b840e6194d70fcf06452cb6edd Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 29 Jan 2017 00:16:15 -0800 Subject: [PATCH 06/18] Allow default values to be passed in for modified attributes --- eos/gamedata.py | 4 +--- eos/modifiedAttributeDict.py | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/eos/gamedata.py b/eos/gamedata.py index a23ed0d8a..10317dab2 100644 --- a/eos/gamedata.py +++ b/eos/gamedata.py @@ -246,10 +246,8 @@ class Item(EqBase): def getAttribute(self, key, default=None): if key in self.attributes: return self.attributes[key].value - elif default: - return default else: - return None + return default def isType(self, type): for effect in self.effects.itervalues(): diff --git a/eos/modifiedAttributeDict.py b/eos/modifiedAttributeDict.py index d060eb425..e558dc64d 100644 --- a/eos/modifiedAttributeDict.py +++ b/eos/modifiedAttributeDict.py @@ -25,19 +25,19 @@ cappingAttrKeyCache = {} class ItemAttrShortcut(object): - def getModifiedItemAttr(self, key): + def getModifiedItemAttr(self, key, default=None): if key in self.itemModifiedAttributes: return self.itemModifiedAttributes[key] else: - return None + return default class ChargeAttrShortcut(object): - def getModifiedChargeAttr(self, key): + def getModifiedChargeAttr(self, key, default=None): if key in self.chargeModifiedAttributes: return self.chargeModifiedAttributes[key] else: - return None + return default class ModifiedAttributeDict(collections.MutableMapping): From c567ee2c08ce644dcec5dbd2eefe9483bf837df3 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 29 Jan 2017 00:16:32 -0800 Subject: [PATCH 07/18] Clean up logic and generally make purdier --- gui/builtinViewColumns/misc.py | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 5a27bab55..87e4ea9db 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -459,28 +459,23 @@ class Miscellanea(ViewColumn): ): if "Armor" in itemGroup or "Shield" in itemGroup: boosted_attribute = "HP" + reload_time = item.getAttribute("reloadTime", 0) / 1000 elif "Capacitor" in itemGroup: boosted_attribute = "Cap" + reload_time = 10 else: - boosted_attribute = None + boosted_attribute = "" + reload_time = 0 - hp = stuff.hpBeforeReload cycles = stuff.numShots cycleTime = stuff.rawCycleTime - if boosted_attribute == "Cap": - if hp is None: - local_booster = stuff.charge.getAttribute("capacitorBonus", 0) - hp = max(local_booster, 0) * cycles - reload_time = 10 - elif boosted_attribute == "HP": - if hp is None: - armor_repairer = item.getAttribute("armorDamageAmount", None) - shield_booster = item.getAttribute("shieldBonus", None) - hp = max(armor_repairer, shield_booster, 0) - reload_time = item.getAttribute("reloadTime", 0) / 1000 - else: - reload_time = 0 + # Get HP or boosted amount + stuff_hp = stuff.hpBeforeReload + armor_hp = stuff.getModifiedItemAttr("armorDamageAmount", 0) + capacitor_hp = stuff.charge.getModifiedChargeAttr("capacitorBonus", 0) + shield_hp = stuff.getModifiedItemAttr("shieldBonus", 0) + hp = max(stuff_hp, armor_hp * cycles, capacitor_hp * cycles, shield_hp * cycles, 0) if not hp or not cycleTime or not cycles: return "", None From f111c49cc62378576dad7c22d5cd66c52d25219f Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 29 Jan 2017 00:25:42 -0800 Subject: [PATCH 08/18] wrap getting attribute in at try/except Catches if there's an attribute error. Useful when we try and get an attribute when the object doesn't even have it. --- gui/builtinViewColumns/misc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 87e4ea9db..897e6a0ab 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -496,7 +496,7 @@ class Miscellanea(ViewColumn): hpRatio = 1 if ("Ancillary" and "Armor") in itemGroup: - hpRatio *= 3 + hpRatio *= stuff.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) ehp = hp * hpRatio @@ -508,6 +508,7 @@ class Miscellanea(ViewColumn): formatAmount((duration+reload_time)*number_of_cycles, 3, 0, 3), formatAmount(number_of_cycles, 3, 0, 3) ) + text = "{0} / {1}s (+{2}s)".format( formatAmount(ehp, 3, 0, 9), formatAmount(duration, 3, 0, 3), From e524197a4d59bc8575dbdd7405c2f885e87b5f1b Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 29 Jan 2017 00:25:55 -0800 Subject: [PATCH 09/18] Revert "wrap getting attribute in at try/except" This reverts commit f111c49cc62378576dad7c22d5cd66c52d25219f. --- gui/builtinViewColumns/misc.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 897e6a0ab..87e4ea9db 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -496,7 +496,7 @@ class Miscellanea(ViewColumn): hpRatio = 1 if ("Ancillary" and "Armor") in itemGroup: - hpRatio *= stuff.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) + hpRatio *= 3 ehp = hp * hpRatio @@ -508,7 +508,6 @@ class Miscellanea(ViewColumn): formatAmount((duration+reload_time)*number_of_cycles, 3, 0, 3), formatAmount(number_of_cycles, 3, 0, 3) ) - text = "{0} / {1}s (+{2}s)".format( formatAmount(ehp, 3, 0, 9), formatAmount(duration, 3, 0, 3), From 1ebd54b2821ed3d095ddef11c891190c979f1f32 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 29 Jan 2017 00:27:45 -0800 Subject: [PATCH 10/18] Wrap getting attribute data in a try/except Useful for when we try to get an sub-attribute on an object where the attribute doesn't exist. Now returns the default value. --- eos/gamedata.py | 9 ++++++--- eos/modifiedAttributeDict.py | 18 ++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/eos/gamedata.py b/eos/gamedata.py index 10317dab2..fca14263a 100644 --- a/eos/gamedata.py +++ b/eos/gamedata.py @@ -244,9 +244,12 @@ class Item(EqBase): return self.__attributes def getAttribute(self, key, default=None): - if key in self.attributes: - return self.attributes[key].value - else: + try: + if key in self.attributes: + return self.attributes[key].value + else: + return default + except AttributeError: return default def isType(self, type): diff --git a/eos/modifiedAttributeDict.py b/eos/modifiedAttributeDict.py index e558dc64d..417a459c2 100644 --- a/eos/modifiedAttributeDict.py +++ b/eos/modifiedAttributeDict.py @@ -26,17 +26,23 @@ cappingAttrKeyCache = {} class ItemAttrShortcut(object): def getModifiedItemAttr(self, key, default=None): - if key in self.itemModifiedAttributes: - return self.itemModifiedAttributes[key] - else: + try: + if key in self.itemModifiedAttributes: + return self.itemModifiedAttributes[key] + else: + return default + except AttributeError: return default class ChargeAttrShortcut(object): def getModifiedChargeAttr(self, key, default=None): - if key in self.chargeModifiedAttributes: - return self.chargeModifiedAttributes[key] - else: + try: + if key in self.chargeModifiedAttributes: + return self.chargeModifiedAttributes[key] + else: + return default + except AttributeError: return default From dd3316a1c245c00aecd29103e8ee9df7f5297f25 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 29 Jan 2017 00:28:20 -0800 Subject: [PATCH 11/18] Gets the multiplier bonus from the item rather than hard coding it to 3 --- gui/builtinViewColumns/misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 87e4ea9db..9535b3656 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -496,7 +496,7 @@ class Miscellanea(ViewColumn): hpRatio = 1 if ("Ancillary" and "Armor") in itemGroup: - hpRatio *= 3 + hpRatio *= stuff.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) ehp = hp * hpRatio From 32611e07c849f6eb05c6234333b30af39543e9e4 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 29 Jan 2017 10:12:16 -0800 Subject: [PATCH 12/18] Fix syntax. Catch scenarios where none can be passed. --- gui/builtinViewColumns/misc.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py index 9535b3656..a5188253d 100644 --- a/gui/builtinViewColumns/misc.py +++ b/gui/builtinViewColumns/misc.py @@ -467,13 +467,13 @@ class Miscellanea(ViewColumn): boosted_attribute = "" reload_time = 0 - cycles = stuff.numShots - cycleTime = stuff.rawCycleTime + cycles = max(stuff.numShots, 0) + cycleTime = max(stuff.rawCycleTime, 0) # Get HP or boosted amount - stuff_hp = stuff.hpBeforeReload + stuff_hp = max(stuff.hpBeforeReload, 0) armor_hp = stuff.getModifiedItemAttr("armorDamageAmount", 0) - capacitor_hp = stuff.charge.getModifiedChargeAttr("capacitorBonus", 0) + capacitor_hp = stuff.getModifiedChargeAttr("capacitorBonus", 0) shield_hp = stuff.getModifiedItemAttr("shieldBonus", 0) hp = max(stuff_hp, armor_hp * cycles, capacitor_hp * cycles, shield_hp * cycles, 0) @@ -495,7 +495,7 @@ class Miscellanea(ViewColumn): else: hpRatio = 1 - if ("Ancillary" and "Armor") in itemGroup: + if "Ancillary" in itemGroup and "Armor" in itemGroup: hpRatio *= stuff.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) ehp = hp * hpRatio From aafc850dbd9466e6aa8210df4d674b65d49aaf4b Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 5 Feb 2017 20:09:00 -0800 Subject: [PATCH 13/18] Adhere to standards --- eos/effects/adaptivearmorhardener.py | 3 --- .../elitebonuscommanddestroyerinfohidden1.py | 5 ++++- ...ogisticremotearmorrepairoptimalfalloff1.py | 10 ++++++++-- ...olebonusremotearmorrepairoptimalfalloff.py | 8 ++++++-- ...pbonusforceauxiliarya4warfarelinksbonus.py | 20 ++++++++++++++----- eos/saveddata/fit.py | 13 +++++++----- gui/utils/exportHtml.py | 2 +- pyfa.py | 3 ++- tox.ini | 4 +++- 9 files changed, 47 insertions(+), 21 deletions(-) diff --git a/eos/effects/adaptivearmorhardener.py b/eos/effects/adaptivearmorhardener.py index 33e9f143c..e25fe48d4 100644 --- a/eos/effects/adaptivearmorhardener.py +++ b/eos/effects/adaptivearmorhardener.py @@ -15,8 +15,6 @@ def handler(fit, module, context): # Skip if there is no damage pattern. Example: projected ships or fleet boosters if damagePattern: - # logger.debug("Damage Pattern: %f/%f/%f/%f", damagePattern.emAmount, damagePattern.thermalAmount, damagePattern.kineticAmount, damagePattern.explosiveAmount) - # logger.debug("Original Armor Resists: %f/%f/%f/%f", fit.ship.getModifiedItemAttr('armorEmDamageResonance'), fit.ship.getModifiedItemAttr('armorThermalDamageResonance'), fit.ship.getModifiedItemAttr('armorKineticDamageResonance'), fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance')) # Populate a tuple with the damage profile modified by current armor resists. baseDamageTaken = ( @@ -50,7 +48,6 @@ def handler(fit, module, context): (2, baseDamageTaken[2] * RAHResistance[2], RAHResistance[2]), (1, baseDamageTaken[1] * RAHResistance[1], RAHResistance[1]), ] - # logger.debug("Damage taken this cycle: %f/%f/%f/%f", damagePattern_tuples[0][1], damagePattern_tuples[3][1], damagePattern_tuples[2][1], damagePattern_tuples[1][1]) # Sort the tuple to drop the highest damage value to the bottom sortedDamagePattern_tuples = sorted(damagePattern_tuples, key=lambda damagePattern: damagePattern[1]) diff --git a/eos/effects/elitebonuscommanddestroyerinfohidden1.py b/eos/effects/elitebonuscommanddestroyerinfohidden1.py index 4ffc352e0..cf31b2b1b 100644 --- a/eos/effects/elitebonuscommanddestroyerinfohidden1.py +++ b/eos/effects/elitebonuscommanddestroyerinfohidden1.py @@ -3,4 +3,7 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Command Specialist"), "commandBonusHidden", src.getModifiedItemAttr("eliteBonusCommandDestroyer1"), skill="Command Destroyers") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Command Specialist"), + "commandBonusHidden", + src.getModifiedItemAttr("eliteBonusCommandDestroyer1"), + skill="Command Destroyers") diff --git a/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py b/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py index 7f8e9fec3..cacbd4478 100644 --- a/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py +++ b/eos/effects/elitebonuslogisticremotearmorrepairoptimalfalloff1.py @@ -6,5 +6,11 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "falloffEffectiveness", + src.getModifiedItemAttr("eliteBonusLogistics1"), + skill="Logistics Cruisers") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "maxRange", + src.getModifiedItemAttr("eliteBonusLogistics1"), + skill="Logistics Cruisers") diff --git a/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py b/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py index c286514f2..fae8acfac 100644 --- a/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py +++ b/eos/effects/rolebonusremotearmorrepairoptimalfalloff.py @@ -6,5 +6,9 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("roleBonusRepairRange")) - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("roleBonusRepairRange")) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "falloffEffectiveness", + src.getModifiedItemAttr("roleBonusRepairRange")) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "maxRange", + src.getModifiedItemAttr("roleBonusRepairRange")) diff --git a/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py b/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py index a8378046b..824f57069 100644 --- a/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py +++ b/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py @@ -6,8 +6,18 @@ type = "passive" def handler(fit, src, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff4Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff3Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff1Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "buffDuration", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff2Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff4Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff3Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff1Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "buffDuration", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or + mod.item.requiresSkill("Information Command"), + "warfareBuff2Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier") diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 26bac09ea..ce351f910 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -487,10 +487,12 @@ class Fit(object): self.ship.boostItemAttr("armor%sDamageResonance" % damageType, value) if warfareBuffID == 14: # Armor Burst: Rapid Repair: Repair Duration/Capacitor - self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or mod.item.requiresSkill("Repair Systems"), - "capacitorNeed", value) - self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or mod.item.requiresSkill("Repair Systems"), "duration", - value) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or + mod.item.requiresSkill("Repair Systems"), + "capacitorNeed", value) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or + mod.item.requiresSkill("Repair Systems"), + "duration", value) if warfareBuffID == 15: # Armor Burst: Armor Reinforcement: Armor HP self.ship.boostItemAttr("armorHP", value, stackingPenalties=True) @@ -624,7 +626,8 @@ class Fit(object): self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Emission Systems"), "shieldBonus", value, stackingPenalties=True) if warfareBuffID == 53: # Leviathan Effect Generator : Armor RR penalty - self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "armorDamageAmount", value, stackingPenalties=True) + self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), + "armorDamageAmount", value, stackingPenalties=True) if warfareBuffID == 54: # Ragnarok Effect Generator : Laser and Hybrid Optimal penalty groups = ("Energy Weapon", "Hybrid Weapon") diff --git a/gui/utils/exportHtml.py b/gui/utils/exportHtml.py index 41fa7584d..194db5a6b 100644 --- a/gui/utils/exportHtml.py +++ b/gui/utils/exportHtml.py @@ -230,7 +230,7 @@ class exportHtmlThread(threading.Thread): HTML += ( '
  • \n' '

    ' + group.groupName + ' ' + str(groupFits) + '

    \n' - '
      \n' + HTMLgroup + + '
        \n' + HTMLgroup + '
      \n' ' ' ) diff --git a/pyfa.py b/pyfa.py index e465b0d5a..4eb9e0b9d 100755 --- a/pyfa.py +++ b/pyfa.py @@ -82,7 +82,8 @@ if not hasattr(sys, 'frozen'): betaFlag = True if saMatch.group(3) == "b" else False saBuild = int(saMatch.group(4)) if not betaFlag else 0 if saMajor == 0 and (saMinor < 5 or (saMinor == 5 and saBuild < 8)): - print("Pyfa requires sqlalchemy 0.5.8 at least but current sqlalchemy version is %s\nYou can download sqlalchemy (0.5.8+) from http://www.sqlalchemy.org/".format(sqlalchemy.__version__)) + print("Pyfa requires sqlalchemy 0.5.8 at least but current sqlalchemy version is %s\n" + "You can download sqlalchemy (0.5.8+) from http://www.sqlalchemy.org/".format(sqlalchemy.__version__)) sys.exit(1) else: print("Unknown sqlalchemy version string format, skipping check") diff --git a/tox.ini b/tox.ini index 2274602e3..dea12ad99 100644 --- a/tox.ini +++ b/tox.ini @@ -12,4 +12,6 @@ commands = py.test -vv --cov Pyfa tests/ [testenv:pep8] deps = flake8 -commands = flake8 --exclude=.svn,CVS,.bzr,.hg,.git,__pycache__,venv,tests,.tox,build,dist,__init__.py --ignore=E126,E127,E128,E501,E731,F401,F403,F405 service gui eos utils config.py pyfa.py --max-line-length=130 +# TODO: Remove F class exceptions once all imports are fixed +# TODO: Remove E731 and convert lambdas to defs +commands = flake8 --exclude=.svn,CVS,.bzr,.hg,.git,__pycache__,venv,tests,.tox,build,dist,__init__.py --ignore=E126,E127,E128,E731,F401,F403,F405 service gui eos utils config.py pyfa.py --max-line-length=165 From 31d74730c5d4d5c8061d3ed2e9677d22a7828bfb Mon Sep 17 00:00:00 2001 From: blitzman Date: Tue, 7 Feb 2017 19:44:59 -0500 Subject: [PATCH 14/18] Add matplotlib version to about window --- gui/mainFrame.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index e33c8bac9..623286669 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -349,6 +349,13 @@ class MainFrame(wx.Frame): info = wx.AboutDialogInfo() info.Name = "pyfa" info.Version = gui.aboutData.versionString + + try: + import matplotlib + matplotlib_version = matplotlib.__version__ + except: + matplotlib_version = None + info.Description = wordwrap(gui.aboutData.description + "\n\nDevelopers:\n\t" + "\n\t".join(gui.aboutData.developers) + "\n\nAdditional credits:\n\t" + @@ -358,7 +365,8 @@ class MainFrame(wx.Frame): "\n\nEVE Data: \t" + gamedata_version + "\nPython: \t\t" + '{}.{}.{}'.format(v.major, v.minor, v.micro) + "\nwxPython: \t" + wx.__version__ + - "\nSQLAlchemy: \t" + sqlalchemy.__version__, + "\nSQLAlchemy: \t" + sqlalchemy.__version__ + + "\nmatplotlib: \t {}".format(matplotlib_version if matplotlib_version else "Not Installed"), 500, wx.ClientDC(self)) if "__WXGTK__" in wx.PlatformInfo: forumUrl = "http://forums.eveonline.com/default.aspx?g=posts&t=466425" From ce9069af4a1d42f6442e432faefe6c0e4fe8194c Mon Sep 17 00:00:00 2001 From: blitzman Date: Tue, 7 Feb 2017 20:11:02 -0500 Subject: [PATCH 15/18] Fix projected fit view not showing projected fit count --- gui/builtinViewColumns/baseName.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/builtinViewColumns/baseName.py b/gui/builtinViewColumns/baseName.py index 973219b2c..b59554e1e 100644 --- a/gui/builtinViewColumns/baseName.py +++ b/gui/builtinViewColumns/baseName.py @@ -19,8 +19,8 @@ # ============================================================================= import wx -from eos.types import Drone, Cargo, Module, Slot, Rack, Implant, Fighter -from service.fit import Fit +from eos.types import Drone, Cargo, Module, Slot, Rack, Implant, Fighter, Fit +from service.fit import Fit as FitSvc from gui.viewColumn import ViewColumn import gui.mainFrame @@ -53,7 +53,7 @@ class BaseName(ViewColumn): else: return "%s (%s)" % (stuff.name, stuff.ship.item.name) elif isinstance(stuff, Rack): - if Fit.getInstance().serviceFittingOptions["rackLabels"]: + if FitSvc.getInstance().serviceFittingOptions["rackLabels"]: if stuff.slot == Slot.MODE: return u'─ Tactical Mode ─' else: @@ -70,7 +70,7 @@ class BaseName(ViewColumn): else: item = getattr(stuff, "item", stuff) - if Fit.getInstance().serviceFittingOptions["showMarketShortcuts"]: + if FitSvc.getInstance().serviceFittingOptions["showMarketShortcuts"]: marketShortcut = getattr(item, "marketShortcut", None) if marketShortcut: From 8a9d2a032ea03b1840839fea80350627f39b1dea Mon Sep 17 00:00:00 2001 From: blitzman Date: Wed, 8 Feb 2017 00:00:16 -0500 Subject: [PATCH 16/18] Revert the try... except, see #960 --- eos/gamedata.py | 9 +++------ eos/modifiedAttributeDict.py | 18 ++++++------------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/eos/gamedata.py b/eos/gamedata.py index fca14263a..10317dab2 100644 --- a/eos/gamedata.py +++ b/eos/gamedata.py @@ -244,12 +244,9 @@ class Item(EqBase): return self.__attributes def getAttribute(self, key, default=None): - try: - if key in self.attributes: - return self.attributes[key].value - else: - return default - except AttributeError: + if key in self.attributes: + return self.attributes[key].value + else: return default def isType(self, type): diff --git a/eos/modifiedAttributeDict.py b/eos/modifiedAttributeDict.py index 417a459c2..e558dc64d 100644 --- a/eos/modifiedAttributeDict.py +++ b/eos/modifiedAttributeDict.py @@ -26,23 +26,17 @@ cappingAttrKeyCache = {} class ItemAttrShortcut(object): def getModifiedItemAttr(self, key, default=None): - try: - if key in self.itemModifiedAttributes: - return self.itemModifiedAttributes[key] - else: - return default - except AttributeError: + if key in self.itemModifiedAttributes: + return self.itemModifiedAttributes[key] + else: return default class ChargeAttrShortcut(object): def getModifiedChargeAttr(self, key, default=None): - try: - if key in self.chargeModifiedAttributes: - return self.chargeModifiedAttributes[key] - else: - return default - except AttributeError: + if key in self.chargeModifiedAttributes: + return self.chargeModifiedAttributes[key] + else: return default From 7a521c655f954ef994d4f08eea29a42b359ec9fe Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 27 Jan 2017 14:24:53 -0800 Subject: [PATCH 17/18] Wrap dlg.Destroy() in a Try/Except Conflicts: gui/mainFrame.py --- gui/mainFrame.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 623286669..7e2eb072f 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -26,6 +26,7 @@ import wx import time from codecs import open +from wx._core import PyDeadObjectError from wx.lib.wordwrap import wordwrap @@ -70,6 +71,9 @@ from service.port import Port from service.settings import HTMLExportSettings from time import gmtime, strftime +import logging + +logger = logging.getLogger(__name__) import threading import webbrowser @@ -389,7 +393,10 @@ class MainFrame(wx.Frame): def showDamagePatternEditor(self, event): dlg = DmgPatternEditorDlg(self) dlg.ShowModal() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + logger.error("Tried to destroy an object that doesn't exist in .") def showImplantSetEditor(self, event): ImplantSetEditorDlg(self) @@ -414,14 +421,20 @@ class MainFrame(wx.Frame): path += ".xml" else: print("oops, invalid fit format %d" % format_) - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + logger.error("Tried to destroy an object that doesn't exist in .") return with open(path, "w", encoding="utf-8") as openfile: openfile.write(output) openfile.close() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + logger.error("Tried to destroy an object that doesn't exist in .") def showPreferenceDialog(self, event): dlg = PreferenceDialog(self) @@ -732,7 +745,10 @@ class MainFrame(wx.Frame): CopySelectDict[selected]() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + logger.error("Tried to destroy an object that doesn't exist in .") def exportSkillsNeeded(self, event): """ Exports skills needed for active fit and active character """ @@ -786,7 +802,10 @@ class MainFrame(wx.Frame): self.progressDialog.message = None sPort.importFitsThreaded(dlg.GetPaths(), self.fileImportCallback) self.progressDialog.ShowModal() - dlg.Destroy() + try: + dlg.Destroy() + except PyDeadObjectError: + logger.error("Tried to destroy an object that doesn't exist in .") def backupToXml(self, event): """ Back up all fits to EVE XML file """ From c90efb8d0ad4bdf1afebbef043a848c5e714306f Mon Sep 17 00:00:00 2001 From: Ryan Holmes Date: Wed, 8 Feb 2017 09:41:59 -0500 Subject: [PATCH 18/18] Fix `emAmount` > `{type}Amount`, some formatting tweaks --- eos/db/saveddata/databaseRepair.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/eos/db/saveddata/databaseRepair.py b/eos/db/saveddata/databaseRepair.py index c65b2fcd2..6c32695a6 100644 --- a/eos/db/saveddata/databaseRepair.py +++ b/eos/db/saveddata/databaseRepair.py @@ -85,8 +85,7 @@ class DatabaseCleanup: logger.error("More than one uniform damage pattern found.") else: uniform_damage_pattern_id = rows[0]['ID'] - update_query = "UPDATE 'fits' SET 'damagePatternID' = " + str(uniform_damage_pattern_id) + \ - " WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL" + update_query = "UPDATE 'fits' SET 'damagePatternID' = {} WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL".format(uniform_damage_pattern_id) update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query) logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount) @@ -167,7 +166,7 @@ class DatabaseCleanup: # See issue #954 for table in ['drones', 'cargo', 'fighters']: logger.debug("Running database cleanup for orphaned %s items.", table) - query = "SELECT COUNT(*) AS num FROM " + table + " WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + query = "SELECT COUNT(*) AS num FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table) results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) if results is None: @@ -176,13 +175,13 @@ class DatabaseCleanup: row = results.first() if row and row['num']: - query = "DELETE FROM " + table + " WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + query = "DELETE FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table) delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) for table in ['modules']: logger.debug("Running database cleanup for orphaned %s items.", table) - query = "SELECT COUNT(*) AS num FROM " + table + " WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + query = "SELECT COUNT(*) AS num FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table) results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) if results is None: @@ -191,7 +190,7 @@ class DatabaseCleanup: row = results.first() if row and row['num']: - query = "DELETE FROM " + table + " WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'" + query = "DELETE FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table) delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) @@ -202,7 +201,7 @@ class DatabaseCleanup: for profileType in ['damagePatterns', 'targetResists']: for damageType in ['em', 'thermal', 'kinetic', 'explosive']: logger.debug("Running database cleanup for null %s values. (%s)", profileType, damageType) - query = "SELECT COUNT(*) AS num FROM " + profileType + " WHERE " + damageType + "Amount IS NULL OR " + damageType + "Amount = ''" + query = "SELECT COUNT(*) AS num FROM {0} WHERE {1}Amount IS NULL OR {1}Amount = ''".format(profileType, damageType) results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) if results is None: @@ -211,7 +210,7 @@ class DatabaseCleanup: row = results.first() if row and row['num']: - query = "UPDATE '" + profileType + "' SET '" + damageType + "Amount' = '0' WHERE " + damageType + "Amount IS NULL OR emAmount = ''" + query = "UPDATE '{0}' SET '{1}Amount' = '0' WHERE {1}Amount IS NULL OR Amount = ''".format(profileType, damageType) delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)