diff --git a/jsonprices.py b/jsonprices.py new file mode 100644 index 00000000..e294434a --- /dev/null +++ b/jsonprices.py @@ -0,0 +1,247 @@ +#! /usr/bin/env python + +import tradedb +from tradeexcept import TradeException +import json + +class UnknownSystemError(TradeException): + def __str__(self): + return "Unknown System: " + ' '.join(self.args) + + +class UnknownStationError(TradeException): + def __str__(self): + return "Unknown Station: " + ' '.join(self.args) + + +def lookup_system(tdb, tdenv, name, x, y, z): + try: + system = tdb.systemByName[name] + except KeyError: + system = None + if not system: + try: + system = tdb.lookupSystem(name) + except LookupError: + pass + + if system: + if (system.posX != x or system.posY != y or system.posZ != z): + raise Exception("System {} position mismatch: " + "Got {},{},{} expected {},{},{}".format( + name, + x, y, z, + system.posX, system.posY, system.posZ + )) + return system + + newSystem = "@{} [{}, {}, {}]".format( + name, x, y, z + ) + + candidates = [] + for candidate in tdb.systemByID.values(): + if (candidate.posX == x and + candidate.posY == y and + candidate.posZ == z + ): + candidates.append(candidate) + + if len(candidates) == 1: + candidate = candidates[0] + if candidate.casefold() != name.casefold(): + if not tdenv.quiet: + print("System name mismatch: " + "Local: {}, " + "Remote: {}, " + "Coords: {}, {}, {}".format( + name, + candidate.dbname, + candidate.posX, + candidate.posY, + candidate.posZ, + )) + return candidates[0] + + if len(candidates): + raise Exception("System {} matches co-ordinates for systems: {}" + + ','.join([system.name for system in candidates]) + ) + + if tdenv.addUnknown: + return tdb.addLocalSystem(name, x, y, z) + + return None + + +def lookup_station(tdb, tdenv, system, name, lsFromStar): + normalizedName = tradedb.TradeDB.normalizedStr(name) + for stn in system.stations: + stnNormalizedName = tradedb.TradeDB.normalizedStr(stn.dbname) + if stnNormalizedName == normalizedName: + if lsFromStar and not stn.lsFromStar: + tdenv.DEBUG0( + "- Updating station {}: " + " dist from star = {}", + stn.name(), + lsFromStar + ) + db = tdb.getDB() + db.execute( + "UPDATE Station " + "SET dist_from_star = ? " + "WHERE station_id = ?", + [lsFromStar, stn.ID] + ) + db.commit() + return stn + + if tdenv.addUnknown: + return tdb.addLocalStation(system, name, lsFromStar) + + return None + +def load_prices_json( + tdb, + tdenv, + jsonText + ): + """ + Take data from a prices file and load it into the database. + """ + + data = json.loads(jsonText) + + sysData = data['sys'] + sysName = sysData['name'] + pos = sysData['pos'] + + stnData = data['stn'] + stnName = stnData['name'] + lsFromStar = stnData['ls'] + + system = lookup_system( + tdb, tdenv, + sysName, + pos[0], pos[1], pos[2], + ) + if not system: + if not tdenv.ignoreUnknown: + raise UnknownSystemError(sysName) + if not tdenv.quiet: + print("NOTE: Ignoring unknown system: {} [{},{},{}]".format( + sysName, + pos[0], pos[1], pos[2], + )) + return + if system.dbname != sysName and tdenv.detail: + print("NOTE: Treating '{}' as '{}'".format( + name, system.dbname + )) + tdenv.DEBUG1("- System: {}", system.dbname) + + station = lookup_station( + tdb, tdenv, + system, + stnName, + lsFromStar, + ) + if not station: + if tdenv.ignoreUnknown: + raise UnknownStationError(stnName) + if not tdenv.quiet: + print("NOTE: Ignoring unknown station: {}/{}".format( + sysName.upper(), stnName + )) + return + tdenv.DEBUG1("- Station: {}", station.dbname) + + +def generate_prices_json( + tdb, + tdenv, + station, + ): + """ + Generate a JSON dump of the specified station along + with everything we know about the station and the system + it is in. + + tdb: + The TradeDB object to use + tdenv: + Settings + station: + Station to dump + """ + + system = station.system + + stationData = { + 'cmdr': tdenv.commander or "unknown", + 'src': 'td/price-json', + 'sys': { + 'name': system.dbname, + 'pos': [ system.posX, system.posY, system.posZ ], + }, + 'stn': { + 'name': station.dbname, + 'ls': station.lsFromStar, + }, + 'items': {} + } + + conn = tdb.getDB() + cur = conn.cursor() + cur.execute(""" + SELECT si.item_id, + si.modified, + sb.price, sb.units, sb.level, + ss.price, ss.units, ss.level + FROM StationItem AS si + LEFT OUTER JOIN StationBuying AS sb + ON ( + sb.station_id = si.station_id + AND sb.item_id = si.item_id + ) + LEFT OUTER JOIN StationSelling AS ss + ON ( + ss.station_id = si.station_id + AND ss.item_id = si.item_id + ) + WHERE si.station_id = ? + """, [station.ID]) + + items = {} + + lastModified = "0" + for ( + itemID, modified, + sbPrice, sbUnits, sbLevel, + ssPrice, ssUnits, ssLevel + ) in cur: + lastModified = max(lastModified, modified) + item = tdb.itemByID[itemID] + itemData = items[item.dbname] = { + 'm': modified, + } + if sbPrice and (sbUnits >= 0 or sbLevel >= 0): + itemData['b'] = [ sbPrice, sbUnits, sbLevel ] + elif sbPrice: + itemData['b'] = sbPrice + if ssPrice and (ssUnits >= 0 or sbLevel >= 0): + itemData['s'] = [ + ssPrice, ssUnits, ssLevel + ] + elif ssPrice: + itemData['s'] = ssPrice + + # dedupe timestamps. + for itemData in items.values(): + if itemData['m'] == lastModified: + del itemData['m'] + + stationData['m'] = lastModified + stationData['items'] = items + + return json.dumps(stationData, separators=(',',':'))