Merge branch 'master' into dps_sim_graph

This commit is contained in:
DarkPhoenix
2019-06-13 12:32:38 +03:00
13 changed files with 239 additions and 83 deletions

View File

@@ -22,8 +22,10 @@ from math import exp, log, radians, sin, inf
from logbook import Logger from logbook import Logger
import eos.config
from eos.const import FittingHardpoint, FittingModuleState from eos.const import FittingHardpoint, FittingModuleState
from eos.graph import SmoothGraph from eos.graph import SmoothGraph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
pyfalog = Logger(__name__) pyfalog = Logger(__name__)
@@ -58,9 +60,10 @@ class FitDpsVsRangeGraph(SmoothGraph):
tgtSpeed = self.penalizeModChain(tgtSpeed, tgtSpeedMods) tgtSpeed = self.penalizeModChain(tgtSpeed, tgtSpeedMods)
tgtSigRad = self.penalizeModChain(tgtSigRad, tgtSigRadMods) tgtSigRad = self.penalizeModChain(tgtSigRad, tgtSigRadMods)
attRad = fit.ship.getModifiedItemAttr('radius', 0) attRad = fit.ship.getModifiedItemAttr('radius', 0)
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
for mod in fit.modules: for mod in fit.modules:
dps = mod.getDps(targetResists=fit.targetResists).total dps = mod.getDps(targetResists=fit.targetResists, spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).total
if mod.hardpoint == FittingHardpoint.TURRET: if mod.hardpoint == FittingHardpoint.TURRET:
if mod.state >= FittingModuleState.ACTIVE: if mod.state >= FittingModuleState.ACTIVE:
total += dps * self.calculateTurretMultiplier(fit, mod, distance, angle, tgtSpeed, tgtSigRad) total += dps * self.calculateTurretMultiplier(fit, mod, distance, angle, tgtSpeed, tgtSigRad)

View File

@@ -1167,6 +1167,10 @@ class Fit(object):
return self.__capRecharge return self.__capRecharge
@property
def capDelta(self):
return (self.__capRecharge or 0) - (self.__capUsed or 0)
def calculateCapRecharge(self, percent=PEAK_RECHARGE): def calculateCapRecharge(self, percent=PEAK_RECHARGE):
capacity = self.ship.getModifiedItemAttr("capacitorCapacity") capacity = self.ship.getModifiedItemAttr("capacitorCapacity")
rechargeRate = self.ship.getModifiedItemAttr("rechargeRate") / 1000.0 rechargeRate = self.ship.getModifiedItemAttr("rechargeRate") / 1000.0

View File

@@ -8,10 +8,12 @@ import gui.mainFrame
import gui.utils.color as colorUtils import gui.utils.color as colorUtils
import gui.utils.draw as drawUtils import gui.utils.draw as drawUtils
import gui.utils.fonts as fonts import gui.utils.fonts as fonts
from .events import FitSelected, SearchSelected, ImportSelected, Stage1Selected, Stage2Selected, Stage3Selected
from gui.bitmap_loader import BitmapLoader from gui.bitmap_loader import BitmapLoader
from service.fit import Fit
from gui.utils.helpers_wxPython import HandleCtrlBackspace from gui.utils.helpers_wxPython import HandleCtrlBackspace
from service.fit import Fit
from utils.cjk import isStringCjk
from .events import FitSelected, SearchSelected, ImportSelected, Stage1Selected, Stage2Selected, Stage3Selected
pyfalog = Logger(__name__) pyfalog = Logger(__name__)
@@ -86,7 +88,8 @@ class NavigationPanel(SFItem.SFBrowserItem):
search = self.BrowserSearchBox.GetValue() search = self.BrowserSearchBox.GetValue()
# Make sure we do not count wildcard as search symbol # Make sure we do not count wildcard as search symbol
realsearch = search.replace("*", "") realsearch = search.replace("*", "")
if len(realsearch) >= 3: minChars = 1 if isStringCjk(realsearch) else 3
if len(realsearch) >= minChars:
self.lastSearch = search self.lastSearch = search
wx.PostEvent(self.shipBrowser, SearchSelected(text=search, back=False)) wx.PostEvent(self.shipBrowser, SearchSelected(text=search, back=False))

View File

