Example #1
0
        /// <summary>
        /// Change composer, based on "greedy algorithm".
        /// </summary>
        /// <param name="walletRepository">The source wallet of the change</param>
        /// <param name="changeValue">The sum of change to compose.</param>
        /// <returns>The change wallet with composed change.</returns>
        public static PaymentWalletRepository ChangeComposer(IWalletRepository walletRepository, Money changeValue)
        {
            // Collect change
            PaymentWalletRepository changeCollected = new PaymentWalletRepository();

            // Collect the change for big to small value
            foreach (var position in walletRepository.WalletList.OrderByDescending(w => w.Item1.Nominal).Where(p => p.Item2 > 0))
            {
                (INotionValue money, int count) = position;
                while (changeValue >= money.MoneyValue && count > 0)
                {
                    count--;
                    changeValue -= money.MoneyValue;
                    changeCollected.AddToWallet(money, 1);
                    walletRepository.RemoveFromWallet(money, 1);
                }
                if (changeValue == Money.Zero)
                {
                    break;
                }
            }

            //Cannot get the change
            if (changeValue != Money.Zero)
            {
                // return all money back
                foreach (var mc in changeCollected.WalletList)
                {
                    walletRepository.AddToWallet(mc.Item1, mc.Item2);
                }
                return(null);
            }

            return(changeCollected);
        }
Example #2
0
        /// <summary>
        /// Processing payment events from the coin receiver
        /// </summary>
        /// <param name="cmd">The event to process.</param>
        /// <param name="payment">The coin received or null</param>
        void PaymentAction(PaymentCmdEvent cmd, INotionValue payment)
        {
            if (VendingMachineState != VendingMachineState.Payment)
            {
                return;
            }
            if (cmd == PaymentCmdEvent.Cancel)
            {
                // Cancellation of the order or/and payment
                CancelOrder();
            }
            else if (cmd == PaymentCmdEvent.Payment)
            {
                _paymentWalletRepository.AddToWallet(payment, 1);
                Money  total = _orderedProducts.Aggregate(Money.Zero, (m, p) => m + p.Price);
                Money  paid  = _paymentWalletRepository.WalletList.Aggregate(Money.Zero, (m, p) => m + new Money(0, (int)p.Item1.Nominal * p.Item2));
                string msg   = String.Format(_vendingMessageRepository.GetMessage(MessageCode.BalancePayment), total, paid);
                _displayPanel.DisplayMessage(msg);
                if (paid >= total)
                {
                    // give change or cancel
                    if (paid > total)
                    {
                        Money change = paid - total;
                        PaymentWalletRepository collectedChange = ChangeComposer(_walletRepository, change);
                        if (collectedChange == null)
                        {
                            DisplayMessageByCode(MessageCode.RunOutOfChange);
                            CancelOrder();
                            return;
                        }
                        foreach (var pm in collectedChange.WalletList)
                        {
                            msg = String.Format(_vendingMessageRepository.GetMessage(MessageCode.GivenChange), pm.Item1.MoneyValue, pm.Item2);
                            _displayPanel.DisplayMessage(msg);
                        }
                    }
                    // complete purchase
                    foreach (var p in _orderedProducts)
                    {
                        msg = String.Format(_vendingMessageRepository.GetMessage(MessageCode.CollectYourPurchase), p);
                        _saleRecord.Sold(p);
                        _displayPanel.DisplayMessage(msg);
                    }

                    _orderedProducts.Clear();
                    foreach (var pm in _paymentWalletRepository.WalletList)
                    {
                        _walletRepository.AddToWallet(pm.Item1, pm.Item2);
                    }

                    _paymentWalletRepository.ClearMoney();
                    // switch back to selling
                    TryToStartSelling();
                    _coinReceiver.Off();
                }
            }
        }