tradedangerous 10.13.9__py3-none-any.whl → 10.14.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tradedangerous might be problematic. Click here for more details.
- tradedangerous/cache.py +2 -2
- tradedangerous/commands/update_gui.py +1 -1
- tradedangerous/gui.py +27 -24
- tradedangerous/plugins/netlog_plug.py +4 -4
- tradedangerous/plugins/spansh_plug.py +379 -0
- tradedangerous/version.py +1 -1
- {tradedangerous-10.13.9.dist-info → tradedangerous-10.14.2.dist-info}/METADATA +2 -1
- {tradedangerous-10.13.9.dist-info → tradedangerous-10.14.2.dist-info}/RECORD +12 -11
- {tradedangerous-10.13.9.dist-info → tradedangerous-10.14.2.dist-info}/WHEEL +1 -1
- {tradedangerous-10.13.9.dist-info → tradedangerous-10.14.2.dist-info}/LICENSE +0 -0
- {tradedangerous-10.13.9.dist-info → tradedangerous-10.14.2.dist-info}/entry_points.txt +0 -0
- {tradedangerous-10.13.9.dist-info → tradedangerous-10.14.2.dist-info}/top_level.txt +0 -0
tradedangerous/cache.py
CHANGED
|
@@ -285,12 +285,12 @@ def getStationByNameIndex(cur):
|
|
|
285
285
|
""" Build station index in STAR/Station notation """
|
|
286
286
|
cur.execute("""
|
|
287
287
|
SELECT station_id,
|
|
288
|
-
|
|
288
|
+
system.name || '/' || station.name
|
|
289
289
|
FROM System
|
|
290
290
|
INNER JOIN Station
|
|
291
291
|
USING (system_id)
|
|
292
292
|
""")
|
|
293
|
-
return { name: ID for (ID, name) in cur }
|
|
293
|
+
return { name.upper(): ID for (ID, name) in cur }
|
|
294
294
|
|
|
295
295
|
|
|
296
296
|
def getItemByNameIndex(cur):
|
tradedangerous/gui.py
CHANGED
|
@@ -36,6 +36,7 @@ from __future__ import with_statement
|
|
|
36
36
|
from __future__ import print_function
|
|
37
37
|
from __future__ import division
|
|
38
38
|
from __future__ import unicode_literals
|
|
39
|
+
from pkg_resources import resource_filename
|
|
39
40
|
import os
|
|
40
41
|
import sys
|
|
41
42
|
import traceback
|
|
@@ -46,8 +47,10 @@ from pathlib import Path
|
|
|
46
47
|
from appJar import gui
|
|
47
48
|
import appJar
|
|
48
49
|
|
|
49
|
-
from tkinter import *
|
|
50
|
-
|
|
50
|
+
# from tkinter import *
|
|
51
|
+
# import tkinter.font as font
|
|
52
|
+
# import tkinter.scrolledtext as scrolledtext
|
|
53
|
+
# from tkinter.ttk import *
|
|
51
54
|
|
|
52
55
|
from . import commands
|
|
53
56
|
from . import plugins
|
|
@@ -294,7 +297,7 @@ def buildArgDicts():
|
|
|
294
297
|
if index.arguments:
|
|
295
298
|
for arg in index.arguments:
|
|
296
299
|
# print(arg.args[0])
|
|
297
|
-
argVals[arg.args[0]] =
|
|
300
|
+
argVals[arg.args[0]] = arg.kwargs.get('default') or None
|
|
298
301
|
|
|
299
302
|
allArgs[cmd]['req'][arg.args[0]] = {kwarg : arg.kwargs[kwarg] for kwarg in arg.kwargs}
|
|
300
303
|
allArgs[cmd]['req'][arg.args[0]]['widget'] = chooseType(arg)
|
|
@@ -303,7 +306,7 @@ def buildArgDicts():
|
|
|
303
306
|
if index.switches:
|
|
304
307
|
for arg in index.switches:
|
|
305
308
|
try:
|
|
306
|
-
argVals[arg.args[0]] =
|
|
309
|
+
argVals[arg.args[0]] = value = arg.kwargs.get('default') or None
|
|
307
310
|
|
|
308
311
|
allArgs[cmd]['opt'][arg.args[0]] = {kwarg : arg.kwargs[kwarg] for kwarg in arg.kwargs}
|
|
309
312
|
allArgs[cmd]['opt'][arg.args[0]]['widget'] = chooseType(arg)
|
|
@@ -320,7 +323,7 @@ def buildArgDicts():
|
|
|
320
323
|
|
|
321
324
|
except AttributeError:
|
|
322
325
|
for argGrp in arg.arguments:
|
|
323
|
-
argVals[argGrp.args[0]] =
|
|
326
|
+
argVals[argGrp.args[0]] = value = argGrp.kwargs.get('default') or None
|
|
324
327
|
|
|
325
328
|
allArgs[cmd]['opt'][argGrp.args[0]] = {kwarg : argGrp.kwargs[kwarg] for kwarg in argGrp.kwargs}
|
|
326
329
|
allArgs[cmd]['opt'][argGrp.args[0]]['widget'] = chooseType(argGrp)
|
|
@@ -472,7 +475,7 @@ def addWidgetFromArg(name, arg, parent):
|
|
|
472
475
|
sub = kwargs.pop('sub', None)
|
|
473
476
|
if type == 'ticks':
|
|
474
477
|
kwargs['height'] = len(kwargs['values'])
|
|
475
|
-
argVals[name] =
|
|
478
|
+
argVals[name] = value = kwargs.pop('values', None)
|
|
476
479
|
kwargs['listvariable'] = argVals[name]
|
|
477
480
|
kwargs['selectmode'] = 'extended'
|
|
478
481
|
#numeric
|
|
@@ -956,24 +959,24 @@ def main(argv = None):
|
|
|
956
959
|
)
|
|
957
960
|
|
|
958
961
|
|
|
959
|
-
window = Tk()
|
|
960
962
|
buildArgDicts()
|
|
961
|
-
|
|
962
|
-
window.title('Trade Dangerous GUI (Beta), TD v.%s' % (__version__,))
|
|
963
|
-
window.iconbitmap('../tradedangerouscrest.ico')
|
|
964
|
-
|
|
965
|
-
widgets['Command'] = addWidget('combo', window, 3, 0, values = Commands, bind = updateCommandBox,
|
|
966
|
-
width = 10, state = 'readonly', height = len(Commands), default = Commands[0], columnspan = 4,
|
|
967
|
-
justify = 'center', sticky = 'ew', tooltip = 'Trade Dangerous command to run.')
|
|
968
|
-
widgets['req'] = addWidget('frame', window, 0, 1, width = 200, height = 175, columnspan = 10, sdir = 'v')
|
|
969
|
-
widgets['opt'] = addWidget('frame', window, 0, 2, width = 200, height = 345, columnspan = 10, sdir = 'v')
|
|
970
|
-
|
|
971
|
-
widgets['tabFrame'] = addWidget('tab', window, 10, 1, rowspan = 2, columnspan = 40, width = 560, height = 520)
|
|
972
|
-
widgets [ 'helpPane'] = addWidget('stext', widgets['tabFrame'], width = 80, font = font.Font(family = 'Courier New', size=10),
|
|
973
|
-
#'fixed', 'oemfixed', 'ansifixed', 'systemfixed', 'TkFixedFont'
|
|
974
|
-
default = (0.0, cmdHelp['help']), state = 'disabled', tab = 'Help')
|
|
975
|
-
widgets['outPane'] = addWidget('stext', widgets['tabFrame'], width = 80, state = 'disabled', tab = 'Output')
|
|
976
963
|
|
|
964
|
+
# window = Tk()
|
|
965
|
+
# window.title('Trade Dangerous GUI (Beta), TD v.%s' % (__version__,))
|
|
966
|
+
# window.iconbitmap(resource_filename(__name__, "../tradedangerouscrest.ico"))
|
|
967
|
+
#
|
|
968
|
+
# widgets['Command'] = addWidget('combo', window, 3, 0, values = Commands, bind = updateCommandBox,
|
|
969
|
+
# width = 10, state = 'readonly', height = len(Commands), default = Commands[0], columnspan = 4,
|
|
970
|
+
# justify = 'center', sticky = 'ew', tooltip = 'Trade Dangerous command to run.')
|
|
971
|
+
# widgets['req'] = addWidget('frame', window, 0, 1, width = 200, height = 175, columnspan = 10, sdir = 'v')
|
|
972
|
+
# widgets['opt'] = addWidget('frame', window, 0, 2, width = 200, height = 345, columnspan = 10, sdir = 'v')
|
|
973
|
+
#
|
|
974
|
+
# widgets['tabFrame'] = addWidget('tab', window, 10, 1, rowspan = 2, columnspan = 40, width = 560, height = 520)
|
|
975
|
+
# widgets [ 'helpPane'] = addWidget('stext', widgets['tabFrame'], width = 80, font = font.Font(family = 'Courier New', size=10),
|
|
976
|
+
# #'fixed', 'oemfixed', 'ansifixed', 'systemfixed', 'TkFixedFont'
|
|
977
|
+
# default = (0.0, cmdHelp['help']), state = 'disabled', tab = 'Help')
|
|
978
|
+
# widgets['outPane'] = addWidget('stext', widgets['tabFrame'], width = 80, state = 'disabled', tab = 'Output')
|
|
979
|
+
#
|
|
977
980
|
# makeWidget('--link-ly', allArgs['--link-ly'], sticky = 'w', width = 4, row = 3, column = 2)
|
|
978
981
|
#
|
|
979
982
|
# makeWidget('--quiet', allArgs['--quiet'], sticky = 'e', disabled = ':', width = 1, row = 3, column = 46)
|
|
@@ -994,8 +997,8 @@ def main(argv = None):
|
|
|
994
997
|
# with win.scrollPane('DB', disabled = 'vertical', row = 5, column = 1, colspan = 49) as pane:
|
|
995
998
|
# pane.configure(width = 500, height = 20)
|
|
996
999
|
# win.label('db', argVals['--db'], sticky = 'w')
|
|
997
|
-
|
|
998
|
-
window.mainloop()
|
|
1000
|
+
#
|
|
1001
|
+
# window.mainloop()
|
|
999
1002
|
|
|
1000
1003
|
with gui('Trade Dangerous GUI (Beta), TD v.%s' % (__version__,), inPadding = 1) as win:
|
|
1001
1004
|
win.setFont(size = 8, family = 'Courier')
|
|
@@ -82,11 +82,11 @@ class ImportPlugin(ImportPluginBase):
|
|
|
82
82
|
tdb, tdenv = self.tdb, self.tdenv
|
|
83
83
|
optShow = self.getOption("show")
|
|
84
84
|
|
|
85
|
-
oldHeadRegEx = re.compile("^(?P<headDateTime>\d\d-\d\d-\d\d-\d\d:\d\d)\s+(?P<headTZName>.*[^\s])\s+(?P<headTimeGMT>\(.*GMT\))")
|
|
86
|
-
newHeadRegEx = re.compile("^(?P<headDateTime>\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)\s+(?P<headTZName>.*[^\s])")
|
|
85
|
+
oldHeadRegEx = re.compile(r"^(?P<headDateTime>\d\d-\d\d-\d\d-\d\d:\d\d)\s+(?P<headTZName>.*[^\s])\s+(?P<headTimeGMT>\(.*GMT\))")
|
|
86
|
+
newHeadRegEx = re.compile(r"^(?P<headDateTime>\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)\s+(?P<headTZName>.*[^\s])")
|
|
87
87
|
|
|
88
|
-
sysRegEx = re.compile('^\{[^\}]+\}\s+System:"(?P<sysName>[^"]+)".*StarPos:\((?P<sysPos>[^)]+)\)ly')
|
|
89
|
-
dateRegEx = re.compile('^\{(?P<logTime>\d\d:\d\d:\d\d)')
|
|
88
|
+
sysRegEx = re.compile(r'^\{[^\}]+\}\s+System:"(?P<sysName>[^"]+)".*StarPos:\((?P<sysPos>[^)]+)\)ly')
|
|
89
|
+
dateRegEx = re.compile(r'^\{(?P<logTime>\d\d:\d\d:\d\d)')
|
|
90
90
|
|
|
91
91
|
def calcSeconds(h=0, m=0, s=0):
|
|
92
92
|
return 3600*h + 60*m + s
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import time
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
|
+
from collections import namedtuple
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
import simdjson
|
|
10
|
+
import sqlite3
|
|
11
|
+
|
|
12
|
+
from .. import plugins
|
|
13
|
+
|
|
14
|
+
SOURCE_URL = 'https://downloads.spansh.co.uk/galaxy_stations.json'
|
|
15
|
+
|
|
16
|
+
STATION_TYPE_MAP = {
|
|
17
|
+
'Drake-Class Carrier': 24, # fleet carriers
|
|
18
|
+
'Settlement': 25, # odyssey settlements
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
System = namedtuple('System', 'name,pos_x,pos_y,pos_z,modified')
|
|
22
|
+
Station = namedtuple('Station', 'name,distance,max_pad_size,market,black_market,shipyard,outfitting,rearm,refuel,repair,planetary,type,modified')
|
|
23
|
+
Commodity = namedtuple('Commodity', 'id,name,category,demand,supply,sell,buy,modified')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Timing:
|
|
27
|
+
|
|
28
|
+
def __init__(self):
|
|
29
|
+
self.start_ts = None
|
|
30
|
+
self.end_ts = None
|
|
31
|
+
|
|
32
|
+
def __enter__(self):
|
|
33
|
+
self.start_ts = time.perf_counter()
|
|
34
|
+
self.end_ts = None
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
def __exit__(self, *args):
|
|
38
|
+
self.end_ts = time.perf_counter()
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def elapsed(self):
|
|
42
|
+
if self.start_ts is None:
|
|
43
|
+
return None
|
|
44
|
+
return (self.end_ts or time.perf_counter()) - self.start_ts
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def is_finished(self):
|
|
48
|
+
return self.end_ts is not None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ImportPlugin(plugins.ImportPluginBase):
|
|
52
|
+
"""Plugin that downloads data from https://spansh.co.uk/dumps.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
pluginOptions = {
|
|
56
|
+
'url': f'URL to download galaxy data from (defaults to {SOURCE_URL})',
|
|
57
|
+
'file': 'Local filename to import galaxy data from; use "-" to load from stdin',
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
def __init__(self, *args, **kwargs):
|
|
61
|
+
super().__init__(*args, **kwargs)
|
|
62
|
+
self.url = self.getOption('url')
|
|
63
|
+
self.file = self.getOption('file')
|
|
64
|
+
assert not (self.url and self.file), 'Provide either url or file, not both'
|
|
65
|
+
if self.file and (self.file != '-'):
|
|
66
|
+
self.file = (Path(self.tdenv.cwDir) / self.file).resolve()
|
|
67
|
+
self.known_space = self.load_known_space()
|
|
68
|
+
self.known_commodities = self.load_known_commodities()
|
|
69
|
+
|
|
70
|
+
def print(self, *args, **kwargs):
|
|
71
|
+
return self.tdenv.uprint(*args, **kwargs)
|
|
72
|
+
|
|
73
|
+
def run(self):
|
|
74
|
+
self.tdenv.filename = str(self.tdb.pricesPath)
|
|
75
|
+
if self.tdenv.detail < 1:
|
|
76
|
+
self.print('This will take at least several minutes...')
|
|
77
|
+
self.print('You can increase verbosity (-v) to get a sense of progress')
|
|
78
|
+
with open(self.tdb.pricesPath, 'w') as f, Timing() as timing:
|
|
79
|
+
self.print(f'Writing prices to {self.tdb.pricesPath}')
|
|
80
|
+
f.write('# Generated from spansh galaxy data\n')
|
|
81
|
+
f.write(f'# Source: {self.file or self.url}\n')
|
|
82
|
+
f.write('#\n')
|
|
83
|
+
f.write((
|
|
84
|
+
'# {name:50s} {sell:>7s} {buy:>7s} '
|
|
85
|
+
'{demand:>11s} {supply:>11s} {ts}\n'
|
|
86
|
+
).format(
|
|
87
|
+
name='Item Name',
|
|
88
|
+
sell='SellCr',
|
|
89
|
+
buy='BuyCr',
|
|
90
|
+
demand='Demand',
|
|
91
|
+
supply='Supply',
|
|
92
|
+
ts='Timestamp',
|
|
93
|
+
))
|
|
94
|
+
system_count = 0
|
|
95
|
+
total_station_count = 0
|
|
96
|
+
total_commodity_count = 0
|
|
97
|
+
self.need_commit = False
|
|
98
|
+
seen_stations = set()
|
|
99
|
+
for system, stations in self.data_stream():
|
|
100
|
+
self.ensure_system(system)
|
|
101
|
+
station_count = 0
|
|
102
|
+
commodity_count = 0
|
|
103
|
+
for station, commodities in stations:
|
|
104
|
+
if (system.name.upper(), station.name.upper()) in seen_stations:
|
|
105
|
+
fq_station_name = f'@{system.name.upper()}/{station.name}'
|
|
106
|
+
if self.tdenv.detail >= 1:
|
|
107
|
+
self.print(f' | {fq_station_name:50s} | Skipping duplicate station record')
|
|
108
|
+
continue
|
|
109
|
+
seen_stations.add((system.name.upper(), station.name.upper()))
|
|
110
|
+
self.ensure_station(system, station)
|
|
111
|
+
f.write('\n')
|
|
112
|
+
f.write(f'@ {system.name.upper()}/{station.name}\n')
|
|
113
|
+
categories = self.categorise_commodities(commodities)
|
|
114
|
+
for category_name, category_commodities in categories.items():
|
|
115
|
+
f.write(f' + {category_name}\n')
|
|
116
|
+
for commodity in category_commodities:
|
|
117
|
+
commodity = self.ensure_commodity(station, commodity)
|
|
118
|
+
f.write((
|
|
119
|
+
' {name:50s} {sell:7d} {buy:7d} '
|
|
120
|
+
'{demand:10d}? {supply:10d}? {modified}\n'
|
|
121
|
+
).format(
|
|
122
|
+
name=commodity.name,
|
|
123
|
+
sell=commodity.sell,
|
|
124
|
+
buy=commodity.buy,
|
|
125
|
+
demand=commodity.demand,
|
|
126
|
+
supply=commodity.supply,
|
|
127
|
+
modified=commodity.modified,
|
|
128
|
+
))
|
|
129
|
+
commodity_count += 1
|
|
130
|
+
station_count += 1
|
|
131
|
+
system_count += 1
|
|
132
|
+
total_station_count += station_count
|
|
133
|
+
total_commodity_count += commodity_count
|
|
134
|
+
if self.tdenv.detail >= 1:
|
|
135
|
+
self.print(
|
|
136
|
+
f'{system_count:6d} | {system.name.upper():50s} | '
|
|
137
|
+
f'{station_count:3d} st {commodity_count:6d} co'
|
|
138
|
+
)
|
|
139
|
+
if self.need_commit:
|
|
140
|
+
self.execute('COMMIT')
|
|
141
|
+
self.need_commit = False
|
|
142
|
+
self.print(
|
|
143
|
+
f'{timedelta(seconds=int(timing.elapsed))!s} Done '
|
|
144
|
+
f'{total_station_count} st {total_commodity_count} co'
|
|
145
|
+
)
|
|
146
|
+
return True
|
|
147
|
+
|
|
148
|
+
def data_stream(self):
|
|
149
|
+
if self.file == '-':
|
|
150
|
+
self.print('Reading prices from stdin')
|
|
151
|
+
stream = sys.stdin
|
|
152
|
+
elif self.file:
|
|
153
|
+
self.print(f'Reading prices from local file: {self.file}')
|
|
154
|
+
stream = open(self.file, 'r', encoding='utf8')
|
|
155
|
+
else:
|
|
156
|
+
url = self.url or SOURCE_URL
|
|
157
|
+
self.print(f'Reading prices from remote URL: {url}')
|
|
158
|
+
req = requests.get(url, stream=True)
|
|
159
|
+
stream = req.iter_lines(decode_unicode=True)
|
|
160
|
+
return ingest_stream(stream)
|
|
161
|
+
|
|
162
|
+
def categorise_commodities(self, commodities):
|
|
163
|
+
categories = {}
|
|
164
|
+
for commodity in commodities:
|
|
165
|
+
categories.setdefault(commodity.category, []).append(commodity)
|
|
166
|
+
return categories
|
|
167
|
+
|
|
168
|
+
def execute(self, query, *params, **kwparams):
|
|
169
|
+
attempts = 5
|
|
170
|
+
cursor = self.tdb.getDB().cursor()
|
|
171
|
+
while True:
|
|
172
|
+
try:
|
|
173
|
+
return cursor.execute(query, params or kwparams)
|
|
174
|
+
except sqlite3.OperationalError as ex:
|
|
175
|
+
if not attempts:
|
|
176
|
+
raise
|
|
177
|
+
attempts -= 1
|
|
178
|
+
self.print(f'Retrying query: {ex!s}')
|
|
179
|
+
time.sleep(1)
|
|
180
|
+
|
|
181
|
+
def load_known_space(self):
|
|
182
|
+
cache = {}
|
|
183
|
+
result = self.execute(
|
|
184
|
+
'''
|
|
185
|
+
SELECT System.name, Station.name FROM System
|
|
186
|
+
LEFT JOIN Station USING (system_id)
|
|
187
|
+
'''
|
|
188
|
+
).fetchall()
|
|
189
|
+
for system, station in result:
|
|
190
|
+
cache.setdefault(system.upper(), set())
|
|
191
|
+
if station is not None:
|
|
192
|
+
cache[system.upper()].add(station.upper())
|
|
193
|
+
return cache
|
|
194
|
+
|
|
195
|
+
def load_known_commodities(self):
|
|
196
|
+
return dict(self.execute('SELECT fdev_id, name FROM Item').fetchall())
|
|
197
|
+
|
|
198
|
+
def ensure_system(self, system):
|
|
199
|
+
if system.name.upper() in self.known_space:
|
|
200
|
+
return
|
|
201
|
+
self.execute(
|
|
202
|
+
'''
|
|
203
|
+
INSERT INTO System (name, pos_x, pos_y, pos_z, modified) VALUES (?, ?, ?, ?, ?)
|
|
204
|
+
''',
|
|
205
|
+
system.name, system.pos_x, system.pos_y, system.pos_z, system.modified,
|
|
206
|
+
)
|
|
207
|
+
self.need_commit = True
|
|
208
|
+
if self.tdenv.detail >= 2:
|
|
209
|
+
self.print(f' | {system.name.upper():50s} | Added missing system')
|
|
210
|
+
self.known_space[system.name.upper()] = set()
|
|
211
|
+
|
|
212
|
+
def ensure_station(self, system, station):
|
|
213
|
+
if station.name.upper() in self.known_space.get(system.name.upper(), set()):
|
|
214
|
+
return
|
|
215
|
+
self.execute(
|
|
216
|
+
'''
|
|
217
|
+
INSERT INTO Station (
|
|
218
|
+
system_id,
|
|
219
|
+
name,
|
|
220
|
+
ls_from_star,
|
|
221
|
+
max_pad_size,
|
|
222
|
+
market,
|
|
223
|
+
blackmarket,
|
|
224
|
+
shipyard,
|
|
225
|
+
outfitting,
|
|
226
|
+
rearm,
|
|
227
|
+
refuel,
|
|
228
|
+
repair,
|
|
229
|
+
planetary,
|
|
230
|
+
modified,
|
|
231
|
+
type_id
|
|
232
|
+
)
|
|
233
|
+
VALUES (
|
|
234
|
+
(SELECT system_id FROM System WHERE upper(name) = ?),
|
|
235
|
+
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
|
236
|
+
)
|
|
237
|
+
''',
|
|
238
|
+
system.name.upper(),
|
|
239
|
+
station.name,
|
|
240
|
+
station.distance,
|
|
241
|
+
station.max_pad_size,
|
|
242
|
+
self.bool_yn(station.market),
|
|
243
|
+
self.bool_yn(station.black_market),
|
|
244
|
+
self.bool_yn(station.shipyard),
|
|
245
|
+
self.bool_yn(station.outfitting),
|
|
246
|
+
self.bool_yn(station.rearm),
|
|
247
|
+
self.bool_yn(station.refuel),
|
|
248
|
+
self.bool_yn(station.repair),
|
|
249
|
+
self.bool_yn(station.planetary),
|
|
250
|
+
station.modified,
|
|
251
|
+
station.type,
|
|
252
|
+
)
|
|
253
|
+
self.need_commit = True
|
|
254
|
+
if self.tdenv.detail >= 2:
|
|
255
|
+
self.print(f' | {station.name:50s} | Added missing station')
|
|
256
|
+
self.known_space[system.name.upper()].add(station.name.upper())
|
|
257
|
+
|
|
258
|
+
def ensure_commodity(self, station, commodity):
|
|
259
|
+
if commodity.id in self.known_commodities:
|
|
260
|
+
if self.known_commodities[commodity.id] != commodity.name:
|
|
261
|
+
if self.tdenv.detail >= 3:
|
|
262
|
+
self.print(f' | - {station.name:45s} | Replace "{commodity.name}" with pre-existing "{self.known_commodities[commodity.id]}"')
|
|
263
|
+
return Commodity(
|
|
264
|
+
id=commodity.id,
|
|
265
|
+
name=self.known_commodities[commodity.id],
|
|
266
|
+
category=commodity.category,
|
|
267
|
+
demand=commodity.demand,
|
|
268
|
+
supply=commodity.supply,
|
|
269
|
+
sell=commodity.sell,
|
|
270
|
+
buy=commodity.buy,
|
|
271
|
+
modified=commodity.modified,
|
|
272
|
+
)
|
|
273
|
+
return commodity
|
|
274
|
+
self.execute(
|
|
275
|
+
'''
|
|
276
|
+
INSERT INTO Item (category_id, name, fdev_id)
|
|
277
|
+
VALUES ((SELECT category_id FROM Category WHERE upper(name) = ?), ?, ?)
|
|
278
|
+
''',
|
|
279
|
+
commodity.category.upper(),
|
|
280
|
+
commodity.name,
|
|
281
|
+
commodity.id,
|
|
282
|
+
)
|
|
283
|
+
self.need_commit = True
|
|
284
|
+
if self.tdenv.detail >= 2:
|
|
285
|
+
self.print(f' | {commodity.name:50s} | Added missing commodity')
|
|
286
|
+
self.known_commodities[commodity.id] = commodity.name
|
|
287
|
+
return commodity
|
|
288
|
+
|
|
289
|
+
def bool_yn(self, value):
|
|
290
|
+
return '?' if value is None else ('Y' if value else 'N')
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def ingest_stream(stream):
|
|
294
|
+
"""Ingest a spansh-style galaxy dump, yielding system-level data."""
|
|
295
|
+
line = next(stream)
|
|
296
|
+
assert line.rstrip(' \n,') == '['
|
|
297
|
+
for line in stream:
|
|
298
|
+
line = line.rstrip().rstrip(',')
|
|
299
|
+
if line == ']':
|
|
300
|
+
break
|
|
301
|
+
system_data = simdjson.Parser().parse(line)
|
|
302
|
+
coords = system_data.get('coords', {})
|
|
303
|
+
yield (
|
|
304
|
+
System(
|
|
305
|
+
name=system_data.get('name', 'Unnamed'),
|
|
306
|
+
pos_x=coords.get('x', 999999),
|
|
307
|
+
pos_y=coords.get('y', 999999),
|
|
308
|
+
pos_z=coords.get('z', 999999),
|
|
309
|
+
modified=parse_ts(system_data.get('date')),
|
|
310
|
+
),
|
|
311
|
+
ingest_stations(system_data),
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def ingest_stations(system_data):
|
|
316
|
+
"""Ingest system-level data, yielding station-level data."""
|
|
317
|
+
targets = [system_data, *system_data.get('bodies', ())]
|
|
318
|
+
is_planetary = False
|
|
319
|
+
for target in targets:
|
|
320
|
+
for station_data in target.get('stations', ()):
|
|
321
|
+
services = set(station_data.get('services', ()))
|
|
322
|
+
if 'Market' not in services:
|
|
323
|
+
continue
|
|
324
|
+
market = station_data.get('market', {})
|
|
325
|
+
if not market.get('commodities'):
|
|
326
|
+
continue
|
|
327
|
+
landing_pads = station_data.get('landingPads', {})
|
|
328
|
+
max_pad_size = '?'
|
|
329
|
+
if landing_pads.get('large'):
|
|
330
|
+
max_pad_size = 'L'
|
|
331
|
+
elif landing_pads.get('medium'):
|
|
332
|
+
max_pad_size = 'M'
|
|
333
|
+
elif landing_pads.get('small'):
|
|
334
|
+
max_pad_size = 'S'
|
|
335
|
+
yield (
|
|
336
|
+
Station(
|
|
337
|
+
name=station_data.get('name', 'Unnamed'),
|
|
338
|
+
distance=station_data.get('distanceToArrival', 999999),
|
|
339
|
+
max_pad_size=max_pad_size,
|
|
340
|
+
market=True,
|
|
341
|
+
black_market='Black Market' in services,
|
|
342
|
+
shipyard='Shipyard' in services,
|
|
343
|
+
outfitting='Outfitting' in services,
|
|
344
|
+
rearm='Restock' in services,
|
|
345
|
+
refuel='Refuel' in services,
|
|
346
|
+
repair='Repair' in services,
|
|
347
|
+
planetary=is_planetary,
|
|
348
|
+
type=STATION_TYPE_MAP.get(station_data.get('type'), 0),
|
|
349
|
+
modified=parse_ts(station_data.get('updateTime')),
|
|
350
|
+
),
|
|
351
|
+
ingest_market(market),
|
|
352
|
+
)
|
|
353
|
+
# first target is system stations, everything else is planetary
|
|
354
|
+
is_planetary = True
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def ingest_market(market):
|
|
358
|
+
"""Ingest station-level market data, yielding commodities."""
|
|
359
|
+
for commodity in market['commodities']:
|
|
360
|
+
yield Commodity(
|
|
361
|
+
id=commodity.get('commodityId'),
|
|
362
|
+
name=commodity.get('name', 'Unnamed'),
|
|
363
|
+
category=commodity.get('category', 'Uncategorised'),
|
|
364
|
+
demand=commodity.get('demand', 0),
|
|
365
|
+
supply=commodity.get('supply', 0),
|
|
366
|
+
sell=commodity.get('sellPrice', 0),
|
|
367
|
+
buy=commodity.get('buyPrice', 0),
|
|
368
|
+
modified=parse_ts(market.get('updateTime'))
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def parse_ts(ts):
|
|
373
|
+
if ts is None:
|
|
374
|
+
return None
|
|
375
|
+
if ts.endswith('+00'):
|
|
376
|
+
ts = ts[:-3]
|
|
377
|
+
if '.' not in ts:
|
|
378
|
+
ts += '.0'
|
|
379
|
+
return datetime.strptime(ts, '%Y-%m-%d %H:%M:%S.%f').replace(microsecond=0)
|
tradedangerous/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tradedangerous
|
|
3
|
-
Version: 10.
|
|
3
|
+
Version: 10.14.2
|
|
4
4
|
Summary: Trade-Dangerous is a set of powerful trading tools for Elite Dangerous, organized around one of the most powerful trade run optimizers available.
|
|
5
5
|
Home-page: https://github.com/eyeonus/Trade-Dangerous
|
|
6
6
|
Author: eyeonus
|
|
@@ -21,6 +21,7 @@ Description-Content-Type: text/markdown
|
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
Requires-Dist: requests
|
|
23
23
|
Requires-Dist: appJar
|
|
24
|
+
Requires-Dist: pysimdjson
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
----------
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
tradedangerous/__init__.py,sha256=5ZeypoZaM8hlh6c-yTkD8x5hZYP8q3Q8a3bVeicHr90,1122
|
|
2
|
-
tradedangerous/cache.py,sha256=
|
|
2
|
+
tradedangerous/cache.py,sha256=t9--q6etNH5vigvA_1VLf_XTdoC_116qkjnqswhshpg,32942
|
|
3
3
|
tradedangerous/cli.py,sha256=ycGkzMszwpP9OrngFIyhQbYoZ2wzRhJMTDCW1YhLrNI,4727
|
|
4
4
|
tradedangerous/corrections.py,sha256=QMs-7MKLw2imFgIHthnwcpqWT1yJTb3CrABJw9LaKLA,1441
|
|
5
5
|
tradedangerous/csvexport.py,sha256=OcOKe_VIgafw6rCvG3k5tM11KwwoYXMNY5DSSfCC0mU,8705
|
|
@@ -7,7 +7,7 @@ tradedangerous/edscupdate.py,sha256=-aglmhmtCKYrUyYKO1SBs4xmEHafTL4CjVeAt8uproU,
|
|
|
7
7
|
tradedangerous/edsmupdate.py,sha256=GesavwY7rI5tuoTTMrM8sjYSN50QaPsDqKR2rrVbRZk,14924
|
|
8
8
|
tradedangerous/formatting.py,sha256=3uqO9zHOTdfgZdFfhhL32gK_jIpliYOPhJocY5C1cfU,6162
|
|
9
9
|
tradedangerous/fs.py,sha256=zVh5dF9dnJB0WLPSGX1KlJ8Sgqff5my3wer7m_4ddwM,2530
|
|
10
|
-
tradedangerous/gui.py,sha256=
|
|
10
|
+
tradedangerous/gui.py,sha256=DvHUB-evcVSoJS1skTe7urx54ovD5jAi6rHPpVgh-xk,44100
|
|
11
11
|
tradedangerous/jsonprices.py,sha256=AQ2YFMc18s-KdvXAGZnYDw2bNbfBksWnM-vXRS8IP70,7013
|
|
12
12
|
tradedangerous/mapping.py,sha256=RNjZy5hpokFVFDw_KkOUELmT4fPJC1RZiN9D8ZeAu5o,4034
|
|
13
13
|
tradedangerous/prices.py,sha256=AcETd8b-lKwuyyx6cTud2jyoQLPZaxMuGgQNI9N-SYU,7593
|
|
@@ -21,7 +21,7 @@ tradedangerous/tradeexcept.py,sha256=aZ-Y31MbkjF7lmAzBAbaMsPPE7FEEfuf4gaX2GvriDk
|
|
|
21
21
|
tradedangerous/tradegui.py,sha256=JbGFnsWupgesk6hrcUgKSdD9NNDyo0U9gh6m3DccAwU,782
|
|
22
22
|
tradedangerous/transfers.py,sha256=NmXXk2aF88YkAvYqc9Syt_aO6d2jJjC-OxoRFoOyQH4,9923
|
|
23
23
|
tradedangerous/utils.py,sha256=PUPvAEqUyxYGqqQa0b_yfLAvq8YVUxK6HfdS-CxM-Lo,5186
|
|
24
|
-
tradedangerous/version.py,sha256=
|
|
24
|
+
tradedangerous/version.py,sha256=5iuvqnu0uphkiczIVtwP6oY8olhV7oHQ5oaAUqtQt6g,647
|
|
25
25
|
tradedangerous/commands/TEMPLATE.py,sha256=7oXL124aqxGHwnb0h9yRylUiwc6M5QrRrGVrubwI1gg,2124
|
|
26
26
|
tradedangerous/commands/__init__.py,sha256=6B0WuqkFBOll5Hj67yKDAnhmyr5ZAnHc6nzUNEUh384,9640
|
|
27
27
|
tradedangerous/commands/buildcache_cmd.py,sha256=oJvP06fA8svnHrfrpWkHKR16cba8GIhHdMOyZqds18Y,2332
|
|
@@ -42,7 +42,7 @@ tradedangerous/commands/shipvendor_cmd.py,sha256=mAIlXoRqa2X8dkVB9Q0dYZwb21LdDqr
|
|
|
42
42
|
tradedangerous/commands/station_cmd.py,sha256=IFRkf-Vw4A3cLZuUsHMgTZQHiFQeh5feES3culurCnc,16412
|
|
43
43
|
tradedangerous/commands/trade_cmd.py,sha256=ABmRIJmZeBDrJGuMLQ7_g9tvpVSNNC-0MEbbsTvUUe0,3175
|
|
44
44
|
tradedangerous/commands/update_cmd.py,sha256=JiE12nPlCQIfZ8y28kTCSlr8T9fHM0yliwabqUEjk-Y,14583
|
|
45
|
-
tradedangerous/commands/update_gui.py,sha256=
|
|
45
|
+
tradedangerous/commands/update_gui.py,sha256=Kd4fPy_Bo9JBZTn0nn1MVft3kioQaMXAlh1qa4vJIkw,23377
|
|
46
46
|
tradedangerous/mfd/__init__.py,sha256=ySrPBGFZs7gzktpZBZWRoT-UoqKUldqx15ccWvNa62E,3065
|
|
47
47
|
tradedangerous/mfd/saitek/__init__.py,sha256=IyIxv8Rd4iJKE32TD16JGTWiQYOBR0omndOvn7C1O4g,63
|
|
48
48
|
tradedangerous/mfd/saitek/directoutput.py,sha256=-9Kt7nTa--72sPY2-qV_T727izT5m6d0vMwolPSMJyA,24949
|
|
@@ -65,14 +65,15 @@ tradedangerous/plugins/edcd_plug.py,sha256=ZPtRzLhcQZEiwEo3AoPyk3Uy4UmRLM6gv2Qi1
|
|
|
65
65
|
tradedangerous/plugins/eddblink_plug.py,sha256=n8AzLh2pJdHdar1SnqSSjCwWPl4f-OKQ8SnmDGXaLFU,54231
|
|
66
66
|
tradedangerous/plugins/edmc_batch_plug.py,sha256=3Ptr-SZqaZFR8ViIIrp9Ak7rvfU3zl11AZYBhIceN7s,4224
|
|
67
67
|
tradedangerous/plugins/journal_plug.py,sha256=K1oIeI7E3mb04fvYLXyoAh7fOTyM9NBelibTI88MIDQ,23696
|
|
68
|
-
tradedangerous/plugins/netlog_plug.py,sha256=
|
|
68
|
+
tradedangerous/plugins/netlog_plug.py,sha256=Gw_HSZWpN17D--OIYEM3Vo8y9SvDOv9UwAUfY24kz28,13460
|
|
69
|
+
tradedangerous/plugins/spansh_plug.py,sha256=ImU1tp995LhzFX7sJXApLiwrxx29b2WXR0jtWvm5O0U,14485
|
|
69
70
|
tradedangerous/templates/Added.csv,sha256=8o54civQCcS9y7_DBo0GX196XWRbbREQqKDYTKibsgQ,649
|
|
70
71
|
tradedangerous/templates/DefaultShipIndex.json,sha256=m5cI3vkKiqRk1VKO1Z_8LZrG9nczV0PUMDfBSt4-1RM,94739
|
|
71
72
|
tradedangerous/templates/RareItem.csv,sha256=F1RhRnTD82PiwrVUO-ai2ErGH2PTqNnQaDw5mcgljXs,10483
|
|
72
73
|
tradedangerous/templates/TradeDangerous.sql,sha256=6sjEogGHy-9zYpjPo0Y2a5tElowmHFyJNwrimOUBfHk,8079
|
|
73
|
-
tradedangerous-10.
|
|
74
|
-
tradedangerous-10.
|
|
75
|
-
tradedangerous-10.
|
|
76
|
-
tradedangerous-10.
|
|
77
|
-
tradedangerous-10.
|
|
78
|
-
tradedangerous-10.
|
|
74
|
+
tradedangerous-10.14.2.dist-info/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
|
75
|
+
tradedangerous-10.14.2.dist-info/METADATA,sha256=F90OuVRZ5eI8SzlzQDdmhrrOQQbEa0RnAMlRKXX-KBk,4421
|
|
76
|
+
tradedangerous-10.14.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
77
|
+
tradedangerous-10.14.2.dist-info/entry_points.txt,sha256=pSwa-q0ob443uiKux7xFKYQl8uen66iDTnjdrQhNLx8,92
|
|
78
|
+
tradedangerous-10.14.2.dist-info/top_level.txt,sha256=bF29i-oEltmNICgElEKxNsg83oahJvxg3a7YrxZi9Rk,15
|
|
79
|
+
tradedangerous-10.14.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|