mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-16 01:00:42 +03:00
207 lines
8.6 KiB
Python
207 lines
8.6 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# Creates an Excel spreadsheet graphing player stats
|
|
#
|
|
# Requires openpyxl >= 2.3
|
|
#
|
|
|
|
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 time
|
|
import re
|
|
|
|
from os.path import isfile, join
|
|
from config import config
|
|
|
|
|
|
dataseries = [
|
|
{
|
|
'name': 'Combat',
|
|
'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),
|
|
('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': ['Quantity', 'Profit [CR]'],
|
|
'keys': [
|
|
('Profit from trading', ['stats', 'trade', 'profit'], True),
|
|
('Commodities traded', ['stats', 'trade', 'qty']),
|
|
('Profit from smuggling', ['stats', 'blackMarket', 'profit'], True),
|
|
('Commodities smuggled', ['stats', 'blackMarket', 'qty']),
|
|
('Profit from mining', ['stats', 'mining', 'profit'], True),
|
|
('Fragments mined', ['stats', 'mining', 'qty']),
|
|
('Fragments converted', ['stats', 'mining', 'converted', 'qty']),
|
|
],
|
|
},
|
|
{
|
|
'name': 'Explorer',
|
|
'axes': ['Quantity', 'Profit [CR]'],
|
|
'keys': [
|
|
('Profits from exploration', ['stats', 'explore', 'creditsEarned'], True),
|
|
('Discovery scans', ['stats', 'explore', 'scanSoldLevels', 'lev_0']),
|
|
('Level 2 detailed scans', ['stats', 'explore', 'scanSoldLevels', 'lev_1']),
|
|
('Level 3 detailed scans', ['stats', 'explore', 'scanSoldLevels', 'lev_2']),
|
|
('Bodies first discovered', ['stats', 'explore', 'bodiesFirstDiscovered']),
|
|
('Hyperspace jumps', ['stats', 'explore', 'hyperspaceJumps']),
|
|
]
|
|
},
|
|
{
|
|
'name': 'Crime',
|
|
'axes': ['Quantity', 'Profit [CR]'],
|
|
'keys': [
|
|
('Fines', ['stats', 'crime', 'fine', 'qty']),
|
|
('Lifetime fine value', ['stats', 'crime', 'fine', 'value'], True),
|
|
('Bounties', ['stats', 'crime', 'bounty', 'qty']),
|
|
('Lifetime bounty value', ['stats', 'crime', 'bounty', 'value'], True),
|
|
('Profit from cargo', ['stats', 'crime', 'stolenCargo', 'value'], True),
|
|
('Stolen cargo', ['stats', 'crime', 'stolenCargo', 'qty']),
|
|
('Profit from goods', ['stats', 'stolenGoods', 'profit'], True),
|
|
('Stolen goods', ['stats', 'stolenGoods', 'qty']),
|
|
],
|
|
},
|
|
{
|
|
'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': ['Quantity', '[CR]'],
|
|
'keys': [
|
|
('Current balance', ['commander', 'credits'], True),
|
|
('Spent on ships', ['stats', 'ship', 'spend', 'ships'], True),
|
|
('Spent on outfitting', ['stats', 'ship', 'spend', 'modules'], True),
|
|
('Spent on repairs', ['stats', 'ship', 'spend', 'repair'], True),
|
|
('Insurance claims', ['stats', 'ship', 'insurance', 'claims']),
|
|
('Total claim costs', ['stats', 'ship', 'insurance', 'value'], True),
|
|
],
|
|
},
|
|
# {
|
|
# 'name': 'Vanish',
|
|
# 'prefix': ['stats', 'vanishCounters'],
|
|
# 'keys': ['amongPeers', 'inDanger', 'inDangerWithPeers', 'isNotDying', 'noPeers', 'notInDanger'],
|
|
# },
|
|
]
|
|
|
|
|
|
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, tuple)):
|
|
y2_axis = [len(x)>2 and x[2] for x in thing['keys']]
|
|
else:
|
|
y2_axis = None
|
|
|
|
if thing['name'] in wb:
|
|
ws = wb[thing['name']]
|
|
else:
|
|
ws = wb.create_sheet(title=thing['name'])
|
|
|
|
# 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']:
|
|
mydata = mydata[key]
|
|
for key2 in keys:
|
|
if isinstance(key2, basestring):
|
|
vals.append(mydata.get(key2, 0))
|
|
else:
|
|
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
|
|
|
|
dates = openpyxl.chart.Reference(ws, 1, 2, 1, ws.max_row)
|
|
|
|
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
|
|
|
|
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)
|