/// <summary> /// Creates a bundle of items. /// </summary> /// <param name="itemDescription">An element describing the characteristics of the item.</param> /// <param name="count">The number of items in the bundle.</param> /// <returns>A bundle of items.</returns> public ItemBundle CreateItemBundle(ItemDescription itemDescription, int count) { // Create bundle ItemBundle bundle = null; switch (itemDescription.Type) { case ItemType.Letter: { bundle = new ColoredLetterBundle(this); } break; case ItemType.SimpleItem: { bundle = new SimpleItemBundle(this); } break; default: throw new ArgumentException("Unknown item type: " + itemDescription.Type); } bundle.ID = _itemBundleID++; bundle.Instance = this; bundle.ItemDescription = itemDescription; bundle.ItemCount = count; ItemBundles.Add(bundle); // Return the filled bundle return(bundle); }
/// <summary> /// Generates a list of orders and bundles. TODO this has to be adapted to handle simple items too. While doing so use a configuration for all the settings and feed it to the GUI. /// </summary> /// <param name="wordFile">The word file.</param> /// <param name="baseColors">The colors</param> /// <param name="baseColorProbabilities"></param> /// <param name="seed"></param> /// <param name="minTime"></param> /// <param name="maxTime"></param> /// <param name="orderCount"></param> /// <param name="minItemWeight"></param> /// <param name="maxItemWeight"></param> /// <param name="minPositionCount"></param> /// <param name="maxPositionCount"></param> /// <param name="minBundleSize"></param> /// <param name="maxBundleSize"></param> /// <param name="relativeBundleCount"></param> /// <returns></returns> public static OrderList GenerateOrders( string wordFile, LetterColors[] baseColors, IDictionary <LetterColors, double> baseColorProbabilities, int seed, double minTime, double maxTime, int orderCount, double minItemWeight, double maxItemWeight, int minPositionCount, int maxPositionCount, int minBundleSize, int maxBundleSize, double relativeBundleCount) { // Init random IRandomizer randomizer = new RandomizerSimple(seed); // Read the words that serve as the base for the item types List <string> baseWords = new List <string>(); using (StreamReader sr = new StreamReader(wordFile)) { string line = ""; while ((line = sr.ReadLine()) != null) { baseWords.Add(line.Trim()); } } baseWords = baseWords.Distinct().ToList(); List <char> baseLetters = baseWords.SelectMany(w => w.ToCharArray()).Distinct().ToList(); // --> Build all necessary item descriptions OrderList orderList = new OrderList(ItemType.Letter); int currentItemDescriptionID = 0; foreach (var letter in baseLetters) { foreach (var color in baseColors) { orderList.ItemDescriptions.Add(new ColoredLetterDescription(null) { ID = currentItemDescriptionID++, Color = color, Letter = letter, Weight = randomizer.NextDouble(minItemWeight, maxItemWeight) }); } } // --> Generate orders randomly for (int i = 0; i < orderCount; i++) { // Choose a random word from the list string word = baseWords[randomizer.NextInt(baseWords.Count)]; Order order = new Order() { TimeStamp = randomizer.NextDouble(minTime, maxTime) }; // Add each letter to originalLetters for (int j = 0; j < word.Length; j++) { // Get color based on distribution double r = randomizer.NextDouble(); // Choose a default one just incase LetterColors chosenColor = baseColors.First(); // Go through and check the range of each color, pulling random number down to the current range foreach (var c in baseColors) { if (baseColorProbabilities[c] > r) { chosenColor = c; break; } r -= baseColorProbabilities[c]; } // Add letter to order order.AddPosition( orderList.ItemDescriptions.Single(d => (d as ColoredLetterDescription).Letter == word[j] && (d as ColoredLetterDescription).Color == chosenColor), randomizer.NextInt(minPositionCount, maxPositionCount + 1)); } // Add the order orderList.Orders.Add(order); } // Get probability of item-descriptions Dictionary <ItemDescription, int> itemFrequency = orderList.Orders.SelectMany(o => o.Positions).GroupBy(p => p.Key).ToDictionary(i => i.Key, i => i.Sum(e => e.Value)); double overallCount = itemFrequency.Sum(f => f.Value); Dictionary <ItemDescription, double> itemProbability = itemFrequency.ToDictionary(k => k.Key, v => (double)itemFrequency[v.Key] / overallCount); // --> Generate appropriate bundles for this list int itemsOrdered = (int)(orderList.Orders.Sum(o => o.Positions.Sum(p => p.Value)) * relativeBundleCount); int newItems = 0; int currentBundleID = 0; for (int itemsStored = 0; itemsStored < itemsOrdered; itemsStored += newItems) { // Draw a random item description based on the frequency of the items ItemDescription newBundleDescription = RandomizerHelper.DrawRandomly <ItemDescription>(itemProbability, randomizer); int bundleSize = randomizer.NextInt(minBundleSize, maxBundleSize); double timeStamp = randomizer.NextDouble(minTime, maxTime); ColoredLetterBundle bundle = new ColoredLetterBundle(null) { ID = currentBundleID++, ItemDescription = newBundleDescription, TimeStamp = timeStamp, ItemCount = bundleSize }; // Add bundle to list orderList.Bundles.Add(bundle); // Signal new items newItems = bundleSize; } // Order the orders and bundles orderList.Sort(); // Return it return(orderList); }