tradedangerous 10.15.2__py3-none-any.whl → 10.16.0__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 +7 -5
- tradedangerous/plugins/eddblink_plug.py +115 -722
- tradedangerous/plugins/spansh_plug.py +205 -119
- tradedangerous/templates/Category.csv +17 -0
- tradedangerous/version.py +1 -1
- {tradedangerous-10.15.2.dist-info → tradedangerous-10.16.0.dist-info}/METADATA +1 -1
- {tradedangerous-10.15.2.dist-info → tradedangerous-10.16.0.dist-info}/RECORD +11 -10
- {tradedangerous-10.15.2.dist-info → tradedangerous-10.16.0.dist-info}/LICENSE +0 -0
- {tradedangerous-10.15.2.dist-info → tradedangerous-10.16.0.dist-info}/WHEEL +0 -0
- {tradedangerous-10.15.2.dist-info → tradedangerous-10.16.0.dist-info}/entry_points.txt +0 -0
- {tradedangerous-10.15.2.dist-info → tradedangerous-10.16.0.dist-info}/top_level.txt +0 -0
|
@@ -17,7 +17,6 @@ from urllib import request
|
|
|
17
17
|
from calendar import timegm
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from importlib import reload
|
|
20
|
-
from builtins import str
|
|
21
20
|
|
|
22
21
|
from .. import plugins, cache, csvexport, tradedb, tradeenv, transfers
|
|
23
22
|
from ..misc import progress as pbar
|
|
@@ -26,16 +25,6 @@ from shutil import copyfile
|
|
|
26
25
|
|
|
27
26
|
# Constants
|
|
28
27
|
BASE_URL = os.environ.get('TD_SERVER') or "https://elite.tromador.com/files/"
|
|
29
|
-
FALLBACK_URL = os.environ.get('TD_FALLBACK') or "https://eddb.io/archive/v6/"
|
|
30
|
-
SHIPS_URL = os.environ.get('TD_SHIPS') or "https://beta.coriolis.io/data/index.json"
|
|
31
|
-
COMMODITIES = "commodities.json"
|
|
32
|
-
SYS_FULL = "systems.csv"
|
|
33
|
-
SYS_RECENT = "systems_recently.csv"
|
|
34
|
-
SYS_POP = "systems_populated.jsonl"
|
|
35
|
-
STATIONS = "stations.jsonl"
|
|
36
|
-
UPGRADES = "modules.json"
|
|
37
|
-
LISTINGS = "listings.csv"
|
|
38
|
-
LIVE_LISTINGS = "listings-live.csv"
|
|
39
28
|
CONTEXT=ssl.create_default_context(cafile=certifi.where())
|
|
40
29
|
|
|
41
30
|
|
|
@@ -57,60 +46,46 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
57
46
|
"""
|
|
58
47
|
|
|
59
48
|
pluginOptions = {
|
|
60
|
-
'item': "
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
'
|
|
64
|
-
'
|
|
65
|
-
'station': "
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
'upvend': "Regenerate UpgradeVendors using latest stations.jsonl dump. (Implies '-O system,station,upgrade')",
|
|
70
|
-
'listings': "Update market data using latest listings.csv dump. (Implies '-O item,system,station,purge')",
|
|
49
|
+
'item': "Update Items using latest file from server. (Implies '-O system,station')",
|
|
50
|
+
'rare': "Update RareItems using latest file from server. (Implies '-O system,station')",
|
|
51
|
+
'ship': "Update Ships using latest file from server.",
|
|
52
|
+
'upgrade': "Update Upgrades using latest file from server.",
|
|
53
|
+
'system': "Update Systems using latest file from server.",
|
|
54
|
+
'station': "Update Stations using latest file from server. (Implies '-O system')",
|
|
55
|
+
'shipvend': "Update ShipVendors using latest file from server. (Implies '-O system,station,ship')",
|
|
56
|
+
'upvend': "Update UpgradeVendors using latest file from server. (Implies '-O system,station,upgrade')",
|
|
57
|
+
'listings': "Update market data using latest listings.csv dump. (Implies '-O item,system,station')",
|
|
71
58
|
'all': "Update everything with latest dumpfiles. (Regenerates all tables)",
|
|
72
59
|
'clean': "Erase entire database and rebuild from empty. (Regenerates all tables.)",
|
|
73
60
|
'skipvend': "Don't regenerate ShipVendors or UpgradeVendors. (Supercedes '-O all', '-O clean'.)",
|
|
74
61
|
'force': "Force regeneration of selected items even if source file not updated since previous run. "
|
|
75
62
|
"(Useful for updating Vendor tables if they were skipped during a '-O clean' run.)",
|
|
76
|
-
'
|
|
77
|
-
'progbar': "Does nothing, only included for backwards compatibility.",
|
|
63
|
+
'purge': "Remove any empty systems that previously had fleet carriers.",
|
|
78
64
|
'solo': "Don't download crowd-sourced market data. (Implies '-O skipvend', supercedes '-O all', '-O clean', '-O listings'.)"
|
|
79
65
|
}
|
|
80
66
|
|
|
81
67
|
def __init__(self, tdb, tdenv):
|
|
82
68
|
super().__init__(tdb, tdenv)
|
|
83
69
|
|
|
84
|
-
self.dataPath = Path(os.environ.get('TD_EDDB')) if os.environ.get('TD_EDDB') else tdb.dataPath / Path("eddb")
|
|
85
|
-
self.
|
|
86
|
-
self.
|
|
87
|
-
self.
|
|
88
|
-
self.
|
|
89
|
-
self.
|
|
90
|
-
self.
|
|
91
|
-
self.
|
|
92
|
-
self.
|
|
93
|
-
self.
|
|
70
|
+
self.dataPath = Path(os.environ.get('TD_EDDB')) if os.environ.get('TD_EDDB') else self.tdb.dataPath / Path("eddb")
|
|
71
|
+
self.categoriesPath = Path("Category.csv")
|
|
72
|
+
self.commoditiesPath = Path("Item.csv")
|
|
73
|
+
self.rareItemPath = Path("RareItem.csv")
|
|
74
|
+
self.shipPath = Path("Ship.csv")
|
|
75
|
+
self.shipVendorPath = Path("ShipVendor.csv")
|
|
76
|
+
self.stationsPath = Path("Station.csv")
|
|
77
|
+
self.sysPath = Path("System.csv")
|
|
78
|
+
self.upgradesPath = Path("Upgrade.csv")
|
|
79
|
+
self.upgradeVendorPath = Path("UpgradeVendor.csv")
|
|
80
|
+
self.listingsPath = Path("listings.csv")
|
|
81
|
+
self.liveListingsPath = Path("listings-live.csv")
|
|
94
82
|
self.pricesPath = Path("listings.prices")
|
|
95
|
-
self.updated = {
|
|
96
|
-
"Category": False,
|
|
97
|
-
"Item": False,
|
|
98
|
-
"RareItem": False,
|
|
99
|
-
"Ship": False,
|
|
100
|
-
"ShipVendor": False,
|
|
101
|
-
"Station": False,
|
|
102
|
-
"System": False,
|
|
103
|
-
"Upgrade": False,
|
|
104
|
-
"UpgradeVendor": False,
|
|
105
|
-
"Listings": False
|
|
106
|
-
}
|
|
107
83
|
|
|
108
84
|
def now(self):
|
|
109
85
|
return datetime.datetime.now()
|
|
110
86
|
|
|
111
87
|
def execute(self, sql_cmd, args = None):
|
|
112
|
-
|
|
113
|
-
cur = tdb.getDB().cursor()
|
|
88
|
+
cur = self.tdb.getDB().cursor()
|
|
114
89
|
|
|
115
90
|
success = False
|
|
116
91
|
result = None
|
|
@@ -131,8 +106,7 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
131
106
|
return result
|
|
132
107
|
|
|
133
108
|
def executemany(self, sql_cmd, args):
|
|
134
|
-
|
|
135
|
-
cur = tdb.getDB().cursor()
|
|
109
|
+
cur = self.tdb.getDB().cursor()
|
|
136
110
|
|
|
137
111
|
success = False
|
|
138
112
|
result = None
|
|
@@ -170,643 +144,66 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
170
144
|
break
|
|
171
145
|
yield b
|
|
172
146
|
|
|
173
|
-
def downloadFile(self,
|
|
147
|
+
def downloadFile(self, path):
|
|
174
148
|
"""
|
|
175
149
|
Fetch the latest dumpfile from the website if newer than local copy.
|
|
176
150
|
"""
|
|
177
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
178
151
|
|
|
179
152
|
def openURL(url):
|
|
180
153
|
return request_url(url, headers = {'User-Agent': 'Trade-Dangerous'})
|
|
181
154
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
tdenv.WARN("Full " + str(self.sysFullPath) + " file is ~5GB in size. This will take awhile.")
|
|
185
|
-
if urlTail == SHIPS_URL:
|
|
186
|
-
url = urlTail
|
|
187
|
-
#Temp until I figure out how to automate this again.
|
|
188
|
-
copyfile(self.tdenv.templateDir / Path("DefaultShipIndex.json"), self.dataPath / path)
|
|
189
|
-
return True
|
|
155
|
+
if path != self.liveListingsPath and path != self.listingsPath:
|
|
156
|
+
localPath = self.tdb.dataPath / path
|
|
190
157
|
else:
|
|
191
|
-
|
|
192
|
-
if url == SHIPS_URL or not self.getOption('fallback'):
|
|
193
|
-
try:
|
|
194
|
-
response = openURL(url)
|
|
195
|
-
except Exception as e:
|
|
196
|
-
# If Tromador's server fails for whatever reason,
|
|
197
|
-
# fallback to download direct from EDDB.io
|
|
198
|
-
tdenv.WARN("Problem with download:\n URL: {}\n Error: {}", url, str(e))
|
|
199
|
-
|
|
200
|
-
if urlTail != LIVE_LISTINGS:
|
|
201
|
-
self.options["fallback"] = True
|
|
158
|
+
localPath = self.dataPath / path
|
|
202
159
|
|
|
203
|
-
|
|
204
|
-
# EDDB.io doesn't have live listings or the ship index.
|
|
205
|
-
if urlTail == LIVE_LISTINGS:
|
|
206
|
-
return False
|
|
207
|
-
|
|
208
|
-
url = FALLBACK_URL + urlTail
|
|
209
|
-
try:
|
|
210
|
-
response = openURL(url)
|
|
211
|
-
except Exception as e:
|
|
212
|
-
tdenv.WARN("Problem with download (fallback enabled):\nURL: {}\nError: {}", url, str(e))
|
|
213
|
-
return False
|
|
160
|
+
url = BASE_URL + str(path)
|
|
214
161
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
# Now we need to make a datetime object using the DateList and TimeList we just created,
|
|
231
|
-
# and then we can finally convert that to a Unix-epoch number.
|
|
232
|
-
dumpDT = datetime.datetime(int(dDL[3]), Months[dDL[2]], int(dDL[1]), \
|
|
233
|
-
hour = int(dTL[0]), minute = int(dTL[1]), second = int(dTL[2]), \
|
|
234
|
-
tzinfo = datetime.timezone.utc)
|
|
235
|
-
dumpModded = timegm(dumpDT.timetuple())
|
|
236
|
-
|
|
237
|
-
if Path.exists(self.dataPath / path):
|
|
238
|
-
localModded = (self.dataPath / path).stat().st_mtime
|
|
239
|
-
if localModded >= dumpModded and url != SHIPS_URL:
|
|
240
|
-
tdenv.DEBUG0("'{}': Dump is not more recent than Local.", path)
|
|
162
|
+
self.tdenv.NOTE("Checking for update to '{}'.", path)
|
|
163
|
+
try:
|
|
164
|
+
response = openURL(url)
|
|
165
|
+
except Exception as e:
|
|
166
|
+
tdenv.WARN("Problem with download:\n URL: {}\n Error: {}", BASE_URL + str(path), str(e))
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
url_time = response.getheader("Last-Modified")
|
|
170
|
+
dumpModded = datetime.strptime(url_time, "%a, %d %b %Y %H:%M:%S %Z").timestamp()
|
|
171
|
+
|
|
172
|
+
if Path.exists(localPath):
|
|
173
|
+
localModded = localPath.stat().st_mtime
|
|
174
|
+
if localModded >= dumpModded:
|
|
175
|
+
self.tdenv.DEBUG0("'{}': Dump is not more recent than Local.", path)
|
|
241
176
|
return False
|
|
242
177
|
|
|
243
|
-
tdenv.NOTE("Downloading file '{}'.", path)
|
|
244
|
-
transfers.download(self.tdenv, url,
|
|
178
|
+
self.tdenv.NOTE("Downloading file '{}'.", path)
|
|
179
|
+
transfers.download(self.tdenv, url, localPath)
|
|
245
180
|
return True
|
|
246
181
|
|
|
247
|
-
def importUpgrades(self):
|
|
248
|
-
"""
|
|
249
|
-
Populate the Upgrade table using modules.json
|
|
250
|
-
Writes directly to database.
|
|
251
|
-
"""
|
|
252
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
253
|
-
|
|
254
|
-
tdenv.NOTE("Processing Upgrades: Start time = {}", self.now())
|
|
255
|
-
with open(str(self.dataPath / self.upgradesPath), "r") as fh:
|
|
256
|
-
upgrades = json.load(fh)
|
|
257
|
-
for upgrade in iter(upgrades):
|
|
258
|
-
upgrade_id = upgrade['id']
|
|
259
|
-
name = upgrade['name'] if upgrade['name'] else upgrade['ed_symbol'].replace('_', ' ')
|
|
260
|
-
weight = upgrade['mass'] if 'mass' in upgrade else 0
|
|
261
|
-
cost = upgrade['price'] if upgrade['price'] else 0
|
|
262
|
-
|
|
263
|
-
tdenv.DEBUG1("Updating: {}, {}, {}, {}", upgrade_id, name, weight, cost)
|
|
264
|
-
try:
|
|
265
|
-
self.execute("""INSERT INTO Upgrade
|
|
266
|
-
( upgrade_id,name,weight,cost ) VALUES
|
|
267
|
-
( ?, ?, ?, ? ) """,
|
|
268
|
-
(upgrade_id, name, weight, cost))
|
|
269
|
-
except sqlite3.IntegrityError:
|
|
270
|
-
try:
|
|
271
|
-
self.execute("""UPDATE Upgrade
|
|
272
|
-
SET name = ?,weight = ?,cost = ?
|
|
273
|
-
WHERE upgrade_id = ?""",
|
|
274
|
-
(name, weight, cost,
|
|
275
|
-
upgrade_id))
|
|
276
|
-
except sqlite3.IntegrityError:
|
|
277
|
-
tdenv.DEBUG0("Unable to insert or update: {}, {}, {}, {}", upgrade_id, name, weight, cost)
|
|
278
|
-
|
|
279
|
-
self.updated['Upgrade'] = True
|
|
280
|
-
|
|
281
|
-
tdenv.NOTE("Finished processing Upgrades. End time = {}", self.now())
|
|
282
|
-
|
|
283
|
-
def importShips(self):
|
|
284
|
-
"""
|
|
285
|
-
Populate the Ship table using coriolis.io's index.json
|
|
286
|
-
Writes directly to database.
|
|
287
|
-
"""
|
|
288
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
289
|
-
|
|
290
|
-
tdenv.NOTE("Processing Ships: Start time = {}", self.now())
|
|
291
|
-
with open(str(self.dataPath / self.shipsPath), "r") as fh:
|
|
292
|
-
ships = json.load(fh)['Ships']
|
|
293
|
-
for ship in iter(ships):
|
|
294
|
-
ship_id = ships[ship]['eddbID']
|
|
295
|
-
name = ships[ship]['properties']['name']
|
|
296
|
-
cost = ships[ship]['retailCost']
|
|
297
|
-
fdev_id = ships[ship]['edID']
|
|
298
|
-
# Arg. Why you do this to me, EDCD?
|
|
299
|
-
if "Phantom" in name and ship_id == 35:
|
|
300
|
-
ship_id = 37
|
|
301
|
-
# Change the names to match how they appear in Stations.jsonl
|
|
302
|
-
if name == "Eagle":
|
|
303
|
-
name = "Eagle Mk. II"
|
|
304
|
-
if name == "Sidewinder":
|
|
305
|
-
name = "Sidewinder Mk. I"
|
|
306
|
-
if name == "Viper":
|
|
307
|
-
name = "Viper Mk. III"
|
|
308
|
-
|
|
309
|
-
# Make sure all the 'Mark N' ship names abbreviate 'Mark' the same.
|
|
310
|
-
# Fix capitalization.
|
|
311
|
-
name = name.replace('MK', 'Mk').replace('mk', 'Mk').replace('mK', 'Mk')
|
|
312
|
-
# Fix no '.' in abbreviation.
|
|
313
|
-
if "Mk" in name and "Mk." not in name:
|
|
314
|
-
name = name.replace('Mk', 'Mk.')
|
|
315
|
-
# Fix no trailing space.
|
|
316
|
-
if "Mk." in name and "Mk. " not in name:
|
|
317
|
-
name = name.replace("Mk.", "Mk. ")
|
|
318
|
-
# Fix no leading space.
|
|
319
|
-
if "Mk." in name and " Mk." not in name:
|
|
320
|
-
name = name.replace("Mk.", " Mk.")
|
|
321
|
-
|
|
322
|
-
tdenv.DEBUG1("Updating: {}, {}, {}, {}", ship_id, name, cost, fdev_id)
|
|
323
|
-
try:
|
|
324
|
-
self.execute("""INSERT INTO Ship
|
|
325
|
-
( ship_id,name,cost,fdev_id ) VALUES
|
|
326
|
-
( ?, ?, ?, ? ) """,
|
|
327
|
-
(ship_id, name, cost, fdev_id))
|
|
328
|
-
except sqlite3.IntegrityError:
|
|
329
|
-
try:
|
|
330
|
-
self.execute("""UPDATE Ship
|
|
331
|
-
SET name = ?,cost = ?,fdev_id = ?
|
|
332
|
-
WHERE ship_id = ?""",
|
|
333
|
-
(name, cost, fdev_id,
|
|
334
|
-
ship_id))
|
|
335
|
-
except sqlite3.IntegrityError:
|
|
336
|
-
tdenv.DEBUG0("Unable to insert or update: {}, {}, {}, {}", ship_id, name, cost, fdev_id)
|
|
337
|
-
|
|
338
|
-
self.updated['Ship'] = True
|
|
339
|
-
|
|
340
|
-
tdenv.NOTE("Finished processing Ships. End time = {}", self.now())
|
|
341
|
-
|
|
342
|
-
def importSystems(self):
|
|
343
|
-
"""
|
|
344
|
-
Populate the System table using systems_populated.jsonl
|
|
345
|
-
and either systems.csv or systems_recent.csv
|
|
346
|
-
Writes directly to database.
|
|
347
|
-
"""
|
|
348
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
349
|
-
|
|
350
|
-
tdenv.NOTE("Processing Systems: Start time = {}", self.now())
|
|
351
|
-
|
|
352
|
-
total = 1
|
|
353
|
-
|
|
354
|
-
with open(str(self.dataPath / self.sysPopPath), "r", encoding = "utf-8", errors = 'ignore') as f:
|
|
355
|
-
total += (sum(bl.count("\n") for bl in self.blocks(f)))
|
|
356
|
-
|
|
357
|
-
with open(str(self.dataPath / self.sysPopPath), "r") as fh:
|
|
358
|
-
prog = pbar.Progress(total, 50)
|
|
359
|
-
for line in fh:
|
|
360
|
-
prog.increment(1, postfix = lambda value, goal: " " + str(round(value / total * 100)) + "%")
|
|
361
|
-
system = json.loads(line)
|
|
362
|
-
system_id = system['id']
|
|
363
|
-
name = system['name']
|
|
364
|
-
pos_x = system['x']
|
|
365
|
-
pos_y = system['y']
|
|
366
|
-
pos_z = system['z']
|
|
367
|
-
modified = datetime.datetime.utcfromtimestamp(system['updated_at']).strftime('%Y-%m-%d %H:%M:%S')
|
|
368
|
-
|
|
369
|
-
result = self.execute("SELECT modified FROM System WHERE system_id = ?", (system_id,)).fetchone()
|
|
370
|
-
if result:
|
|
371
|
-
updated = timegm(datetime.datetime.strptime(result[0].split('.')[0], '%Y-%m-%d %H:%M:%S').timetuple())
|
|
372
|
-
if system['updated_at'] > updated:
|
|
373
|
-
tdenv.DEBUG0("System '{}' has been updated: '{}' vs '{}'", name, modified, result[0])
|
|
374
|
-
tdenv.DEBUG1("Updating: {}, {}, {}, {}, {}, {}", system_id, name, pos_x, pos_y, pos_z, modified)
|
|
375
|
-
self.execute("""UPDATE System
|
|
376
|
-
SET name = ?,pos_x = ?,pos_y = ?,pos_z = ?,modified = ?
|
|
377
|
-
WHERE system_id = ?""",
|
|
378
|
-
(name, pos_x, pos_y, pos_z, modified,
|
|
379
|
-
system_id))
|
|
380
|
-
self.updated['System'] = True
|
|
381
|
-
else:
|
|
382
|
-
tdenv.DEBUG0("System '{}' has been added.", name)
|
|
383
|
-
tdenv.DEBUG1("Inserting: {}, {}, {}, {}, {}, {}", system_id, name, pos_x, pos_y, pos_z, modified)
|
|
384
|
-
self.execute("""INSERT INTO System
|
|
385
|
-
( system_id,name,pos_x,pos_y,pos_z,modified ) VALUES
|
|
386
|
-
( ?, ?, ?, ?, ?, ? ) """,
|
|
387
|
-
(system_id, name, pos_x, pos_y, pos_z, modified))
|
|
388
|
-
self.updated['System'] = True
|
|
389
|
-
while prog.value < prog.maxValue:
|
|
390
|
-
prog.increment(1, postfix = lambda value, goal: " " + str(round(value / total * 100)) + "%")
|
|
391
|
-
prog.clear()
|
|
392
|
-
|
|
393
|
-
tdenv.NOTE("Finished processing Systems. End time = {}", self.now())
|
|
394
|
-
|
|
395
|
-
def importAllSystems(self, source):
|
|
396
|
-
"""
|
|
397
|
-
Populate the System table using systems_populated.jsonl
|
|
398
|
-
and either systems.csv or systems_recent.csv
|
|
399
|
-
Writes directly to database.
|
|
400
|
-
"""
|
|
401
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
402
|
-
|
|
403
|
-
tdenv.NOTE("Processing Systems in {}: Start time = {}", str(source), self.now())
|
|
404
|
-
|
|
405
|
-
total = 1
|
|
406
|
-
|
|
407
|
-
with open(str(self.dataPath / source), "r", encoding = "utf-8", errors = 'ignore') as f:
|
|
408
|
-
total += (sum(bl.count("\n") for bl in self.blocks(f)))
|
|
409
|
-
|
|
410
|
-
with open(str(self.dataPath / source), "r") as fh:
|
|
411
|
-
sysDict = csv.DictReader(fh)
|
|
412
|
-
prog = pbar.Progress(total, 50)
|
|
413
|
-
for system in sysDict:
|
|
414
|
-
prog.increment(1, postfix = lambda value, goal: " " + str(round(value / total * 100)) + "%")
|
|
415
|
-
system_id = system['id']
|
|
416
|
-
name = system['name']
|
|
417
|
-
pos_x = system['x']
|
|
418
|
-
pos_y = system['y']
|
|
419
|
-
pos_z = system['z']
|
|
420
|
-
modified = datetime.datetime.utcfromtimestamp(int(system['updated_at'])).strftime('%Y-%m-%d %H:%M:%S')
|
|
421
|
-
|
|
422
|
-
result = self.execute("SELECT modified FROM System WHERE system_id = ?", (system_id,)).fetchone()
|
|
423
|
-
if result:
|
|
424
|
-
updated = timegm(datetime.datetime.strptime(result[0].split('.')[0], '%Y-%m-%d %H:%M:%S').timetuple())
|
|
425
|
-
if int(system['updated_at']) > updated:
|
|
426
|
-
tdenv.DEBUG0("System '{}' has been updated: '{}' vs '{}'", name, modified, result[0])
|
|
427
|
-
tdenv.DEBUG1("Updating: {}, {}, {}, {}, {}, {}", system_id, name, pos_x, pos_y, pos_z, modified)
|
|
428
|
-
self.execute("""UPDATE System
|
|
429
|
-
SET name = ?,pos_x = ?,pos_y = ?,pos_z = ?,modified = ?
|
|
430
|
-
WHERE system_id = ?""",
|
|
431
|
-
(name, pos_x, pos_y, pos_z, modified,
|
|
432
|
-
system_id))
|
|
433
|
-
self.updated['System'] = True
|
|
434
|
-
else:
|
|
435
|
-
tdenv.DEBUG0("System '{}' has been added.", name)
|
|
436
|
-
tdenv.DEBUG1("Inserting: {}, {}, {}, {}, {}, {}", system_id, name, pos_x, pos_y, pos_z, modified)
|
|
437
|
-
self.execute("""INSERT INTO System
|
|
438
|
-
( system_id,name,pos_x,pos_y,pos_z,modified ) VALUES
|
|
439
|
-
( ?, ?, ?, ?, ?, ? ) """,
|
|
440
|
-
(system_id, name, pos_x, pos_y, pos_z, modified))
|
|
441
|
-
self.updated['System'] = True
|
|
442
|
-
while prog.value < prog.maxValue:
|
|
443
|
-
prog.increment(1, postfix = lambda value, goal: " " + str(round(value / total * 100)) + "%")
|
|
444
|
-
prog.clear()
|
|
445
|
-
|
|
446
|
-
tdenv.NOTE("Finished processing Systems. End time = {}", self.now())
|
|
447
|
-
|
|
448
182
|
def purgeSystems(self):
|
|
449
183
|
"""
|
|
450
184
|
Purges systems from the System table that do not have any stations claiming to be in them.
|
|
451
185
|
Keeps table from becoming too large because of fleet carriers moving to unpopulated systems.
|
|
452
186
|
"""
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
187
|
+
|
|
188
|
+
self.tdenv.NOTE("Purging Systems with no stations: Start time = {}", self.now())
|
|
189
|
+
|
|
457
190
|
self.execute("PRAGMA foreign_keys = OFF")
|
|
458
|
-
|
|
191
|
+
|
|
459
192
|
print("Saving systems with stations.... " + str(self.now()) + "\t\t\t\t", end="\r")
|
|
460
193
|
self.execute("DROP TABLE IF EXISTS System_copy")
|
|
461
194
|
self.execute("""CREATE TABLE System_copy AS SELECT * FROM System
|
|
462
195
|
WHERE system_id IN (SELECT system_id FROM Station)
|
|
463
196
|
""")
|
|
464
|
-
|
|
197
|
+
|
|
465
198
|
print("Erasing table and reinserting kept systems.... " + str(self.now()) + "\t\t\t\t", end="\r")
|
|
466
199
|
self.execute("DELETE FROM System")
|
|
467
200
|
self.execute("INSERT INTO System SELECT * FROM System_copy")
|
|
468
|
-
|
|
201
|
+
|
|
469
202
|
print("Removing copy.... " + str(self.now()) + "\t\t\t\t", end="\r")
|
|
470
203
|
self.execute("PRAGMA foreign_keys = ON")
|
|
471
204
|
self.execute("DROP TABLE IF EXISTS System_copy")
|
|
472
|
-
|
|
473
|
-
tdenv.NOTE("Finished purging Systems. End time = {}", self.now())
|
|
474
|
-
|
|
475
|
-
def importStations(self):
|
|
476
|
-
"""
|
|
477
|
-
Populate the Station table using stations.jsonl
|
|
478
|
-
Also populates the ShipVendor table if the option is set.
|
|
479
|
-
Writes directly to database.
|
|
480
|
-
"""
|
|
481
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
482
|
-
|
|
483
|
-
tdenv.NOTE("Processing Stations, this may take a bit: Start time = {}", self.now())
|
|
484
|
-
if self.getOption('shipvend'):
|
|
485
|
-
tdenv.NOTE("Simultaneously processing ShipVendors.")
|
|
486
|
-
|
|
487
|
-
if self.getOption('upvend'):
|
|
488
|
-
tdenv.NOTE("Simultaneously processing UpgradeVendors, this will take quite a while.")
|
|
489
|
-
|
|
490
|
-
total = 1
|
|
491
|
-
|
|
492
|
-
with open(str(self.dataPath / self.stationsPath), "r", encoding = "utf-8", errors = 'ignore') as f:
|
|
493
|
-
total += (sum(bl.count("\n") for bl in self.blocks(f)))
|
|
494
|
-
|
|
495
|
-
with open(str(self.dataPath / self.stationsPath), "r") as fh:
|
|
496
|
-
prog = pbar.Progress(total, 50)
|
|
497
|
-
for line in fh:
|
|
498
|
-
prog.increment(1, postfix = lambda value, goal: " " + str(round(value / total * 100)) + "%")
|
|
499
|
-
station = json.loads(line)
|
|
500
|
-
|
|
501
|
-
# Import Stations
|
|
502
|
-
station_id = station['id']
|
|
503
|
-
name = station['name']
|
|
504
|
-
system_id = station['system_id']
|
|
505
|
-
ls_from_star = station['distance_to_star'] if station['distance_to_star'] else 0
|
|
506
|
-
blackmarket = 'Y' if station['has_blackmarket'] else 'N'
|
|
507
|
-
max_pad_size = station['max_landing_pad_size'] if station['max_landing_pad_size'] and station['max_landing_pad_size'] != 'None' else '?'
|
|
508
|
-
market = 'Y' if station['has_market'] else 'N'
|
|
509
|
-
shipyard = 'Y' if station['has_shipyard'] else 'N'
|
|
510
|
-
modified = datetime.datetime.utcfromtimestamp(station['updated_at']).strftime('%Y-%m-%d %H:%M:%S')
|
|
511
|
-
outfitting = 'Y' if station['has_outfitting'] else 'N'
|
|
512
|
-
rearm = 'Y' if station['has_rearm'] else 'N'
|
|
513
|
-
refuel = 'Y' if station['has_refuel'] else 'N'
|
|
514
|
-
repair = 'Y' if station['has_repair'] else 'N'
|
|
515
|
-
planetary = 'Y' if station['is_planetary'] else 'N'
|
|
516
|
-
type_id = station['type_id'] if station['type_id'] else 0
|
|
517
|
-
|
|
518
|
-
systemList = self.execute("SELECT System.name FROM System WHERE System.system_id = ?", (system_id,)).fetchone()
|
|
519
|
-
if systemList:
|
|
520
|
-
system = systemList[0].upper()
|
|
521
|
-
else:
|
|
522
|
-
system = "Unknown Space"
|
|
523
|
-
self.execute("""INSERT INTO System
|
|
524
|
-
( system_id,name,pos_x,pos_y,pos_z,modified ) VALUES
|
|
525
|
-
( ?, ?, ?, ?, ?, ? ) """,
|
|
526
|
-
(system_id, system, 0, 0, 0, modified))
|
|
527
|
-
self.updated['System'] = True
|
|
528
|
-
|
|
529
|
-
result = self.execute("SELECT modified FROM Station WHERE station_id = ?", (station_id,)).fetchone()
|
|
530
|
-
if result:
|
|
531
|
-
updated = timegm(datetime.datetime.strptime(result[0].split('.')[0], '%Y-%m-%d %H:%M:%S').timetuple())
|
|
532
|
-
if station['updated_at'] > updated:
|
|
533
|
-
tdenv.DEBUG0("{}/{} has been updated: {} vs {}",
|
|
534
|
-
system , name, modified, result[0])
|
|
535
|
-
tdenv.DEBUG1("Updating: {}, {}, {}, {}, {}, {}, {},"
|
|
536
|
-
" {}, {}, {}, {}, {}, {}, {}, {}",
|
|
537
|
-
station_id, name, system_id, ls_from_star, blackmarket,
|
|
538
|
-
max_pad_size, market, shipyard, modified, outfitting,
|
|
539
|
-
rearm, refuel, repair, planetary, type_id)
|
|
540
|
-
self.execute("""UPDATE Station
|
|
541
|
-
SET name = ?, system_id = ?, ls_from_star = ?, blackmarket = ?,
|
|
542
|
-
max_pad_size = ?, market = ?, shipyard = ?, modified = ?,
|
|
543
|
-
outfitting = ?, rearm = ?, refuel = ?, repair = ?, planetary = ?, type_id = ?
|
|
544
|
-
WHERE station_id = ?""",
|
|
545
|
-
(name, system_id, ls_from_star, blackmarket,
|
|
546
|
-
max_pad_size, market, shipyard, modified,
|
|
547
|
-
outfitting, rearm, refuel, repair, planetary, type_id,
|
|
548
|
-
station_id))
|
|
549
|
-
self.updated['Station'] = True
|
|
550
|
-
else:
|
|
551
|
-
tdenv.DEBUG0("{}/{} has been added:", system , name)
|
|
552
|
-
tdenv.DEBUG1("Inserting: {}, {}, {}, {}, {}, {}, {},"
|
|
553
|
-
" {}, {}, {}, {}, {}, {}, {}, {}",
|
|
554
|
-
station_id, name, system_id, ls_from_star, blackmarket,
|
|
555
|
-
max_pad_size, market, shipyard, modified, outfitting,
|
|
556
|
-
rearm, refuel, repair, planetary, type_id)
|
|
557
|
-
self.execute("""INSERT INTO Station (
|
|
558
|
-
station_id,name,system_id,ls_from_star,
|
|
559
|
-
blackmarket,max_pad_size,market,shipyard,
|
|
560
|
-
modified,outfitting,rearm,refuel,
|
|
561
|
-
repair,planetary,type_id ) VALUES
|
|
562
|
-
( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) """,
|
|
563
|
-
(station_id, name, system_id, ls_from_star,
|
|
564
|
-
blackmarket, max_pad_size, market, shipyard,
|
|
565
|
-
modified, outfitting, rearm, refuel,
|
|
566
|
-
repair, planetary, type_id))
|
|
567
|
-
self.updated['Station'] = True
|
|
568
|
-
|
|
569
|
-
# Import shipyards into ShipVendors if shipvend is set.
|
|
570
|
-
if station['has_shipyard'] and self.getOption('shipvend'):
|
|
571
|
-
if not station['shipyard_updated_at']:
|
|
572
|
-
station['shipyard_updated_at'] = station['updated_at']
|
|
573
|
-
modified = datetime.datetime.utcfromtimestamp(station['shipyard_updated_at']).strftime('%Y-%m-%d %H:%M:%S')
|
|
574
|
-
result = self.execute("SELECT modified FROM ShipVendor WHERE station_id = ?", (station_id,)).fetchone()
|
|
575
|
-
if result:
|
|
576
|
-
updated = timegm(datetime.datetime.strptime(result[0].split('.')[0], '%Y-%m-%d %H:%M:%S').timetuple())
|
|
577
|
-
else:
|
|
578
|
-
updated = 0
|
|
579
|
-
if station['shipyard_updated_at'] > updated:
|
|
580
|
-
self.execute("DELETE FROM ShipVendor WHERE station_id = ?", (station_id,))
|
|
581
|
-
tdenv.DEBUG1("{}/{} has shipyard, updating ships sold.", system, name)
|
|
582
|
-
for ship in station['selling_ships']:
|
|
583
|
-
# Make sure all the 'Mark N' ship names abbreviate 'Mark' as '<Name> Mk. <Number>'.
|
|
584
|
-
# Fix capitalization.
|
|
585
|
-
ship = ship.replace('MK', 'Mk').replace('mk', 'Mk').replace('mK', 'Mk')
|
|
586
|
-
# Fix no '.' in abbreviation.
|
|
587
|
-
if "Mk" in ship and "Mk." not in ship:
|
|
588
|
-
ship = ship.replace('Mk', 'Mk.')
|
|
589
|
-
# Fix no trailing space.
|
|
590
|
-
if "Mk." in ship and "Mk. " not in ship:
|
|
591
|
-
ship = ship.replace("Mk.", "Mk. ")
|
|
592
|
-
# Fix no leading space.
|
|
593
|
-
if "Mk." in ship and " Mk." not in ship:
|
|
594
|
-
ship = ship.replace("Mk.", " Mk.")
|
|
595
|
-
|
|
596
|
-
tdenv.DEBUG2("ship_id:{},station_id:{},modified:{}",
|
|
597
|
-
ship,
|
|
598
|
-
station_id,
|
|
599
|
-
modified)
|
|
600
|
-
try:
|
|
601
|
-
self.execute("""INSERT INTO ShipVendor
|
|
602
|
-
( ship_id,station_id,modified ) VALUES
|
|
603
|
-
( (SELECT Ship.ship_id FROM Ship WHERE Ship.name = ?), ?, ? ) """,
|
|
604
|
-
(ship,
|
|
605
|
-
station_id,
|
|
606
|
-
modified))
|
|
607
|
-
except sqlite3.IntegrityError:
|
|
608
|
-
continue
|
|
609
|
-
self.updated['ShipVendor'] = True
|
|
610
|
-
|
|
611
|
-
# Import Outfitters into UpgradeVendors if upvend is set.
|
|
612
|
-
if station['has_outfitting'] and self.getOption('upvend'):
|
|
613
|
-
if not station['outfitting_updated_at']:
|
|
614
|
-
station['outfitting_updated_at'] = station['updated_at']
|
|
615
|
-
modified = datetime.datetime.utcfromtimestamp(station['outfitting_updated_at']).strftime('%Y-%m-%d %H:%M:%S')
|
|
616
|
-
result = self.execute("SELECT modified FROM UpgradeVendor WHERE station_id = ?", (station_id,)).fetchone()
|
|
617
|
-
if result:
|
|
618
|
-
updated = timegm(datetime.datetime.strptime(result[0].split('.')[0], '%Y-%m-%d %H:%M:%S').timetuple())
|
|
619
|
-
else:
|
|
620
|
-
updated = 0
|
|
621
|
-
if station['outfitting_updated_at'] > updated:
|
|
622
|
-
self.execute("DELETE FROM UpgradeVendor WHERE station_id = ?", (station_id,))
|
|
623
|
-
tdenv.DEBUG1("{}/{} has outfitting, updating modules sold.", system, name)
|
|
624
|
-
for upgrade in station['selling_modules']:
|
|
625
|
-
tdenv.DEBUG2("upgrade_id:{},station_id:{},modified:{}",
|
|
626
|
-
upgrade,
|
|
627
|
-
station['id'],
|
|
628
|
-
modified)
|
|
629
|
-
try:
|
|
630
|
-
self.execute("""INSERT INTO UpgradeVendor
|
|
631
|
-
( upgrade_id,station_id,cost,modified ) VALUES
|
|
632
|
-
( ?, ?, (SELECT Upgrade.cost FROM Upgrade WHERE Upgrade.upgrade_id = ?), ? ) """,
|
|
633
|
-
(upgrade,
|
|
634
|
-
station_id,
|
|
635
|
-
upgrade,
|
|
636
|
-
modified))
|
|
637
|
-
except sqlite3.IntegrityError:
|
|
638
|
-
continue
|
|
639
|
-
self.updated['UpgradeVendor'] = True
|
|
640
|
-
while prog.value < prog.maxValue:
|
|
641
|
-
prog.increment(1, postfix = lambda value, goal: " " + str(round(value / total * 100)) + "%")
|
|
642
|
-
prog.clear()
|
|
643
|
-
|
|
644
|
-
tdenv.NOTE("Finished processing Stations. End time = {}", self.now())
|
|
645
|
-
|
|
646
|
-
def importCommodities(self):
|
|
647
|
-
"""
|
|
648
|
-
Populate the Category, and Item tables using commodities.json
|
|
649
|
-
Writes directly to the database.
|
|
650
|
-
"""
|
|
651
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
652
|
-
|
|
653
|
-
tdenv.NOTE("Processing Categories and Items: Start time = {}", self.now())
|
|
654
|
-
with open(str(self.dataPath / self.commoditiesPath), "r") as fh:
|
|
655
|
-
commodities = json.load(fh)
|
|
656
|
-
|
|
657
|
-
# EDDB still hasn't added these Commodities to the API,
|
|
658
|
-
# so we'll add them ourselves.
|
|
659
|
-
tdenv.NOTE("Checking for missing items....")
|
|
660
|
-
|
|
661
|
-
# Need to get the category_ids from the .csv file.
|
|
662
|
-
cat_ids = dict()
|
|
663
|
-
try:
|
|
664
|
-
with open(str(tdb.dataPath / Path("Category.csv")), "r") as fh:
|
|
665
|
-
cats = csv.DictReader(fh, quotechar = "'")
|
|
666
|
-
for cat in cats:
|
|
667
|
-
cat_ids[cat['name']] = int(cat['unq:category_id'])
|
|
668
|
-
# Use default if no file, such as on a 'clean' run.
|
|
669
|
-
except FileNotFoundError:
|
|
670
|
-
cat_ids = {'Chemicals':1, 'Consumer Items':2, 'Legal Drugs':3, 'Foods':4, 'Industrial Materials':5,
|
|
671
|
-
'Machinery':6, 'Medicines':7, 'Metals':8, 'Minerals':9, 'Slavery':10, 'Technology':11,
|
|
672
|
-
'Textiles':12, 'Waste':13, 'Weapons':14, 'Unknown':15, 'Salvage':16}
|
|
673
|
-
|
|
674
|
-
# EDCD is really quick about getting new items updated, so we'll use its item list to check
|
|
675
|
-
# for missing items in EDDB.io's list.
|
|
676
|
-
edcd_source = 'https://raw.githubusercontent.com/EDCD/FDevIDs/master/commodity.csv'
|
|
677
|
-
edcd_csv = request_url(edcd_source)
|
|
678
|
-
edcd_dict = csv.DictReader(codecs.iterdecode(edcd_csv, 'utf-8'))
|
|
679
|
-
|
|
680
|
-
def blankItem(name, ed_id, category, category_id):
|
|
681
|
-
return {"id":ed_id, "name":name, "category_id":category_id, "average_price":None, "is_rare":0,
|
|
682
|
-
"max_buy_price":None, "max_sell_price":None, "min_buy_price":None, "min_sell_price":None,
|
|
683
|
-
"buy_price_lower_average":0, "sell_price_upper_average":0, "is_non_marketable":0, "ed_id":ed_id,
|
|
684
|
-
"category":{"id":category_id, "name":category}}
|
|
685
|
-
|
|
686
|
-
for line in iter(edcd_dict):
|
|
687
|
-
if not any(c.get('ed_id', None) == int(line['id']) for c in commodities):
|
|
688
|
-
tdenv.DEBUG0("'{}' with fdev_id {} not found, adding.", line['name'], line['id'])
|
|
689
|
-
commodities.append(blankItem(line['name'], line['id'], line['category'], cat_ids[line['category']]))
|
|
690
|
-
|
|
691
|
-
tdenv.NOTE("Missing item check complete.")
|
|
692
|
-
|
|
693
|
-
# Prep-work for checking if an item's item_id has changed.
|
|
694
|
-
cur_ids = dict()
|
|
695
|
-
result = self.execute("SELECT fdev_id,item_id FROM Item ORDER BY fdev_id").fetchall()
|
|
696
|
-
for item in result:
|
|
697
|
-
cur_ids[item[0]] = item[1]
|
|
698
|
-
|
|
699
|
-
tdenv.DEBUG0("Beginning loop.")
|
|
700
|
-
for commodity in iter(commodities):
|
|
701
|
-
# Make sure the broken item(s) in EDDB.io's API isn't imported.
|
|
702
|
-
if not commodity['ed_id']:
|
|
703
|
-
tdenv.DEBUG0("Skipping faulty item: {}:{}" , commodity['id'], commodity['name'])
|
|
704
|
-
continue
|
|
705
|
-
# Get the categories from the json and place them into the Category table.
|
|
706
|
-
category_id = commodity['category']['id']
|
|
707
|
-
category_name = commodity['category']['name']
|
|
708
|
-
|
|
709
|
-
tdenv.DEBUG1("Updating: {}, {}", category_id, category_name)
|
|
710
|
-
try:
|
|
711
|
-
self.execute("""INSERT INTO Category
|
|
712
|
-
( category_id, name ) VALUES
|
|
713
|
-
( ?, ? ) """,
|
|
714
|
-
(category_id, category_name))
|
|
715
|
-
except sqlite3.IntegrityError:
|
|
716
|
-
try:
|
|
717
|
-
self.execute("""UPDATE Category
|
|
718
|
-
SET name = ?
|
|
719
|
-
WHERE category_id = ?""",
|
|
720
|
-
(category_name, category_id))
|
|
721
|
-
|
|
722
|
-
except sqlite3.IntegrityError:
|
|
723
|
-
tdenv.DEBUG0("Unable to insert or update: {}, {}", category_id, category_name)
|
|
724
|
-
|
|
725
|
-
item_id = commodity['id']
|
|
726
|
-
name = commodity['name']
|
|
727
|
-
if name.lower() == 'salvageable wreckage':
|
|
728
|
-
name = 'Wreckage Components'
|
|
729
|
-
if name.lower() == 'political prisoner':
|
|
730
|
-
name = 'Political Prisoners'
|
|
731
|
-
if name.lower() == 'hostage':
|
|
732
|
-
name = 'Hostages'
|
|
733
|
-
if name.lower() == 'methanol monohydrate':
|
|
734
|
-
name = 'Methanol Monohydrate Crystals'
|
|
735
|
-
if name.lower() == 'occupied cryopod':
|
|
736
|
-
name = 'Occupied Escape Pod'
|
|
737
|
-
category_id = commodity['category_id']
|
|
738
|
-
avg_price = commodity['average_price']
|
|
739
|
-
fdev_id = commodity['ed_id']
|
|
740
|
-
# "ui_order" doesn't have an equivalent field in the json.
|
|
741
|
-
|
|
742
|
-
tdenv.DEBUG1("Updating: {}, {}, {}, {}, {}", item_id, name, category_id, avg_price, fdev_id)
|
|
743
|
-
|
|
744
|
-
# If the item_id has changed, we need to completely delete the old entry.
|
|
745
|
-
if cur_ids.get(fdev_id) != item_id:
|
|
746
|
-
tdenv.DEBUG1("Did not match item_id:{} with fdev_id:{} -- {}", item_id, fdev_id, cur_ids.get(fdev_id))
|
|
747
|
-
if cur_ids.get(fdev_id):
|
|
748
|
-
tdenv.DEBUG0("item_id for '{}' has changed, updating.", name)
|
|
749
|
-
self.execute("DELETE FROM Item where fdev_id = ?", (fdev_id,))
|
|
750
|
-
|
|
751
|
-
try:
|
|
752
|
-
self.execute("""INSERT INTO Item
|
|
753
|
-
(item_id,name,category_id,avg_price,fdev_id) VALUES
|
|
754
|
-
( ?, ?, ?, ?, ? )""",
|
|
755
|
-
(item_id, name, category_id, avg_price, fdev_id))
|
|
756
|
-
except sqlite3.IntegrityError:
|
|
757
|
-
try:
|
|
758
|
-
self.execute("""UPDATE Item
|
|
759
|
-
SET name = ?,category_id = ?,avg_price = ?,fdev_id = ?
|
|
760
|
-
WHERE item_id = ?""",
|
|
761
|
-
(name, category_id, avg_price, fdev_id, item_id))
|
|
762
|
-
except sqlite3.IntegrityError:
|
|
763
|
-
tdenv.DEBUG0("Unable to insert or update: {}, {}, {}, {}, {}", item_id, name, category_id, avg_price, fdev_id)
|
|
764
|
-
|
|
765
|
-
# The items aren't in the same order in the json as they are in the game's UI.
|
|
766
|
-
# This creates a temporary object that has all the items sorted first
|
|
767
|
-
# by category and second by name, as in the UI, which will then be used to
|
|
768
|
-
# update the entries in the database with the correct "ui_order" value.
|
|
769
|
-
temp = self.execute("""SELECT
|
|
770
|
-
name, category_id, fdev_id
|
|
771
|
-
FROM Item
|
|
772
|
-
ORDER BY category_id, name
|
|
773
|
-
""")
|
|
774
|
-
cat_id = 0
|
|
775
|
-
ui_order = 1
|
|
776
|
-
tdenv.DEBUG0("Adding ui_order data to items.")
|
|
777
|
-
for line in temp:
|
|
778
|
-
if line[1] != cat_id:
|
|
779
|
-
ui_order = 1
|
|
780
|
-
cat_id = line[1]
|
|
781
|
-
else:
|
|
782
|
-
ui_order += 1
|
|
783
|
-
self.execute("""UPDATE Item
|
|
784
|
-
set ui_order = ?
|
|
785
|
-
WHERE fdev_id = ?""",
|
|
786
|
-
(ui_order, line[2]))
|
|
787
|
-
|
|
788
|
-
self.updated['Category'] = True
|
|
789
|
-
self.updated['Item'] = True
|
|
790
|
-
|
|
791
|
-
tdenv.NOTE("Finished processing Categories and Items. End time = {}", self.now())
|
|
792
205
|
|
|
793
|
-
|
|
794
|
-
for table in [
|
|
795
|
-
"Category",
|
|
796
|
-
"Item",
|
|
797
|
-
"RareItem",
|
|
798
|
-
"Ship",
|
|
799
|
-
"ShipVendor",
|
|
800
|
-
"Station",
|
|
801
|
-
"System",
|
|
802
|
-
"Upgrade",
|
|
803
|
-
"UpgradeVendor",
|
|
804
|
-
]:
|
|
805
|
-
if self.updated[table]:
|
|
806
|
-
_, path = csvexport.exportTableToFile(
|
|
807
|
-
self.tdb, self.tdenv, table
|
|
808
|
-
)
|
|
809
|
-
self.tdenv.NOTE("{} exported.", path)
|
|
206
|
+
self.tdenv.NOTE("Finished purging Systems. End time = {}", self.now())
|
|
810
207
|
|
|
811
208
|
def commit(self):
|
|
812
209
|
success = False
|
|
@@ -823,11 +220,10 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
823
220
|
Updates the market data (AKA the StationItem table) using listings.csv
|
|
824
221
|
Writes directly to database.
|
|
825
222
|
"""
|
|
826
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
827
223
|
|
|
828
|
-
tdenv.NOTE("Processing market data from {}: Start time = {}", listings_file, self.now())
|
|
224
|
+
self.tdenv.NOTE("Processing market data from {}: Start time = {}", listings_file, self.now())
|
|
829
225
|
if not (self.dataPath / listings_file).exists():
|
|
830
|
-
tdenv.NOTE("File not found, aborting: {}", (self.dataPath / listings_file))
|
|
226
|
+
self.tdenv.NOTE("File not found, aborting: {}", (self.dataPath / listings_file))
|
|
831
227
|
return
|
|
832
228
|
|
|
833
229
|
total = 1
|
|
@@ -927,26 +323,21 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
927
323
|
prog.increment(1, postfix = lambda value, goal: " " + str(round(value / total * 100)) + "%")
|
|
928
324
|
prog.clear()
|
|
929
325
|
|
|
930
|
-
tdenv.NOTE("Import file processing complete, updating database. {}", self.now())
|
|
326
|
+
self.tdenv.NOTE("Import file processing complete, updating database. {}", self.now())
|
|
931
327
|
if liveList:
|
|
932
|
-
tdenv.NOTE("Marking data now in the EDDB listings.csv as no longer 'live'. {}", self.now())
|
|
328
|
+
self.tdenv.NOTE("Marking data now in the EDDB listings.csv as no longer 'live'. {}", self.now())
|
|
933
329
|
self.executemany(liveStmt, liveList)
|
|
934
330
|
if delList:
|
|
935
|
-
tdenv.NOTE("Deleting old listing data. {}", self.now())
|
|
331
|
+
self.tdenv.NOTE("Deleting old listing data. {}", self.now())
|
|
936
332
|
self.executemany(delStmt, delList)
|
|
937
333
|
if listingList:
|
|
938
|
-
tdenv.NOTE("Inserting new listing data. {}", self.now())
|
|
334
|
+
self.tdenv.NOTE("Inserting new listing data. {}", self.now())
|
|
939
335
|
self.executemany(listingStmt, listingList)
|
|
940
336
|
|
|
941
337
|
self.updated['Listings'] = True
|
|
942
|
-
tdenv.NOTE("Finished processing market data. End time = {}", self.now())
|
|
338
|
+
self.tdenv.NOTE("Finished processing market data. End time = {}", self.now())
|
|
943
339
|
|
|
944
340
|
def run(self):
|
|
945
|
-
tdb, tdenv = self.tdb, self.tdenv
|
|
946
|
-
|
|
947
|
-
if self.getOption("progbar"):
|
|
948
|
-
tdenv.NOTE("The 'progbar' option has been deprecated and no longer has any function.")
|
|
949
|
-
|
|
950
341
|
# Create the /eddb folder for downloading the source files if it doesn't exist.
|
|
951
342
|
try:
|
|
952
343
|
Path(str(self.dataPath)).mkdir()
|
|
@@ -954,18 +345,19 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
954
345
|
pass
|
|
955
346
|
|
|
956
347
|
# Run 'listings' by default:
|
|
957
|
-
# If no options, or if only '
|
|
348
|
+
# If no options, or if only 'force', and/or 'skipvend',
|
|
958
349
|
# have been passed, enable 'listings'.
|
|
959
350
|
default = True
|
|
960
351
|
for option in self.options:
|
|
961
|
-
if not option in ('force', 'fallback', 'skipvend', 'progbar'):
|
|
352
|
+
# if not option in ('force', 'fallback', 'skipvend', 'progbar'):
|
|
353
|
+
if not option in ('force', 'skipvend'):
|
|
962
354
|
default = False
|
|
963
355
|
if default:
|
|
964
356
|
self.options["listings"] = True
|
|
965
357
|
|
|
966
358
|
# We can probably safely assume that the plugin has never been run if
|
|
967
359
|
# the prices file doesn't exist, since the plugin always generates it.
|
|
968
|
-
if not (tdb.dataPath / Path("TradeDangerous.prices")).exists():
|
|
360
|
+
if not (self.tdb.dataPath / Path("TradeDangerous.prices")).exists():
|
|
969
361
|
self.options["clean"] = True
|
|
970
362
|
|
|
971
363
|
if self.getOption("clean"):
|
|
@@ -981,32 +373,32 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
981
373
|
"Upgrade",
|
|
982
374
|
"UpgradeVendor",
|
|
983
375
|
]:
|
|
984
|
-
file = tdb.dataPath / Path(name + ".csv")
|
|
376
|
+
file = self.tdb.dataPath / Path(name + ".csv")
|
|
985
377
|
try:
|
|
986
378
|
os.remove(str(file))
|
|
987
379
|
except FileNotFoundError:
|
|
988
380
|
pass
|
|
989
381
|
|
|
990
382
|
try:
|
|
991
|
-
os.remove(str(tdb.dataPath) + "/TradeDangerous.db")
|
|
383
|
+
os.remove(str(self.tdb.dataPath) + "/TradeDangerous.db")
|
|
992
384
|
except FileNotFoundError:
|
|
993
385
|
pass
|
|
994
386
|
try:
|
|
995
|
-
os.remove(str(tdb.dataPath) + "/TradeDangerous.prices")
|
|
387
|
+
os.remove(str(self.tdb.dataPath) + "/TradeDangerous.prices")
|
|
996
388
|
except FileNotFoundError:
|
|
997
389
|
pass
|
|
998
390
|
|
|
999
391
|
# Because this is a clean run, we need to temporarily rename the RareItem.csv,
|
|
1000
392
|
# otherwise TD will crash trying to insert the rare items to the database,
|
|
1001
393
|
# because there's nothing in the Station table it tries to pull from.
|
|
1002
|
-
ri_path = tdb.dataPath / Path("RareItem.csv")
|
|
394
|
+
ri_path = self.tdb.dataPath / Path("RareItem.csv")
|
|
1003
395
|
rib_path = ri_path.with_suffix(".tmp")
|
|
1004
396
|
if ri_path.exists():
|
|
1005
397
|
if rib_path.exists():
|
|
1006
398
|
rib_path.unlink()
|
|
1007
399
|
ri_path.rename(rib_path)
|
|
1008
400
|
|
|
1009
|
-
tdb.reloadCache()
|
|
401
|
+
self.tdb.reloadCache()
|
|
1010
402
|
|
|
1011
403
|
# Now it's safe to move RareItems back.
|
|
1012
404
|
if ri_path.exists():
|
|
@@ -1017,18 +409,18 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
1017
409
|
self.options["all"] = True
|
|
1018
410
|
self.options["force"] = True
|
|
1019
411
|
|
|
1020
|
-
tdenv.ignoreUnknown = True
|
|
412
|
+
self.tdenv.ignoreUnknown = True
|
|
1021
413
|
|
|
1022
414
|
success = False
|
|
1023
415
|
while not success:
|
|
1024
416
|
try:
|
|
1025
|
-
tdenv.DEBUG0("Loading Database. {}", self.now())
|
|
1026
|
-
tdb.load(maxSystemLinkLy = tdenv.maxSystemLinkLy)
|
|
417
|
+
self.tdenv.DEBUG0("Loading Database. {}", self.now())
|
|
418
|
+
self.tdb.load(maxSystemLinkLy = self.tdenv.maxSystemLinkLy)
|
|
1027
419
|
success = True
|
|
1028
420
|
except sqlite3.OperationalError:
|
|
1029
421
|
print("Database is locked, waiting for access.", end = "\r")
|
|
1030
422
|
time.sleep(1)
|
|
1031
|
-
tdenv.DEBUG0("Database loaded.")
|
|
423
|
+
self.tdenv.DEBUG0("Database loaded.")
|
|
1032
424
|
|
|
1033
425
|
# Select which options will be updated
|
|
1034
426
|
if self.getOption("listings"):
|
|
@@ -1043,11 +435,18 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
1043
435
|
self.options["upgrade"] = True
|
|
1044
436
|
self.options["station"] = True
|
|
1045
437
|
|
|
438
|
+
if self.getOption['item']:
|
|
439
|
+
self.options['station'] = True
|
|
440
|
+
|
|
441
|
+
if self.getOption['rare']:
|
|
442
|
+
self.options['station'] = True
|
|
443
|
+
|
|
1046
444
|
if self.getOption("station"):
|
|
1047
445
|
self.options["system"] = True
|
|
1048
446
|
|
|
1049
447
|
if self.getOption("all"):
|
|
1050
448
|
self.options["item"] = True
|
|
449
|
+
self.options['rare'] = True
|
|
1051
450
|
self.options["ship"] = True
|
|
1052
451
|
self.options["shipvend"] = True
|
|
1053
452
|
self.options["station"] = True
|
|
@@ -1056,9 +455,6 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
1056
455
|
self.options["upvend"] = True
|
|
1057
456
|
self.options["listings"] = True
|
|
1058
457
|
|
|
1059
|
-
if self.getOption("systemrec"):
|
|
1060
|
-
self.options["purge"] = True
|
|
1061
|
-
|
|
1062
458
|
if self.getOption("solo"):
|
|
1063
459
|
self.options["listings"] = False
|
|
1064
460
|
self.options["skipvend"] = True
|
|
@@ -1068,66 +464,63 @@ class ImportPlugin(plugins.ImportPluginBase):
|
|
|
1068
464
|
self.options["upvend"] = False
|
|
1069
465
|
|
|
1070
466
|
# Download required files and update tables.
|
|
467
|
+
buildCache = False
|
|
468
|
+
if self.getOption("purge"):
|
|
469
|
+
self.purgeSystems()
|
|
470
|
+
self.commit()
|
|
471
|
+
|
|
1071
472
|
if self.getOption("upgrade"):
|
|
1072
|
-
if self.downloadFile(
|
|
1073
|
-
|
|
1074
|
-
self.commit()
|
|
473
|
+
if self.downloadFile(self.upgradesPath) or self.getOption("force"):
|
|
474
|
+
buildCache = True
|
|
1075
475
|
|
|
1076
476
|
if self.getOption("ship"):
|
|
1077
|
-
if self.downloadFile(
|
|
1078
|
-
|
|
1079
|
-
self.commit()
|
|
1080
|
-
|
|
1081
|
-
if self.getOption("systemfull"):
|
|
1082
|
-
if self.downloadFile(SYS_FULL, self.sysFullPath) or self.getOption("force"):
|
|
1083
|
-
self.importAllSystems(self.sysFullPath)
|
|
1084
|
-
self.commit()
|
|
477
|
+
if self.downloadFile(self.shipsPath) or self.getOption("force"):
|
|
478
|
+
buildCache = True
|
|
1085
479
|
|
|
1086
|
-
if self.getOption("
|
|
1087
|
-
if self.downloadFile(
|
|
1088
|
-
|
|
1089
|
-
|
|
480
|
+
if self.getOption("rare"):
|
|
481
|
+
if self.downloadFile(self.rareItemPath) or self.getOption("force"):
|
|
482
|
+
buildCache = True
|
|
483
|
+
|
|
484
|
+
if self.getOption("shipvend"):
|
|
485
|
+
if self.downloadFile(self.shipVendorPath) or self.getOption("force"):
|
|
486
|
+
buildCache = True
|
|
487
|
+
|
|
488
|
+
if self.getOption("upvend"):
|
|
489
|
+
if self.downloadFile(self.upgradeVendorPath) or self.getOption("force"):
|
|
490
|
+
buildCache = True
|
|
1090
491
|
|
|
1091
492
|
if self.getOption("system"):
|
|
1092
|
-
if self.downloadFile(
|
|
1093
|
-
|
|
1094
|
-
self.commit()
|
|
493
|
+
if self.downloadFile(self.sysPath) or self.getOption("force"):
|
|
494
|
+
buildCache = True
|
|
1095
495
|
|
|
1096
496
|
if self.getOption("station"):
|
|
1097
|
-
if self.downloadFile(
|
|
1098
|
-
|
|
1099
|
-
self.commit()
|
|
1100
|
-
|
|
1101
|
-
if self.getOption("purge"):
|
|
1102
|
-
self.purgeSystems()
|
|
1103
|
-
self.commit()
|
|
497
|
+
if self.downloadFile(self.stationsPath) or self.getOption("force"):
|
|
498
|
+
buildCache = True
|
|
1104
499
|
|
|
1105
500
|
if self.getOption("item"):
|
|
1106
|
-
if self.downloadFile(
|
|
1107
|
-
self.
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
# Remake the .csv files with the updated info.
|
|
1111
|
-
self.regenerate()
|
|
501
|
+
if self.downloadFile(self.commoditiesPath) or self.getOption("force"):
|
|
502
|
+
self.downloadFile(self.categoriesPath)
|
|
503
|
+
buildCache = True
|
|
1112
504
|
|
|
1113
|
-
#
|
|
1114
|
-
|
|
505
|
+
# Remake the .db files with the updated info.
|
|
506
|
+
if buildCache:
|
|
507
|
+
cache.buildCache(self.tdb, self.tdenv)
|
|
1115
508
|
|
|
1116
509
|
if self.getOption("listings"):
|
|
1117
|
-
if self.downloadFile(
|
|
510
|
+
if self.downloadFile(self.listingsPath) or self.getOption("force"):
|
|
1118
511
|
self.importListings(self.listingsPath)
|
|
1119
|
-
if
|
|
512
|
+
if self.downloadFile(self.liveListingsPath) or self.getOption("force"):
|
|
1120
513
|
self.importListings(self.liveListingsPath)
|
|
1121
514
|
|
|
1122
515
|
self.commit()
|
|
1123
516
|
|
|
1124
|
-
tdb.close()
|
|
517
|
+
self.tdb.close()
|
|
1125
518
|
|
|
1126
519
|
if self.updated['Listings']:
|
|
1127
|
-
tdenv.NOTE("Regenerating .prices file.")
|
|
1128
|
-
cache.regeneratePricesFile(tdb, tdenv)
|
|
520
|
+
self.tdenv.NOTE("Regenerating .prices file.")
|
|
521
|
+
cache.regeneratePricesFile(self.tdb, self.tdenv)
|
|
1129
522
|
|
|
1130
|
-
tdenv.NOTE("Import completed.")
|
|
523
|
+
self.tdenv.NOTE("Import completed.")
|
|
1131
524
|
|
|
1132
525
|
# TD doesn't need to do anything, tell it to just quit.
|
|
1133
526
|
return False
|