public IProductAmountCollection BuyGoods(IPopulationGroup buyer, IProduct good, double amount, IPopulationGroup seller) { if (buyer is null) { throw new ArgumentNullException(nameof(buyer)); } if (good is null) { throw new ArgumentNullException(nameof(good)); } if (seller is null) { throw new ArgumentNullException(nameof(seller)); } if (amount <= 0) { throw new ArgumentOutOfRangeException(nameof(amount)); } // get the cash we have available. var cash = buyer.GetCash(AcceptedCurrencies); var result = new ProductAmountCollection(); // if we have any cash, try to buy with that first. if (cash.Any(x => x.Item2 > 0)) { // Buy what we can with our cash. var transaction = seller.BuyGood(cash, good, amount, this); // With our transaction initiated, complete it on the buyer's end. buyer.CompleteTransaction(transaction); // Add the transaction to our return value result.AddProducts(transaction); // Update our desired amount amount -= transaction.GetProductValue(good); } // if we still have more to buy, it means we are out of cash. Begin bartering. // check we have things to barter. if (amount > 0 && buyer.ForSale.Any(x => x.Item2 > 0) && BarterLegal) { // Begin Bartering var barter = seller.BarterGood(buyer.ForSale, good, amount, this); // with the barter complete, finish for buyer. buyer.CompleteTransaction(barter); // add the transaction to the result result.AddProducts(barter); } // we've bought what we could from the pop, so return. return(result); }
/// <summary> /// Buys good from the market. /// </summary> /// <param name="buyer">The one buying the good.</param> /// <param name="good">The good they are trying to buy.</param> /// <param name="amount">How much they are trying to buy.</param> /// <returns>The Receipt of purchases</returns> public IProductAmountCollection BuyGoodsFromMarket(IPopulationGroup buyer, IProduct good, double amount) { if (buyer is null) { throw new ArgumentNullException(nameof(buyer)); } if (good is null) { throw new ArgumentNullException(nameof(good)); } if (amount <= 0) { throw new ArgumentOutOfRangeException(nameof(amount)); } // The result of the purchases. IProductAmountCollection result = new ProductAmountCollection(); // First buy from local merchants, they only accept cash. result = Populous.Merchants .BuyGood(buyer.GetCash(AcceptedCurrencies), good, amount, this); // see how much was bought. double remainder = 0; // if any was bought, update what we are seeking. if (result.Contains(good)) { remainder = amount - result.GetProductValue(good); // and complete the transaction buyer.CompleteTransaction(result); } // if no remainder, return if (remainder <= 0) { return(result); } // Then buy from everyone else via both cash and barter. foreach (var seller in Populous.GetPopsSellingProduct(good)) { // If someone is selling the good, buy or barter with them. var reciept = BuyGoods(buyer, good, remainder, seller); // if something was bought if (reciept.Count() > 0) { // remove it from the remainder remainder -= reciept.GetProductValue(good); // add it to our result result.AddProducts(reciept); } // if nothing remains, we're done. if (remainder <= 0) { return(result); } } // Finish buy going to the travelling merchants, if all else fails. foreach (var travSeller in TravellingMerchantsSelling(good)) { var reciept = travSeller.BuyGood(buyer.GetCash(AcceptedCurrencies), good, remainder, this); // if something was bought if (reciept.Count() > 0) { // remove it from remainder remainder -= reciept.GetProductValue(good); // Complete the transaction for the buyer buyer.CompleteTransaction(reciept); // add it to the result result.AddProducts(reciept); } // if nothing remains, return if (remainder <= 0) { return(result); } } // return the ultimate receipt. return(result); }