diff --git a/CHANGES.txt b/CHANGES.txt index 81353caf..805ce80b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,20 @@ TradeDangerous, Copyright (C) Oliver "kfsone" Smith, July 2014 ============================================================================== +v6.0.4 Nov 21 2014 (Beta 3.9.1) +. (kfsone) Added "sell" command (find places to sell a specific item) +. (kfsone) Reactive Armor changed to Reactive Armour +. (kfsone) Added 'Chemical Waste' +. (kfsone) Update GUI now consistently selects text on entering a cell +. (kfsone) Update GUI now selects the first column of the first line on startup +. (kfsone) Update GUI now supports up/down key inputs and has a default size +. (kfsone) Issue#57 Fixed extra cache rebuilds after doing an 'update' +. (kfsone) Changing .prices won't force a full rebuild of the cache +. (kfsone) Better integrated update gui (improved startup times) +. (kfsone) Added "--all" (-A) option to 'update -G' to show ALL items +. (kfsone) (Update GUI) Set 'selling' and 'asking' to 0 to delete an item +. (kfsone) Fixed "buy" command showing multiple hits for multi-station systems + v6.0.3 Nov 21 2014 . (kfsone) Added a GUI to the "update" sub-command, it's experimental: - Use / to cycle across rows, diff --git a/README.txt b/README.txt index 5f1c50a0..66b24664 100644 --- a/README.txt +++ b/README.txt @@ -535,6 +535,44 @@ LOCAL sub-command: == ADDING OR CHANGING PRICE DATA ============================================================================== +*** Experimental GUI in 6.0 *** +******************************* + + +As of v6.0 I've added an experimental GUI for updating prices. I'm still +working out some of the issues, in particular you currently have to manually +size and scroll the window. + +To use it, simply type: + + trade.py update Aulin + +or whichever station you need to update. While it is in experimental status, +you'll be asked to provide an extra switch. + +- To save your changes: + +Click the window's close button, don't alt-f4 or command-q. + +- To remove an item: + +Set the 'paying' and 'asking' values to 0 + +- To move around + + . Use tab/shift-tab to cycle thru cells, + . Use up/down arrows to move between rows, + . Press ENTER to move to the first column of the next line, + +- To add items to a station: + +Use the "-A" switch and leave the items you don't want empty. + + +*** Other ways of editing Price Data *** +**************************************** + + TradeDangerous uses a human-readable text format for price information. This is designed to closely resemble what we see in the market screens in-game. @@ -660,3 +698,4 @@ loading" by functions like TradeCalc.getBestHops(). When TradeDB and TradeCalc do not currently provide built-in queries for the information you need, you can revert to the SQL Database with the TradeDB.query() and TradeDB.fetch_all() commands. + diff --git a/cache.py b/cache.py index fbd36006..07152707 100644 --- a/cache.py +++ b/cache.py @@ -155,6 +155,16 @@ def __init__(self, fromFile, lineNo, itemName): error = "Unrecognized item name, '{}'.".format(itemName) super().__init__(fromFile, lineNo, error) +class UnknownCategoryError(BuildCacheBaseException): + """ + Raised in the case of a categrory name that we don't know. + Attributes: + categoryName Key we tried to look up. + """ + def __init__(self, fromFile, lineNo, categoryName): + error = "Unrecognized category name, '{}'.".format(categoryName) + super().__init__(fromFile, lineNo, error) + class DuplicateKeyError(BuildCacheBaseException): """ @@ -366,7 +376,8 @@ def changeStation(matches): ### Change current station categoryID, uiOrder = None, 0 - systemName, stationName = matches.group(1, 2) + systemNameIn, stationNameIn = matches.group(1, 2) + systemName, stationName = systemNameIn, stationNameIn facility = systemName.upper() + '/' + stationName.upper() tdenv.DEBUG1("NEW STATION: {}", facility) @@ -379,7 +390,7 @@ def changeStation(matches): if stationID < 0: systemName = corrections.correctSystem(systemName) - stationName = corrections.correctStation(stationName) + stationName = corrections.correctStation(systemName, stationName) if systemName == DELETED or stationName == DELETED: tdenv.DEBUG1("DELETED: {}", facility) stationID = DELETED @@ -388,7 +399,29 @@ def changeStation(matches): stationID = systemByName[facility] tdenv.DEBUG0("Renamed: {}", facility) except KeyError: - raise UnknownStationError(priceFile, lineNo, facility) from None + if tdenv.corrections: + ### HACK: HERE BE DRAEGONS + # Stations we didn't have a name for are named {STAR}-STATION, + # this is a catch-all for the case where we have a .prices + # that provides the actual name for the station but we don't + # yet have a corrections.py/Station.csv entry for it. + # Run with --corrections to generate a list of corrections.py + # additions. + altStationName = systemName.upper() + "-STATION" + altFacility = systemName.upper() + '/' + altStationName + try: + stationID = systemByName[altFacility] + except KeyError: + stationID = -1 + if stationID >= 0: + facility = altFacility + if altStationName in corrections.stations: + raise Exception(altStationName + " conflicts") + print(" \"{}\": \"{}\",".format( + facility, stationNameIn, + ), file=sys.stderr) + if stationID < 0 : + raise UnknownStationError(priceFile, lineNo, facility) from None # Check for duplicates if stationID in processedStations: @@ -400,6 +433,12 @@ def changeStation(matches): processedStations[stationID] = lineNo processedItems = {} + # Clear old entries for this station. + db.execute( + "DELETE FROM StationItem WHERE station_id = ?", + [stationID] + ) + def changeCategory(matches): nonlocal uiOrder, categoryID @@ -422,7 +461,7 @@ def changeCategory(matches): categoryID = categoriesByName[categoryName] tdenv.DEBUG1("Renamed: {}", categoryName) except KeyError: - raise UnknownCategoryError(priceFile, lineNo, facility) + raise UnknownCategoryError(priceFile, lineNo, categoryName) def processItemLine(matches): @@ -452,7 +491,6 @@ def processItemLine(matches): except KeyError: itemID = -1 if itemID < 0: - print("correcting") oldName = itemName itemName = corrections.correctItem(itemName) if itemName == DELETED: @@ -531,16 +569,9 @@ def processItemLine(matches): ###################################################################### -def processPricesFile(tdenv, db, pricesPath, stationID=None, defaultZero=False): +def processPricesFile(tdenv, db, pricesPath, defaultZero=False): tdenv.DEBUG0("Processing Prices file '{}'", pricesPath) - if stationID: - tdenv.DEBUG0("Deleting stale entries for {}", stationID) - db.execute( - "DELETE FROM StationItem WHERE station_id = ?", - [stationID] - ) - with pricesPath.open() as pricesFile: items, buys, sells = [], [], [] for price in genSQLFromPriceLines(tdenv, pricesFile, db, defaultZero): @@ -592,7 +623,7 @@ def deprecationCheckStation(line, debug): if debug: print("! Station.csv: deprecated system: {}".format(line[0])) line[0] = correctSystem - correctStation = corrections.correctStation(line[1]) + correctStation = corrections.correctStation(correctSystem, line[1]) if correctStation != line[1]: if debug: print("! Station.csv: deprecated station: {}".format(line[1])) line[1] = correctStation @@ -792,3 +823,39 @@ def buildCache(tdenv, dbPath, sqlPath, pricesPath, importTables, defaultZero=Fal tdenv.DEBUG0("Finished") + +###################################################################### + +def importDataFromFile(tdenv, tdb, path, reset=False): + """ + Import price data from a file on a per-station basis, + that is when a new station is encountered, delete any + existing records for that station in the database. + """ + + if reset: + tdenv.DEBUG0("Resetting price data") + tdb.getDB().execute("DELETE FROM StationItem") + + tdenv.DEBUG0("Importing data from {}".format(str(path))) + processPricesFile(tdenv, + db=tdb.getDB(), + pricesPath=path, + defaultZero=tdenv.forceNa, + ) + + # If everything worked, we may need to re-build the prices file. + if path != tdb.pricesPath: + import prices + tdenv.DEBUG0("Update complete, regenerating .prices file") + with tdb.pricesPath.open("w") as pricesFile: + prices.dumpPrices( + tdb.dbURI, + prices.Element.full, + file=pricesFile, + debug=tdenv.debug) + + # Update the DB file so we don't regenerate it. + os.utime(tdb.dbURI) + + diff --git a/commands/__init__.py b/commands/__init__.py index f3b22463..5dcbd562 100644 --- a/commands/__init__.py +++ b/commands/__init__.py @@ -15,6 +15,7 @@ 'local', 'nav', 'run', + 'sell', 'update', 'export', ] diff --git a/commands/buildcache_cmd.py b/commands/buildcache_cmd.py index 412f1f73..b54df89e 100644 --- a/commands/buildcache_cmd.py +++ b/commands/buildcache_cmd.py @@ -30,7 +30,17 @@ ParseArgument( '-f', '--force', default=False, action='store_true', dest='force', - help='Overwite existing file', + help='Overwrite existing file', + ), + ParseArgument( + '--corrections', default=False, action='store_true', + help=( + "EXPERT: " + "Allow- and generate corrections for- station names that " + "replace a defaulted station name. Corrections are " + "printed to stderr so you can capture them and add them " + "to your data/corrections.py." + ) ), ] diff --git a/commands/buy_cmd.py b/commands/buy_cmd.py index 79f1dee7..cb9ede84 100644 --- a/commands/buy_cmd.py +++ b/commands/buy_cmd.py @@ -97,7 +97,7 @@ def run(results, cmdenv, tdb): whereClause = ' AND '.join(constraints) stmt = """ - SELECT {columns} + SELECT DISTINCT {columns} FROM {tables} WHERE {where} """.format( diff --git a/commands/nav_cmd.py b/commands/nav_cmd.py index 61b5ad13..d459ec46 100644 --- a/commands/nav_cmd.py +++ b/commands/nav_cmd.py @@ -117,7 +117,7 @@ def run(results, cmdenv, tdb): results.rows.append(row) lastHop = hop results.rows[0].action='Depart' - results.rows[1].action='Arrive' + results.rows[-1].action='Arrive' return results diff --git a/commands/sell_cmd.py b/commands/sell_cmd.py new file mode 100644 index 00000000..199a07d5 --- /dev/null +++ b/commands/sell_cmd.py @@ -0,0 +1,153 @@ +from __future__ import absolute_import, with_statement, print_function, division, unicode_literals +from commands.parsing import MutuallyExclusiveGroup, ParseArgument +from commands.exceptions import * +import math + +###################################################################### +# Parser config + +help='Find places to sell a given item within range of a given station.' +name='sell' +epilog=None +wantsTradeDB=True +arguments = [ + ParseArgument('item', help='Name of item you want to sell.', type=str), +] +switches = [ + ParseArgument('--near', + help='Find buyers within jump range of this system.', + type=str + ), + ParseArgument('--ly-per', + help='Maximum light years per jump.', + default=None, + dest='maxLyPer', + metavar='N.NN', + type=float, + ), + ParseArgument('--limit', + help='Maximum number of results to list.', + default=None, + type=int, + ), + ParseArgument('--price-sort', '-P', + help='(When using --near) Sort by price not distance', + action='store_true', + default=False, + dest='sortByPrice', + ), +] + +###################################################################### +# Perform query and populate result set + +def run(results, cmdenv, tdb): + from commands.commandenv import ResultRow + + item = tdb.lookupItem(cmdenv.item) + cmdenv.DEBUG0("Looking up item {} (#{})", item.name(), item.ID) + + # Constraints + tables = "StationBuying AS sb" + constraints = [ "(item_id = {})".format(item.ID) ] + columns = [ 'sb.station_id', 'sb.price', 'sb.units' ] + bindValues = [ ] + + if cmdenv.quantity: + constraints.append("(units = -1 or units >= ?)") + bindValues.append(cmdenv.quantity) + + results.summary = ResultRow() + results.summary.item = item + + nearSystem = cmdenv.nearSystem + distances = dict() + if nearSystem: + maxLy = cmdenv.maxLyPer or tdb.maxSystemLinkLy + results.summary.near = nearSystem + results.summary.ly = maxLy + + cmdenv.DEBUG0("Searching within {}ly of {}", maxLy, nearSystem.name()) + tables += ( + " INNER JOIN StationLink AS sl" + " ON (sl.rhs_station_id = sb.station_id)" + ) + columns.append('sl.dist') + constraints.append("(lhs_system_id = {})".format( + nearSystem.ID + )) + constraints.append("(dist <= {})".format( + maxLy + )) + else: + columns += [ '0' ] + + whereClause = ' AND '.join(constraints) + stmt = """ + SELECT DISTINCT {columns} + FROM {tables} + WHERE {where} + """.format( + columns=','.join(columns), + tables=tables, + where=whereClause + ) + cmdenv.DEBUG0('SQL: {}', stmt) + cur = tdb.query(stmt, bindValues) + + stationByID = tdb.stationByID + for (stationID, priceCr, demand, dist) in cur: + row = ResultRow() + row.station = stationByID[stationID] + cmdenv.DEBUG2("{} {}cr {} units", row.station.name(), priceCr, demand) + if nearSystem: + row.dist = dist + row.price = priceCr + row.demand = demand + results.rows.append(row) + + if not results.rows: + raise NoDataError("No available items found") + + results.summary.sort = "Price" + results.rows.sort(key=lambda result: result.demand, reverse=True) + results.rows.sort(key=lambda result: result.price, reverse=True) + if nearSystem and not cmdenv.sortByPrice: + results.summary.sort = "Dist" + results.rows.sort(key=lambda result: result.dist) + + limit = cmdenv.limit or 0 + if limit > 0: + results.rows = results.rows[:limit] + + return results + + +####################################################################### +## Transform result set into output + +def render(results, cmdenv, tdb): + from formatting import RowFormat, ColumnFormat + + longestNamed = max(results.rows, key=lambda result: len(result.station.name())) + longestNameLen = len(longestNamed.station.name()) + + stnRowFmt = RowFormat() + stnRowFmt.addColumn('Station', '<', longestNameLen, + key=lambda row: row.station.name()) + stnRowFmt.addColumn('Cost', '>', 10, 'n', + key=lambda row: row.price) + if cmdenv.detail: + stnRowFmt.addColumn('Demand', '>', 10, + key=lambda row: '{:n}'.format(row.demand) if row.demand >= 0 else 'unknown') + if cmdenv.nearSystem: + stnRowFmt.addColumn('Dist', '>', 6, '.2f', + key=lambda row: row.dist) + + if not cmdenv.quiet: + heading, underline = stnRowFmt.heading() + print(heading, underline, sep='\n') + + for row in results.rows: + print(stnRowFmt.format(row)) + diff --git a/commands/update_cmd.py b/commands/update_cmd.py index ef69a256..3c079a2b 100644 --- a/commands/update_cmd.py +++ b/commands/update_cmd.py @@ -40,6 +40,11 @@ action='store_true', default=False, ), + ParseArgument('--all', '-A', + help='List all known items.', + action='store_true', + default=False, + ), ParseArgument('--force-na', '-0', help="Forces 'unk' supply to become 'n/a' by default", action='store_true', @@ -80,24 +85,24 @@ class TemporaryFileExistsError(TradeException): def getTemporaryPath(cmdenv): - tmpPath = pathlib.Path("prices.tmp") - if tmpPath.exists(): - if not cmdenv.force: - raise TemporaryFileExistsError( - "Temporary file already exists: {}\n" - "(Check you aren't already editing in another window" - .format(tmpPath) - ) - tmpPath.unlink() - return tmpPath + tmpPath = pathlib.Path("prices.tmp") + if tmpPath.exists(): + if not cmdenv.force: + raise TemporaryFileExistsError( + "Temporary file already exists: {}\n" + "(Check you aren't already editing in another window" + .format(tmpPath) + ) + tmpPath.unlink() + return tmpPath def saveTemporaryFile(tmpPath): - if tmpPath.exists(): - lastPath = pathlib.Path("prices.last") - if lastPath.exists(): - lastPath.unlink() - tmpPath.rename(lastPath) + if tmpPath.exists(): + lastPath = pathlib.Path("prices.last") + if lastPath.exists(): + lastPath.unlink() + tmpPath.rename(lastPath) def getEditorPaths(cmdenv, editorName, envVar, windowsFolders, winExe, nixExe): @@ -138,25 +143,6 @@ def getEditorPaths(cmdenv, editorName, envVar, windowsFolders, winExe, nixExe): ) -def importDataFromFile(cmdenv, tdb, path, stationID, dbFilename): - cmdenv.DEBUG0("Importing data from {}".format(str(path))) - cache.processPricesFile(cmdenv, - db=tdb.getDB(), - pricesPath=path, - stationID=stationID, - defaultZero=cmdenv.forceNa - ) - - # If everything worked, we need to re-build the prices file. - cmdenv.DEBUG0("Update complete, regenerating .prices file") - - with tdb.pricesPath.open("w") as pricesFile: - prices.dumpPrices(dbFilename, prices.Element.full, file=pricesFile, debug=cmdenv.debug) - - # Update the DB file so we don't regenerate it. - pathlib.Path(dbFilename).touch() - - def editUpdate(tdb, cmdenv, stationID): """ Dump the price data for a specific station to a file and @@ -264,7 +250,7 @@ def editUpdate(tdb, cmdenv, stationID): "Suit you, sir! Oh!" ]))) else: - importDataFromFile(cmdenv, tdb, tmpPath, stationID, dbFilename) + cache.importDataFromFile(cmdenv, tdb, tmpPath) tmpPath.unlink() tmpPath = None @@ -272,21 +258,26 @@ def editUpdate(tdb, cmdenv, stationID): finally: # Save a copy if absoluteFilename and tmpPath: - saveTemporaryFile(tmpPath) + saveTemporaryFile(tmpPath) def guidedUpdate(tdb, cmdenv): - stationID = cmdenv.startStation.ID - dbFilename = cmdenv.dbFilename or tdb.defaultDB - tmpPath = getTemporaryPath(cmdenv) - - from commands.update_gui import render - try: - render(tdb.dbPath, stationID, tmpPath) - cmdenv.DEBUG0("Got results, importing") - importDataFromFile(cmdenv, tdb, tmpPath, stationID, dbFilename) - finally: - saveTemporaryFile(tmpPath) + dbFilename = cmdenv.dbFilename or tdb.defaultDB + tmpPath = getTemporaryPath(cmdenv) + + from commands.update_gui import render + try: + render(tdb, cmdenv, tmpPath) + cmdenv.DEBUG0("Got results, importing") + cache.importDataFromFile(cmdenv, tdb, tmpPath) + except Exception as e: + print("*** ERROR ENCOUNTERED ***") + print("*** YOUR UPDATES WILL BE SAVED AS {} ***".format( + "prices.last" + )) + raise + finally: + saveTemporaryFile(tmpPath) ###################################################################### diff --git a/commands/update_gui.py b/commands/update_gui.py index dd567157..8269aff3 100644 --- a/commands/update_gui.py +++ b/commands/update_gui.py @@ -10,25 +10,18 @@ def __init__(self, ID, catID, name, displayNo): self.displayNo = displayNo -class UpdateFrame(tk.Frame): - def __init__(self, root, dbPath, stationID): - tk.Frame.__init__(self, root) +class UpdateGUI(tk.Canvas): + """ + Implements a tk canvas which displays an editor + for TradeDangerous Price Updates + """ - self.root = root - self.style = ttk.Style() - self.style.theme_use("default") - - self.canvas = tk.Canvas(root, borderwidth=0) - self.canvas.bind_all("", self.onMouseWheel) - self.frame = tk.Frame(self.canvas) - self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview) - self.canvas.configure(yscrollcommand=self.vsb.set) - - self.vsb.pack(side="right", fill="y") - self.canvas.pack(side="left", fill="both", expand=True) - self.canvas.create_window((4,4), window=self.frame, anchor="nw", tags="self.frame") + def __init__(self, root, tdb, cmdenv): + super().__init__(root, borderwidth=0, width=500, height=440) - self.frame.bind("", self.onFrameConfigure) + self.root = root + self.tdb = tdb + self.cmdenv = cmdenv self.rowNo = 0 self.colNo = 0 @@ -39,39 +32,77 @@ def __init__(self, root, dbPath, stationID): self.results = None self.headings = [] - self.createWidgets(dbPath, stationID) + self.bind_all("", self.onMouseWheel) + self.vsb = tk.Scrollbar(root, orient="vertical", command=self.yview) + self.configure(yscrollcommand=self.vsb.set) + self.vsb.pack(side="right", fill="y") + + self.frame = tk.Frame(self) + self.frame.bind("", self.onFrameConfigure) + self.frame.rowconfigure(0, weight=1) + self.frame.columnconfigure(0, weight=1) + + self.createWidgets() + + self.focusOn(0, 0) + + self.create_window((4,4), window=self.frame, anchor="nw", tags="self.frame") + self.pack(fill=tk.BOTH, expand=True) + def onFrameConfigure(self, event): - self.canvas.configure(scrollregion=self.canvas.bbox("all")) + """ Handle the event for the frame """ + + self.configure(scrollregion=self.bbox("all")) def onMouseWheel(self, event): - self.canvas.yview_scroll(int(-1 * (event.delta/120)), "units") + """ Translate mouse wheel inputs to scroll bar motions """ + + self.yview_scroll(int(-1 * (event.delta/120)), "units") + + + def focusOn(self, displayNo, pos): + """ Set focus to a widget and select the text in it """ + + row = self.itemDisplays[displayNo] + widget = row[pos][0] + widget.focus_set() + widget.selection_range(0, tk.END) def query(self, itemName, pos): + """ Find the cell for a given item name and a position """ + item = self.items[itemName] row = self.itemDisplays[item.displayNo] return item, row, row[pos][1].get() def validate(self, item, row, value, pos): + """ For checking the contents of a widget. TBD """ + return True - def handleShiftTab(self, itemName, pos, event): + def onShiftTab(self, itemName, pos, event): + """ Process user pressing Shift+TAB """ + item, row, value = self.query(itemName, pos) if not self.validate(item, row, value, pos): return if pos > 0 or item.displayNo > 0: # Natural flow return + self.root.bell() return "break" - def handleTab(self, itemName, pos, event): + def onTab(self, itemName, pos, event): + """ Process user pressing TAB """ + item, row, value = self.query(itemName, pos) if not self.validate(item, row, value, pos): return @@ -83,7 +114,13 @@ def handleTab(self, itemName, pos, event): return "break" - def handleReturn(self, itemName, pos, event): + def onReturn(self, itemName, pos, event): + """ + When the user hits , advance to + the first cell on the next line, or if + we are at the bottom of the list, beep. + """ + item, row, value = self.query(itemName, pos) if not self.validate(item, row, value, pos): return @@ -92,8 +129,37 @@ def handleReturn(self, itemName, pos, event): if newDisplayNo >= len(self.itemDisplays): self.root.bell() return "break" - row = self.itemDisplays[newDisplayNo] - row[0][0].focus_set() + + self.focusOn(newDisplayNo, 0) + + + def onUp(self, itemName, pos, event): + """ Handle the user pressing up, go up a row """ + + item, row, value = self.query(itemName, pos) + if not self.validate(item, row, value, pos): + return + # can we go up a line? + if item.displayNo <= 0: + self.root.bell() + return "break" + + self.focusOn(item.displayNo - 1, pos) + + + def onDown(self, itemName, pos, event): + """ Handle the user pressing down, go down a row """ + + item, row, value = self.query(itemName, pos) + if not self.validate(item, row, value, pos): + return + # can we go up a line? + newDisplayNo = item.displayNo + 1 + if newDisplayNo >= len(self.itemDisplays): + self.root.bell() + return "break" + + self.focusOn(newDisplayNo, pos) def endRow(self): @@ -130,11 +196,15 @@ def addInput(self, item, defValue, row): justify=tk.RIGHT, textvariable=inputVal) inputEl.bind('', - lambda evt: self.handleShiftTab(item, pos, evt)) + lambda evt: self.onShiftTab(item, pos, evt)) inputEl.bind('', - lambda evt: self.handleTab(item, pos, evt)) + lambda evt: self.onTab(item, pos, evt)) inputEl.bind('', - lambda evt: self.handleReturn(item, pos, evt)) + lambda evt: self.onReturn(item, pos, evt)) + inputEl.bind('', + lambda evt: self.onDown(item, pos, evt)) + inputEl.bind('', + lambda evt: self.onUp(item, pos, evt)) self.addWidget(inputEl, sticky='E') row.append((inputEl, inputVal)) @@ -160,7 +230,7 @@ def addItemRow(self, ID, catID, itemName, paying, asking, demand, stock): self.items[itemName] = item self.itemList.append(item) - self.addLabel(itemName) + self.addLabel(itemName.upper()) self.addInput(itemName, paying, row) self.addInput(itemName, asking, row) self.addInput(itemName, demand, row) @@ -171,54 +241,48 @@ def addItemRow(self, ID, catID, itemName, paying, asking, demand, stock): self.endRow() - def createWidgets(self, dbPath, stationID): + def createWidgets(self): self.addHeadings() - db = sqlite3.connect(str(dbPath)) + tdb, cmdenv = self.tdb, self.cmdenv + station = cmdenv.startStation + self.root.title(station.name()) + + db = tdb.getDB() db.row_factory = sqlite3.Row cur = db.cursor() - cur.execute(""" - SELECT sys.name, stn.name - FROM Station AS stn - INNER JOIN System AS sys - USING (system_id) - WHERE stn.station_id = ? - LIMIT 1 - """, [stationID]) - (self.sysName, self.stnName) = (cur.fetchone()) - - self.root.title("{}/{}".format(self.sysName.upper(), self.stnName)) - - cur.execute(""" - SELECT cat.category_id AS ID, - cat.name AS name - FROM Category AS cat - """) - self.categories = { row["ID"]: row["name"] for row in cur } - - cur.execute(""" - SELECT item.category_id AS catID, - item.item_id AS ID, - item.name AS name, - IFNULL(sb.price, '') AS paying, - IFNULL(ss.price, '') AS asking, - IFNULL(sb.units, 0) AS demandUnits, - IFNULL(sb.level, 0) AS demandLevel, - IFNULL(ss.units, 0) AS stockUnits, - IFNULL(ss.level, 0) AS stockLevel - FROM Category AS cat - INNER JOIN Item item - USING (category_id) - INNER JOIN StationItem si - USING (item_id) - LEFT OUTER JOIN StationBuying sb - USING (station_id, item_id) - LEFT OUTER JOIN StationSelling ss - USING (station_id, item_id) - WHERE si.station_id = ? - ORDER BY cat.name, si.ui_order - """, [stationID]) + self.categories = self.tdb.categoryByID + + # if the user specified "--all", force listing of all items + siJoin = "INNER" if not cmdenv.all else "LEFT OUTER" + stmt = """ + SELECT item.category_id AS catID, + item.item_id AS ID, + item.name AS name, + IFNULL(sb.price, '') AS paying, + IFNULL(ss.price, '') AS asking, + IFNULL(sb.units, 0) AS demandUnits, + IFNULL(sb.level, 0) AS demandLevel, + IFNULL(ss.units, 0) AS stockUnits, + IFNULL(ss.level, 0) AS stockLevel + FROM ( + Category AS cat + INNER JOIN Item item + USING (category_id) + ) {siJoin} JOIN + StationItem si + ON (si.item_id = item.item_id + AND si.station_id = ?) + LEFT OUTER JOIN StationBuying sb + USING (station_id, item_id) + LEFT OUTER JOIN StationSelling ss + USING (station_id, item_id) + ORDER BY cat.name, si.ui_order, item.name + """.format( + siJoin=siJoin + ) + cur.execute(stmt, [station.ID]) def describeSupply(units, level): if not level: @@ -233,7 +297,7 @@ def describeSupply(units, level): for row in cur: cat = row["catID"] if cat != lastCat: - self.addSection(self.categories[cat]) + self.addSection(self.categories[cat].name()) lastCat = cat itemName = row["name"] paying, asking = row["paying"], row["asking"] @@ -248,15 +312,14 @@ def getResults(self): txt = ( "# Generated by TDGUI\n" "\n" - "@ {sys}/{stn}\n".format( - sys=self.sysName.upper(), - stn=self.stnName + "@ {stn}\n".format( + stn=self.cmdenv.startStation.name(), ) ) for item in self.itemList: if item.catID != lastCat: lastCat = item.catID - txt += (" + {}\n".format(self.categories[lastCat])) + txt += (" + {}\n".format(self.categories[lastCat].dbname)) row = self.itemDisplays[item.displayNo] rowvals = [ val[1].get() for val in row ] @@ -267,10 +330,14 @@ def getResults(self): demand = rowvals[2] stock = rowvals[3] + if not paying and not asking: + continue + + if paying and not demand: + demand = "?" + if asking == 0: stock = "-" - elif asking > 0 and not demand: - demand = "?" txt += (" {item:<30s} " "{paying:>10} " @@ -286,17 +353,17 @@ def getResults(self): self.results = txt -def render(dbPath, stationID, tmpPath): +def render(tdb, cmdenv, tmpPath): root = tk.Tk() - frame = UpdateFrame(root, dbPath, stationID) - frame.pack(side="top", fill="both", expand=True) - frame.mainloop() - if not frame.results: - frame.getResults() + gui = UpdateGUI(root, tdb, cmdenv) + gui.mainloop() + if not gui.results: + gui.getResults() with tmpPath.open("w") as fh: - print(frame.results, file=fh) + print(gui.results, file=fh) if __name__ == "__main__": render(Path("data/TradeDangerous.db"), 374, Path("update.prices")) print("- Wrote to update.prices") + diff --git a/data/AltItemNames.csv b/data/AltItemNames.csv index ab19c493..3eae13b6 100644 --- a/data/AltItemNames.csv +++ b/data/AltItemNames.csv @@ -6,5 +6,5 @@ unq:name@Item.item_id,unq:alt_name 'Microbial Furnaces','heliostaticfurnaces' 'Narcotics','basicnarcotics' 'Non-Lethal Wpns','nonlethalweapons' -'Reactive Armor','reactivearmour' +'Reactive Armour','reactivearmour' 'Land Enrichment Systems','terrainenrichmentsystems' diff --git a/data/Item.csv b/data/Item.csv index 351efb86..d65a16e4 100644 --- a/data/Item.csv +++ b/data/Item.csv @@ -74,8 +74,9 @@ name@Category.category_id,unq:name 'Textiles','Natural Fabrics' 'Textiles','Synthetic Fabrics' 'Waste','Biowaste' +'Waste','Chemical Waste' 'Waste','Scrap' 'Weapons','Battle Weapons' 'Weapons','Non-Lethal Wpns' 'Weapons','Personal Weapons' -'Weapons','Reactive Armor' +'Weapons','Reactive Armour' diff --git a/data/Station.csv b/data/Station.csv index d204f9f8..e73813b9 100644 --- a/data/Station.csv +++ b/data/Station.csv @@ -1,791 +1,377 @@ name@System.system_id,unq:name,ls_from_star '10 Canum Venaticorum','Janifer Port',0.0 -'10 Ursae Majoris','10 Ursae Majoris-Station',0.0 -'16 c Ursae Majoris','16 c Ursae Majoris-Station',0.0 -'17 Crateris','17 Crateris-Station',0.0 -'20 Leonis Minoris','20 Leonis Minoris-Station',0.0 '21 Draco','Roberts Port',0.0 -'24 Iota Crateris','24 Iota Crateris-Station',0.0 '26 Draconis','Bouch Beacon',0.0 -'35 Draconis','35 Draconis-Station',0.0 -'36 Ursae Majoris','36 Ursae Majoris-Station',0.0 +'36 Ursae Majoris','Liwei Outpost',0.0 '37 Xi Bootis','Schirba Plant',0.0 -'41 Gamma Serpentis','41 Gamma Serpentis-Station',0.0 -'44 chi Draconis','Lawson Camp',0.0 -'47 Cassiopeiae','47 Cassiopeiae-Station',0.0 -'47 Ursae Majoris','47 Ursae Majoris-Station',0.0 +'41 Gamma Serpentis','Abe Landing',0.0 +'44 Chi Draconis','Lawson Camp',0.0 +'47 URSAE MAJORIS','Avdeyev Beacon',0.0 '54 G. Antlia','Boas Orbital',0.0 -'59 Virginis','59 Virginis-Station',0.0 -'60 Tau Draconis','60 Tau Draconis-Station',0.0 -'61 Ursae Majoris','61 Ursae Majoris-Station',0.0 -'61 Virginis','61 Virginis-Station',0.0 -'66 Draconis','66 Draconis-Station',0.0 +'61 Ursae Majoris','Worlidge Dock',0.0 +'61 Virginis','Artsebarsky Station',0.0 '68 Draconis','Gaspar De Lemos Port',0.0 '70 Virginis','Reis Platform',0.0 -'Abrogo','Abrogo-Station',0.0 +'Abrogo','Laing Hub',0.0 'Acihaut','Cuffey Plant',0.0 'Acurukunabogamal','Aguirre Terminal',0.0 -'Adityaraguala','Adityaraguala-Station',0.0 -'Aegilips','Aegilips-Station',0.0 -'Aeneas','Aeneas-Station',0.0 'Aganippe','Julian Market',0.0 -'Agwe','Agwe-Station',0.0 'Akhenaten','Wang Platform',0.0 -'Aknango','Aknango-Station',0.0 -'Al Mina','Al Mina-Station',0.0 -'Aladu Kuan Gon','Aladu Kuan Gon-Station',0.0 -'Alchita','Alchita-Station',0.0 -'Alcor','Alcor-Station',0.0 -'Algorab','Algorab-Station',0.0 -'Alrai','Alrai-Station',0.0 +'Aknango','Banks Station',0.0 +'Al Mina','Dana Port',0.0 +'Alrai','Becquerel Gateway',0.0 'Ammapa','Bamford Enterprise',0.0 -'Amun','Amun-Station',0.0 -'Anaiwal','Anaiwal-Station',0.0 -'Andancan','Andancan-Station',0.0 'Andoe','Moffitt Settlement',0.0 -'Anemoi','Anemoi-Station',0.0 -'Anete','Anete-Station',0.0 -'Aninohini','Aninohini-Station',0.0 +'Anemoi','Abasheli Point',0.0 'Anlave','Suri Park',0.0 'Ansari','Wiberg Colony',0.0 -'Antevorta','Antevorta-Station',0.0 'Antinica','Benyovszky Terminal',0.0 -'Anyanwu','Anyanwu-Station',0.0 'Ao Guang','Kotov Settlement',0.0 'Ao Qin','Chapman Hub',0.0 -'Ao Shun','Ao Shun-Station',0.0 'Apalai','Gubarev Base',0.0 -'Apura','Apura-Station',0.0 +'Apura','Harris Dock',0.0 'Arcturus','Fort Harrison',0.0 'Arin','Kettle Landing',0.0 -'Asellus Primus','Foster Research Lab',171 -'Asellus Primus','Beagle 2 Landing',1252 -'Ashtart','Ashtart-Station',0.0 -'Atarapa','Atarapa-Station',0.0 -'Atum','Atum-Station',0.0 -'Audhisatsuri','Audhisatsuri-Station',0.0 -'Audusi','Audusi-Station',0.0 -'Aulin','Yurchikhin Gateway',60.2 -'Aulin','Aulin Enterprise',117 -'Aulin','Binnie City',347 -'Aulis','Aulis-Station',0.0 -'Aurvandill','Aurvandill-Station',0.0 -'Awabatamori','Awabatamori-Station',0.0 -'Awngtei','Awngtei-Station',0.0 -'Azaladshu','Azaladshu-Station',0.0 +'Asellus Primus','Beagle 2 Landing',0.0 +'Aulin','Aulin Enterprise',0.0 +'Aulis','Dezhurov Gateway',0.0 +'Azaladshu','Goddard Outpost',0.0 'Baga','Shipton Exchange',0.0 -'Balmus','Balmus-Station',0.0 -'Bast','Bast-Station',0.0 -'Batani','Batani-Station',0.0 +'Bast','White Hart Lane',0.0 'Baudus','Agnesi City',0.0 -'BD+03 2279','BD+03 2279-Station',0.0 -'BD+03 2316','BD+03 2316-Station',0.0 -'BD+16 2404','BD+16 2404-Station',0.0 -'BD+26 2184','BD+26 2184-Station',0.0 -'BD+27 1739','BD+27 1739-Station',0.0 'BD+29 2405','Shaara City',0.0 -'BD+47 2112','Olivas Settlement',230 +'BD+47 2112','Olivas Settlement',0.0 'BD+55 1519','Eskridge Orbital',0.0 -'BD+57 2595','BD+57 2595-Station',0.0 -'BD+63 1764','BD+63 1764-Station',0.0 -'BD+64 1452','BD+64 1452-Station',0.0 'BD+65 1846','Shargin Beacon',0.0 -'BD+66 193','BD+66 193-Station',0.0 -'BD+67 1409','BD+67 1409-Station',0.0 -'BD+71 1033','BD+71 1033-Station',0.0 -'BD+72 545','BD+72 545-Station',0.0 +'BD+71 1033','Fourneyron Port',0.0 'BD+74 526','Smith Prospect',0.0 -'BD+87 118','BD+87 118-Station',0.0 -'BD-01 2784','BD-01 2784-Station',0.0 -'BD-18 3106','BD-18 3106-Station',0.0 -'Begou','Begou-Station',0.0 -'Belobog','Belobog-Station',0.0 'BF Canis Venatici','Kornbluth Dock',0.0 -'Bhaguti','Bhaguti-Station',0.0 -'Bhotega','Buchli Port',114 -'Bhotega','Newton Station',167 -'Bhotepa','Bhotepa-Station',0.0 -'Binbeal','Binbeal-Station',0.0 -'Bingui','Bingui-Station',0.0 -'Blata','Blata-Station',0.0 -'Blatrimpe','Blatrimpe-Station',0.0 -'Bogatiku','Bogatiku-Station',0.0 -'Bolg','Moxon''s Mojo',935 -'Bolg','Payette Platform',1835 -'Borom Caquit','Borom Caquit-Station',0.0 -'Bragurom Du','Bragurom Du-Station',0.0 -'Brahma','Brahma-Station',0.0 -'Bugas','Bugas-Station',0.0 -'Bumbo','Bumbo-Station',0.0 -'Bunda','Bunda-Station',0.0 -'Buryacuan Wu','Buryacuan Wu-Station',0.0 -'Caeronthudti','Caeronthudti-Station',0.0 -'Caicius','Bridges Survey',0.0 -'Caluayaksheper','Caluayaksheper-Station',0.0 -'Candjinan','Candjinan-Station',0.0 -'Carnoeck','Carnoeck-Station',0.0 -'Carnutenichuara','Carnutenichuara-Station',0.0 -'Catuntinigi','Catuntinigi-Station',0.0 -'Cavashira','Cavashira-Station',0.0 -'Cavins','Cavins-Station',0.0 -'CD-35 6972','CD-35 6972-Station',0.0 +'Blata','Sinclair Orbital',0.0 +'Bolg','Moxon''s Mojo',0.0 +'BRAGUROM DU','Comino Station',0.0 +'Brahma','Banks Landing',0.0 'CE Bootis','Sellers Relay',0.0 -'Cenil','Cenil-Station',0.0 +'Cenil','Xing Hub',0.0 'Chaac','Antonio De Andrade',0.0 'Chapoyo','Piccard Port',0.0 -'Chara','Reilly Refinery',11738 +'Chara','Reilly Refinery',0.0 'Chaxiraxi','Brother''s Progress',0.0 -'Chechehet','Chechehet-Station',0.0 -'Chelmen','Chelmen-Station',0.0 'Chemaku','Bartoe Platform',0.0 -'Chi Herculis','Gorbatko Reserve',899 -'Chi Herculis','Gemar Orbital',899 -'Chini','Chini-Station',0.0 +'Chi Herculis','Gorbatko Reserve',0.0 'Chongquan','Eisele Park',0.0 -'Chontantici','Chontantici-Station',0.0 -'Choujemait','Choujemait-Station',0.0 -'Ciguru','Ciguru-Station',0.0 -'Circios','Circios-Station',0.0 -'CM Draco','CM Draco-Station',0.0 +'CM Draco','Anderson Escape',0.0 'Coelrind','Siegel Hanger',0.0 'Coriccha','Cunningham',0.0 -'Corioskeh Tryth','Corioskeh Tryth-Station',0.0 -'CPD-23 501','CPD-23 501-Station',0.0 'CR Draco','Strekalov Settlement',0.0 -'Cuages','Cuages-Station',0.0 -'Cybele','Cybele-Station',0.0 -'Czernovale','Czernovale-Station',0.0 -'Dagaz','Dagaz-Station',0.0 -'Dahan','Dahan Gateway',468 -'Dahan','Dahan 3 Metalworks',1854 +'Dagaz','Wakata Refinery',0.0 +'Dahan','Dahan Gateway',0.0 'Dakantjarini','Nachtigal Vision',0.0 'Darahk','Noblehome',0.0 'Demeter','Marusek Settlement',0.0 -'Denebola','Volkov Dock',567 -'Denebola','Chomsky Point',1371 -'Denebola','Chamitoff Point',7482 -'Dierfar','Dierfar-Station',0.0 +'Denebola','Volkov Dock',0.0 'Difu','Backers Pledge High',0.0 -'Divja Mu','Divja Mu-Station',0.0 -'Djedet','Djedet-Station',0.0 'Doris','Isherwood Dock',0.0 -'DT Virginis','Chun Station',0.0 +'DT Virginis','Chun Vision',0.0 'Duamta','Rutherford Gateway',0.0 'DX 799','Shargin Plant',0.0 'DX Cancri','Horowitz Landing',0.0 'Dyaushis','Helmholtz Station',0.0 -'EGGR 431','EGGR 431-Station',0.0 -'Egovedunuvitra','Egovedunuvitra-Station',0.0 -'Ehlangai','Ehlangai-Station',0.0 -'Eme','Eme-Station',0.0 -'Enumclawilya','Enumclawilya-Station',0.0 -'Eranin','Azeban Orbital',294 -'Eranin','Azeban City',295 -'Eranin','Eranin 4 Survey',2024 -'Eravarenth','Eravarenth-Station',0.0 -'Erlaza','Erlaza-Station',0.0 +'Eranin','Azeban City',0.0 'Eta Corvi','Ivins Plant',0.0 -'Eta Draconis','Eta Draconis-Station',0.0 -'Etznabihik Mangk','Etznabihik Mangk-Station',0.0 -'Evergreen','Evergreen-Station',0.0 -'Exbeur','Exbeur-Station',0.0 -'FAUST 2688','Faust 2688-Station',0.0 +'Eta Draconis','Zahn Orbital',0.0 +'Etznabihik Mangk','Heng Orbital',0.0 +'Evergreen','Stafford Terminal',0.0 'Feng Huang','Murdoch Plant',0.0 -'Fianna','Fianna-Station',0.0 -'Fionn','Fionn-Station',0.0 'Flousop','Fawcett Installation',0.0 'FN Virginis','Priestley Port',0.0 -'Friggirawi','Friggirawi-Station',0.0 -'Fu Haiting','Fu Haiting-Station',0.0 -'G 113-20','G 113-20-Station',0.0 +'Friggirawi','Griffin Station',0.0 'G 121-8','Brosnan Gateway',0.0 'G 123-49','JET-GANG',0.0 'G 14-6','Yamazaki Orbital',0.0 -'G 146-5','G 146-5-Station',0.0 -'G 175-42','G 175-42-Station',0.0 -'G 180-18','Alexandria Gateway',8.97 -'G 180-18','Rozhdestvensky Ring',16 -'G 180-18','Allen Ring',29.3 -'G 181-6','Thomas Installation',485 -'G 181-6','Dezhurov Platform',21366 +'G 180-18','Alexandria Gateway',0.0 +'G 181-6','Thomas Installation',0.0 'G 203-47','Michelson Terminal',0.0 -'G 224-46','G 224-46-Station',0.0 -'G 239-25','G 239-25-Station',0.0 -'G 250-34','G 250-34-Station',0.0 -'G 65-9','G 65-9-Station',0.0 -'G 89-32','EISELE PARK 2',0.0 +'G 250-34','Cavendish Terminal',0.0 +'G 65-9','Marconi Port',0.0 'GD 140','Fujimori Hub',0.0 'Gendalla','Normand Platform',0.0 'Gendini','Houtman Gateway',0.0 'Gera','Kennicott Platform',0.0 'Gliese 3371','Navigator Colony',0.0 -'Gliese 9843','Gliese 9843-Station',0.0 -'Gomm Crua','Gomm Crua-Station',0.0 'Gong Gu','Cheli Dock',0.0 -'GQ Virginis','GQ Virginis-Station',0.0 +'GQ Virginis','Garriott Colony',0.0 'Grabri','Platform',0.0 'Groombridge 1618','Gernhardt Hub',0.0 'Guangul','Laue''s Claim',0.0 -'Gunnovii','Gunnovii-Station',0.0 -'Guy','Guy-Station',0.0 -'h Draconis','Brislington',0.0 +'Gunnovii','Wilder Prospect',0.0 +'H Draconis','Brislington',0.0 'Hach','Mohmand Settlement',0.0 -'Hadad','Hadad-Station',0.0 -'Haeditjaray','Haeditjaray-Station',0.0 +'Hadad','Levy settlement',0.0 'Hagalaz','De Andrade Ring',0.0 -'Haidjaram','Haidjaram-Station',0.0 'Hambula','Qureshi Hub',0.0 -'Haokah','Haokah-Station',0.0 -'Hared','Hared-Station',0.0 +'Hared','Morey Refinery',0.0 'Haribaluayai','Debye Port',0.0 -'Havat','Havat-Station',0.0 'HDS 1879','Hedin orbital',0.0 -'Heheng De','Heheng De-Station',0.0 -'Helios','Helios-Station',0.0 -'HIP 105557','HIP 105557-Station',0.0 -'HIP 107457','HIP 107457-Station',0.0 -'HIP 109479','HIP 109479-Station',0.0 -'HIP 110773','HIP 110773-Station',0.0 -'HIP 111496','HIP 111496-Station',0.0 +'Heheng De','Malchiodi Colony',0.0 +'HIP 110773','Bain Orbital',0.0 'HIP 113477','Diophantus Port',0.0 -'HIP 113905','HIP 113905-Station',0.0 'HIP 114099','Bacigalupi Mine',0.0 -'HIP 114769','HIP 114769-Station',0.0 -'HIP 2422','HIP 2422-Station',0.0 -'HIP 2453','HIP 2453-Station',0.0 +'HIP 2422','Shargin Port',0.0 'HIP 4907','Edison Platform',0.0 -'HIP 85887','HIP 85887-Station',0.0 -'HIP 91906','HIP 91906-Station',0.0 -'Hlocidirus','Hlocidirus-Station',0.0 -'Hlooyn','Hlooyn-Station',0.0 'Holiacan','Hopi',0.0 -'HR 3862','HR 3862-Station',0.0 'HR 3991','Greenland Exchange',0.0 -'HR 4979','HR 4979-Station',0.0 -'HR 7925','HR 7925-Station',0.0 -'HR 8423','HR 8423-Station',0.0 -'HR 8472','HR 8472-Station',0.0 -'HR 8474','HR 8474-Station',0.0 -'Hsien Baji','Hsien Baji-Station',0.0 -'Hun Banja','Hun Banja-Station',0.0 -'Huokang','Huokang-Station',0.0 +'Hsien Baji','Novitski Mines',0.0 +'Huokang','Solovyev City',0.0 'Hyperion','Ivens Ring',0.0 -'i Bootis','Chango Dock',1098 -'i Bootis','Maher Stellar Research',20929 -'Igororai','Igororai-Station',0.0 -'Ikpenones','Ikpenones-Station',0.0 -'Issin','Issin-Station',0.0 +'I Bootis','Chango Dock',0.0 'Istanu','Hayden Ring',0.0 -'Ithaca','Ithaca-Station',0.0 -'Jaitu','Jaitu-Station',0.0 -'Janjak','Janjak-Station',0.0 -'Jata','Jata-Station',0.0 -'Jeidrungaragototo','Jeidrungaragototo-Station',0.0 -'Jetes','Jetes-Station',0.0 -'Jok Islese','Jok Islese-Station',0.0 -'Jolangen','Jolangen-Station',0.0 -'Juipedun','Juipedun-Station',0.0 -'Jula Oh','Jula Oh-Station',0.0 -'Jun','Jun-Station',0.0 -'Jungkurara','Jungkurara-Station',0.0 -'K Camelopardalis','K Camelopardalis-Station',0.0 -'Kaal','Kaal-Station',0.0 -'Kaha''i','Kaha''i-Station',0.0 -'Kali','Kali-Station',0.0 -'Kamchaultultula','Kamchaultultula-Station',0.0 -'Kanati','Kanati-Station',0.0 +'Ithaca','Hume Depot',0.0 +'K Camelopardalis','Anning Station',0.0 +'Kaha''i','Bohm Station',0.0 'Kanos','Lee Station',0.0 -'Karovices','Karovices-Station',0.0 -'Kassi Hua','Kassi Hua-Station',0.0 +'Kassi Hua','Clauss Platform',0.0 'Katae','Coulomb Survey',0.0 -'Kato','Kato-Station',0.0 'Keiadjara','Brown Hub',0.0 -'Keian Gu','Keian Gu-Station',0.0 +'Keian Gu','Zhigang Platform',0.0 'Keling','Lopez De Villalobos',0.0 -'Keries','Derrickson''s Escape',270 -'Khernidjal','Khernidjal-Station',0.0 +'Keries','Derrickson''s Escape',0.0 'Kholedo','Cowpercity',0.0 -'Khong Qin Gu','Khong Qin Gu-Station',0.0 -'Kishia','Kishia-Station',0.0 'Kokobujundji','Buchli Station',0.0 -'Kokoto','Kokoto-Station',0.0 -'Kongi','Kongi-Station',0.0 'Korubu','Markov Gateway',0.0 'Kotaition','Bykovsky Vision',0.0 -'Krumine','Krumine-Station',0.0 -'Kuikian Batji','Kuikian Batji-Station',0.0 -'Kumana','Kumana-Station',0.0 -'Kunapalanezti','Kunapalanezti-Station',0.0 +'Kuikian Batji','ALI INSTALLATION',0.0 'Kunbuluan','Ayerdhal Orbital',0.0 -'Kungati','Kungati-Station',0.0 -'Kurngali','Kurngali-Station',0.0 -'Kurui Gubi','Kurui Gubi-Station',0.0 -'Kurunmindjuk','Kurunmindjuk-Station',0.0 -'Kushentinoni','Kushentinoni-Station',0.0 -'Kwakamitreyja','Kwakamitreyja-Station',0.0 -'Kwamennero Kojin','Kwamennero Kojin-Station',0.0 -'Labed','Labed-Station',0.0 -'Lakluit','Lakluit-Station',0.0 +'Kurui Gubi','Ellis Landing',0.0 +'Kushentinoni','Bennett Port',0.0 +'Kwakamitreyja','Laliberte Camp',0.0 'Lalande 18115','Gilliland Port',0.0 'Lalande 22954','Haber Terminal',0.0 -'Lalande 29917','Lalande 29917-Station',0.0 -'Lalande 30699','Lalande 30699-Station',0.0 +'Lalande 29917','Cori Terminal',0.0 +'Lalande 30699','Johnson Works',0.0 'Lalande 37923','Keyes City',0.0 'Las Xenangaresti','Murdoch Station',0.0 -'Latucairhemaiabi','Latucairhemaiabi-Station',0.0 -'LAWD 17','LAWD 17-Station',0.0 +'Latucairhemaiabi','Cavendish Station',0.0 'LAWD 52','Guerrero Horizons',0.0 -'LDS 2314','Mcdonald Colony',0.0 -'LDS 413','LDS 413-Station',0.0 -'Lei Ta Tetona','Lei Ta Tetona-Station',0.0 -'Leng Wanjadimuru','Leng Wanjadimuru-Station',0.0 -'LFT 1072','LFT 1072-Station',0.0 -'LFT 1421','LFT 1421-Station',0.0 +'LDS 2314','McDonald Colony',0.0 +'LFT 1072','Forsskal Vision',0.0 'LFT 1446','Bosch Settlement',0.0 'LFT 1748','Longyear Port',0.0 'LFT 424','England City',0.0 -'LFT 601','LFT 601-Station',0.0 -'LFT 625','LFT 625-Station',0.0 -'LFT 682','LFT 682-Station',0.0 -'LFT 698','LFT 698-Station',0.0 -'LFT 709','LFT 709-Station',0.0 -'LFT 820','LFT 820-Station',0.0 -'LFT 824','LFT 824-Station',0.0 +'LFT 820','Bailey Landing',0.0 'LFT 859','Stross City',0.0 -'LFT 880','Baker Platform',5.68 -'LFT 90','LFT 90-Station',0.0 -'LFT 926','LFT 926-Station',0.0 -'LFT 945','LFT 945-Station',0.0 -'LFT 992','LFT 992-Station',0.0 -'LHS 1065','Hornblower Platform',90855 -'LHS 1101','LHS 1101-Station',0.0 +'LFT 880','Baker Platform',0.0 +'LFT 926','Onizuka Platform',0.0 +'LFT 945','Hahn Base',0.0 +'LFT 992','Szulkin mines',0.0 +'LHS 1065','Hornblower Platform',0.0 +'LHS 1101','Bondar City',0.0 'LHS 1167','Fangrim''s Folly',0.0 -'LHS 140','Onizuka Orbital',581 -'LHS 1505','LHS 1505-Station',0.0 -'LHS 1663','LHS 1663-Station',0.0 -'LHS 1882','LHS 1882-Station',0.0 -'LHS 1923','LHS 1923-Station',0.0 -'LHS 1951','LHS 1951-Station',0.0 -'LHS 1963','LHS 1963-Station',0.0 -'LHS 2037','LHS 2037-Station',0.0 -'LHS 207','LHS 207-Station',0.0 +'LHS 140','Onizuka Orbital',0.0 +'LHS 1951','Yegorov Platform',0.0 'LHS 2088','Comer''s Inheritance',0.0 -'LHS 2123','LHS 2123-Station',0.0 'LHS 215','Lubin Port',0.0 -'LHS 2157','LHS 2157-Station',0.0 -'LHS 2166','LHS 2166-Station',0.0 -'LHS 221','LHS 221-Station',0.0 -'LHS 2217','LHS 2217-Station',0.0 -'LHS 2233','LHS 2233-Station',0.0 -'LHS 224','LHS 224-Station',0.0 -'LHS 2274','LHS 2274-Station',0.0 -'LHS 229','LHS 229-Station',0.0 -'LHS 2314','LHS 2314-Station',0.0 -'LHS 2335','LHS 2335-Station',0.0 -'LHS 2337','LHS 2337-Station',0.0 -'LHS 2363','LHS 2363-Station',0.0 -'LHS 2405','LHS 2405-Station',0.0 -'LHS 2412','LHS 2412-Station',0.0 -'LHS 2429','LHS 2429-Station',0.0 -'LHS 246','LHS 246-Station',0.0 -'LHS 2471','LHS 2471-Station',0.0 -'LHS 2477','LHS 2477-Station',0.0 -'LHS 2482','LHS 2482-Station',0.0 +'LHS 221','Guest Terminal',0.0 +'LHS 2233','O''Donnell Survey',0.0 +'LHS 2363','Kennan Platform',0.0 +'LHS 246','ELLIS LABORATORY',0.0 +'LHS 2471','Cowper Dock',0.0 'LHS 2494','Heceta Colony',0.0 -'LHS 250','Kovalesky Enterprise',0.0 +'LHS 250','Kovalevsky Enterprise',0.0 'LHS 2541','Artyukhin Platform',0.0 -'LHS 2552','LHS 2552-Station',0.0 -'LHS 259','LHS 259-Station',0.0 -'LHS 262','LHS 262-Station',0.0 'LHS 2651','Schmitz Gateway',0.0 'LHS 2661','Irwin Gateway',0.0 'LHS 2691','Ivanchenkov Colony',0.0 -'LHS 274','LHS 274-Station',0.0 'LHS 2764a','Serre Port',0.0 'LHS 278','Clebsch Colony',0.0 -'LHS 2789','LHS 2789-Station',0.0 -'LHS 2819','LHS 2819-Station',0.0 +'LHS 2819','Tasaki Freeport',0.0 'LHS 283','Zoline Enterprise',0.0 -'LHS 287','LHS 287-Station',0.0 -'LHS 2884','LHS 2884-Station',0.0 +'LHS 2884','Abnett Platform',0.0 'LHS 2887','Massimino Dock',0.0 'LHS 2936','Ferguson Relay',0.0 'LHS 295','White Settlement',0.0 'LHS 3006','WCM Transfer Orbital',0.0 -'LHS 301','LHS 301-Station',0.0 -'LHS 302','LHS 302-Station',0.0 'LHS 3057','Wallace Colony',0.0 -'LHS 306','LHS 306-Station',0.0 -'LHS 317','LHS 317-Station',0.0 'LHS 3262','Lacaille Prospect',0.0 -'LHS 331','LHS 331-Station',0.0 -'LHS 336','LHS 336-Station',0.0 -'LHS 346','LHS 346-Station',0.0 +'LHS 331','Hopkinson City',0.0 'LHS 351','Brunel Hub',0.0 'LHS 3549','Baydukov Base',0.0 'LHS 355','Foucault Landing',0.0 -'LHS 3586','LHS 3586-Station',0.0 'LHS 3631','Currie Hub',0.0 'LHS 369','Cavendish Port',0.0 'LHS 371','Fischer Works',0.0 -'LHS 380','LHS 380-Station',0.0 -'LHS 3877','LHS 3877-Station',0.0 +'LHS 3877','Fischer Colony',0.0 'LHS 391','Savinykh Works',0.0 'LHS 411','Kuhn Colony',0.0 'LHS 417','Gernhardt Camp',0.0 'LHS 450','Wilson Relay',0.0 -'LHS 5072','LHS 5072-Station',0.0 -'LHS 5287','LHS 5287-Station',0.0 -'LHS 6128','LHS 6128-Station',0.0 -'LHS 6197','LHS 6197-Station',0.0 +'LHS 5072','NORTHROP DOCK',0.0 +'LHS 5287','McArthur''s Reach',0.0 'LHS 6282','Kendrick Base',0.0 -'LHS 6309','Carey Colony',73 -'LHS 6309','Ryumin Terminal',133 -'LHS 6309','Smeaton Port',2531 -'LHS 6309','Kaku Station',2702 -'LHS 64','LHS 64-Station',0.0 -'Li Quang','Li Quang-Station',0.0 -'Loga','Loga-Station',0.0 +'LHS 6309','Smeaton Port',0.0 +'LHS 64','Kopra Survey',0.0 +'Li Quang','Boodt Gateway',0.0 'Logoni','Knight Platform',0.0 'Lokapuri','McArthur Dock',0.0 -'Lopu Maid Fo','Lopu Maid Fo-Station',0.0 -'LP 1-52','LP 1-52-Station',0.0 'LP 102-320','Shepard Hub',0.0 -'LP 131-55','LP 131-55-Station',0.0 'LP 167-64','Chu City',0.0 -'LP 167-71','LP 167-71-Station',0.0 -'LP 211-12','LP 211-12-Station',0.0 -'LP 27-9','LP 27-9-Station',0.0 'LP 29-188','Smith Enterprise',0.0 -'LP 30-55','LP 30-55-Station',0.0 +'LP 30-55','REIS DOCK',0.0 'LP 320-359','Fisher Camp',0.0 -'LP 322-836','LP 322-836-Station',0.0 -'LP 36-115','LP 36-115-Station',0.0 -'LP 37-75','LP 37-75-Station',0.0 -'LP 377-100','LP 377-100-Station',0.0 -'LP 45-128','LP 45-128-Station',0.0 +'LP 322-836','Bolotov Port',0.0 +'LP 45-128','Salam Point',0.0 'LP 465-14','Oluwafemi Terminal',0.0 -'LP 48-567','LP 48-567-Station',0.0 -'LP 488-37','LP 488-37-Station',0.0 -'LP 5-88','LP 5-88-Station',0.0 'LP 51-17','Archambault Horizons',0.0 -'LP 58-247','LP 58-247-Station',0.0 -'LP 60-205','LP 60-205-Station',0.0 -'LP 617-37','LP 617-37-Station',0.0 -'LP 64-194','LP 64-194-Station',0.0 -'LP 672-42','LP 672-42-Station',0.0 -'LP 673-13','LP 673-13-Station',0.0 -'LP 675-76','LP 675-76-Station',0.0 +'LP 5-88','Midgley Settlement',0.0 +'LP 64-194','Longyear Survey',0.0 +'LP 673-13','Brown Orbital',0.0 'LP 71-157','Buckland Colony',0.0 -'LP 732-94','LP 732-94-Station',0.0 -'LP 734-11','LP 734-11-Station',0.0 -'LP 787-52','LP 787-52-Station',0.0 -'LP 792-20','LP 792-20-Station',0.0 -'LP 792-33','LP 792-33-Station',0.0 -'LP 793-33','LP 793-33-Station',0.0 -'LP 844-28','LP 844-28-Station',0.0 -'LP 847-48','LP 847-48-Station',0.0 -'LP 849-20','LP 849-20-Station',0.0 -'LP 855-34','LP 855-34-Station',0.0 -'LP 90-39','LP 90-39-Station',0.0 -'LP 906-9','LP 906-9-Station',0.0 -'LP 908-11','LP 908-11-Station',0.0 -'LP 98-132','Freeport',184 -'LP 98-132','Prospect Five',389 +'LP 732-94','Sellers Hub',0.0 +'LP 98-132','Freeport',0.0 'LP Draconis','McDivitt Settlement',0.0 'LTT 10482','Hubble Relay',0.0 -'LTT 12680','LTT 12680-Station',0.0 -'LTT 12990','LTT 12990-Station',0.0 'LTT 15294','Tem Ring',0.0 -'LTT 16523','LTT 16523-Station',0.0 -'LTT 16979','LTT 16979-Station',0.0 -'LTT 3919','LTT 3919-Station',0.0 +'LTT 16523','Fozard Survey',0.0 'LTT 4131','Ponce de Leon Station',0.0 -'LTT 4150','LTT 4150-Station',0.0 -'LTT 4376','LTT 4376-Station',0.0 -'LTT 4447','LTT 4447-Station',0.0 +'LTT 4150','Meikle Orbital',0.0 'LTT 4461','Artsebarsky Gateway',0.0 -'LTT 4527','LTT 4527-Station',0.0 -'LTT 4549','LTT 4549-Station',0.0 -'LTT 4730','LTT 4730-Station',0.0 -'LTT 4772','LTT 4772-Station',0.0 -'LTT 4898','LTT 4898-Station',0.0 -'LTT 5131','LTT 5131-Station',0.0 'LTT 5455','Blaha Legacy',0.0 -'LU Velorum','LU Velorum-Station',0.0 -'Lucab Ku','Lucab Ku-Station',0.0 +'Lucab Ku','Potter Station',0.0 'Luggerates','Stewart Settlement',0.0 'Lugien Chabtani','Conklin Ring',0.0 -'Luhman 16','Luhman 16-Station',0.0 'Luyten 674-15','Sinclair Relay',0.0 'Luyten''s Star','Still Outpost',0.0 -'Macomaneleng Mu','Macomaneleng Mu-Station',0.0 -'Magec','Xiaoguan Hub',131 -'Magec','Garriott Outpost',335 -'Magec','Trumpler Dock',4541 +'Magec','Xiaoguan Hub',0.0 'Maitaokona','Gresley Gateway',0.0 -'Maitis','Maitis-Station',0.0 -'Malanquiya','Malanquiya-Station',0.0 -'Malina','Malina-Station',0.0 -'Maljenni','Maljenni-Station',0.0 +'Maljenni','Lazarev Depot',0.0 'Manarato','Goldstein Installation',0.0 -'Manbai Chac Moco','Manbai Chac Moco-Station',0.0 -'Mankob','Mankob-Station',0.0 -'Mannheim','Mannheim-Station',0.0 -'Maranarinjhian Hsi','Maranarinjhian Hsi-Station',0.0 'Marasing','Thiele Enterprise',0.0 -'Maraupol Bumbin','Maraupol Bumbin-Station',0.0 -'Marditj','Marditj-Station',0.0 -'Markanomovoy','Markanomovoy-Station',0.0 -'Marojini','Marojini-Station',0.0 +'Markanomovoy','Compton Dock',0.0 'Marsinatani','Hewish Relay',0.0 -'Maujinagoto','Maujinagoto-Station',0.0 -'Mbuthamovites','Mbuthamovites-Station',0.0 +'MAUJINAGOTO','Halsell Point',0.0 'MCC 858','Jacquard Orbital',0.0 -'Megrez','Megrez-Station',0.0 -'Melcior','Melcior-Station',0.0 +'Melcior','Goddard Dock',0.0 'Meliae','Shawl Beacon',0.0 -'Midgcut','Midgcut-Station',0.0 'Mildeptu','Gerst Platform',0.0 -'Mildjarayuta','Mildjarayuta-Station',0.0 -'Minawara','Minawara-Station',0.0 -'Miola','Miola-Station',0.0 -'Miquich','Miquich-Station',0.0 +'Miola','Harris Hospital',0.0 'Mizar','Borel Park',0.0 -'Mobokomu','Mobokomu-Station',0.0 -'Mokojing','Mokojing-Station',0.0 -'Momoirent','Momoirent-Station',0.0 -'Morgor','Romanek''s Folly',916 +'Morgor','Romanek''s Folly',0.0 'Moros','Tesla Depot',0.0 -'Moscab Kutja','Moscab Kutja-Station',0.0 'Mu Nora','Virts Port',0.0 -'Muango','Muango-Station',0.0 'Mufrid','Hardwick Base',0.0 'Mullag','Kelly City',0.0 -'Muncheim','Muncheim-Station',0.0 -'Nagariggam','Nagariggam-Station',0.0 -'Nahundi','Nahundi-Station',0.0 -'Nakuma','Nakuma-Station',0.0 +'Nakuma','Nelder Mines',0.0 'Nang Ta-khian','Hay Point',0.0 -'Naraka','Novitski Oasis',0.0 -'Neche','Neche-Station',0.0 -'Nemepawe','Nemepawe-Station',0.0 'Nener','Popov Dock',0.0 -'Ngardamayo','Ngardamayo-Station',0.0 -'Ngolitjali','Ngolitjali-Station',0.0 -'Ngoloki Anaten','Ngoloki Anaten-Station',0.0 +'Ngolitjali','Vinogradov platform',0.0 'Nicobarese','Berezovoy Station',0.0 -'Njikan','Njikan-Station',0.0 -'NLTT 26813','NLTT 26813-Station',0.0 -'NLTT 34715','NLTT 34715-Station',0.0 'NLTT 46621','Hope Point',0.0 'NLTT 48502','Webb Holdings',0.0 -'NLTT 50716','NLTT 50716-Station',0.0 'NLTT 53889','Roosa Platform',0.0 -'Nuenets','Nuenets-Station',0.0 -'Nuguynici','Nuguynici-Station',0.0 'Nuwang','Schade Outpost',0.0 -'Nzam Cakua','Nzam Cakua-Station',0.0 'Nzambassee','Garriott Stop',0.0 'Okinoukhe','Stableford Ring',0.0 'Okuapang','Pribylov Park',0.0 -'Olgrea','Olgrea-Station',0.0 -'Onduwatya','Onduwatya-Station',0.0 -'Opala','Meikle Point',1391 -'Opala','Onizuka''s Hold',1449 -'Opala','Romanenko Estate',1451 -'Ori','Ori-Station',0.0 +'Opala','Romanenko Estate',0.0 +'Ori','Alexeyev Depot',0.0 'OT Serpentis','Serebrov Port',0.0 -'Ovid','Abe Works',379 -'Ovid','Bradfield Orbital',377 +'Ovid','Bradfield Orbital',0.0 'Pachanu','Aubakirov Hub',0.0 'Pan','Gunn Plant',0.0 'Pangluya','Bradbury Works',0.0 -'Parcae','Parcae-Station',0.0 +'Parcae','Sturckow terminal',0.0 'Paul-Friedrichs Star','Paul-Friedrichs Base Camp',0.0 'Pemede','Berners-Lee Terminal',0.0 -'Perendi','Perendi-Station',0.0 -'Phra Zhan','Phra Zhan-Station',0.0 +'Perendi','Shepherd Installation',0.0 'Pi-fang','Brooks Estate',0.0 -'Piran','Piran-Station',0.0 +'Piran','Garcia Gateway',0.0 'Pliny','Sharman Gateway',0.0 -'Pollux','Pollux-Station',0.0 -'Popon','Popon-Station',0.0 -'PPM 41187','PPM 41187-Station',0.0 -'Privir','Privir-Station',0.0 +'Privir','Lambert Station',0.0 'Procyon','Manakov Dock',0.0 'Psamathe','Nelson Gateway',0.0 -'PW Hydrae','PW Hydrae-Station',0.0 -'Quiness','Quiness-Station',0.0 -'Rabates','Rabates-Station',0.0 -'Rahu','Rahu-Station',0.0 +'Quiness','Lockyer''s Rest',0.0 +'Rahu','Lebedev Beacon',0.0 'Rakapila','Stone Enterprise',0.0 -'Ratri','Ratri-Station',0.0 -'Rauratunab','Rauratunab-Station',0.0 -'Rhea','Rhea-Station',0.0 -'Rho Cancri','Rho Cancri-Station',0.0 -'Ross 1003','Ross 1003-Station',0.0 -'Ross 1015','Ross 1015-Station',0.0 +'Rho Cancri','Hamilton Reserve',0.0 +'Ross 1015','Bowersox Mines',0.0 'Ross 104','Glenn Dock',0.0 -'Ross 1051','Ross 1051-Station',0.0 -'Ross 1057','Ross 1057-Station',0.0 -'Ross 112','Ross 112-Station',0.0 +'Ross 1051','Abetti Platform',0.0 +'ROSS 1057','Wang Estate',0.0 'Ross 128','Warren Prison Mine',0.0 'Ross 130','Huxley Relay',0.0 'Ross 210','Viktorenko Park',0.0 -'Ross 211','Ross 211-Station',0.0 +'Ross 211','Chilton Vision',0.0 'Ross 318','Koch Hub',0.0 -'Ross 446','Ross 446-Station',0.0 -'Ross 447','Ross 447-Station',0.0 +'Ross 446','Nowak Laboratory',0.0 'Ross 486','Brash Vision',0.0 'Ross 490','Delucas Landing',0.0 -'Ross 667','Ross 667-Station',0.0 -'Ross 695','Ross 695-Station',0.0 -'Ross 85','Ross 85-Station',0.0 -'Ross 860','Ross 860-Station',0.0 -'Ross 905','Morukov Platform',16.1 -'Ross 905','Xing Dock',945 -'Ross 93','Ross 93-Station',0.0 +'Ross 905','Morukov Platform',0.0 'Ross 986','Jones Station',0.0 -'Sak Chelmir','Sak Chelmir-Station',0.0 -'Salarhul','Salarhul-Station',0.0 -'Samkyha','Samkyha-Station',0.0 -'Sanguru','Sanguru-Station',0.0 -'Seber','Seber-Station',0.0 -'Sekhemet','Sekhemet-Station',0.0 -'Selebegua','Selebegua-Station',0.0 +'Salarhul','Lavoisier Outpost',0.0 +'Samkyha','Tesla Station',0.0 'Seting','Cox Landing',0.0 'Shama','Clairaut Port',0.0 -'Shamash','Shamash-Station',0.0 -'Shapash','Shapash-Station',0.0 -'Shebayeb','Shebayeb-Station',0.0 +'Shebayeb','Volta Landing',0.0 'Sheela Na Gig','Birkhoff Terminal',0.0 'Sigma Bootis','Meikle Platform',0.0 -'Skeggiko O','Skeggiko O-Station',0.0 -'Slatus','Slatus-Station',0.0 +'Slatus','Hoffman Orbital',0.0 'Sofagre','Markov Park',0.0 'Sokoji','Cavendish Relay',0.0 'Song Te Tians','La Cosa Dock',0.0 'Sopdu','Borlaug Camp',0.0 -'Stein 2051','Trevithick Port',0.0 -'Styx','Gerst Port',70 -'Styx','Chi Hub',653 +'Stein 2051','TREVITHICK PORT',0.0 +'Styx','Searfoss Plant',0.0 +'Styx','Boyle Terminal',0.0 'Sudz','Divis Enterprise',0.0 -'Sukub Tungatis','Sukub Tungatis-Station',0.0 -'Sukuruaco','Sukuruaco-Station',0.0 -'Supen','Supen-Station',0.0 +'Sukub Tungatis','Allen Horizons',0.0 'Suraci','Priestley Ring',0.0 'Surya','Burbank Camp',0.0 -'T''ang Bumbain','T''ang Bumbain-Station',0.0 'Tabassapisi','Parise Camp',0.0 -'Taexalkoloine','Taexalkoloine-Station',0.0 +'Taexalkoloine','Rutherford Works',0.0 'Taima Baijuhacmoora','Mills Park',0.0 -'Taleachishvakhrud','Taleachishvakhrud-Station',0.0 -'Taliesin','Taliesin-Station',0.0 'Talitha','Ross Platform',0.0 -'Taosha','Taosha-Station',0.0 -'Tarasa','Tarasa-Station',0.0 'Tatil','Mallett Settlement',0.0 'Tau Bootis','Weitz Hub',0.0 -'Tau-1 Hydrae','Tau-1 Hydrae-Station',0.0 -'Tefenhua','Tefenhua-Station',0.0 -'Teng Yeh','Garan Survey',3089 -'Teng Yeh','Haxel Station',3089 -'Teng Yeh','Phillips Hub',3094 -'Teng Yeh','Korniyenko Dock',3093 -'Teng Yeh','Zhen Port',3117 -'Theta Cygni','Theta Cygni-Station',0.0 +'Teng Yeh','Garan Survey',0.0 'Theta Ursae Majoris','Landsteiner Silo',0.0 -'Thosim Biamh','Thosim Biamh-Station',0.0 -'Thoth','Thoth-Station',0.0 +'Thosim biamh','jones terminal',0.0 'Thottacahuan Wang','Baxter Camp',0.0 -'Thraskias','Thraskias-Station',0.0 -'Tiapalan','Tiapalan-Station',0.0 +'Thraskias','Herreshoff Station',0.0 'Tiethay','Santos Plant1',0.0 -'Tilian','Keeler Rest',196 -'Tilian','Maunder''s Hope',196 -'Tinia','Tinia-Station',0.0 -'Tivertsi','Tivertsi-Station',0.0 +'Tilian','Maunder''s Hope',0.0 'Tollan','Bayliss Base',0.0 -'Trepin','Trepin-Station',0.0 -'Tripu','Vinogradov Installation',2077 -'Tripu','Laval City',3411 -'Tsetan','Tsetan-Station',0.0 +'Tripu','Vinogradov Installation',0.0 'Tsohodiae','Barba Port',0.0 -'Tun','Tun''s Wart',226 -'Turmakul','Turmakul-Station',0.0 -'Tyche','Tyche-Station',0.0 -'Tyr','Tyr-Station',0.0 -'Udegoci','Udegoci-Station',0.0 -'V1090 Herculis','V1090 Herculis-Station',0.0 -'V2151 Cygni','V2151 Cygni-Station',0.0 -'V417 Hydrae','V417 Hydrae-Station',0.0 -'V419 Hydrae','V419 Hydrae-Station',0.0 +'Tun','Tun''s Wart',0.0 +'Tyr','Walz Works',0.0 +'V417 Hydrae','Clervoy Vista',0.0 'V538 Aurigae','Card Park',0.0 -'V740 Cassiopeiae','V740 Cassiopeiae-Station',0.0 -'V886 Centauri','V886 Centauri-Station',0.0 'V989 Cassiopeiae','Low Works',0.0 -'Vega','Vega-Station',0.0 -'Veneri','Veneri-Station',0.0 -'Verboni','Verboni-Station',0.0 -'Vetr','Vetr-Station',0.0 -'VZ Corvi','VZ Corvi-Station',0.0 -'Wadjuk','Wadjuk-Station',0.0 -'Wakarendians','Wakarendians-Station',0.0 +'Vetr','Wisoff Depot',0.0 'Wanggu','Besonders Port',0.0 -'Wathlanukh','Wathlanukh-Station',0.0 -'Wei Jung','Wei Jung-Station',0.0 -'Wen Tsakimori','Wen Tsakimori-Station',0.0 -'Widjararappan','Widjararappan-Station',0.0 -'Widjigarasir','Widjigarasir-Station',0.0 +'Wei Jung','Cooper Dock',0.0 'Wikmeang','Ivanov Hub',0.0 'WISE 1506+7027','Silverberg Relay',0.0 'Wolf 1409','Carter Vision',0.0 'Wolf 1478','Franklin Orbital',0.0 -'Wolf 1481','Wolf 1481-Station',0.0 -'Wolf 248','Wolf 248-Station',0.0 +'WOLF 248','Hencke Centre',0.0 'Wolf 294','Hippalus Station',0.0 'Wolf 359','Lomas Orbiter',0.0 -'Wolf 369','Wolf 369-Station',0.0 -'Wolf 393','Wolf 393-Station',0.0 +'Wolf 393','Lichtenberg Horizons',0.0 'Wolf 417','Egan Port',0.0 'Wolf 424','Sping Terminal',0.0 'Wolf 437','Fischer Platform',0.0 'Wolf 46','Fischer City',0.0 -'Wolf 485a','Wolf 485a-Station',0.0 'Wolf 497','Bamford Station',0.0 'Wolf 54','Meeking''s Way',0.0 -'Wolf 562','Wolf 562-Station',0.0 -'Wosyra Pao','Kaku Terminal',54.6 -'Wosyra Pao','Kovalyonok City',62.4 -'Wosyra Pao','Burbank Settlement',79.5 -'Wosyra Pao','Onufrienko Settlement',91 -'Wosyra Pao','Agnesi Refinery',125 -'Wu Gondru','Wu Gondru-Station',0.0 +'Wolf 562','LEONICENO CAMP',0.0 +'Wosyra Pao','Kaku Terminal',0.0 'Wunian','Sellers Landing',0.0 'WX Ursa Majoris','Teng-Hui Terminal',0.0 -'Wyrd','Vonarburg Co-operative',161 -'Wyrd','Bokeili Station',849 -'Wyrd','Gareth Edwards Park',849 -'Xelabara','Xelabara-Station',0.0 +'Wyrd','Vonarburg Co-Operative',0.0 'Xi Ursae Majoris','Joule Settlement',0.0 'Xi Wangkala','Ross Colony',0.0 -'Xolotl','Xolotl-Station',0.0 -'Ya''Nomisiyaces','Ya''Nomisiyaces-Station',0.0 -'Yakan','Yakan-Station',0.0 -'Yakawana','Yakawana-Station',0.0 -'Yanyan','Yanyan-Station',0.0 +'Yanyan','Morin City',0.0 'Yarigui','Schade City',0.0 -'Ye''kuapemas','Ye''kuapemas-Station',0.0 -'Yeru Bao Hinu','Yeru Bao Hinu-Station',0.0 -'Yoruba','Yoruba-Station',0.0 -'Yuggsanawyddis','Yuggsanawyddis-Station',0.0 -'Yugusitanitou','Yugusitanitou-Station',0.0 -'Zangi','Zangi-Station',0.0 +'Ye''Kuapemas','Hawke''s Progress',0.0 'Zaraluvul','Sturckow City',0.0 -'Zenmaku','Zenmaku-Station',0.0 -'Zeta Herculis','Shepherd Ring',8151 -'Zombardgriti','Zombardgriti-Station',0.0 -'Zombo','Zombo-Station',0.0 -'Zopiates','Zopiates-Station',0.0 -'Zosma','Zosma-Station',0.0 +'Zeta Herculis','Shepherd Ring',0.0 diff --git a/data/corrections.py b/data/corrections.py index 64359d7f..50424316 100644 --- a/data/corrections.py +++ b/data/corrections.py @@ -10,308 +10,9 @@ } stations = { - "10 CANUM VENATICORUM-STATION": "Janifer Port", - "21 DRACO-STATION": "Roberts Port", - "26 DRACONIS-STATION": "Bouch Beacon", - "37 XI BOOTIS-STATION": "Schirba Plant", - "44 CHI DRACONIS-STATION": "Lawson Camp", - "54 G. ANTLIA-STATION": "Boas Orbital", - "61 URSAE MAJORIS-STATION": "Worlidge Dock", - "61 VIRGINIS-STATION": "Artsebarsky Station", - "68 DRACONIS-STATION": "Gaspar De Lemos Port", - "70 VIRGINIS-STATION": "Reis Platform", - "ABNETT PLATEFORM": "Abnett Platform", - "ACIHAUT-STATION": "Cuffey Plant", - "ACURUKUNABOGAMAL-STATION": "Aguirre Terminal", - "AGANIPPE-STATION": "Julian Market", - "AKHENATEN-STATION": "Wang Platform", - "ALRAI-STATION": "Becquerel Gateway", - "AMMAPA-STATION": "Bamford Enterprise", - "ANDOE-STATION": "Moffitt Settlement", - "ANEMOI-STATION": "Abasheli Point", - "ANLAVE-STATION": "Suri Park", - "ANSARI-STATION": "Wiberg Colony", - "ANTINICA-STATION": "Benyovszky Terminal", - "AO GUANG-STATION": "Kotov Settlement", - "AO QIN-STATION": "Chapman Hub", - "APALAI-STATION": "Gubarev Base", - "ARCTURUS-STATION": "Fort Harrison", - "ARIN-STATION": "Kettle Landing", - "AULIS-STATION": "Dezhurov Gateway", - "BAGA-STATION": "Shipton Exchange", - "BAST-STATION": "White Hart Lane", - "BAUDUS-STATION": "Agnesi City", - "BD+29 2405-STATION": "Shaara City", - "BD+55 1519-STATION": "Eskridge Orbital", - "BD+65 1846-STATION": "Shargin Beacon", - "BD+74 526-STATION": "Smith Prospect", - "BF CANIS VENATICI-STATION": "Kornbluth Dock", - "BHOTEGA-STATION": "Buchli Port", - "BRAHMA-STATION": "Banks Landing", - "CAICIUS-STATION": "Bridges Survey", - "CE BOOTIS-STATION": "Sellers Relay", - "CHAAC-STATION": "Antonio De Andrade", - "CHAPOYO-STATION": "Piccard Port", - "CHAXIRAXI-STATION": "Brother's Progress", - "CHEMAKU-STATION": "Bartoe Platform", - "CHONGQUAN-STATION": "Eisele Park", - "CM DRACO-STATION": "Anderson Escape", - "COELRIND-STATION": "Siegel Hanger", - "CORICCHA-STATION": "Cunningham", - "CR DRACO-STATION": "Strekalov Settlement", - "DAKANTJARINI-STATION": "Nachtigal Vision", - "DARAHK-STATION": "Noblehome", - "DEMETER-STATION": "Marusek Settlement", - "DENEBOLA-STATION": "Chomsky Point", - "DIFU-STATION": "Backers Pledge High", - "DIVIS ENTERPRISE": "Divis Enterprise", - "DORIS-STATION": "Isherwood Dock", - "DT VIRGINIS-STATION": "Chun Station", - "DUAMTA-STATION": "Rutherford Gateway", - "DX 799-STATION": "Shargin Plant", - "DX CANCRI-STATION": "Horowitz Landing", - "DYAUSHIS-STATION": "Helmholtz Station", - "EJETA STATION": DELETED, - "ETA CORVI-STATION": "Ivins Plant", - "ETA DRACONIS-STATION": "Zahn Orbital", - "EVERGREEN-STATION": "Stafford Terminal", - "FENG HUANG-STATION": "Murdoch Plant", - "FLOUSOP-STATION": "Fawcett Installation", - "FN VIRGINIS-STATION": "Priestley Port", - "G 121-8-STATION": "Brosnan Gateway", - "G 123-49-STATION": "JET-GANG", - "G 14-6-STATION": "Yamazaki Orbital", - "G 180-18-STATION": "Alexandria Gateway", - "G 181-6-STATION": "Dezhurov Platform", - "G 203-47-STATION": "Michelson Terminal", - "G 65-9-STATION": "Marconi Port", - "G 89-32-STATION": "EISELE PARK", - "GARAN SURVERY": "Garan Survey", - "GD 140-STATION": "Fujimori Hub", - "GENDALLA-STATION": "Normand Platform", - "GENDINI-STATION": "Houtman Gateway", - "GERA-STATION": "Kennicott Platform", - "GLIESE 3371-STATION": "Navigator Colony", - "GONG GU-STATION": "Cheli Dock", - "GQ VIRGINIS-STATION": "Garriott Colony", - "GRABRI-STATION": "Platform", - "GROOMBRIDGE 1618-STATION": "Gernhardt Hub", - "GUANGUL-STATION": "Laue's Claim", - "H DRACONIS-STATION": "Brislington", - "HACH-STATION": "Mohmand Settlement", - "HADAD-STATION": "Levy Settlement", - "HAGALAZ-STATION": "De Andrade Ring", - "HAMBULA-STATION": "Qureshi Hub", - "HARIBALUAYAI-STATION": "Debye Port", - "HDS 1879-STATION": "Hedin Orbital", - "HIP 113477-STATION": "Diophantus Port", - "HIP 114099-STATION": "Bacigalupi Mine", - "HIP 4907-STATION": "Edison Platform", - "HOLIACAN-STATION": "Hopi", - "HOPKINS HANGAR": "Cori Terminal", - "HR 3991-STATION": "Greenland Exchange", - "HSIEN BAJI-STATION": "Novitski Mines", - "HYPERION-STATION": "Ivens Ring", - "ISTANU-STATION": "Hayden Ring", - "ITHACA-STATION": "Hume Depot", - "IVANCHENKOV COLONY": "Ivanchenkov Colony", - "K CAMELOPARDALIS-STATION": "Anning Station", - "KANOS-STATION": "Lee Station", - "KATAE-STATION": "Coulomb Survey", - "KEIADJARA-STATION": "Brown Hub", - "KELING-STATION": "Lopez De Villalobos", - "KHOLEDO-STATION": "Cowpercity", - "KOKOBUJUNDJI-STATION": "Buchli Station", - "KORUBU-STATION": "Markov Gateway", - "KOTAITION-STATION": "Bykovsky Vision", - "KOVALESKY ENTERPRISE": "Kovalevsky Enterprise", - "KUNBULUAN-STATION": "Ayerdhal Orbital", - "LALANDE 18115-STATION": "Gilliland Port", - "LALANDE 22954-STATION": "Haber Terminal", - "LALANDE 29917-STATION": "Cori Terminal", - "LALANDE 37923-STATION": "Keyes City", - "LAS XENANGARESTI-STATION": "Murdoch Station", - "LATUCAIRHEMAIABI-STATION": "Cavendish Station", - "LAWD 52-STATION": "Guerrero Horizons", - "LDS 2314-STATION": "Mcdonald Colony", - "LFT 1446-STATION": "Bosch Settlement", - "LFT 1748-STATION": "Longyear Port", - "LFT 424-STATION": "England City", - "LFT 859-STATION": "Stross City", - "LFT 880-STATION": "Baker Platform", - "LFT 992-STATION": "Szulkin Mines", - "LHS 1065-STATION": "Hornblower Platform", - "LHS 1167-STATION": "Fangrim's Folly", - "LHS 140-STATION": "Onizuka Orbital", - "LHS 2088-STATION": "Comer's Inheritance", - "LHS 215-STATION": "Lubin Port", - "LHS 2471-STATION": "Cowper Dock", - "LHS 2494-STATION": "Heceta Colony", - "LHS 250-STATION": "Kovalevsky Enterprise", - "LHS 2541-STATION": "Artyukhin Platform", - "LHS 2651-STATION": "Schmitz Gateway", - "LHS 2661-STATION": "Irwin Gateway", - "LHS 2691-STATION": "Ivanchenkov Colony", - "LHS 2764a-STATION": "Serre Port", - "LHS 278-STATION": "Clebsch Colony", - "LHS 2819-STATION": "Tasaki Freeport", - "LHS 283-STATION": "Zoline Enterprise", - "LHS 2884-STATION": "Abnett Platform", - "LHS 2887-STATION": "Massimino Dock", - "LHS 2936-STATION": "Ferguson Relay", - "LHS 295-STATION": "White Settlement", - "LHS 3006-STATION": "WCM Transfer Orbital", - "LHS 3057-STATION": "Wallace Colony", - "LHS 3262-STATION": "Lacaille Prospect", - "LHS 331-STATION": "Hopkinson City", - "LHS 351-STATION": "Brunel Hub", - "LHS 3549-STATION": "Baydukov Base", - "LHS 355-STATION": "Foucault Landing", - "LHS 3631-STATION": "Currie Hub", - "LHS 369-STATION": "Cavendish Port", - "LHS 371-STATION": "Fischer Works", - "LHS 391-STATION": "Savinykh Works", - "LHS 411-STATION": "Kuhn Colony", - "LHS 417-STATION": "Gernhardt Camp", - "LHS 450-STATION": "Wilson Relay", - "LHS 5287-STATION": "Mcarthur's Reach", - "LHS 6282-STATION": "Kendrick Base", - "LHS 64-STATION": "Kopra Survey", - "LOGONI-STATION": "Knight Platform", - "LOKAPURI-STATION": "McArthur Dock", - "LOUIS DE LACAILLE PROSPECT": "Lacaille Prospect", - "LP 102-320-STATION": "Shepard Hub", - "LP 167-64-STATION": "Chu City", - "LP 29-188-STATION": "Smith Enterprise", - "LP 320-359-STATION": "Fisher Camp", - "LP 465-14-STATION": "Oluwafemi Terminal", - "LP 5-88-STATION": "Midgley Settlement", - "LP 51-17-STATION": "Archambault Horizons", - "LP 64-194-STATION": "Longyear Survey", - "LP 673-13-STATION": "Brown Orbital", - "LP 71-157-STATION": "Buckland Colony", - "LP DRACONIS-STATION": "McDivitt Settlement", - "LTT 10482-STATION": "Hubble Relay", - "LTT 15294-STATION": "Tem Ring", - "LTT 4131-STATION": "Ponce de Leon Station", - "LTT 4461-STATION": "Artsebarsky Gateway", - "LTT 5455-STATION": "Blaha Legacy", - "LUCAB KU-STATION": "Potter Station", - "LUGGERATES-STATION": "Stewart Settlement", - "LUGIEN CHABTANI-STATION": "Conklin Ring", - "LUYTEN 674-15-STATION": "Sinclair Relay", - "LUYTEN'S STAR-STATION": "Still Outpost", - "MAITAOKONA-STATION": "Gresley Gateway", - "MANARATO-STATION": "Goldstein Installation", - "MARASING-STATION": "Thiele Enterprise", - "MARKANOMOVOY-STATION": "Compton Dock", - "MARSINATANI-STATION": "Hewish Relay", - "MCC 858-STATION": "Jacquard Orbital", - "MELIAE-STATION": "Shawl Beacon", - "MILDEPTU-STATION": "Gerst Platform", - "MIZAR-STATION": "Borel Park", - "MORGOR-STATION": "Romanek's Folly", - "MOROS-STATION": "Tesla Depot", - "MOXONS MOJO": "Moxon's Mojo", - "MU NORA-STATION": "Virts Port", - "MUFRID-STATION": "Hardwick Base", - "MULLAG-STATION": "Kelly City", - "NANG TA-KHIAN-STATION": "Hay Point", - "NARAKA-STATION": "Novitski Oasis", - "NENER-STATION": "Popov Dock", - "NGOLITJALI-STATION": "Vinogradov Platform", - "NICOBARESE-STATION": "Berezovoy Station", - "NLTT 46621-STATION": "Hope Point", - "NLTT 48502-STATION": "Webb Holdings", - "NLTT 53889-STATION": "Roosa Platform", - "NUWANG-STATION": "Schade Outpost", - "NZAMBASSEE-STATION": "Garriott Stop", - "OKINOUKHE-STATION": "Stableford Ring", - "OKUAPANG-STATION": "Pribylov Park", - "ORI-STATION": "Alexeyev Depot", - "OT SERPENTIS-STATION": "Serebrov Port", - "PACHANU-STATION": "Aubakirov Hub", - "PAN-STATION": "Gunn Plant", - "PANGLUYA-STATION": "Bradbury Works", - "PAUL-FRIEDRICHS STAR-STATION": "Paul-Friedrichs Base Camp", - "PEMEDE-STATION": "Berners-Lee Terminal", - "PI-FANG-STATION": "Brooks Estate", - "PIRAN-STATION": "Garcia Gateway", - "PLINY-STATION": "Sharman Gateway", - "PROCYON-STATION": "Manakov Dock", - "PSAMATHE-STATION": "Nelson Gateway", - "QUINESS-STATION": "Lockyer's Rest", - "RAKAPILA-STATION": "Stone Enterprise", - "ROSS 1015-STATION": "Bowersox Mines", - "ROSS 104-STATION": "Glenn Dock", - "ROSS 1051-STATION": "Abetti Platform", - "ROSS 128-STATION": "Warren Prison Mine", - "ROSS 130-STATION": "Huxley Relay", - "ROSS 210-STATION": "Viktorenko Park", - "ROSS 211-STATION": "Chilton Vision", - "ROSS 318-STATION": "Koch Hub", - "ROSS 486-STATION": "Brash Vision", - "ROSS 490-STATION": "Delucas Landing", - "ROSS 905-STATION": "Morukov Platform", - "ROSS 986-STATION": "Jones Station", - "SALARHUL-STATION": "Lavoisier Outpost", - "SETING-STATION": "Cox Landing", - "SHAMA-STATION": "Clairaut Port", - "SHEELA NA GIG-STATION": "Birkhoff Terminal", - "SHEPHERD RING": "Shepherd Ring", - "SIEGEL HANGER": "Siegel Hanger", - "SIGMA BOOTIS-STATION": "Meikle Platform", - "SOFAGRE-STATION": "Markov Park", - "SOKOJI-STATION": "Cavendish Relay", - "SONG TE TIANS-STATION": "La Cosa Dock", - "SOPDU-STATION": "Borlaug Camp", - "STEIN 2051-STATION": "Trevithick Port", - "STURCKOW CITY": "Sturckow City", - "STYX-STATION": "Chi Hub", - "SUDZ-STATION": "Divis Enterprise", - "SUKUB TUNGATIS-STATION": "Allen Horizons", - "SURACI-STATION": "Priestley Ring", - "SURYA-STATION": "Burbank Camp", - "TABASSAPISI-STATION": "Parise Camp", - "TAEXALKOLOINE-STATION": "Rutherford Works", - "TAIMA BAIJUHACMOORA-STATION": "Mills Park", - "TALITHA-STATION": "Ross Platform", - "TATIL-STATION": "Mallett Settlement", - "TAU BOOTIS-STATION": "Weitz Hub", - "TENG YEH-STATION": "Zhen Port", - "THETA URSAE MAJORIS-STATION": "Landsteiner Silo", - "THOTTACAHUAN WANG-STATION": "Baxter Camp", - "TIETHAY-STATION": "Santos Plant1", - "TOLLAN-STATION": "Bayliss Base", - "TSOHODIAE-STATION": "Barba Port", - "TUN-STATION": "Tun's Wart", - "TYR-STATION": "Walz Works", - "V538 AURIGAE-STATION": "Card Park", - "V989 CASSIOPEIAE-STATION": "Low Works", - "VIKTORENKO PARK": "Viktorenko Park", - "WANGGU-STATION": "Besonders Port", - "WEI JUNG-STATION": "Cooper Dock", - "WIKMEANG-STATION": "Ivanov Hub", - "WISE 1506+7027-STATION": "Silverberg Relay", - "WOLF 1409-STATION": "Carter Vision", - "WOLF 1478-STATION": "Franklin Orbital", - "WOLF 294-STATION": "Hippalus Station", - "WOLF 359-STATION": "Lomas Orbiter", - "WOLF 417-STATION": "Egan Port", - "WOLF 424-STATION": "Sping Terminal", - "WOLF 437-STATION": "Fischer Platform", - "WOLF 46-STATION": "Fischer City", - "WOLF 497-STATION": "Bamford Station", - "WOLF 54-STATION": "Meeking's Way", - "WUNIAN-STATION": "Sellers Landing", - "WX URSA MAJORIS-STATION": "Teng-Hui Terminal", - "XI URSAE MAJORIS-STATION": "Joule Settlement", - "XI WANGKALA-STATION": "Ross Colony", - "YANYAN-STATION": "Morin City", - "YARIGUI-STATION": "Schade City", - "YE'KUAPEMAS-STATION": "Hawke's Progress", - "ZARALUVUL-STATION": "Sturckow City", - "ZETA HERCULIS-STATION": "Shepherd Ring", + "STYX/STYX-STATION": "Searfoss Plant", + "STYX/CHI HUB": "Searfoss Plant", + "STYX/CHU HUB": "Searfoss Plant", } categories = { @@ -323,6 +24,7 @@ 'MARINE SUPPLIES': 'Marine Equipment', 'TERRAIN ENRICH SYS': 'Land Enrichment Systems', 'HEL-STATIC FURNACES': 'Microbial Furnaces', + 'REACTIVE ARMOR': 'Reactive Armour', } def correctSystem(oldName): @@ -331,7 +33,11 @@ def correctSystem(oldName): except KeyError: return oldName -def correctStation(oldName): +def correctStation(systemName, oldName): + try: + return stations[systemName.upper() + "/" + oldName.upper()] + except KeyError: + pass try: return stations[oldName.upper()] except KeyError: diff --git a/prices.py b/prices.py index 06aee1d4..e34514e0 100644 --- a/prices.py +++ b/prices.py @@ -77,7 +77,7 @@ def dumpPrices(dbFilename, elementMask, stationID=None, file=None, defaultZero=F Item INNER JOIN Category USING (category_id) {stationWhere} - ORDER BY Station.system_id, Station.station_id, Category.name, Item.name + ORDER BY stn.system_id, stn.station_id, Category.name, Item.name """ else: stmt = """ diff --git a/tradedb.py b/tradedb.py index 54acb74c..59cfa86f 100644 --- a/tradedb.py +++ b/tradedb.py @@ -22,6 +22,7 @@ from tradeexcept import TradeException from tradeenv import TradeEnv +import cache import locale locale.setlocale(locale.LC_ALL, '') @@ -432,38 +433,44 @@ def reloadCache(self): """ if self.dbPath.exists(): - # We're looking to see if the .sql file or .prices file - # was modified or created more recently than the last time - # we *created* the db file. - dbFileCreatedTimestamp = self.dbPath.stat().st_mtime - - def getMostRecentTimestamp(altPath): - try: - stat = altPath.stat() - return max(stat.st_mtime, stat.st_ctime) - except FileNotFoundError: - return 0 - - sqlTimestamp, pricesTimestamp = getMostRecentTimestamp(self.sqlPath), getMostRecentTimestamp(self.pricesPath) - - # rebuild if the sql or prices file is more recent than the db file - if max(sqlTimestamp, pricesTimestamp) < dbFileCreatedTimestamp: - # sql and prices file are older than the db, db may be upto date, - # check if any of the table files have changed. - changedFiles = [ fileName for (fileName, _) in self.importTables if getMostRecentTimestamp(Path(fileName)) > dbFileCreatedTimestamp ] - if not changedFiles: + dbFileStamp = self.dbPath.stat().st_mtime + + paths = [ self.sqlPath ] + paths += [ Path(f) for (f, _) in self.importTables ] + + changedPaths = [ + [path, path.stat().st_mtime] + for path in paths + if path.exists() and + path.stat().st_mtime > dbFileStamp + ] + + if not changedPaths: + # Do we need to reload the .prices file? + if not self.pricesPath.exists(): + self.tdenv.DEBUG1("No .prices file to load") + return + + pricesStamp = self.pricesPath.stat().st_mtime + if pricesStamp <= dbFileStamp: self.tdenv.DEBUG1("DB Cache is up to date.") return - self.tdenv.DEBUG0("Rebuilding DB Cache because of modified {}", - ', '.join(changedFiles)) - else: - self.tdenv.DEBUG0("Rebuilding DB Cache [db:{}, sql:{}, prices:{}]", - dbFileCreatedTimestamp, sqlTimestamp, pricesTimestamp) + + self.tdenv.DEBUG0(".prices has changed: re-importing") + cache.importDataFromFile(self.tdenv, self, self.pricesPath, reset=True) + return + + self.tdenv.DEBUG0("Rebuilding DB Cache [{}]", str(changedPaths)) else: self.tdenv.DEBUG0("Building DB Cache") - import cache - cache.buildCache(self.tdenv, dbPath=self.dbPath, sqlPath=self.sqlPath, pricesPath=self.pricesPath, importTables=self.importTables) + cache.buildCache( + self.tdenv, + dbPath=self.dbPath, + sqlPath=self.sqlPath, + pricesPath=self.pricesPath, + importTables=self.importTables + ) ############################################################