static void Main(string[] args) { //test space time profit cache //SpaceTimeProfitCache stpCache = new SpaceTimeProfitCache(); //Console.WriteLine(stpCache); //Console.WriteLine(stpCache.achievesBetterProfit("foobar", 1.0, 100)); //Console.WriteLine(stpCache); //Console.WriteLine(stpCache.achievesBetterProfit("foobar", 1.0, 100)); //Console.WriteLine(stpCache); //Console.WriteLine(stpCache.achievesBetterProfit("foobar", 2.0, 100)); //Console.WriteLine(stpCache); //Console.WriteLine(stpCache.achievesBetterProfit("foobar", 3.0, 150)); //Console.WriteLine(stpCache); //Console.WriteLine(stpCache.achievesBetterProfit("foobar", 3.0, 175)); //Console.WriteLine(stpCache); //Console.WriteLine(stpCache.achievesBetterProfit("foobar", 0.5, 175)); //Console.WriteLine(stpCache); //Console.ReadLine(); //return; //test pqueue //PriorityQueue<int, int> pq = new PriorityQueue<int, int>(); //Random r = new Random(); //for (int i = 0; i < 100; ++i) //{ // pq.push(r.Next(1000) - 500, i); //} //while (pq.count() > 0) //{ // PriorityQueue<int, int>.Pair p = pq.pop(); // Console.WriteLine("key = " + p.key + ", value = " + p.value); //} //Console.ReadKey(); //return; Console.WriteLine("Welcome to a rather ghetto build of EveSpaceTrucker."); Console.WriteLine(); Console.Write("Importing Solar System Info..."); //import system info StreamReader reader = File.OpenText( "C:\\Documents and Settings\\snap\\Desktop\\eve\\space trucking\\quantum rise database csvs\\solarSystems.csv"); UniverseGraph universeGraph = new UniverseGraph(); string line = reader.ReadLine(); //ignore header line line = reader.ReadLine(); while (line != null) { universeGraph.addSystemInfo(line); line = reader.ReadLine(); } reader.Close(); Console.WriteLine(" OK."); Console.Write("Importing System Jump Info..."); //import jump info to construct adjacency lists reader = File.OpenText( "C:\\Documents and Settings\\snap\\Desktop\\eve\\space trucking\\quantum rise database csvs\\solarSystemJumps.csv"); line = reader.ReadLine(); //ignore header line line = reader.ReadLine(); while (line != null) { universeGraph.addJumpInfo(line); line = reader.ReadLine(); } reader.Close(); Console.WriteLine(" OK."); float lowSecThreshhold = 0.5f; Console.WriteLine("Removing Systems with Security < "+lowSecThreshhold+" ..."); // cull lowsec from the map int cullCount = universeGraph.removeLowSecuritySystems(lowSecThreshhold); Console.WriteLine("OK, number of systems culled was "+cullCount); Console.Write("Importing Item Type Info ..."); ItemDatabase items = new ItemDatabase(); items.parseInvTypes( "C:\\Documents and Settings\\snap\\Desktop\\eve\\space trucking\\quantum rise database csvs\\invTypes.csv"); Console.WriteLine(" OK."); Console.Write("Importing Market Dumps ..."); MarketDatabase market = new MarketDatabase(universeGraph, items); DirectoryInfo dumpDir = new DirectoryInfo( "C:\\Documents and Settings\\snap\\My Documents\\EVE\\logs\\Marketlogs\\"); FileInfo[] dumps = dumpDir.GetFiles("*.txt"); foreach (FileInfo fi in dumps) { string dumpPath = fi.FullName; //Console.WriteLine("- " + dumpPath); market.parseMarketDumpFile(dumpPath); } Console.WriteLine(" OK."); TradeRouteMiner.Constraints constraints; //trade routes must meet or exceed this level of profit / (volume * jump) constraints.minProfitDensityRate = 3.0; //trade routes must meet or exceed this level of profit / jump assuming ALL items were transported //this ensures orders with small quantities are ignored, unless they are very profitable per item constraints.minBulkProfitRate = 30000.0; Pathfinder pather = new Pathfinder(universeGraph, 0.5f, 1024); TradeRouteMiner routeMiner = new TradeRouteMiner(pather, market, items); routeMiner.setConstraints(constraints); string distanceCachePath = "C:\\Documents and Settings\\snap\\Desktop\\eve\\space trucking\\cache\\jumps.cache"; Console.WriteLine("Importing jumps from "+distanceCachePath); pather.importDistanceCache(distanceCachePath); Console.Write(" OK."); Console.WriteLine("Computing trade routes ..."); routeMiner.computeRoutes(); Console.WriteLine(" OK."); Console.WriteLine(" ~ " + routeMiner.addedRoutes + " were added"); Console.WriteLine("Exporting jumps to " + distanceCachePath); pather.exportDistanceCache(distanceCachePath); Console.WriteLine(" OK."); bool quit = false; double initialWallet = 0.0; double initialCargoCap = 0.0; string initialSystemName = ""; int maxJumps = 0; while (!quit) { try { Console.WriteLine("GHETTO PLANNER INTERFACE"); Console.WriteLine("available commands: query, plan"); Console.Write("Cmd >"); string cmd = Console.ReadLine(); if (cmd.Equals("query")) { Console.WriteLine("item names are case sensitive"); Console.Write("Item Name >"); string itemName = Console.ReadLine(); Console.WriteLine("database entry: " + items.nameToEntry[itemName]); continue; } else if (cmd.Equals("plan")) { Console.Write("Wallet >"); initialWallet = double.Parse(Console.ReadLine()); Console.Write("CargoCap >"); initialCargoCap = double.Parse(Console.ReadLine()); Console.Write("SystemName >"); initialSystemName = Console.ReadLine(); //double initialWallet = 60000000.0; //double initialCargoCap = 13000.0; //string initialSystemName = "Amarr"; Console.Write("MaxJumps >"); maxJumps = int.Parse(Console.ReadLine()); } else { continue; } } catch (Exception e) { Console.WriteLine("parse error (?)"); continue; } Console.Write("Attempting to Plan Trade Routes (Experimental, yet Promising!) ..."); TradePlanner planner = new TradePlanner(routeMiner, universeGraph); TradePlanner.PlannerState ps = planner.computePlan(initialWallet, initialCargoCap, initialSystemName, maxJumps); Console.WriteLine(" OK."); planner.nicelyDumpPlanToConsole(ps); Console.ReadKey(); } }
public TradePlanner(TradeRouteMiner trm, UniverseGraph graph) { this.trm = trm; this.graph = graph; }
public List<PlannerState> expandStates(TradeRouteMiner trm, UniverseGraph graph) { //synchronise our idea of history with market state performTradesFromStart(); List<PlannerState> expandedStates = new List<PlannerState>(); //expand no-trade one-jump moves to neighbouring systems List<UniverseGraph.SystemId> neighbours = graph.systemEdges[graph.nameToId[sysName]]; foreach (UniverseGraph.SystemId nid in neighbours) { expandedStates.Add(new PlannerState(this,graph.idToInfo[nid].name)); } // for each trade route destination, expand the most profitable route to that destination // to do this, construct a dictionary of (route,profitRate) pairs indexed by dest Dictionary<string, KeyValuePair<TradeRouteMiner.Route,double>> bestRouteToDest = new Dictionary<string, KeyValuePair<TradeRouteMiner.Route,double>>(); //check if there are any decent trade routes from the current location UniverseGraph.SystemId ourSystemID = graph.nameToId[sysName]; if(trm.systemRoutes.ContainsKey(ourSystemID)) { //Console.WriteLine("[begin expand trade routes]"); //determine best route to each dest foreach (TradeRouteMiner.Route r in trm.systemRoutes[ourSystemID]) { //Console.WriteLine("+ " + r); string destName = r.buyer.location.name; double profitRate = computeProfitRate(r); if ((!bestRouteToDest.ContainsKey(destName)) || (profitRate > bestRouteToDest[destName].Value)) { bestRouteToDest[destName] = new KeyValuePair<TradeRouteMiner.Route, double>(r,profitRate); } } //expand states along best route to each dest foreach (string destName in bestRouteToDest.Keys) { KeyValuePair<TradeRouteMiner.Route,double> pair = bestRouteToDest[destName]; //Console.WriteLine("+{"+destName+"} " + pair.Key + " @ profit/jump " + pair.Value); expandedStates.Add(new PlannerState(this, pair.Key, computeOptimalQuantity(pair.Key))); //Console.WriteLine("++ opt quantity = " + computeOptimalQuantity(pair.Key)); } //Console.WriteLine("[end expand trade routes]"); //Console.ReadLine(); } //restore market state revertTradesToStart(); return expandedStates; }
public double computeProfitRate(TradeRouteMiner.Route route) { //return profit per jump return (double)(computeOptimalQuantity(route)) * route.profitPerItem / jumpElapsedCost(route.jumps); }
public int computeOptimalQuantity(TradeRouteMiner.Route route) { int maxBuyQuantity = (int)(wallet / route.seller.price); int maxCarryQuantity = (int)(cargoCapacity / route.seller.item.volume); //this is how many of the things we can buy and carry int maxPotentialQuantity = Math.Min(maxBuyQuantity, maxCarryQuantity); //ensure we dont try to carry more things than there are to buy / sell return Math.Min(maxPotentialQuantity, route.quantity); }
//used to advance to a new state via a trade route public PlannerState(PlannerState previous, TradeRouteMiner.Route routeToTake, int quantityToHaul) { this.cargoCapacity = previous.cargoCapacity; this.wallet = previous.wallet + routeToTake.profitPerItem * quantityToHaul; this.jumpsElapsed = previous.jumpsElapsed + jumpElapsedCost(routeToTake.jumps); this.sysName = routeToTake.buyer.location.name; this.parent = previous; this.lastRoute = routeToTake; this.lastQuantityHauled = quantityToHaul; }