@@ -85,46 +85,44 @@ class CapacitorViewFull(StatsView):
sizerCapacitor.Add(baseBox, 0, wx.ALIGN_CENTER_HORIZONTAL) sizerCapacitor.Add(baseBox, 0, wx.ALIGN_CENTER_HORIZONTAL)
tooltip = wx.ToolTip("Capacitor throughput") tooltip = wx.ToolTip("Extra stats")
bitmap = BitmapLoader.getStaticBitmap("capacitorRecharge_big", parent, "gui") bitmap = BitmapLoader.getStaticBitmap("capacitorRecharge_big", parent, "gui")
bitmap.SetToolTip(tooltip) bitmap.SetToolTip(tooltip)
baseBox.Add(bitmap, 0, wx.ALIGN_CENTER) baseBox.Add(bitmap, 0, wx.ALIGN_CENTER)
# Recharge # Delta
chargeSizer = wx.FlexGridSizer(2, 3, 0, 0) chargeSizer = wx.BoxSizer(wx.VERTICAL)
baseBox.Add(chargeSizer, 0, wx.ALIGN_CENTER) baseBox.Add(chargeSizer, 0, wx.ALIGN_CENTER)
chargeSizer.Add(wx.StaticText(parent, wx.ID_ANY, "+ "), 0, wx.ALIGN_CENTER) lbl = wx.StaticText(parent, wx.ID_ANY, "0 GJ/s")
lbl = wx.StaticText(parent, wx.ID_ANY, "0.0") setattr(self, "label%sCapacitorDelta" % panel.capitalize(), lbl)
setattr(self, "label%sCapacitorRecharge" % panel.capitalize(), lbl)
chargeSizer.Add(lbl, 0, wx.ALIGN_CENTER) chargeSizer.Add(lbl, 0, wx.ALIGN_CENTER)
chargeSizer.Add(wx.StaticText(parent, wx.ID_ANY, " GJ/s"), 0, wx.ALIGN_CENTER)
# Discharge # Resists
chargeSizer.Add(wx.StaticText(parent, wx.ID_ANY, "- "), 0, wx.ALIGN_CENTER) lbl = wx.StaticText(parent, wx.ID_ANY, "0%")
lbl = wx.StaticText(parent, wx.ID_ANY, "0.0") setattr(self, "label%sCapacitorResist" % panel.capitalize(), lbl)
setattr(self, "label%sCapacitorDischarge" % panel.capitalize(), lbl)
chargeSizer.Add(lbl, 0, wx.ALIGN_CENTER) chargeSizer.Add(lbl, 0, wx.ALIGN_CENTER)
chargeSizer.Add(wx.StaticText(parent, wx.ID_ANY, " GJ/s"), 0, wx.ALIGN_CENTER)
def refreshPanel(self, fit): def refreshPanel(self, fit):
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here # If we did anything intresting, we'd update our labels to reflect the new fit's stats here
stats = ( stats = (
("label%sCapacitorCapacity", lambda: fit.ship.getModifiedItemAttr("capacitorCapacity"), 3, 0, 9), ("label%sCapacitorCapacity", lambda: fit.ship.getModifiedItemAttr("capacitorCapacity"), 3, 0, 9, False, ''),
("label%sCapacitorRecharge", lambda: fit.capRecharge, 3, 0, 0), ("label%sCapacitorDelta", lambda: fit.capDelta, 3, 0, 0, True, ' GJ/s'),
("label%sCapacitorDischarge", lambda: fit.capUsed, 3, 0, 0), ("label%sCapacitorResist", lambda: (1 - fit.ship.getModifiedItemAttr("energyWarfareResistance", 1)) * 100, 3, 0, 0, False, '%'),
) )
if fit is not None: if fit is not None:
neut_resist = fit.ship.getModifiedItemAttr("energyWarfareResistance", 0) cap_amount = fit.ship.getModifiedItemAttr("capacitorCapacity")
cap_recharge = fit.capRecharge cap_recharge = fit.capRecharge
cap_use = fit.capUsed cap_use = fit.capUsed
neut_res = fit.ship.getModifiedItemAttr("energyWarfareResistance", 1)
else: else:
neut_resist = 0 cap_amount = 0
cap_recharge = 0 cap_recharge = 0
cap_use = 0 cap_use = 0
neut_res = 1
panel = "Full" panel = "Full"
for labelName, value, prec, lowest, highest in stats: for labelName, value, prec, lowest, highest, forceSign, unit in stats:
label = getattr(self, labelName % panel) label = getattr(self, labelName % panel)
value = value() if fit is not None else 0 value = value() if fit is not None else 0
value = value if value is not None else 0 value = value if value is not None else 0
@@ -132,15 +130,19 @@ class CapacitorViewFull(StatsView):
label.SetLabel(value) label.SetLabel(value)
label.SetToolTip(wx.ToolTip(value)) label.SetToolTip(wx.ToolTip(value))
else: else:
label.SetLabel(formatAmount(value, prec, lowest, highest)) label.SetLabel('{}{}'.format(formatAmount(value, prec, lowest, highest, forceSign=forceSign), unit))
label.SetToolTip(wx.ToolTip("%.1f" % value)) label.SetToolTip(wx.ToolTip("%.1f" % value))
if labelName in ("label%sCapacitorRecharge", "label%sCapacitorDischarge"): if labelName == 'label%sCapacitorDelta':
neut_resist_preformat = 100 - (neut_resist * 100) if neut_resist else neut_resist label_tooltip = 'Capacitor delta:\n+{} GJ/s\n-{} GJ/s'.format(
label_tooltip = "Capacitor delta: {}\nNeut resistance: {}%".format( formatAmount(cap_recharge, 3, 0, 3),
formatAmount(cap_recharge - cap_use, 3, 0, 3, forceSign=True), formatAmount(cap_use, 3, 0, 3))
formatAmount(neut_resist_preformat, 3, 0, 3))
label.SetToolTip(wx.ToolTip(label_tooltip)) label.SetToolTip(wx.ToolTip(label_tooltip))
if labelName == 'label%sCapacitorResist':
texts = ['Neutralizer resistance']
if cap_amount > 0 and neut_res < 1:
texts.append('Effective capacity: {} GJ'.format(formatAmount(cap_amount / neut_res, 3, 0, 9)))
label.SetToolTip(wx.ToolTip('\n'.join(texts)))
capState = fit.capState if fit is not None else 0 capState = fit.capState if fit is not None else 0
capStable = fit.capStable if fit is not None else False capStable = fit.capStable if fit is not None else False

