Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/1463 insurance #1699

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions gui/builtinContextMenus/insuranceOptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import wx
import gui.mainFrame
from gui.contextMenu import ContextMenu
from service.settings import InsuranceMenuSettings


class InsuranceOptions(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.settings = InsuranceMenuSettings.getInstance()
self.optionList = ["Cost", "Payout", "Difference"]

def display(self, srcContext, selection):
return srcContext in ("insuranceViewFull")

def getText(self, itmContext, selection):
return "Column Display (Requires Restart)"

def addOption(self, menu, option):
label = option
id = ContextMenu.nextID()
self.optionIds[id] = option
menuItem = wx.MenuItem(menu, id, label, kind=wx.ITEM_CHECK)
menu.Bind(wx.EVT_MENU, self.handleMode, menuItem)
return menuItem

def getSubMenu(self, context, selection, rootMenu, i, pitem):
msw = True if "wxMSW" in wx.PlatformInfo else False
self.context = context
self.optionIds = {}

sub = wx.Menu()

for option in self.optionList:
menuItem = self.addOption(rootMenu if msw else sub, option)
sub.Append(menuItem)
menuItem.Check(self.settings.get(option.lower()))

return sub

def handleMode(self, event):
option = self.optionIds[event.Id]
self.settings.set(option.lower(), event.Int)


InsuranceOptions.register()
9 changes: 9 additions & 0 deletions gui/builtinPreferenceViews/pyfaStatViewPreferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ def populatePanel(self, panel):
self.rbOutgoing.SetSelection(self.settings.get('outgoing'))
rbSizerRow3.Add(self.rbOutgoing, 1, wx.TOP | wx.RIGHT, 5)
self.rbOutgoing.Bind(wx.EVT_RADIOBOX, self.OnOutgoingChange)

self.rbInsurance = wx.RadioBox(panel, -1, "Insurance", wx.DefaultPosition, wx.DefaultSize, ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS)
self.rbInsurance.EnableItem(1, False)
self.rbInsurance.SetSelection(self.settings.get('insurance'))
rbSizerRow3.Add(self.rbInsurance, 1, wx.TOP | wx.RIGHT, 5)
self.rbInsurance.Bind(wx.EVT_RADIOBOX, self.OnInsuranceChange)
# We don't have views for these.....yet
'''
self.rbMining = wx.RadioBox(panel, -1, "Mining", wx.DefaultPosition, wx.DefaultSize,
Expand Down Expand Up @@ -143,6 +149,9 @@ def OnPriceChange(self, event):
def OnOutgoingChange(self, event):
self.settings.set('outgoing', event.GetInt())

def OnInsuranceChange(self, event):
self.settings.set('insurance', event.GetInt())

def OnMiningYieldChange(self, event):
self.settings.set('miningyield', event.GetInt())

Expand Down
1 change: 1 addition & 0 deletions gui/builtinStatsViews/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
"targetingMiscViewMinimal",
"priceViewFull",
"priceViewMinimal",
"insuranceViewFull",
]
101 changes: 101 additions & 0 deletions gui/builtinStatsViews/insuranceViewFull.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import wx
from gui.statsView import StatsView
from gui.utils.numberFormatter import formatAmount
from service.insurance import Insurance
from service.settings import InsuranceMenuSettings


class InsuranceViewFull(StatsView):
name = "insuranceViewFull"

def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
self.insuranceLevels = None
self.settings = InsuranceMenuSettings.getInstance()
self.displayColumns = self.getDisplayColumns(self.settings)

def getDisplayColumns(self, settings):
return {'cost': self.settings.get("cost"), 'payout': self.settings.get("payout"), 'difference': self.settings.get("difference")}

''' Future use when repopulate can be called during runtime, might need rewrite from changing displayColumns from list to dict
def settingsDiffer(self, settings):
newColumns = self.getDisplayColumns(settings)
if self.displayColumns == newColumns:
return False
self.displayColumns = newColumns
return True
'''

def getHeaderText(self, fit):
return "Insurance"

def newBoxText(self, grid, contentPanel, text):
box = wx.BoxSizer(wx.VERTICAL)
grid.Add(box, 0, wx.ALIGN_TOP)
box.Add(wx.StaticText(contentPanel, wx.ID_ANY, text), 0, wx.ALIGN_CENTER)

def newBoxLabel(self, grid, contentPanel, labeltype, label):
lbl = wx.StaticText(contentPanel, wx.ID_ANY, "0.00 ISK")
setattr(self, "labelInsurance{}{}".format(labeltype, label), lbl)
box = wx.BoxSizer(wx.VERTICAL)
grid.Add(box, 0, wx.ALIGN_TOP)
box.Add(lbl, 0, wx.ALIGN_LEFT)

def populatePanel(self, contentPanel, headerPanel):
contentSizer = contentPanel.GetSizer()
self.panel = contentPanel
self.headerPanel = headerPanel

columnCount = sum(self.displayColumns.values()) + 1

gridInsuranceValues = wx.GridSizer(6, columnCount, 0, 0)
contentSizer.Add(gridInsuranceValues, 0, wx.EXPAND | wx.ALL, 0)

self.newBoxText(gridInsuranceValues, contentPanel, "Level")

if (self.settings.get("cost")):
self.newBoxText(gridInsuranceValues, contentPanel, "Cost")
if (self.settings.get("payout")):
self.newBoxText(gridInsuranceValues, contentPanel, "Payout")
if (self.settings.get("difference")):
self.newBoxText(gridInsuranceValues, contentPanel, "Difference")

for level in ["Basic", "Bronze", "Silver", "Gold", "Platinum"]:
self.newBoxText(gridInsuranceValues, contentPanel, level)
if (self.settings.get("cost")):
self.newBoxLabel(gridInsuranceValues, contentPanel, "Cost", level)
if (self.settings.get("payout")):
self.newBoxLabel(gridInsuranceValues, contentPanel, "Payout", level)
if (self.settings.get("difference")):
self.newBoxLabel(gridInsuranceValues, contentPanel, "Difference", level)

def refreshPanel(self, fit):
if fit is not None:
sInsurance = Insurance.getInstance()
self.insuranceLevels = sInsurance.getInsurance(fit.ship.item.ID)

# Currently populate is only called on init from statsPane.py, so a restart is required for repopulate
# Could also create the 6 different configurations and enable/disable, but it looks like work is being
# done to add runtime repopulation of panels, so I'm going to just require restart for column view change
# to take effect, and then enable this function when the changes for runtime repopulation go live
# if self.settingsDiffer(self.settings):
# self.populatePanel(self.panel, self.headerPanel, True)

self.refreshInsurancePanelPrices()
self.panel.Layout()

def refreshInsurancePanelPrices(self):
if self.insuranceLevels:
for index, label in enumerate(["Basic", "Bronze", "Silver", "Gold", "Platinum"]):
cost = self.insuranceLevels[index].get('cost')
payout = self.insuranceLevels[index].get('payout')
if self.displayColumns["cost"]:
getattr(self, "labelInsuranceCost%s" % label).SetLabel("%s ISK" % formatAmount(cost, 3, 3, 9, currency=True))
if self.displayColumns["payout"]:
getattr(self, "labelInsurancePayout%s" % label).SetLabel("%s ISK" % formatAmount(payout, 3, 3, 9, currency=True))
if self.displayColumns["difference"]:
getattr(self, "labelInsuranceDifference%s" % label).SetLabel("%s ISK" % formatAmount(payout - cost, 3, 3, 9, currency=True))


InsuranceViewFull.register()
1 change: 1 addition & 0 deletions gui/contextMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,5 @@ def getBitmap(self, context, selection):
commandFits,
tabbedFits,
mutaplasmids,
insuranceOptions,
)
1 change: 1 addition & 0 deletions gui/statsPane.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class StatsPane(wx.Panel):
"capacitor",
"targetingMisc",
"price",
"insurance",
]

# Don't have these....yet....
Expand Down
1 change: 1 addition & 0 deletions gui/statsView.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ def refreshPanel(self, fit):
priceViewMinimal,
outgoingViewFull,
outgoingViewMinimal,
insuranceViewFull,
)
5 changes: 5 additions & 0 deletions pyfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ def _process_args(self, largs, rargs, values):
mf = MainFrame(options.title)
ErrorHandler.SetParent(mf)

from service.insurance import Insurance
# Needs to be performed after wx init
sInsurance = Insurance.getInstance()
sInsurance.apiFetch(lambda response: pyfalog.debug(str(response)))

if options.profile_path:
profile_path = os.path.join(options.profile_path, 'pyfa-{}.profile'.format(datetime.datetime.now().strftime('%Y%m%d_%H%M%S')))
pyfalog.debug("Starting pyfa with a profiler, saving to {}".format(profile_path))
Expand Down
4 changes: 4 additions & 0 deletions service/esi.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ def getSsoCharacter(self, id):
eos.db.commit()
return char

def getInsurance(self):
resp = super().getInsurance()
return resp.json()

def getSkills(self, id):
char = self.getSsoCharacter(id)
resp = super().getSkills(char)
Expand Down
7 changes: 6 additions & 1 deletion service/esiAccess.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class ESIEndpoints(Enum):
CHAR_SKILLS = "/v4/characters/{character_id}/skills/"
CHAR_FITTINGS = "/v1/characters/{character_id}/fittings/"
CHAR_DEL_FIT = "/v1/characters/{character_id}/fittings/{fitting_id}/"
INSURANCE = "/v1/insurance/prices/"


class EsiAccess(object):
Expand Down Expand Up @@ -109,6 +110,9 @@ def oauth_authorize(self):
def oauth_token(self):
return '%s/oauth/token' % self.sso_url

def getInsurance(self):
return self.get(None, ESIEndpoints.INSURANCE)

def getSkills(self, char):
return self.get(char, ESIEndpoints.CHAR_SKILLS, character_id=char.characterID)

Expand Down Expand Up @@ -269,7 +273,8 @@ def _after_request(self, resp):
return resp

def get(self, ssoChar, endpoint, *args, **kwargs):
self._before_request(ssoChar)
if ssoChar:
self._before_request(ssoChar)
endpoint = endpoint.format(**kwargs)
return self._after_request(self._session.get("{}{}".format(self.esi_url, endpoint)))

Expand Down
57 changes: 57 additions & 0 deletions service/insurance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import sys
import wx
import threading
from logbook import Logger
from service.esi import Esi

pyfalog = Logger(__name__)


class Insurance():
instance = None

@classmethod
def getInstance(cls):
if cls.instance is None:
cls.instance = Insurance()

return cls.instance

def __init__(self):
self.allInsurance = None

def apiFetch(self, callerCallback):
thread = InsuranceApiThread((self.insuranceApiCallback, callerCallback))
thread.start()

# Modify the Insurance class with data from the threaded api call if there were no errors
def insuranceApiCallback(self, response, callerCallback, e=None):
if e:
wx.CallAfter(callerCallback, e)
else:
self.allInsurance = response
wx.CallAfter(callerCallback, response)

def getInsurance(self, typeID):
if self.allInsurance:
# Search the insurance list for the first item that has the typeID we are looking for
try:
return next(iter([item for item in self.allInsurance if item.get('type_id') == typeID]))['levels']
except StopIteration:
return None


class InsuranceApiThread(threading.Thread):
def __init__(self, callback):
threading.Thread.__init__(self)
self.name = "InsuranceImport"
self.callback = callback

def run(self):
try:
sEsi = Esi.getInstance()
resp = sEsi.getInsurance()
self.callback[0](resp, self.callback[1])
except Exception as ex:
pyfalog.warn(ex)
self.callback[0](None, self.callback[1], sys.exc_info())
31 changes: 31 additions & 0 deletions service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ def __init__(self):
"miningyield" : 2,
"drones" : 2,
"outgoing" : 2,
"insurance" : 2,
}

# We don't have these....yet
Expand All @@ -448,6 +449,36 @@ def set(self, type, value):
self.serviceStatViewDefaultSettings[type] = value


class InsuranceMenuSettings(object):
_instance = None

@classmethod
def getInstance(cls):
if cls._instance is None:
cls._instance = InsuranceMenuSettings()

return cls._instance

def __init__(self):
# mode
# 0 - Do not add to total
# 1 - Add to total
InsuranceMenuDefaultSettings = {
"cost" : 1,
"payout" : 1,
"difference" : 1
}

self.InsuranceMenuDefaultSettings = SettingsProvider.getInstance().getSettings("pyfaInsuranceMenuSettings",
InsuranceMenuDefaultSettings)

def get(self, type):
return self.InsuranceMenuDefaultSettings[type]

def set(self, type, value):
self.InsuranceMenuDefaultSettings[type] = value


class PriceMenuSettings(object):
_instance = None

Expand Down