diff --git a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py
index acdfb398b..6cb611797 100644
--- a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py
+++ b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py
@@ -90,7 +90,9 @@ class PFGeneralPref(PreferenceView):
self.stDefaultSystem.Wrap(-1)
priceSizer.Add(self.stDefaultSystem, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
+ self.chPriceSource = wx.Choice(panel, choices=sorted(Price.sources.keys()))
self.chPriceSystem = wx.Choice(panel, choices=Price.systemsList.keys())
+ priceSizer.Add(self.chPriceSource, 1, wx.ALL | wx.EXPAND, 5)
priceSizer.Add(self.chPriceSystem, 1, wx.ALL | wx.EXPAND, 5)
mainSizer.Add(priceSizer, 0, wx.ALL | wx.EXPAND, 0)
@@ -124,6 +126,7 @@ class PFGeneralPref(PreferenceView):
self.cbGaugeAnimation.SetValue(self.sFit.serviceFittingOptions["enableGaugeAnimation"])
self.cbExportCharges.SetValue(self.sFit.serviceFittingOptions["exportCharges"])
self.cbOpenFitInNew.SetValue(self.sFit.serviceFittingOptions["openFitInNew"])
+ self.chPriceSource.SetStringSelection(self.sFit.serviceFittingOptions["priceSource"])
self.chPriceSystem.SetStringSelection(self.sFit.serviceFittingOptions["priceSystem"])
self.cbShowShipBrowserTooltip.SetValue(self.sFit.serviceFittingOptions["showShipBrowserTooltip"])
self.intDelay.SetValue(self.sFit.serviceFittingOptions["marketSearchDelay"])
@@ -140,6 +143,7 @@ class PFGeneralPref(PreferenceView):
self.cbGaugeAnimation.Bind(wx.EVT_CHECKBOX, self.onCBGaugeAnimation)
self.cbExportCharges.Bind(wx.EVT_CHECKBOX, self.onCBExportCharges)
self.cbOpenFitInNew.Bind(wx.EVT_CHECKBOX, self.onCBOpenFitInNew)
+ self.chPriceSource.Bind(wx.EVT_CHOICE, self.onPricesSourceSelection)
self.chPriceSystem.Bind(wx.EVT_CHOICE, self.onPriceSelection)
self.cbShowShipBrowserTooltip.Bind(wx.EVT_CHECKBOX, self.onCBShowShipBrowserTooltip)
self.intDelay.Bind(wx.lib.intctrl.EVT_INT, self.onMarketDelayChange)
@@ -224,5 +228,9 @@ class PFGeneralPref(PreferenceView):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
event.Skip()
+ def onPricesSourceSelection(self, event):
+ source = self.chPriceSource.GetString(self.chPriceSource.GetSelection())
+ self.sFit.serviceFittingOptions["priceSource"] = source
+
PFGeneralPref.register()
diff --git a/service/fit.py b/service/fit.py
index 94cb67d0a..85c6ccffd 100644
--- a/service/fit.py
+++ b/service/fit.py
@@ -74,6 +74,7 @@ class Fit(object):
"exportCharges": True,
"openFitInNew": False,
"priceSystem": "Jita",
+ "priceSource": "eve-central.com",
"showShipBrowserTooltip": True,
"marketSearchDelay": 250
}
diff --git a/service/marketSources/__init__.py b/service/marketSources/__init__.py
new file mode 100644
index 000000000..b093a0010
--- /dev/null
+++ b/service/marketSources/__init__.py
@@ -0,0 +1 @@
+__all__ = ['evecentral', 'evemarketdata']
\ No newline at end of file
diff --git a/service/marketSources/evecentral.py b/service/marketSources/evecentral.py
new file mode 100644
index 000000000..3a17ac957
--- /dev/null
+++ b/service/marketSources/evecentral.py
@@ -0,0 +1,87 @@
+# =============================================================================
+# 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 .
+# =============================================================================
+
+import time
+from logbook import Logger
+from xml.dom import minidom
+
+from service.network import Network
+from service.price import Price, VALIDITY, TIMEOUT, TimeoutError
+
+
+pyfalog = Logger(__name__)
+
+
+class EveCentral(object):
+
+ name = "eve-central.com"
+
+ def __init__(self, types, system, priceMap):
+ data = []
+ baseurl = "https://eve-central.com/api/marketstat"
+ data.append(("usesystem", system)) # Use Jita for market
+
+ for typeID in types: # Add all typeID arguments
+ data.append(("typeid", typeID))
+
+ # Attempt to send request and process it
+ try:
+ network = Network.getInstance()
+ data = network.request(baseurl, network.PRICES, data)
+ xml = minidom.parse(data)
+ types = xml.getElementsByTagName("marketstat").item(0).getElementsByTagName("type")
+ # Cycle through all types we've got from request
+ for type_ in types:
+ # Get data out of each typeID details tree
+ typeID = int(type_.getAttribute("id"))
+ sell = type_.getElementsByTagName("sell").item(0)
+ # If price data wasn't there, set price to zero
+ try:
+ percprice = float(sell.getElementsByTagName("percentile").item(0).firstChild.data)
+ except (TypeError, ValueError):
+ pyfalog.warning("Failed to get price for: {0}", type_)
+ percprice = 0
+
+ # Fill price data
+ priceobj = priceMap[typeID]
+ priceobj.price = percprice
+ priceobj.time = time.time() + VALIDITY
+ priceobj.failed = None
+
+ # delete price from working dict
+ del priceMap[typeID]
+
+ # If getting or processing data returned any errors
+ except TimeoutError:
+ # Timeout error deserves special treatment
+ pyfalog.warning("Price fetch timout")
+ for typeID in priceMap.keys():
+ priceobj = priceMap[typeID]
+ priceobj.time = time.time() + TIMEOUT
+ priceobj.failed = True
+
+ del priceMap[typeID]
+ except:
+ # all other errors will pass and continue onward to the REREQUEST delay
+ pyfalog.warning("Caught exception in fetchPrices")
+ pass
+ pass
+
+
+Price.register(EveCentral)
diff --git a/service/marketSources/evemarketdata.py b/service/marketSources/evemarketdata.py
new file mode 100644
index 000000000..4ca7a3633
--- /dev/null
+++ b/service/marketSources/evemarketdata.py
@@ -0,0 +1,85 @@
+# =============================================================================
+# 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 .
+# =============================================================================
+
+import time
+from logbook import Logger
+from xml.dom import minidom
+
+from service.network import Network
+from service.price import Price, VALIDITY, TIMEOUT, TimeoutError
+
+
+pyfalog = Logger(__name__)
+
+
+class EveMarketData(object):
+
+ name = "eve-marketdata.com"
+
+ def __init__(self, types, system, priceMap):
+ data = []
+ baseurl = "https://eve-marketdata.com/api/item_prices.xml"
+ data.append(("system_id", system)) # Use Jita for market
+ data.append(("type_ids", ','.join(str(x) for x in types)))
+
+ # Attempt to send request and process it
+ try:
+ network = Network.getInstance()
+ data = network.request(baseurl, network.PRICES, data)
+ xml = minidom.parse(data)
+ print (xml.getElementsByTagName("eve").item(0))
+ types = xml.getElementsByTagName("eve").item(0).getElementsByTagName("price")
+ # Cycle through all types we've got from request
+ for type_ in types:
+ # Get data out of each typeID details tree
+ typeID = int(type_.getAttribute("id"))
+ price = 0
+
+ try:
+ price = float(type_.firstChild.data)
+ except (TypeError, ValueError):
+ pyfalog.warning("Failed to get price for: {0}", type_)
+
+ # Fill price data
+ priceobj = priceMap[typeID]
+ priceobj.price = price
+ priceobj.time = time.time() + VALIDITY
+ priceobj.failed = None
+
+ # delete price from working dict
+ del priceMap[typeID]
+
+ # If getting or processing data returned any errors
+ except TimeoutError:
+ # Timeout error deserves special treatment
+ pyfalog.warning("Price fetch timout")
+ for typeID in priceMap.keys():
+ priceobj = priceMap[typeID]
+ priceobj.time = time.time() + TIMEOUT
+ priceobj.failed = True
+
+ del priceMap[typeID]
+ except:
+ # all other errors will pass and continue onward to the REREQUEST delay
+ pyfalog.warning("Caught exception in fetchPrices")
+ pass
+ pass
+
+
+Price.register(EveMarketData)
\ No newline at end of file
diff --git a/service/price.py b/service/price.py
index c6e089f79..b37d6a0d4 100644
--- a/service/price.py
+++ b/service/price.py
@@ -39,7 +39,6 @@ REREQUEST = 4 * 60 * 60 # Re-request delay for failed fetches, 4 hours
TIMEOUT = 15 * 60 # Network timeout delay for connection issues, 15 minutes
-
class Price(object):
instance = None
@@ -51,12 +50,18 @@ class Price(object):
"Hek": 30002053
}
+ sources = {}
+
def __init__(self):
# Start price fetcher
self.priceWorkerThread = PriceWorkerThread()
self.priceWorkerThread.daemon = True
self.priceWorkerThread.start()
+ @classmethod
+ def register(cls, source):
+ cls.sources[source.name] = source
+
@classmethod
def getInstance(cls):
if cls.instance is None:
@@ -95,8 +100,13 @@ class Price(object):
sFit = Fit.getInstance()
- func = cls.evemarketdata
- func(toRequest, cls.systemsList[sFit.serviceFittingOptions["priceSystem"]], priceMap)
+ if len(cls.sources.keys()) == 0:
+ pyfalog.warn('No price source can be found')
+ return
+
+ # attempt to find user's selected price source, otherwise get first one
+ sourceCls = cls.sources.get(sFit.serviceFittingOptions["priceSource"], cls.sources[cls.sources.keys()[0]])
+ sourceCls(toRequest, cls.systemsList[sFit.serviceFittingOptions["priceSystem"]], priceMap)
# if we get to this point, then we've got an error. Set to REREQUEST delay
for typeID in priceMap.keys():
@@ -163,109 +173,6 @@ class Price(object):
pyfalog.debug("Clearing Prices")
db.clearPrices()
- # todo: create classes for these, inherit a base class that allows a simple api of setPrice() and stuff?
- @classmethod
- def evecentral(self, types, system, priceMap):
- data = []
- baseurl = "https://eve-central.com/api/marketstat"
- data.append(("usesystem", system)) # Use Jita for market
-
- for typeID in types: # Add all typeID arguments
- data.append(("typeid", typeID))
-
- # Attempt to send request and process it
- try:
- network = Network.getInstance()
- data = network.request(baseurl, network.PRICES, data)
- xml = minidom.parse(data)
- types = xml.getElementsByTagName("marketstat").item(0).getElementsByTagName("type")
- # Cycle through all types we've got from request
- for type_ in types:
- # Get data out of each typeID details tree
- typeID = int(type_.getAttribute("id"))
- sell = type_.getElementsByTagName("sell").item(0)
- # If price data wasn't there, set price to zero
- try:
- percprice = float(sell.getElementsByTagName("percentile").item(0).firstChild.data)
- except (TypeError, ValueError):
- pyfalog.warning("Failed to get price for: {0}", type_)
- percprice = 0
-
- # Fill price data
- priceobj = priceMap[typeID]
- priceobj.price = percprice
- priceobj.time = time.time() + VALIDITY
- priceobj.failed = None
-
- # delete price from working dict
- del priceMap[typeID]
-
- # If getting or processing data returned any errors
- except TimeoutError:
- # Timeout error deserves special treatment
- pyfalog.warning("Price fetch timout")
- for typeID in priceMap.keys():
- priceobj = priceMap[typeID]
- priceobj.time = time.time() + TIMEOUT
- priceobj.failed = True
-
- del priceMap[typeID]
- except:
- # all other errors will pass and continue onward to the REREQUEST delay
- pyfalog.warning("Caught exception in fetchPrices")
- pass
- pass
-
- @classmethod
- def evemarketdata(self, types, system, priceMap):
- data = []
- baseurl = "https://eve-marketdata.com/api/item_prices.xml"
- data.append(("system_id", system)) # Use Jita for market
- data.append(("type_ids", ','.join(str(x) for x in types)))
-
- # Attempt to send request and process it
- try:
- network = Network.getInstance()
- data = network.request(baseurl, network.PRICES, data)
- xml = minidom.parse(data)
- print (xml.getElementsByTagName("eve").item(0))
- types = xml.getElementsByTagName("eve").item(0).getElementsByTagName("price")
- # Cycle through all types we've got from request
- for type_ in types:
- # Get data out of each typeID details tree
- typeID = int(type_.getAttribute("id"))
- price = 0
-
- try:
- price = float(type_.firstChild.data)
- except (TypeError, ValueError):
- pyfalog.warning("Failed to get price for: {0}", type_)
-
- # Fill price data
- priceobj = priceMap[typeID]
- priceobj.price = price
- priceobj.time = time.time() + VALIDITY
- priceobj.failed = None
-
- # delete price from working dict
- del priceMap[typeID]
-
- # If getting or processing data returned any errors
- except TimeoutError:
- # Timeout error deserves special treatment
- pyfalog.warning("Price fetch timout")
- for typeID in priceMap.keys():
- priceobj = priceMap[typeID]
- priceobj.time = time.time() + TIMEOUT
- priceobj.failed = True
-
- del priceMap[typeID]
- except:
- # all other errors will pass and continue onward to the REREQUEST delay
- pyfalog.warning("Caught exception in fetchPrices")
- pass
- pass
-
class PriceWorkerThread(threading.Thread):
def __init__(self):
@@ -302,3 +209,5 @@ class PriceWorkerThread(threading.Thread):
if itemID not in self.wait:
self.wait[itemID] = []
self.wait[itemID].append(callback)
+
+from service.marketSources import * # noqa: E402,F401