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.
- py.typed +1 -0
- trade.py +49 -0
- tradedangerous/__init__.py +43 -0
- tradedangerous/cache.py +1381 -0
- tradedangerous/cli.py +136 -0
- tradedangerous/commands/TEMPLATE.py +74 -0
- tradedangerous/commands/__init__.py +244 -0
- tradedangerous/commands/buildcache_cmd.py +102 -0
- tradedangerous/commands/buy_cmd.py +427 -0
- tradedangerous/commands/commandenv.py +372 -0
- tradedangerous/commands/exceptions.py +94 -0
- tradedangerous/commands/export_cmd.py +150 -0
- tradedangerous/commands/import_cmd.py +222 -0
- tradedangerous/commands/local_cmd.py +243 -0
- tradedangerous/commands/market_cmd.py +207 -0
- tradedangerous/commands/nav_cmd.py +252 -0
- tradedangerous/commands/olddata_cmd.py +270 -0
- tradedangerous/commands/parsing.py +221 -0
- tradedangerous/commands/rares_cmd.py +298 -0
- tradedangerous/commands/run_cmd.py +1521 -0
- tradedangerous/commands/sell_cmd.py +262 -0
- tradedangerous/commands/shipvendor_cmd.py +60 -0
- tradedangerous/commands/station_cmd.py +68 -0
- tradedangerous/commands/trade_cmd.py +181 -0
- tradedangerous/commands/update_cmd.py +67 -0
- tradedangerous/corrections.py +55 -0
- tradedangerous/csvexport.py +234 -0
- tradedangerous/db/__init__.py +27 -0
- tradedangerous/db/adapter.py +192 -0
- tradedangerous/db/config.py +107 -0
- tradedangerous/db/engine.py +259 -0
- tradedangerous/db/lifecycle.py +332 -0
- tradedangerous/db/locks.py +208 -0
- tradedangerous/db/orm_models.py +500 -0
- tradedangerous/db/paths.py +113 -0
- tradedangerous/db/utils.py +661 -0
- tradedangerous/edscupdate.py +565 -0
- tradedangerous/edsmupdate.py +474 -0
- tradedangerous/formatting.py +210 -0
- tradedangerous/fs.py +156 -0
- tradedangerous/gui.py +1146 -0
- tradedangerous/mapping.py +133 -0
- tradedangerous/mfd/__init__.py +103 -0
- tradedangerous/mfd/saitek/__init__.py +3 -0
- tradedangerous/mfd/saitek/directoutput.py +678 -0
- tradedangerous/mfd/saitek/x52pro.py +195 -0
- tradedangerous/misc/checkpricebounds.py +287 -0
- tradedangerous/misc/clipboard.py +49 -0
- tradedangerous/misc/coord64.py +83 -0
- tradedangerous/misc/csvdialect.py +57 -0
- tradedangerous/misc/derp-sentinel.py +35 -0
- tradedangerous/misc/diff-system-csvs.py +159 -0
- tradedangerous/misc/eddb.py +81 -0
- tradedangerous/misc/eddn.py +349 -0
- tradedangerous/misc/edsc.py +437 -0
- tradedangerous/misc/edsm.py +121 -0
- tradedangerous/misc/importeddbstats.py +54 -0
- tradedangerous/misc/prices-json-exp.py +179 -0
- tradedangerous/misc/progress.py +194 -0
- tradedangerous/plugins/__init__.py +249 -0
- tradedangerous/plugins/edcd_plug.py +371 -0
- tradedangerous/plugins/eddblink_plug.py +861 -0
- tradedangerous/plugins/edmc_batch_plug.py +133 -0
- tradedangerous/plugins/spansh_plug.py +2647 -0
- tradedangerous/prices.py +211 -0
- tradedangerous/submit-distances.py +422 -0
- tradedangerous/templates/Added.csv +37 -0
- tradedangerous/templates/Category.csv +17 -0
- tradedangerous/templates/RareItem.csv +143 -0
- tradedangerous/templates/TradeDangerous.sql +338 -0
- tradedangerous/tools.py +40 -0
- tradedangerous/tradecalc.py +1302 -0
- tradedangerous/tradedb.py +2320 -0
- tradedangerous/tradeenv.py +313 -0
- tradedangerous/tradeenv.pyi +109 -0
- tradedangerous/tradeexcept.py +131 -0
- tradedangerous/tradeorm.py +183 -0
- tradedangerous/transfers.py +192 -0
- tradedangerous/utils.py +243 -0
- tradedangerous/version.py +16 -0
- tradedangerous-12.7.6.dist-info/METADATA +106 -0
- tradedangerous-12.7.6.dist-info/RECORD +87 -0
- tradedangerous-12.7.6.dist-info/WHEEL +5 -0
- tradedangerous-12.7.6.dist-info/entry_points.txt +3 -0
- tradedangerous-12.7.6.dist-info/licenses/LICENSE +373 -0
- tradedangerous-12.7.6.dist-info/top_level.txt +2 -0
- tradegui.py +24 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from .commandenv import ResultRow
|
|
4
|
+
from .exceptions import CommandLineError, NoDataError
|
|
5
|
+
from ..formatting import RowFormat, max_len
|
|
6
|
+
from ..tradedb import Station, System, TradeDB
|
|
7
|
+
from .parsing import (
|
|
8
|
+
AvoidPlacesArgument, BlackMarketSwitch, FleetCarrierArgument, MutuallyExclusiveGroup,
|
|
9
|
+
NoPlanetSwitch, OdysseyArgument, PadSizeArgument, ParseArgument, PlanetaryArgument,
|
|
10
|
+
)
|
|
11
|
+
from sqlalchemy import text
|
|
12
|
+
|
|
13
|
+
# TODO: Add UPGRADE_MODE
|
|
14
|
+
ITEM_MODE = "Item"
|
|
15
|
+
SHIP_MODE = "Ship"
|
|
16
|
+
|
|
17
|
+
######################################################################
|
|
18
|
+
# Parser config
|
|
19
|
+
|
|
20
|
+
help = 'Find places to buy a given item within range of a given station.'
|
|
21
|
+
name = 'buy'
|
|
22
|
+
epilog = None
|
|
23
|
+
wantsTradeDB = True
|
|
24
|
+
arguments = (
|
|
25
|
+
ParseArgument(
|
|
26
|
+
'name',
|
|
27
|
+
help = 'Items or Ships to look for.',
|
|
28
|
+
type = str,
|
|
29
|
+
nargs = '+',
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
switches = (
|
|
33
|
+
ParseArgument(
|
|
34
|
+
'--supply', '--quantity',
|
|
35
|
+
help = 'Limit to stations known to have at least this much supply.',
|
|
36
|
+
default = 0,
|
|
37
|
+
type = int,
|
|
38
|
+
),
|
|
39
|
+
ParseArgument(
|
|
40
|
+
'--near',
|
|
41
|
+
help = 'Find sellers within jump range of this system.',
|
|
42
|
+
type = str
|
|
43
|
+
),
|
|
44
|
+
ParseArgument(
|
|
45
|
+
'--ly',
|
|
46
|
+
help = '[Requires --near] Systems within this range of --near.',
|
|
47
|
+
default = None,
|
|
48
|
+
dest = 'maxLyPer',
|
|
49
|
+
metavar = 'N.NN',
|
|
50
|
+
type = float,
|
|
51
|
+
),
|
|
52
|
+
ParseArgument(
|
|
53
|
+
'--limit',
|
|
54
|
+
help = 'Maximum number of results to list.',
|
|
55
|
+
default = None,
|
|
56
|
+
type = int,
|
|
57
|
+
),
|
|
58
|
+
AvoidPlacesArgument(),
|
|
59
|
+
ParseArgument('--age', '--max-days-old', '-MD',
|
|
60
|
+
help = 'Maximum age (in days) of trade data to use.',
|
|
61
|
+
metavar = 'DAYS',
|
|
62
|
+
type = float,
|
|
63
|
+
dest = 'maxAge',
|
|
64
|
+
),
|
|
65
|
+
PadSizeArgument(),
|
|
66
|
+
MutuallyExclusiveGroup(
|
|
67
|
+
NoPlanetSwitch(),
|
|
68
|
+
PlanetaryArgument(),
|
|
69
|
+
),
|
|
70
|
+
FleetCarrierArgument(),
|
|
71
|
+
OdysseyArgument(),
|
|
72
|
+
BlackMarketSwitch(),
|
|
73
|
+
MutuallyExclusiveGroup(
|
|
74
|
+
ParseArgument(
|
|
75
|
+
'--one-stop', '-1',
|
|
76
|
+
help = 'Only list stations that carry all items listed.',
|
|
77
|
+
action = 'store_true',
|
|
78
|
+
dest = 'oneStop',
|
|
79
|
+
),
|
|
80
|
+
ParseArgument(
|
|
81
|
+
'--price-sort', '-P',
|
|
82
|
+
help = '(When using --near) Sort by price not distance',
|
|
83
|
+
action = 'store_true',
|
|
84
|
+
default = False,
|
|
85
|
+
dest = 'sortByPrice',
|
|
86
|
+
),
|
|
87
|
+
ParseArgument(
|
|
88
|
+
'--units-sort', '-S',
|
|
89
|
+
help = 'Sort by available units followed by price',
|
|
90
|
+
action = 'store_true',
|
|
91
|
+
default = False,
|
|
92
|
+
dest = 'sortByUnits',
|
|
93
|
+
),
|
|
94
|
+
),
|
|
95
|
+
ParseArgument(
|
|
96
|
+
'--gt',
|
|
97
|
+
help = 'Limit to prices above Ncr',
|
|
98
|
+
metavar = 'N',
|
|
99
|
+
dest = 'gt',
|
|
100
|
+
type = "credits",
|
|
101
|
+
),
|
|
102
|
+
ParseArgument(
|
|
103
|
+
'--lt',
|
|
104
|
+
help = 'Limit to prices below Ncr',
|
|
105
|
+
metavar = 'N',
|
|
106
|
+
dest = 'lt',
|
|
107
|
+
type = "credits",
|
|
108
|
+
),
|
|
109
|
+
ParseArgument('--ls-max',
|
|
110
|
+
help='Only consider stations up to this many ls from their star.',
|
|
111
|
+
metavar='LS',
|
|
112
|
+
dest='maxLs',
|
|
113
|
+
type=int,
|
|
114
|
+
default=0,
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def get_lookup_list(cmdenv, tdb):
|
|
120
|
+
# Credit: http://stackoverflow.com/a/952952/257645
|
|
121
|
+
# Turns [['a'],['b','c']] => ['a', 'b', 'c']
|
|
122
|
+
names = [
|
|
123
|
+
name for names in cmdenv.name for name in names.split(',')
|
|
124
|
+
]
|
|
125
|
+
# We only support searching for one type of purchase a time: ship or item.
|
|
126
|
+
# Our first match is open-ended, but once we have matched one type of
|
|
127
|
+
# thing, the remaining arguments are all sourced from the same pool.
|
|
128
|
+
# Thus: [food, cobra, metals] is illegal but [metals, hydrogen] is legal.
|
|
129
|
+
mode = None
|
|
130
|
+
|
|
131
|
+
queries = {}
|
|
132
|
+
for name in names:
|
|
133
|
+
if mode is not SHIP_MODE:
|
|
134
|
+
# Either no mode selected yet or we are in ITEM_MODE.
|
|
135
|
+
# Consider categories first.
|
|
136
|
+
try:
|
|
137
|
+
category = tdb.lookupCategory(name)
|
|
138
|
+
for item in category.items:
|
|
139
|
+
names.append(item.name())
|
|
140
|
+
queries[item.ID] = item
|
|
141
|
+
mode = ITEM_MODE
|
|
142
|
+
continue
|
|
143
|
+
except LookupError:
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
# Item names secondary.
|
|
147
|
+
try:
|
|
148
|
+
item = tdb.lookupItem(name)
|
|
149
|
+
cmdenv.DEBUG0("Looking up item {} (#{})", item.name(), item.ID)
|
|
150
|
+
queries[item.ID] = item
|
|
151
|
+
mode = ITEM_MODE
|
|
152
|
+
continue
|
|
153
|
+
except LookupError:
|
|
154
|
+
if mode is ITEM_MODE:
|
|
155
|
+
raise CommandLineError(
|
|
156
|
+
"Unrecognized item: {}".format(name)
|
|
157
|
+
)
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
# Either no mode selected yet or we are in SHIP_MODE.
|
|
161
|
+
try:
|
|
162
|
+
ship = tdb.lookupShip(name)
|
|
163
|
+
cmdenv.DEBUG0("Looking up ship {} (#{})", ship.name(), ship.ID)
|
|
164
|
+
queries[ship.ID] = ship
|
|
165
|
+
mode = SHIP_MODE
|
|
166
|
+
continue
|
|
167
|
+
except LookupError:
|
|
168
|
+
if not mode:
|
|
169
|
+
raise CommandLineError(
|
|
170
|
+
"Unrecognized item/ship: {}".format(name)
|
|
171
|
+
)
|
|
172
|
+
raise CommandLineError(
|
|
173
|
+
"Unrecognized ship: {}".format(name)
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
return queries, mode
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def sql_query(cmdenv, tdb, queries, mode):
|
|
180
|
+
"""
|
|
181
|
+
Backend-portable query builder.
|
|
182
|
+
- Uses named binds (':param') instead of SQLite '?'.
|
|
183
|
+
- Materializes rows eagerly to avoid closed-cursor issues.
|
|
184
|
+
- Preserves return shapes:
|
|
185
|
+
* Ship: (ship_id, station_id, cost, 1)
|
|
186
|
+
* Item: (item_id, station_id, supply_price, supply_units)
|
|
187
|
+
"""
|
|
188
|
+
ids = list(queries.keys())
|
|
189
|
+
|
|
190
|
+
# Build a stable, named-parameter IN(...) list
|
|
191
|
+
params = {}
|
|
192
|
+
placeholders = []
|
|
193
|
+
for i, val in enumerate(ids):
|
|
194
|
+
key = f"id{i}"
|
|
195
|
+
placeholders.append(f":{key}")
|
|
196
|
+
params[key] = val
|
|
197
|
+
id_list_sql = ",".join(placeholders)
|
|
198
|
+
|
|
199
|
+
if mode is SHIP_MODE:
|
|
200
|
+
columns = "s.ship_id, s.station_id, sh.cost, 1"
|
|
201
|
+
tables = "ShipVendor AS s JOIN Ship AS sh ON sh.ship_id = s.ship_id"
|
|
202
|
+
constraints = [f"(s.ship_id IN ({id_list_sql}))"]
|
|
203
|
+
else:
|
|
204
|
+
columns = "s.item_id, s.station_id, s.supply_price, s.supply_units"
|
|
205
|
+
tables = "StationItem AS s"
|
|
206
|
+
constraints = [
|
|
207
|
+
f"(s.item_id IN ({id_list_sql}))",
|
|
208
|
+
"(s.supply_price > 0)", # preserves index intent across backends
|
|
209
|
+
]
|
|
210
|
+
if cmdenv.supply:
|
|
211
|
+
constraints.append("(s.supply_units >= :supply)")
|
|
212
|
+
params["supply"] = cmdenv.supply
|
|
213
|
+
if cmdenv.lt:
|
|
214
|
+
constraints.append("(s.supply_price < :lt)")
|
|
215
|
+
params["lt"] = cmdenv.lt
|
|
216
|
+
if cmdenv.gt:
|
|
217
|
+
constraints.append("(s.supply_price > :gt)")
|
|
218
|
+
params["gt"] = cmdenv.gt
|
|
219
|
+
|
|
220
|
+
where_clause = " AND ".join(constraints)
|
|
221
|
+
stmt = f"SELECT DISTINCT {columns} FROM {tables} WHERE {where_clause}"
|
|
222
|
+
cmdenv.DEBUG0('SQL: {} ; params={}', stmt, params)
|
|
223
|
+
|
|
224
|
+
# Eagerly fetch to avoid closed cursor when iterating later.
|
|
225
|
+
with tdb.engine.connect() as conn:
|
|
226
|
+
result = conn.execute(text(stmt), params)
|
|
227
|
+
rows = result.fetchall()
|
|
228
|
+
return rows
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
######################################################################
|
|
233
|
+
# Perform query and populate result set
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def run(results, cmdenv, tdb):
|
|
237
|
+
if cmdenv.lt and cmdenv.gt:
|
|
238
|
+
if cmdenv.lt <= cmdenv.gt:
|
|
239
|
+
raise CommandLineError("--gt must be lower than --lt")
|
|
240
|
+
|
|
241
|
+
# Find out what we're looking for.
|
|
242
|
+
queries, mode = get_lookup_list(cmdenv, tdb)
|
|
243
|
+
cmdenv.DEBUG0("{} query: {}", mode, queries.values())
|
|
244
|
+
|
|
245
|
+
avoidSystems = {s for s in cmdenv.avoidPlaces if isinstance(s, System)}
|
|
246
|
+
avoidStations = {s for s in cmdenv.avoidPlaces if isinstance(s, Station)}
|
|
247
|
+
|
|
248
|
+
# Summarize
|
|
249
|
+
results.summary = ResultRow()
|
|
250
|
+
results.summary.mode = mode
|
|
251
|
+
results.summary.queries = queries
|
|
252
|
+
results.summary.oneStop = cmdenv.oneStop
|
|
253
|
+
results.summary.avoidSystems = avoidSystems
|
|
254
|
+
results.summary.avoidStations = avoidStations
|
|
255
|
+
|
|
256
|
+
# In single mode with detail enabled, add average reports.
|
|
257
|
+
# Thus if you're looking up "algae" or the "asp", it'll
|
|
258
|
+
# tell you the average/ship cost.
|
|
259
|
+
singleMode = len(queries) == 1
|
|
260
|
+
if singleMode and cmdenv.detail:
|
|
261
|
+
first = list(queries.values())[0]
|
|
262
|
+
if mode is SHIP_MODE:
|
|
263
|
+
results.summary.avg = first.cost
|
|
264
|
+
else:
|
|
265
|
+
# Portable AVG with named bind; eager scalar fetch
|
|
266
|
+
with tdb.engine.connect() as conn:
|
|
267
|
+
avg_val = conn.execute(
|
|
268
|
+
text("""
|
|
269
|
+
SELECT AVG(si.supply_price) AS avg_price
|
|
270
|
+
FROM StationItem AS si
|
|
271
|
+
WHERE si.item_id = :item_id AND si.supply_price > 0
|
|
272
|
+
"""),
|
|
273
|
+
{"item_id": first.ID},
|
|
274
|
+
).scalar()
|
|
275
|
+
results.summary.avg = int(avg_val or 0)
|
|
276
|
+
|
|
277
|
+
# System-based search
|
|
278
|
+
nearSystem = cmdenv.nearSystem
|
|
279
|
+
if nearSystem:
|
|
280
|
+
maxLy = cmdenv.maxLyPer or cmdenv.maxSystemLinkLy
|
|
281
|
+
results.summary.near = nearSystem
|
|
282
|
+
results.summary.ly = maxLy
|
|
283
|
+
distanceFn = nearSystem.distanceTo
|
|
284
|
+
else:
|
|
285
|
+
distanceFn = None
|
|
286
|
+
|
|
287
|
+
oneStopMode = cmdenv.oneStop
|
|
288
|
+
padSize = cmdenv.padSize
|
|
289
|
+
planetary = cmdenv.planetary
|
|
290
|
+
fleet = cmdenv.fleet
|
|
291
|
+
odyssey = cmdenv.odyssey
|
|
292
|
+
wantNoPlanet = cmdenv.noPlanet
|
|
293
|
+
wantBlackMarket = cmdenv.blackMarket
|
|
294
|
+
mls = cmdenv.maxLs
|
|
295
|
+
|
|
296
|
+
stations = defaultdict(list)
|
|
297
|
+
stationByID = tdb.stationByID
|
|
298
|
+
|
|
299
|
+
cur = sql_query(cmdenv, tdb, queries, mode)
|
|
300
|
+
for (ID, stationID, price, units) in cur:
|
|
301
|
+
station = stationByID[stationID]
|
|
302
|
+
if padSize and not station.checkPadSize(padSize):
|
|
303
|
+
continue
|
|
304
|
+
if planetary and not station.checkPlanetary(planetary):
|
|
305
|
+
continue
|
|
306
|
+
if fleet and not station.checkFleet(fleet):
|
|
307
|
+
continue
|
|
308
|
+
if odyssey and not station.checkOdyssey(odyssey):
|
|
309
|
+
continue
|
|
310
|
+
if wantNoPlanet and station.planetary != 'N':
|
|
311
|
+
continue
|
|
312
|
+
if wantBlackMarket and station.blackMarket != 'Y':
|
|
313
|
+
continue
|
|
314
|
+
if station in avoidStations:
|
|
315
|
+
continue
|
|
316
|
+
if station.system in avoidSystems:
|
|
317
|
+
continue
|
|
318
|
+
maxAge, stnAge = cmdenv.maxAge, station.dataAge or float("inf")
|
|
319
|
+
if maxAge and stnAge > maxAge:
|
|
320
|
+
continue
|
|
321
|
+
|
|
322
|
+
row = ResultRow()
|
|
323
|
+
row.station = station
|
|
324
|
+
if mls:
|
|
325
|
+
distanceFromStar = station.lsFromStar
|
|
326
|
+
if distanceFromStar > mls:
|
|
327
|
+
continue
|
|
328
|
+
if distanceFn:
|
|
329
|
+
distance = distanceFn(row.station.system)
|
|
330
|
+
if distance > maxLy:
|
|
331
|
+
continue
|
|
332
|
+
row.dist = distance
|
|
333
|
+
row.item = queries[ID]
|
|
334
|
+
row.price = price
|
|
335
|
+
row.units = units
|
|
336
|
+
row.age = station.itemDataAgeStr
|
|
337
|
+
if oneStopMode:
|
|
338
|
+
stationRows = stations[stationID]
|
|
339
|
+
stationRows.append(row)
|
|
340
|
+
if len(stationRows) >= len(queries):
|
|
341
|
+
results.rows.extend(stationRows)
|
|
342
|
+
else:
|
|
343
|
+
results.rows.append(row)
|
|
344
|
+
|
|
345
|
+
if not results.rows:
|
|
346
|
+
if oneStopMode and len(stations):
|
|
347
|
+
raise NoDataError("No one-stop stations found")
|
|
348
|
+
raise NoDataError("No available items found")
|
|
349
|
+
|
|
350
|
+
if oneStopMode and not singleMode:
|
|
351
|
+
results.rows.sort(key = lambda result: result.item.name())
|
|
352
|
+
results.rows.sort(key = lambda result: result.station.name())
|
|
353
|
+
if cmdenv.sortByUnits:
|
|
354
|
+
results.summary.sort = "units"
|
|
355
|
+
results.rows.sort(key = lambda result: result.price)
|
|
356
|
+
results.rows.sort(key = lambda result: result.units, reverse = True)
|
|
357
|
+
else:
|
|
358
|
+
if not oneStopMode:
|
|
359
|
+
results.summary.sort = "Price"
|
|
360
|
+
results.rows.sort(key = lambda result: result.units, reverse = True)
|
|
361
|
+
results.rows.sort(key = lambda result: result.price)
|
|
362
|
+
if nearSystem and not cmdenv.sortByPrice:
|
|
363
|
+
results.summary.sort = "Ly"
|
|
364
|
+
results.rows.sort(key = lambda result: result.dist)
|
|
365
|
+
|
|
366
|
+
limit = cmdenv.limit or 0
|
|
367
|
+
if limit > 0:
|
|
368
|
+
results.rows = results.rows[:limit]
|
|
369
|
+
|
|
370
|
+
return results
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
#######################################################################
|
|
375
|
+
# # Transform result set into output
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def render(results, cmdenv, tdb):
|
|
379
|
+
mode = results.summary.mode
|
|
380
|
+
singleMode = len(results.summary.queries) == 1
|
|
381
|
+
maxStnLen = max_len(results.rows, key = lambda row: row.station.name())
|
|
382
|
+
|
|
383
|
+
stnRowFmt = RowFormat()
|
|
384
|
+
stnRowFmt.addColumn('Station', '<', maxStnLen,
|
|
385
|
+
key = lambda row: row.station.name())
|
|
386
|
+
if not singleMode:
|
|
387
|
+
maxItmLen = max_len(results.rows, key = lambda row: row.item.name(cmdenv.detail))
|
|
388
|
+
stnRowFmt.addColumn(results.summary.mode, '<', maxItmLen,
|
|
389
|
+
key = lambda row: row.item.name(cmdenv.detail)
|
|
390
|
+
)
|
|
391
|
+
if mode is not SHIP_MODE or not singleMode:
|
|
392
|
+
stnRowFmt.addColumn('Cost', '>', 10, 'n',
|
|
393
|
+
key = lambda row: row.price)
|
|
394
|
+
if mode is not SHIP_MODE:
|
|
395
|
+
stnRowFmt.addColumn('Units', '>', 10,
|
|
396
|
+
key = lambda row: '{:n}'.format(row.units) if row.units >= 0 else '?')
|
|
397
|
+
|
|
398
|
+
if cmdenv.nearSystem:
|
|
399
|
+
stnRowFmt.addColumn('DistLy', '>', 6, '.2f',
|
|
400
|
+
key = lambda row: row.dist)
|
|
401
|
+
|
|
402
|
+
if mode is not SHIP_MODE:
|
|
403
|
+
stnRowFmt.addColumn('Age/days', '>', 7,
|
|
404
|
+
key = lambda row: row.age)
|
|
405
|
+
stnRowFmt.addColumn("StnLs", '>', 10,
|
|
406
|
+
key = lambda row: row.station.distFromStar())
|
|
407
|
+
stnRowFmt.addColumn('B/mkt', '>', 4,
|
|
408
|
+
key = lambda row: TradeDB.marketStates[row.station.blackMarket])
|
|
409
|
+
stnRowFmt.addColumn("Pad", '>', '3',
|
|
410
|
+
key = lambda row: TradeDB.padSizes[row.station.maxPadSize])
|
|
411
|
+
stnRowFmt.addColumn("Plt", '>', '3',
|
|
412
|
+
key = lambda row: TradeDB.planetStates[row.station.planetary])
|
|
413
|
+
stnRowFmt.addColumn("Flc", '>', '3',
|
|
414
|
+
key = lambda row: TradeDB.fleetStates[row.station.fleet])
|
|
415
|
+
stnRowFmt.addColumn("Ody", '>', '3',
|
|
416
|
+
key = lambda row: TradeDB.odysseyStates[row.station.odyssey])
|
|
417
|
+
|
|
418
|
+
if not cmdenv.quiet:
|
|
419
|
+
heading, underline = stnRowFmt.heading()
|
|
420
|
+
print(heading, underline, sep = '\n')
|
|
421
|
+
|
|
422
|
+
for row in results.rows:
|
|
423
|
+
print(stnRowFmt.format(row))
|
|
424
|
+
|
|
425
|
+
if singleMode and cmdenv.detail:
|
|
426
|
+
msg = "-- Ship Cost" if mode is SHIP_MODE else "-- Average"
|
|
427
|
+
print(f"{msg:{maxStnLen}} {results.summary.avg:>10n}")
|