tradedangerous 12.7.6__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.
Files changed (87) hide show
  1. py.typed +1 -0
  2. trade.py +49 -0
  3. tradedangerous/__init__.py +43 -0
  4. tradedangerous/cache.py +1381 -0
  5. tradedangerous/cli.py +136 -0
  6. tradedangerous/commands/TEMPLATE.py +74 -0
  7. tradedangerous/commands/__init__.py +244 -0
  8. tradedangerous/commands/buildcache_cmd.py +102 -0
  9. tradedangerous/commands/buy_cmd.py +427 -0
  10. tradedangerous/commands/commandenv.py +372 -0
  11. tradedangerous/commands/exceptions.py +94 -0
  12. tradedangerous/commands/export_cmd.py +150 -0
  13. tradedangerous/commands/import_cmd.py +222 -0
  14. tradedangerous/commands/local_cmd.py +243 -0
  15. tradedangerous/commands/market_cmd.py +207 -0
  16. tradedangerous/commands/nav_cmd.py +252 -0
  17. tradedangerous/commands/olddata_cmd.py +270 -0
  18. tradedangerous/commands/parsing.py +221 -0
  19. tradedangerous/commands/rares_cmd.py +298 -0
  20. tradedangerous/commands/run_cmd.py +1521 -0
  21. tradedangerous/commands/sell_cmd.py +262 -0
  22. tradedangerous/commands/shipvendor_cmd.py +60 -0
  23. tradedangerous/commands/station_cmd.py +68 -0
  24. tradedangerous/commands/trade_cmd.py +181 -0
  25. tradedangerous/commands/update_cmd.py +67 -0
  26. tradedangerous/corrections.py +55 -0
  27. tradedangerous/csvexport.py +234 -0
  28. tradedangerous/db/__init__.py +27 -0
  29. tradedangerous/db/adapter.py +192 -0
  30. tradedangerous/db/config.py +107 -0
  31. tradedangerous/db/engine.py +259 -0
  32. tradedangerous/db/lifecycle.py +332 -0
  33. tradedangerous/db/locks.py +208 -0
  34. tradedangerous/db/orm_models.py +500 -0
  35. tradedangerous/db/paths.py +113 -0
  36. tradedangerous/db/utils.py +661 -0
  37. tradedangerous/edscupdate.py +565 -0
  38. tradedangerous/edsmupdate.py +474 -0
  39. tradedangerous/formatting.py +210 -0
  40. tradedangerous/fs.py +156 -0
  41. tradedangerous/gui.py +1146 -0
  42. tradedangerous/mapping.py +133 -0
  43. tradedangerous/mfd/__init__.py +103 -0
  44. tradedangerous/mfd/saitek/__init__.py +3 -0
  45. tradedangerous/mfd/saitek/directoutput.py +678 -0
  46. tradedangerous/mfd/saitek/x52pro.py +195 -0
  47. tradedangerous/misc/checkpricebounds.py +287 -0
  48. tradedangerous/misc/clipboard.py +49 -0
  49. tradedangerous/misc/coord64.py +83 -0
  50. tradedangerous/misc/csvdialect.py +57 -0
  51. tradedangerous/misc/derp-sentinel.py +35 -0
  52. tradedangerous/misc/diff-system-csvs.py +159 -0
  53. tradedangerous/misc/eddb.py +81 -0
  54. tradedangerous/misc/eddn.py +349 -0
  55. tradedangerous/misc/edsc.py +437 -0
  56. tradedangerous/misc/edsm.py +121 -0
  57. tradedangerous/misc/importeddbstats.py +54 -0
  58. tradedangerous/misc/prices-json-exp.py +179 -0
  59. tradedangerous/misc/progress.py +194 -0
  60. tradedangerous/plugins/__init__.py +249 -0
  61. tradedangerous/plugins/edcd_plug.py +371 -0
  62. tradedangerous/plugins/eddblink_plug.py +861 -0
  63. tradedangerous/plugins/edmc_batch_plug.py +133 -0
  64. tradedangerous/plugins/spansh_plug.py +2647 -0
  65. tradedangerous/prices.py +211 -0
  66. tradedangerous/submit-distances.py +422 -0
  67. tradedangerous/templates/Added.csv +37 -0
  68. tradedangerous/templates/Category.csv +17 -0
  69. tradedangerous/templates/RareItem.csv +143 -0
  70. tradedangerous/templates/TradeDangerous.sql +338 -0
  71. tradedangerous/tools.py +40 -0
  72. tradedangerous/tradecalc.py +1302 -0
  73. tradedangerous/tradedb.py +2320 -0
  74. tradedangerous/tradeenv.py +313 -0
  75. tradedangerous/tradeenv.pyi +109 -0
  76. tradedangerous/tradeexcept.py +131 -0
  77. tradedangerous/tradeorm.py +183 -0
  78. tradedangerous/transfers.py +192 -0
  79. tradedangerous/utils.py +243 -0
  80. tradedangerous/version.py +16 -0
  81. tradedangerous-12.7.6.dist-info/METADATA +106 -0
  82. tradedangerous-12.7.6.dist-info/RECORD +87 -0
  83. tradedangerous-12.7.6.dist-info/WHEEL +5 -0
  84. tradedangerous-12.7.6.dist-info/entry_points.txt +3 -0
  85. tradedangerous-12.7.6.dist-info/licenses/LICENSE +373 -0
  86. tradedangerous-12.7.6.dist-info/top_level.txt +2 -0
  87. tradegui.py +24 -0
