public UniverseGraph GenerateDesignGraph(int count) { if (DataSource.Count < count) { ResetDataSource(count); } var result = new UniverseGraph(); var universeObjects = GetUniverseObjects(); Random rand = new Random(); try { var root = new UniverseVertex() { ID = 1, Text = "root", Model = "Root" }; result.AddVertex(root); //Create and add vertices using some DataSource for ID's foreach (var universe in DataSource.Take(count)) { var parent = new UniverseVertex() { ID = universe.ID, Text = universe.Text, Model = universe }; result.AddVertex(parent); result.AddEdge(new UniverseEdge(root, parent, 1) { Text = string.Format("{0} -> {1}", root.Text, parent.Text) }); var thisUniversesObjects = universeObjects.Where(o => o.UniverseId == universe.ID); foreach (var universObject in thisUniversesObjects) { var child = new UniverseVertex() { ID = universObject.Id, Text = universObject.ObjectName, Model = universObject }; result.AddVertex(child); result.AddEdge(new UniverseEdge(parent, child, 1) { Text = string.Format("{0} -> {1}", parent.Text, child.Text) }); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } return(result); }
public int dist(UniverseGraph.SystemId sid1, UniverseGraph.SystemId sid2) { SystemPair pair = new SystemPair(sid1, sid2); if (!distance.ContainsKey(pair)) return UNREACHABLE; else return distance[pair]; }
public MarketDatabase(UniverseGraph systems, ItemDatabase items) { this.systems = systems; this.items = items; sellers = new Dictionary<string, List<Order>>(); buyers = new Dictionary<string, List<Order>>(); }
public Pathfinder(UniverseGraph graph, float minSecurity, int maxClosedSize) { this.graph = graph; this.minSecurity = minSecurity; this.maxClosedSize = maxClosedSize; distanceCache = new Dictionary<SystemPair, int>(); cacheHits = 0; cacheMisses = 0; }
public void relax(UniverseGraph.SystemId sid1, UniverseGraph.SystemId sid2) { int distUpperBound = dist(sid1, sid2); SystemPair pair = new SystemPair(sid1, sid2); foreach (UniverseGraph.SystemId sid in graph.idToInfo.Keys) { int distCandidate = dist(sid1, sid) + dist(sid, sid2); if (distCandidate < distUpperBound) { distance[pair] = distCandidate; distUpperBound = distCandidate; } } }
//todo : add some kind of control to keep cache size in check public int getDistance(UniverseGraph.SystemId source, UniverseGraph.SystemId dest) { SystemPair key = new SystemPair(source.id, dest.id); if (distanceCache.ContainsKey(key)) { ++cacheHits; return distanceCache[key]; } else { ++cacheMisses; int computedDist = findDist(source, dest); distanceCache[key] = computedDist; return computedDist; } }
private void ResetGraphData() { if (Edges?.Count() > 0) { Edges.Clear(); } if (Vertices?.Count() > 0) { Vertices.Clear(); } if (UniverseGraph != null) { UniverseGraph.Clear(); } UniverseGraph = GraphDataHelper.LoadGraphData(300); }
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 Order(ItemDatabase.Entry item, double price, UniverseGraph.SystemInfo location, int quantity, int minQuantity, int orderId) { this.item = item; this.price = price; this.location = location; this.quantity = quantity; this.minQuantity = minQuantity; this.orderId = orderId; }
public SystemPair(UniverseGraph.SystemId idA, UniverseGraph.SystemId idB) { if (idA.id < idB.id) { id1 = idA; id2 = idB; } else { id2 = idA; id1 = idB; } }
public JumpEstimator(UniverseGraph graph) { this.graph = graph; distance = new Dictionary<SystemPair, int>(); }
public int getDistance(UniverseGraph.SystemInfo source, UniverseGraph.SystemInfo dest) { return getDistance(graph.nameToId[source.name], graph.nameToId[dest.name]); }
public Node(Node parent, UniverseGraph.SystemId sysid) { this.parent = parent; this.sysid = sysid; }
private int findDist(UniverseGraph.SystemId source, UniverseGraph.SystemId dest) { open = new PriorityQueue<int, Node>(); closed = new HashSet<UniverseGraph.SystemId>(); open.push(0, new Node(null, source)); Node current = null; int currentPriority = 0; while ((open.count() > 0) && (closed.Count < maxClosedSize)) { //pop top PriorityQueue<int, Node>.Pair head = open.pop(); current = head.value; currentPriority = head.key; //check if we've reached the destination if (current.sysid.id == dest.id) return currentPriority*-1; if (!closed.Contains(current.sysid)) { //mark that we've already expanded it closed.Add(current.sysid); //expand it foreach (UniverseGraph.SystemId neighbour in graph.systemEdges[current.sysid]) { if (graph.idToInfo[neighbour].security > minSecurity) { Node nNode = new Node(current, neighbour); //decrease priority by number of jumps so far - ie breadth first search //some a* like heuristic would be nice.... int nPriority = currentPriority - 1; open.push(nPriority, nNode); } } } } //some kind of failure state - either no path, or seach size exceeded (too far) return -1; }
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; }