View File

@@ -1 +1 @@
__all__ = ['evemarketer', 'evemarketdata'] __all__ = ['evemarketer', 'evemarketdata', 'evepraisal']

View File

@@ -31,7 +31,7 @@ pyfalog = Logger(__name__)
class EveMarketData: class EveMarketData:
name = "eve-marketdata.com" name = 'eve-marketdata.com'
def __init__(self, priceMap, system, fetchTimeout): def __init__(self, priceMap, system, fetchTimeout):
# Try selected system first # Try selected system first
@@ -42,24 +42,24 @@ class EveMarketData:
@staticmethod @staticmethod
def fetchPrices(priceMap, fetchTimeout, system=None): def fetchPrices(priceMap, fetchTimeout, system=None):
params = {"type_ids": ','.join(str(typeID) for typeID in priceMap)} params = {'type_ids': ','.join(str(typeID) for typeID in priceMap)}
if system is not None: if system is not None:
params["system_id"] = system params['system_id'] = system
baseurl = "https://eve-marketdata.com/api/item_prices.xml" baseurl = 'https://eve-marketdata.com/api/item_prices.xml'
network = Network.getInstance() network = Network.getInstance()
data = network.request(baseurl, network.PRICES, params=params, timeout=fetchTimeout) data = network.get(url=baseurl, type=network.PRICES, params=params, timeout=fetchTimeout)
xml = minidom.parseString(data.text) xml = minidom.parseString(data.text)
types = xml.getElementsByTagName("eve").item(0).getElementsByTagName("price") types = xml.getElementsByTagName('eve').item(0).getElementsByTagName('price')
# Cycle through all types we've got from request # Cycle through all types we've got from request
for type_ in types: for type_ in types:
# Get data out of each typeID details tree # Get data out of each typeID details tree
typeID = int(type_.getAttribute("id")) typeID = int(type_.getAttribute('id'))
try: try:
price = float(type_.firstChild.data) price = float(type_.firstChild.data)
except (TypeError, ValueError): except (TypeError, ValueError):
pyfalog.warning("Failed to get price for: {0}", type_) pyfalog.warning('Failed to get price for: {0}', type_)
continue continue
# eve-marketdata returns 0 if price data doesn't even exist for the item # eve-marketdata returns 0 if price data doesn't even exist for the item

View File

