/// <summary> /// This is a helper method to know what RemoveQuantity will take (between RemovalMultiple and exactAmountOnly, it /// gets a little complex) /// </summary> public static double GetRemoveAmount(IContainer container, double amount, bool exactAmountOnly) { //NOTE: I couldn't think of a way to make this totally threadsafe without adding more to the IContainer interface that returns all the needed //variables in one shot. But in reality, OnlyRemoveMultiples and RemovalMultiple should change very infrequently if ever double retVal = amount; double quantityCurrent = container.QuantityCurrent; // See if the outgoing flow needs to be restricted if (retVal > quantityCurrent) { retVal = quantityCurrent; } // See if it wants even multiples if (container.OnlyRemoveMultiples) { double removalMultiple = container.RemovalMultiple; if (!Math1D.IsDivisible(retVal, removalMultiple)) { // Remove as many multiples of the requested amount as possible retVal = Math.Floor(retVal / removalMultiple) * removalMultiple; } } // Exact amount if (exactAmountOnly && !Math1D.IsNearValue(retVal, amount)) { retVal = 0d; } // Exit Function return(retVal); }
public double RemoveQuantity(double amount, bool exactAmountOnly) { lock (_lock) { double current = GetQuantityCurrent(); double max = GetQuantityMax().Item1; // using the destroyed aware max double actualAmount = amount; // See if I need to restrict the outgoing flow if (actualAmount > current) { actualAmount = current; } //NOTE: Only looking at the whole, not each individual container if (_onlyRemoveMultiples && !Math1D.IsDivisible(actualAmount, _removalMultiple)) { // Remove as many multiples of the requested amount as possible actualAmount = Math.Floor(actualAmount / _removalMultiple) * _removalMultiple; } if (exactAmountOnly && !Math1D.IsNearValue(actualAmount, amount)) { actualAmount = 0d; } if (actualAmount != 0d) { #region Remove it // Ensure that the containers are equalized switch (_ownership) { case ContainerOwnershipType.GroupIsSoleOwner: // Nothing to do break; case ContainerOwnershipType.QuantitiesCanChange: EqualizeContainers(false); break; case ContainerOwnershipType.QuantitiesMaxesCanChange: EqualizeContainers(true); break; default: throw new ApplicationException("Unknown ContainerOwnershipType: " + _ownership.ToString()); } // Remove the value evenly for (int cntr = 0; cntr < _containers.Count; cntr++) { _containers[cntr].Item1.QuantityCurrent -= actualAmount * _ratios[cntr].Item1; // using the destroyed aware ratio } // Cache the new value (this is used if sole owner) _current = current - actualAmount; #endregion } // Exit function return(amount - actualAmount); } }