@@ -0,0 +1,371 @@
1
+ import csv
2
+ import pathlib
3
+
4
+ from .. import cache, transfers, csvexport
5
+ from ..tradedb import Category, Item
6
+ from . import PluginException, ImportPluginBase
7
+
8
+ class ImportPlugin(ImportPluginBase):
9
+ """
10
+ Download and process EDCD CSV-file(s)
11
+ """
12
+
13
+ pluginOptions = {
14
+ 'local': "Use local EDCD CSV-files.",
15
+ 'csvs': "Download and process all EDCD CSV-files.",
16
+ 'shipyard': "Download and process EDCD shipyard.csv",
17
+ 'commodity': "Download and process EDCD commodity.csv",
18
+ 'outfitting': "Download and process EDCD outfitting.csv",
19
+ }
20
+
21
+ def __init__(self, tdb, tdenv):
22
+ super().__init__(tdb, tdenv)
23
+
24
+ def check_local_edcd(self):
25
+ """
26
+ Check local DB against EDCD
27
+ """
28
+ tdb, tdenv = self.tdb, self.tdenv
29
+
30
+ tdCategories = []
31
+ for catID, catTD in sorted(tdb.categories(), key=lambda x: x[1].dbname):
32
+ tdCategories.append(catTD.dbname)
33
+ if catTD.dbname not in self.edcdCategories:
34
+ tdenv.WARN("Category '{}' not in EDCD", catTD.dbname)
35
+
36
+ for itemTD in sorted(catTD.items, key=lambda x: x.dbname):
37
+ itemEDCD = self.edcdItems.get(itemTD.dbname, None)
38
+ if not itemEDCD:
39
+ tdenv.DEBUG0("Item '{}' not in EDCD", itemTD.fullname)
40
+ else:
41
+ if catTD.dbname != itemEDCD.category.dbname:
42
+ tdenv.WARN("Item '{}' has different category "
43
+ "'{}' (TD) != '{}' (EDCD)",
44
+ itemTD.dbname,
45
+ catTD.dbname, itemEDCD.category.dbname
46
+ )
47
+ self.tdCategories = tdCategories
48
+
49
+ def update_item_order(self, db):
50
+ """
51
+ Update the ui_order of the items
52
+ """
53
+ sqlStmt = (
54
+ "SELECT category_id, name"
55
+ " FROM Category"
56
+ " ORDER BY name"
57
+ )
58
+ itmStmt = (
59
+ "SELECT item_id, name"
60
+ " FROM Item"
61
+ " WHERE category_id = ?"
62
+ " ORDER BY name"
63
+ )
64
+ updStmt = (
65
+ "UPDATE Item"
66
+ " SET ui_order = ?"
67
+ " WHERE item_id = ?"
68
+ )
69
+ for catID, catName in db.execute(sqlStmt):
70
+ itmOrder = 0
71
+ for itmID, itmName in db.execute(itmStmt, [ catID ]):
72
+ itmOrder += 1
73
+ db.execute(updStmt, [ itmOrder, itmID ])
74
+
75
+ def check_edcd_local(self):
76
+ """
77
+ Check EDCD items against local DB
78
+ """
79
+ tdb, tdenv = self.tdb, self.tdenv
80
+
81
+ addItem = 0
82
+ updItem = 0
83
+ addCategory = 0
84
+
85
+ commit = False
86
+ db = tdb.getDB()
87
+ for catNameEDCD in sorted(self.edcdCategories):
88
+ catEDCD = self.edcdCategories[catNameEDCD]
89
+ if catEDCD.dbname not in self.tdCategories:
90
+ tdenv.NOTE("New category '{}'", catEDCD.dbname)
91
+ sqlStmt = "INSERT INTO Category(name) VALUES(?)"
92
+
93
+ tdenv.DEBUG0("SQL-Statement: {}", sqlStmt)
94
+ tdenv.DEBUG0("SQL-Values: {}", [ catEDCD.dbname ])
95
+
96
+ db.execute(sqlStmt, [ catEDCD.dbname ])
97
+ addCategory += 1
98
+ commit = True
99
+
100
+ # Check EDCD items against local DB
101
+ for itemEDCD in sorted(catEDCD.items, key=lambda x: x.dbname):
102
+ itemTD = tdb.itemByName.get(itemEDCD.dbname, None)
103
+ if not itemTD:
104
+ itemTD = tdb.itemByFDevID.get(itemEDCD.fdevID, None)
105
+ if itemTD:
106
+ tdenv.WARN(
107
+ "Item '{}' has different name '{}' (TD) != '{} '(EDCD).",
108
+ itemEDCD.fdevID, itemTD.dbname, itemEDCD.dbname
109
+ )
110
+ else:
111
+ tdenv.NOTE("New Item '{}'", itemEDCD.fullname)
112
+ insColumns = [
113
+ "name",
114
+ "category_id",
115
+ "fdev_id"
116
+ ]
117
+ insValues = [
118
+ itemEDCD.dbname,
119
+ catEDCD.dbname,
120
+ itemEDCD.fdevID
121
+ ]
122
+ if itemEDCD.avgPrice:
123
+ insColumns.append('avg_price')
124
+ insValues.append(itemEDCD.avgPrice)
125
+ sqlStmt = (
126
+ "INSERT INTO Item({}) VALUES(?,"
127
+ "(SELECT category_id "
128
+ "FROM Category WHERE name = ?),?{})"
129
+ .format(
130
+ ",".join(insColumns),
131
+ ",?" if itemEDCD.avgPrice else ""
132
+ )
133
+ )
134
+ tdenv.DEBUG0("SQL-Statement: {}", sqlStmt)
135
+ tdenv.DEBUG0("SQL-Values: {}", insValues)
136
+
137
+ db.execute(sqlStmt, insValues)
138
+ addItem += 1
139
+ commit = True
140
+ else:
141
+ updValues, updColumns = [], []
142
+ if itemEDCD.avgPrice and itemTD.avgPrice != itemEDCD.avgPrice:
143
+ updColumns.append('avg_price')
144
+ updValues.append(itemEDCD.avgPrice)
145
+ if not itemTD.fdevID:
146
+ updColumns.append('fdev_id')
147
+ updValues.append(itemEDCD.fdevID)
148
+ elif itemTD.fdevID != itemEDCD.fdevID:
149
+ tdenv.WARN(
150
+ "Item '{}' has different FDevID {} (TD) != {} (EDCD).",
151
+ itemTD.fullname, itemTD.fdevID, itemEDCD.fdevID
152
+ )
153
+ if updColumns:
154
+ tdenv.NOTE("Update Item '{}' {} {}",
155
+ itemTD.fullname, updColumns, updValues
156
+ )
157
+ updValues.append(itemTD.ID)
158
+ sqlStmt = (
159
+ "UPDATE Item SET {} = ?"
160
+ " WHERE Item.item_id = ?".format(
161
+ " = ?,".join(updColumns))
162
+ )
163
+ tdenv.DEBUG0("SQL-Statement: {}", sqlStmt)
164
+ tdenv.DEBUG0("SQL-Values: {}", updValues)
165
+
166
+ db.execute(sqlStmt, updValues)
167
+ updItem += 1
168
+ commit = True
169
+
170
+ if addItem:
171
+ self.update_item_order(db)
172
+
173
+ if commit:
174
+ db.commit()
175
+ if addCategory:
176
+ tdenv.NOTE("Added {} categorie(s)", addCategory)
177
+ _, csvPath = csvexport.exportTableToFile(tdb, tdenv, 'Category')
178
+ tdenv.NOTE("{} updated.", csvPath)
179
+ if addItem or updItem:
180
+ for textAdd, intAdd in [('Added', addItem), ('Updated', updItem)]:
181
+ if intAdd:
182
+ tdenv.NOTE("{} {} item(s)", textAdd, intAdd)
183
+ _, csvPath = csvexport.exportTableToFile(tdb, tdenv, 'Item')
184
+ tdenv.NOTE("{} updated.", csvPath)
185
+
186
+ if not commit:
187
+ tdenv.NOTE("Nothing had to be done")
188
+
189
+
190
+ def process_fdevids_items(self, localPath, tableName):
191
+ """
192
+ More to do for commodities
193
+ """
194
+ tdenv = self.tdenv
195
+ tdenv.NOTE("Processing {}", tableName)
196
+
197
+ itmCount = 0
198
+ catCount = 0
199
+ edcdItems = {}
200
+ edcdCategories = {}
201
+ with localPath.open('r', encoding='utf-8') as importFile:
202
+ csvIn = csv.reader(
203
+ importFile, delimiter=',', quotechar="'", doublequote=True
204
+ )
205
+ # first line must be the column names
206
+ columnDefs = next(csvIn)
207
+
208
+ tdenv.DEBUG0("columnDefs: {}", columnDefs)
209
+
210
+ idxMap = {}
211
+ for cIndex, cName in enumerate(columnDefs):
212
+ idxMap[cName] = cIndex
213
+ tdenv.DEBUG0("idxMap: {}", idxMap)
214
+
215
+ notGood = False
216
+ for checkMe in ('id', 'category', 'name'):
217
+ if checkMe not in idxMap:
218
+ tdenv.WARN("'{}' column not in {}.", checkMe, localPath)
219
+ notGood = True
220
+ hasAverage = True if 'average' in idxMap else False
221
+
222
+ def castToInteger(val):
223
+ try:
224
+ val = int(val)
225
+ except:
226
+ val = None
227
+ pass
228
+ return val
229
+
230
+ if notGood:
231
+ tdenv.NOTE("Import stopped.", checkMe, localPath)
232
+ else:
233
+ for lineIn in csvIn:
234
+ if not lineIn:
235
+ continue
236
+ lineNo = csvIn.line_num
237
+ tdenv.DEBUG0("LINE {}: {}", lineNo, lineIn)
238
+
239
+ # strip() it do be save
240
+ edcdId = lineIn[idxMap['id']].strip()
241
+ edcdCategory = lineIn[idxMap['category']].strip()
242
+ edcdName = lineIn[idxMap['name']].strip()
243
+ if hasAverage:
244
+ edcdAverage = lineIn[idxMap['average']].strip()
245
+ else:
246
+ edcdAverage = None
247
+
248
+ if edcdCategory.lower() == "nonmarketable":
249
+ # we are, after all, a trading tool
250
+ tdenv.DEBUG0("Ignoring {}/{}", edcdCategory, edcdName)
251
+ continue
252
+
253
+ edcdId = castToInteger(edcdId)
254
+ edcdAverage = castToInteger(edcdAverage)
255
+
256
+ itemCategory = edcdCategories.get(edcdCategory, None)
257
+ if not itemCategory:
258
+ itemCategory = Category(0, edcdCategory, [])
259
+ edcdCategories[edcdCategory] = itemCategory
260
+ catCount += 1
261
+ tdenv.DEBUG1("NEW CATEGORY: {}", edcdCategory)
262
+
263
+ if edcdName not in edcdItems:
264
+ newItem = Item(
265
+ edcdId, edcdName, itemCategory,
266
+ '{}/{}'.format(itemCategory.dbname, edcdName),
267
+ edcdAverage, edcdId
268
+ )
269
+ edcdItems[edcdName] = newItem
270
+ itemCategory.items.append(newItem)
271
+ itmCount += 1
272
+ tdenv.DEBUG1("NEW ITEM: {}", edcdName)
273
+
274
+ self.edcdItems = edcdItems
275
+ self.edcdCategories = edcdCategories
276
+
277
+ tdenv.NOTE("Found {} categorie(s)", catCount)
278
+ tdenv.NOTE("Found {} item(s)", itmCount)
279
+
280
+ if catCount or itmCount:
281
+ self.check_local_edcd()
282
+ self.check_edcd_local()
283
+
284
+ def process_fdevids_table(self, localPath, tableName):
285
+ """
286
+ Shipyard and outfitting files can be directly imported.
287
+ """
288
+ tdb, tdenv = self.tdb, self.tdenv
289
+ tdenv.NOTE("Processing {}", tableName)
290
+
291
+ db = tdb.getDB()
292
+ db.execute("DELETE FROM {}".format(tableName))
293
+ cache.processImportFile(
294
+ tdenv,
295
+ db,
296
+ localPath,
297
+ tableName
298
+ )
299
+ db.commit()
300
+ lines, csvPath = csvexport.exportTableToFile(
301
+ tdb,
302
+ tdenv,
303
+ tableName,
304
+ )
305
+ tdenv.NOTE("Imported {} {}(s).", lines, tableName)
306
+ tdenv.NOTE("{} updated.", csvPath)
307
+
308
+ def download_fdevids(self):
309
+ """
310
+ Download the current data from EDCD,
311
+ see https://github.com/EDCD/FDevIDs
312
+ """
313
+ tdb, tdenv = self.tdb, self.tdenv
314
+
315
+ BASE_URL = "https://raw.githubusercontent.com/EDCD/FDevIDs/master/"
316
+ downloadList = []
317
+ if self.getOption("shipyard"):
318
+ downloadList.append(
319
+ ('FDevShipyard', 'shipyard.csv', self.process_fdevids_table)
320
+ )
321
+ if self.getOption("outfitting"):
322
+ downloadList.append(
323
+ ('FDevOutfitting', 'outfitting.csv', self.process_fdevids_table)
324
+ )
325
+ if self.getOption("commodity"):
326
+ downloadList.append(
327
+ ('FDevCommodity', 'commodity.csv', self.process_fdevids_items)
328
+ )
329
+
330
+ if len(downloadList) == 0:
331
+ tdenv.NOTE("I don't know what do to, give me some options!")
332
+ return
333
+
334
+ optLocal = self.getOption("local")
335
+ for tableName, fileEDCD, callMeBack in downloadList:
336
+ localPath = tdb.dataPath / pathlib.Path(tableName).with_suffix(".csv")
337
+ if optLocal:
338
+ if not localPath.exists():
339
+ raise PluginException(
340
+ "CSV-file '{}' not found.".format(str(localPath))
341
+ )
342
+ else:
343
+ transfers.download(
344
+ tdenv,
345
+ BASE_URL + fileEDCD,
346
+ str(localPath),
347
+ )
348
+ if callMeBack:
349
+ callMeBack(localPath, tableName)
350
+
351
+ def run(self):
352
+ tdb, tdenv = self.tdb, self.tdenv
353
+
354
+ tdenv.DEBUG0("csvs: {}", self.getOption("csvs"))
355
+ tdenv.DEBUG0("shipyard: {}", self.getOption("shipyard"))
356
+ tdenv.DEBUG0("commodity: {}", self.getOption("commodity"))
357
+ tdenv.DEBUG0("outfitting: {}", self.getOption("outfitting"))
358
+
359
+ if self.getOption("csvs"):
360
+ self.options["shipyard"] = True
361
+ self.options["commodity"] = True
362
+ self.options["outfitting"] = True
363
+
364
+ # Ensure the cache is built and reloaded.
365
+ tdb.reloadCache()
366
+ tdb.load()
367
+
368
+ self.download_fdevids()
369
+
370
+ # We did all the work
371
+ return False