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,437 @@
1
+ #! /usr/bin/env python3
2
+
3
+ from collections import namedtuple
4
+ from urllib.request import Request, urlopen
5
+
6
+ import json
7
+ import requests
8
+
9
+
10
+ def edsc_log(apiCall, params, jsonData=None, error=None):
11
+ """
12
+ Logs an EDSC query and it's response to tmp/edsc.log
13
+ """
14
+ try:
15
+ with open("tmp/edsc.log", "a", encoding="utf-8") as fh:
16
+ print('-'*70, file=fh)
17
+ print("API:", apiCall, file=fh)
18
+ print("REQ:", str(params), file=fh)
19
+ if jsonData:
20
+ print("REP:", json.dumps(jsonData, indent=1), file=fh)
21
+ if error:
22
+ print("ERR:", error)
23
+ print(file=fh)
24
+ except FileNotFoundError:
25
+ pass
26
+
27
+
28
+ class EDSCQueryBase:
29
+ """
30
+ Base class for creating an EDSC Query class, do not use directly.
31
+
32
+ Derived class must declare "apiCall" which is appended to baseURL
33
+ to form the query URL.
34
+ """
35
+
36
+ baseURL = "http://edstarcoordinator.com/api.asmx/"
37
+
38
+ def __init__(self, detail=2, test=False, known=1, confidence=0, **kwargs):
39
+ self.url = self.baseURL + self.apiCall
40
+ self.params = {
41
+ 'data': {
42
+ 'ver': 2,
43
+ 'test': test,
44
+ 'outputmode': detail,
45
+ 'filter': {
46
+ 'knownstatus': known,
47
+ 'cr': confidence,
48
+ }
49
+ }
50
+ }
51
+ for k, v in kwargs.items():
52
+ self.params['data']['filter'][k] = v
53
+
54
+ self.jsData = None
55
+
56
+
57
+ def fetch(self):
58
+ params = json.dumps(self.params).encode('utf-8')
59
+ request = Request(self.url, params, {
60
+ 'Content-Type': 'application/json;charset=utf-8',
61
+ 'Content-Length': len(params)
62
+ })
63
+
64
+ with urlopen(request, params) as stream:
65
+ self.jsData = stream.read()
66
+
67
+ data = json.loads(self.jsData.decode())['d']
68
+ inputNo = 0
69
+ self.status = data['status']['input'][inputNo]['status']
70
+
71
+ edsc_log(self.apiCall, self.params, data)
72
+
73
+ return data
74
+
75
+
76
+ class StarQuery(EDSCQueryBase):
77
+ """
78
+ Query EDSC Systems.
79
+ """
80
+ apiCall = "GetSystems"
81
+
82
+
83
+ class DistanceQuery(EDSCQueryBase):
84
+ """
85
+ Request distances from EDSC.
86
+ """
87
+ apiCall = "GetDistances"
88
+
89
+
90
+ class SubmissionError(Exception):
91
+ pass
92
+
93
+
94
+ class Status(namedtuple('Status', [
95
+ 'source', 'code', 'msg', 'lhs', 'rhs'
96
+ ])):
97
+ pass
98
+
99
+ class StarSubmissionResult:
100
+ """
101
+ Translates a response the json we get back from EDSC when
102
+ we submit a StarSubmission into something less awful to
103
+ work with.
104
+
105
+ Attributes:
106
+ valid
107
+ True or False whether the response looked healthy
108
+
109
+ summary
110
+ A summary of the /parse/; currently either "No Data"
111
+ or "OK". This does NOT represent whether the
112
+ submission itself was successful.
113
+
114
+ systems
115
+ A dict{ system name: [msgnum, coords] } for systems which
116
+ were reported as being added or updated. See
117
+ translateCode for converting these to text.
118
+ 'coords' is either None if the system hasn't been
119
+ trilaterated yet, or an array of [x,y,z]
120
+
121
+ distances
122
+ A dict{ lhs system: { rhs system: dist } }. It's not
123
+ really very useful but I didn't want to drop the data
124
+ EDSC was sending back to us, just incase.
125
+
126
+ errors
127
+ A list of SubmissionError objects describing problems
128
+ that were encountered, mostly 304 (distance added but
129
+ failed to verify coordinates) and 305 (distance appears
130
+ to be wrong).
131
+
132
+ recheck
133
+ A dict{ system name: dist } for systems that had a 305
134
+ error for a distance to "star". They still appear in
135
+ the 'errors' attribute, but this is a short-cut for
136
+ prompting the user to double check a distance from their
137
+ current p0.
138
+
139
+ """
140
+
141
+ codeMap = {
142
+ 201: "New Entry",
143
+ 202: "System CR increased",
144
+ 203: "Coordinates calculated",
145
+ 301: "Distance added",
146
+ 302: "Distance CR increased",
147
+ 303: "Added verification",
148
+ 304: "OK: Needs more data",
149
+ 305: "Distance appears to be wrong",
150
+ 401: "CALCULATED",
151
+ 402: "No solution found, more data needed"
152
+ }
153
+
154
+
155
+ def __init__(self, star, response):
156
+ self.star = star
157
+ self.valid = False
158
+ self.summary = "No Data"
159
+ self.systems = {}
160
+ self.distances = {}
161
+ self.errors = []
162
+ self.recheck = {}
163
+
164
+ # This line righ there, this is just the beginning of
165
+ # why it's necessary to have this complicated of a
166
+ # wrapper for this json data. Don't forget, we have
167
+ # already peeled off some layers of json around this.
168
+ summary = response['status']['input'][0]['status']
169
+ code, msg = int(summary['statusnum']), summary['msg']
170
+ if code != 0:
171
+ self.valid = False
172
+ self.summary = "Error #{}: {}".format(code, msg)
173
+ self.errors.append(Status(
174
+ 'status', code, msg, None, None
175
+ ))
176
+ return
177
+
178
+ self.valid = True
179
+ self.summary = "OK"
180
+
181
+ # We get back an array of things called 'system', which
182
+ # allows EDSC to tell us that something got added. It
183
+ # could be p0 or it could be one of the refs or it could
184
+ # be something that was sitting in EDSCs distances buffer.
185
+ sysArray = response['status']['system']
186
+ for ent in sysArray:
187
+ sysName = ent['system'].upper()
188
+ code = int(ent['status']['statusnum'])
189
+ msg = ent['status']['msg']
190
+ if code in [201, 202, 203]:
191
+ self.systems[sysName] = (code, None)
192
+ else:
193
+ self.errors.append(Status(
194
+ 'system', code, msg, sysName, None,
195
+ ))
196
+
197
+ # Now the pair-wise distance checks. These are either not
198
+ # very useful/duplicate the systems list, or they tell us
199
+ # about conflicts with pre-existing data.
200
+ # Pairs which generate 305 (distance wrong) that relate
201
+ # to P0 will be added to "recheck" so that the caller can
202
+ # ask their user to provide sanity values.
203
+ distArray = response['status']['dist']
204
+ errPairs = set()
205
+ for ent in distArray:
206
+ lhsName = ent['system1'].upper()
207
+ rhsName = ent['system2'].upper()
208
+ code = int(ent['status']['statusnum'])
209
+ msg = ent['status']['msg']
210
+ if code in [301, 302, 303, 304]:
211
+ if lhsName not in self.distances:
212
+ self.distances[lhsName] = {}
213
+ try:
214
+ rhsDists = self.distances[rhsName]
215
+ if lhsName in rhsDists:
216
+ continue
217
+ except KeyError:
218
+ pass
219
+ dist = float(ent['dist'])
220
+ self.distances[lhsName][rhsName] = dist
221
+ if lhsName not in self.systems:
222
+ self.systems[lhsName] = (code, None)
223
+ else:
224
+ if (lhsName,rhsName,code) in errPairs:
225
+ continue
226
+ if (rhsName,lhsName,code) in errPairs:
227
+ continue
228
+ errPairs.add((lhsName,rhsName,code))
229
+ errPairs.add((rhsName,lhsName,code))
230
+ self.errors.append(Status(
231
+ 'dist', code, msg, lhsName, rhsName,
232
+ ))
233
+ if code == 305:
234
+ if lhsName == star:
235
+ self.recheck[rhsName] = ent['dist']
236
+ elif rhsName == star:
237
+ self.recheck[lhsName] = ent['dist']
238
+
239
+ # Finally we look thru the trilat array which is telling us
240
+ # how the search for p0's coordinates went on a per-ref
241
+ # basis.
242
+ #
243
+ # Successful trilateration will result in an array of
244
+ # trilats that contain code 401 and the coordinates of
245
+ # p0, one per ref. Since we can't tell what the *other*
246
+ # system is, this is a bit stupid. Probably a bug in edsc.
247
+ triArray = response['status']['trilat']
248
+ for ent in triArray:
249
+ sysName = ent['system'].upper()
250
+ code = int(ent['status']['statusnum'])
251
+ if code == 401:
252
+ try:
253
+ system = self.systems[sysName]
254
+ if system[1] is not None:
255
+ continue
256
+ except KeyError:
257
+ system = (code, None)
258
+ assert system[1] is None
259
+ coord = ent['coord']
260
+ x, y, z = coord['x'], coord['y'], coord['z']
261
+ self.systems[sysName] = (system[0], [x,y,z])
262
+ elif code == 402:
263
+ pass
264
+ else:
265
+ self.errors.append(Status(
266
+ 'trilat', code, msg, sysName, None,
267
+ ))
268
+
269
+
270
+ def __str__(self):
271
+ if not self.valid:
272
+ return "ERROR: {}".format(self.summary)
273
+
274
+ text = ""
275
+
276
+ if not self.errors:
277
+ text += "Success.\n"
278
+
279
+ if self.systems:
280
+ text += "+Updates:\n"
281
+ sysNames = list(self.systems.keys())
282
+ sysNames.sort(key=lambda s: self.systems[s][0])
283
+ for sysName in sysNames:
284
+ code, coords = self.systems[sysName]
285
+ sysText = self.translateCode(code)
286
+ if coords is not None:
287
+ sysText += str(coords)
288
+ text += "|- {:.<30s} {}\n".format(
289
+ sysName, sysText,
290
+ )
291
+ text += "\n"
292
+
293
+ if self.errors:
294
+ text += "+Problems:\n"
295
+ errors = sorted(self.errors, key=lambda e: e.rhs or "")
296
+ errors.sort(key=lambda e: e.lhs or "")
297
+ errors.sort(key=lambda e: e.code)
298
+ for err in errors:
299
+ text += "|- {:.<30s} #{} {}".format(
300
+ err.lhs,
301
+ err.code,
302
+ self.translateCode(err.code),
303
+ )
304
+ if err.rhs:
305
+ text += " <-> " + err.rhs
306
+ text += "\n"
307
+
308
+ return text
309
+
310
+ def translateCode(self, code):
311
+ try:
312
+ return self.codeMap[code]
313
+ except KeyError:
314
+ return "Error #{} (unknown)".format(code)
315
+
316
+
317
+
318
+ class StarSubmission:
319
+ baseURL = "http://edstarcoordinator.com/api.asmx/"
320
+ apiCall = "SubmitDistances"
321
+
322
+ def __init__(
323
+ self, star,
324
+ test=False, commander=None,
325
+ refs=None, distances=None,
326
+ ):
327
+ assert isinstance(star, str)
328
+ assert isinstance(test, bool)
329
+ if refs:
330
+ assert isinstance(refs, list)
331
+ self.test = test
332
+ self.name = star.upper()
333
+ self.refs = refs or []
334
+ if distances:
335
+ if isinstance(distances, list):
336
+ for name, dist in distances:
337
+ self.add_distance(name, dist)
338
+ elif isinstance(distances, dict):
339
+ for name, dist in distances.items():
340
+ self.add_distance(name, dist)
341
+ else:
342
+ raise SubmissionError("Invalid distances parameter")
343
+ if commander:
344
+ self.commander = commander
345
+
346
+ def __repr__(self):
347
+ return (
348
+ "StarSubmission("
349
+ "test={}, star=\"{}\", commander=\"{}\", refs={}"
350
+ ")".format(
351
+ self.test,
352
+ self.name,
353
+ self.commander,
354
+ self.refs,
355
+ )
356
+ )
357
+
358
+
359
+ def add_distance(self, name, dist):
360
+ assert isinstance(name, str)
361
+ assert isinstance(dist, (float, int))
362
+ assert name.upper() != self.name
363
+
364
+ name = name.upper()
365
+ for i, ref in enumerate(self.refs):
366
+ if ref['name'] == name:
367
+ ref['dist'] = dist
368
+ return
369
+
370
+ self.refs.append({'name': name, 'dist': dist})
371
+
372
+
373
+ def submit(self):
374
+ assert len(self.refs) != 0
375
+
376
+ headers = { 'Content-Type': 'application/json; charset=utf-8' }
377
+ data = {
378
+ 'data': {
379
+ 'test': self.test,
380
+ 'ver': 2,
381
+ 'p0': { 'name': self.name },
382
+ 'refs': self.refs
383
+ },
384
+ }
385
+ if self.commander:
386
+ data['data']['commander'] = self.commander
387
+
388
+ jsonData = json.dumps(data, indent=None, separators=(',', ':'))
389
+
390
+ url = self.baseURL + self.apiCall
391
+ req = requests.post(
392
+ url,
393
+ headers=headers,
394
+ data=jsonData
395
+ )
396
+ resp = req.text
397
+ if not resp.startswith('{'):
398
+ edsc_log(self.apiCall, repr(self), error=resp)
399
+ raise SubmissionError("Server Side Error: " + resp)
400
+
401
+ try:
402
+ respData = json.loads(resp)
403
+ except Exception:
404
+ edsc_log(self.apiCall, repr(self), error=resp)
405
+ raise SubmissionError("Invalid server response: " + resp)
406
+ edsc_log(self.apiCall, repr(self), respData)
407
+ try:
408
+ innerData = respData['d']
409
+ except KeyError:
410
+ raise SubmissionError("Server Error: " + resp)
411
+
412
+ return innerData
413
+
414
+
415
+ if __name__ == "__main__":
416
+ print("Requesting recent, non-test, coords-known, cr >= 2 stars")
417
+ edsq = StarQuery(test=False, confidence=2, known=1)
418
+ data = edsq.fetch()
419
+
420
+ if edsq.status['statusnum'] != 0:
421
+ raise Exception("Query failed: {} ({})".format(
422
+ edsq.status['msg'],
423
+ edsq.status['statusnum'],
424
+ ))
425
+
426
+ date = data['date']
427
+ systems = data['systems']
428
+
429
+ for sysinfo in systems:
430
+ print("{:<30s} {:11f} {:11f} {:11f} {}".format(
431
+ sysinfo['name'].upper(),
432
+ sysinfo['coord'][0],
433
+ sysinfo['coord'][1],
434
+ sysinfo['coord'][2],
435
+ sysinfo['createdate'],
436
+ ))
437
+
@@ -0,0 +1,121 @@
1
+ #! /usr/bin/env python
2
+
3
+ """
4
+ based on edsc.py
5
+ uses EDSM - https://www.edsm.net/api
6
+ """
7
+
8
+ import json
9
+ import requests
10
+
11
+
12
+ def edsm_log(apiCall, url, params, jsonData=None, error=None):
13
+ """
14
+ Logs an EDSM query and it's response to tmp/edsm.log
15
+ """
16
+ try:
17
+ with open("tmp/edsm.log", "a", encoding="utf-8") as fh:
18
+ print('-'*70, file=fh)
19
+ print("API:", apiCall, file=fh)
20
+ print("REQ:", str(params), file=fh)
21
+ print("URL:", url, file=fh)
22
+ if jsonData:
23
+ print("REP:", json.dumps(jsonData, indent=1), file=fh)
24
+ if error:
25
+ print("ERR:", error)
26
+ print(file=fh)
27
+ except FileNotFoundError:
28
+ pass
29
+
30
+
31
+ class EDSMQueryBase:
32
+ """
33
+ Base class for creating an EDSM Query class, do not use directly.
34
+
35
+ Derived class must declare "apiCall" which is appended to baseURL
36
+ to form the query URL.
37
+ """
38
+
39
+ baseURL = "https://www.edsm.net/api-v1/"
40
+
41
+ def __init__(self, log=False, known=1, coords=1, **kwargs):
42
+ self.log = log
43
+ self.url = self.baseURL + self.apiCall
44
+ self.params = {
45
+ 'known': known,
46
+ 'coords': coords,
47
+ }
48
+ for k, v in kwargs.items():
49
+ self.params[k] = v
50
+
51
+ def fetch(self):
52
+ res = requests.get(self.url, self.params)
53
+ self.status = res.status_code
54
+
55
+ try:
56
+ data = res.json()
57
+ except:
58
+ data = None
59
+ pass
60
+
61
+ if self.log:
62
+ edsm_log(self.apiCall, res.url, self.params, data)
63
+
64
+ return data
65
+
66
+
67
+ class StarQuerySingle(EDSMQueryBase):
68
+ """
69
+ Query EDSM System.
70
+
71
+ provide:
72
+ systemName
73
+ """
74
+ apiCall = "system"
75
+
76
+ class StarQueryMulti(EDSMQueryBase):
77
+ """
78
+ Query EDSM Systems.
79
+
80
+ provide:
81
+ systemName
82
+ """
83
+ apiCall = "systems"
84
+
85
+ class StarQuerySphere(EDSMQueryBase):
86
+ """
87
+ Query EDSM Systems.
88
+ provide:
89
+ systemName or center-coords as x, y and z
90
+ radius N.NN
91
+ """
92
+ apiCall = "sphere-systems"
93
+
94
+ class DistanceQuery(EDSMQueryBase):
95
+ """
96
+ Request distances from EDSM.
97
+ """
98
+ apiCall = "distances"
99
+
100
+
101
+ if __name__ == "__main__":
102
+ print("Requesting Azrael, coords-known")
103
+ edsq = StarQuerySingle(log=True, systemName="Azrael")
104
+ data = edsq.fetch()
105
+ print("{:<30s} {:11f} {:11f} {:11f}".format(
106
+ data['name'].upper(),
107
+ data['coords']['x'],
108
+ data['coords']['y'],
109
+ data['coords']['z'],
110
+ ))
111
+
112
+ print("Requesting 10ly sphere of Sol, coords-known")
113
+ edsq = StarQuerySphere(systemName="Sol", radius=10)
114
+ data = edsq.fetch()
115
+ for sysinfo in data:
116
+ print("{:<30s} {:11f} {:11f} {:11f}".format(
117
+ sysinfo['name'].upper(),
118
+ sysinfo['coords']['x'],
119
+ sysinfo['coords']['y'],
120
+ sysinfo['coords']['z'],
121
+ ))
@@ -0,0 +1,54 @@
1
+ import csvexport
2
+ import misc.eddb
3
+ import tradedb
4
+
5
+ # Build an ID=>Name mapping for EDDB systems
6
+ tdb = tradedb.TradeDB()
7
+ systems = {}
8
+ tdSysLookup = tdb.systemByName.get
9
+ for s in misc.eddb.SystemsQuery():
10
+ tdSys = tdSysLookup(s['name'].upper(), None)
11
+ if tdSys and tdSys.stations:
12
+ systems[s['id']] = { stn.dbname.upper(): stn for stn in tdSys.stations }
13
+
14
+ def matching_stations():
15
+ # generator that searches the eddb station set for entries that
16
+ # match tdb entries and yields the tuple (tdStn, eddbStn)
17
+
18
+ for eddbStn in misc.eddb.StationsQuery():
19
+ stationList = systems.get(eddbStn['system_id'], None)
20
+ if not stationList:
21
+ continue
22
+ name = eddbStn['name'].upper()
23
+ tdStn = stationList.get(name, None)
24
+ if tdStn:
25
+ yield tdStn, eddbStn
26
+
27
+
28
+ updateStation = tdb.updateLocalStation
29
+
30
+ bool_trans = { None: '?', 0: 'N', 1: 'Y' }
31
+
32
+ updates = 0
33
+ for tdStn, eddbStn in matching_stations():
34
+ mps = eddbStn['max_landing_pad_size'] or '?'
35
+ if updateStation(
36
+ station=tdStn,
37
+ lsFromStar=eddbStn['distance_to_star'],
38
+ maxPadSize=mps,
39
+ market=bool_trans[eddbStn['has_commodities']],
40
+ blackMarket=bool_trans[eddbStn['has_blackmarket']],
41
+ shipyard=bool_trans[eddbStn['has_shipyard']],
42
+ outfitting=bool_trans[eddbStn['has_outfitting']],
43
+ rearm=bool_trans[eddbStn['has_rearm']],
44
+ refuel=bool_trans[eddbStn['has_refuel']],
45
+ repair=bool_trans[eddbStn['has_repair']],
46
+ modified='now',
47
+ commit=False,
48
+ ):
49
+ updates += 1
50
+
51
+ if updates:
52
+ tdb.getDB().commit()
53
+ csvexport.exportTableToFile(tdb, tdb.tdenv, "Station")
54
+ print("Updated Station.csv: {} updates".format(updates))