@@ -31,7 +31,7 @@ pyfalog = Logger(__name__)
class EveMarketer: class EveMarketer:
name = "evemarketer" name = 'evemarketer'
def __init__(self, priceMap, system, fetchTimeout): def __init__(self, priceMap, system, fetchTimeout):
# Try selected system first # Try selected system first
@@ -42,24 +42,24 @@ class EveMarketer:
@staticmethod @staticmethod
def fetchPrices(priceMap, fetchTimeout, system=None): def fetchPrices(priceMap, fetchTimeout, system=None):
params = {"typeid": {typeID for typeID in priceMap}} params = {'typeid': {typeID for typeID in priceMap}}
if system is not None: if system is not None:
params["usesystem"] = system params['usesystem'] = system
baseurl = "https://api.evemarketer.com/ec/marketstat" baseurl = 'https://api.evemarketer.com/ec/marketstat'
network = Network.getInstance() network = Network.getInstance()
data = network.request(baseurl, network.PRICES, params=params, timeout=fetchTimeout) data = network.get(url=baseurl, type=network.PRICES, params=params, timeout=fetchTimeout)
xml = minidom.parseString(data.text) xml = minidom.parseString(data.text)
types = xml.getElementsByTagName("marketstat").item(0).getElementsByTagName("type") types = xml.getElementsByTagName('marketstat').item(0).getElementsByTagName('type')
# Cycle through all types we've got from request # Cycle through all types we've got from request
for type_ in types: for type_ in types:
# Get data out of each typeID details tree # Get data out of each typeID details tree
typeID = int(type_.getAttribute("id")) typeID = int(type_.getAttribute('id'))
sell = type_.getElementsByTagName("sell").item(0) sell = type_.getElementsByTagName('sell').item(0)
# If price data wasn't there, set price to zero # If price data wasn't there, skip the item
try: try:
percprice = float(sell.getElementsByTagName("percentile").item(0).firstChild.data) percprice = float(sell.getElementsByTagName('percentile').item(0).firstChild.data)
except (TypeError, ValueError): except (TypeError, ValueError):
pyfalog.warning("Failed to get price for: {0}", type_) pyfalog.warning('Failed to get price for: {0}', type_)
continue continue
# Price is 0 if evemarketer has info on this item, but it is not available # Price is 0 if evemarketer has info on this item, but it is not available
@@ -67,7 +67,6 @@ class EveMarketer:
# such items to check globally, and do not skip if requested globally # such items to check globally, and do not skip if requested globally
if percprice == 0 and system is not None: if percprice == 0 and system is not None:
continue continue
priceMap[typeID].update(PriceStatus.fetchSuccess, percprice) priceMap[typeID].update(PriceStatus.fetchSuccess, percprice)
del priceMap[typeID] del priceMap[typeID]

View File

@@ -0,0 +1,78 @@
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
from logbook import Logger
from eos.saveddata.price import PriceStatus
from service.network import Network
from service.price import Price
pyfalog = Logger(__name__)
systemAliases = {
None: 'universe',
30000142: 'jita',
30002187: 'amarr',
30002659: 'dodixie',
30002510: 'rens',
30002053: 'hek'}
class EvePraisal:
name = 'evepraisal'
def __init__(self, priceMap, system, fetchTimeout):
# Try selected system first
self.fetchPrices(priceMap, max(2 * fetchTimeout / 3, 2), system)
# If price was not available - try globally
if priceMap:
self.fetchPrices(priceMap, max(fetchTimeout / 3, 2))
@staticmethod
def fetchPrices(priceMap, fetchTimeout, system=None):
if system not in systemAliases:
return
jsonData = {
'market_name': systemAliases[system],
'items': [{'type_id': typeID} for typeID in priceMap]}
baseurl = 'https://evepraisal.com/appraisal/structured.json'
network = Network.getInstance()
resp = network.post(baseurl, network.PRICES, jsonData=jsonData, timeout=fetchTimeout)
data = resp.json()
try:
itemsData = data['appraisal']['items']
except (KeyError, TypeError):
return
# Cycle through all types we've got from request
for itemData in itemsData:
try:
typeID = int(itemData['typeID'])
price = itemData['prices']['sell']['min']
except (KeyError, TypeError):
continue
# evepraisal returns 0 if price data doesn't even exist for the item
if price == 0:
continue
priceMap[typeID].update(PriceStatus.fetchSuccess, price)
del priceMap[typeID]
Price.register(EvePraisal)

View File

