public FakeCounterCategory(string name) : base(name) { var inSyncRoot = new object(); InTotal = new SumTotal(inSyncRoot); InPerSec = new RatePerSecond(InTotal, inSyncRoot); var outSyncRoot = new object(); OutTotal = new SumTotal(outSyncRoot); OutPerSec = new RatePerSecond(OutTotal, outSyncRoot); PendingCount = new Delta( InTotal, OutTotal, outSyncRoot); PendingTimeAverage = new MovingAverage( syncRoot: outSyncRoot); var errorsSyncRoot = new object(); ErrorsTotal = new SumTotal(errorsSyncRoot); ErrorsPerSec = new RatePerSecond(ErrorsTotal, errorsSyncRoot); ErrorRatio = new MeanAverage( ErrorsTotal, InTotal, errorsSyncRoot); }
/// <summary> /// The capital method to get random portions for a list of names. /// </summary> /// <param name="itemOrGroupNames"> /// These are the names with which a random portion is supposed to be generated. /// </param> /// <returns> /// A set of item names to some percent where the sum of all the name's portion is 1 (i.e. 100%). /// </returns> /// <remarks> /// <![CDATA[ /// FAQ /// Q: What happens if no names are given? /// A: An ArgumentNullException is thrown. /// /// Q: What happens if you just invoke it with no options whatsoever (meaning, just instantiate it and call this)? /// A: Then every item-name gets a truly random value - the sum of which equals 1. /// /// Q: How does SumTotal work with GivenDirectly? /// A: The only time it matters is when SumTotal exceeds the GivenDirectly's cumulative total; furthermore, SumTotal has no use /// when the GivenDirectly is empty since we are getting random portions and not random values. /// /// Q: So what happens when there are GivenDirectly values and no SumTotal? /// A: Then its just doing the math and nothing is random. /// /// Q: What happens if SumTotal is less-than GivenDirectly's cumulative total. /// A: Then SumTotal is just reassigned to the cumulative total and it again just doing the math - nothing random. /// /// Q: What about when SumTotal exceeds cumulative total? /// A: Then the excess amount is what is used to generate random portions for the other item-names not present /// in GivenDirectly. /// /// Q: What if there are no items in GivenDirectly? /// A: It just resorts back to all item-names having a random portion. /// /// Q: What happens when the item-names don't match the names present in GivenDirectly? /// A: The output is always tied to the item-names - any GivenDirectly not found in the item-names is ignored. /// /// Q: Can a GivenDirectly entry be assigned an value of zero? /// A: Yes, and that is their main purpose to selectively remove randomness for certian item-names - recall /// that the function wants to assign some portion to every item-name, no matter how small. /// /// Q: What happens if I force every item to be zero using GivenDirectly? /// A: An exception is thrown - the function cannot satisfy portions whose sum is equal to both zero and one. /// /// Q: How do the PossibleZeroOuts play with explict values on GivenDirectly? /// A: The PossiableZeroOuts are only considered when they are not present in the GivenDirectly. /// /// Q: What if the SumTotal exceeds the GivenDirectly's sum but all the other item-names are present /// in the PossiblyZeroOut's and, it just so happens, that they all get selected to be zero-ed out? /// A: It leaves one to receive the excess - in effect forcing the dice role to be false for at least /// one of the PossiblyZeroOuts in this case no matter the odds. /// ]]> /// </remarks> public virtual List <Tuple <string, double> > GetNames2Portions(string[] itemOrGroupNames) { const StringComparison STR_OPT = StringComparison.OrdinalIgnoreCase; //make this required if (itemOrGroupNames == null || !itemOrGroupNames.Any()) { throw new ArgumentNullException(nameof(itemOrGroupNames)); } var givenDirectlyItems = GivenDirectly ?? new List <Tuple <VocaBase, double> >(); //immediately reduce this to only the items present in 'itemNames' givenDirectlyItems = givenDirectlyItems.Where(gd => itemOrGroupNames.Any(n => string.Equals(gd.Item1.Name, n, STR_OPT))).ToList(); //get the direct assign's total var givenDirectTotal = givenDirectlyItems.Where(x => x?.Item2 != null) .Select(x => Math.Round(Math.Abs(x.Item2), DF_ROUND_DECIMAL_PLACES)).Sum(); //get total given by the caller if any var sumTotalR = SumTotal.GetValueOrDefault(0); //get a random rate for all item names var randPortions = Etx.RandomDiminishingPortions(itemOrGroupNames.Length, _derivativeSlope); //put this random rate together with each item name var randMap = itemOrGroupNames .Zip(randPortions, (n, v) => new Tuple <string, double>(n, v)).ToList(); //convert it to a dictionary var randDict = new Dictionary <string, double>(); foreach (var t in randMap) { randDict.Add(t.Item1, t.Item2); } //filter zero out's down, likewise, to only what's actually in itemNames var possibleZeroOuts = Pzos2Prob.Keys.Distinct().ToList(); possibleZeroOuts = possibleZeroOuts .Where(p => itemOrGroupNames.Any(i => String.Equals(p, i, STR_OPT))).ToList(); //zero outs will get applied just like any other ReassignRates var actualZeroOuts = new List <Tuple <string, double> >(); //select actual zero outs from the possible zero outs if (possibleZeroOuts.Any()) { foreach (var pzo in possibleZeroOuts) { //this is the only random part in actual zero-outs var diceRoll = Pzos2Prob.ContainsKey(pzo) ? Pzos2Prob[pzo] : _defaultDice; //these predicates are filters var isAlreadyPresent = actualZeroOuts.Any(z => z.Item1 == pzo); var isInGivenDirectly = givenDirectlyItems.Any(x => string.Equals(x.Item1.Name, pzo, STR_OPT)); if (diceRoll(pzo) && !isAlreadyPresent && !isInGivenDirectly) { actualZeroOuts.Add(new Tuple <string, double>(pzo, 0.0D)); } } } //apply any GivenDirectly's of zero like PossibleZeroOuts foreach (var dr in givenDirectlyItems.Where(o => o.Item2 == 0)) { if (actualZeroOuts.All(z => z.Item1 != dr.Item1.Name)) { actualZeroOuts.Add(new Tuple <string, double>(dr.Item1.Name, 0.0D)); } } //zero out all the select names if (actualZeroOuts.Any()) { //make one last check that we aren't zero'ing out everything if (actualZeroOuts.Count == itemOrGroupNames.Length) { throw new WatDaFookIzDis("A sum total of 1 cannot be perserved when " + "all items have been directly assigned to 0."); } randDict = ReassignRates(randDict, actualZeroOuts, _derivativeSlope); } //there is nothing left to do so leave if (givenDirectTotal == 0.0D) { return(randDict.Select(kv => new Tuple <string, double>(kv.Key, kv.Value)).ToList()); } //we will need a denominator if the caller didn't give one use the sum what they did give var total = sumTotalR; //if caller gives a sumtotal in which all the GivenDirectly won't fit then up the total to make it fit if (total < givenDirectTotal) { total = givenDirectTotal; } //get a dict of group names to all 0.0D var calcDict = new Dictionary <string, double>(); //get the sum of each given directly item foreach (var d in givenDirectlyItems) { var dName = d.Item1.Name; if (string.IsNullOrWhiteSpace(dName) || d.Item2 == 0) { continue; } if (calcDict.ContainsKey(dName)) { calcDict[dName] += Math.Abs(d.Item2); } else { calcDict.Add(dName, Math.Abs(d.Item2)); } } var calcMap = new List <Tuple <string, double> >(); //get the item sum as a ratio of the total foreach (var k in itemOrGroupNames) { //we only want to reassign when value was explicitly given in options if (!calcDict.ContainsKey(k)) { continue; } var rate = Math.Round(calcDict[k] / total, DF_ROUND_DECIMAL_PLACES); calcMap.Add(new Tuple <string, double>(k, rate)); } //if the calc map doesn't leave any room for reassignment then we are done if (IsCloseEnoughToOne(Math.Round(calcMap.Select(t => t.Item2).Sum(), DF_ROUND_DECIMAL_PLACES))) { //still need to add in the 0.0 items since calcMap has only the directly assigned values foreach (var k in itemOrGroupNames) { if (calcMap.Any(t => string.Equals(t.Item1, k, STR_OPT))) { continue; } calcMap.Add(new Tuple <string, double>(k, 0.0D)); } return(calcMap); } //convert it to a dictionary return(ReassignRates(randDict, calcMap).Select(kv => new Tuple <string, double>(kv.Key, kv.Value)).ToList()); }
private void ClearAllForm() { InputOne.Clear(); InputTwo.Clear(); SumTotal.Clear(); }