Merge branch 'master' into ammo_graph
# Conflicts: # gui/builtinMarketBrowser/itemView.py # service/market.py
This commit is contained in:
119
.appveyor.yml
119
.appveyor.yml
@@ -1,126 +1,76 @@
|
||||
image: Visual Studio 2019
|
||||
clone_depth: 400
|
||||
|
||||
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: "C:\\Python36"
|
||||
PYTHON_VERSION: "3.6.x"
|
||||
PYTHON_ARCH: "32"
|
||||
init:
|
||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- PYTHON: "C:\\Python38-x64"
|
||||
# Should be enabled only for build process debugging
|
||||
# init:
|
||||
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
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." }
|
||||
- ps: echo("OS version:")
|
||||
- ps: "[System.Environment]::OSVersion.Version"
|
||||
|
||||
- ECHO "Filesystem root:"
|
||||
- ps: "ls \"C:/\""
|
||||
- ps: echo("Filesystem - root:")
|
||||
- ps: "ls \"C:\\\""
|
||||
|
||||
- ECHO "Filesystem projects root:"
|
||||
- ps: echo("Filesystem - projects root:")
|
||||
- ps: "ls \"C:\\projects\\\""
|
||||
|
||||
- ECHO "Filesystem pyfa root:"
|
||||
- ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\""
|
||||
- ps: echo("Filesystem - pyfa root:")
|
||||
- ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\\\""
|
||||
|
||||
- ECHO "Installed SDKs:"
|
||||
- ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
|
||||
- ps: echo("Filesystem - installed SDKs:")
|
||||
- ps: "ls \"C:\\Program Files (x86)\\Windows Kits\\\""
|
||||
|
||||
# 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%"
|
||||
- cmd: "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
|
||||
- "python --version"
|
||||
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
|
||||
- cmd: "python --version"
|
||||
- cmd: "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"
|
||||
- cmd: "python -m pip install --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
|
||||
- ECHO "Install pip requirements:"
|
||||
- "python -m pip install -r requirements.txt"
|
||||
- "python -m pip install PyInstaller"
|
||||
- ps: echo("Install pip requirements:")
|
||||
- cmd: "python -m pip install -r requirements.txt"
|
||||
- cmd: "python -m pip install PyInstaller==3.6"
|
||||
|
||||
before_build:
|
||||
# directory that will contain the built files
|
||||
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
|
||||
- ps: $env:PYFA_VERSION = (python ./scripts/dump_version.py)
|
||||
- ps: echo("pyfa version ")
|
||||
- ps: echo ($env:PYFA_VERSION)
|
||||
- ps: echo("pyfa version $env:PYFA_VERSION")
|
||||
|
||||
build_script:
|
||||
- ECHO "Build pyfa:"
|
||||
|
||||
- ps: echo("Build pyfa:")
|
||||
# Build gamedata DB
|
||||
- "python db_update.py"
|
||||
##########
|
||||
# PyInstaller - create binaries for pyfa
|
||||
##########
|
||||
- cmd: "python db_update.py"
|
||||
# Build command for PyInstaller
|
||||
- "python -m PyInstaller --noupx --clean --windowed --noconsole -y pyfa.spec"
|
||||
- cmd: "python -m PyInstaller --noupx --clean --windowed --noconsole -y pyfa.spec"
|
||||
# Copy over manifest (See pyfa-org/pyfa#1622)
|
||||
- ps: xcopy /y dist_assets\win\pyfa.exe.manifest $env:PYFA_DIST_DIR\pyfa\
|
||||
# Not really sure if this is needed, but why not
|
||||
- ps: xcopy /y dist_assets\win\Microsoft.VC90.CRT.manifest $env:PYFA_DIST_DIR\pyfa\
|
||||
|
||||
##########
|
||||
# InnoScript EXE building
|
||||
# This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
|
||||
##########
|
||||
- "python dist_assets/win/dist.py"
|
||||
# InnoScript EXE building. This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
|
||||
- cmd: "python dist_assets/win/dist.py"
|
||||
- ps: dir $env:PYFA_DIST_DIR/
|
||||
#- 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\\$env:APPVEYOR_PROJECT_SLUG\\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\*.*
|
||||
- ps: 7z a "pyfa-$env:PYFA_VERSION-win.zip" -r "$env:PYFA_DIST_DIR\pyfa\*.*"
|
||||
#- 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"
|
||||
# Ha... we're just building
|
||||
|
||||
artifacts:
|
||||
# Archive the generated packages in the ci.appveyor.com build report.
|
||||
- path: pyfa*-win.zip
|
||||
- path: pyfa*-win.exe
|
||||
#- path: pyfa_debug.zip
|
||||
# name: Pyfa_debug
|
||||
|
||||
deploy:
|
||||
tag: $(pyfa_version)
|
||||
@@ -128,10 +78,9 @@ deploy:
|
||||
description: 'Release description'
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: BfNHO66ff5hVx2O2ORbl49X0U/5h2V2T0IuRZDwm7fd1HvsVluF0wRCbl29oRp1M
|
||||
secure: X+U3hOAMTt7HGXCR/LXaGNF6qyhUXetrjz5+xlWiNJQ3XEdzhZZmHK75m0Hm6qre
|
||||
draft: true
|
||||
force_update: false
|
||||
# deploy on tag push only
|
||||
on:
|
||||
APPVEYOR_REPO_TAG: true # deploy on tag push only
|
||||
#on_success:
|
||||
# - TODO: upload the content of dist/*.whl to a public wheelhouse
|
||||
#
|
||||
APPVEYOR_REPO_TAG: true
|
||||
|
||||
@@ -3,13 +3,12 @@ language: python
|
||||
git:
|
||||
depth: 400
|
||||
python:
|
||||
- 3.6
|
||||
- 3.8
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode11.3
|
||||
language: generic
|
||||
env: PYTHON=3.6.1
|
||||
before_install:
|
||||
- bash scripts/setup-osx.sh
|
||||
install:
|
||||
@@ -22,7 +21,7 @@ before_deploy:
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: Xfu0xApoB0zUPLXl29aYUulVC3iA4/3bXQwwADKCfAKZwxgNon4dLbO7Rie5/7Ukf2POL0KwmRaQGN3kOr+XSoIVTE4M5sXxnhiaaLGKQ+48hDizLE6JuXcZGJvkxUaghaTzIdCwHsG7VGBsPfQgfGsjJcfBp8tFNLmRyM/Jpsr8T6BR2MxtBIEUVy8zrOWFNZqnmWrY2pWMsB9fYt3JFNdpqeIgRAYqbBsBcZQ1MngLTi3ztuYS5IaF+lk06RrnBlHmUsJu/5nCvIpvPvD0i2BLZ3Uu0+Fn+8QWUgjJEL9MNseXZMXynu05xd8YRk7Ajc9CUrzQIIbAktyteYp85kE3pUJHmrMLcXhh7nqkwttR5/47Zwa3OLJLJFKBxMx6wY5jFkJjkV08850B7aWrmTFl/Eqc3Q5nZMuiEt3wFRbjxHi9h1mTN/fkxfRRHg8u3ENGPR+ZPiFC3J18qtks/B/hsKjjHvZP1i79OYlET4V/zyLyyQkCbpDaARQANuotLYJyZ7tH+KWEyRsvTi0M9Yev9mNNw6aI4vzh4HfkEhvcvnWnYwckPj1dnjQ573Qpw0Z9wsconoWfHAn+hBDt3+YLMrrFZl++mCRskHH1mZChX3aGMDi49zD0kfxBUkYPOAhguc6PwudBxHUZP+O6T/SoHylff6EizCE/k5dGeAk=
|
||||
secure: D8tBW0kyHlKf/sXS69aIuexsYTx9auY2DzudKFlfcvdzqat4N2XZqZbZCTVd7YVvptQ8Dj0oZ/p3KUxEGpnJZmlTeJL142rpM/qaNd6wOIMy2yUde/aZl+W9JLFNQp7KHutM+MxObYLzJGihx/8YsupmFx6lxgdngGDXtXYZe/ruDIWDs92ShoKJ4vlce9Csm7eGKv7wv6Z6V9sD5FS3E9J8xdWStHxsbrkPBOflmG+uHU09dpEqzUm+ZYROIoTwig1Xbw3fw+gfjmNrfdSU4fAJcVZI1hrgoenZyJbMfhI2Ej/nZdbZgaXcZNF/eUpqOGgbPe1JljqFnHTbexcE+LPBVyAToScsGMpByHhig67DrZ0nk9gSZoC6CPNl5YS6xub+5dncMJ3P5L03DOGYRu4SL9NczbeuQyKuea7+JPP/8VLwfFDSEqbNEAmgzABAzrdfano+VXtuBuE/Tiy5eE7le9hJu6aSQoKW1SA3cUhMsmr2amzdO96sh+PN8FA1oNr45Yuy0pqOj4SUIkb8JUy4th7vgdhljEkSxrHDK1UcHpxUTp+IIUZkZVVk50aH68dQZxGwSTVOeRxpjrTcEf7VCGaM98qxi/ZK4RW6Ewiq0eo0AxwEeB2Zm841lycGPR/406vM9/ZBzv5IhELIdDdVWTk+dGjJBXB8z5hPJOg=
|
||||
file_glob: true
|
||||
file: "dist/pyfa-*.zip"
|
||||
skip_cleanup: true
|
||||
|
||||
@@ -49,6 +49,8 @@ def DBInMemory_test():
|
||||
gamedata_version = gamedata_session.execute(
|
||||
"SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'client_build'"
|
||||
).fetchone()[0]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
print("Missing gamedata version.")
|
||||
gamedata_version = None
|
||||
|
||||
@@ -233,6 +233,8 @@ def defLogging():
|
||||
# reset=False,
|
||||
)
|
||||
])
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
print("Critical error attempting to setup logging. Falling back to console only.")
|
||||
logging_setup = NestedSetup([
|
||||
|
||||
@@ -40,7 +40,7 @@ def db_needs_update():
|
||||
try:
|
||||
with open(os.path.join(JSON_DIR, 'phobos', 'metadata.json')) as f:
|
||||
data_version = next((r['field_value'] for r in json.load(f) if r['field_name'] == 'client_build'))
|
||||
except KeyboardInterrupt:
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
# If we have no source data - return None; should not update in this case
|
||||
except:
|
||||
@@ -61,7 +61,7 @@ def db_needs_update():
|
||||
db_schema_version = int(row[0])
|
||||
cursor.close()
|
||||
db.close()
|
||||
except KeyboardInterrupt:
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
print('Error when fetching gamedata DB metadata')
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<noInheritable/>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.VC90.CRT"
|
||||
version="9.0.21022.8"
|
||||
processorArchitecture="x86"
|
||||
publicKeyToken="1fc8b3b9a1e18e3b"/>
|
||||
<file name="MSVCR90.DLL"/>
|
||||
<file name="MSVCM90.DLL"/>
|
||||
<file name="MSVCP90.DLL"/>
|
||||
</assembly>
|
||||
@@ -14,7 +14,7 @@ with open("version.yml", 'r') as file:
|
||||
os.environ["PYFA_DIST_DIR"] = os.path.join(os.getcwd(), 'dist')
|
||||
|
||||
os.environ["PYFA_VERSION"] = version
|
||||
iscc = "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" # inno script location via wine
|
||||
iscc = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe"
|
||||
|
||||
source = os.path.join(os.environ["PYFA_DIST_DIR"], "pyfa")
|
||||
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
#define MyAppURL "https://github.com/pyfa-org/Pyfa/"
|
||||
#define MyAppExeName "pyfa.exe"
|
||||
|
||||
; What version starts with the new structure (1.x.0). This is used to determine if we run directory structure cleanup
|
||||
#define MajorVersionFlag 2
|
||||
#define MinorVersionFlag 0
|
||||
|
||||
#ifndef MyOutputFile
|
||||
#define MyOutputFile LowerCase(StringChange(MyAppName+'-'+MyAppVersion+'-win', " ", "-"))
|
||||
#endif
|
||||
@@ -30,7 +26,6 @@
|
||||
#endif
|
||||
|
||||
[Setup]
|
||||
|
||||
; NOTE: The value of AppId uniquely identifies this application.
|
||||
; Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
@@ -41,6 +36,9 @@ AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
ArchitecturesAllowed=x64
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
CloseApplications=yes
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
AllowNoIcons=yes
|
||||
@@ -49,7 +47,6 @@ OutputDir={#MyOutputDir}
|
||||
OutputBaseFilename={#MyOutputFile}
|
||||
SetupIconFile={#MyAppDir}\pyfa.ico
|
||||
SolidCompression=yes
|
||||
CloseApplications=yes
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
@@ -83,6 +80,7 @@ Type: files; Name: "{app}\*.pyc"
|
||||
|
||||
[Code]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function IsAppRunning(const FileName : string): Boolean;
|
||||
var
|
||||
FSWbemLocator: Variant;
|
||||
@@ -99,6 +97,7 @@ begin
|
||||
FSWbemLocator := Unassigned;
|
||||
end;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
procedure RemoveFromVirtualStore;
|
||||
var
|
||||
VirtualStore,FileName,FilePath:String;
|
||||
@@ -115,6 +114,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
||||
begin
|
||||
if(IsAppRunning( 'pyfa.exe' )) then
|
||||
@@ -127,54 +127,61 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
function GetUninstallString: string;
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function GetUninstallString(): String;
|
||||
var
|
||||
sUnInstPath: string;
|
||||
sUnInstPath: String;
|
||||
sUnInstallString: String;
|
||||
begin
|
||||
Result := '';
|
||||
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1'); //Your App GUID/ID
|
||||
sUnInstallString := '';
|
||||
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
|
||||
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
|
||||
if not RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString) then
|
||||
if not RegQueryStringValue(HKLM32, sUnInstPath, 'UninstallString', sUnInstallString) then
|
||||
RegQueryStringValue(HKCU32, sUnInstPath, 'UninstallString', sUnInstallString);
|
||||
Result := sUnInstallString;
|
||||
end;
|
||||
|
||||
function IsUpgrade: Boolean;
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function UnInstallOldVersion(): Integer;
|
||||
var
|
||||
sUnInstallString: String;
|
||||
iResultCode: Integer;
|
||||
begin
|
||||
// Return Values:
|
||||
// 1 - uninstall string is empty
|
||||
// 2 - error executing the UnInstallString
|
||||
// 3 - successfully executed the UnInstallString
|
||||
|
||||
// default return value
|
||||
Result := 0;
|
||||
|
||||
// get the uninstall string of the old app
|
||||
sUnInstallString := GetUninstallString();
|
||||
if sUnInstallString <> '' then begin
|
||||
sUnInstallString := RemoveQuotes(sUnInstallString);
|
||||
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
|
||||
Result := 3
|
||||
else
|
||||
Result := 2;
|
||||
end else
|
||||
Result := 1;
|
||||
end;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function IsUpgrade(): Boolean;
|
||||
begin
|
||||
Result := (GetUninstallString() <> '');
|
||||
end;
|
||||
|
||||
function InitializeSetup: Boolean;
|
||||
var
|
||||
V: Integer;
|
||||
iResultCode: Integer;
|
||||
sUnInstallString: string;
|
||||
iOldVersionMajor: Cardinal;
|
||||
iOldVersionMinor: Cardinal;
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
Result := True; // in case when no previous version is found
|
||||
if RegValueExists(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1', 'UninstallString') then //Your App GUID/ID
|
||||
if (CurStep=ssInstall) then
|
||||
begin
|
||||
RegQueryDWordValue(HKEY_LOCAL_MACHINE,
|
||||
'Software\Microsoft\Windows\CurrentVersion\Uninstall\{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1',
|
||||
'MajorVersion', iOldVersionMajor);
|
||||
RegQueryDWordValue(HKEY_LOCAL_MACHINE,
|
||||
'Software\Microsoft\Windows\CurrentVersion\Uninstall\{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1',
|
||||
'MinorVersion', iOldVersionMinor);
|
||||
if (iOldVersionMajor < {#MajorVersionFlag}) or ((iOldVersionMajor = {#MajorVersionFlag}) and (iOldVersionMinor < {#MinorVersionFlag})) then // If old version with old structure is installed.
|
||||
if (IsUpgrade()) then
|
||||
begin
|
||||
V := MsgBox(ExpandConstant('An old version of pyfa was detected. Due to recent changes in the application structure, you must uninstall the previous version first. This will not affect your user data (saved fittings, characters, etc.). Do you want to uninstall now?'), mbInformation, MB_YESNO); //Custom Message if App installed
|
||||
if V = IDYES then
|
||||
begin
|
||||
sUnInstallString := GetUninstallString();
|
||||
sUnInstallString := RemoveQuotes(sUnInstallString);
|
||||
Exec(ExpandConstant(sUnInstallString), '', '', SW_SHOW, ewWaitUntilTerminated, iResultCode);
|
||||
Result := True; //if you want to proceed after uninstall
|
||||
//Exit; //if you want to quit after uninstall
|
||||
end
|
||||
else
|
||||
Result := False; //when older version present and not uninstalled
|
||||
UnInstallOldVersion();
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
|
||||
@@ -20,7 +20,6 @@ added_files = [
|
||||
('../../service/jargon/*.yaml', 'service/jargon'),
|
||||
('../../dist_assets/win/pyfa.ico', '.'),
|
||||
('../../dist_assets/win/pyfa.exe.manifest', '.'),
|
||||
('../../dist_assets/win/Microsoft.VC90.CRT.manifest', '.'),
|
||||
(requests.certs.where(), '.'), # is this needed anymore?
|
||||
('../../eve.db', '.'),
|
||||
('../../README.md', '.'),
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
# -*- 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',
|
||||
)
|
||||
@@ -56,6 +56,8 @@ try:
|
||||
config.gamedata_date = gamedata_session.execute(
|
||||
"SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'dump_time'"
|
||||
).fetchone()[0]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.warning("Missing gamedata version.")
|
||||
pyfalog.critical(e)
|
||||
|
||||
@@ -33,9 +33,13 @@ def upgrade(saveddata_engine):
|
||||
try:
|
||||
saveddata_session.execute(commandFits_table.insert(),
|
||||
{"boosterID": value, "boostedID": boosted, "active": 1})
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
pass
|
||||
saveddata_session.commit()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
# Shouldn't fail unless you have updated database without the old fleet schema and manually modify the database version
|
||||
# If it does, simply fail. Fleet data migration isn't critically important here
|
||||
|
||||
@@ -4235,6 +4235,8 @@ def upgrade(saveddata_engine):
|
||||
|
||||
# And last but not least, delete the last subsystem
|
||||
saveddata_engine.execute("DELETE FROM modules WHERE ID = ?", (oldModules[4][0],))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
# if something fails, fuck it, we tried. It'll default to the generic conversion below
|
||||
continue
|
||||
|
||||
@@ -560,6 +560,8 @@ def commit():
|
||||
with sd_lock:
|
||||
try:
|
||||
saveddata_session.commit()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
saveddata_session.rollback()
|
||||
exc_info = sys.exc_info()
|
||||
@@ -570,6 +572,8 @@ def flush():
|
||||
with sd_lock:
|
||||
try:
|
||||
saveddata_session.flush()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
saveddata_session.rollback()
|
||||
exc_info = sys.exc_info()
|
||||
|
||||
@@ -42,7 +42,7 @@ class Effect4(BaseEffect):
|
||||
shieldBoosting
|
||||
|
||||
Used by:
|
||||
Modules from group: Shield Booster (97 of 97)
|
||||
Modules from group: Shield Booster (89 of 89)
|
||||
"""
|
||||
|
||||
runTime = 'late'
|
||||
@@ -147,7 +147,7 @@ class Effect27(BaseEffect):
|
||||
armorRepair
|
||||
|
||||
Used by:
|
||||
Modules from group: Armor Repair Unit (108 of 108)
|
||||
Modules from group: Armor Repair Unit (100 of 100)
|
||||
"""
|
||||
|
||||
runTime = 'late'
|
||||
@@ -1762,7 +1762,7 @@ class Effect598(BaseEffect):
|
||||
ammoSpeedMultiplier
|
||||
|
||||
Used by:
|
||||
Charges from group: Festival Charges (27 of 28)
|
||||
Charges from group: Festival Charges (28 of 28)
|
||||
Charges from group: Interdiction Probe (2 of 2)
|
||||
Charges from group: Structure Festival Charges (2 of 2)
|
||||
Special Edition Assetss from group: Festival Charges Expired (4 of 4)
|
||||
@@ -9584,7 +9584,7 @@ class Effect3200(BaseEffect):
|
||||
|
||||
Used by:
|
||||
Modules from group: Ancillary Armor Repairer (7 of 7)
|
||||
Modules from group: Armor Repair Unit (108 of 108)
|
||||
Modules from group: Armor Repair Unit (100 of 100)
|
||||
"""
|
||||
|
||||
type = 'overheat'
|
||||
@@ -9602,7 +9602,7 @@ class Effect3201(BaseEffect):
|
||||
|
||||
Used by:
|
||||
Modules from group: Ancillary Shield Booster (8 of 8)
|
||||
Modules from group: Shield Booster (97 of 97)
|
||||
Modules from group: Shield Booster (89 of 89)
|
||||
"""
|
||||
|
||||
type = 'overheat'
|
||||
@@ -23589,7 +23589,7 @@ class Effect5994(BaseEffect):
|
||||
resistanceKillerHullAll
|
||||
|
||||
Used by:
|
||||
Modules named like: Polarized (12 of 18)
|
||||
Modules named like: Polarized (12 of 15)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
@@ -23606,7 +23606,7 @@ class Effect5995(BaseEffect):
|
||||
resistanceKillerShieldArmorAll
|
||||
|
||||
Used by:
|
||||
Modules named like: Polarized (12 of 18)
|
||||
Modules named like: Polarized (12 of 15)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
@@ -32691,6 +32691,8 @@ class Effect6871(BaseEffect):
|
||||
# via https://forums.eveonline.com/default.aspx?g=posts&t=515826
|
||||
try:
|
||||
bonus = max(0, min(50.0, (src.owner.character.secStatus * 10)))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
bonus = None
|
||||
|
||||
@@ -36227,7 +36229,7 @@ class Effect8011(BaseEffect):
|
||||
shieldHpBonusPostPercentHpLocationShip
|
||||
|
||||
Used by:
|
||||
Implants named like: grade Nirvana (10 of 12)
|
||||
Implants named like: grade Nirvana (15 of 18)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
@@ -36242,7 +36244,7 @@ class Effect8013(BaseEffect):
|
||||
setBonusNirvana
|
||||
|
||||
Used by:
|
||||
Implants named like: grade Nirvana (12 of 12)
|
||||
Implants named like: grade Nirvana (18 of 18)
|
||||
"""
|
||||
|
||||
runTime = 'early'
|
||||
|
||||
@@ -193,6 +193,8 @@ class Effect(EqBase):
|
||||
self.__dealsDamage = False
|
||||
self.__type = None
|
||||
pyfalog.error("AttributeError generating handler: {0}", e)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
self.__handler = eos.effects.DummyEffect.handler
|
||||
self.__runTime = "normal"
|
||||
@@ -210,6 +212,8 @@ class Effect(EqBase):
|
||||
|
||||
try:
|
||||
return self.__effectDef.get(key, None)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
return getattr(self.__effectDef, key, None)
|
||||
|
||||
|
||||
@@ -118,15 +118,15 @@ BUILTINS = OrderedDict([
|
||||
# Source: ticket #2067
|
||||
(-86, ('[NPC][Invasion][Invading Precursor Entities]Dread', 0, 417, 0, 583)),
|
||||
(-87, ('[NPC][Invasion][Invading Precursor Entities]Normal Subcaps', 0, 610, 0, 390)),
|
||||
(-88, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 0% spool up', 363, 160, 363, 115)),
|
||||
(-89, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 50% spool up', 286, 249, 286, 179)),
|
||||
(-90, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 100% spool up', 236, 307, 236, 221)),
|
||||
(-88, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 0% spool up', 367, 155, 367, 112)),
|
||||
(-89, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 50% spool up', 291, 243, 291, 175)),
|
||||
(-90, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 100% spool up', 241, 301, 241, 217)),
|
||||
(-91, ('[NPC][Invasion][Retaliating Amarr Entities]Dread/Subcaps', 583, 417, 0, 0)),
|
||||
(-92, ('[NPC][Invasion][Retaliating Caldari Entities]Dread', 1000, 0, 0, 0)),
|
||||
(-93, ('[NPC][Invasion][Retaliating Caldari Entities]Subcaps', 511, 21, 29, 439)),
|
||||
(-93, ('[NPC][Invasion][Retaliating Caldari Entities]Subcaps', 511, 21, 29, 440)),
|
||||
(-94, ('[NPC][Invasion][Retaliating Gallente Entities]Dread/Subcaps', 0, 417, 583, 0)),
|
||||
(-95, ('[NPC][Invasion][Retaliating Minmatar Entities]Dread', 0, 0, 583, 417)),
|
||||
(-96, ('[NPC][Invasion][Retaliating Minmatar Entities]Subcaps', 302, 132, 330, 236)),
|
||||
(-96, ('[NPC][Invasion][Retaliating Minmatar Entities]Subcaps', 302, 136, 328, 234)),
|
||||
(-97, ('[NPC][Mission]Amarr Empire', 4464, 3546, 97, 0)),
|
||||
(-98, ('[NPC][Mission]Caldari State', 0, 2139, 4867, 0)),
|
||||
(-99, ('[NPC][Mission]CONCORD', 336, 134, 212, 412)),
|
||||
@@ -260,6 +260,8 @@ class DamagePattern:
|
||||
line = line.split('#', 1)[0] # allows for comments
|
||||
type, data = line.rsplit('=', 1)
|
||||
type, data = type.strip(), data.split(',')
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
# Data isn't in correct format, continue to next line
|
||||
continue
|
||||
@@ -274,6 +276,8 @@ class DamagePattern:
|
||||
for index, val in enumerate(data):
|
||||
try:
|
||||
fields["%sAmount" % cls.DAMAGE_TYPES[index]] = int(val)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
continue
|
||||
|
||||
|
||||
@@ -73,6 +73,8 @@ class Mutator(EqBase):
|
||||
self.dynamicAttribute = next(a for a in self.module.mutaplasmid.attributes if a.attributeID == self.attrID)
|
||||
# base attribute links to the base ite's attribute for this mutated definition (contains original, base value)
|
||||
self.baseAttribute = self.module.item.attributes[self.dynamicAttribute.name]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
self.module = None
|
||||
|
||||
|
||||
@@ -294,6 +294,8 @@ class TargetProfile:
|
||||
line = line.split('#', 1)[0] # allows for comments
|
||||
type, data = line.rsplit('=', 1)
|
||||
type, data = type.strip(), [d.strip() for d in data.split(',')]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Data isn't in correct format, continue to next line.")
|
||||
continue
|
||||
@@ -312,6 +314,8 @@ class TargetProfile:
|
||||
try:
|
||||
assert 0 <= val <= 100
|
||||
fields["%sAmount" % cls.DAMAGE_TYPES[index]] = val / 100
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Caught unhandled exception in import patterns.")
|
||||
continue
|
||||
|
||||
@@ -54,6 +54,8 @@ try:
|
||||
except ImportError as e:
|
||||
pyfalog.warning('Matplotlib failed to import. Likely missing or incompatible version.')
|
||||
graphFrame_enabled = False
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
# We can get exceptions deep within matplotlib. Catch those. See GH #1046
|
||||
tb = traceback.format_exc()
|
||||
@@ -71,6 +73,8 @@ class GraphCanvasPanel(wx.Panel):
|
||||
# Remove matplotlib font cache, see #234
|
||||
try:
|
||||
cache_dir = mpl._get_cachedir()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
cache_dir = os.path.expanduser(os.path.join('~', '.matplotlib'))
|
||||
cache_file = os.path.join(cache_dir, 'fontList.cache')
|
||||
@@ -168,6 +172,8 @@ class GraphCanvasPanel(wx.Panel):
|
||||
legendData.append((color, lineStyle, source.shortName))
|
||||
else:
|
||||
legendData.append((color, lineStyle, '{} vs {}'.format(source.shortName, target.shortName)))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
pyfalog.warning('Failed to plot "{}" vs "{}"'.format(source.name, '' if target is None else target.name))
|
||||
self.canvas.draw()
|
||||
@@ -241,6 +247,8 @@ class GraphCanvasPanel(wx.Panel):
|
||||
src=source,
|
||||
tgt=target)
|
||||
addYMark(y)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
pyfalog.warning('Failed to get X mark for "{}" vs "{}"'.format(source.name, '' if target is None else target.name))
|
||||
# Silently skip this mark, otherwise other marks and legend display will fail
|
||||
|
||||
@@ -112,6 +112,8 @@ class ItemAffectedBy(wx.Panel):
|
||||
else:
|
||||
try:
|
||||
self.affectedBy.CollapseAll()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -171,7 +173,7 @@ class ItemAffectedBy(wx.Panel):
|
||||
|
||||
def sortAttrDisplayName(self, attr):
|
||||
info = self.stuff.item.attributes.get(attr)
|
||||
if info and info.displayName != "":
|
||||
if info and info.displayName:
|
||||
return info.displayName
|
||||
|
||||
return attr
|
||||
@@ -251,7 +253,7 @@ class ItemAffectedBy(wx.Panel):
|
||||
|
||||
for attrName in attrOrder:
|
||||
attrInfo = self.stuff.item.attributes.get(attrName)
|
||||
displayName = attrInfo.displayName if attrInfo and attrInfo.displayName != "" else attrName
|
||||
displayName = attrInfo.displayName if attrInfo and attrInfo.displayName else attrName
|
||||
|
||||
if attrInfo:
|
||||
if attrInfo.iconID is not None:
|
||||
@@ -444,7 +446,7 @@ class ItemAffectedBy(wx.Panel):
|
||||
attrModifier = "-"
|
||||
attrAmount = -attrAmount
|
||||
|
||||
attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier,
|
||||
attributes.append((attrName, (displayName if displayName else attrName), attrModifier,
|
||||
attrAmount, penalized, attrIcon))
|
||||
|
||||
attrSorted = sorted(attributes, key=lambda attribName: attribName[0])
|
||||
@@ -454,14 +456,14 @@ class ItemAffectedBy(wx.Panel):
|
||||
if self.showRealNames:
|
||||
display = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
|
||||
saved = "%s %s %.2f %s" % (
|
||||
displayName if displayName != "" else attrName,
|
||||
displayName if displayName else attrName,
|
||||
attrModifier,
|
||||
attrAmount,
|
||||
penalized
|
||||
)
|
||||
else:
|
||||
display = "%s %s %.2f %s" % (
|
||||
displayName if displayName != "" else attrName,
|
||||
displayName if displayName else attrName,
|
||||
attrModifier,
|
||||
attrAmount,
|
||||
penalized
|
||||
|
||||
@@ -86,6 +86,8 @@ class ItemProperties(wx.Panel):
|
||||
valueUnit = str(value)
|
||||
|
||||
self.paramList.SetItem(index, 1, valueUnit)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
# TODO: Add logging to this.
|
||||
# We couldn't get a property for some reason. Skip it for now.
|
||||
|
||||
@@ -48,7 +48,6 @@ class ItemView(Display):
|
||||
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
|
||||
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
|
||||
|
||||
# Make reverse map, used by sorter
|
||||
self.active = []
|
||||
|
||||
def delaySearch(self, evt):
|
||||
@@ -178,7 +177,7 @@ class ItemView(Display):
|
||||
return
|
||||
|
||||
self.marketBrowser.mode = 'search'
|
||||
self.sMkt.searchItems(search, self.populateSearch)
|
||||
self.sMkt.searchItems(search, self.populateSearch, 'market')
|
||||
|
||||
def clearSearch(self, event=None):
|
||||
# Wipe item store and update everything to accomodate with it
|
||||
@@ -201,7 +200,6 @@ class ItemView(Display):
|
||||
self.setToggles()
|
||||
self.filterItemStore()
|
||||
|
||||
|
||||
def contextMenu(self, event):
|
||||
clickedPos = self.getRowByAbs(event.Position)
|
||||
self.ensureSelection(clickedPos)
|
||||
@@ -235,11 +233,9 @@ class ItemView(Display):
|
||||
# Re-sort stuff
|
||||
if self.marketBrowser.mode != 'recent':
|
||||
items.sort(key=self.sMkt.itemSort)
|
||||
|
||||
for i, item in enumerate(items[:9]):
|
||||
# set shortcut info for first 9 modules
|
||||
item.marketShortcut = i + 1
|
||||
|
||||
Display.refresh(self, items)
|
||||
|
||||
def columnBackground(self, colItem, item):
|
||||
|
||||
@@ -63,6 +63,8 @@ class MarketTree(wx.TreeCtrl):
|
||||
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
|
||||
try:
|
||||
childId = self.AppendItem(root, childMktGrp.name, iconId, data=childMktGrp.ID)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.debug("Error appending item.")
|
||||
pyfalog.debug(e)
|
||||
|
||||
@@ -66,6 +66,8 @@ class FitSpawner(gui.multiSwitch.TabSpawner):
|
||||
self.multiSwitch.SetSelection(index)
|
||||
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(event.fitID,)))
|
||||
break
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Caught exception in fitSelected")
|
||||
pyfalog.critical(e)
|
||||
@@ -812,6 +814,8 @@ class FittingView(d.Display):
|
||||
if self and not self.IsShown():
|
||||
try:
|
||||
self.MakeSnapshot()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Failed to make snapshot")
|
||||
pyfalog.critical(e)
|
||||
@@ -837,6 +841,8 @@ class FittingView(d.Display):
|
||||
sFit = Fit.getInstance()
|
||||
try:
|
||||
fit = sFit.getFit(self.activeFitID)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Failed to get fit")
|
||||
pyfalog.critical(e)
|
||||
|
||||
@@ -309,7 +309,7 @@ class ItemView(d.Display):
|
||||
self.clearSearch()
|
||||
return
|
||||
|
||||
sMkt.searchItems(search, self.populateSearch, ["Implant"])
|
||||
sMkt.searchItems(search, self.populateSearch, 'implants')
|
||||
|
||||
def populateSearch(self, items):
|
||||
if not self.IsShown():
|
||||
|
||||
@@ -475,6 +475,8 @@ class SkillTreeView(wx.Panel):
|
||||
if skill:
|
||||
skill.setLevel(level, ignoreRestrict=True)
|
||||
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.error(e)
|
||||
with wx.MessageDialog(self, "There was an error importing skills, please see log file", "Error", wx.ICON_ERROR) as dlg:
|
||||
@@ -839,7 +841,7 @@ class APIView(wx.Panel):
|
||||
|
||||
def getActiveCharacter(self):
|
||||
selection = self.charChoice.GetCurrentSelection()
|
||||
return self.charChoice.GetClientData(selection) if selection is not -1 else None
|
||||
return self.charChoice.GetClientData(selection) if selection != -1 else None
|
||||
|
||||
def ssoListChanged(self, event):
|
||||
if not self: # todo: fix event not unbinding properly
|
||||
|
||||
@@ -122,7 +122,7 @@ class CharacterSelection(wx.Panel):
|
||||
|
||||
def getActiveCharacter(self):
|
||||
selection = self.charChoice.GetCurrentSelection()
|
||||
return self.charChoice.GetClientData(selection) if selection is not -1 else None
|
||||
return self.charChoice.GetClientData(selection) if selection != -1 else None
|
||||
|
||||
def refreshCharacterList(self, event=None):
|
||||
choice = self.charChoice
|
||||
@@ -303,7 +303,6 @@ class CharacterSelection(wx.Panel):
|
||||
if tabulationLevel == 0:
|
||||
for item, subReqs in reqs.items():
|
||||
skillsMap = self._buildSkillsTooltipCondensed(subReqs, item.name, 1, skillsMap)
|
||||
sorted(skillsMap, key=skillsMap.get)
|
||||
else:
|
||||
for name, info in reqs.items():
|
||||
level, ID, more = info
|
||||
@@ -323,3 +322,25 @@ class CharacterSelection(wx.Panel):
|
||||
skillsMap = self._buildSkillsTooltipCondensed(more, currItem, tabulationLevel + 1, skillsMap)
|
||||
|
||||
return skillsMap
|
||||
|
||||
def _buildSkillsTooltipSuperCondensed(self, reqs, currItem="", tabulationLevel=0, skillsMap=None):
|
||||
allReqs = {}
|
||||
implicitReqs = {}
|
||||
|
||||
def traverseReqs(itemReqs, topLevel=True):
|
||||
for skillName, (skillLevel, skillTypeID, subReqs) in itemReqs.items():
|
||||
if (skillTypeID, skillName) not in allReqs or allReqs[(skillTypeID, skillName)] < skillLevel:
|
||||
allReqs[(skillTypeID, skillName)] = skillLevel
|
||||
if not topLevel and (skillTypeID not in implicitReqs or implicitReqs[skillTypeID] < skillLevel):
|
||||
implicitReqs[skillTypeID] = skillLevel
|
||||
traverseReqs(subReqs, topLevel=False)
|
||||
|
||||
for item, itemReqs in reqs.items():
|
||||
traverseReqs(itemReqs)
|
||||
|
||||
newReqs = {}
|
||||
for (skillTypeID, skillName), skillLevel in allReqs.items():
|
||||
if skillTypeID not in implicitReqs or implicitReqs[skillTypeID] < skillLevel:
|
||||
newReqs[skillName] = skillLevel, skillTypeID
|
||||
|
||||
return newReqs
|
||||
|
||||
@@ -1138,6 +1138,8 @@ class _TabsContainer(wx.Panel):
|
||||
self.preview_tab = tab
|
||||
self.preview_timer.Start(500, True)
|
||||
break
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@@ -125,6 +125,8 @@ class EveFittings(AuxiliaryFrame):
|
||||
# Can't do this in a finally because then it obscures the message dialog
|
||||
del waitDialog # noqa: F821
|
||||
ESIExceptionHandler(self, ex)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as ex:
|
||||
del waitDialog # noqa: F821
|
||||
raise ex
|
||||
@@ -302,6 +304,8 @@ class ExportToEve(AuxiliaryFrame):
|
||||
except APIException as ex:
|
||||
try:
|
||||
ESIExceptionHandler(self, ex)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as ex:
|
||||
self.statusbar.SetStatusText("ERROR", 0)
|
||||
self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1)
|
||||
@@ -381,6 +385,8 @@ class SsoCharacterMgmt(AuxiliaryFrame):
|
||||
try:
|
||||
sEsi = Esi.getInstance()
|
||||
sEsi.login()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as ex:
|
||||
ESIServerExceptionHandler(self, ex)
|
||||
|
||||
@@ -457,6 +463,8 @@ class FittingsTreeView(wx.Panel):
|
||||
cargo = Cargo(getItem(item['type_id']))
|
||||
cargo.amount = item['quantity']
|
||||
list.append(cargo)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Exception caught in displayFit")
|
||||
pyfalog.critical(e)
|
||||
|
||||
@@ -99,12 +99,14 @@ class PFPanel(wx.Panel):
|
||||
|
||||
|
||||
class OpenFitsThread(threading.Thread):
|
||||
|
||||
def __init__(self, fits, callback):
|
||||
threading.Thread.__init__(self)
|
||||
self.name = "LoadingOpenFits"
|
||||
self.mainFrame = MainFrame.getInstance()
|
||||
self.callback = callback
|
||||
self.fits = fits
|
||||
self.running = True
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
@@ -118,10 +120,15 @@ class OpenFitsThread(threading.Thread):
|
||||
# We use 1 for all fits except the last one where we use 2 so that we
|
||||
# have correct calculations displayed at startup
|
||||
for fitID in self.fits[:-1]:
|
||||
wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID, startup=1))
|
||||
if self.running:
|
||||
wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID, startup=1))
|
||||
|
||||
wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[-1], startup=2))
|
||||
wx.CallAfter(self.callback)
|
||||
if self.running:
|
||||
wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[-1], startup=2))
|
||||
wx.CallAfter(self.callback)
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
|
||||
# todo: include IPortUser again
|
||||
@@ -251,10 +258,12 @@ class MainFrame(wx.Frame):
|
||||
fit = sFit.getFit(id, basic=True)
|
||||
if fit is None:
|
||||
fits.remove(id)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
fits.remove(id)
|
||||
|
||||
if not self.prevOpenFits['enabled'] or len(fits) is 0:
|
||||
if not self.prevOpenFits['enabled'] or len(fits) == 0:
|
||||
# add blank page if there are no fits to be loaded
|
||||
self.fitMultiSwitch.AddPage()
|
||||
return
|
||||
@@ -747,9 +756,12 @@ class MainFrame(wx.Frame):
|
||||
activeFit = self.getActiveFit()
|
||||
try:
|
||||
importType, importData = Port().importFitFromBuffer(clipboard, activeFit)
|
||||
if importType == "MutatedItem":
|
||||
# we've imported an Abyssal module, need to fire off the command to add it to the fit
|
||||
self.command.Submit(cmd.GuiImportLocalMutatedModuleCommand(activeFit, *importData[0]))
|
||||
if importType == "FittingItem":
|
||||
baseItem, mutaplasmidItem, mutations = importData[0]
|
||||
if mutaplasmidItem:
|
||||
self.command.Submit(cmd.GuiImportLocalMutatedModuleCommand(activeFit, baseItem, mutaplasmidItem, mutations))
|
||||
else:
|
||||
self.command.Submit(cmd.GuiAddLocalModuleCommand(activeFit, baseItem.ID))
|
||||
return
|
||||
if importType == "AdditionsDrones":
|
||||
if self.command.Submit(cmd.GuiImportLocalDronesCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
|
||||
@@ -771,6 +783,8 @@ class MainFrame(wx.Frame):
|
||||
if self.command.Submit(cmd.GuiImportCargosCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
|
||||
self.additionsPane.select("Cargo")
|
||||
return
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.error("Attempt to import failed:\n{0}", clipboard)
|
||||
else:
|
||||
|
||||
@@ -265,6 +265,8 @@ class DmgPatternEditor(AuxiliaryFrame):
|
||||
except ImportError as e:
|
||||
pyfalog.error(e)
|
||||
self.stNotice.SetLabel(str(e))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
msg = "Could not import from clipboard: unknown errors"
|
||||
pyfalog.warning(msg)
|
||||
|
||||
@@ -168,10 +168,7 @@ class ItemView(d.Display):
|
||||
|
||||
def __init__(self, parent):
|
||||
d.Display.__init__(self, parent)
|
||||
sMkt = Market.getInstance()
|
||||
|
||||
self.things = sMkt.getItemsWithOverrides()
|
||||
self.items = self.things
|
||||
self.activeItems = []
|
||||
|
||||
self.searchBox = parent.Parent.Parent.searchBox
|
||||
# Bind search actions
|
||||
@@ -180,20 +177,16 @@ class ItemView(d.Display):
|
||||
self.searchBox.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
|
||||
self.searchBox.Bind(SBox.EVT_TEXT, self.scheduleSearch)
|
||||
|
||||
self.update(self.items)
|
||||
self.update(Market.getInstance().getItemsWithOverrides())
|
||||
|
||||
def clearSearch(self, event=None):
|
||||
if event:
|
||||
self.searchBox.Clear()
|
||||
self.items = self.things
|
||||
self.update(self.items)
|
||||
self.update(Market.getInstance().getItemsWithOverrides())
|
||||
|
||||
def updateItems(self, updateDisplay=False):
|
||||
sMkt = Market.getInstance()
|
||||
self.things = sMkt.getItemsWithOverrides()
|
||||
self.items = self.things
|
||||
if updateDisplay:
|
||||
self.update(self.things)
|
||||
self.update(Market.getInstance().getItemsWithOverrides())
|
||||
|
||||
def scheduleSearch(self, event=None):
|
||||
sMkt = Market.getInstance()
|
||||
@@ -206,12 +199,40 @@ class ItemView(d.Display):
|
||||
self.clearSearch()
|
||||
return
|
||||
|
||||
sMkt.searchItems(search, self.populateSearch, False)
|
||||
sMkt.searchItems(search, self.populateSearch, 'everything')
|
||||
|
||||
def itemSort(self, item):
|
||||
sMkt = Market.getInstance()
|
||||
isFittable = item.group.name in sMkt.FIT_GROUPS or item.category.name in sMkt.FIT_CATEGORIES
|
||||
catname = sMkt.getCategoryByItem(item).name
|
||||
try:
|
||||
mktgrpid = sMkt.getMarketGroupByItem(item).ID
|
||||
except AttributeError:
|
||||
mktgrpid = -1
|
||||
pyfalog.warning("unable to find market group for {}".format(item.name))
|
||||
parentname = sMkt.getParentItemByItem(item).name
|
||||
# Get position of market group
|
||||
metagrpid = sMkt.getMetaGroupIdByItem(item)
|
||||
metatab = sMkt.META_MAP_REVERSE_INDICES.get(metagrpid)
|
||||
metalvl = item.metaLevel or 0
|
||||
|
||||
return not isFittable, catname, mktgrpid, parentname, metatab, metalvl, item.name
|
||||
|
||||
def populateSearch(self, items):
|
||||
self.items = list(items)
|
||||
self.update(items)
|
||||
|
||||
def populate(self, items):
|
||||
if len(items) > 0:
|
||||
self.unselectAll()
|
||||
items.sort(key=self.itemSort)
|
||||
self.activeItems = items
|
||||
d.Display.populate(self, items)
|
||||
|
||||
def refresh(self, items):
|
||||
if len(items) > 1:
|
||||
items.sort(key=self.itemSort)
|
||||
d.Display.refresh(self, items)
|
||||
|
||||
|
||||
class AttributeGrid(wxpg.PropertyGrid):
|
||||
def __init__(self, parent):
|
||||
@@ -236,7 +257,7 @@ class AttributeGrid(wxpg.PropertyGrid):
|
||||
self.Clear()
|
||||
self.btn.Enable(True)
|
||||
sel = event.EventObject.GetFirstSelected()
|
||||
self.item = item = self.itemView.items[sel]
|
||||
self.item = item = self.itemView.activeItems[sel]
|
||||
|
||||
for key in sorted(item.attributes.keys()):
|
||||
override = item.overrides.get(key, None)
|
||||
|
||||
@@ -211,6 +211,8 @@ class ImplantSetEditor(AuxiliaryFrame):
|
||||
except ImportError as e:
|
||||
pyfalog.error(e)
|
||||
self.stNotice.SetLabel(str(e))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.error(e)
|
||||
self.stNotice.SetLabel("Could not import from clipboard: unknown errors")
|
||||
|
||||
@@ -352,6 +352,8 @@ class TargetProfileEditor(AuxiliaryFrame):
|
||||
except ImportError as e:
|
||||
pyfalog.error(e)
|
||||
self.stNotice.SetLabel(str(e))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
msg = "Could not import from clipboard:"
|
||||
pyfalog.warning(msg)
|
||||
|
||||
@@ -70,6 +70,8 @@ class exportHtmlThread(threading.Thread):
|
||||
except IOError as ex:
|
||||
pyfalog.warning("Failed to write to " + settings.getPath())
|
||||
pass
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as ex:
|
||||
pass
|
||||
|
||||
@@ -226,6 +228,8 @@ class exportHtmlThread(threading.Thread):
|
||||
|
||||
HTMLfit += ' </ul>\n </li>\n'
|
||||
HTMLship += HTMLfit
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Failed to export line")
|
||||
continue
|
||||
@@ -281,6 +285,8 @@ class exportHtmlThread(threading.Thread):
|
||||
HTML += '<a class="outOfGameBrowserLink" target="_blank" href="' + dnaUrl + dnaFit + '">' \
|
||||
+ ship.name + ': ' + \
|
||||
fit[1] + '</a><br> \n'
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.error("Failed to export line")
|
||||
continue
|
||||
|
||||
15
pyfa.py
15
pyfa.py
@@ -151,5 +151,18 @@ if __name__ == "__main__":
|
||||
else:
|
||||
pyfa.MainLoop()
|
||||
|
||||
# TODO: Add some thread cleanup code here. Right now we bail, and that can lead to orphaned threads or threads not properly exiting.
|
||||
# When main loop is over, threads have 5 seconds to comply...
|
||||
import threading
|
||||
from utils.timer import CountdownTimer
|
||||
|
||||
timer = CountdownTimer(5)
|
||||
stoppableThreads = []
|
||||
for t in threading.enumerate():
|
||||
if t is not threading.main_thread() and hasattr(t, 'stop'):
|
||||
stoppableThreads.append(t)
|
||||
t.stop()
|
||||
for t in stoppableThreads:
|
||||
t.join(timeout=timer.remainder())
|
||||
|
||||
# Nah, just kidding, no way to terminate threads - just try to exit
|
||||
sys.exit()
|
||||
|
||||
@@ -31,7 +31,6 @@ if os_name == 'Windows':
|
||||
added_files.extend([
|
||||
('dist_assets/win/pyfa.ico', '.'),
|
||||
('dist_assets/win/pyfa.exe.manifest', '.'),
|
||||
('dist_assets/win/Microsoft.VC90.CRT.manifest', '.')
|
||||
])
|
||||
|
||||
icon = 'dist_assets/win/pyfa.ico'
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
wxPython == 4.0.7.post2
|
||||
logbook >= 1.0.0
|
||||
matplotlib == 3.0.3
|
||||
numpy==1.16.4
|
||||
matplotlib >= 3.1.2
|
||||
python-dateutil
|
||||
requests >= 2.0.0
|
||||
sqlalchemy >= 1.3.0
|
||||
cryptography >= 2.3
|
||||
markdown2 == 2.3.5
|
||||
packaging == 16.8
|
||||
roman == 2.0.0
|
||||
beautifulsoup4 == 4.6.0
|
||||
markdown2 >= 2.3.5
|
||||
packaging >= 16.8
|
||||
roman >= 2.0.0
|
||||
beautifulsoup4 >= 4.6.0
|
||||
pyyaml >= 5.1
|
||||
|
||||
@@ -119,7 +119,7 @@ def calc_outerscore(innerscore_dict, pereffect_totalaffected, weight):
|
||||
def validate_string(s):
|
||||
try:
|
||||
s.encode('ascii')
|
||||
except KeyboardInterrupt:
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@@ -394,6 +394,8 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True):
|
||||
new_cursor.execute(query)
|
||||
for row in new_cursor:
|
||||
new_meta[row[0]] = row[1]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
# Print jobs
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Pyfa version (ENV):"
|
||||
echo "${PYFA_VERSION}"
|
||||
|
||||
echo "Pyfa version (YAML):"
|
||||
cat version.yml
|
||||
echo "Building distributive..."
|
||||
python3 -m PyInstaller -y --clean --windowed dist_assets/mac/pyfa.spec
|
||||
echo "Compressing distributive..."
|
||||
cd dist
|
||||
zip -r "pyfa-$PYFA_VERSION-mac.zip" pyfa.app
|
||||
echo "Uploading distributive to transfer.sh..."
|
||||
curl --connect-timeout 30 --max-time 300 --upload-file "pyfa-$PYFA_VERSION-mac.zip" https://transfer.sh/ || echo 'upload to transfer.sh failed'
|
||||
echo -e "\n"
|
||||
md5 -r "pyfa-$PYFA_VERSION-mac.zip"
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
wget "https://www.python.org/ftp/python/${PYTHON}/python-${PYTHON}-macosx10.6.pkg"
|
||||
sudo installer -pkg python-${PYTHON}-macosx10.6.pkg -target /
|
||||
sudo python3 -m ensurepip --upgrade
|
||||
# A manual check that the correct version of Python is running.
|
||||
echo "Python version:"
|
||||
python3 --version
|
||||
echo "Upgrading pip..."
|
||||
python3 -m pip install --upgrade pip
|
||||
echo "Installing app requirements..."
|
||||
python3 -m pip install -r requirements.txt
|
||||
python3 -m pip install PyInstaller
|
||||
echo "Installing packaging tools..."
|
||||
python3 -m pip install PyInstaller==3.6
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,89 +0,0 @@
|
||||
Electronic Subsystem Technology,Core Subsystem Technology
|
||||
Amarr Electronic Systems,Amarr Core Systems
|
||||
Gallente Electronic Systems,Gallente Core Systems
|
||||
Caldari Electronic Systems,Caldari Core Systems
|
||||
Minmatar Electronic Systems,Minmatar Core Systems
|
||||
Datacore - Electronic Subsystems Engineering,Datacore - Core Subsystems Engineering
|
||||
Malfunctioning Electromechanical Component,Malfunctioning Power Cores
|
||||
Wrecked Electromechanical Component,Wrecked Power Cores
|
||||
Intact Electromechanical Component,Intact Power Cores
|
||||
Legion Electronics - Energy Parasitic Complex,Legion Core - Energy Parasitic Complex
|
||||
Legion Electronics - Tactical Targeting Network,Legion Core - Dissolution Sequencer
|
||||
Legion Electronics - Dissolution Sequencer,Legion Core - Dissolution Sequencer
|
||||
Legion Electronics - Emergent Locus Analyzer,Legion Core - Dissolution Sequencer
|
||||
Tengu Electronics - Obfuscation Manifold,Tengu Core - Obfuscation Manifold
|
||||
Tengu Electronics - CPU Efficiency Gate,Tengu Core - Electronic Efficiency Gate
|
||||
Tengu Electronics - Dissolution Sequencer,Tengu Core - Electronic Efficiency Gate
|
||||
Tengu Electronics - Emergent Locus Analyzer,Tengu Core - Electronic Efficiency Gate
|
||||
Proteus Electronics - Friction Extension Processor,Proteus Core - Friction Extension Processor
|
||||
Proteus Electronics - CPU Efficiency Gate,Proteus Core - Electronic Efficiency Gate
|
||||
Proteus Electronics - Dissolution Sequencer,Proteus Core - Electronic Efficiency Gate
|
||||
Proteus Electronics - Emergent Locus Analyzer,Proteus Core - Electronic Efficiency Gate
|
||||
Loki Electronics - Immobility Drivers,Loki Core - Immobility Drivers
|
||||
Loki Electronics - Tactical Targeting Network,Loki Core - Dissolution Sequencer
|
||||
Loki Electronics - Dissolution Sequencer,Loki Core - Dissolution Sequencer
|
||||
Loki Electronics - Emergent Locus Analyzer,Loki Core - Dissolution Sequencer
|
||||
Tengu Engineering - Power Core Multiplier,Tengu Core - Augmented Graviton Reactor
|
||||
Tengu Engineering - Augmented Capacitor Reservoir,Tengu Core - Augmented Graviton Reactor
|
||||
Tengu Engineering - Capacitor Regeneration Matrix,Tengu Core - Augmented Graviton Reactor
|
||||
Tengu Engineering - Supplemental Coolant Injector,Tengu Core - Obfuscation Manifold
|
||||
Proteus Engineering - Power Core Multiplier,Proteus Core - Augmented Fusion Reactor
|
||||
Proteus Engineering - Augmented Capacitor Reservoir,Proteus Core - Augmented Fusion Reactor
|
||||
Proteus Engineering - Capacitor Regeneration Matrix,Proteus Core - Augmented Fusion Reactor
|
||||
Proteus Engineering - Supplemental Coolant Injector,Proteus Core - Friction Extension Processor
|
||||
Loki Engineering - Power Core Multiplier,Loki Core - Augmented Nuclear Reactor
|
||||
Loki Engineering - Augmented Capacitor Reservoir,Loki Core - Augmented Nuclear Reactor
|
||||
Loki Engineering - Capacitor Regeneration Matrix,Loki Core - Augmented Nuclear Reactor
|
||||
Loki Engineering - Supplemental Coolant Injector,Loki Core - Immobility Drivers
|
||||
Legion Engineering - Power Core Multiplier,Legion Core - Augmented Antimatter Reactor
|
||||
Legion Engineering - Augmented Capacitor Reservoir,Legion Core - Augmented Antimatter Reactor
|
||||
Legion Engineering - Capacitor Regeneration Matrix,Legion Core - Augmented Antimatter Reactor
|
||||
Legion Engineering - Supplemental Coolant Injector,Legion Core - Energy Parasitic Complex
|
||||
Legion Propulsion - Chassis Optimization,Legion Propulsion - Intercalated Nanofibers
|
||||
Legion Propulsion - Fuel Catalyst,Legion Propulsion - Wake Limiter
|
||||
Legion Propulsion - Wake Limiter,Legion Propulsion - Wake Limiter
|
||||
Legion Propulsion - Interdiction Nullifier,Legion Propulsion - Interdiction Nullifier
|
||||
Tengu Propulsion - Intercalated Nanofibers,Tengu Propulsion - Chassis Optimization
|
||||
Tengu Propulsion - Gravitational Capacitor,Tengu Propulsion - Chassis Optimization
|
||||
Tengu Propulsion - Fuel Catalyst,Tengu Propulsion - Fuel Catalyst
|
||||
Tengu Propulsion - Interdiction Nullifier,Tengu Propulsion - Interdiction Nullifier
|
||||
Proteus Propulsion - Wake Limiter,Proteus Propulsion - Localized Injectors
|
||||
Proteus Propulsion - Localized Injectors,Proteus Propulsion - Localized Injectors
|
||||
Proteus Propulsion - Gravitational Capacitor,Proteus Propulsion - Hyperspatial Optimization
|
||||
Proteus Propulsion - Interdiction Nullifier,Proteus Propulsion - Interdiction Nullifier
|
||||
Loki Propulsion - Chassis Optimization,Loki Propulsion - Intercalated Nanofibers
|
||||
Loki Propulsion - Intercalated Nanofibers,Loki Propulsion - Intercalated Nanofibers
|
||||
Loki Propulsion - Fuel Catalyst,Loki Propulsion - Wake Limiter
|
||||
Loki Propulsion - Interdiction Nullifier,Loki Propulsion - Interdiction Nullifier
|
||||
Legion Defensive - Adaptive Augmenter,Legion Defensive - Augmented Plating
|
||||
Legion Defensive - Nanobot Injector,Legion Defensive - Nanobot Injector
|
||||
Legion Defensive - Augmented Plating,Legion Defensive - Augmented Plating
|
||||
Legion Defensive - Warfare Processor,Legion Defensive - Augmented Plating
|
||||
Tengu Defensive - Adaptive Shielding,Tengu Defensive - Supplemental Screening
|
||||
Tengu Defensive - Amplification Node,Tengu Defensive - Amplification Node
|
||||
Tengu Defensive - Supplemental Screening,Tengu Defensive - Supplemental Screening
|
||||
Tengu Defensive - Warfare Processor,Tengu Defensive - Supplemental Screening
|
||||
Loki Defensive - Adaptive Shielding,Loki Defensive - Augmented Durability
|
||||
Loki Defensive - Adaptive Augmenter,Loki Defensive - Augmented Durability
|
||||
Loki Defensive - Amplification Node,Loki Defensive - Adaptive Defense Node
|
||||
Loki Defensive - Warfare Processor,Loki Defensive - Augmented Durability
|
||||
Proteus Defensive - Adaptive Augmenter,Proteus Defensive - Augmented Plating
|
||||
Proteus Defensive - Nanobot Injector,Proteus Defensive - Nanobot Injector
|
||||
Proteus Defensive - Augmented Plating,Proteus Defensive - Augmented Plating
|
||||
Proteus Defensive - Warfare Processor,Proteus Defensive - Augmented Plating
|
||||
Legion Offensive - Drone Synthesis Projector,Legion Offensive - Assault Optimization
|
||||
Legion Offensive - Assault Optimization,Legion Offensive - Assault Optimization
|
||||
Legion Offensive - Liquid Crystal Magnifiers,Legion Offensive - Liquid Crystal Magnifiers
|
||||
Legion Offensive - Covert Reconfiguration,Legion Offensive - Liquid Crystal Magnifiers
|
||||
Tengu Offensive - Accelerated Ejection Bay,Tengu Offensive - Accelerated Ejection Bay
|
||||
Tengu Offensive - Rifling Launcher Pattern,Tengu Offensive - Accelerated Ejection Bay
|
||||
Tengu Offensive - Magnetic Infusion Basin,Tengu Offensive - Magnetic Infusion Basin
|
||||
Tengu Offensive - Covert Reconfiguration,Tengu Offensive - Accelerated Ejection Bay
|
||||
Proteus Offensive - Dissonic Encoding Platform,Proteus Offensive - Hybrid Encoding Platform
|
||||
Proteus Offensive - Hybrid Propulsion Armature,Proteus Offensive - Hybrid Encoding Platform
|
||||
Proteus Offensive - Drone Synthesis Projector,Proteus Offensive - Drone Synthesis Projector
|
||||
Proteus Offensive - Covert Reconfiguration,Proteus Offensive - Hybrid Encoding Platform
|
||||
Loki Offensive - Turret Concurrence Registry,Loki Offensive - Projectile Scoping Array
|
||||
Loki Offensive - Projectile Scoping Array,Loki Offensive - Projectile Scoping Array
|
||||
Loki Offensive - Hardpoint Efficiency Configuration,Loki Offensive - Launcher Efficiency Configuration
|
||||
Loki Offensive - Covert Reconfiguration,Loki Offensive - Projectile Scoping Array
|
||||
|
@@ -1,48 +0,0 @@
|
||||
# Prints out a fucking large python dictionary for use with the t3c conversion migration.\
|
||||
# Requires eve-old.db file (which is the previous releases database so that we can lookup the old items)
|
||||
# See https://community.eveonline.com/news/patch-notes/patch-notes-for-july-2017-release
|
||||
|
||||
import csv
|
||||
import sys
|
||||
from os.path import abspath, dirname, join, realpath
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
newDB = create_engine('sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "eve.db")), sys.getfilesystemencoding()))
|
||||
oldDB = create_engine('sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "eve-old.db")), sys.getfilesystemencoding()))
|
||||
|
||||
oldItemMapping = {}
|
||||
newItemMapping = {}
|
||||
|
||||
with open('t3conversionSheet.csv', 'r') as f:
|
||||
reader = csv.reader(f)
|
||||
print "conversion = {"
|
||||
for row in reader:
|
||||
|
||||
fromList = []
|
||||
toList = []
|
||||
for x in xrange(1, 6):
|
||||
try:
|
||||
if (row[0], row[x]) not in oldItemMapping:
|
||||
item = oldDB.execute("SELECT * FROM invtypes WHERE typeName LIKE ?", ("{}%{}".format(row[0], row[x]),)).first()
|
||||
oldItemMapping[(row[0], row[x])] = item['typeID']
|
||||
fromList.append(str(oldItemMapping[(row[0], row[x])]))
|
||||
except:
|
||||
pass
|
||||
for x in xrange(6, 10):
|
||||
if row[x] not in newItemMapping:
|
||||
item = newDB.execute("SELECT * FROM invtypes WHERE typeName = ?",
|
||||
(row[x],)).first()
|
||||
newItemMapping[row[x]] = item['typeID']
|
||||
toList.append(str(newItemMapping[row[x]]))
|
||||
print "\tfrozenset([{}]): ({}),".format(','.join(fromList), ','.join(toList))
|
||||
print "}"
|
||||
|
||||
with open('t3conversionSheetLoose.csv', 'r') as f:
|
||||
reader = csv.reader(f)
|
||||
print "conversion2 = {"
|
||||
for row in reader:
|
||||
oldItem = oldDB.execute("SELECT typeID FROM invtypes WHERE typeName = ?", (row[0],)).scalar()
|
||||
newItem = newDB.execute("SELECT typeID FROM invtypes WHERE typeName = ?", (row[1],)).scalar()
|
||||
print "\t{}: {},".format(oldItem, newItem)
|
||||
print "}"
|
||||
BIN
scripts/upx.exe
BIN
scripts/upx.exe
Binary file not shown.
@@ -45,11 +45,13 @@ pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class CharacterImportThread(threading.Thread):
|
||||
|
||||
def __init__(self, paths, callback):
|
||||
threading.Thread.__init__(self)
|
||||
self.name = "CharacterImport"
|
||||
self.paths = paths
|
||||
self.callback = callback
|
||||
self.running = True
|
||||
|
||||
def run(self):
|
||||
paths = self.paths
|
||||
@@ -61,6 +63,8 @@ class CharacterImportThread(threading.Thread):
|
||||
all_skill_ids.append(skill.itemID)
|
||||
|
||||
for path in paths:
|
||||
if not self.running:
|
||||
break
|
||||
try:
|
||||
charFile = open(path, mode='r').read()
|
||||
doc = minidom.parseString(charFile)
|
||||
@@ -86,6 +90,8 @@ class CharacterImportThread(threading.Thread):
|
||||
)
|
||||
char = sCharacter.new(name + " (EVEMon)")
|
||||
sCharacter.apiUpdateCharSheet(char.ID, skills, securitystatus)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.error("Exception on character import:")
|
||||
pyfalog.error(e)
|
||||
@@ -93,6 +99,9 @@ class CharacterImportThread(threading.Thread):
|
||||
|
||||
wx.CallAfter(self.callback)
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
|
||||
class SkillBackupThread(threading.Thread):
|
||||
def __init__(self, path, saveFmt, activeFit, callback):
|
||||
@@ -102,25 +111,32 @@ class SkillBackupThread(threading.Thread):
|
||||
self.saveFmt = saveFmt
|
||||
self.activeFit = activeFit
|
||||
self.callback = callback
|
||||
self.running = True
|
||||
|
||||
def run(self):
|
||||
path = self.path
|
||||
sCharacter = Character.getInstance()
|
||||
|
||||
if self.saveFmt == "xml" or self.saveFmt == "emp":
|
||||
backupData = sCharacter.exportXml()
|
||||
else:
|
||||
backupData = sCharacter.exportText()
|
||||
backupData = None
|
||||
if self.running:
|
||||
if self.saveFmt == "xml" or self.saveFmt == "emp":
|
||||
backupData = sCharacter.exportXml()
|
||||
else:
|
||||
backupData = sCharacter.exportText()
|
||||
|
||||
if self.saveFmt == "emp":
|
||||
with gzip.open(path, mode='wb') as backupFile:
|
||||
backupFile.write(backupData.encode())
|
||||
else:
|
||||
with open(path, mode='w', encoding='utf-8') as backupFile:
|
||||
backupFile.write(backupData)
|
||||
if self.running and backupData is not None:
|
||||
if self.saveFmt == "emp":
|
||||
with gzip.open(path, mode='wb') as backupFile:
|
||||
backupFile.write(backupData.encode())
|
||||
else:
|
||||
with open(path, mode='w', encoding='utf-8') as backupFile:
|
||||
backupFile.write(backupData)
|
||||
|
||||
wx.CallAfter(self.callback)
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
|
||||
class Character:
|
||||
instance = None
|
||||
@@ -151,6 +167,8 @@ class Character:
|
||||
data += "Skills required for {}:\n".format(item)
|
||||
data += "{}{}: {}\n".format(" " * s["indent"], s["skill"], int(s["level"]))
|
||||
data += "-" * 79 + "\n"
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -376,8 +394,8 @@ class Character:
|
||||
char.apiUpdateCharSheet(skills, securitystatus)
|
||||
eos.db.commit()
|
||||
|
||||
@staticmethod
|
||||
def changeLevel(charID, skillID, level, persist=False, ifHigher=False):
|
||||
@classmethod
|
||||
def changeLevel(cls, charID, skillID, level, persist=False, ifHigher=False):
|
||||
char = eos.db.getCharacter(charID)
|
||||
skill = char.getSkill(skillID)
|
||||
|
||||
@@ -386,10 +404,19 @@ class Character:
|
||||
|
||||
if isinstance(level, str) or level > 5 or level < 0:
|
||||
skill.setLevel(None, persist)
|
||||
else:
|
||||
eos.db.commit()
|
||||
elif skill.level != level:
|
||||
cls._trainSkillReqs(char, skill, persist)
|
||||
skill.setLevel(level, persist)
|
||||
eos.db.commit()
|
||||
|
||||
eos.db.commit()
|
||||
@classmethod
|
||||
def _trainSkillReqs(cls, char, skill, persist):
|
||||
for childSkillItem, neededSkillLevel in skill.item.requiredSkills.items():
|
||||
childSkill = char.getSkill(childSkillItem.ID)
|
||||
if childSkill.level < neededSkillLevel:
|
||||
childSkill.setLevel(neededSkillLevel, persist)
|
||||
cls._trainSkillReqs(char, childSkill, persist)
|
||||
|
||||
@staticmethod
|
||||
def revertLevel(charID, skillID):
|
||||
@@ -442,13 +469,13 @@ class Character:
|
||||
if subThing is not None:
|
||||
if isinstance(thing, es_Fighter) and attr == "charge":
|
||||
continue
|
||||
self._checkRequirements(fit, fit.character, subThing, subReqs)
|
||||
self._checkRequirements(fit.character, subThing, subReqs)
|
||||
if subReqs:
|
||||
reqs[subThing] = subReqs
|
||||
|
||||
return reqs
|
||||
|
||||
def _checkRequirements(self, fit, char, subThing, reqs):
|
||||
def _checkRequirements(self, char, subThing, reqs):
|
||||
for req, level in subThing.requiredSkills.items():
|
||||
name = req.name
|
||||
ID = req.ID
|
||||
@@ -456,18 +483,19 @@ class Character:
|
||||
currLevel, subs = info if info is not None else 0, {}
|
||||
if level > currLevel and (char is None or char.getSkill(req).level < level):
|
||||
reqs[name] = (level, ID, subs)
|
||||
self._checkRequirements(fit, char, req, subs)
|
||||
|
||||
self._checkRequirements(char, req, subs)
|
||||
return reqs
|
||||
|
||||
|
||||
class UpdateAPIThread(threading.Thread):
|
||||
|
||||
def __init__(self, charID, callback):
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
self.name = "CheckUpdate"
|
||||
self.callback = callback
|
||||
self.charID = charID
|
||||
self.running = True
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
@@ -476,18 +504,31 @@ class UpdateAPIThread(threading.Thread):
|
||||
sEsi = Esi.getInstance()
|
||||
sChar = Character.getInstance()
|
||||
ssoChar = sChar.getSsoCharacter(char.ID)
|
||||
|
||||
if not self.running:
|
||||
self.callback[0](self.callback[1])
|
||||
return
|
||||
resp = sEsi.getSkills(ssoChar.ID)
|
||||
|
||||
if not self.running:
|
||||
self.callback[0](self.callback[1])
|
||||
return
|
||||
# todo: check if alpha. if so, pop up a question if they want to apply it as alpha. Use threading events to set the answer?
|
||||
char.clearSkills()
|
||||
for skillRow in resp["skills"]:
|
||||
char.addSkill(Skill(char, skillRow["skill_id"], skillRow["trained_skill_level"]))
|
||||
|
||||
if not self.running:
|
||||
self.callback[0](self.callback[1])
|
||||
return
|
||||
resp = sEsi.getSecStatus(ssoChar.ID)
|
||||
|
||||
char.secStatus = resp['security_status']
|
||||
|
||||
self.callback[0](self.callback[1])
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as ex:
|
||||
pyfalog.warn(ex)
|
||||
self.callback[0](self.callback[1], sys.exc_info())
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Conversion pack for Januray 2020 release
|
||||
Conversion pack for January 2020 release
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
@@ -10,5 +10,29 @@ CONVERSIONS = {
|
||||
'Large Clarity Ward Booster I': 'Large Clarity Ward Enduring Shield Booster',
|
||||
'Large C5-L Emergency Shield Overload I': 'Large C5-L Compact Shield Booster',
|
||||
'X-Large Clarity Ward Booster I': 'X-Large Clarity Ward Enduring Shield Booster',
|
||||
'X-Large C5-L Emergency Shield Overload I': 'X-Large C5-L Compact Shield Booster'
|
||||
'X-Large C5-L Emergency Shield Overload I': 'X-Large C5-L Compact Shield Booster',
|
||||
'Small I-a Polarized Armor Regenerator': 'Small I-a Enduring Armor Repairer',
|
||||
'Small \'Accommodation\' Vestment Reconstructer I': 'Small ACM Compact Armor Repairer',
|
||||
'Medium I-a Polarized Armor Regenerator': 'Medium I-a Enduring Armor Repairer',
|
||||
'Medium \'Accommodation\' Vestment Reconstructer I': 'Medium ACM Compact Armor Repairer',
|
||||
'Large I-a Polarized Armor Regenerator': 'Large I-a Enduring Armor Repairer',
|
||||
'Large \'Accommodation\' Vestment Reconstructer I': 'Large ACM Compact Armor Repairer',
|
||||
# Entries below were removed from DB, but CCP converted them to another item type
|
||||
'Small Converse Deflection Catalyzer': 'Small Clarity Ward Enduring Shield Booster',
|
||||
'Small Neutron Saturation Injector I': 'Small C5-L Compact Shield Booster',
|
||||
'Medium Converse Deflection Catalyzer': 'Medium Clarity Ward Enduring Shield Booster',
|
||||
'Medium Neutron Saturation Injector I': 'Medium C5-L Compact Shield Booster',
|
||||
'Large Converse Deflection Catalyzer': 'Large Clarity Ward Enduring Shield Booster',
|
||||
'Large Neutron Saturation Injector I': 'Large C5-L Compact Shield Booster',
|
||||
'X-Large Converse Deflection Catalyzer': 'X-Large Clarity Ward Enduring Shield Booster',
|
||||
'X-Large Neutron Saturation Injector I': 'X-Large C5-L Compact Shield Booster',
|
||||
'Small Inefficient Armor Repair Unit': 'Small ACM Compact Armor Repairer',
|
||||
'Small Automated Carapace Restoration': 'Small I-a Enduring Armor Repairer',
|
||||
'Medium Inefficient Armor Repair Unit': 'Medium ACM Compact Armor Repairer',
|
||||
'Medium Automated Carapace Restoration': 'Medium I-a Enduring Armor Repairer',
|
||||
'Medium Nano Armor Repair Unit I': '\'Meditation\' Medium Armor Repairer I',
|
||||
'Large Inefficient Armor Repair Unit': 'Large ACM Compact Armor Repairer',
|
||||
'Large Automated Carapace Restoration': 'Large I-a Enduring Armor Repairer',
|
||||
# This item was not mentioned, assuming conversion to storyline
|
||||
'Large \'Reprieve\' Vestment Reconstructer I': '\'Protest\' Large Armor Repairer I'
|
||||
}
|
||||
|
||||
@@ -110,6 +110,8 @@ class ImplantSets:
|
||||
else:
|
||||
item = sMkt.getItem(line)
|
||||
current.implants.append(es_Implant(item))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
@@ -46,6 +46,7 @@ class ShipBrowserWorkerThread(threading.Thread):
|
||||
threading.Thread.__init__(self)
|
||||
pyfalog.debug("Initialize ShipBrowserWorkerThread.")
|
||||
self.name = "ShipBrowser"
|
||||
self.running = True
|
||||
|
||||
def run(self):
|
||||
self.queue = queue.Queue()
|
||||
@@ -60,6 +61,8 @@ class ShipBrowserWorkerThread(threading.Thread):
|
||||
cache = self.cache
|
||||
sMkt = Market.getInstance()
|
||||
while True:
|
||||
if not self.running:
|
||||
break
|
||||
try:
|
||||
id_, callback = queue.get()
|
||||
set_ = cache.get(id_)
|
||||
@@ -68,16 +71,23 @@ class ShipBrowserWorkerThread(threading.Thread):
|
||||
cache[id_] = set_
|
||||
|
||||
wx.CallAfter(callback, (id_, set_))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Callback failed.")
|
||||
pyfalog.critical(e)
|
||||
finally:
|
||||
try:
|
||||
queue.task_done()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Queue task done failed.")
|
||||
pyfalog.critical(e)
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
|
||||
class SearchWorkerThread(threading.Thread):
|
||||
def __init__(self):
|
||||
@@ -87,6 +97,7 @@ class SearchWorkerThread(threading.Thread):
|
||||
# load the jargon while in an out-of-thread context, to spot any problems while in the main thread
|
||||
self.jargonLoader.get_jargon()
|
||||
self.jargonLoader.get_jargon().apply('test string')
|
||||
self.running = True
|
||||
|
||||
def run(self):
|
||||
self.cv = threading.Condition()
|
||||
@@ -97,49 +108,70 @@ class SearchWorkerThread(threading.Thread):
|
||||
cv = self.cv
|
||||
|
||||
while True:
|
||||
if not self.running:
|
||||
break
|
||||
cv.acquire()
|
||||
while self.searchRequest is None:
|
||||
cv.wait()
|
||||
|
||||
request, callback, filterOn = self.searchRequest
|
||||
request, callback, filterName = self.searchRequest
|
||||
self.searchRequest = None
|
||||
cv.release()
|
||||
sMkt = Market.getInstance()
|
||||
if filterOn is True:
|
||||
if filterName == 'market':
|
||||
# Rely on category data provided by eos as we don't hardcode them much in service
|
||||
filter_ = or_(types_Category.name.in_(sMkt.SEARCH_CATEGORIES), types_Group.name.in_(sMkt.SEARCH_GROUPS))
|
||||
elif filterOn: # filter by selected categories
|
||||
filter_ = types_Category.name.in_(filterOn)
|
||||
filters = [or_(
|
||||
types_Category.name.in_(sMkt.SEARCH_CATEGORIES),
|
||||
types_Group.name.in_(sMkt.SEARCH_GROUPS))]
|
||||
# Used in implant editor
|
||||
elif filterName == 'implants':
|
||||
filters = [types_Category.name == 'Implant']
|
||||
# Actually not everything, just market search + ships
|
||||
elif filterName == 'everything':
|
||||
filters = [
|
||||
or_(
|
||||
types_Category.name.in_(sMkt.FIT_CATEGORIES),
|
||||
types_Group.name.in_(sMkt.FIT_GROUPS)),
|
||||
or_(
|
||||
types_Category.name.in_(sMkt.SEARCH_CATEGORIES),
|
||||
types_Group.name.in_(sMkt.SEARCH_GROUPS))]
|
||||
else:
|
||||
filter_ = None
|
||||
filters = [None]
|
||||
|
||||
jargon_request = self.jargonLoader.get_jargon().apply(request)
|
||||
|
||||
results = []
|
||||
all_results = set()
|
||||
if len(request) >= config.minItemSearchLength:
|
||||
results = eos.db.searchItems(request, where=filter_,
|
||||
join=(types_Item.group, types_Group.category),
|
||||
eager=("group.category", "metaGroup"))
|
||||
for filter_ in filters:
|
||||
regular_results = eos.db.searchItems(
|
||||
request, where=filter_,
|
||||
join=(types_Item.group, types_Group.category),
|
||||
eager=("group.category", "metaGroup"))
|
||||
all_results.update(regular_results)
|
||||
|
||||
jargon_results = []
|
||||
if len(jargon_request) >= config.minItemSearchLength:
|
||||
jargon_results = eos.db.searchItems(jargon_request, where=filter_,
|
||||
join=(types_Item.group, types_Group.category),
|
||||
eager=("group.category", "metaGroup"))
|
||||
for filter_ in filters:
|
||||
jargon_results = eos.db.searchItems(
|
||||
jargon_request, where=filter_,
|
||||
join=(types_Item.group, types_Group.category),
|
||||
eager=("group.category", "metaGroup"))
|
||||
all_results.update(jargon_results)
|
||||
|
||||
items = set()
|
||||
# Return only published items, consult with Market service this time
|
||||
for item in [*results, *jargon_results]:
|
||||
for item in all_results:
|
||||
if sMkt.getPublicityByItem(item):
|
||||
items.add(item)
|
||||
wx.CallAfter(callback, items)
|
||||
wx.CallAfter(callback, list(items))
|
||||
|
||||
def scheduleSearch(self, text, callback, filterOn=True):
|
||||
def scheduleSearch(self, text, callback, filterName=None):
|
||||
self.cv.acquire()
|
||||
self.searchRequest = (text, callback, filterOn)
|
||||
self.searchRequest = (text, callback, filterName)
|
||||
self.cv.notify()
|
||||
self.cv.release()
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
class Market:
|
||||
instance = None
|
||||
@@ -264,8 +296,6 @@ class Market:
|
||||
self.ITEMS_FORCEDMETAGROUP = {
|
||||
"'Habitat' Miner I": ("Storyline", "Miner I"),
|
||||
"'Wild' Miner I": ("Storyline", "Miner I"),
|
||||
"Medium Nano Armor Repair Unit I": ("Tech I", "Medium Armor Repairer I"),
|
||||
"Large 'Reprieve' Vestment Reconstructer I": ("Storyline", "Large Armor Repairer I"),
|
||||
"Khanid Navy Torpedo Launcher": ("Faction", "Torpedo Launcher I"),
|
||||
"Dark Blood Tracking Disruptor": ("Faction", "Tracking Disruptor I"),
|
||||
"Dread Guristas Standup Variable Spectrum ECM": ("Structure Faction", "Standup Variable Spectrum ECM I"),
|
||||
@@ -321,6 +351,7 @@ class Market:
|
||||
for mgid in mgids:
|
||||
self.META_MAP_REVERSE_GROUPED[mgid] = i
|
||||
i += 1
|
||||
self.META_MAP_REVERSE_INDICES = self.__makeReverseMetaMapIndices()
|
||||
self.SEARCH_CATEGORIES = (
|
||||
"Drone",
|
||||
"Module",
|
||||
@@ -344,6 +375,8 @@ class Market:
|
||||
2203 # Structure Modifications
|
||||
)
|
||||
self.SHOWN_MARKET_GROUPS = eos.db.getMarketTreeNodeIds(self.ROOT_MARKET_GROUPS)
|
||||
self.FIT_CATEGORIES = ['Ship']
|
||||
self.FIT_GROUPS = ['Citadel', 'Engineering Complex', 'Refinery']
|
||||
# Tell other threads that Market is at their service
|
||||
mktRdy.set()
|
||||
|
||||
@@ -363,6 +396,15 @@ class Market:
|
||||
rev[value].add(item)
|
||||
return rev
|
||||
|
||||
def __makeReverseMetaMapIndices(self):
|
||||
revmap = {}
|
||||
i = 0
|
||||
for mgids in self.META_MAP.values():
|
||||
for mgid in mgids:
|
||||
revmap[mgid] = i
|
||||
i += 1
|
||||
return revmap
|
||||
|
||||
@staticmethod
|
||||
def getItem(identity, *args, **kwargs):
|
||||
"""Get item by its ID or name"""
|
||||
@@ -382,6 +424,8 @@ class Market:
|
||||
item = eos.db.getItem(id_, *args, **kwargs)
|
||||
else:
|
||||
raise TypeError("Need Item object, integer, float or string as argument")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.error("Could not get item: {0}", identity)
|
||||
raise
|
||||
@@ -756,9 +800,9 @@ class Market:
|
||||
ships.add(item)
|
||||
return ships
|
||||
|
||||
def searchItems(self, name, callback, filterOn=True):
|
||||
def searchItems(self, name, callback, filterName=None):
|
||||
"""Find items according to given text pattern"""
|
||||
self.searchWorkerThread.scheduleSearch(name, callback, filterOn)
|
||||
self.searchWorkerThread.scheduleSearch(name, callback, filterName)
|
||||
|
||||
@staticmethod
|
||||
def getItemsWithOverrides():
|
||||
|
||||
@@ -92,6 +92,8 @@ class Network:
|
||||
raise Error(error)
|
||||
except requests.exceptions.Timeout:
|
||||
raise TimeoutError()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as error:
|
||||
raise Error(error)
|
||||
|
||||
@@ -117,6 +119,8 @@ class Network:
|
||||
raise Error(error)
|
||||
except requests.exceptions.Timeout:
|
||||
raise TimeoutError()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as error:
|
||||
raise Error(error)
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ def importDna(string, fitName=None):
|
||||
Citadel(sMkt.getItem(id_))
|
||||
string = string[string.index(str(id_)):]
|
||||
break
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Exception caught in importDna")
|
||||
pass
|
||||
@@ -107,6 +109,8 @@ def importDna(string, fitName=None):
|
||||
for i in range(int(amount)):
|
||||
try:
|
||||
m = Module(item)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Exception caught in importDna")
|
||||
continue
|
||||
|
||||
@@ -269,6 +269,8 @@ class EfsPort:
|
||||
else:
|
||||
modTypeIDSets[mod.slot].append(0)
|
||||
moduleNameSets[mod.slot].append("Empty Slot")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.error("Could not find name for module {0}".format(vars(mod)))
|
||||
|
||||
|
||||
@@ -321,6 +321,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
sMkt = Market.getInstance()
|
||||
try:
|
||||
sMkt.getItem(shipname)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
return [] # empty list is expected
|
||||
|
||||
@@ -377,6 +379,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
# Bail if we can't get item or it's not from drone category
|
||||
try:
|
||||
droneItem = sMkt.getItem(droneName, eager="group.category")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Cannot get item.")
|
||||
continue
|
||||
@@ -399,6 +403,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
# Bail if we can't get item or it's not from implant category
|
||||
try:
|
||||
implantItem = sMkt.getItem(entityData, eager="group.category")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Cannot get item.")
|
||||
continue
|
||||
@@ -415,6 +421,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
# Bail if we can't get item or it's not from implant category
|
||||
try:
|
||||
boosterItem = sMkt.getItem(entityData, eager="group.category")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Cannot get item.")
|
||||
continue
|
||||
@@ -436,6 +444,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
# Bail if we can't get item
|
||||
try:
|
||||
item = sMkt.getItem(cargoName)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Cannot get item.")
|
||||
continue
|
||||
@@ -453,6 +463,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
# If we can't get module item, skip it
|
||||
try:
|
||||
modItem = sMkt.getItem(modName)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Cannot get item.")
|
||||
continue
|
||||
@@ -475,6 +487,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
chargeItem = sMkt.getItem(chargeName, eager="group.category")
|
||||
if chargeItem.category.name == "Charge":
|
||||
m.charge = chargeItem
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Cannot get item.")
|
||||
pass
|
||||
@@ -499,6 +513,8 @@ def importEftCfg(shipname, lines, iportuser):
|
||||
"%s:\n%s" % (fitobj.ship.name, fitobj.name)
|
||||
)
|
||||
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
# Skip fit silently if we get an exception
|
||||
except Exception as e:
|
||||
pyfalog.error("Caught exception on fit.")
|
||||
@@ -593,6 +609,8 @@ def _importCreateFit(lines):
|
||||
except ValueError:
|
||||
fit.ship = Citadel(ship)
|
||||
fit.name = fitName
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning('service.port.eft.importEft: exception caught when parsing header')
|
||||
raise EftImportError
|
||||
|
||||
@@ -161,6 +161,8 @@ def importESI(string):
|
||||
fitobj.ship = Ship(sMkt.getItem(ship))
|
||||
except ValueError:
|
||||
fitobj.ship = Citadel(sMkt.getItem(ship))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Caught exception in importESI")
|
||||
return None
|
||||
@@ -201,6 +203,8 @@ def importESI(string):
|
||||
|
||||
moduleList.append(m)
|
||||
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pyfalog.warning("Could not process module.")
|
||||
continue
|
||||
|
||||
@@ -177,6 +177,8 @@ class Port:
|
||||
|
||||
except UserCancelException:
|
||||
return False, "Processing has been canceled.\n"
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Unknown exception processing: {0}", path)
|
||||
pyfalog.critical(e)
|
||||
@@ -253,11 +255,13 @@ class Port:
|
||||
# Try to import mutated module
|
||||
try:
|
||||
baseItem, mutaplasmidItem, mutations = parseMutant(lines)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if baseItem is not None and mutaplasmidItem is not None:
|
||||
return "MutatedItem", False, ((baseItem, mutaplasmidItem, mutations),)
|
||||
if baseItem is not None:
|
||||
return "FittingItem", False, ((baseItem, mutaplasmidItem, mutations),)
|
||||
# Try to import into one of additions panels
|
||||
isDrone, droneData = isValidDroneImport(string)
|
||||
if isDrone:
|
||||
|
||||
@@ -84,11 +84,13 @@ def _resolve_ship(fitting, sMkt, b_localized):
|
||||
ship = Ship(sMkt.getItem(shipType))
|
||||
except ValueError:
|
||||
ship = Citadel(sMkt.getItem(shipType))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.warning("Caught exception on _resolve_ship")
|
||||
pyfalog.error(e)
|
||||
limit -= 1
|
||||
if limit is 0:
|
||||
if limit == 0:
|
||||
break
|
||||
shipType = anything
|
||||
must_retry = True
|
||||
@@ -128,11 +130,13 @@ def _resolve_module(hardware, sMkt, b_localized):
|
||||
must_retry = False
|
||||
try:
|
||||
item = sMkt.getItem(moduleName, eager="group.category")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.warning("Caught exception on _resolve_module")
|
||||
pyfalog.error(e)
|
||||
limit -= 1
|
||||
if limit is 0:
|
||||
if limit == 0:
|
||||
break
|
||||
moduleName = emergency
|
||||
must_retry = True
|
||||
@@ -158,6 +162,8 @@ def importXml(text, iportuser):
|
||||
for fitting in fittings:
|
||||
try:
|
||||
fitobj = _resolve_ship(fitting, sMkt, b_localized)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
failed += 1
|
||||
continue
|
||||
@@ -264,6 +270,8 @@ def exportXml(fits, iportuser, callback):
|
||||
description.setAttribute(
|
||||
"value", re.sub("(\r|\n|\r\n)+", "<br>", notes) if notes is not None else ""
|
||||
)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.warning("read description is failed, msg=%s\n" % e.args)
|
||||
|
||||
@@ -328,6 +336,8 @@ def exportXml(fits, iportuser, callback):
|
||||
hardware.setAttribute("slot", "cargo")
|
||||
hardware.setAttribute("type", name)
|
||||
fitting.appendChild(hardware)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.error("Failed on fitID: %d, message: %s" % e.message)
|
||||
continue
|
||||
|
||||
@@ -17,6 +17,8 @@ class PreCheckMessage:
|
||||
app = wx.App(False)
|
||||
wx.MessageBox(msg, 'Error', wx.ICON_ERROR | wx.STAY_ON_TOP)
|
||||
app.MainLoop()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
@@ -45,6 +47,8 @@ def version_precheck():
|
||||
|
||||
import wx
|
||||
version_block += "\nwxPython version: {} ({})".format(VERSION_STRING, wx.wxWidgets_version)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
msg = "pyfa requires wxPython v4.0.0b2+. You can download wxPython from https://wxpython.org/pages/downloads/"
|
||||
raise PreCheckException(msg)
|
||||
@@ -56,6 +60,8 @@ def version_precheck():
|
||||
|
||||
if (int(saMatch.group(1)), int(saMatch.group(2)), int(saMatch.group(3))) < (1, 0, 5):
|
||||
raise Exception()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
msg = "pyfa requires SQLAlchemy v1.0.5+. You can download SQLAlchemy from https://www.sqlalchemy.org/download.html"
|
||||
raise PreCheckException(msg)
|
||||
@@ -67,12 +73,16 @@ def version_precheck():
|
||||
|
||||
if int(logVersion[0]) < 1:
|
||||
raise Exception()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
raise PreCheckException("pyfa requires Logbook version 1.0.0+. You can download Logbook from https://pypi.python.org/pypi/Logbook")
|
||||
|
||||
try:
|
||||
import requests
|
||||
version_block += "\nRequests version: {}".format(requests.__version__)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
msg = "pyfa requires the requests module. You can download requests from https://pypi.python.org/pypi/requests"
|
||||
raise PreCheckException(msg)
|
||||
@@ -80,6 +90,8 @@ def version_precheck():
|
||||
try:
|
||||
import dateutil
|
||||
version_block += "\nDateutil version: {}".format(dateutil.__version__)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
msg = "pyfa requires the python-dateutil module. You can download python-dateutil form https://pypi.python.org/pypi/python-dateutil"
|
||||
raise PreCheckException(msg)
|
||||
|
||||
@@ -131,6 +131,8 @@ class Price:
|
||||
except TimeoutError:
|
||||
pyfalog.warning("Price fetch timeout for source {}".format(source))
|
||||
timedOutSources[source] = True
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.warn('Failed to fetch prices from price source {}: {}'.format(source, e))
|
||||
# Sources remove price map items as they fetch info, if none remain then we're done
|
||||
@@ -176,6 +178,8 @@ class Price:
|
||||
def cb():
|
||||
try:
|
||||
callback(requests)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Execution of callback from getPrices failed.")
|
||||
pyfalog.critical(e)
|
||||
@@ -211,6 +215,8 @@ class Price:
|
||||
replacementsCheaper[replacee] = replacer
|
||||
try:
|
||||
callback(replacementsCheaper)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.critical("Execution of callback from findCheaperReplacements failed.")
|
||||
pyfalog.critical(e)
|
||||
@@ -229,11 +235,14 @@ class PriceWorkerThread(threading.Thread):
|
||||
self.name = "PriceWorker"
|
||||
self.queue = queue.Queue()
|
||||
self.wait = {}
|
||||
self.running = True
|
||||
pyfalog.debug("Initialize PriceWorkerThread.")
|
||||
|
||||
def run(self):
|
||||
queue = self.queue
|
||||
while True:
|
||||
if not self.running:
|
||||
break
|
||||
# Grab our data
|
||||
callback, requests, fetchTimeout, validityOverride = queue.get()
|
||||
|
||||
@@ -259,6 +268,9 @@ class PriceWorkerThread(threading.Thread):
|
||||
callbacks = self.wait.setdefault(price.typeID, [])
|
||||
callbacks.append(callback)
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
|
||||
# Import market sources only to initialize price source modules, they register on their own
|
||||
from service.marketSources import evemarketer, evemarketdata, evepraisal # noqa: E402
|
||||
|
||||
@@ -88,6 +88,8 @@ class AuthHandler(http.server.BaseHTTPRequestHandler):
|
||||
# For implicit mode, we have to serve up the page which will take the hash and redirect using a querystring
|
||||
pyfalog.info("Processing response from EVE Online.")
|
||||
msg = "Processing response from EVE Online"
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as ex:
|
||||
pyfalog.error("Error logging into EVE")
|
||||
pyfalog.error(ex)
|
||||
|
||||
@@ -69,6 +69,8 @@ class SettingsProvider:
|
||||
for item in defaults:
|
||||
if item not in info:
|
||||
info[item] = defaults[item]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
info = {}
|
||||
info.update(defaults)
|
||||
|
||||
@@ -41,6 +41,7 @@ class CheckUpdateThread(threading.Thread):
|
||||
self.callback = callback
|
||||
self.settings = UpdateSettings.getInstance()
|
||||
self.network = Network.getInstance()
|
||||
self.running = True
|
||||
|
||||
def run(self):
|
||||
network = Network.getInstance()
|
||||
@@ -49,11 +50,13 @@ class CheckUpdateThread(threading.Thread):
|
||||
try:
|
||||
response = network.get(
|
||||
url='https://www.pyfa.io/update_check?pyfa_version={}&client_hash={}'.format(config.version, config.getClientSecret()),
|
||||
type=network.UPDATE)
|
||||
type=network.UPDATE, timeout=5)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
response = network.get(
|
||||
url='https://api.github.com/repos/pyfa-org/Pyfa/releases',
|
||||
type=network.UPDATE)
|
||||
type=network.UPDATE, timeout=5)
|
||||
|
||||
jsonResponse = response.json()
|
||||
jsonResponse.sort(
|
||||
@@ -81,6 +84,8 @@ class CheckUpdateThread(threading.Thread):
|
||||
wx.CallAfter(self.callback, release, rVersion)
|
||||
break
|
||||
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except Exception as e:
|
||||
pyfalog.error("Caught exception in run")
|
||||
pyfalog.error(e)
|
||||
@@ -90,6 +95,9 @@ class CheckUpdateThread(threading.Thread):
|
||||
def versiontuple(v):
|
||||
return tuple(map(int, (v.split("."))))
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
|
||||
class Update:
|
||||
instance = None
|
||||
|
||||
@@ -166173,7 +166173,7 @@
|
||||
"dogmaAttributes": [
|
||||
{
|
||||
"attributeID": 6,
|
||||
"value": 40.0
|
||||
"value": 36.0
|
||||
},
|
||||
{
|
||||
"attributeID": 9,
|
||||
@@ -166185,7 +166185,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 50,
|
||||
"value": 4.0
|
||||
"value": 5.0
|
||||
},
|
||||
{
|
||||
"attributeID": 73,
|
||||
@@ -166193,7 +166193,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 84,
|
||||
"value": 72.0
|
||||
"value": 79.0
|
||||
},
|
||||
{
|
||||
"attributeID": 182,
|
||||
@@ -166373,7 +166373,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 84,
|
||||
"value": 83.0
|
||||
"value": 79.0
|
||||
},
|
||||
{
|
||||
"attributeID": 182,
|
||||
@@ -166397,7 +166397,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 4.0
|
||||
"value": 1.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -166533,7 +166533,7 @@
|
||||
"dogmaAttributes": [
|
||||
{
|
||||
"attributeID": 6,
|
||||
"value": 160.0
|
||||
"value": 144.0
|
||||
},
|
||||
{
|
||||
"attributeID": 9,
|
||||
@@ -166553,7 +166553,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 84,
|
||||
"value": 290.0
|
||||
"value": 317.0
|
||||
},
|
||||
{
|
||||
"attributeID": 182,
|
||||
@@ -166721,11 +166721,11 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 30,
|
||||
"value": 120.0
|
||||
"value": 108.0
|
||||
},
|
||||
{
|
||||
"attributeID": 50,
|
||||
"value": 21.0
|
||||
"value": 20.0
|
||||
},
|
||||
{
|
||||
"attributeID": 73,
|
||||
@@ -166733,7 +166733,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 84,
|
||||
"value": 331.0
|
||||
"value": 317.0
|
||||
},
|
||||
{
|
||||
"attributeID": 182,
|
||||
@@ -166757,7 +166757,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 4.0
|
||||
"value": 1.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -166983,7 +166983,7 @@
|
||||
"dogmaAttributes": [
|
||||
{
|
||||
"attributeID": 6,
|
||||
"value": 400.0
|
||||
"value": 360.0
|
||||
},
|
||||
{
|
||||
"attributeID": 9,
|
||||
@@ -166995,7 +166995,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 50,
|
||||
"value": 47.0
|
||||
"value": 49.0
|
||||
},
|
||||
{
|
||||
"attributeID": 73,
|
||||
@@ -167003,7 +167003,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 84,
|
||||
"value": 725.0
|
||||
"value": 794.0
|
||||
},
|
||||
{
|
||||
"attributeID": 182,
|
||||
@@ -167171,11 +167171,11 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 30,
|
||||
"value": 1800.0
|
||||
"value": 1620.0
|
||||
},
|
||||
{
|
||||
"attributeID": 50,
|
||||
"value": 46.0
|
||||
"value": 40.0
|
||||
},
|
||||
{
|
||||
"attributeID": 73,
|
||||
@@ -167183,7 +167183,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 84,
|
||||
"value": 828.0
|
||||
"value": 794.0
|
||||
},
|
||||
{
|
||||
"attributeID": 182,
|
||||
@@ -167207,7 +167207,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 4.0
|
||||
"value": 1.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -473928,7 +473928,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474022,7 +474022,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474116,7 +474116,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474210,7 +474210,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474304,7 +474304,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474398,7 +474398,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474492,7 +474492,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474586,7 +474586,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -474680,7 +474680,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -563033,7 +563033,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -563127,7 +563127,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -563221,7 +563221,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -780699,7 +780699,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -780793,7 +780793,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -780887,7 +780887,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -783267,7 +783267,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -783361,7 +783361,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -783455,7 +783455,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -1096977,7 +1096977,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 6.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -1097080,7 +1097080,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 7.0
|
||||
"value": 6.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -1637789,7 +1637789,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -1638073,7 +1638073,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
@@ -1638440,7 +1638440,7 @@
|
||||
},
|
||||
{
|
||||
"attributeID": 633,
|
||||
"value": 9.0
|
||||
"value": 8.0
|
||||
},
|
||||
{
|
||||
"attributeID": 1180,
|
||||
|
||||
@@ -5362,12 +5362,11 @@
|
||||
"descriptionID": 87829,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 610,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 2,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
@@ -5406,12 +5405,11 @@
|
||||
"descriptionID": 95300,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 610,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 1,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 8,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
@@ -5450,12 +5448,11 @@
|
||||
"descriptionID": 87832,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 611,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 2,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
@@ -5494,12 +5491,11 @@
|
||||
"descriptionID": 95295,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 611,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 1,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 8,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
@@ -5538,12 +5534,11 @@
|
||||
"descriptionID": 87835,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 612,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 2,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
@@ -5582,12 +5577,11 @@
|
||||
"descriptionID": 95315,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 612,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 1,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 8,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
@@ -36877,7 +36871,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -36898,7 +36892,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -36919,7 +36913,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -36940,7 +36934,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -36961,7 +36955,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -36982,7 +36976,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -37003,7 +36997,7 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -37024,7 +37018,7 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -37045,7 +37039,7 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -56244,7 +56238,7 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -56265,7 +56259,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -56286,7 +56280,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -83156,7 +83150,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -83177,7 +83171,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -83198,7 +83192,7 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -84023,7 +84017,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -84044,7 +84038,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -84065,7 +84059,7 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -146773,7 +146767,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 3,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 6,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"techLevel": 1,
|
||||
@@ -146825,7 +146819,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 3,
|
||||
"metaLevel": 7,
|
||||
"metaLevel": 6,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"techLevel": 1,
|
||||
@@ -232483,7 +232477,7 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -232575,7 +232569,7 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -232721,7 +232715,7 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 4,
|
||||
"metaLevel": 9,
|
||||
"metaLevel": 8,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
@@ -510303,7 +510297,7 @@
|
||||
"raceID": 1,
|
||||
"techLevel": 1,
|
||||
"typeID": 4529,
|
||||
"typeName": "Small I-a Polarized Armor Regenerator",
|
||||
"typeName": "Small I-a Enduring Armor Repairer",
|
||||
"typeNameID": 77030,
|
||||
"variationParentTypeID": 523,
|
||||
"volume": 5.0
|
||||
@@ -510334,13 +510328,13 @@
|
||||
"descriptionID": 87515,
|
||||
"groupID": 62,
|
||||
"iconID": 80,
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 2,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"radius": 1.0,
|
||||
"techLevel": 1,
|
||||
"typeID": 4531,
|
||||
"typeName": "Small Inefficient Armor Repair Unit",
|
||||
@@ -510358,13 +510352,13 @@
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 4,
|
||||
"metaLevel": 1,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
"techLevel": 1,
|
||||
"typeID": 4533,
|
||||
"typeName": "Small 'Accommodation' Vestment Reconstructer I",
|
||||
"typeName": "Small ACM Compact Armor Repairer",
|
||||
"typeNameID": 77032,
|
||||
"variationParentTypeID": 523,
|
||||
"volume": 5.0
|
||||
@@ -510376,13 +510370,13 @@
|
||||
"descriptionID": 87517,
|
||||
"groupID": 62,
|
||||
"iconID": 80,
|
||||
"marketGroupID": 1049,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 3,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 8,
|
||||
"radius": 1.0,
|
||||
"techLevel": 1,
|
||||
"typeID": 4535,
|
||||
"typeName": "Small Automated Carapace Restoration",
|
||||
@@ -514477,7 +514471,7 @@
|
||||
"raceID": 1,
|
||||
"techLevel": 1,
|
||||
"typeID": 4569,
|
||||
"typeName": "Medium I-a Polarized Armor Regenerator",
|
||||
"typeName": "Medium I-a Enduring Armor Repairer",
|
||||
"typeNameID": 77034,
|
||||
"variationParentTypeID": 3528,
|
||||
"volume": 10.0
|
||||
@@ -514808,13 +514802,13 @@
|
||||
"descriptionID": 87519,
|
||||
"groupID": 62,
|
||||
"iconID": 80,
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 2,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"radius": 1.0,
|
||||
"techLevel": 1,
|
||||
"typeID": 4571,
|
||||
"typeName": "Medium Inefficient Armor Repair Unit",
|
||||
@@ -515131,13 +515125,13 @@
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 4,
|
||||
"metaLevel": 1,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
"techLevel": 1,
|
||||
"typeID": 4573,
|
||||
"typeName": "Medium 'Accommodation' Vestment Reconstructer I",
|
||||
"typeName": "Medium ACM Compact Armor Repairer",
|
||||
"typeNameID": 77036,
|
||||
"variationParentTypeID": 3528,
|
||||
"volume": 10.0
|
||||
@@ -515461,13 +515455,13 @@
|
||||
"descriptionID": 87521,
|
||||
"groupID": 62,
|
||||
"iconID": 80,
|
||||
"marketGroupID": 1050,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 3,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 8,
|
||||
"radius": 1.0,
|
||||
"techLevel": 1,
|
||||
"typeID": 4575,
|
||||
"typeName": "Medium Automated Carapace Restoration",
|
||||
@@ -516087,7 +516081,7 @@
|
||||
"mass": 500.0,
|
||||
"metaLevel": 4,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"techLevel": 1,
|
||||
"typeID": 4579,
|
||||
@@ -520665,7 +520659,7 @@
|
||||
"raceID": 1,
|
||||
"techLevel": 1,
|
||||
"typeID": 4609,
|
||||
"typeName": "Large I-a Polarized Armor Regenerator",
|
||||
"typeName": "Large I-a Enduring Armor Repairer",
|
||||
"typeNameID": 77039,
|
||||
"variationParentTypeID": 3538,
|
||||
"volume": 50.0
|
||||
@@ -520996,13 +520990,13 @@
|
||||
"descriptionID": 87524,
|
||||
"groupID": 62,
|
||||
"iconID": 80,
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 2,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"radius": 1.0,
|
||||
"techLevel": 1,
|
||||
"typeID": 4611,
|
||||
"typeName": "Large Inefficient Armor Repair Unit",
|
||||
@@ -521320,13 +521314,13 @@
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 4,
|
||||
"metaLevel": 1,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"raceID": 4,
|
||||
"techLevel": 1,
|
||||
"typeID": 4613,
|
||||
"typeName": "Large 'Accommodation' Vestment Reconstructer I",
|
||||
"typeName": "Large ACM Compact Armor Repairer",
|
||||
"typeNameID": 77041,
|
||||
"variationParentTypeID": 3538,
|
||||
"volume": 50.0
|
||||
@@ -521638,13 +521632,13 @@
|
||||
"descriptionID": 87526,
|
||||
"groupID": 62,
|
||||
"iconID": 80,
|
||||
"marketGroupID": 1051,
|
||||
"mass": 500.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 3,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 8,
|
||||
"radius": 1.0,
|
||||
"techLevel": 1,
|
||||
"typeID": 4615,
|
||||
"typeName": "Large Automated Carapace Restoration",
|
||||
@@ -522579,7 +522573,7 @@
|
||||
"mass": 500.0,
|
||||
"metaLevel": 5,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 4,
|
||||
"techLevel": 1,
|
||||
"typeID": 4621,
|
||||
@@ -602906,12 +602900,11 @@
|
||||
"descriptionID": 87666,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 609,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 2,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 2,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
@@ -602975,12 +602968,11 @@
|
||||
"descriptionID": 95311,
|
||||
"groupID": 40,
|
||||
"iconID": 84,
|
||||
"marketGroupID": 609,
|
||||
"mass": 0.0,
|
||||
"metaGroupID": 1,
|
||||
"metaLevel": 1,
|
||||
"portionSize": 1,
|
||||
"published": true,
|
||||
"published": false,
|
||||
"raceID": 8,
|
||||
"radius": 500.0,
|
||||
"techLevel": 1,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"field_name": "client_build",
|
||||
"field_value": 1651039
|
||||
"field_value": 1655072
|
||||
},
|
||||
{
|
||||
"field_name": "dump_time",
|
||||
"field_value": 1579607729
|
||||
"field_value": 1580211149
|
||||
}
|
||||
]
|
||||
2
tox.ini
2
tox.ini
@@ -7,7 +7,7 @@ passenv = CI TRAVIS TRAVIS_*
|
||||
deps =
|
||||
-rrequirements.txt
|
||||
-rrequirements_test.txt
|
||||
basepython = python3.6
|
||||
basepython = python3.8
|
||||
commands = py.test -vv --cov Pyfa tests2/
|
||||
|
||||
[testenv:pep8]
|
||||
|
||||
@@ -35,3 +35,16 @@ class Timer:
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.checkpoint('finished')
|
||||
pass
|
||||
|
||||
|
||||
class CountdownTimer:
|
||||
|
||||
def __init__(self, timeout):
|
||||
self.timeout = timeout
|
||||
self.start = time.time()
|
||||
|
||||
def elapsed(self):
|
||||
return time.time() - self.start
|
||||
|
||||
def remainder(self):
|
||||
return max(self.timeout - self.elapsed(), 0)
|
||||
|
||||
@@ -1 +1 @@
|
||||
version: v2.16.0
|
||||
version: v2.17.0
|
||||
|
||||
Reference in New Issue
Block a user