Replace submodules with actual files
Submodules never were actually useful
This commit is contained in:
116
eos/graph/__init__.py
Executable file
116
eos/graph/__init__.py
Executable file
@@ -0,0 +1,116 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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 itertools
|
||||
|
||||
class Graph(object):
|
||||
def __init__(self, fit, function, data = None):
|
||||
self.fit = fit
|
||||
self.data = {}
|
||||
if data is not None:
|
||||
for name, d in data.iteritems():
|
||||
self.setData(Data(name, d))
|
||||
|
||||
self.function = function
|
||||
|
||||
def clearData(self):
|
||||
self.data.clear()
|
||||
|
||||
def setData(self, data):
|
||||
self.data[data.name] = data
|
||||
|
||||
def getIterator(self):
|
||||
pointNames = []
|
||||
pointIterators = []
|
||||
for data in self.data.itervalues():
|
||||
pointNames.append(data.name)
|
||||
pointIterators.append(data)
|
||||
|
||||
return self._iterator(pointNames, pointIterators)
|
||||
|
||||
def _iterator(self, pointNames, pointIterators):
|
||||
for pointValues in itertools.product(*pointIterators):
|
||||
point = {}
|
||||
for i in xrange(len(pointValues)):
|
||||
point[pointNames[i]] = pointValues[i]
|
||||
|
||||
yield point, self.function(point)
|
||||
|
||||
|
||||
class Data(object):
|
||||
def __init__(self, name, dataString, step=None):
|
||||
self.name = name
|
||||
self.step = step
|
||||
self.data = self.parseString(dataString)
|
||||
|
||||
def parseString(self, dataString):
|
||||
if not isinstance(dataString, basestring):
|
||||
return (Constant(dataString),)
|
||||
|
||||
dataList = []
|
||||
for data in dataString.split(";"):
|
||||
if isinstance(data, basestring) and "-" in data:
|
||||
#Dealing with a range
|
||||
dataList.append(Range(data, self.step))
|
||||
else:
|
||||
dataList.append(Constant(data))
|
||||
|
||||
return dataList
|
||||
|
||||
def __iter__(self):
|
||||
for data in self.data:
|
||||
for value in data:
|
||||
yield value
|
||||
|
||||
def isConstant(self):
|
||||
return len(self.data) == 1 and self.data[0].isConstant()
|
||||
|
||||
|
||||
class Constant(object):
|
||||
def __init__(self, const):
|
||||
if isinstance(const, basestring):
|
||||
self.value = None if const == "" else float(const)
|
||||
else:
|
||||
self.value = const
|
||||
|
||||
def __iter__(self):
|
||||
yield self.value
|
||||
|
||||
def isConstant(self):
|
||||
return True
|
||||
|
||||
class Range(object):
|
||||
def __init__(self, string, step):
|
||||
start, end = string.split("-")
|
||||
self.start = float(start)
|
||||
self.end = float(end)
|
||||
self.step = step
|
||||
|
||||
def __iter__(self):
|
||||
current = start = self.start
|
||||
end = self.end
|
||||
step = self.step or (end - start) / 50.0
|
||||
i = 1
|
||||
while current < end:
|
||||
current = start + i * step
|
||||
i += 1
|
||||
yield current
|
||||
|
||||
def isConstant(self):
|
||||
return False
|
||||
98
eos/graph/fitDps.py
Executable file
98
eos/graph/fitDps.py
Executable file
@@ -0,0 +1,98 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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.graph import Graph, Data
|
||||
from eos.types import Hardpoint, State
|
||||
from math import log, sin, radians
|
||||
|
||||
class FitDpsGraph(Graph):
|
||||
defaults = {"angle": 0,
|
||||
"distance": 0,
|
||||
"signatureRadius": None,
|
||||
"velocity": 0}
|
||||
|
||||
def __init__(self, fit, data=None):
|
||||
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
|
||||
self.fit = fit
|
||||
|
||||
def calcDps(self, data):
|
||||
fit = self.fit
|
||||
total = 0
|
||||
distance = data["distance"] * 1000
|
||||
for mod in fit.modules:
|
||||
if mod.hardpoint == Hardpoint.TURRET:
|
||||
if mod.state >= State.ACTIVE:
|
||||
total += mod.dps * self.calculateTurretMultiplier(mod, data)
|
||||
|
||||
elif mod.hardpoint == Hardpoint.MISSILE:
|
||||
if mod.state >= State.ACTIVE and mod.maxRange >= distance:
|
||||
total += mod.dps * self.calculateMissileMultiplier(mod, data)
|
||||
|
||||
if distance <= fit.extraAttributes["droneControlRange"]:
|
||||
for drone in fit.drones:
|
||||
multiplier = 1 if drone.getModifiedItemAttr("maxVelocity") > 0 else self.calculateTurretMultiplier(drone, data)
|
||||
total += drone.dps * multiplier
|
||||
|
||||
return total
|
||||
|
||||
def calculateMissileMultiplier(self, mod, data):
|
||||
targetSigRad = data["signatureRadius"]
|
||||
targetVelocity = data["velocity"]
|
||||
explosionRadius = mod.getModifiedChargeAttr("aoeCloudSize")
|
||||
targetSigRad = explosionRadius if targetSigRad is None else targetSigRad
|
||||
explosionVelocity = mod.getModifiedChargeAttr("aoeVelocity")
|
||||
damageReductionFactor = mod.getModifiedChargeAttr("aoeDamageReductionFactor")
|
||||
damageReductionSensitivity = mod.getModifiedChargeAttr("aoeDamageReductionSensitivity")
|
||||
|
||||
sigRadiusFactor = targetSigRad / explosionRadius
|
||||
if targetVelocity:
|
||||
velocityFactor = (explosionVelocity / explosionRadius * targetSigRad / targetVelocity) ** (log(damageReductionFactor) / log(damageReductionSensitivity))
|
||||
else:
|
||||
velocityFactor = 1
|
||||
return min(sigRadiusFactor, velocityFactor, 1)
|
||||
|
||||
def calculateTurretMultiplier(self, mod, data):
|
||||
#Source for most of turret calculation info: http://wiki.eveonline.com/en/wiki/Falloff
|
||||
chanceToHit = self.calculateTurretChanceToHit(mod, data)
|
||||
if chanceToHit > 0.01:
|
||||
#AvgDPS = Base Damage * [ ( ChanceToHit^2 + ChanceToHit + 0.0499 ) / 2 ]
|
||||
multiplier = (chanceToHit ** 2 + chanceToHit + 0.0499) / 2
|
||||
else:
|
||||
#All hits are wreckings
|
||||
multiplier = chanceToHit * 3
|
||||
dmgScaling = mod.getModifiedItemAttr("turretDamageScalingRadius")
|
||||
if dmgScaling:
|
||||
targetSigRad = data["signatureRadius"]
|
||||
multiplier = min(1, (float(targetSigRad) / dmgScaling) ** 2)
|
||||
return multiplier
|
||||
|
||||
def calculateTurretChanceToHit(self, mod, data):
|
||||
distance = data["distance"] * 1000
|
||||
tracking = mod.getModifiedItemAttr("trackingSpeed")
|
||||
turretOptimal = mod.maxRange
|
||||
turretFalloff = mod.falloff
|
||||
turretSigRes = mod.getModifiedItemAttr("optimalSigRadius")
|
||||
targetSigRad = data["signatureRadius"]
|
||||
targetSigRad = turretSigRes if targetSigRad is None else targetSigRad
|
||||
transversal = sin(radians(data["angle"])) * data["velocity"]
|
||||
trackingEq = (((transversal / (distance * tracking)) *
|
||||
(turretSigRes / targetSigRad)) ** 2)
|
||||
rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2
|
||||
|
||||
return 0.5 ** (trackingEq + rangeEq)
|
||||
Reference in New Issue
Block a user