public IList <PrizeResultRow> CombinePrizeResultTables(IList <PrizeResultRow> table1, IList <PrizeResultRow> table2) { if (table1 == null || table2 == null) { throw new ArgumentException("prize results tables must not be null"); } //check that both tables have the same number of entries if (table1.Count != table2.Count) { throw new ArgumentException("pull results tables must be the same size"); } //check that both tables have the same schema (prize cat names, prizename, prizeindex int rowCount = table1.Count; for (int counter = 0; counter < rowCount; counter++) { PrizeResultRow table1Row = table1[counter]; PrizeResultRow table2Row = table2[counter]; if (table1Row.PrizeIndex != table2Row.PrizeIndex || table1Row.PrizeCategoryName != table2Row.PrizeCategoryName || table1Row.PrizeName != table2Row.PrizeName) { throw new ArgumentException("table1 and table 2 must have the same schema with respect to PrizeIndex, PrizeName, PrizeCategoryName"); } } IList <PrizeResultRow> combinedPrizeResultsTable = table1.Zip(table2, (t1, t2) => new PrizeResultRow() { PrizeIndex = t1.PrizeIndex, PrizeCategoryName = t1.PrizeCategoryName, PrizeName = t1.PrizeName, PrizeSelectedCount = t1.PrizeSelectedCount + t2.PrizeSelectedCount }).ToList(); return(combinedPrizeResultsTable); }
public IList <PrizeResultRow> SelectPrizes(IList <SelectionDomain> selectionDomains, Random random = null) { #region Validations foreach (var selectionDomain in selectionDomains) { if (selectionDomain.PrizesToSelectFromDomainCount <= 0) { throw new ArgumentException($"PrizesToSelectFromDomainCount for SelectFromDomain {selectionDomain.SelectionDomainName} must be greater than 0"); } if (!_prizeSelectionTableHelper.IsPrizeSelectionTableValid(selectionDomain.PrizeSelectionTable)) { throw new ArgumentException($"PrizeSelectionTable for selectionDomain {selectionDomain.SelectionDomainName} was invalid"); } } #endregion Stopwatch sw = Stopwatch.StartNew(); //Set up variables and structures if (random == null) { random = new Random(); } IList <PrizeNameCategoryPair> uniquePrizeNames = GetUniquePrizeNameCategoryPairs(selectionDomains); int finalPrizeRowCount = uniquePrizeNames.Count(); IList <PrizeResultRow> prizeResultTable = new List <PrizeResultRow>(finalPrizeRowCount); List <IDictionary <int, int> > resultSummariesList = new List <IDictionary <int, int> >(); //perform the actual selection and counting for (int domainCounter = 0; domainCounter < selectionDomains.Count; domainCounter++) { SelectionDomain currentSelectionDomain = selectionDomains[domainCounter]; //for intermediate use because we need to update the prize counts in a performant way. IDictionary <int, int> resultsSummary = _prizeResultsTableHelper.GetEmptyPrizeResultsSummary(currentSelectionDomain.PrizeSelectionTable.Count); for (int counter = 0; counter < currentSelectionDomain.PrizesToSelectFromDomainCount; counter++) { PrizeSelectionRow selectedPrizeRow = SelectPrizeFromPrizeTable(currentSelectionDomain.PrizeSelectionTable, random.NextDouble()); if (selectedPrizeRow != null) { resultsSummary[selectedPrizeRow.PrizeIndex]++; } } resultSummariesList.Add(resultsSummary); } //now that we have the counts of selected prizes by index, we need to translate them back to the more //informative structure of the prize results table //generate table with all the data except counts and indexes prizeResultTable = uniquePrizeNames.Select(psr => new PrizeResultRow() { PrizeCategoryName = psr.CategoryName, PrizeIndex = 0, PrizeName = psr.PrizeName, PrizeSelectedCount = 0 }).ToList(); //put in indexes for (int i = 0; i < finalPrizeRowCount; i++) { prizeResultTable[i].PrizeIndex = i + 1; } //now insert the counts; assumption is that the keys of the generated resultsSummary dictionary must match in number //and start at the same index (1), as the largestSelectionDomain which is used to prepopulate the prizeResultTable for (int domainCounter = 0; domainCounter < selectionDomains.Count; domainCounter++) { //since the resultsSummary dictionaries don't have names embedded, we can only relate the counts //to prize name in context of the associated selection domain. SelectionDomain currentSelectionDomain = selectionDomains[domainCounter]; IDictionary <int, int> resultsSummary = resultSummariesList[domainCounter]; //walk through prizeResultTable one prize at a time, ADDING in counts //walk through non zero resultsSummary one prize at a time, linking to prize name and ADDING in counts for (int item = 0; item < resultsSummary.Count; item++) { if (resultsSummary[item + 1] > 0) { //get prize name from selection domain prizeSelectionTable string prizeName = currentSelectionDomain.PrizeSelectionTable .Where(r => r.PrizeIndex == (item + 1)).Select(r => r.PrizeName).Single(); //now map prizeName back to prizeResultTable PrizeResultRow rowToUpdate = prizeResultTable.Single(p => p.PrizeName == prizeName); rowToUpdate.PrizeSelectedCount += resultsSummary[item + 1]; } } } sw.Stop(); _logger.LogDebug($"finished a selection operation in {sw.ElapsedMilliseconds} milliseconds"); return(prizeResultTable); }