@@ -70,36 +70,18 @@ class Network:
return cls._instance return cls._instance
def request(self, url, type, *args, **kwargs): def get(self, url, type, **kwargs):
self.__networkAccessCheck(type)
# URL is required to be https as of right now headers = self.__getHeaders()
# print "Starting request: %s\n\tType: %s\n\tPost Data: %s"%(url,type,data) proxies = self.__getProxies()
# Make sure request is enabled
access = NetworkSettings.getInstance().getAccess()
if not self.ENABLED & access or not type & access:
pyfalog.warning("Access not enabled - please enable in Preferences > Network")
raise Error("Access not enabled - please enable in Preferences > Network")
# Set up some things for the request
versionString = "{0}".format(config.version)
headers = {"User-Agent": "pyfa {0} (python-requests {1})".format(versionString, requests.__version__)}
# user-agent: pyfa 2.0.0b4 git -YC120.2 1.2 (python-requests 2.18.4)
# python-requests supports setting proxy for request as parameter to get() / post()
# in a form like: proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080' }
# or with HTTP Basic auth support: proxies = {'http': 'http://user:pass@10.10.1.10:3128/'}
# then you do: requests.get('http://example.org', proxies=proxies)
proxies = NetworkSettings.getInstance().getProxySettingsInRequestsFormat()
try: try:
resp = requests.get(url, headers=headers, proxies=proxies, **kwargs) resp = requests.get(url, headers=headers, proxies=proxies, **kwargs)
resp.raise_for_status() resp.raise_for_status()
return resp return resp
except requests.exceptions.HTTPError as error: except requests.exceptions.HTTPError as error:
pyfalog.warning("HTTPError:") pyfalog.warning('HTTPError:')
pyfalog.warning(error) pyfalog.warning(error)
if error.response.status_code == 404: if error.response.status_code == 404:
raise RequestError() raise RequestError()
@@ -112,3 +94,46 @@ class Network:
raise TimeoutError() raise TimeoutError()
except Exception as error: except Exception as error:
raise Error(error) raise Error(error)
def post(self, url, type, jsonData, **kwargs):
self.__networkAccessCheck(type)
headers = self.__getHeaders()
proxies = self.__getProxies()
try:
resp = requests.post(url, json=jsonData, headers=headers, proxies=proxies, **kwargs)
resp.raise_for_status()
return resp
except requests.exceptions.HTTPError as error:
pyfalog.warning('HTTPError:')
pyfalog.warning(error)
if error.response.status_code == 404:
raise RequestError()
elif error.response.status_code == 403:
raise AuthenticationError()
elif error.response.status_code >= 500:
raise ServerError()
raise Error(error)
except requests.exceptions.Timeout:
raise TimeoutError()
except Exception as error:
raise Error(error)
def __networkAccessCheck(self, type):
# Make sure request is enabled
access = NetworkSettings.getInstance().getAccess()
if not self.ENABLED & access or not type & access:
pyfalog.warning('Access not enabled - please enable in Preferences > Network')
raise Error('Access not enabled - please enable in Preferences > Network')
def __getHeaders(self):
versionString = '{0}'.format(config.version)
return {'User-Agent': 'pyfa {0} (python-requests {1})'.format(versionString, requests.__version__)}
def __getProxies(self):
# python-requests supports setting proxy for request as parameter to get() / post()
# in a form like: proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080' }
# or with HTTP Basic auth support: proxies = {'http': 'http://user:pass@10.10.1.10:3128/'}
# then you do: requests.get('http://example.org', proxies=proxies)
return NetworkSettings.getInstance().getProxySettingsInRequestsFormat()

View File

@@ -136,15 +136,13 @@ class EfsPort:
CalcChangeModuleChargesCommand( CalcChangeModuleChargesCommand(
fit.ID, fit.ID,
projected=False, projected=False,
chargeMap={mod.position: None}, chargeMap={mod.position: None}).Do()
commit=False).Do()
sFit.recalc(fit) sFit.recalc(fit)
stats["unloadedCapacitorNeed"] = mod.getModifiedItemAttr("capacitorNeed") stats["unloadedCapacitorNeed"] = mod.getModifiedItemAttr("capacitorNeed")
CalcChangeModuleChargesCommand( CalcChangeModuleChargesCommand(
fit.ID, fit.ID,
projected=False, projected=False,
chargeMap={mod.position: c.typeID}, chargeMap={mod.position: c.typeID}).Do()
commit=False).Do()
sFit.recalc(fit) sFit.recalc(fit)
elif mod.item.group.name == "Capacitor Booster": elif mod.item.group.name == "Capacitor Booster":
# The capacitorNeed is negative, which provides the boost. # The capacitorNeed is negative, which provides the boost.

