def run(results, cmdenv, tdb): from commands.commandenv import ResultRow calc = TradeCalc(tdb, cmdenv) lhs = cmdenv.startStation rhs = cmdenv.stopStation if lhs == rhs: raise CommandLineError("Must specify two different stations.") results.summary = ResultRow() results.summary.fromStation = lhs results.summary.toStation = rhs trades = calc.getTrades(lhs, rhs) if not trades: raise CommandLineError("No profitable trades {} -> {}".format( lhs.name(), rhs.name())) if cmdenv.detail > 1: tdb.getAverageSelling() tdb.getAverageBuying() for item in trades: results.rows.append(item) return results
def run(results, cmdenv, tdb): from commands.commandenv import ResultRow calc = TradeCalc(tdb, cmdenv) lhs = cmdenv.startStation rhs = cmdenv.stopStation if lhs == rhs: raise CommandLineError("Must specify two different stations.") results.summary = ResultRow() results.summary.fromStation = lhs results.summary.toStation = rhs trades = calc.getTrades(lhs, rhs) if not trades: raise CommandLineError("No profitable trades {} -> {}".format( lhs.name(), rhs.name() )) if cmdenv.detail > 1: tdb.getAverageSelling() tdb.getAverageBuying() for item in trades: results.rows.append(item) return results
def run(results, cmdenv, tdb): cmdenv.DEBUG1("loading trades") if tdb.tradingCount == 0: raise NoDataError("Database does not contain any profitable trades.") # Instantiate the calculator object calc = TradeCalc(tdb, cmdenv) validateRunArguments(tdb, cmdenv, calc) origPlace, viaSet = cmdenv.origPlace, cmdenv.viaSet avoidPlaces = cmdenv.avoidPlaces stopStations = cmdenv.destinations goalSystem = cmdenv.goalSystem maxLs = cmdenv.maxLs # seed the route table with starting places startCr = cmdenv.credits - cmdenv.insurance routes = [ Route( stations=(src,), hops=(), jumps=(), startCr=startCr, gainCr=0, score=0 ) for src in cmdenv.origins ] numHops = cmdenv.hops lastHop = numHops - 1 viaStartPos = 1 if origPlace else 0 cmdenv.DEBUG1("numHops {}, vias {}, adhocHops {}", numHops, len(viaSet), cmdenv.adhocHops) results.summary = ResultRow() results.summary.exception = "" if cmdenv.loop: routePickPred = lambda route: \ route.lastStation is route.firstStation elif cmdenv.shorten: if not cmdenv.destPlace: routePickPred = lambda route: \ route.lastStation is route.firstStation elif isinstance(cmdenv.destPlace, System): routePickPred = lambda route: \ route.lastSystem is cmdenv.destPlace else: routePickPred = lambda route: \ route.lastStation is cmdenv.destPlace else: routePickPred = None pickedRoutes = [] pruneMod = cmdenv.pruneScores / 100 if cmdenv.loop: distancePruning = lambda rt, distLeft: \ rt.lastSystem.distanceTo(rt.firstSystem) <= distLeft elif cmdenv.destPlace and not cmdenv.direct: distancePruning = lambda rt, distLeft: \ any( stop for stop in stopSystems if rt.lastSystem.distanceTo(stop) <= distLeft ) else: distancePruning = False if distancePruning: maxHopDistLy = cmdenv.maxJumpsPer * cmdenv.maxLyPer if not cmdenv.loop: stopSystems = {stop.system for stop in stopStations} for hopNo in range(numHops): restrictTo = None if hopNo == lastHop and stopStations: restrictTo = set(stopStations) manualRestriction = bool(cmdenv.destPlace) elif len(viaSet) > cmdenv.adhocHops: restrictTo = viaSet manualRestriction = True if distancePruning: preCrop = len(routes) distLeft = maxHopDistLy * (numHops - hopNo) routes = [rt for rt in routes if distancePruning(rt, distLeft)] if not routes: if pickedRoutes: break raise NoDataError( "No routes are in-range of any end stations at the end of hop {}" .format(hopNo) ) pruned = preCrop - len(routes) if pruned: cmdenv.NOTE("Pruned {} origins too far from any end stations", pruned) if hopNo >= 1 and (cmdenv.maxRoutes or pruneMod): routes.sort() if pruneMod and hopNo + 1 >= cmdenv.pruneHops and len(routes) > 10: crop = int(len(routes) * pruneMod) routes = routes[:-crop] cmdenv.NOTE("Pruned {} origins", crop) if cmdenv.maxRoutes and len(routes) > cmdenv.maxRoutes: routes = routes[:cmdenv.maxRoutes] if cmdenv.progress: extra = "" if hopNo > 0 and cmdenv.detail > 1: extra = extraRouteProgress(routes) print( "* Hop {:3n}: {:.>10n} origins {}" .format(hopNo+1, len(routes), extra) ) elif cmdenv.debug: cmdenv.DEBUG0("Hop {}...", hopNo+1) try: newRoutes = calc.getBestHops(routes, restrictTo=restrictTo) except NoHopsError: if hopNo == 0 and len(cmdenv.origSystems) == 1: raise NoDataError( "Couldn't find any trading links within {} x {}ly jumps of {}." .format( cmdenv.maxJumpsPer, cmdenv.maxLyPer, cmdenv.origSystems[0].name(), ) ) raise NoDataError( "No routes had reachable trading links at hop #{}".format(hopNo + 1) ) if not newRoutes: if pickedRoutes: break checkReachability(tdb, cmdenv) if hopNo > 0: if restrictTo and manualRestriction: results.summary.exception += routeFailedRestrictions( tdb, cmdenv, restrictTo, maxLs, hopNo ) break results.summary.exception += ( "SORRY: Could not find profitable destinations " "beyond hop #{:n}\n" .format(hopNo + 1) ) break if hopNo == 0: if cmdenv.origPlace and len(routes) == 1: errText = ( "No profitable buyers found for the goods at {}.\n" "\n" "You may want to try:\n" " {} local \"{}\" --ly {} -vv --stations --trading" .format( routes[0].lastStation.name(), sys.argv[0], cmdenv.origPlace.system.name(), cmdenv.maxJumpsPer * cmdenv.maxLyPer, ) ) if isinstance(cmdenv.origPlace, Station): errText += ( "\n" "or:\n" " {} market \"{}\" --sell -vv" .format( sys.argv[0], cmdenv.origPlace.name(), ) ) raise NoDataError(errText) routes = newRoutes if routes and goalSystem: # Promote the winning route to the top of the list # while leaving the remainder of the list intact routes.sort( key=lambda route: 0 if route.lastSystem is goalSystem else 1 ) if routes[0].lastSystem is goalSystem: cmdenv.NOTE("Goal system reached!") routes = routes[:1] break if routePickPred: pickedRoutes.extend( route for route in routes if routePickPred(route) ) if cmdenv.loop or cmdenv.shorten: cmdenv.DEBUG0("Using {} picked routes", len(pickedRoutes)) routes = pickedRoutes # normalise the scores for fairness... for route in routes: cmdenv.DEBUG0( "{} hops, {} score, {} gpt", len(route.hops), route.score, route.gpt ) route.score /= len(route.hops) if not routes: raise NoDataError( "No profitable trades matched your critera, " "or price data along the route is missing." ) if viaSet: routes, caution = filterByVia(routes, viaSet, viaStartPos) if caution: results.summary.exception += caution + "\n" routes.sort() results.data = routes return results