public void Execute() { int[] sellerIdx = new int[_sellers.Count]; // create an array of the seller indices for (int i = 0; i < _sellers.Count; i++) { sellerIdx[i] = i; } // create the threads to process the potential combinations for (int i = 0; i < _maxThreads; i++) { new Thread(new ThreadStart(ConsumeJob)).Start(); } _queue.Start(); for (int i = 1; i <= _maxCombinations; i++) { _results.Add(i, new List <PotentialCombination>()); Combinations <int> combinations = new Combinations <int>(sellerIdx, i); Console.WriteLine("Searching " + combinations.Count + " combinations of " + i + " sellers:"); int j = 0; foreach (IList <int> c in combinations) { // to quickly check whether it's even worth checking the detailed inventory for each seller, we construct // a bitarray of all the items, setting the value to 1 if the seller has any of that item. We then OR together // the arrays from each seller in this combination and call GetBitArrayCardinality which counts the number // set to 1 without having to iterate through the whole array. We then only do a full check if it matches the item count BitArray baseArray = new BitArray(_items.Count); foreach (var k in c) { Seller seller = _sellers[k]; baseArray.Or(seller.ItemAvailiabilityArray); } if (GetBitArrayCardinality(baseArray) == _items.Count) { // item count matches so add to queue for full check _queue.Enqueue(new PotentialCombination(c, j, i)); } Console.Write("\r{0} combinations searched", j + 1); j++; } Console.WriteLine(); Console.WriteLine(); } // shut the consumer queue off and wait for the last one to signal it's done. _queue.Stop(); if (_queue.Count > 0) { // wait for the _waitHandle.Set() call in ConsumeJob which gets called by the last completing thread _waitHandle.WaitOne(); } for (int i = 1; i <= _maxCombinations; i++) { Console.WriteLine("{0} sellers: {1} valid combinations found", i, _results[i].Count); } }
public void Export() { CreateDefaultHtml(); StringBuilder sb = new StringBuilder(); sb.AppendLine("<html><head><style> table { border-collapse: collapse; } * {font-family: arial; font-size: 1em; } </style></head><body><h3>Results generated on " + DateTime.Now + "</h3><p><a href=\"wantedlist.html\" target=\"details\">Wanted list</a></p>"); for (int i = 1; i <= _maxCombinations; i++) { sb.AppendLine("<p><b>" + i + " seller solutions:</b></p><ul>"); if (_results[i].Count > 0) { List <PotentialCombination> results = _results[i].OrderBy(o => o.Price).ToList(); // if more results than the limit, restrict to the limit int limit = (results.Count > _maxResults) ? _maxResults : results.Count; for (int j = 0; j < limit; j++) { var pc = results[j]; ResultSet rs = new ResultSet(_items); foreach (var k in pc.SellerIds) { Seller seller = _sellers[k]; rs.Sellers.Add(seller.Storename); foreach (var lot in seller.AvailableItems) { rs.CurrentStatus[lot.GetId()] += lot.Quantity; rs.CurrentItems.Add(lot); } } rs.CalculateCost(); sb.AppendLine("<li><a href=\"" + i + "-" + j + ".html\" target=\"details\">" + string.Join(",", rs.Sellers.ToArray()) + " (£" + pc.Price + ")</a></li>"); rs.CreateFile("", _outputDir + i + "-" + j + ".html", rs.CreateDisplayHtml(_itemsLookup, _imageUrls, _sellerLookup)); } } else { sb.AppendLine("<li>No results</li>"); } sb.AppendLine("</ul>"); } sb.AppendLine("</body></html>"); this.ExportWantedList(); StreamWriter logger = File.CreateText(_outputDir + "resultlist.html"); logger.Write(sb.ToString()); logger.Close(); Console.WriteLine(); Console.WriteLine("Results have been written to:"); Console.WriteLine("{0}index.html", _outputDir); }