diff --git a/eos/db/gamedata/item.py b/eos/db/gamedata/item.py index fd7be477d..2683a41e9 100644 --- a/eos/db/gamedata/item.py +++ b/eos/db/gamedata/item.py @@ -41,8 +41,7 @@ items_table = Table("invtypes", gamedata_meta, Column("iconID", Integer), Column("graphicID", Integer), Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True), - Column("replaceSame", String), - Column("replaceBetter", String)) + Column("replacements", String)) from .metaGroup import metatypes_table # noqa from .traits import traits_table # noqa diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index df1048ce3..338c13676 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -984,7 +984,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): charge = self.charge Module.__init__(self, item, self.baseItem, self.mutaplasmid) self.state = state - self.charge = charge + if self.isValidCharge(charge): + self.charge = charge for x in self.mutators.values(): Mutator(self, x.attribute, x.value) diff --git a/eve.db b/eve.db index a63d57b6f..aa3cfee9c 100644 Binary files a/eve.db and b/eve.db differ diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 2aac8eaa1..8cd5f4ae6 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -679,7 +679,7 @@ class MainFrame(wx.Frame): if changes: wx.PostEvent(self, GE.FitChanged(fitID=fitID)) - sPrice.optimizeFitPrice(fit, cb, includeBetter=True, fetchTimeout=10) + sPrice.optimizeFitPrice(fit, cb, fetchTimeout=10) def AdditionsTabSelect(self, event): selTab = self.additionsSelect.index(event.GetId()) diff --git a/scripts/jsonToSql.py b/scripts/jsonToSql.py index e700cdfcb..74dc399eb 100755 --- a/scripts/jsonToSql.py +++ b/scripts/jsonToSql.py @@ -178,36 +178,15 @@ def main(db, json_path): def fillReplacements(tables): - def compareAttrs(attrs1, attrs2, attrHig): - """ - Compares received attribute sets. Returns: - - 0 if sets have no attributes for comparison - - 1 if sets are different - - 2 if sets are exactly the same - - 3 if first set is strictly better - - 4 if second set is strictly better - """ + def compareAttrs(attrs1, attrs2): + # Consider items as different if they have no attrs if len(attrs1) == 0 and len(attrs2) == 0: - return 0 + return False if set(attrs1) != set(attrs2): - return 1 + return False if all(attrs1[aid] == attrs2[aid] for aid in attrs1): - return 2 - if all( - (attrs1[aid] <= attrs2[aid] and attrHig[aid] == 0) or - (attrs1[aid] >= attrs2[aid] and attrHig[aid] == 1) or - (attrs1[aid] == attrs2[aid] and attrHig[aid] == 2) - for aid in attrs1 - ): - return 3 - if all( - (attrs2[aid] <= attrs1[aid] and attrHig[aid] == 0) or - (attrs2[aid] >= attrs1[aid] and attrHig[aid] == 1) or - (attrs2[aid] == attrs1[aid] and attrHig[aid] == 2) - for aid in attrs1 - ): - return 4 - return 1 + return True + return False print('finding replacements') skillReqAttribs = { @@ -240,13 +219,15 @@ def main(db, json_path): # Ignore these attributes for comparison purposes elif attributeID in ( # We do not need mass as it affects final ship stats only when carried by ship itself - # (and we're not going to replace ships), but it's wildly inconsistent for other items + # (and we're not going to replace ships), but it's wildly inconsistent for other items, + # which otherwise would be the same 4, # mass 124, # mainColor 162, # radius 422, # techLevel 633, # metaLevel - 1692 # metaGroupID + 1692, # metaGroupID + 1768 # typeColorScheme ): continue else: @@ -267,40 +248,6 @@ def main(db, json_path): except (KeyError, ValueError): continue typeSkillReqs[skillType] = skillLevel - # Get data on attribute highIsGood flag - # Format: {type ID: 0 if high is bad, 1 if high is good, 2 if neither} - attrHig = {} - for row in tables['dgmattribs']: - attrHig[row['attributeID']] = 1 if row['highIsGood'] else 0 - # As CCP data is not really consistent, do some overrides - attrHig[4] = 0 # mass - # Sometimes high is positive, sometimes it's not (e.g. AB cycle bonus vs smartbomb cycle bonus) - attrHig[66] = 2 # durationBonus - # Sometimes high is positive, sometimes it's not (e.g. invuln cycle vs rep cycle) - attrHig[73] = 2 # duration - attrHig[151] = 0 # agilityBonus - attrHig[161] = 0 # volume - attrHig[293] = 0 # rofBonus - attrHig[310] = 0 # cpuNeedBonus - attrHig[312] = 0 # durationSkillBonus - attrHig[314] = 0 # capRechargeBonus - attrHig[317] = 0 # capNeedBonus - attrHig[319] = 0 # warpCapacitorNeedBonus - attrHig[323] = 0 # powerNeedBonus - attrHig[331] = 2 # implantness - attrHig[338] = 0 # rechargeratebonus - attrHig[440] = 0 # manufacturingTimeBonus - attrHig[441] = 0 # turretSpeeBonus - attrHig[452] = 0 # copySpeedBonus - attrHig[453] = 0 # blueprintmanufactureTimeBonus - attrHig[468] = 0 # mineralNeedResearchBonus - attrHig[780] = 0 # iceHarvestCycleBonus - attrHig[848] = 0 # aoeCloudSizeBonus - attrHig[927] = 0 # miningUpgradeCPUReductionBonus - attrHig[1087] = 2 # boosterness - attrHig[1125] = 0 # boosterChanceBonus - attrHig[1126] = 0 # boosterAttributeModifier - attrHig[1156] = 0 # maxScanDeviationModifier # Format: {group ID: category ID} groupCategories = {} for row in tables['evegroups']: @@ -338,28 +285,17 @@ def main(db, json_path): groupData = groupedData.setdefault((typeGroup, typeSkillreqs, typeEffects), []) groupData.append((typeID, typeAttribs)) # Format: {type ID: set(type IDs)} - same = {} - better = {} - # Now, go through composed groups and for every item within it find items which are - # the same and which are better + replacements = {} + # Now, go through composed groups and for every item within it + # find items which are the same for groupData in groupedData.values(): for type1, type2 in itertools.combinations(groupData, 2): - comparisonResult = compareAttrs(type1[1], type2[1], attrHig) - # Equal - if comparisonResult == 2: - same.setdefault(type1[0], set()).add(type2[0]) - same.setdefault(type2[0], set()).add(type1[0]) - # First is better - elif comparisonResult == 3: - better.setdefault(type2[0], set()).add(type1[0]) - # Second is better - elif comparisonResult == 4: - better.setdefault(type1[0], set()).add(type2[0]) + if compareAttrs(type1[1], type2[1]): + replacements.setdefault(type1[0], set()).add(type2[0]) + replacements.setdefault(type2[0], set()).add(type1[0]) # Put this data into types table so that normal process hooks it up for row in tables['evetypes']: - typeID = row['typeID'] - row['replaceSame'] = ','.join('{}'.format(tid) for tid in sorted(same.get(typeID, ()))) - row['replaceBetter'] = ','.join('{}'.format(tid) for tid in sorted(better.get(typeID, ()))) + row['replacements'] = ','.join('{}'.format(tid) for tid in sorted(replacements.get(row['typeID'], ()))) data = {} diff --git a/service/market.py b/service/market.py index 384efad82..085fef624 100644 --- a/service/market.py +++ b/service/market.py @@ -796,12 +796,10 @@ class Market(object): filtered = set([item for item in items if self.getMetaGroupIdByItem(item) in metas]) return filtered - def getReplacements(self, identity, includeBetter): + def getReplacements(self, identity): item = self.getItem(identity) # We already store needed type IDs in database - replTypeIDs = {int(i) for i in item.replaceSame.split(",") if i} - if includeBetter: - replTypeIDs.update({int(i) for i in item.replaceBetter.split(",") if i}) + replTypeIDs = {int(i) for i in item.replacements.split(",") if i} if not replTypeIDs: return () # As replacements were generated without keeping track which items were published, diff --git a/service/port/multibuy.py b/service/port/multibuy.py index da2326086..6c4074e82 100644 --- a/service/port/multibuy.py +++ b/service/port/multibuy.py @@ -70,15 +70,15 @@ def exportMultiBuy(fit, options, callback): if options[Options.OPTIMIZE_PRICES.value]: - def cb(replacements): + def processCheaperMapCb(replacementsCheaper): updatedAmounts = {} for item, itemAmount in itemAmounts.items(): - _addItem(updatedAmounts, replacements.get(item, item), itemAmount) + _addItem(updatedAmounts, replacementsCheaper.get(item, item), itemAmount) string = _prepareString(fit.ship.item, updatedAmounts) callback(string) priceSvc = sPrc.getInstance() - priceSvc.findCheaperReplacements(itemAmounts, cb, includeBetter=True) + priceSvc.findCheaperReplacements(itemAmounts, processCheaperMapCb) else: string = _prepareString(fit.ship.item, itemAmounts) if callback: diff --git a/service/price.py b/service/price.py index c4b9a3cc9..0f0f11ce6 100644 --- a/service/price.py +++ b/service/price.py @@ -201,14 +201,14 @@ class Price: pyfalog.debug("Clearing Prices") db.clearPrices() - def findCheaperReplacements(self, items, callback, includeBetter, fetchTimeout=10): + def findCheaperReplacements(self, items, callback, fetchTimeout=10): sMkt = Market.getInstance() replacementsAll = {} # All possible item replacements for item in items: if item in replacementsAll: continue - itemRepls = sMkt.getReplacements(item, includeBetter) + itemRepls = sMkt.getReplacements(item) if itemRepls: replacementsAll[item] = itemRepls itemsToFetch = {i for i in chain(replacementsAll.keys(), *replacementsAll.values())} @@ -230,16 +230,19 @@ class Price: validityOverride = 2 * 60 * 60 self.getPrices(itemsToFetch, makeCheapMapCb, fetchTimeout=fetchTimeout, validityOverride=validityOverride) - def optimizeFitPrice(self, fit, callback, includeBetter, fetchTimeout=10): + def optimizeFitPrice(self, fit, callback, fetchTimeout=10): def updateFitCb(replacementsCheaper): changes = False - for container in (fit.modules, fit.drones, fit.fighters, fit.implants, fit.boosters, fit.cargo): + for mod in fit.modules: + if mod.item in replacementsCheaper: + mod.rebase(replacementsCheaper[mod.item]) + changes = True + if mod.charge in replacementsCheaper: + mod.charge = replacementsCheaper[mod.charge] + changes = True + for container in (fit.drones, fit.fighters, fit.implants, fit.boosters, fit.cargo): for obj in container: - charge = getattr(obj, 'charge', None) - if charge is not None and charge in replacementsCheaper: - obj.charge = replacementsCheaper[charge] - changes = True if obj.item in replacementsCheaper: obj.rebase(replacementsCheaper[obj.item]) changes = True @@ -252,7 +255,7 @@ class Price: pyfalog.critical(e) fitItems = {i for i in self.fitItemIter(fit) if i is not fit.ship.item} - self.findCheaperReplacements(fitItems, updateFitCb, includeBetter, fetchTimeout=fetchTimeout) + self.findCheaperReplacements(fitItems, updateFitCb, fetchTimeout=fetchTimeout) class PriceWorkerThread(threading.Thread):