View File

@@ -20,6 +20,7 @@
import queue import queue
import threading import threading
import timeit
from itertools import chain from itertools import chain
import math import math
@@ -112,15 +113,18 @@ class Price:
if source == sourcePrimary: if source == sourcePrimary:
continue continue
sources[source] = min(sources.values()) - 1 sources[source] = min(sources.values()) - 1
timeoutWeightMult = fetchTimeout / sum(sources.values())
# Record timeouts as it will affect our final decision # Record timeouts as it will affect our final decision
timedOutSources = {} timedOutSources = {}
for source, timeoutWeight in sources.items(): remainingTime = fetchTimeout
for source in sorted(sources, key=sources.get, reverse=True):
timeBefore = timeit.default_timer()
pyfalog.info('Trying {}'.format(source)) pyfalog.info('Trying {}'.format(source))
timedOutSources[source] = False timedOutSources[source] = False
sourceFetchTimeout = timeoutWeight * timeoutWeightMult # Time we allocate for a source depends on source weight and remaining time
sourceFetchTimeout = remainingTime * sources[source] / sum(sources.values())
try: try:
sourceCls = cls.sources.get(source) sourceCls = cls.sources.get(source)
sourceCls(priceMap, cls.systemsList[sFit.serviceFittingOptions["priceSystem"]], sourceFetchTimeout) sourceCls(priceMap, cls.systemsList[sFit.serviceFittingOptions["priceSystem"]], sourceFetchTimeout)
@@ -132,6 +136,16 @@ class Price:
# Sources remove price map items as they fetch info, if none remain then we're done # Sources remove price map items as they fetch info, if none remain then we're done
if not priceMap: if not priceMap:
break break
timeAfter = timeit.default_timer()
# Remove source so it doesn't affect time weights of sources we're going to use next
del sources[source]
remainingTime -= timeAfter - timeBefore
# No time remaining (should not happen) - mark remaining sources as timeout
if remainingTime <= 0:
for source in sources:
timedOutSources[source] = True
break
# If we get to this point, then we've failed to get price with all our sources # If we get to this point, then we've failed to get price with all our sources
# If all sources failed due to timeouts, set one status # If all sources failed due to timeouts, set one status
@@ -247,4 +261,4 @@ class PriceWorkerThread(threading.Thread):
# Import market sources only to initialize price source modules, they register on their own # Import market sources only to initialize price source modules, they register on their own
from service.marketSources import evemarketer, evemarketdata # noqa: E402 from service.marketSources import evemarketer, evemarketdata, evepraisal # noqa: E402

View File

@@ -47,10 +47,13 @@ class CheckUpdateThread(threading.Thread):
try: try:
try: try:
response = network.request('https://www.pyfa.io/update_check?pyfa_version={}&client_hash={}'.format( response = network.get(
config.version, config.getClientSecret()), network.UPDATE) url='https://www.pyfa.io/update_check?pyfa_version={}&client_hash={}'.format(config.version, config.getClientSecret()),
type=network.UPDATE)
except Exception as e: except Exception as e:
response = network.request('https://api.github.com/repos/pyfa-org/Pyfa/releases', network.UPDATE) response = network.get(
url='https://api.github.com/repos/pyfa-org/Pyfa/releases',
type=network.UPDATE)
jsonResponse = response.json() jsonResponse = response.json()
jsonResponse.sort( jsonResponse.sort(

27
utils/cjk.py Normal file
View File

@@ -0,0 +1,27 @@
def isCharCjk(char):
# https://stackoverflow.com/questions/1366068/whats-the-complete-range-for-chinese-characters-in-unicode
ranges = (
('\u4e00', '\u9fff'),
('\u3400', '\u4dbf'),
('\u20000', '\u2a6df'),
('\u2a700', '\u2b73f'),
('\u2b740', '\u2b81f'),
('\u2b820', '\u2ceaf'),
('\uf900', '\ufaff'),
('\u2f800', '\u2fa1f'),
('\uac00', '\ud7af'))
for low, high in ranges:
if low <= char <= high:
return True
return False
def isStringCjk(string):
checked = set()
for char in string:
if char in checked:
continue
checked.add(char)
if isCharCjk(char):
return True
return False