Merge remote-tracking branch 'origin/master' into singularity
This commit is contained in:
186
.appveyor.yml
Normal file
186
.appveyor.yml
Normal file
@@ -0,0 +1,186 @@
|
||||
environment:
|
||||
|
||||
global:
|
||||
# SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
|
||||
# /E:ON and /V:ON options are not enabled in the batch script intepreter
|
||||
# See: http://stackoverflow.com/a/13751649/163740
|
||||
CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
|
||||
|
||||
matrix:
|
||||
|
||||
# Python 2.7.10 is the latest version and is not pre-installed.
|
||||
|
||||
- PYTHON: "C:\\Python27.10"
|
||||
PYTHON_VERSION: "2.7.10"
|
||||
PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python27.10-x64"
|
||||
# PYTHON_VERSION: "2.7.10"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
# Pre-installed Python versions, which Appveyor may upgrade to
|
||||
# a later point release.
|
||||
# See: http://www.appveyor.com/docs/installed-software#python
|
||||
|
||||
#- PYTHON: "C:\\Python27"
|
||||
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python27-x64"
|
||||
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
#- PYTHON: "C:\\Python33"
|
||||
# PYTHON_VERSION: "3.3.x" # currently 3.3.5
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python33-x64"
|
||||
# PYTHON_VERSION: "3.3.x" # currently 3.3.5
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
#- PYTHON: "C:\\Python34"
|
||||
# PYTHON_VERSION: "3.4.x" # currently 3.4.3
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python34-x64"
|
||||
# PYTHON_VERSION: "3.4.x" # currently 3.4.3
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
# Python versions not pre-installed
|
||||
|
||||
# Python 2.6.6 is the latest Python 2.6 with a Windows installer
|
||||
# See: https://github.com/ogrisel/python-appveyor-demo/issues/10
|
||||
|
||||
#- PYTHON: "C:\\Python266"
|
||||
# PYTHON_VERSION: "2.6.6"
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python266-x64"
|
||||
# PYTHON_VERSION: "2.6.6"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
#- PYTHON: "C:\\Python35"
|
||||
# PYTHON_VERSION: "3.5.0"
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python35-x64"
|
||||
# PYTHON_VERSION: "3.5.0"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
# Major and minor releases (i.e x.0.0 and x.y.0) prior to 3.3.0 use
|
||||
# a different naming scheme.
|
||||
|
||||
#- PYTHON: "C:\\Python270"
|
||||
# PYTHON_VERSION: "2.7.0"
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python270-x64"
|
||||
# PYTHON_VERSION: "2.7.0"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
install:
|
||||
# If there is a newer build queued for the same PR, cancel this one.
|
||||
# The AppVeyor 'rollout builds' option is supposed to serve the same
|
||||
# purpose but it is problematic because it tends to cancel builds pushed
|
||||
# directly to master instead of just PR builds (or the converse).
|
||||
# credits: JuliaLang developers.
|
||||
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
|
||||
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
|
||||
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
|
||||
throw "There are newer queued builds for this pull request, failing early." }
|
||||
|
||||
# Install wxPython
|
||||
- 'ECHO Downloading wxPython.'
|
||||
- "appveyor DownloadFile https://goo.gl/yvO8PB -FileName C:\\wxpython.exe"
|
||||
#- "appveyor DownloadFile https://goo.gl/Uj0jV3 -FileName C:\\wxpython64.exe"
|
||||
|
||||
- 'ECHO Install wxPython'
|
||||
- "C:\\wxpython.exe /SP- /VERYSILENT /NORESTART"
|
||||
#- "C:\\wxpython64.exe /SP- /VERYSILENT /NORESTART"
|
||||
|
||||
- ECHO "Filesystem root:"
|
||||
- ps: "ls \"C:/\""
|
||||
|
||||
- ECHO "Filesystem pyfa root:"
|
||||
- ps: "ls \"C:\\projects\\pyfa\\\""
|
||||
|
||||
- ECHO "Installed SDKs:"
|
||||
- ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
|
||||
|
||||
# Install Python (from the official .msi of http://python.org) and pip when
|
||||
# not already installed.
|
||||
# - ps: if (-not(Test-Path($env:PYTHON))) { & appveyor\install.ps1 }
|
||||
|
||||
# Prepend newly installed Python to the PATH of this build (this cannot be
|
||||
# done from inside the powershell script as it would require to restart
|
||||
# the parent CMD process).
|
||||
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
|
||||
# Check that we have the expected version and architecture for Python
|
||||
- "python --version"
|
||||
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
|
||||
|
||||
# Upgrade to the latest version of pip to avoid it displaying warnings
|
||||
# about it being out of date.
|
||||
- "pip install --disable-pip-version-check --user --upgrade pip"
|
||||
|
||||
# Install the build dependencies of the project. If some dependencies contain
|
||||
# compiled extensions and are not provided as pre-built wheel packages,
|
||||
# pip will build them from source using the MSVC compiler matching the
|
||||
# target Python version and architecture
|
||||
# C:\\projects\\eve-gnosis\\
|
||||
- ECHO "Install pip requirements:"
|
||||
- "pip install -r requirements.txt"
|
||||
- "pip install -r requirements_test.txt"
|
||||
- "pip install -r requirements_build_windows.txt"
|
||||
|
||||
build_script:
|
||||
# Build the compiled extension
|
||||
# - "python setup.py build"
|
||||
- ECHO "Build pyfa:"
|
||||
#- copy C:\projects\pyfa\dist_assets\win\pyfa.spec C:\projects\pyfa\pyfa.spec
|
||||
- "python C:\\projects\\pyfa\\setup.py build"
|
||||
|
||||
#- ECHO "Build pyfa (Debug):"
|
||||
#- copy C:\projects\pyfa\dist_assets\win\pyfa_debug.spec C:\projects\pyfa\pyfa_debug.spec
|
||||
#- "pyinstaller.exe --clean --noconfirm --windowed --upx-dir=C:\\projects\\pyfa\\scripts\\upx.exe C:\\projects\\pyfa\\pyfa_debug.spec"
|
||||
|
||||
build: on
|
||||
|
||||
after_build:
|
||||
- ps: "ls \"./\""
|
||||
#- ps: "ls \"C:\\projects\\pyfa\\build\\pyfa\\\""
|
||||
- ps: "ls \"C:\\projects\\pyfa\\build\\\""
|
||||
- ps: "ls \"C:\\projects\\pyfa\\build\\exe.win32-2.7\\\""
|
||||
# Zip
|
||||
# APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER
|
||||
#- 7z a build.zip -r C:\projects\pyfa\build\pyfa\*.*
|
||||
- 7z a pyfa.zip -r C:\projects\pyfa\build\exe.win32-2.7\*.*
|
||||
#- 7z a pyfa_debug.zip -r C:\projects\pyfa\dist\pyfa_debug\*.*
|
||||
|
||||
on_success:
|
||||
# Do nothing right now
|
||||
|
||||
test_script:
|
||||
#- tox
|
||||
#- "py.test --cov=./"
|
||||
# Run the project tests
|
||||
# - "%CMD_IN_ENV% python C:/projects/eve-gnosis/setup.py nosetests"
|
||||
|
||||
after_test:
|
||||
# If tests are successful, create binary packages for the project.
|
||||
# - "%CMD_IN_ENV% python setup.py bdist_wheel"
|
||||
# - "%CMD_IN_ENV% python setup.py bdist_wininst"
|
||||
# - "%CMD_IN_ENV% python setup.py bdist_msi"
|
||||
# - ps: "ls dist"
|
||||
|
||||
artifacts:
|
||||
# Archive the generated packages in the ci.appveyor.com build report.
|
||||
- path: pyfa.zip
|
||||
name: 'pyfa.zip'
|
||||
#- path: pyfa_debug.zip
|
||||
# name: Pyfa_debug
|
||||
|
||||
#on_success:
|
||||
# - TODO: upload the content of dist/*.whl to a public wheelhouse
|
||||
#
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -49,7 +49,6 @@ Pyfa.egg-info/
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# pyfa
|
||||
|
||||
[](https://pyfainvite.azurewebsites.net/)
|
||||
[](https://pyfainvite.azurewebsites.net/) [](https://travis-ci.org/pyfa-org/Pyfa)
|
||||
|
||||

|
||||
|
||||
@@ -42,6 +42,7 @@ If you wish to help with development or simply need to run pyfa through a Python
|
||||
* `dateutil`
|
||||
* `matplotlib` (for some Linux distributions you may need to install separate wxPython bindings such as `python-matplotlib-wx`)
|
||||
* `requests`
|
||||
* `logbook` >= 1.0.0
|
||||
|
||||
## Bug Reporting
|
||||
The preferred method of reporting bugs is through the project's [GitHub Issues interface](https://github.com/pyfa-org/Pyfa/issues). Alternatively, posting a report in the [pyfa thread](http://forums.eveonline.com/default.aspx?g=posts&t=247609) on the official EVE Online forums is acceptable. Guidelines for bug reporting can be found on [this wiki page](https://github.com/DarkFenX/Pyfa/wiki/Bug-Reporting).
|
||||
@@ -51,8 +52,7 @@ pyfa is licensed under the GNU GPL v3.0, see LICENSE
|
||||
|
||||
## Resources
|
||||
* Development repository: [https://github.com/pyfa-org/Pyfa](https://github.com/pyfa-org/Pyfa)
|
||||
* XMPP conference: [pyfa@conference.jabber.org](pyfa@conference.jabber.org)
|
||||
* [EVE forum thread](http://forums.eveonline.com/default.aspx?g=posts&t=247609)
|
||||
* [EVE forum thread](https://forums.eveonline.com/default.aspx?g=posts&t=466425)
|
||||
* [EVE University guide using pyfa](http://wiki.eveuniversity.org/Guide_to_using_PYFA)
|
||||
* [EVE Online website](http://www.eveonline.com/)
|
||||
|
||||
|
||||
13
_development/Pyfa_CodeStyle.xml
Normal file
13
_development/Pyfa_CodeStyle.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<code_scheme name="Pyfa">
|
||||
<option name="LINE_SEPARATOR" value="
" />
|
||||
<option name="RIGHT_MARGIN" value="165" />
|
||||
<Python>
|
||||
<option name="NEW_LINE_AFTER_COLON" value="true" />
|
||||
<option name="DICT_ALIGNMENT" value="2" />
|
||||
<option name="DICT_NEW_LINE_AFTER_LEFT_BRACE" value="true" />
|
||||
<option name="DICT_NEW_LINE_BEFORE_RIGHT_BRACE" value="true" />
|
||||
<option name="USE_CONTINUATION_INDENT_FOR_ARGUMENTS" value="true" />
|
||||
<option name="OPTIMIZE_IMPORTS_SORT_NAMES_IN_FROM_IMPORTS" value="true" />
|
||||
<option name="OPTIMIZE_IMPORTS_JOIN_FROM_IMPORTS_WITH_SAME_SOURCE" value="true" />
|
||||
</Python>
|
||||
</code_scheme>
|
||||
54
_development/Pyfa_Inspections.xml
Normal file
54
_development/Pyfa_Inspections.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Pyfa" />
|
||||
<inspection_tool class="IgnoreUnusedEntry" enabled="false" level="UNUSED ENTRY" enabled_by_default="false" />
|
||||
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyBehaveInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyClassicStyleClassInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ourVersions">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="2.7" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="wxPython" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8Inspection" enabled="true" level="TYPO" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="E203" />
|
||||
<option value="E127" />
|
||||
<option value="E128" />
|
||||
<option value="E126" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="TYPO" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="N802" />
|
||||
<option value="N806" />
|
||||
<option value="N803" />
|
||||
<option value="N814" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyShadowingNamesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
123
config.py
123
config.py
@@ -1,27 +1,28 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# TODO: move all logging back to pyfa.py main loop
|
||||
# We moved it here just to avoid rebuilding windows skeleton for now (any change to pyfa.py needs it)
|
||||
import logging
|
||||
import logging.handlers
|
||||
from logbook import Logger
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
# Load variable overrides specific to distribution type
|
||||
try:
|
||||
import configforced
|
||||
except ImportError:
|
||||
pyfalog.warning("Failed to import: configforced")
|
||||
configforced = None
|
||||
|
||||
|
||||
# Turns on debug mode
|
||||
debug = False
|
||||
# Defines if our saveddata will be in pyfa root or not
|
||||
saveInRoot = False
|
||||
|
||||
# Version data
|
||||
version = "1.26.1"
|
||||
version = "1.28.2"
|
||||
tag = "git"
|
||||
expansionName = "YC118.10"
|
||||
expansionVersion = "1.2"
|
||||
expansionName = "YC119.3"
|
||||
expansionVersion = "1.0"
|
||||
evemonMinVersion = "4081"
|
||||
|
||||
pyfaPath = None
|
||||
@@ -30,22 +31,6 @@ saveDB = None
|
||||
gameDB = None
|
||||
|
||||
|
||||
class StreamToLogger(object):
|
||||
"""
|
||||
Fake file-like stream object that redirects writes to a logger instance.
|
||||
From: http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/
|
||||
"""
|
||||
|
||||
def __init__(self, logger, log_level=logging.INFO):
|
||||
self.logger = logger
|
||||
self.log_level = log_level
|
||||
self.linebuf = ''
|
||||
|
||||
def write(self, buf):
|
||||
for line in buf.rstrip().splitlines():
|
||||
self.logger.log(self.log_level, line.rstrip())
|
||||
|
||||
|
||||
def isFrozen():
|
||||
if hasattr(sys, 'frozen'):
|
||||
return True
|
||||
@@ -58,6 +43,17 @@ def __createDirs(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def getPyfaRoot():
|
||||
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
|
||||
root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
|
||||
root = unicode(root, sys.getfilesystemencoding())
|
||||
return root
|
||||
|
||||
|
||||
def getDefaultSave():
|
||||
return unicode(os.path.expanduser(os.path.join("~", ".pyfa")), sys.getfilesystemencoding())
|
||||
|
||||
|
||||
def defPaths(customSavePath):
|
||||
global debug
|
||||
global pyfaPath
|
||||
@@ -66,65 +62,42 @@ def defPaths(customSavePath):
|
||||
global gameDB
|
||||
global saveInRoot
|
||||
|
||||
if debug:
|
||||
logLevel = logging.DEBUG
|
||||
else:
|
||||
logLevel = logging.WARN
|
||||
pyfalog.debug("Configuring Pyfa")
|
||||
|
||||
# The main pyfa directory which contains run.py
|
||||
# Python 2.X uses ANSI by default, so we need to convert the character encoding
|
||||
pyfaPath = getattr(configforced, "pyfaPath", pyfaPath)
|
||||
if pyfaPath is None:
|
||||
pyfaPath = getPyfaPath()
|
||||
pyfaPath = getPyfaRoot()
|
||||
|
||||
# Where we store the saved fits etc, default is the current users home directory
|
||||
if saveInRoot is True:
|
||||
savePath = getattr(configforced, "savePath", None)
|
||||
if savePath is None:
|
||||
savePath = getPyfaPath("saveddata")
|
||||
savePath = os.path.join(pyfaPath, "saveddata")
|
||||
else:
|
||||
savePath = getattr(configforced, "savePath", None)
|
||||
if savePath is None:
|
||||
if customSavePath is None: # customSavePath is not overriden
|
||||
savePath = os.path.expanduser(os.path.join("~", ".pyfa"))
|
||||
savePath = getDefaultSave()
|
||||
else:
|
||||
savePath = customSavePath
|
||||
|
||||
__createDirs(savePath)
|
||||
|
||||
if isFrozen():
|
||||
certName = "cacert.pem"
|
||||
os.environ["REQUESTS_CA_BUNDLE"] = getPyfaPath(certName).encode('utf8')
|
||||
os.environ["SSL_CERT_FILE"] = getPyfaPath(certName).encode('utf8')
|
||||
|
||||
loggingFormat = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s'
|
||||
logging.basicConfig(format=loggingFormat, level=logLevel)
|
||||
handler = logging.handlers.RotatingFileHandler(getSavePath("log.txt"), maxBytes=1000000, backupCount=3)
|
||||
formatter = logging.Formatter(loggingFormat)
|
||||
handler.setFormatter(formatter)
|
||||
logging.getLogger('').addHandler(handler)
|
||||
|
||||
logging.info("Starting pyfa")
|
||||
|
||||
if hasattr(sys, 'frozen'):
|
||||
stdout_logger = logging.getLogger('STDOUT')
|
||||
sl = StreamToLogger(stdout_logger, logging.INFO)
|
||||
sys.stdout = sl
|
||||
|
||||
# This interferes with cx_Freeze's own handling of exceptions. Find a way to fix this.
|
||||
# stderr_logger = logging.getLogger('STDERR')
|
||||
# sl = StreamToLogger(stderr_logger, logging.ERROR)
|
||||
# sys.stderr = sl
|
||||
os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8')
|
||||
os.environ["SSL_CERT_FILE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8')
|
||||
|
||||
# The database where we store all the fits etc
|
||||
saveDB = getSavePath("saveddata.db")
|
||||
saveDB = os.path.join(savePath, "saveddata.db")
|
||||
|
||||
# The database where the static EVE data from the datadump is kept.
|
||||
# This is not the standard sqlite datadump but a modified version created by eos
|
||||
# maintenance script
|
||||
gameDB = getPyfaPath("eve.db")
|
||||
gameDB = os.path.join(pyfaPath, "eve.db")
|
||||
|
||||
# DON'T MODIFY ANYTHING BELOW!
|
||||
# DON'T MODIFY ANYTHING BELOW
|
||||
import eos.config
|
||||
|
||||
# Caching modifiers, disable all gamedata caching, its unneeded.
|
||||
@@ -133,40 +106,6 @@ def defPaths(customSavePath):
|
||||
eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False"
|
||||
eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False"
|
||||
|
||||
|
||||
def getPyfaPath(Append=None):
|
||||
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
|
||||
root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
|
||||
|
||||
if Append:
|
||||
path = parsePath(root, Append)
|
||||
else:
|
||||
path = parsePath(root)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def getSavePath(Append=None):
|
||||
root = savePath
|
||||
|
||||
if Append:
|
||||
path = parsePath(root, Append)
|
||||
else:
|
||||
path = parsePath(root)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def parsePath(root, Append=None):
|
||||
if Append:
|
||||
path = os.path.join(root, Append)
|
||||
else:
|
||||
path = root
|
||||
|
||||
if type(path) == str: # leave unicode ones alone
|
||||
try:
|
||||
path = path.decode('utf8')
|
||||
except UnicodeDecodeError:
|
||||
path = path.decode('windows-1252')
|
||||
|
||||
return path
|
||||
# initialize the settings
|
||||
from service.settings import EOSSettings
|
||||
eos.config.settings = EOSSettings.getInstance().EOSSettings # this is kind of confusing, but whatever
|
||||
|
||||
5666
dist_assets/cacert.pem
Normal file
5666
dist_assets/cacert.pem
Normal file
File diff suppressed because it is too large
Load Diff
83
dist_assets/win/pyfa.spec
Normal file
83
dist_assets/win/pyfa.spec
Normal file
@@ -0,0 +1,83 @@
|
||||
# -*- mode: python -*-
|
||||
|
||||
# Note: This script is provided AS-IS for those that may be interested.
|
||||
# pyfa does not currently support pyInstaller (or any other build process) 100% at the moment
|
||||
|
||||
# Command line to build:
|
||||
# (Run from directory where pyfa.py and pyfa.spec lives.)
|
||||
# c:\Python27\scripts\pyinstaller.exe --clean --noconfirm --windowed --upx-dir=.\scripts\upx.exe pyfa.spec
|
||||
|
||||
# Don't forget to change the path to where your pyfa.py and pyfa.spec lives
|
||||
# pathex=['C:\\Users\\Ebag333\\Documents\\GitHub\\Ebag333\\Pyfa'],
|
||||
|
||||
import os
|
||||
|
||||
block_cipher = None
|
||||
|
||||
added_files = [
|
||||
( 'imgs/gui/*.png', 'imgs/gui' ),
|
||||
( 'imgs/gui/*.gif', 'imgs/gui' ),
|
||||
( 'imgs/icons/*.png', 'imgs/icons' ),
|
||||
( 'imgs/renders/*.png', 'imgs/renders' ),
|
||||
( 'dist_assets/win/pyfa.ico', '.' ),
|
||||
( 'dist_assets/cacert.pem', '.' ),
|
||||
( 'eve.db', '.' ),
|
||||
( 'README.md', '.' ),
|
||||
( 'LICENSE', '.' ),
|
||||
]
|
||||
|
||||
import_these = []
|
||||
|
||||
# Walk eos.effects and add all effects so we can import them properly
|
||||
for root, folders, files in os.walk("eos/effects"):
|
||||
for file_ in files:
|
||||
if file_.endswith(".py") and not file_.startswith("_"):
|
||||
mod_name = "{}.{}".format(
|
||||
root.replace("/", "."),
|
||||
file_.split(".py")[0],
|
||||
)
|
||||
import_these.append(mod_name)
|
||||
|
||||
a = Analysis(
|
||||
['pyfa.py'],
|
||||
pathex=['C:\\projects\\pyfa\\'],
|
||||
binaries=[],
|
||||
datas=added_files,
|
||||
hiddenimports=import_these,
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
)
|
||||
|
||||
pyz = PYZ(
|
||||
a.pure,
|
||||
a.zipped_data,
|
||||
cipher=block_cipher,
|
||||
)
|
||||
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
exclude_binaries=True,
|
||||
debug=False,
|
||||
console=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='pyfa',
|
||||
icon='dist_assets/win/pyfa.ico',
|
||||
onefile=False,
|
||||
)
|
||||
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
onefile=False,
|
||||
name='pyfa',
|
||||
icon='dist_assets/win/pyfa.ico',
|
||||
)
|
||||
83
dist_assets/win/pyfa_debug.spec
Normal file
83
dist_assets/win/pyfa_debug.spec
Normal file
@@ -0,0 +1,83 @@
|
||||
# -*- mode: python -*-
|
||||
|
||||
# Note: This script is provided AS-IS for those that may be interested.
|
||||
# pyfa does not currently support pyInstaller (or any other build process) 100% at the moment
|
||||
|
||||
# Command line to build:
|
||||
# (Run from directory where pyfa.py and pyfa.spec lives.)
|
||||
# c:\Python27\scripts\pyinstaller.exe --clean --noconfirm --windowed --upx-dir=.\scripts\upx.exe pyfa.spec
|
||||
|
||||
# Don't forget to change the path to where your pyfa.py and pyfa.spec lives
|
||||
# pathex=['C:\\Users\\Ebag333\\Documents\\GitHub\\Ebag333\\Pyfa'],
|
||||
|
||||
import os
|
||||
|
||||
block_cipher = None
|
||||
|
||||
added_files = [
|
||||
( 'imgs/gui/*.png', 'imgs/gui' ),
|
||||
( 'imgs/gui/*.gif', 'imgs/gui' ),
|
||||
( 'imgs/icons/*.png', 'imgs/icons' ),
|
||||
( 'imgs/renders/*.png', 'imgs/renders' ),
|
||||
( 'dist_assets/win/pyfa.ico', '.' ),
|
||||
( 'dist_assets/cacert.pem', '.' ),
|
||||
( 'eve.db', '.' ),
|
||||
( 'README.md', '.' ),
|
||||
( 'LICENSE', '.' ),
|
||||
]
|
||||
|
||||
import_these = []
|
||||
|
||||
# Walk eos.effects and add all effects so we can import them properly
|
||||
for root, folders, files in os.walk("eos/effects"):
|
||||
for file_ in files:
|
||||
if file_.endswith(".py") and not file_.startswith("_"):
|
||||
mod_name = "{}.{}".format(
|
||||
root.replace("/", "."),
|
||||
file_.split(".py")[0],
|
||||
)
|
||||
import_these.append(mod_name)
|
||||
|
||||
a = Analysis(
|
||||
['pyfa.py'],
|
||||
pathex=['C:\\projects\\pyfa\\'],
|
||||
binaries=[],
|
||||
datas=added_files,
|
||||
hiddenimports=import_these,
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
)
|
||||
|
||||
pyz = PYZ(
|
||||
a.pure,
|
||||
a.zipped_data,
|
||||
cipher=block_cipher,
|
||||
)
|
||||
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
exclude_binaries=True,
|
||||
debug=True,
|
||||
console=True,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='pyfa_debug',
|
||||
icon='dist_assets/win/pyfa.ico',
|
||||
onefile=False,
|
||||
)
|
||||
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
onefile=False,
|
||||
name='pyfa_debug',
|
||||
icon='dist_assets/win/pyfa.ico',
|
||||
)
|
||||
@@ -1,8 +1,2 @@
|
||||
version = "0.2.3"
|
||||
tag = "git"
|
||||
|
||||
|
||||
def test():
|
||||
import tests.runTests
|
||||
import unittest
|
||||
unittest.main(defaultTest="discover", testLoader=tests.runTests.loader)
|
||||
|
||||
@@ -10,6 +10,9 @@ gamedata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath
|
||||
saveddata_connectionstring = 'sqlite:///' + unicode(
|
||||
realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata.db")), sys.getfilesystemencoding())
|
||||
|
||||
settings = {
|
||||
"setting1": True
|
||||
}
|
||||
|
||||
# Autodetect path, only change if the autodetection bugs out.
|
||||
path = dirname(unicode(__file__, sys.getfilesystemencoding()))
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
import threading
|
||||
|
||||
from sqlalchemy import MetaData, create_engine
|
||||
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import pool
|
||||
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
import migration
|
||||
from eos import config
|
||||
from logbook import Logger
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class ReadOnlyException(Exception):
|
||||
@@ -49,7 +49,9 @@ try:
|
||||
config.gamedata_version = gamedata_session.execute(
|
||||
"SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'client_build'"
|
||||
).fetchone()[0]
|
||||
except:
|
||||
except Exception as e:
|
||||
pyfalog.warning("Missing gamedata version.")
|
||||
pyfalog.critical(e)
|
||||
config.gamedata_version = None
|
||||
|
||||
saveddata_connectionstring = config.saveddata_connectionstring
|
||||
@@ -62,16 +64,22 @@ if saveddata_connectionstring is not None:
|
||||
saveddata_meta = MetaData()
|
||||
saveddata_meta.bind = saveddata_engine
|
||||
saveddata_session = sessionmaker(bind=saveddata_engine, autoflush=False, expire_on_commit=False)()
|
||||
else:
|
||||
saveddata_meta = None
|
||||
|
||||
# Lock controlling any changes introduced to session
|
||||
sd_lock = threading.Lock()
|
||||
|
||||
# Import all the definitions for all our database stuff
|
||||
from eos.db.gamedata import *
|
||||
from eos.db.saveddata import *
|
||||
# noinspection PyPep8
|
||||
from eos.db.gamedata import alphaClones, attribute, category, effect, group, icon, item, marketGroup, metaData, metaGroup, queries, traits, unit
|
||||
# noinspection PyPep8
|
||||
from eos.db.saveddata import booster, cargo, character, crest, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, loadDefaultDatabaseValues, miscData, module, override, price, queries, skill, targetResists, user
|
||||
|
||||
# Import queries
|
||||
# noinspection PyPep8
|
||||
from eos.db.gamedata.queries import *
|
||||
# noinspection PyPep8
|
||||
from eos.db.saveddata.queries import *
|
||||
|
||||
# If using in memory saveddata, you'll want to reflect it so the data structure is good.
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Table, ForeignKey
|
||||
from sqlalchemy.orm import relation, mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import AlphaClone, AlphaCloneSkill
|
||||
from eos.gamedata import AlphaClone, AlphaCloneSkill
|
||||
|
||||
alphaclones_table = Table(
|
||||
"alphaClones",
|
||||
|
||||
@@ -22,7 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Attribute, Icon, AttributeInfo, Unit
|
||||
from eos.gamedata import Attribute, AttributeInfo, Unit, Icon
|
||||
|
||||
typeattributes_table = Table("dgmtypeattribs", gamedata_meta,
|
||||
Column("value", Float),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, ForeignKey, Boolean, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Category, Icon
|
||||
from eos.gamedata import Category, Icon
|
||||
|
||||
categories_table = Table("invcategories", gamedata_meta,
|
||||
Column("categoryID", Integer, primary_key=True),
|
||||
|
||||
@@ -22,7 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import mapper, synonym, relation, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Effect, EffectInfo
|
||||
from eos.gamedata import Effect, EffectInfo
|
||||
|
||||
typeeffects_table = Table("dgmtypeeffects", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Group, Icon, Category
|
||||
from eos.gamedata import Category, Group, Icon
|
||||
|
||||
groups_table = Table("invgroups", gamedata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Table
|
||||
from sqlalchemy.orm import mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Icon
|
||||
from eos.gamedata import Icon
|
||||
|
||||
icons_table = Table("icons", gamedata_meta,
|
||||
Column("iconID", Integer, primary_key=True),
|
||||
|
||||
@@ -23,7 +23,7 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Icon, Attribute, Item, Effect, MetaType, Group, Traits
|
||||
from eos.gamedata import Attribute, Effect, Group, Icon, Item, MetaType, Traits
|
||||
|
||||
items_table = Table("invtypes", gamedata_meta,
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
@@ -39,8 +39,8 @@ items_table = Table("invtypes", gamedata_meta,
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")),
|
||||
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True))
|
||||
|
||||
from .metaGroup import metatypes_table # noqa
|
||||
from .traits import traits_table # noqa
|
||||
from .metaGroup import metatypes_table # noqa
|
||||
from .traits import traits_table # noqa
|
||||
|
||||
mapper(Item, items_table,
|
||||
properties={"group": relation(Group, backref="items"),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Item, MarketGroup, Icon
|
||||
from eos.gamedata import Icon, Item, MarketGroup
|
||||
|
||||
marketgroups_table = Table("invmarketgroups", gamedata_meta,
|
||||
Column("marketGroupID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, Table, String
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import MetaData
|
||||
from eos.gamedata import MetaData
|
||||
|
||||
metadata_table = Table("metadata", gamedata_meta,
|
||||
Column("field_name", String, primary_key=True),
|
||||
|
||||
@@ -23,7 +23,7 @@ from sqlalchemy.orm import relation, mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.db.gamedata.item import items_table
|
||||
from eos.types import MetaGroup, Item, MetaType
|
||||
from eos.gamedata import Item, MetaGroup, MetaType
|
||||
|
||||
metagroups_table = Table("invmetagroups", gamedata_meta,
|
||||
Column("metaGroupID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,13 +21,11 @@ from sqlalchemy.orm import join, exc
|
||||
from sqlalchemy.sql import and_, or_, select
|
||||
|
||||
import eos.config
|
||||
# TODO: Unsure which item the code below needs :(
|
||||
# from eos.gamedata import Item
|
||||
from eos.gamedata import Attribute
|
||||
from eos.db import gamedata_session
|
||||
from eos.db.gamedata.metaGroup import metatypes_table, items_table
|
||||
from eos.db.gamedata.group import groups_table
|
||||
from eos.db.util import processEager, processWhere
|
||||
from eos.types import Item, Category, Group, MarketGroup, AttributeInfo, MetaData, MetaGroup, AlphaClone
|
||||
from eos.gamedata import AlphaClone, Attribute, Category, Group, Item, MarketGroup, MetaGroup, AttributeInfo, MetaData
|
||||
|
||||
configVal = getattr(eos.config, "gamedataCache", None)
|
||||
if configVal is True:
|
||||
@@ -252,7 +250,7 @@ def searchItems(nameLike, where=None, join=None, eager=None):
|
||||
|
||||
|
||||
@cachedQuery(2, "where", "itemids")
|
||||
def getVariations(itemids, where=None, eager=None):
|
||||
def getVariations(itemids, groupIDs=None, where=None, eager=None):
|
||||
for itemid in itemids:
|
||||
if not isinstance(itemid, int):
|
||||
raise TypeError("All passed item IDs must be integers")
|
||||
@@ -265,7 +263,17 @@ def getVariations(itemids, where=None, eager=None):
|
||||
joinon = items_table.c.typeID == metatypes_table.c.typeID
|
||||
vars = gamedata_session.query(Item).options(*processEager(eager)).join((metatypes_table, joinon)).filter(
|
||||
filter).all()
|
||||
return vars
|
||||
|
||||
if vars:
|
||||
return vars
|
||||
elif groupIDs:
|
||||
itemfilter = or_(*(groups_table.c.groupID == groupID for groupID in groupIDs))
|
||||
filter = processWhere(itemfilter, where)
|
||||
joinon = items_table.c.groupID == groups_table.c.groupID
|
||||
vars = gamedata_session.query(Item).options(*processEager(eager)).join((groups_table, joinon)).filter(
|
||||
filter).all()
|
||||
|
||||
return vars
|
||||
|
||||
|
||||
@cachedQuery(1, "attr")
|
||||
|
||||
@@ -2,7 +2,7 @@ from sqlalchemy import Column, Table, Integer, String, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Traits
|
||||
from eos.gamedata import Traits
|
||||
|
||||
traits_table = Table("invtraits", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, Table, Integer, String
|
||||
from sqlalchemy.orm import mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Unit
|
||||
from eos.gamedata import Unit
|
||||
|
||||
groups_table = Table("dgmunits", gamedata_meta,
|
||||
Column("unitID", Integer, primary_key=True),
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import logging
|
||||
from logbook import Logger
|
||||
import shutil
|
||||
import time
|
||||
|
||||
import config
|
||||
import migrations
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
def getVersion(db):
|
||||
@@ -37,7 +37,7 @@ def update(saveddata_engine):
|
||||
for version in xrange(dbVersion, appVersion):
|
||||
func = migrations.updates[version + 1]
|
||||
if func:
|
||||
logger.info("Applying database update: %d", version + 1)
|
||||
pyfalog.info("Applying database update: {0}", version + 1)
|
||||
func(saveddata_engine)
|
||||
|
||||
# when all is said and done, set version to current
|
||||
|
||||
@@ -4,8 +4,6 @@ Migration 15
|
||||
- Delete projected modules on citadels
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
sql = """
|
||||
|
||||
@@ -4,8 +4,6 @@ Migration 17
|
||||
- Moves all fleet boosters to the new schema
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
from eos.db import saveddata_session
|
||||
|
||||
@@ -4,8 +4,6 @@ Migration 19
|
||||
- Deletes broken references to fits from the commandFits table (see GH issue #844)
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
from eos.db import saveddata_session
|
||||
|
||||
10
eos/db/migrations/upgrade21.py
Normal file
10
eos/db/migrations/upgrade21.py
Normal file
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
Migration 21
|
||||
|
||||
- Fixes discrepancy in drone table where we may have an amount active that is not equal to the amount in the stack
|
||||
(we don't support activating only 2/5 drones). See GH issue #728
|
||||
"""
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
saveddata_engine.execute("UPDATE drones SET amountActive = amount where amountActive > 0 AND amountActive <> amount;")
|
||||
@@ -22,7 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Booster
|
||||
from eos.saveddata.booster import Booster
|
||||
|
||||
boosters_table = Table("boosters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Cargo
|
||||
from eos.saveddata.cargo import Cargo
|
||||
|
||||
cargo_table = Table("cargo", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -23,7 +23,9 @@ from sqlalchemy.orm import relation, mapper
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.implant import charImplants_table
|
||||
from eos.effectHandlerHelpers import HandledImplantBoosterList
|
||||
from eos.types import Character, User, Skill, Implant
|
||||
from eos.saveddata.implant import Implant
|
||||
from eos.saveddata.user import User
|
||||
from eos.saveddata.character import Character, Skill
|
||||
|
||||
characters_table = Table("characters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, String
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import CrestChar
|
||||
from eos.saveddata.crestchar import CrestChar
|
||||
|
||||
crest_table = Table("crest", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import DamagePattern
|
||||
from eos.saveddata.damagePattern import DamagePattern
|
||||
|
||||
damagePatterns_table = Table("damagePatterns", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
import sqlalchemy
|
||||
import logging
|
||||
from sqlalchemy.exc import DatabaseError
|
||||
from logbook import Logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class DatabaseCleanup:
|
||||
class DatabaseCleanup(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@@ -32,8 +32,8 @@ class DatabaseCleanup:
|
||||
try:
|
||||
results = saveddata_engine.execute(query)
|
||||
return results
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
logger.error("Failed to connect to database or error executing query:\n%s", query)
|
||||
except DatabaseError:
|
||||
pyfalog.error("Failed to connect to database or error executing query:\n{0}", query)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
@@ -41,7 +41,7 @@ class DatabaseCleanup:
|
||||
# Find orphaned character skills.
|
||||
# This solves an issue where the character doesn't exist, but skills for that character do.
|
||||
# See issue #917
|
||||
logger.debug("Running database cleanup for character skills.")
|
||||
pyfalog.debug("Running database cleanup for character skills.")
|
||||
query = "SELECT COUNT(*) AS num FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
@@ -53,14 +53,14 @@ class DatabaseCleanup:
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)"
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def OrphanedFitDamagePatterns(saveddata_engine):
|
||||
# Find orphaned damage patterns.
|
||||
# This solves an issue where the damage pattern doesn't exist, but fits reference the pattern.
|
||||
# See issue #777
|
||||
logger.debug("Running database cleanup for orphaned damage patterns attached to fits.")
|
||||
pyfalog.debug("Running database cleanup for orphaned damage patterns attached to fits.")
|
||||
query = "SELECT COUNT(*) AS num FROM fits WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
@@ -80,20 +80,20 @@ class DatabaseCleanup:
|
||||
rows = uniform_results.fetchall()
|
||||
|
||||
if len(rows) == 0:
|
||||
logger.error("Missing uniform damage pattern.")
|
||||
pyfalog.error("Missing uniform damage pattern.")
|
||||
elif len(rows) > 1:
|
||||
logger.error("More than one uniform damage pattern found.")
|
||||
pyfalog.error("More than one uniform damage pattern found.")
|
||||
else:
|
||||
uniform_damage_pattern_id = rows[0]['ID']
|
||||
update_query = "UPDATE 'fits' SET 'damagePatternID' = " + str(uniform_damage_pattern_id) + \
|
||||
" WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL"
|
||||
update_query = "UPDATE 'fits' SET 'damagePatternID' = {} " \
|
||||
"WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL".format(uniform_damage_pattern_id)
|
||||
update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", update_results.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def OrphanedFitCharacterIDs(saveddata_engine):
|
||||
# Find orphaned character IDs. This solves an issue where the character doesn't exist, but fits reference the pattern.
|
||||
logger.debug("Running database cleanup for orphaned characters attached to fits.")
|
||||
pyfalog.debug("Running database cleanup for orphaned characters attached to fits.")
|
||||
query = "SELECT COUNT(*) AS num FROM fits WHERE characterID NOT IN (SELECT ID FROM characters) OR characterID IS NULL"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
@@ -113,22 +113,22 @@ class DatabaseCleanup:
|
||||
rows = all5_results.fetchall()
|
||||
|
||||
if len(rows) == 0:
|
||||
logger.error("Missing 'All 5' character.")
|
||||
pyfalog.error("Missing 'All 5' character.")
|
||||
elif len(rows) > 1:
|
||||
logger.error("More than one 'All 5' character found.")
|
||||
pyfalog.error("More than one 'All 5' character found.")
|
||||
else:
|
||||
all5_id = rows[0]['ID']
|
||||
update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \
|
||||
update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \
|
||||
" WHERE characterID not in (select ID from characters) OR characterID IS NULL"
|
||||
update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", update_results.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def NullDamagePatternNames(saveddata_engine):
|
||||
# Find damage patterns that are missing the name.
|
||||
# This solves an issue where the damage pattern ends up with a name that is null.
|
||||
# See issue #949
|
||||
logger.debug("Running database cleanup for missing damage pattern names.")
|
||||
pyfalog.debug("Running database cleanup for missing damage pattern names.")
|
||||
query = "SELECT COUNT(*) AS num FROM damagePatterns WHERE name IS NULL OR name = ''"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
@@ -140,14 +140,14 @@ class DatabaseCleanup:
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM damagePatterns WHERE name IS NULL OR name = ''"
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def NullTargetResistNames(saveddata_engine):
|
||||
# Find target resists that are missing the name.
|
||||
# This solves an issue where the target resist ends up with a name that is null.
|
||||
# See issue #949
|
||||
logger.debug("Running database cleanup for missing target resist names.")
|
||||
pyfalog.debug("Running database cleanup for missing target resist names.")
|
||||
query = "SELECT COUNT(*) AS num FROM targetResists WHERE name IS NULL OR name = ''"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
@@ -159,4 +159,81 @@ class DatabaseCleanup:
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM targetResists WHERE name IS NULL OR name = ''"
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def OrphanedFitIDItemID(saveddata_engine):
|
||||
# Orphaned items that are missing the fit ID or item ID.
|
||||
# See issue #954
|
||||
for table in ['drones', 'cargo', 'fighters']:
|
||||
pyfalog.debug("Running database cleanup for orphaned {0} items.", table)
|
||||
query = "SELECT COUNT(*) AS num FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(
|
||||
table)
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(
|
||||
table)
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount)
|
||||
|
||||
for table in ['modules']:
|
||||
pyfalog.debug("Running database cleanup for orphaned {0} items.", table)
|
||||
query = "SELECT COUNT(*) AS num FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(
|
||||
table)
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table)
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def NullDamageTargetPatternValues(saveddata_engine):
|
||||
# Find patterns that have null values
|
||||
# See issue #954
|
||||
for profileType in ['damagePatterns', 'targetResists']:
|
||||
for damageType in ['em', 'thermal', 'kinetic', 'explosive']:
|
||||
pyfalog.debug("Running database cleanup for null {0} values. ({1})", profileType, damageType)
|
||||
query = "SELECT COUNT(*) AS num FROM {0} WHERE {1}Amount IS NULL OR {1}Amount = ''".format(profileType,
|
||||
damageType)
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
query = "UPDATE '{0}' SET '{1}Amount' = '0' WHERE {1}Amount IS NULL OR {1}Amount = ''".format(profileType,
|
||||
damageType)
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def DuplicateSelectedAmmoName(saveddata_engine):
|
||||
# Orphaned items that are missing the fit ID or item ID.
|
||||
# See issue #954
|
||||
pyfalog.debug("Running database cleanup for duplicated selected ammo profiles.")
|
||||
query = "SELECT COUNT(*) AS num FROM damagePatterns WHERE name = 'Selected Ammo'"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num'] > 1:
|
||||
query = "DELETE FROM damagePatterns WHERE name = 'Selected Ammo'"
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
pyfalog.error("Database corruption found. Cleaning up {0} records.", delete.rowcount)
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Drone
|
||||
from eos.saveddata.drone import Drone
|
||||
|
||||
drones_table = Table("drones", saveddata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,8 +21,9 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Fighter, Fit
|
||||
from eos.types import FighterAbility
|
||||
from eos.saveddata.fighterAbility import FighterAbility
|
||||
from eos.saveddata.fighter import Fighter
|
||||
from eos.saveddata.fit import Fit
|
||||
|
||||
fighters_table = Table("fighters", saveddata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
|
||||
@@ -32,8 +32,17 @@ from eos.db.saveddata.implant import fitImplants_table
|
||||
from eos.db.saveddata.module import modules_table
|
||||
from eos.effectHandlerHelpers import HandledModuleList, HandledImplantBoosterList, HandledProjectedModList, \
|
||||
HandledDroneCargoList, HandledProjectedDroneList
|
||||
from eos.types import Fit as es_Fit, Module, User, Booster, Drone, Fighter, Cargo, Implant, Character, DamagePattern, \
|
||||
TargetResists, ImplantLocation
|
||||
from eos.saveddata.implant import Implant
|
||||
from eos.saveddata.character import Character
|
||||
from eos.saveddata.user import User
|
||||
from eos.saveddata.fighter import Fighter
|
||||
from eos.saveddata.fit import Fit as es_Fit, ImplantLocation
|
||||
from eos.saveddata.drone import Drone
|
||||
from eos.saveddata.booster import Booster
|
||||
from eos.saveddata.module import Module
|
||||
from eos.saveddata.cargo import Cargo
|
||||
from eos.saveddata.damagePattern import DamagePattern
|
||||
from eos.saveddata.targetResists import TargetResists
|
||||
|
||||
fits_table = Table("fits", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
@@ -131,7 +140,7 @@ mapper(es_Fit, fits_table,
|
||||
"_Fit__modules": relation(
|
||||
Module,
|
||||
collection_class=HandledModuleList,
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
|
||||
order_by=modules_table.c.position,
|
||||
cascade='all, delete, delete-orphan'),
|
||||
"_Fit__projectedModules": relation(
|
||||
@@ -139,7 +148,7 @@ mapper(es_Fit, fits_table,
|
||||
collection_class=HandledProjectedModList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
|
||||
"owner": relation(
|
||||
User,
|
||||
backref="fits"),
|
||||
@@ -155,13 +164,13 @@ mapper(es_Fit, fits_table,
|
||||
collection_class=HandledDroneCargoList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
|
||||
"_Fit__fighters": relation(
|
||||
Fighter,
|
||||
collection_class=HandledDroneCargoList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
|
||||
"_Fit__cargo": relation(
|
||||
Cargo,
|
||||
collection_class=HandledDroneCargoList,
|
||||
@@ -173,13 +182,13 @@ mapper(es_Fit, fits_table,
|
||||
collection_class=HandledProjectedDroneList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
|
||||
"_Fit__projectedFighters": relation(
|
||||
Fighter,
|
||||
collection_class=HandledProjectedDroneList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
|
||||
"_Fit__implants": relation(
|
||||
Implant,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Implant
|
||||
from eos.saveddata.implant import Implant
|
||||
|
||||
implants_table = Table("implants", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -23,7 +23,8 @@ from sqlalchemy.orm import relation, mapper
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.implant import implantsSetMap_table
|
||||
from eos.effectHandlerHelpers import HandledImplantBoosterList
|
||||
from eos.types import Implant, ImplantSet
|
||||
from eos.saveddata.implant import Implant
|
||||
from eos.saveddata.implantSet import ImplantSet
|
||||
|
||||
implant_set_table = Table("implantSets", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -26,7 +26,7 @@ class ImportError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DefaultDatabaseValues():
|
||||
class DefaultDatabaseValues(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Column, Table, String
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import MiscData
|
||||
from eos.saveddata.miscData import MiscData
|
||||
|
||||
miscdata_table = Table("miscdata", saveddata_meta,
|
||||
Column("fieldName", String, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,8 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Bool
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Module, Fit
|
||||
from eos.saveddata.module import Module
|
||||
from eos.saveddata.fit import Fit
|
||||
|
||||
modules_table = Table("modules", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, Float
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Override
|
||||
from eos.saveddata.override import Override
|
||||
|
||||
overrides_table = Table("overrides", saveddata_meta,
|
||||
Column("itemID", Integer, primary_key=True, index=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Float, Integer
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Price
|
||||
from eos.saveddata.price import Price
|
||||
|
||||
prices_table = Table("prices", saveddata_meta,
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
|
||||
@@ -22,8 +22,17 @@ from sqlalchemy.sql import and_
|
||||
from eos.db import saveddata_session, sd_lock
|
||||
from eos.db.saveddata.fit import projectedFits_table
|
||||
from eos.db.util import processEager, processWhere
|
||||
from eos.saveddata.price import Price
|
||||
from eos.saveddata.user import User
|
||||
from eos.saveddata.crestchar import CrestChar
|
||||
from eos.saveddata.damagePattern import DamagePattern
|
||||
from eos.saveddata.targetResists import TargetResists
|
||||
from eos.saveddata.character import Character
|
||||
from eos.saveddata.implantSet import ImplantSet
|
||||
from eos.saveddata.fit import Fit
|
||||
from eos.saveddata.miscData import MiscData
|
||||
from eos.saveddata.override import Override
|
||||
|
||||
from eos.types import *
|
||||
import eos.config
|
||||
|
||||
configVal = getattr(eos.config, "saveddataCache", None)
|
||||
@@ -59,6 +68,7 @@ if configVal is True:
|
||||
def checkAndReturn(*args, **kwargs):
|
||||
useCache = kwargs.pop("useCache", True)
|
||||
cacheKey = []
|
||||
items = None
|
||||
cacheKey.extend(args)
|
||||
for keyword in keywords:
|
||||
cacheKey.append(kwargs.get(keyword))
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Skill
|
||||
from eos.saveddata.character import Skill
|
||||
|
||||
skills_table = Table("characterSkills", saveddata_meta,
|
||||
Column("characterID", ForeignKey("characters.ID"), primary_key=True, index=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, Float, ForeignKey, String
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import TargetResists
|
||||
from eos.saveddata.targetResists import TargetResists
|
||||
|
||||
targetResists_table = Table("targetResists", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -21,7 +21,7 @@ from sqlalchemy import Table, Column, Integer, String, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import User
|
||||
from eos.saveddata.user import User
|
||||
|
||||
users_table = Table("users", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
|
||||
@@ -17,12 +17,9 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
# from sqlalchemy.orm.attributes import flag_modified
|
||||
import logging
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class HandledList(list):
|
||||
@@ -139,10 +136,6 @@ class HandledModuleList(HandledList):
|
||||
self.remove(mod)
|
||||
return
|
||||
|
||||
# fix for #529, where a module may be in incorrect state after CCP changes mechanics of module
|
||||
if not mod.isValidState(mod.state):
|
||||
mod.state = eos.types.State.ONLINE
|
||||
|
||||
def insert(self, index, mod):
|
||||
mod.position = index
|
||||
i = index
|
||||
@@ -162,7 +155,7 @@ class HandledModuleList(HandledList):
|
||||
def toDummy(self, index):
|
||||
mod = self[index]
|
||||
if not mod.isEmpty:
|
||||
dummy = eos.types.Module.buildEmpty(mod.slot)
|
||||
dummy = mod.buildEmpty(mod.slot)
|
||||
dummy.position = index
|
||||
self[index] = dummy
|
||||
|
||||
@@ -205,7 +198,7 @@ class HandledImplantBoosterList(HandledList):
|
||||
# if needed, remove booster that was occupying slot
|
||||
oldObj = next((m for m in self if m.slot == thing.slot), None)
|
||||
if oldObj:
|
||||
logging.info("Slot %d occupied with %s, replacing with %s", thing.slot, oldObj.item.name, thing.item.name)
|
||||
pyfalog.info("Slot {0} occupied with {1}, replacing with {2}", thing.slot, oldObj.item.name, thing.item.name)
|
||||
oldObj.itemID = 0 # hack to remove from DB. See GH issue #324
|
||||
self.remove(oldObj)
|
||||
|
||||
@@ -229,7 +222,7 @@ class HandledProjectedModList(HandledList):
|
||||
oldEffect = next((m for m in self if m.item.group.name == "Effect Beacon"), None)
|
||||
|
||||
if oldEffect:
|
||||
logging.info("System effect occupied with %s, replacing with %s", oldEffect.item.name, proj.item.name)
|
||||
pyfalog.info("System effect occupied with {0}, replacing with {1}", oldEffect.item.name, proj.item.name)
|
||||
self.remove(oldEffect)
|
||||
|
||||
HandledList.append(self, proj)
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#
|
||||
# Used by:
|
||||
# Module: Reactive Armor Hardener
|
||||
import logging
|
||||
from logbook import Logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
runTime = "late"
|
||||
type = "active"
|
||||
@@ -15,8 +15,6 @@ def handler(fit, module, context):
|
||||
|
||||
# Skip if there is no damage pattern. Example: projected ships or fleet boosters
|
||||
if damagePattern:
|
||||
# logger.debug("Damage Pattern: %f/%f/%f/%f", damagePattern.emAmount, damagePattern.thermalAmount, damagePattern.kineticAmount, damagePattern.explosiveAmount)
|
||||
# logger.debug("Original Armor Resists: %f/%f/%f/%f", fit.ship.getModifiedItemAttr('armorEmDamageResonance'), fit.ship.getModifiedItemAttr('armorThermalDamageResonance'), fit.ship.getModifiedItemAttr('armorKineticDamageResonance'), fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance'))
|
||||
|
||||
# Populate a tuple with the damage profile modified by current armor resists.
|
||||
baseDamageTaken = (
|
||||
@@ -25,7 +23,7 @@ def handler(fit, module, context):
|
||||
damagePattern.kineticAmount * fit.ship.getModifiedItemAttr('armorKineticDamageResonance'),
|
||||
damagePattern.explosiveAmount * fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance'),
|
||||
)
|
||||
# logger.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f", baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])
|
||||
# pyfalog.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f", baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])
|
||||
|
||||
resistanceShiftAmount = module.getModifiedItemAttr(
|
||||
'resistanceShiftAmount') / 100 # The attribute is in percent and we want a fraction
|
||||
@@ -41,7 +39,7 @@ def handler(fit, module, context):
|
||||
cycleList = []
|
||||
loopStart = -20
|
||||
for num in range(50):
|
||||
# logger.debug("Starting cycle %d.", num)
|
||||
# pyfalog.debug("Starting cycle %d.", num)
|
||||
# The strange order is to emulate the ingame sorting when different types have taken the same amount of damage.
|
||||
# This doesn't take into account stacking penalties. In a few cases fitting a Damage Control causes an inaccurate result.
|
||||
damagePattern_tuples = [
|
||||
@@ -50,7 +48,6 @@ def handler(fit, module, context):
|
||||
(2, baseDamageTaken[2] * RAHResistance[2], RAHResistance[2]),
|
||||
(1, baseDamageTaken[1] * RAHResistance[1], RAHResistance[1]),
|
||||
]
|
||||
# logger.debug("Damage taken this cycle: %f/%f/%f/%f", damagePattern_tuples[0][1], damagePattern_tuples[3][1], damagePattern_tuples[2][1], damagePattern_tuples[1][1])
|
||||
|
||||
# Sort the tuple to drop the highest damage value to the bottom
|
||||
sortedDamagePattern_tuples = sorted(damagePattern_tuples, key=lambda damagePattern: damagePattern[1])
|
||||
@@ -80,7 +77,7 @@ def handler(fit, module, context):
|
||||
RAHResistance[sortedDamagePattern_tuples[1][0]] = sortedDamagePattern_tuples[1][2] + change1
|
||||
RAHResistance[sortedDamagePattern_tuples[2][0]] = sortedDamagePattern_tuples[2][2] + change2
|
||||
RAHResistance[sortedDamagePattern_tuples[3][0]] = sortedDamagePattern_tuples[3][2] + change3
|
||||
# logger.debug("Resistances shifted to %f/%f/%f/%f", RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3])
|
||||
# pyfalog.debug("Resistances shifted to %f/%f/%f/%f", RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3])
|
||||
|
||||
# See if the current RAH profile has been encountered before, indicating a loop.
|
||||
for i, val in enumerate(cycleList):
|
||||
@@ -90,7 +87,7 @@ def handler(fit, module, context):
|
||||
abs(RAHResistance[2] - val[2]) <= tolerance and \
|
||||
abs(RAHResistance[3] - val[3]) <= tolerance:
|
||||
loopStart = i
|
||||
# logger.debug("Loop found: %d-%d", loopStart, num)
|
||||
# pyfalog.debug("Loop found: %d-%d", loopStart, num)
|
||||
break
|
||||
if loopStart >= 0:
|
||||
break
|
||||
@@ -98,7 +95,7 @@ def handler(fit, module, context):
|
||||
cycleList.append(list(RAHResistance))
|
||||
|
||||
if loopStart < 0:
|
||||
logger.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: %f/%f/%f/%f",
|
||||
pyfalog.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: {0}/{1}/{2}/{3}",
|
||||
baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])
|
||||
|
||||
# Average the profiles in the RAH loop, or the last 20 if it didn't find a loop.
|
||||
@@ -113,7 +110,7 @@ def handler(fit, module, context):
|
||||
average[i] = round(average[i] / numCycles, 3)
|
||||
|
||||
# Set the new resistances
|
||||
# logger.debug("Setting new resist profile: %f/%f/%f/%f", average[0], average[1], average[2],average[3])
|
||||
# pyfalog.debug("Setting new resist profile: %f/%f/%f/%f", average[0], average[1], average[2],average[3])
|
||||
for i, attr in enumerate((
|
||||
'armorEmDamageResonance', 'armorThermalDamageResonance', 'armorKineticDamageResonance',
|
||||
'armorExplosiveDamageResonance')):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# ammoInfluenceCapNeed
|
||||
#
|
||||
# Used by:
|
||||
# Items from category: Charge (465 of 899)
|
||||
# Items from category: Charge (465 of 912)
|
||||
# Charges from group: Frequency Crystal (185 of 185)
|
||||
# Charges from group: Hybrid Charge (209 of 209)
|
||||
type = "passive"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# ammoInfluenceRange
|
||||
#
|
||||
# Used by:
|
||||
# Items from category: Charge (571 of 899)
|
||||
# Items from category: Charge (571 of 912)
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# ammoSpeedMultiplier
|
||||
#
|
||||
# Used by:
|
||||
# Charges from group: Festival Charges (9 of 9)
|
||||
# Charges from group: Festival Charges (22 of 22)
|
||||
# Charges from group: Interdiction Probe (2 of 2)
|
||||
# Charges from group: Survey Probe (3 of 3)
|
||||
type = "passive"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Used by:
|
||||
# Modules from group: Armor Coating (202 of 202)
|
||||
# Modules from group: Armor Plating Energized (187 of 187)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# armorRepairAmountBonusSubcap
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Grade Asklepian (15 of 16)
|
||||
# Implants named like: grade Asklepian (15 of 18)
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Data Miners (15 of 16)
|
||||
# Module: QA Cross Protocol Analyzer
|
||||
type = "active"
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Automated Targeting System (6 of 6)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -3,4 +3,7 @@ type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Command Specialist"), "commandBonusHidden", src.getModifiedItemAttr("eliteBonusCommandDestroyer1"), skill="Command Destroyers")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Command Specialist"),
|
||||
"commandBonusHidden",
|
||||
src.getModifiedItemAttr("eliteBonusCommandDestroyer1"),
|
||||
skill="Command Destroyers")
|
||||
|
||||
@@ -6,5 +6,11 @@ type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"),
|
||||
"falloffEffectiveness",
|
||||
src.getModifiedItemAttr("eliteBonusLogistics1"),
|
||||
skill="Logistics Cruisers")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"),
|
||||
"maxRange",
|
||||
src.getModifiedItemAttr("eliteBonusLogistics1"),
|
||||
skill="Logistics Cruisers")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Not used by any item
|
||||
from eos.types import State
|
||||
from eos.saveddata.module import State
|
||||
|
||||
type = "active", "projected"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Energy Neutralizer (51 of 51)
|
||||
from eos.types import State
|
||||
from eos.saveddata.module import State
|
||||
|
||||
type = "active", "projected"
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Heat Sink (18 of 18)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Used by:
|
||||
# Drones from group: Energy Neutralizer Drone (3 of 3)
|
||||
from eos.types import State
|
||||
from eos.saveddata.module import State
|
||||
|
||||
type = "active", "projected"
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Tracking Enhancer (10 of 10)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Tracking Enhancer (10 of 10)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Tracking Enhancer (10 of 10)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Magnetic Field Stabilizer (14 of 14)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff4Multiplier",
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff4Value",
|
||||
src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff1Multiplier",
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff1Value",
|
||||
src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "buffDuration",
|
||||
src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff3Multiplier",
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff3Value",
|
||||
src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff2Multiplier",
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining Foreman"), "warfareBuff2Value",
|
||||
src.getModifiedItemAttr("shipBonusICS2"), skill="Industrial Command Ships")
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Ballistic Control system (17 of 17)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
# Modules from group: Reactor Control Unit (22 of 22)
|
||||
# Modules from group: Shield Recharger (4 of 4)
|
||||
# Modules named like: Flux Coil (12 of 12)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# remoteWeaponDisruptEntity
|
||||
# npcEntityWeaponDisruptor
|
||||
#
|
||||
# Used by:
|
||||
# Drones named like: TD (3 of 3)
|
||||
@@ -11,8 +11,6 @@
|
||||
# Modules from group: Smart Bomb (118 of 118)
|
||||
# Modules from group: Warp Disrupt Field Generator (7 of 7)
|
||||
# Modules named like: Ancillary Remote (8 of 8)
|
||||
# Module: QA Remote Armor Repair System - 5 Players
|
||||
# Module: QA Shield Transporter - 5 Players
|
||||
# Module: Reactive Armor Hardener
|
||||
# Module: Target Spectrum Breaker
|
||||
type = "overheat"
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Gyrostabilizer (13 of 13)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -6,5 +6,9 @@ type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("roleBonusRepairRange"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("roleBonusRepairRange"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"),
|
||||
"falloffEffectiveness",
|
||||
src.getModifiedItemAttr("roleBonusRepairRange"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"),
|
||||
"maxRange",
|
||||
src.getModifiedItemAttr("roleBonusRepairRange"))
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
# scanStrengthBonusPercentActivate
|
||||
#
|
||||
# Used by:
|
||||
# Module: QA ECCM
|
||||
# Not used by any item
|
||||
type = "active"
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# scanStrengthBonusPercentPassive
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: High grade (20 of 61)
|
||||
# Implants named like: High grade (20 of 66)
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# setBonusAsklepian
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Grade Asklepian (16 of 16)
|
||||
# Implants named like: grade Asklepian Omega (2 of 2)
|
||||
# Implants named like: grade Asklepian (18 of 18)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
# shieldTransfer
|
||||
#
|
||||
# Used by:
|
||||
# Module: QA Shield Transporter - 5 Players
|
||||
# Not used by any item
|
||||
type = "projected", "active"
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,18 @@ type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff4Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff3Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff1Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "buffDuration", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or mod.item.requiresSkill("Information Command"), "warfareBuff2Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or
|
||||
mod.item.requiresSkill("Information Command"),
|
||||
"warfareBuff4Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or
|
||||
mod.item.requiresSkill("Information Command"),
|
||||
"warfareBuff3Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or
|
||||
mod.item.requiresSkill("Information Command"),
|
||||
"warfareBuff1Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or
|
||||
mod.item.requiresSkill("Information Command"),
|
||||
"buffDuration", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command") or
|
||||
mod.item.requiresSkill("Information Command"),
|
||||
"warfareBuff2Value", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# remoteGuidanceDisruptFalloff
|
||||
# shipModuleGuidanceDisruptor
|
||||
#
|
||||
# Used by:
|
||||
# Variations of module: Guidance Disruptor I (6 of 6)
|
||||
@@ -1,4 +1,4 @@
|
||||
# remoteTrackingAssistFalloff
|
||||
# shipModuleRemoteTrackingComputer
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Remote Tracking Computer (8 of 8)
|
||||
@@ -1,4 +1,4 @@
|
||||
# remoteTrackingDisruptFalloff
|
||||
# shipModuleTrackingDisruptor
|
||||
#
|
||||
# Used by:
|
||||
# Variations of module: Tracking Disruptor I (6 of 6)
|
||||
@@ -2,7 +2,6 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Signal Amplifier (7 of 7)
|
||||
# Module: QA Damage Module
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# standardMissilesSkillBoostMissileVelocityBonus
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Defender Missiles
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, skill, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Defender Missiles"),
|
||||
"maxVelocity", skill.getModifiedItemAttr("missileVelocityBonus") * skill.level)
|
||||
@@ -3,7 +3,6 @@
|
||||
# Used by:
|
||||
# Implants named like: Inherent Implants 'Noble' Repair Proficiency RP (6 of 6)
|
||||
# Modules named like: Auxiliary Nano Pump (8 of 8)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
# Implant: Imperial Navy Modified 'Noble' Implant
|
||||
type = "passive"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Not used by any item
|
||||
from eos.types import State
|
||||
from eos.saveddata.module import State
|
||||
|
||||
type = "active", "projected"
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Used by:
|
||||
# Modules from group: Nanofiber Internal Structure (7 of 7)
|
||||
# Modules from group: Reinforced Bulkhead (8 of 8)
|
||||
# Modules named like: QA Multiship Module Players (4 of 4)
|
||||
type = "passive"
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Not used by any item
|
||||
from eos.types import State
|
||||
from eos.saveddata.module import State
|
||||
|
||||
# Not used by any item
|
||||
runTime = "early"
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
# targetArmorRepair
|
||||
#
|
||||
# Used by:
|
||||
# Module: QA Remote Armor Repair System - 5 Players
|
||||
# Not used by any item
|
||||
type = "projected", "active"
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Tractor Beam (4 of 4)
|
||||
from eos.config import settings
|
||||
type = "active"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
print settings['setting1']
|
||||
pass
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# Not used by any item
|
||||
type = "projected", "active"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
if "projected" in context:
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"trackingSpeed", container.getModifiedItemAttr("trackingSpeedMultiplier"),
|
||||
stackingPenalties=True, penaltyGroup="postMul")
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"maxRange", container.getModifiedItemAttr("maxRangeMultiplier"),
|
||||
stackingPenalties=True, penaltyGroup="postMul")
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"falloff", container.getModifiedItemAttr("fallofMultiplier"),
|
||||
stackingPenalties=True, penaltyGroup="postMul")
|
||||
@@ -3,7 +3,7 @@
|
||||
# Used by:
|
||||
# Modules from group: Missile Launcher Heavy (12 of 12)
|
||||
# Modules from group: Missile Launcher Rocket (15 of 15)
|
||||
# Modules named like: Launcher (151 of 151)
|
||||
# Modules named like: Launcher (153 of 153)
|
||||
type = 'active', "projected"
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Used by:
|
||||
# Modules named like: Warp Scrambler (26 of 26)
|
||||
|
||||
from eos.types import State
|
||||
from eos.saveddata.module import State
|
||||
|
||||
runTime = "early"
|
||||
type = "projected", "active"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Enum():
|
||||
class Enum(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
|
||||
class EqBase(object):
|
||||
ID = None
|
||||
|
||||
def __eq__(self, other):
|
||||
return type(self) == type(other) and self.ID == other.ID
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
# ===============================================================================
|
||||
|
||||
import re
|
||||
import traceback
|
||||
|
||||
from sqlalchemy.orm import reconstructor
|
||||
|
||||
@@ -30,6 +29,10 @@ try:
|
||||
except ImportError:
|
||||
from utils.compat import OrderedDict
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class Effect(EqBase):
|
||||
"""
|
||||
@@ -64,6 +67,8 @@ class Effect(EqBase):
|
||||
if not self.__generated:
|
||||
self.__generateHandler()
|
||||
|
||||
pyfalog.debug("Generating effect: {0} ({1}) [runTime: {2}]", self.name, self.effectID, self.runTime)
|
||||
|
||||
return self.__handler
|
||||
|
||||
@property
|
||||
@@ -138,7 +143,7 @@ class Effect(EqBase):
|
||||
@property
|
||||
def isImplemented(self):
|
||||
"""
|
||||
Wether this effect is implemented in code or not,
|
||||
Whether this effect is implemented in code or not,
|
||||
unimplemented effects simply do nothing at all when run
|
||||
"""
|
||||
return self.handler != effectDummy
|
||||
@@ -156,36 +161,30 @@ class Effect(EqBase):
|
||||
"""
|
||||
try:
|
||||
self.__effectModule = effectModule = __import__('eos.effects.' + self.handlerName, fromlist=True)
|
||||
try:
|
||||
self.__handler = getattr(effectModule, "handler")
|
||||
except AttributeError:
|
||||
print "effect {} exists, but no handler".format(self.handlerName)
|
||||
raise
|
||||
|
||||
try:
|
||||
self.__runTime = getattr(effectModule, "runTime") or "normal"
|
||||
except AttributeError:
|
||||
self.__runTime = "normal"
|
||||
|
||||
try:
|
||||
self.__activeByDefault = getattr(effectModule, "activeByDefault")
|
||||
except AttributeError:
|
||||
self.__activeByDefault = True
|
||||
|
||||
try:
|
||||
t = getattr(effectModule, "type")
|
||||
except AttributeError:
|
||||
t = None
|
||||
self.__handler = getattr(effectModule, "handler", effectDummy)
|
||||
self.__runTime = getattr(effectModule, "runTime", "normal")
|
||||
self.__activeByDefault = getattr(effectModule, "activeByDefault", True)
|
||||
t = getattr(effectModule, "type", None)
|
||||
|
||||
t = t if isinstance(t, tuple) or t is None else (t,)
|
||||
self.__type = t
|
||||
except (ImportError, AttributeError) as e:
|
||||
except (ImportError) as e:
|
||||
# Effect probably doesn't exist, so create a dummy effect and flag it with a warning.
|
||||
self.__handler = effectDummy
|
||||
self.__runTime = "normal"
|
||||
self.__activeByDefault = True
|
||||
self.__type = None
|
||||
pyfalog.warning("ImportError generating handler: {0}", e)
|
||||
except (AttributeError) as e:
|
||||
# Effect probably exists but there is an issue with it. Turn it into a dummy effect so we can continue, but flag it with an error.
|
||||
self.__handler = effectDummy
|
||||
self.__runTime = "normal"
|
||||
self.__activeByDefault = True
|
||||
self.__type = None
|
||||
pyfalog.error("AttributeError generating handler: {0}", e)
|
||||
except Exception as e:
|
||||
traceback.print_exc(e)
|
||||
pyfalog.critical("Exception generating handler:")
|
||||
pyfalog.critical(e)
|
||||
|
||||
self.__generated = True
|
||||
|
||||
@@ -243,9 +242,11 @@ class Item(EqBase):
|
||||
|
||||
return self.__attributes
|
||||
|
||||
def getAttribute(self, key):
|
||||
def getAttribute(self, key, default=None):
|
||||
if key in self.attributes:
|
||||
return self.attributes[key].value
|
||||
else:
|
||||
return default
|
||||
|
||||
def isType(self, type):
|
||||
for effect in self.effects.itervalues():
|
||||
@@ -283,8 +284,6 @@ class Item(EqBase):
|
||||
@property
|
||||
def requiredSkills(self):
|
||||
if self.__requiredSkills is None:
|
||||
# This import should be here to make sure it's fully initialized
|
||||
from eos import db
|
||||
requiredSkills = OrderedDict()
|
||||
self.__requiredSkills = requiredSkills
|
||||
# Map containing attribute IDs we may need for required skills
|
||||
@@ -295,7 +294,7 @@ class Item(EqBase):
|
||||
# { attributeID : attributeValue }
|
||||
skillAttrs = {}
|
||||
# Get relevant attribute values from db (required skill IDs and levels) for our item
|
||||
for attrInfo in db.directAttributeRequest((self.ID,), tuple(combinedAttrIDs)):
|
||||
for attrInfo in eos.db.directAttributeRequest((self.ID,), tuple(combinedAttrIDs)):
|
||||
attrID = attrInfo[1]
|
||||
attrVal = attrInfo[2]
|
||||
skillAttrs[attrID] = attrVal
|
||||
@@ -306,7 +305,7 @@ class Item(EqBase):
|
||||
skillID = int(skillAttrs[srqIDAtrr])
|
||||
skillLvl = skillAttrs[srqLvlAttr]
|
||||
# Fetch item from database and fill map
|
||||
item = db.getItem(skillID)
|
||||
item = eos.db.getItem(skillID)
|
||||
requiredSkills[item] = skillLvl
|
||||
return self.__requiredSkills
|
||||
|
||||
@@ -339,18 +338,20 @@ class Item(EqBase):
|
||||
# thus keep old mechanism for now
|
||||
except KeyError:
|
||||
# Define race map
|
||||
map = {1: "caldari",
|
||||
2: "minmatar",
|
||||
4: "amarr",
|
||||
5: "sansha", # Caldari + Amarr
|
||||
6: "blood", # Minmatar + Amarr
|
||||
8: "gallente",
|
||||
9: "guristas", # Caldari + Gallente
|
||||
10: "angelserp", # Minmatar + Gallente, final race depends on the order of skills
|
||||
12: "sisters", # Amarr + Gallente
|
||||
16: "jove",
|
||||
32: "sansha", # Incrusion Sansha
|
||||
128: "ore"}
|
||||
map = {
|
||||
1 : "caldari",
|
||||
2 : "minmatar",
|
||||
4 : "amarr",
|
||||
5 : "sansha", # Caldari + Amarr
|
||||
6 : "blood", # Minmatar + Amarr
|
||||
8 : "gallente",
|
||||
9 : "guristas", # Caldari + Gallente
|
||||
10 : "angelserp", # Minmatar + Gallente, final race depends on the order of skills
|
||||
12 : "sisters", # Amarr + Gallente
|
||||
16 : "jove",
|
||||
32 : "sansha", # Incrusion Sansha
|
||||
128: "ore"
|
||||
}
|
||||
# Race is None by default
|
||||
race = None
|
||||
# Check primary and secondary required skills' races
|
||||
@@ -420,7 +421,7 @@ class Item(EqBase):
|
||||
|
||||
def __repr__(self):
|
||||
return "Item(ID={}, name={}) at {}".format(
|
||||
self.ID, self.name, hex(id(self))
|
||||
self.ID, self.name, hex(id(self))
|
||||
)
|
||||
|
||||
|
||||
@@ -474,7 +475,7 @@ class Icon(EqBase):
|
||||
class MarketGroup(EqBase):
|
||||
def __repr__(self):
|
||||
return u"MarketGroup(ID={}, name={}, parent={}) at {}".format(
|
||||
self.ID, self.name, getattr(self.parent, "name", None), self.name, hex(id(self))
|
||||
self.ID, self.name, getattr(self.parent, "name", None), self.name, hex(id(self))
|
||||
).encode('utf8')
|
||||
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class Data(object):
|
||||
|
||||
def parseString(self, dataString):
|
||||
if not isinstance(dataString, basestring):
|
||||
return (Constant(dataString),)
|
||||
return Constant(dataString),
|
||||
|
||||
dataList = []
|
||||
for data in dataString.split(";"):
|
||||
@@ -93,7 +93,8 @@ class Constant(object):
|
||||
def __iter__(self):
|
||||
yield self.value
|
||||
|
||||
def isConstant(self):
|
||||
@staticmethod
|
||||
def isConstant():
|
||||
return True
|
||||
|
||||
|
||||
@@ -114,5 +115,6 @@ class Range(object):
|
||||
i += 1
|
||||
yield current
|
||||
|
||||
def isConstant(self):
|
||||
@staticmethod
|
||||
def isConstant():
|
||||
return False
|
||||
|
||||
@@ -20,7 +20,10 @@
|
||||
from math import log, sin, radians, exp
|
||||
|
||||
from eos.graph import Graph
|
||||
from eos.types import Hardpoint, State
|
||||
from eos.saveddata.module import State, Hardpoint
|
||||
from logbook import Logger
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class FitDpsGraph(Graph):
|
||||
@@ -38,7 +41,7 @@ class FitDpsGraph(Graph):
|
||||
fit = self.fit
|
||||
total = 0
|
||||
distance = data["distance"] * 1000
|
||||
abssort = lambda val: -abs(val - 1)
|
||||
abssort = lambda _val: -abs(_val - 1)
|
||||
|
||||
for mod in fit.modules:
|
||||
if not mod.isEmpty and mod.state >= State.ACTIVE:
|
||||
@@ -65,8 +68,9 @@ class FitDpsGraph(Graph):
|
||||
bonus = values[i]
|
||||
val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
|
||||
data[attr] = val
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
pyfalog.critical("Caught exception in calcDPS.")
|
||||
pyfalog.critical(e)
|
||||
|
||||
for mod in fit.modules:
|
||||
dps, _ = mod.damageStats(fit.targetResists)
|
||||
@@ -95,7 +99,8 @@ class FitDpsGraph(Graph):
|
||||
|
||||
return total
|
||||
|
||||
def calculateMissileMultiplier(self, mod, data):
|
||||
@staticmethod
|
||||
def calculateMissileMultiplier(mod, data):
|
||||
targetSigRad = data["signatureRadius"]
|
||||
targetVelocity = data["velocity"]
|
||||
explosionRadius = mod.getModifiedChargeAttr("aoeCloudSize")
|
||||
@@ -126,7 +131,8 @@ class FitDpsGraph(Graph):
|
||||
multiplier = min(1, (float(targetSigRad) / dmgScaling) ** 2)
|
||||
return multiplier
|
||||
|
||||
def calculateFighterMissileMultiplier(self, ability, data):
|
||||
@staticmethod
|
||||
def calculateFighterMissileMultiplier(ability, data):
|
||||
prefix = ability.attrPrefix
|
||||
|
||||
targetSigRad = data["signatureRadius"]
|
||||
@@ -156,7 +162,8 @@ class FitDpsGraph(Graph):
|
||||
|
||||
return min(sigRadiusFactor, velocityFactor, 1)
|
||||
|
||||
def calculateTurretChanceToHit(self, mod, data):
|
||||
@staticmethod
|
||||
def calculateTurretChanceToHit(mod, data):
|
||||
distance = data["distance"] * 1000
|
||||
tracking = mod.getModifiedItemAttr("trackingSpeed")
|
||||
turretOptimal = mod.maxRange
|
||||
@@ -171,7 +178,8 @@ class FitDpsGraph(Graph):
|
||||
|
||||
return 0.5 ** (trackingEq + rangeEq)
|
||||
|
||||
def calculateModuleMultiplier(self, mod, data):
|
||||
@staticmethod
|
||||
def calculateModuleMultiplier(mod, data):
|
||||
# Simplified formula, we make some assumptions about the module
|
||||
# This is basically the calculateTurretChanceToHit without tracking values
|
||||
distance = data["distance"] * 1000
|
||||
@@ -179,4 +187,4 @@ class FitDpsGraph(Graph):
|
||||
turretFalloff = mod.falloff
|
||||
rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2
|
||||
|
||||
return 0.5 ** (rangeEq)
|
||||
return 0.5 ** rangeEq
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user