Reformatting eos.saveddata

This commit is contained in:
Ebag333
2016-10-19 11:42:45 -07:00
parent b4360d44f1
commit f9f53a13c0
21 changed files with 366 additions and 289 deletions

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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:

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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(

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
from eos.eqBase import EqBase
class MiscData(EqBase):
def __init__(self, name, val=None):
self.fieldName = name

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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",))

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
import time
from sqlalchemy.orm import reconstructor
class Price(object):
class Price(object):
def __init__(self, typeID):
self.typeID = typeID
self.time = 0

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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"):

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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()

View File

@@ -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 <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
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