private PurchaseResult(PurchaseOptimizer <Resource, Self, Other> optimizer, Self simSelf, Other simOther, Resource[] bannedPurchases)
            {
                this.optimizer = optimizer;
                purchases      = new List <Resource>();
                var ledger = new PurchaseOperationResult <Resource>();

                ledger.utilityGained = 0;
                ledger.exchages      = new List <ExchangeResult <Resource> >();

                int iterations = 0;

                //drain the bank
                for (
                    var resource = optimizer.GetHighestPurchaseableUtilityPerCost(simSelf, simOther, bannedPurchases);
                    !EqualityComparer <Resource> .Default.Equals(resource, default);
                    resource = optimizer.GetHighestPurchaseableUtilityPerCost(simSelf, simOther, bannedPurchases))
                {
                    var purchaseResult = optimizer.exchange.Purchase(resource, optimizer.increment, simSelf, simOther);
                    ledger.utilityGained += optimizer.utilityFunctions.GetIncrementalUtility(
                        resource,
                        simSelf,
                        purchaseResult.info.amount);
                    purchaseResult.Execute();
                    ledger.exchages.Add(purchaseResult.info);
                    purchases.Add(resource);

                    iterations++;
                    if (iterations > 1000)
                    {
                        throw new Exception("Attempted to purchase over too many iterations, broke to safegaurd against infinite loop");
                    }
                }

                this.ledger = ledger;
            }
 /// <summary>
 /// Buy and sell items until the bank is empty; maximizing utility
 /// </summary>
 /// <param name="bank">the amount of money which can be spent</param>
 /// <returns>the amount of utility gained during purchase</returns>
 public static PurchaseResult Purchase(PurchaseOptimizer <Resource, Self, Other> optimizer, Self simSelf, Other simOther, Resource[] bannedPurchases = null)
 {
     if (bannedPurchases == null)
     {
         bannedPurchases = new Resource[0];
     }
     return(new PurchaseResult(optimizer, simSelf, simOther, bannedPurchases));
 }