From 47bccc0684921efa5ae7f0453847192676119a59 Mon Sep 17 00:00:00 2001 From: Jonathan Harris Date: Wed, 22 Jul 2015 04:12:27 +0100 Subject: [PATCH] Add support for charting Cmdr statistics. --- EDMarketConnector.py | 25 ++++- EDMarketConnector.wxs | 8 ++ README.md | 9 +- trends.py => chart.py | 215 ++++++++++++++++++++---------------------- config.py | 1 + img/Balance.png | Bin 0 -> 49431 bytes prefs.py | 20 ++-- 7 files changed, 152 insertions(+), 126 deletions(-) rename trends.py => chart.py (51%) mode change 100755 => 100644 create mode 100644 img/Balance.png diff --git a/EDMarketConnector.py b/EDMarketConnector.py index d050773f..b335e3ae 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -23,6 +23,7 @@ import eddn import loadout import flightlog import stats +import chart import prefs from config import appname, applongname, config @@ -202,10 +203,20 @@ class AppWindow: self.status['text'] = "Where are you?!" # Shouldn't happen elif not data.get('ship') or not data['ship'].get('modules') or not data['ship'].get('name','').strip(): self.status['text'] = "What are you flying?!" # Shouldn't happen + elif (config.getint('output') & config.OUT_EDDN) and data['commander'].get('docked') and not data['lastStarport'].get('ships') and not retrying: - # API is flakey about shipyard info - retry if missing (<1s is usually sufficient - 4s for margin). + # API is flakey about shipyard info - retry if missing (<1s is usually sufficient - 5s for margin). self.w.after(shipyard_retry * 1000, lambda:self.getandsend(retrying=True)) + + # Stuff we can do while waiting for retry + if config.getint('output') & config.OUT_STAT: + chart.export(data) + if config.getint('output') & config.OUT_LOG: + flightlog.export(data) + if config.getint('output') & config.OUT_SHIP: + loadout.export(data) return + else: if __debug__ and retrying: print data['lastStarport'].get('ships') and 'Retry for shipyard - Success' or 'Retry for shipyard - Fail' @@ -213,10 +224,14 @@ class AppWindow: if __debug__: # Recording with open('%s%s.%s.json' % (data['lastSystem']['name'], data['commander'].get('docked') and '.'+data['lastStarport']['name'] or '', strftime('%Y-%m-%dT%H.%M.%S', localtime())), 'wt') as h: h.write(json.dumps(data, indent=2, sort_keys=True)) - if config.getint('output') & config.OUT_LOG: - flightlog.export(data) - if config.getint('output') & config.OUT_SHIP: - loadout.export(data) + + if not retrying: + if config.getint('output') & config.OUT_STAT: + chart.export(data) + if config.getint('output') & config.OUT_LOG: + flightlog.export(data) + if config.getint('output') & config.OUT_SHIP: + loadout.export(data) if not (config.getint('output') & (config.OUT_CSV|config.OUT_TD|config.OUT_BPC|config.OUT_EDDN)): # no further output requested diff --git a/EDMarketConnector.wxs b/EDMarketConnector.wxs index c23ad5c6..4461bbdc 100644 --- a/EDMarketConnector.wxs +++ b/EDMarketConnector.wxs @@ -51,6 +51,9 @@ + + + @@ -78,6 +81,9 @@ + + + @@ -318,6 +324,7 @@ + @@ -327,6 +334,7 @@ + diff --git a/README.md b/README.md index e81175d1..3aa1e21a 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,14 @@ This app downloads commodity market and other data from the game [Elite: Dangero * sends the data to the [Elite Dangerous Data Network](http://eddn-gateway.elite-markets.net/) ("EDDN") from where you and others can use it via online trading tools such as [eddb](http://eddb.io/), [Elite Trade Net](http://etn.io/), [Inara](http://inara.cz), etc. * saves the data to files on your computer that you can load into trading tools such as [Slopey's BPC Market Tool](https://forums.frontier.co.uk/showthread.php?t=76081), [Trade Dangerous](https://bitbucket.org/kfsone/tradedangerous/wiki/Home), [Thrudd's Trading Tools](http://www.elitetradingtool.co.uk/), [Inara](http://inara.cz), etc. -* saves a record of your ship loadout and/or flight log. +* saves a record of your ship loadout, flight log and/or statistics. The user-interface is deliberately minimal - when you land at a station just switch to the app and press the "Update" button or press Enter to automatically download and transmit and/or save your choice of data. ![Windows screenshot](img/win.png) ![Mac screenshot](img/mac.png) +![Balance screenshot](img/Balance.png) + Installation -------- @@ -60,6 +62,9 @@ This app can save a variety of data in a variety of formats: * Flight log * Adds a record of your location, ship and cargo to a file that you can open in a text editor or a spreadsheet program such as Excel. Note: Don't edit, rename or move this file - take a copy if you wish to change it. +* Cmdr statstics + * Generates a number of charts of your progress in an Excel file. Note: Don't edit, rename or move this file. + By default these files will be placed in your Documents folder. Since this app will create a lot of files if you use it for a while you may wish to create a separate folder for the files and tell the app to place them there. Statistics @@ -100,6 +105,8 @@ Linux: * Requires the Python "imaging-tk", "iniparse" and "requests" modules. On Debian-based systems install these with `sudo apt-get install python-imaging-tk python-iniparse python-requests` . * Run with `./EDMarketConnector.py` . +On all platforms charting Cmdr statistics additionally requires verison 2.3.0 or later of the [openpyxl](https://pypi.python.org/pypi/openpyxl) module. + Packaging for distribution -------- diff --git a/trends.py b/chart.py old mode 100755 new mode 100644 similarity index 51% rename from trends.py rename to chart.py index 202671a6..128d8cbb --- a/trends.py +++ b/chart.py @@ -1,92 +1,45 @@ #!/usr/bin/python # -# Creates an Excel spreadsheet graphing player stats using data from .json dumps created by -# EDMarketconnector in interactive mode. +# Creates an Excel spreadsheet graphing player stats # -# Requires XlsxWriter +# Requires openpyxl >= 2.3 # -import json -import os -import re +try: + import lxml._elementpath # Explicit dependency for py2exe + import openpyxl + if map(int, openpyxl.__version__.split('.')[:2]) < [2,3]: + raise ImportError() + have_openpyxl = True +except: + have_openpyxl = False + import datetime -import xlsxwriter +import time +import re - -workbook = xlsxwriter.Workbook('trends.xlsx') - -F_TITLE = workbook.add_format({'align': 'center', 'bold':True}) -F_SUB = workbook.add_format({'align': 'right', 'bold':True}) -F_DATE = workbook.add_format({'num_format': 'yy-mm-dd hh:mm:ss'}) - -def makesheet(workbook, name, titles): - worksheet = workbook.add_worksheet(name) - worksheet.write(0, 0, 'Date', F_SUB) - if isinstance(titles[0], tuple): - start = end = 1 - for (head, subtitles) in titles: - for i in range(len(subtitles)): - worksheet.write(1, end, subtitles[i], F_SUB) - end += 1 - worksheet.merge_range(0, start, 0, end-1, head, F_TITLE) - start = end - worksheet.set_column(0, end, 15) - else: - worksheet.set_column(0, len(titles), 15) - for i in range(len(titles)): - worksheet.write(0, i+1, titles[i], F_SUB) - return worksheet - -def addrow(worksheet, row, dt, items): - worksheet.write_datetime(row, 0, dt, F_DATE) - for i in range(len(items)): - worksheet.write(row, i+1, items[i]) - -def makechart(workbook, worksheet, title, axes=None): - chart = workbook.add_chart({'type': 'scatter', 'subtype': 'straight'}) - chart.set_title({'name': title}) - chart.set_size({'width': 2400, 'height': 1600}) - chart.set_x_axis({'date_axis': True, 'num_format': 'yyyy-mm-dd'}) - if axes: - if isinstance(axes, list) or isinstance(axes, tuple): - chart.set_y_axis( {'name': axes[0]}) - chart.set_y2_axis({'name': axes[1]}) - else: - chart.set_y_axis( {'name': axes}) - worksheet.insert_chart('B2', chart) - return chart - - - -inputs = {} -regexp = re.compile('.+\.(\d\d\d\d\-\d\d\-\d\dT\d\d\.\d\d\.\d\d)\.json$') -for f in os.listdir('.'): - match = regexp.match(f) - if match: - inputs[datetime.datetime.strptime(match.group(1), '%Y-%m-%dT%H.%M.%S')] = json.loads(open(f).read()) -if not inputs: - print "No data!" - exit() +from os.path import isfile, join +from config import config dataseries = [ { 'name': 'Combat', - 'axes': ['qty', 'CR'], + 'axes': ['Quantity', 'Profit [CR]'], 'keys': [ ('Bounties', ['stats', 'combat', 'bounty', 'qty']), ('Profit from bounties', ['stats', 'combat', 'bounty', 'value'], True), ('Bonds', ['stats', 'combat', 'bond', 'qty']), ('Profit from bonds', ['stats', 'combat', 'bond', 'value'], True), - ('Assassin', ['stats', 'missions', 'assassin', 'missionsCompleted']), + ('Assassinations', ['stats', 'missions', 'assassin', 'missionsCompleted']), ('Profit from assassin', ['stats', 'missions', 'assassin', 'creditsEarned'], True), ('Hunting', ['stats', 'missions', 'bountyHunter', 'missionsCompleted']), ('Profit from hunting', ['stats', 'missions', 'bountyHunter', 'creditsEarned'], True), - ], + ], }, { 'name': 'Trade', - 'axes': ['qty', 'CR'], + 'axes': ['Quantity', 'Profit [CR]'], 'keys': [ ('Profit from trading', ['stats', 'trade', 'profit'], True), ('Commodities traded', ['stats', 'trade', 'qty']), @@ -98,8 +51,8 @@ dataseries = [ ], }, { - 'name': 'Explore', - 'axes': ['qty', 'CR'], + 'name': 'Explorer', + 'axes': ['Quantity', 'Profit [CR]'], 'keys': [ ('Profits from exploration', ['stats', 'explore', 'creditsEarned'], True), ('Discovery scans', ['stats', 'explore', 'scanSoldLevels', 'lev_0']), @@ -111,7 +64,7 @@ dataseries = [ }, { 'name': 'Crime', - 'axes': ['qty', 'CR'], + 'axes': ['Quantity', 'Profit [CR]'], 'keys': [ ('Fines', ['stats', 'crime', 'fine', 'qty']), ('Lifetime fine value', ['stats', 'crime', 'fine', 'value'], True), @@ -125,17 +78,19 @@ dataseries = [ }, { 'name': 'NPC', + 'axes': 'Quantity', 'prefix': ['stats', 'NPC', 'kills', 'ranks'], 'keys': [('Harmless', 'r0'), ('Mostly Harmless', 'r1'), ('Novice', 'r2'), ('Competent', 'r3'), ('Expert', 'r4'), ('Master', 'r5'), ('Dangerous', 'r6'), ('Deadly', 'r7'), ('Elite', 'r8'), ('Capital', 'rArray')], }, { 'name': 'PVP', + 'axes': 'Quantity', 'prefix': ['stats', 'PVP', 'kills', 'ranks'], 'keys': [('Harmless', 'r0'), ('Mostly Harmless', 'r1'), ('Novice', 'r2'), ('Competent', 'r3'), ('Expert', 'r4'), ('Master', 'r5'), ('Dangerous', 'r6'), ('Deadly', 'r7'), ('Elite', 'r8'), ('Capital', 'rArray')], }, { 'name': 'Balance', - 'axes': ['qty', 'CR'], + 'axes': ['Quantity', '[CR]'], 'keys': [ ('Current balance', ['commander', 'credits'], True), ('Spent on ships', ['stats', 'ship', 'spend', 'ships'], True), @@ -153,63 +108,99 @@ dataseries = [ ] -for thing in dataseries: - if isinstance(thing['keys'][0], tuple): +def export(data, csv=False): + + if not have_openpyxl: return False + + TITLE_F = openpyxl.styles.Font(bold=True) + TITLE_A = openpyxl.styles.Alignment(horizontal='right') + + querytime = config.getint('querytime') or int(time.time()) + + filename = join(config.get('outdir'), 'Cmdr %s.xlsx' % re.sub(r'[\\/:*?"<>|]', '_', data['commander']['name'])) + if not isfile(filename): + wb = openpyxl.Workbook() + try: + wb.active.title = 'Combat' # Workbook is created with one sheet - rename it + except: + pass # except that it isn't under 2.30b1 + else: + wb = openpyxl.load_workbook(filename) + + for thing in dataseries: legends = [x[0] for x in thing['keys']] keys = [x[1] for x in thing['keys']] - if thing.get('axes') and (isinstance(thing['axes'], list) or isinstance(thing['axes'], tuple)): + if thing.get('axes') and isinstance(thing['axes'], (list, tuple)): y2_axis = [len(x)>2 and x[2] for x in thing['keys']] else: - y2_axis = [False] * len(keys) - else: - legends = keys = thing['keys'] - y2_axis = [False] * len(keys) + y2_axis = None - sheet = makesheet(workbook, thing['name'], legends) + if thing['name'] in wb: + ws = wb[thing['name']] + else: + ws = wb.create_sheet(title=thing['name']) - timeseries = sorted(inputs) - for i in range(len(inputs)): - row = i+1 - dt = timeseries[i] - data = inputs[dt] + # Add header row + if ws.max_row <= 1: # Returns 1 for empty sheet + ws.append(['Date'] + legends) + for i in range(ws.max_column): + ws.column_dimensions[openpyxl.utils.get_column_letter(i+1)].width = 17 + for row in ws.get_squared_range(1, 1, ws.max_column, 1): + for cell in row: + cell.font = TITLE_F + cell.alignment = TITLE_A + + # Add data row + vals = [datetime.datetime.fromtimestamp(querytime)] + mydata = data if thing.get('prefix'): for key in thing['prefix']: - data = data[key] - vals = [] + mydata = mydata[key] for key2 in keys: if isinstance(key2, basestring): - vals.append(data.get(key2, 0)) + vals.append(mydata.get(key2, 0)) else: - value = data + value = mydata for key in key2: value = value.get(key, 0) if not value: break vals.append(value) + ws.append(vals) + ws.cell(row=ws.max_row, column=1).number_format = 'yyyy-mm-dd hh:mm:ss' # just a string, not a style - addrow(sheet, row, dt, vals) + dates = openpyxl.chart.Reference(ws, 1, 2, 1, ws.max_row) - chart = makechart(workbook, sheet, thing['name'], thing.get('axes')) - for i in range(len(thing['keys'])): - chart.add_series({'categories': [thing['name'], 1, 0, row, 0], - 'values': [thing['name'], 1, 1+i, row, 1+i], - 'name': legends[i], - 'marker': {'type': 'diamond'}, - 'y2_axis': y2_axis[i], - }) - # Label each line - if y2_axis[i]: - chart.add_series({'categories': [thing['name'], row, 0, row, 0], # last row - 'values': [thing['name'], row, 1+i, row, 1+i], - 'name': legends[i], - 'data_labels': {'series_name': True, 'position': 'right'}, - 'y2_axis': True, - }) - else: - chart.add_series({'categories': [thing['name'], 1, 0, 1, 0], # first row - 'values': [thing['name'], 1, 1+i, 1, 1+i], - 'name': legends[i], - 'data_labels': {'series_name': True, 'position': 'left'}, - }) - chart.set_legend({'delete_series': range(1, 2*len(thing['keys']), 2)}) + chart = openpyxl.chart.ScatterChart() + chart.title = thing['name'] + chart.width, chart.height = 60, 30 # in cm! + chart.scatterStyle = 'lineMarker' + chart.set_categories(dates) + chart.x_axis.number_format = ('yyyy-mm-dd') # date only + chart.x_axis.majorGridlines = None -workbook.close() + if y2_axis: + chart.y_axis.majorGridlines = None # prefer grid lines on secondary axis + chart2 = openpyxl.chart.ScatterChart() + chart2.scatterStyle = 'lineMarker' + # Hack - second chart must have different axis ID + chart2.y_axis = openpyxl.chart.axis.NumericAxis(axId=30, crossAx=10, axPos='r', crosses='max') + + for i in range(len(keys)): + series = openpyxl.chart.Series(openpyxl.chart.Reference(ws, i+2, 1, i+2, ws.max_row), dates, title_from_data=True) + series.marker.symbol = 'diamond' + if y2_axis and y2_axis[i]: + series.dLbls = openpyxl.chart.label.DataLabels([openpyxl.chart.label.DataLabel(idx=ws.max_row-2, dLblPos='r', showSerName=True)]) + chart2.series.append(series) + else: + series.dLbls = openpyxl.chart.label.DataLabels([openpyxl.chart.label.DataLabel(idx=0, dLblPos='l', showSerName=True)]) + chart.series.append(series) + if y2_axis: + chart.y_axis.title = thing['axes'][0] + chart2.y_axis.title = thing['axes'][1] + chart.z_axis = chart2.y_axis + chart += chart2 + elif thing['axes']: + chart.y_axis.title = thing['axes'] + ws.add_chart(chart, 'B2') + + wb.save(filename) diff --git a/config.py b/config.py index 6f31727e..d759164e 100644 --- a/config.py +++ b/config.py @@ -71,6 +71,7 @@ class Config: OUT_CSV = 8 OUT_SHIP = 16 OUT_LOG = 32 + OUT_STAT = 64 if platform=='darwin': diff --git a/img/Balance.png b/img/Balance.png new file mode 100644 index 0000000000000000000000000000000000000000..8696f44c022f365f4ec98450edf5aae65620b5e9 GIT binary patch literal 49431 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 z zgO!~fI|~cCtUw!b*9`gHb(=XT!{B0bJv<3nQ;Tf8tgTlqE98~$sz;*1KMF7dMvPJz zqzMnhl|ycCfrbKFF7RJtJ{ML5WT?+m0XT?pM4cw&!SgD|+hLSE%#>jQroTzj+-I+Y zROJ|)1bm>W@|gC=rH15nVyPo0T47rZSrF9GAwU-dEFnH6w;@R9F1MR{E%n|y-<7_I zsd8G}*+LR)fwm4#Mi?rXnwr|{vGNFLN5h0bDw0mLu`gTkv9bf^J5Cp+1wnBILaw$9 zurb8mJOS)8KnP2L6ag?q4{%cc?&(>Ci5)9h$QJxuL9i^;0}CV5k_O;&;dG+Wm^lL= zk^WWJI(3V_`q=~>P+&Uflo(&Fab3r}rkIE$kdW{6tMK*x`O^fgs#aiu9&JbYbwV2+ zx{Ls^gC4p9X#V=L1eF;01;O3UeV%cxyWN z8ah8cjB&p>JA@Q14EGYoKj1f!1F12@tHIG0I2|L^E?ltEW`kMe<;4jKQn6UR+vB^B|POF13>~9E#)1G**5lc)7hpF z3ZpwM~)yC{COy^{-Ef- H;oJWOtQE|Z literal 0 HcmV?d00001 diff --git a/prefs.py b/prefs.py index 4551db29..467b8073 100644 --- a/prefs.py +++ b/prefs.py @@ -9,6 +9,7 @@ import ttk import tkFileDialog from config import config +from chart import have_openpyxl if platform=='win32': @@ -77,10 +78,10 @@ class PreferencesDialog(tk.Toplevel): outframe.grid(padx=10, pady=10, sticky=tk.NSEW) outframe.columnconfigure(0, weight=1) - output = config.getint('output') or (config.OUT_EDDN | config.OUT_SHIP) + output = config.getint('output') or (config.OUT_EDDN | config.OUT_SHIP | config.OUT_STAT) ttk.Label(outframe, text="Please choose what data to save").grid(row=0, columnspan=2, padx=5, pady=3, sticky=tk.W) self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1 or 0) - ttk.Checkbutton(outframe, text="Send market data to the Elite Dangerous Data Network", variable=self.out_eddn).grid(row=1, columnspan=2, padx=5, sticky=tk.W) + ttk.Checkbutton(outframe, text="Send station data to the Elite Dangerous Data Network", variable=self.out_eddn).grid(row=1, columnspan=2, padx=5, sticky=tk.W) self.out_bpc = tk.IntVar(value = (output & config.OUT_BPC ) and 1 or 0) ttk.Checkbutton(outframe, text="Market data in Slopey's BPC format", variable=self.out_bpc, command=self.outvarchanged).grid(row=2, columnspan=2, padx=5, sticky=tk.W) self.out_td = tk.IntVar(value = (output & config.OUT_TD ) and 1 or 0) @@ -89,14 +90,17 @@ class PreferencesDialog(tk.Toplevel): ttk.Checkbutton(outframe, text="Market data in CSV format", variable=self.out_csv, command=self.outvarchanged).grid(row=4, columnspan=2, padx=5, sticky=tk.W) self.out_ship= tk.IntVar(value = (output & config.OUT_SHIP) and 1 or 0) ttk.Checkbutton(outframe, text="Ship loadout in E:D Shipyard format", variable=self.out_ship, command=self.outvarchanged).grid(row=5, columnspan=2, padx=5, sticky=tk.W) - self.out_log = tk.IntVar(value = (output & config.OUT_LOG) and 1 or 0) + self.out_log = tk.IntVar(value = (output & config.OUT_LOG ) and 1 or 0) ttk.Checkbutton(outframe, text="Flight log", variable=self.out_log, command=self.outvarchanged).grid(row=6, columnspan=2, padx=5, sticky=tk.W) - ttk.Label(outframe, text=(platform=='darwin' and 'Where:' or 'File location:')).grid(row=7, padx=5, pady=(5,0), sticky=tk.NSEW) + self.out_stat= tk.IntVar(value = have_openpyxl and (output & config.OUT_STAT) and 1 or 0) + ttk.Checkbutton(outframe, text="Cmdr statistics", variable=self.out_stat, command=self.outvarchanged, state=have_openpyxl and tk.NORMAL or tk.DISABLED).grid(row=7, columnspan=2, padx=5, sticky=tk.W) + + ttk.Label(outframe, text=(platform=='darwin' and 'Where:' or 'File location:')).grid(row=8, padx=5, pady=(5,0), sticky=tk.NSEW) self.outbutton = ttk.Button(outframe, text=(platform=='darwin' and 'Change...' or 'Browse...'), command=self.outbrowse) - self.outbutton.grid(row=7, column=1, padx=5, pady=(5,0), sticky=tk.NSEW) + self.outbutton.grid(row=8, column=1, padx=5, pady=(5,0), sticky=tk.NSEW) self.outdir = ttk.Entry(outframe) self.outdir.insert(0, config.get('outdir')) - self.outdir.grid(row=8, columnspan=2, padx=5, pady=5, sticky=tk.EW) + self.outdir.grid(row=9, columnspan=2, padx=5, pady=5, sticky=tk.EW) self.outvarchanged() privacyframe = ttk.LabelFrame(frame, text='Privacy') @@ -123,7 +127,7 @@ class PreferencesDialog(tk.Toplevel): #self.wait_window(self) # causes duplicate events on OSX def outvarchanged(self): - local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship.get() or self.out_log.get() + local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship.get() or self.out_log.get() or self.out_stat.get() self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED self.outdir['state'] = local and 'readonly' or tk.DISABLED @@ -162,7 +166,7 @@ class PreferencesDialog(tk.Toplevel): credentials = (config.get('username'), config.get('password')) config.set('username', self.username.get().strip()) config.set('password', self.password.get().strip()) - config.set('output', (self.out_eddn.get() and config.OUT_EDDN or 0) + (self.out_bpc.get() and config.OUT_BPC or 0) + (self.out_td.get() and config.OUT_TD or 0) + (self.out_csv.get() and config.OUT_CSV or 0) + (self.out_ship.get() and config.OUT_SHIP or 0) + (self.out_log.get() and config.OUT_LOG or 0)) + config.set('output', (self.out_eddn.get() and config.OUT_EDDN or 0) + (self.out_bpc.get() and config.OUT_BPC or 0) + (self.out_td.get() and config.OUT_TD or 0) + (self.out_csv.get() and config.OUT_CSV or 0) + (self.out_ship.get() and config.OUT_SHIP or 0) + (self.out_log.get() and config.OUT_LOG or 0) + (self.out_stat.get() and config.OUT_STAT or 0)) config.set('outdir', self.outdir.get().strip()) config.set('anonymous', self.out_anon.get()) self.destroy()