diff --git a/eos/saveddata/booster.py b/eos/saveddata/booster.py index cfe9b5a72..84369633d 100644 --- a/eos/saveddata/booster.py +++ b/eos/saveddata/booster.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,16 +15,19 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut -from eos.effectHandlerHelpers import HandledItem -from sqlalchemy.orm import reconstructor, validates -import eos.db import logging +from sqlalchemy.orm import reconstructor, validates + +import eos.db +from eos.effectHandlerHelpers import HandledItem +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut + logger = logging.getLogger(__name__) + class Booster(HandledItem, ItemAttrShortcut): def __init__(self, item): self.__item = item @@ -103,7 +106,7 @@ class Booster(HandledItem, ItemAttrShortcut): def clear(self): self.itemModifiedAttributes.clear() - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): if forceProjected: return if not self.active: return for effect in self.item.effects.itervalues(): @@ -117,13 +120,15 @@ class Booster(HandledItem, ItemAttrShortcut): @validates("ID", "itemID", "ammoID", "active") def validator(self, key, val): map = {"ID": lambda val: isinstance(val, int), - "itemID" : lambda val: isinstance(val, int), - "ammoID" : lambda val: isinstance(val, int), - "active" : lambda val: isinstance(val, bool), - "slot" : lambda val: isinstance(val, int) and 1 <= val <= 3} + "itemID": lambda val: isinstance(val, int), + "ammoID": lambda val: isinstance(val, int), + "active": lambda val: isinstance(val, bool), + "slot": lambda val: isinstance(val, int) and 1 <= val <= 3} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def __deepcopy__(self, memo): copy = Booster(self.item) diff --git a/eos/saveddata/cargo.py b/eos/saveddata/cargo.py index ea90d6f8a..34ab42db3 100644 --- a/eos/saveddata/cargo.py +++ b/eos/saveddata/cargo.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,18 +15,20 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut -from eos.effectHandlerHelpers import HandledItem, HandledCharge -from sqlalchemy.orm import validates, reconstructor -import eos.db import logging +from sqlalchemy.orm import validates, reconstructor + +import eos.db +from eos.effectHandlerHelpers import HandledItem +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut + logger = logging.getLogger(__name__) -class Cargo(HandledItem, ItemAttrShortcut): +class Cargo(HandledItem, ItemAttrShortcut): def __init__(self, item): """Initialize cargo from the program""" self.__item = item @@ -69,10 +71,12 @@ class Cargo(HandledItem, ItemAttrShortcut): @validates("fitID", "itemID") def validator(self, key, val): map = {"fitID": lambda val: isinstance(val, int), - "itemID" : lambda val: isinstance(val, int)} + "itemID": lambda val: isinstance(val, int)} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def __deepcopy__(self, memo): copy = Cargo(self.item) diff --git a/eos/saveddata/character.py b/eos/saveddata/character.py index a0b56c2f8..cc7ad7162 100644 --- a/eos/saveddata/character.py +++ b/eos/saveddata/character.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,20 +15,22 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from sqlalchemy.orm import validates, reconstructor +import logging from itertools import chain -from eos.effectHandlerHelpers import HandledItem, HandledImplantBoosterList -import eos.db +from sqlalchemy.orm import validates, reconstructor + import eos +import eos.db import eos.types -import logging +from eos.effectHandlerHelpers import HandledItem, HandledImplantBoosterList logger = logging.getLogger(__name__) + class Character(object): __itemList = None __itemIDMap = None @@ -211,7 +213,7 @@ class Character(object): if filter(element): element.boostItemAttr(*args, **kwargs) - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): if forceProjected: return for skill in self.skills: fit.register(skill) @@ -239,18 +241,21 @@ class Character(object): @validates("ID", "name", "apiKey", "ownerID") def validator(self, key, val): map = {"ID": lambda val: isinstance(val, int), - "name" : lambda val: True, - "apiKey" : lambda val: val is None or (isinstance(val, basestring) and len(val) > 0), - "ownerID" : lambda val: isinstance(val, int) or val is None} + "name": lambda val: True, + "apiKey": lambda val: val is None or (isinstance(val, basestring) and len(val) > 0), + "ownerID": lambda val: isinstance(val, int) or val is None} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def __repr__(self): return "Character(ID={}, name={}) at {}".format( self.ID, self.name, hex(id(self)) ) + class Skill(HandledItem): def __init__(self, item, level=0, ro=False, learned=True): self.__item = item if not isinstance(item, int) else None @@ -304,13 +309,12 @@ class Skill(HandledItem): if self.activeLevel == self.__level and self in self.character.dirtySkills: self.character.dirtySkills.remove(self) - @property def item(self): if self.__item is None: self.__item = item = Character.getSkillIDMap().get(self.itemID) if item is None: - #This skill is no longer in the database and thus invalid it, get rid of it. + # This skill is no longer in the database and thus invalid it, get rid of it. self.character.removeSkill(self) return self.__item @@ -322,7 +326,7 @@ class Skill(HandledItem): return None def calculateModifiedAttributes(self, fit, runTime): - if self.__suppressed: # or not self.learned - removed for GH issue 101 + if self.__suppressed: # or not self.learned - removed for GH issue 101 return item = self.item @@ -330,7 +334,8 @@ class Skill(HandledItem): return for effect in item.effects.itervalues(): - if effect.runTime == runTime and effect.isType("passive") and (not fit.isStructure or effect.isType("structure")): + if effect.runTime == runTime and effect.isType("passive") and ( + not fit.isStructure or effect.isType("structure")): try: effect.handler(fit, self, ("skill",)) except AttributeError: @@ -352,10 +357,12 @@ class Skill(HandledItem): raise ReadOnlyException() map = {"characterID": lambda val: isinstance(val, int), - "skillID" : lambda val: isinstance(val, int)} + "skillID": lambda val: isinstance(val, int)} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def __deepcopy__(self, memo): copy = Skill(self.item, self.level, self.__ro) @@ -366,5 +373,6 @@ class Skill(HandledItem): self.item.ID, self.item.name, hex(id(self)) ) + class ReadOnlyException(Exception): pass diff --git a/eos/saveddata/citadel.py b/eos/saveddata/citadel.py index f4d5fed47..1c3c22884 100644 --- a/eos/saveddata/citadel.py +++ b/eos/saveddata/citadel.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,22 +15,20 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut -from eos.effectHandlerHelpers import HandledItem -from eos.saveddata.mode import Mode -import eos.db -from eos.types import Ship import logging +from eos.types import Ship + logger = logging.getLogger(__name__) -class Citadel(Ship): +class Citadel(Ship): def validate(self, item): if item.category.name != "Structure": - raise ValueError('Passed item "%s" (category: (%s)) is not under Structure category'%(item.name, item.category.name)) + raise ValueError( + 'Passed item "%s" (category: (%s)) is not under Structure category' % (item.name, item.category.name)) def __deepcopy__(self, memo): copy = Citadel(self.item) diff --git a/eos/saveddata/crestchar.py b/eos/saveddata/crestchar.py index 9fa78f551..51a32fe26 100644 --- a/eos/saveddata/crestchar.py +++ b/eos/saveddata/crestchar.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,17 +15,15 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== - -import urllib -from cStringIO import StringIO +# =============================================================================== from sqlalchemy.orm import reconstructor -#from tomorrow import threads + + +# from tomorrow import threads class CrestChar(object): - def __init__(self, id, name, refresh_token=None): self.ID = id self.name = name diff --git a/eos/saveddata/damagePattern.py b/eos/saveddata/damagePattern.py index f9be89746..f10e6b50b 100644 --- a/eos/saveddata/damagePattern.py +++ b/eos/saveddata/damagePattern.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,14 +15,15 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== import re + class DamagePattern(object): DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive") - def __init__(self, emAmount = 25, thermalAmount = 25, kineticAmount = 25, explosiveAmount = 25): + def __init__(self, emAmount=25, thermalAmount=25, kineticAmount=25, explosiveAmount=25): self.emAmount = emAmount self.thermalAmount = thermalAmount self.kineticAmount = kineticAmount @@ -50,7 +51,7 @@ class DamagePattern(object): totalDamage = sum((self.emAmount, self.thermalAmount, self.kineticAmount, self.explosiveAmount)) specificDivider = 0 for damageType in self.DAMAGE_TYPES: - #Compose an attribute name, then make sure the first letter is NOT capitalized + # Compose an attribute name, then make sure the first letter is NOT capitalized attrName = "%s%sDamageResonance" % (type, damageType.capitalize()) attrName = attrName[0].lower() + attrName[1:] @@ -65,6 +66,7 @@ class DamagePattern(object): "therm": "thermal", "kin": "kinetic", "exp": "explosive"} + @classmethod def importPatterns(cls, text): lines = re.split('[\n\r]+', text) @@ -74,8 +76,8 @@ class DamagePattern(object): try: if line.strip()[0] == "#": # comments continue - line = line.split('#',1)[0] # allows for comments - type, data = line.rsplit('=',1) + line = line.split('#', 1)[0] # allows for comments + type, data = line.rsplit('=', 1) type, data = type.strip(), data.split(',') except: # Data isn't in correct format, continue to next line @@ -94,7 +96,7 @@ class DamagePattern(object): except: continue - if len(fields) == 4: # Avoid possible blank lines + if len(fields) == 4: # Avoid possible blank lines pattern = DamagePattern(**fields) pattern.name = name.strip() patterns.append(pattern) @@ -102,9 +104,10 @@ class DamagePattern(object): return patterns, numPatterns EXPORT_FORMAT = "DamageProfile = %s,%d,%d,%d,%d\n" + @classmethod def exportPatterns(cls, *patterns): - out = "# Exported from pyfa\n#\n" + out = "# Exported from pyfa\n#\n" out += "# Values are in following format:\n" out += "# DamageProfile = [name],[EM amount],[Thermal amount],[Kinetic amount],[Explosive amount]\n\n" for dp in patterns: diff --git a/eos/saveddata/drone.py b/eos/saveddata/drone.py index 4b7abd4eb..03e52fe7c 100644 --- a/eos/saveddata/drone.py +++ b/eos/saveddata/drone.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,16 +15,19 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut -from eos.effectHandlerHelpers import HandledItem, HandledCharge -from sqlalchemy.orm import validates, reconstructor -import eos.db import logging +from sqlalchemy.orm import validates, reconstructor + +import eos.db +from eos.effectHandlerHelpers import HandledItem, HandledCharge +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut + logger = logging.getLogger(__name__) + class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): DAMAGE_TYPES = ("em", "kinetic", "explosive", "thermal") MINING_ATTRIBUTES = ("miningAmount",) @@ -116,7 +119,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def dps(self): return self.damageStats() - def damageStats(self, targetResists = None): + def damageStats(self, targetResists=None): if self.__dps is None: self.__volley = 0 self.__dps = 0 @@ -125,12 +128,14 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): attr = "missileLaunchDuration" getter = self.getModifiedChargeAttr else: - attr = "speed" + attr = "speed" getter = self.getModifiedItemAttr cycleTime = self.getModifiedItemAttr(attr) - volley = sum(map(lambda d: (getter("%sDamage"%d) or 0) * (1-getattr(targetResists, "%sAmount"%d, 0)), self.DAMAGE_TYPES)) + volley = sum( + map(lambda d: (getter("%sDamage" % d) or 0) * (1 - getattr(targetResists, "%sAmount" % d, 0)), + self.DAMAGE_TYPES)) volley *= self.amountActive volley *= self.getModifiedItemAttr("damageMultiplier") or 1 self.__volley = volley @@ -180,13 +185,15 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @validates("ID", "itemID", "chargeID", "amount", "amountActive") def validator(self, key, val): map = {"ID": lambda val: isinstance(val, int), - "itemID" : lambda val: isinstance(val, int), - "chargeID" : lambda val: isinstance(val, int), - "amount" : lambda val: isinstance(val, int) and val >= 0, - "amountActive" : lambda val: isinstance(val, int) and self.amount >= val >= 0} + "itemID": lambda val: isinstance(val, int), + "chargeID": lambda val: isinstance(val, int), + "amount": lambda val: isinstance(val, int) and val >= 0, + "amountActive": lambda val: isinstance(val, int) and self.amount >= val >= 0} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def clear(self): self.__dps = None @@ -213,7 +220,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): else: return True - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): if self.projected or forceProjected: context = "projected", "drone" projected = True diff --git a/eos/saveddata/fighter.py b/eos/saveddata/fighter.py index 6275c3abc..52f0fb8d8 100644 --- a/eos/saveddata/fighter.py +++ b/eos/saveddata/fighter.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,14 +15,15 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut -from eos.effectHandlerHelpers import HandledItem, HandledCharge, HandledDroneCargoList -from sqlalchemy.orm import validates, reconstructor -import eos.db -from eos.enum import Enum import logging + +from sqlalchemy.orm import validates, reconstructor + +import eos.db +from eos.effectHandlerHelpers import HandledItem, HandledCharge +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut from eos.types import FighterAbility, Slot logger = logging.getLogger(__name__) @@ -155,7 +156,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def dps(self): return self.damageStats() - def damageStats(self, targetResists = None): + def damageStats(self, targetResists=None): if self.__dps is None: self.__volley = 0 self.__dps = 0 @@ -164,7 +165,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): dps, volley = ability.damageStats(targetResists) self.__dps += dps self.__volley += volley - + # For forward compatability this assumes a fighter can have more than 2 damaging abilities and/or multiple that use charges. if self.owner.factorReload: activeTimes = [] @@ -179,7 +180,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): continue activeTimes.append(ability.numShots * ability.cycleTime) reloadTimes.append(ability.reloadTime) - + if len(activeTimes) > 0: shortestActive = sorted(activeTimes)[0] longestReload = sorted(reloadTimes, reverse=True)[0] @@ -214,13 +215,15 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @validates("ID", "itemID", "chargeID", "amount", "amountActive") def validator(self, key, val): map = {"ID": lambda val: isinstance(val, int), - "itemID" : lambda val: isinstance(val, int), - "chargeID" : lambda val: isinstance(val, int), - "amount" : lambda val: isinstance(val, int) and val >= -1, + "itemID": lambda val: isinstance(val, int), + "chargeID": lambda val: isinstance(val, int), + "amount": lambda val: isinstance(val, int) and val >= -1, } - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def clear(self): self.__dps = None @@ -248,7 +251,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): else: return True - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): if not self.active: return @@ -263,7 +266,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if ability.active: effect = ability.effect if effect.runTime == runTime and \ - ((projected and effect.isType("projected")) or not projected): + ((projected and effect.isType("projected")) or not projected): if ability.grouped: effect.handler(fit, self, context) else: @@ -283,4 +286,3 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return False return True - diff --git a/eos/saveddata/fighterAbility.py b/eos/saveddata/fighterAbility.py index 0c830bc40..f2c09555a 100644 --- a/eos/saveddata/fighterAbility.py +++ b/eos/saveddata/fighterAbility.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,13 +15,15 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from sqlalchemy.orm import validates, reconstructor import logging +from sqlalchemy.orm import reconstructor + logger = logging.getLogger(__name__) + class FighterAbility(object): DAMAGE_TYPES = ("em", "kinetic", "explosive", "thermal") DAMAGE_TYPES2 = ("EM", "Kin", "Exp", "Therm") @@ -30,18 +32,17 @@ class FighterAbility(object): # with the fighter squadron role NUM_SHOTS_MAPPING = { 1: 0, # Superiority fighter / Attack - 2: 12, # Light fighter / Attack + 2: 12, # Light fighter / Attack 4: 6, # Heavy fighter / Heavy attack 5: 3, # Heavy fighter / Long range attack } # Same as above REARM_TIME_MAPPING = { - 1: 0, # Superiority fighter / Attack + 1: 0, # Superiority fighter / Attack 2: 4000, # Light fighter / Attack 4: 6000, # Heavy fighter / Heavy attack - 5: 20000, # Heavy fighter / Long range attack + 5: 20000, # Heavy fighter / Long range attack } - def __init__(self, effect): """Initialize from the program""" @@ -94,11 +95,14 @@ class FighterAbility(object): @property def reloadTime(self): - return self.fighter.getModifiedItemAttr("fighterRefuelingTime") + (self.REARM_TIME_MAPPING[self.fighter.getModifiedItemAttr("fighterSquadronRole")] or 0 if self.hasCharges else 0) * self.numShots + return self.fighter.getModifiedItemAttr("fighterRefuelingTime") + (self.REARM_TIME_MAPPING[ + self.fighter.getModifiedItemAttr( + "fighterSquadronRole")] or 0 if self.hasCharges else 0) * self.numShots @property def numShots(self): - return self.NUM_SHOTS_MAPPING[self.fighter.getModifiedItemAttr("fighterSquadronRole")] or 0 if self.hasCharges else 0 + return self.NUM_SHOTS_MAPPING[ + self.fighter.getModifiedItemAttr("fighterSquadronRole")] or 0 if self.hasCharges else 0 @property def cycleTime(self): @@ -126,7 +130,7 @@ class FighterAbility(object): if self.attrPrefix == "fighterAbilityLaunchBomb": # bomb calcs volley = sum(map(lambda attr: (self.fighter.getModifiedChargeAttr("%sDamage" % attr) or 0) * ( - 1 - getattr(targetResists, "%sAmount" % attr, 0)), self.DAMAGE_TYPES)) + 1 - getattr(targetResists, "%sAmount" % attr, 0)), self.DAMAGE_TYPES)) else: volley = sum(map(lambda d2, d: (self.fighter.getModifiedItemAttr( diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 611944748..f937d1e5e 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,26 +15,24 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.effectHandlerHelpers import * -from eos.modifiedAttributeDict import ModifiedAttributeDict -from sqlalchemy.orm import validates, reconstructor -from itertools import chain -from eos import capSim -from copy import deepcopy -from math import sqrt, log, asinh -from eos.types import Drone, Cargo, Ship, Character, State, Slot, Module, Implant, Booster, Skill, Citadel -from eos.saveddata.module import State, Hardpoint -from eos.saveddata.mode import Mode -import eos.db -import time import copy -from utils.timer import Timer -from eos.enum import Enum - - import logging +import time +from copy import deepcopy +from itertools import chain +from math import sqrt, log, asinh + +from sqlalchemy.orm import validates, reconstructor + +import eos.db +from eos import capSim +from eos.effectHandlerHelpers import * +from eos.enum import Enum +from eos.saveddata.module import State, Hardpoint +from eos.types import Ship, Character, Slot, Module, Citadel +from utils.timer import Timer logger = logging.getLogger(__name__) @@ -43,6 +41,7 @@ try: except ImportError: from utils.compat import OrderedDict + class ImplantLocation(Enum): def __init__(self): pass @@ -50,6 +49,7 @@ class ImplantLocation(Enum): FIT = 0 CHARACTER = 1 + class Fit(object): """Represents a fitting, with modules, ship, implants, etc.""" @@ -68,7 +68,7 @@ class Fit(object): self.__cargo = HandledDroneCargoList() self.__implants = HandledImplantBoosterList() self.__boosters = HandledImplantBoosterList() - #self.__projectedFits = {} + # self.__projectedFits = {} self.__projectedModules = HandledProjectedModList() self.__projectedDrones = HandledProjectedDroneList() self.__projectedFighters = HandledProjectedDroneList() @@ -302,7 +302,8 @@ class Fit(object): @property def maxTargets(self): - return min(self.extraAttributes["maxTargetsLockedFromSkills"], self.ship.getModifiedItemAttr("maxLockedTargets")) + return min(self.extraAttributes["maxTargetsLockedFromSkills"], + self.ship.getModifiedItemAttr("maxLockedTargets")) @property def maxTargetRange(self): @@ -329,7 +330,7 @@ class Fit(object): @property def jamChance(self): - return (1-self.ecmProjectedStr)*100 + return (1 - self.ecmProjectedStr) * 100 @property def maxSpeed(self): @@ -364,11 +365,13 @@ class Fit(object): @validates("ID", "ownerID", "shipID") def validator(self, key, val): map = {"ID": lambda val: isinstance(val, int), - "ownerID" : lambda val: isinstance(val, int) or val is None, - "shipID" : lambda val: isinstance(val, int) or val is None} + "ownerID": lambda val: isinstance(val, int) or val is None, + "shipID": lambda val: isinstance(val, int) or val is None} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def clear(self, projected=False): self.__effectiveTank = None @@ -417,8 +420,8 @@ class Fit(object): if stuff is not None and stuff != self: stuff.clear(projected=True) - #Methods to register and get the thing currently affecting the fit, - #so we can correctly map "Affected By" + # Methods to register and get the thing currently affecting the fit, + # so we can correctly map "Affected By" def register(self, currModifier, origin=None): self.__modifier = currModifier self.__origin = origin @@ -442,7 +445,7 @@ class Fit(object): context = ("gang", thing.__class__.__name__.lower()) if isinstance(thing, Module): if effect.isType("offline") or (effect.isType("passive") and thing.state >= State.ONLINE) or \ - (effect.isType("active") and thing.state >= State.ACTIVE): + (effect.isType("active") and thing.state >= State.ACTIVE): # Run effect, and get proper bonuses applied try: self.register(thing) @@ -486,7 +489,7 @@ class Fit(object): logger.debug("Fleet is set, gathering gang boosts") self.gangBoosts = self.fleet.recalculateLinear(withBoosters=withBoosters) - timer.checkpoint("Done calculating gang boosts for %r"%self) + timer.checkpoint("Done calculating gang boosts for %r" % self) elif self.fleet is None: self.gangBoosts = None @@ -537,7 +540,7 @@ class Fit(object): r = [(self.mode,), self.projectedDrones, self.projectedFighters, self.projectedModules] # chain unrestricted and restricted into one iterable - c = chain.from_iterable(u+r) + c = chain.from_iterable(u + r) # We calculate gang bonuses first so that projected fits get them if self.gangBoosts is not None: @@ -558,7 +561,7 @@ class Fit(object): targetFit.register(item, origin=self) item.calculateModifiedAttributes(targetFit, runTime, True) - timer.checkpoint('Done with runtime: %s'%runTime) + timer.checkpoint('Done with runtime: %s' % runTime) # Mark fit as calculated self.__calculated = True @@ -591,7 +594,7 @@ class Fit(object): self.modules.append(Module.buildEmpty(slotType)) if amount < 0: - #Look for any dummies of that type to remove + # Look for any dummies of that type to remove toRemove = [] for mod in self.modules: if mod.isEmpty and mod.slot == slotType: @@ -610,7 +613,7 @@ class Fit(object): @property def modCount(self): - x=0 + x = 0 for i in xrange(len(self.modules) - 1, -1, -1): mod = self.modules[i] if not mod.isEmpty: @@ -733,7 +736,7 @@ class Fit(object): def activeDrones(self): amount = 0 for d in self.drones: - amount +=d.amountActive + amount += d.amountActive return amount @@ -802,7 +805,6 @@ class Fit(object): return self.__capRecharge - @property def sustainableTank(self): if self.__sustainableTank is None: @@ -820,22 +822,22 @@ class Fit(object): sustainable = {} repairers = [] - #Map a repairer type to the attribute it uses + # Map a repairer type to the attribute it uses groupAttrMap = {"Armor Repair Unit": "armorDamageAmount", - "Ancillary Armor Repairer": "armorDamageAmount", - "Hull Repair Unit": "structureDamageAmount", - "Shield Booster": "shieldBonus", - "Ancillary Shield Booster": "shieldBonus", - "Remote Armor Repairer": "armorDamageAmount", - "Remote Shield Booster": "shieldBonus"} - #Map repairer type to attribute + "Ancillary Armor Repairer": "armorDamageAmount", + "Hull Repair Unit": "structureDamageAmount", + "Shield Booster": "shieldBonus", + "Ancillary Shield Booster": "shieldBonus", + "Remote Armor Repairer": "armorDamageAmount", + "Remote Shield Booster": "shieldBonus"} + # Map repairer type to attribute groupStoreMap = {"Armor Repair Unit": "armorRepair", "Hull Repair Unit": "hullRepair", "Shield Booster": "shieldRepair", "Ancillary Shield Booster": "shieldRepair", "Remote Armor Repairer": "armorRepair", "Remote Shield Booster": "shieldRepair", - "Ancillary Armor Repairer": "armorRepair",} + "Ancillary Armor Repairer": "armorRepair", } capUsed = self.capUsed for attr in ("shieldRepair", "armorRepair", "hullRepair"): @@ -861,25 +863,26 @@ class Fit(object): sustainable[attr] -= amount / (cycleTime / 1000.0) repairers.append(mod) + # Sort repairers by efficiency. We want to use the most efficient repairers first + repairers.sort(key=lambda mod: mod.getModifiedItemAttr( + groupAttrMap[mod.item.group.name]) / mod.getModifiedItemAttr("capacitorNeed"), reverse=True) - #Sort repairers by efficiency. We want to use the most efficient repairers first - repairers.sort(key=lambda mod: mod.getModifiedItemAttr(groupAttrMap[mod.item.group.name]) / mod.getModifiedItemAttr("capacitorNeed"), reverse = True) - - #Loop through every module until we're above peak recharge - #Most efficient first, as we sorted earlier. - #calculate how much the repper can rep stability & add to total + # Loop through every module until we're above peak recharge + # Most efficient first, as we sorted earlier. + # calculate how much the repper can rep stability & add to total totalPeakRecharge = self.capRecharge for mod in repairers: if capUsed > totalPeakRecharge: break cycleTime = mod.cycleTime capPerSec = mod.capUse if capPerSec is not None and cycleTime is not None: - #Check how much this repper can work + # Check how much this repper can work sustainability = min(1, (totalPeakRecharge - capUsed) / capPerSec) - #Add the sustainable amount + # Add the sustainable amount amount = mod.getModifiedItemAttr(groupAttrMap[mod.item.group.name]) - sustainable[groupStoreMap[mod.item.group.name]] += sustainability * (amount / (cycleTime / 1000.0)) + sustainable[groupStoreMap[mod.item.group.name]] += sustainability * ( + amount / (cycleTime / 1000.0)) capUsed += capPerSec sustainable["passiveShield"] = self.calculateShieldRecharge() @@ -887,12 +890,12 @@ class Fit(object): return self.__sustainableTank - def calculateCapRecharge(self, percent = PEAK_RECHARGE): + def calculateCapRecharge(self, percent=PEAK_RECHARGE): capacity = self.ship.getModifiedItemAttr("capacitorCapacity") rechargeRate = self.ship.getModifiedItemAttr("rechargeRate") / 1000.0 return 10 / rechargeRate * sqrt(percent) * (1 - sqrt(percent)) * capacity - def calculateShieldRecharge(self, percent = PEAK_RECHARGE): + def calculateShieldRecharge(self, percent=PEAK_RECHARGE): capacity = self.ship.getModifiedItemAttr("shieldCapacity") rechargeRate = self.ship.getModifiedItemAttr("shieldRechargeRate") / 1000.0 return 10 / rechargeRate * sqrt(percent) * (1 - sqrt(percent)) * capacity @@ -903,9 +906,9 @@ class Fit(object): energyNeutralizerSignatureResolution = src.getModifiedItemAttr("energyNeutralizerSignatureResolution") signatureRadius = self.ship.getModifiedItemAttr("signatureRadius") - #Signature reduction, uses the bomb formula as per CCP Larrikin + # Signature reduction, uses the bomb formula as per CCP Larrikin if energyNeutralizerSignatureResolution: - capNeed = capNeed*min(1, signatureRadius/energyNeutralizerSignatureResolution) + capNeed = capNeed * min(1, signatureRadius / energyNeutralizerSignatureResolution) resistance = self.ship.getModifiedItemAttr("energyWarfareResistance") or 1 if capNeed > 0 else 1 self.__extraDrains.append((cycleTime, capNeed * resistance, clipSize)) @@ -936,7 +939,8 @@ class Fit(object): # If this is a turret, don't stagger activations disableStagger = mod.hardpoint == Hardpoint.TURRET - drains.append((int(fullCycleTime), mod.getModifiedItemAttr("capacitorNeed") or 0, mod.numShots or 0, disableStagger)) + drains.append((int(fullCycleTime), mod.getModifiedItemAttr("capacitorNeed") or 0, + mod.numShots or 0, disableStagger)) for fullCycleTime, capNeed, clipSize in self.iterDrains(): # Stagger incoming effects for cap simulation @@ -990,7 +994,7 @@ class Fit(object): @property def tank(self): - hps = {"passiveShield" : self.calculateShieldRecharge()} + hps = {"passiveShield": self.calculateShieldRecharge()} for type in ("shield", "armor", "hull"): hps["%sRepair" % type] = self.extraAttributes["%sRepair" % type] @@ -1020,13 +1024,12 @@ class Fit(object): return self.__effectiveSustainableTank - def calculateLockTime(self, radius): scanRes = self.ship.getModifiedItemAttr("scanResolution") if scanRes is not None and scanRes > 0: # Yes, this function returns time in seconds, not miliseconds. # 40,000 is indeed the correct constant here. - return min(40000 / scanRes / asinh(radius)**2, 30*60) + return min(40000 / scanRes / asinh(radius) ** 2, 30 * 60) else: return self.ship.getModifiedItemAttr("scanSpeed") / 1000.0 @@ -1079,7 +1082,7 @@ class Fit(object): def __deepcopy__(self, memo): copy = Fit() - #Character and owner are not copied + # Character and owner are not copied copy.character = self.__character copy.owner = self.owner copy.ship = deepcopy(self.ship, memo) @@ -1087,7 +1090,9 @@ class Fit(object): copy.damagePattern = self.damagePattern copy.targetResists = self.targetResists - toCopy = ("modules", "drones", "fighters", "cargo", "implants", "boosters", "projectedModules", "projectedDrones", "projectedFighters") + toCopy = ( + "modules", "drones", "fighters", "cargo", "implants", "boosters", "projectedModules", "projectedDrones", + "projectedFighters") for name in toCopy: orig = getattr(self, name) c = getattr(copy, name) diff --git a/eos/saveddata/fleet.py b/eos/saveddata/fleet.py index 780301968..fccb95ed8 100644 --- a/eos/saveddata/fleet.py +++ b/eos/saveddata/fleet.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,15 +15,17 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from itertools import chain -from eos.types import Skill, Module, Ship from copy import deepcopy +from itertools import chain + +from eos.types import Skill, Module, Ship + class Fleet(object): def calculateModifiedAttributes(self): - #Make sure ALL fits in the gang have been calculated + # Make sure ALL fits in the gang have been calculated for c in chain(self.wings, (self.leader,)): if c is not None: c.calculateModifiedAttributes() @@ -32,24 +34,26 @@ class Fleet(object): self.broken = False self.store = store = Store() store.set(booster, "fleet") - #Go all the way down for each subtree we have. + # Go all the way down for each subtree we have. for wing in self.wings: wing.calculateGangBonusses(store) # Check skill requirements and wing amount to see if we break or not - if len(self.wings) == 0 or leader is None or leader.character is None or leader.character.getSkill("Fleet Command").level < len(self.wings): + if len(self.wings) == 0 or leader is None or leader.character is None or leader.character.getSkill( + "Fleet Command").level < len(self.wings): self.broken = True - #Now calculate our own if we aren't broken + # Now calculate our own if we aren't broken if not self.broken: - #We only get our own bonuses *Sadface* + # We only get our own bonuses *Sadface* store.apply(leader, "fleet") def recalculateLinear(self, withBoosters=True, dirtyStorage=None): self.store = Store() self.linearBoosts = {} if withBoosters is True: - if self.leader is not None and self.leader.character is not None and self.leader.character.getSkill("Fleet Command").level >= 1: + if self.leader is not None and self.leader.character is not None and self.leader.character.getSkill( + "Fleet Command").level >= 1: self.leader.boostsFits.add(self.wings[0].squads[0].members[0].ID) self.leader.calculateModifiedAttributes() self.store.set(self.leader, "squad", clearingUpdate=True) @@ -83,6 +87,7 @@ class Fleet(object): return copy + class Wing(object): def calculateModifiedAttributes(self): for c in chain(self.squads, (self.leader,)): @@ -95,24 +100,26 @@ class Wing(object): store.set(booster, "wing") - #ALWAYS move down + # ALWAYS move down for squad in self.squads: squad.calculateGangBonusses(store) # Check skill requirements and squad amount to see if we break or not - if len(self.squads) == 0 or leader is None or leader.character is None or leader.character.getSkill("Wing Command").level < len(self.squads): + if len(self.squads) == 0 or leader is None or leader.character is None or leader.character.getSkill( + "Wing Command").level < len(self.squads): self.broken = True - #Check if we aren't broken, if we aren't, boost + # Check if we aren't broken, if we aren't, boost if not self.broken: store.apply(leader, "wing") else: - #We broke, don't go up + # We broke, don't go up self.gang.broken = True def recalculateLinear(self, store, withBoosters=True, dirtyStorage=None): if withBoosters is True: - if self.leader is not None and self.leader.character is not None and self.leader.character.getSkill("Wing Command").level >= 1: + if self.leader is not None and self.leader.character is not None and self.leader.character.getSkill( + "Wing Command").level >= 1: self.leader.boostsFits.add(self.squads[0].members[0].ID) self.leader.calculateModifiedAttributes() store.set(self.leader, "squad", clearingUpdate=False) @@ -162,7 +169,8 @@ class Squad(object): store.set(booster, "squad") # Check skill requirements and squad size to see if we break or not - if len(self.members) <= 0 or leader is None or leader.character is None or leader.character.getSkill("Leadership").level * 2 < len(self.members): + if len(self.members) <= 0 or leader is None or leader.character is None or leader.character.getSkill( + "Leadership").level * 2 < len(self.members): self.broken = True if not self.broken: @@ -173,7 +181,8 @@ class Squad(object): def recalculateLinear(self, store, withBoosters=True, dirtyStorage=None): if withBoosters is True: - if self.leader is not None and self.leader.character is not None and self.leader.character.getSkill("Leadership").level >= 1: + if self.leader is not None and self.leader.character is not None and self.leader.character.getSkill( + "Leadership").level >= 1: self.leader.boostsFits.add(self.members[0].ID) self.leader.calculateModifiedAttributes(dirtyStorage=dirtyStorage) store.set(self.leader, "squad", clearingUpdate=False) @@ -231,6 +240,7 @@ class Squad(object): return copy + class Store(object): def __init__(self): # Container for gang boosters and their respective bonuses, three-layered diff --git a/eos/saveddata/implant.py b/eos/saveddata/implant.py index a368e9714..7a4bf1790 100644 --- a/eos/saveddata/implant.py +++ b/eos/saveddata/implant.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,16 +15,19 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut -from eos.effectHandlerHelpers import HandledItem -from sqlalchemy.orm import validates, reconstructor -import eos.db import logging +from sqlalchemy.orm import validates, reconstructor + +import eos.db +from eos.effectHandlerHelpers import HandledItem +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut + logger = logging.getLogger(__name__) + class Implant(HandledItem, ItemAttrShortcut): def __init__(self, item): self.__item = item @@ -84,7 +87,7 @@ class Implant(HandledItem, ItemAttrShortcut): def clear(self): self.itemModifiedAttributes.clear() - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): if forceProjected: return if not self.active: return for effect in self.item.effects.itervalues(): @@ -94,11 +97,13 @@ class Implant(HandledItem, ItemAttrShortcut): @validates("fitID", "itemID", "active") def validator(self, key, val): map = {"fitID": lambda val: isinstance(val, int), - "itemID" : lambda val: isinstance(val, int), + "itemID": lambda val: isinstance(val, int), "active": lambda val: isinstance(val, bool)} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def __deepcopy__(self, memo): copy = Implant(self.item) diff --git a/eos/saveddata/implantSet.py b/eos/saveddata/implantSet.py index 8e495c5ea..2daaaa3eb 100644 --- a/eos/saveddata/implantSet.py +++ b/eos/saveddata/implantSet.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2016 Ryan Holmes # # This file is part of eos. @@ -15,10 +15,12 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== + +from copy import deepcopy from eos.effectHandlerHelpers import HandledImplantBoosterList -from copy import deepcopy + class ImplantSet(object): def __init__(self, name=None): @@ -31,12 +33,12 @@ class ImplantSet(object): @classmethod def exportSets(cls, *sets): - out = "# Exported from pyfa\n#\n" \ - "# Values are in following format:\n" \ - "# [Implant Set name]\n" \ - "# [Implant name]\n" \ - "# [Implant name]\n" \ - "# ...\n\n" + out = "# Exported from pyfa\n#\n" \ + "# Values are in following format:\n" \ + "# [Implant Set name]\n" \ + "# [Implant name]\n" \ + "# [Implant name]\n" \ + "# ...\n\n" for set in sets: out += "[{}]\n".format(set.name) diff --git a/eos/saveddata/miscData.py b/eos/saveddata/miscData.py index c7a859afe..909b574bc 100644 --- a/eos/saveddata/miscData.py +++ b/eos/saveddata/miscData.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2011 Anton Vorobyov # # This file is part of eos. @@ -15,10 +15,11 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== from eos.eqBase import EqBase + class MiscData(EqBase): def __init__(self, name, val=None): self.fieldName = name diff --git a/eos/saveddata/mode.py b/eos/saveddata/mode.py index 91fbaf6eb..f494d8d9f 100644 --- a/eos/saveddata/mode.py +++ b/eos/saveddata/mode.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,17 +15,18 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut from eos.effectHandlerHelpers import HandledItem -import eos.db +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut + class Mode(ItemAttrShortcut, HandledItem): def __init__(self, item): if item.group.name != "Ship Modifiers": - raise ValueError('Passed item "%s" (category: (%s)) is not a Ship Modifier'%(item.name, item.category.name)) + raise ValueError( + 'Passed item "%s" (category: (%s)) is not a Ship Modifier' % (item.name, item.category.name)) self.__item = item self.__itemModifiedAttributes = ModifiedAttributeDict() @@ -47,8 +48,8 @@ class Mode(ItemAttrShortcut, HandledItem): def clear(self): self.itemModifiedAttributes.clear() - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): if self.item: for effect in self.item.effects.itervalues(): if effect.runTime == runTime: - effect.handler(fit, self, context = ("module",)) + effect.handler(fit, self, context=("module",)) diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index 7ce55d331..5236ef58f 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,20 +15,22 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== + +import logging from sqlalchemy.orm import validates, reconstructor -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut +import eos.db from eos.effectHandlerHelpers import HandledItem, HandledCharge from eos.enum import Enum from eos.mathUtils import floorFloat -import eos.db +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut from eos.types import Citadel -import logging logger = logging.getLogger(__name__) + class State(Enum): def __init__(self): pass @@ -38,6 +40,7 @@ class State(Enum): ACTIVE = 1 OVERHEATED = 2 + class Slot(Enum): def __init__(self): pass @@ -60,6 +63,7 @@ class Slot(Enum): F_SUPPORT = 11 F_HEAVY = 12 + class Hardpoint(Enum): def __init__(self): pass @@ -68,10 +72,11 @@ class Hardpoint(Enum): MISSILE = 1 TURRET = 2 + class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): """An instance of this class represents a module together with its charge and modified attributes""" DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive") - MINING_ATTRIBUTES = ("miningAmount", ) + MINING_ATTRIBUTES = ("miningAmount",) def __init__(self, item): """Initialize a module from the program""" @@ -136,7 +141,6 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): self.__chargeModifiedAttributes.original = self.__charge.attributes self.__chargeModifiedAttributes.overrides = self.__charge.overrides - @classmethod def buildEmpty(cls, slot): empty = Module(None) @@ -163,7 +167,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def isInvalid(self): if self.isEmpty: return False - return self.__item is None or (self.__item.category.name not in ("Module", "Subsystem", "Structure Module") and self.__item.group.name != "Effect Beacon") + return self.__item is None or (self.__item.category.name not in ( + "Module", "Subsystem", "Structure Module") and self.__item.group.name != "Effect Beacon") @property def numCharges(self): @@ -261,7 +266,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): mass = self.getModifiedChargeAttr("mass") agility = self.getModifiedChargeAttr("agility") if maxVelocity and flightTime and mass and agility: - accelTime = min(flightTime, mass*agility/1000000) + accelTime = min(flightTime, mass * agility / 1000000) # Average distance done during acceleration duringAcceleration = maxVelocity / 2 * accelTime # Distance done after being at full speed @@ -279,7 +284,6 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def slot(self): return self.__slot - @property def itemModifiedAttributes(self): return self.__itemModifiedAttributes @@ -321,7 +325,9 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): else: func = self.getModifiedItemAttr - volley = sum(map(lambda attr: (func("%sDamage"%attr) or 0) * (1-getattr(targetResists, "%sAmount"%attr, 0)), self.DAMAGE_TYPES)) + volley = sum(map( + lambda attr: (func("%sDamage" % attr) or 0) * (1 - getattr(targetResists, "%sAmount" % attr, 0)), + self.DAMAGE_TYPES)) volley *= self.getModifiedItemAttr("damageMultiplier") or 1 if volley: cycleTime = self.cycleTime @@ -337,7 +343,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): self.__miningyield = 0 else: if self.state >= State.ACTIVE: - volley = self.getModifiedItemAttr("specialtyMiningAmount") or self.getModifiedItemAttr("miningAmount") or 0 + volley = self.getModifiedItemAttr("specialtyMiningAmount") or self.getModifiedItemAttr( + "miningAmount") or 0 if volley: cycleTime = self.cycleTime self.__miningyield = volley / (cycleTime / 1000.0) @@ -402,7 +409,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if shipGroup is not None: fitsOnGroup.add(shipGroup) - if (len(fitsOnGroup) > 0 or len(fitsOnType) > 0) and fit.ship.item.group.ID not in fitsOnGroup and fit.ship.item.ID not in fitsOnType: + if (len(fitsOnGroup) > 0 or len( + fitsOnType) > 0) and fit.ship.item.group.ID not in fitsOnGroup and fit.ship.item.ID not in fitsOnType: return False # AFAIK Citadel modules will always be restricted based on canFitShipType/Group. If we are fitting to a Citadel @@ -439,7 +447,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if (fit.ship.getModifiedItemAttr('turretSlotsLeft') or 0) - fit.getHardpointsUsed(Hardpoint.TURRET) < 1: return False elif self.hardpoint == Hardpoint.MISSILE: - if (fit.ship.getModifiedItemAttr('launcherSlotsLeft')or 0) - fit.getHardpointsUsed(Hardpoint.MISSILE) < 1: + if (fit.ship.getModifiedItemAttr('launcherSlotsLeft') or 0) - fit.getHardpointsUsed( + Hardpoint.MISSILE) < 1: return False return True @@ -448,7 +457,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): """ Check if the state is valid for this module, without considering other modules at all """ - #Check if we're within bounds + # Check if we're within bounds if state < -1 or state > 2: return False elif state >= State.ACTIVE and not self.item.isType("active"): @@ -501,7 +510,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return True def isValidCharge(self, charge): - #Check sizes, if 'charge size > module volume' it won't fit + # Check sizes, if 'charge size > module volume' it won't fit if charge is None: return True chargeVolume = charge.volume moduleCapacity = self.item.capacity @@ -534,11 +543,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if singleItem.published and self.isValidCharge(singleItem): validCharges.add(singleItem) - return validCharges def __calculateHardpoint(self, item): - effectHardpointMap = {"turretFitted" : Hardpoint.TURRET, + effectHardpointMap = {"turretFitted": Hardpoint.TURRET, "launcherFitted": Hardpoint.MISSILE} if item is None: @@ -551,11 +559,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return Hardpoint.NONE def __calculateSlot(self, item): - effectSlotMap = {"rigSlot" : Slot.RIG, - "loPower" : Slot.LOW, - "medPower" : Slot.MED, - "hiPower" : Slot.HIGH, - "subSystem" : Slot.SUBSYSTEM, + effectSlotMap = {"rigSlot": Slot.RIG, + "loPower": Slot.LOW, + "medPower": Slot.MED, + "hiPower": Slot.HIGH, + "subSystem": Slot.SUBSYSTEM, "serviceSlot": Slot.SERVICE} if item is None: return None @@ -570,11 +578,13 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @validates("ID", "itemID", "ammoID") def validator(self, key, val): map = {"ID": lambda val: isinstance(val, int), - "itemID" : lambda val: val is None or isinstance(val, int), - "ammoID" : lambda val: isinstance(val, int)} + "itemID": lambda val: val is None or isinstance(val, int), + "ammoID": lambda val: isinstance(val, int)} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val def clear(self): self.__dps = None @@ -586,15 +596,15 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): self.itemModifiedAttributes.clear() self.chargeModifiedAttributes.clear() - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): - #We will run the effect when two conditions are met: - #1: It makes sense to run the effect + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): + # We will run the effect when two conditions are met: + # 1: It makes sense to run the effect # The effect is either offline # or the effect is passive and the module is in the online state (or higher) # or the effect is active and the module is in the active state (or higher) # or the effect is overheat and the module is in the overheated state (or higher) - #2: the runtimes match + # 2: the runtimes match if self.projected or forceProjected: context = "projected", "module" @@ -614,8 +624,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if self.state >= State.OVERHEATED: for effect in self.item.effects.itervalues(): if effect.runTime == runTime and \ - effect.isType("overheat") and \ - not forceProjected: + effect.isType("overheat") and \ + not forceProjected: effect.handler(fit, self, context) for effect in self.item.effects.itervalues(): @@ -682,6 +692,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): else: return "EmptyModule() at {}".format(hex(id(self))) + class Rack(Module): """ This is simply the Module class named something else to differentiate diff --git a/eos/saveddata/override.py b/eos/saveddata/override.py index b33875e89..c4f8a1e02 100644 --- a/eos/saveddata/override.py +++ b/eos/saveddata/override.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2015 Ryan Holmes # # This file is part of eos. @@ -15,17 +15,19 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.eqBase import EqBase -from sqlalchemy.orm import validates, reconstructor -import eos.db import logging +from sqlalchemy.orm import reconstructor + +import eos.db +from eos.eqBase import EqBase + logger = logging.getLogger(__name__) -class Override(EqBase): +class Override(EqBase): def __init__(self, item, attr, value): self.itemID = item.ID self.__item = item diff --git a/eos/saveddata/price.py b/eos/saveddata/price.py index ea9b0ac92..8074373df 100644 --- a/eos/saveddata/price.py +++ b/eos/saveddata/price.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # Copyright (C) 2011 Anton Vorobyov # @@ -16,13 +16,14 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== import time + from sqlalchemy.orm import reconstructor -class Price(object): +class Price(object): def __init__(self, typeID): self.typeID = typeID self.time = 0 diff --git a/eos/saveddata/ship.py b/eos/saveddata/ship.py index 4094534e6..3cf179ec2 100644 --- a/eos/saveddata/ship.py +++ b/eos/saveddata/ship.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,16 +15,18 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== -from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, cappingAttrKeyCache -from eos.effectHandlerHelpers import HandledItem -from eos.saveddata.mode import Mode -import eos.db import logging +import eos.db +from eos.effectHandlerHelpers import HandledItem +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, cappingAttrKeyCache +from eos.saveddata.mode import Mode + logger = logging.getLogger(__name__) + class Ship(ItemAttrShortcut, HandledItem): EXTRA_ATTRIBUTES = { "armorRepair": 0, @@ -50,7 +52,7 @@ class Ship(ItemAttrShortcut, HandledItem): self.__itemModifiedAttributes.original = dict(self.item.attributes) self.__itemModifiedAttributes.original.update(self.EXTRA_ATTRIBUTES) self.__itemModifiedAttributes.overrides = self.item.overrides - + if "maximumRangeCap" in self.__itemModifiedAttributes.original: cappingAttrKeyCache["maxTargetRange"] = "maximumRangeCap" @@ -61,7 +63,8 @@ class Ship(ItemAttrShortcut, HandledItem): def validate(self, item): if item.category.name != "Ship": - raise ValueError('Passed item "%s" (category: (%s)) is not under Ship category'%(item.name, item.category.name)) + raise ValueError( + 'Passed item "%s" (category: (%s)) is not under Ship category' % (item.name, item.category.name)) @property def item(self): @@ -75,7 +78,7 @@ class Ship(ItemAttrShortcut, HandledItem): self.itemModifiedAttributes.clear() self.commandBonus = 0 - def calculateModifiedAttributes(self, fit, runTime, forceProjected = False): + def calculateModifiedAttributes(self, fit, runTime, forceProjected=False): if forceProjected: return for effect in self.item.effects.itervalues(): if effect.runTime == runTime and effect.isType("passive"): diff --git a/eos/saveddata/targetResists.py b/eos/saveddata/targetResists.py index 8798ebf19..8b286b3f6 100644 --- a/eos/saveddata/targetResists.py +++ b/eos/saveddata/targetResists.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2014 Ryan Holmes # # This file is part of eos. @@ -15,15 +15,16 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== import re + class TargetResists(object): # also determined import/export order - VERY IMPORTANT DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive") - def __init__(self, emAmount = 0, thermalAmount = 0, kineticAmount = 0, explosiveAmount = 0): + def __init__(self, emAmount=0, thermalAmount=0, kineticAmount=0, explosiveAmount=0): self.emAmount = emAmount self.thermalAmount = thermalAmount self.kineticAmount = kineticAmount @@ -38,8 +39,8 @@ class TargetResists(object): try: if line.strip()[0] == "#": # comments continue - line = line.split('#',1)[0] # allows for comments - type, data = line.rsplit('=',1) + line = line.split('#', 1)[0] # allows for comments + type, data = line.rsplit('=', 1) type, data = type.strip(), data.split(',') except: # Data isn't in correct format, continue to next line @@ -56,11 +57,11 @@ class TargetResists(object): val = float(val) try: assert 0 <= val <= 100 - fields["%sAmount" % cls.DAMAGE_TYPES[index]] = val/100 + fields["%sAmount" % cls.DAMAGE_TYPES[index]] = val / 100 except: continue - if len(fields) == 4: # Avoid possible blank lines + if len(fields) == 4: # Avoid possible blank lines pattern = TargetResists(**fields) pattern.name = name.strip() patterns.append(pattern) @@ -68,13 +69,15 @@ class TargetResists(object): return patterns, numPatterns EXPORT_FORMAT = "TargetResists = %s,%.1f,%.1f,%.1f,%.1f\n" + @classmethod def exportPatterns(cls, *patterns): - out = "# Exported from pyfa\n#\n" + out = "# Exported from pyfa\n#\n" out += "# Values are in following format:\n" out += "# TargetResists = [name],[EM %],[Thermal %],[Kinetic %],[Explosive %]\n\n" for dp in patterns: - out += cls.EXPORT_FORMAT % (dp.name, dp.emAmount*100, dp.thermalAmount*100, dp.kineticAmount*100, dp.explosiveAmount*100) + out += cls.EXPORT_FORMAT % ( + dp.name, dp.emAmount * 100, dp.thermalAmount * 100, dp.kineticAmount * 100, dp.explosiveAmount * 100) return out.strip() diff --git a/eos/saveddata/user.py b/eos/saveddata/user.py index 26144feb0..25015c2c5 100644 --- a/eos/saveddata/user.py +++ b/eos/saveddata/user.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of eos. @@ -15,15 +15,17 @@ # # You should have received a copy of the GNU Lesser General Public License # along with eos. If not, see . -#=============================================================================== +# =============================================================================== + +import hashlib +import random +import string from sqlalchemy.orm import validates -import hashlib -import string -import random + class User(object): - def __init__(self, username, password = None, admin = False): + def __init__(self, username, password=None, admin=False): self.username = username if password is not None: self.encodeAndSetPassword(password) self.admin = admin @@ -46,9 +48,11 @@ class User(object): @validates("ID", "username", "password", "admin") def validator(self, key, val): map = {"ID": lambda val: isinstance(val, int), - "username" : lambda val: isinstance(val, basestring), - "password" : lambda val: isinstance(val, basestring) and len(val) == 96, - "admin" : lambda val: isinstance(val, bool)} + "username": lambda val: isinstance(val, basestring), + "password": lambda val: isinstance(val, basestring) and len(val) == 96, + "admin": lambda val: isinstance(val, bool)} - if not map[key](val): raise ValueError(str(val) + " is not a valid value for " + key) - else: return val + if not map[key](val): + raise ValueError(str(val) + " is not a valid value for " + key) + else: + return val