// получаем максимальный номинал из перечисления, который есть в запасах и который меньше указанной суммы:
        private static Banknote_values max_available_value_less_than(uint summ, Banknote_values max_value)
        {
            var banknote_value = ((max_value == Banknote_values.how_many_banknotes_values)? max_value - 1 : max_value);

            while ((Banknote.get_banknote_value_by_text(banknote_value) > summ) ||
                   (banknotes_stock_for_check[Convert.ToInt32(banknote_value)].get_banknote_quantity() == 0))
            {
                if (banknote_value == Banknote_values.ten_rubles)
                {
                    break;
                }
                // переходим к более низкому номиналу, пока номинал превышает сумму или в нулевом количестве
                banknote_value--;
            }
            return(banknote_value);
        }
Example #2
0
        // МЕТОДЫ:
        // наполняем банкомат случайным образом, не выходя за рамки ограничений:
        public static void create_random_ATM_stock()
        {
            Random random_number  = new Random();
            var    banknote_value = Banknote_values.ten_rubles; // здесь немного корявый момент, по сути это должно быть первое значение из перечисления, но как к нему обратиться я не знаю

            do
            {
                // делим максимальное количество купюр на количество номиналов, этим будем ограничивать случайное количество:
                uint random_quantity = Convert.ToUInt32(random_number.Next()) %
                                       (max_banknotes_number / number_of_banknotes_values);
                Banknote next_banknote = new Banknote(Banknote.get_banknote_value_by_text(banknote_value), random_quantity);
                // добавляем новую стопку купюр одного номинала в запас банкомата, даже если их 0:
                banknotes_stock.Add(next_banknote);
                banknote_value++;                                                  // переходим к следующему номиналу
            } while (banknote_value < Banknote_values.how_many_banknotes_values);  // перебираем все номиналы
        }
        private void button_replenishment_Click(object sender, EventArgs e)
        {
            uint number_to_replenish = 0;                    // общее количество купюр для пополнения
            bool everything_is_ok    = true;

            for (int i = 0; i < textbox_array.Length; i++)   // идём по всем номиналам купюр
            {
                try
                {
                    uint quantity_for_value = 0;
                    if (textbox_array[i].Text != "")          // если поле пустое - оставляем ноль, иначе ловит ошибку
                    // здесь могут быть и буквы, поэтому это всё происходит под try:
                    {
                        quantity_for_value = Convert.ToUInt32(textbox_array[i].Text);
                    }
                    if (quantity_for_value < 0)               // отрицательное значение - тоже плохо
                    {
                        everything_is_ok      = false;
                        label_what_to_do.Text = "Количества не могут быть отрицательными!";
                    }
                    number_to_replenish += quantity_for_value; // количество купюр увеличиваем на значение из поля
                    // проверяем, не превысит ли количество вносимых купюр установленное максимально возможное:
                    if ((number_to_replenish + ATM.how_many_banknotes()) > ATM.get_maximum_banknotes_number())
                    {
                        everything_is_ok      = false;
                        label_what_to_do.Text = "Ограничение! Общее количество не должно превышать "
                                                + (ATM.get_maximum_banknotes_number() - ATM.how_many_banknotes());
                    }
                }
                catch
                {
                    everything_is_ok      = false;
                    label_what_to_do.Text = "Введены некорректные количества, введите корректные:";
                }
                if (!everything_is_ok)
                {
                    break;                     // если на каком-то поле некорректное значение или перебор по купюрам, обрываем проверку
                }
            }

            if (!everything_is_ok)
            {
                // красим строку сигнальным цветом, чтобы пользователь увидел, что надо исправить
                label_what_to_do.ForeColor = Color.Yellow;
            }

            else // everything_is_ok
            {
                uint summ_of_replenishment = 0;                  // считаем общую сумму, на которую пополняем
                var  value = Banknote_values.ten_rubles;
                for (int i = 0; i < textbox_array.Length; i++)   // опять идём по всем номиналам, полям для количеств
                {
                    textbox_array[i].Visible = false;            // выше было проверено, что всё ок, поэтому поля для ввода количеств больше не нужны
                    uint quantity_for_value = 0;                 // количество для пополнения определённого номинала
                    if (textbox_array[i].Text != "")             // иначе не сможем конвертировать пустоту в число
                    {
                        quantity_for_value = Convert.ToUInt32(textbox_array[i].Text);
                    }
                    ATM.replenish_banknote(Banknote.get_banknote_value_by_text(value), quantity_for_value);
                    summ_of_replenishment += (Banknote.get_banknote_value_by_text(value) * quantity_for_value);
                    value++;
                }
                // показываем результат, прячем лишнее
                label_what_to_do.Text      = "Успешно внесена сумма: " + summ_of_replenishment;
                label_what_to_do.ForeColor = Color.MediumSpringGreen;

                button_replenishment.Visible = false;
                label1.Visible = false;
                label2.Visible = false;
                label3.Visible = false;
                label4.Visible = false;
                label5.Visible = false;
                label6.Visible = false;
                label7.Visible = false;
                label8.Visible = false;
            }
        }
        // функция проверяет, можем ли мы выдать заданную сумму и заполняет массив купюр (достоинство-количество),
        // которыми можно выдать. Возвращает истину, если всё получилось и ложь - если нет.
        private bool check_and_withdrawal(bool by_large_values)
        {
            label_no_result.Visible = false;
            uint users_wish = 0; // в этой переменной будем хранить сумму, которую хочет получить пользователь

            // СНАЧАЛА ПРОВЕРЯЕМ, НОРМАЛЬНУЮ ЛИ СУММУ ХОЧЕТ ПОЛЬЗОВАТЕЛЬ
            try
            {
                // пытаемся получить сумму из окошка для неё, если там не число - ловим ошибку
                users_wish = Convert.ToUInt32(textBox_for_summ.Text);
            }
            catch
            {
                MessageBox.Show("Запрашиваемая сумма не корректна!");
            }
            if (users_wish == 0)
            // 0 - нормальное число, но не в данном случае
            {
                label_no_result.Text = "Введите ненулевую и недробную сумму";
                return(false);
            }
            // если пользователь хочет больше, чем есть - тоже сразу нет:
            uint ATM_balanсe = ATM.how_much_money();

            if (users_wish > ATM_balanсe)
            {
                label_no_result.Text = "В банкомате нет столько денег!\nПроверьте баланс и попробуйте ввести сумму меньше.";
                return(false);
            }
            // если пользователь хочет более мелкие деньги, чем есть, то тоже нет:
            if (users_wish % Banknote.get_banknote_value_by_text(min_available_value()) != 0)
            {
                label_no_result.Text  = "Минимальная доступная купюра: ";
                label_no_result.Text += Banknote.get_banknote_value_by_text(min_available_value());
                label_no_result.Text += "р. Скорректируйте сумму для выдачи с учётом этого.";
                return(false);
            }

            // для каждой транзакции будем заполнять массив с проверочными остатками заново:
            banknotes_stock_for_check.Clear();

            // пара сокращений:
            Banknote_values min_value = Banknote_values.ten_rubles;
            Banknote_values max_value = Banknote_values.how_many_banknotes_values;

            if (by_large_values) // нужна выдача крупными купюрами, о мелких не беспокоимся, просто копируем данные
            {
                for (var value = min_value; value < max_value; value++)
                {
                    Banknote next_banknote = new Banknote(Banknote.get_banknote_value_by_text(value), ATM.how_many_banknotes_of(value));
                    banknotes_stock_for_check.Add(next_banknote);
                }
            }
            else // нужна выдача мелкими купюрами, тут код подлиннее, чтобы сразу понять, какими купюрами можем обойтись
            {
                // изначально полагаем максимальную мелкую купюру равной 200р
                Banknote_values max_small_value      = Banknote_values.two_hundred_rubles;
                uint            summ_of_small_values = 0; // будем считать сумму, которую можем выдать мелкими купюрами

                // копируем остатки банкомата в массив для проверки выдачи суммы, считаем сумму мелких купюр:
                for (var value = min_value; value < max_value; value++)
                {
                    Banknote next_banknote = new Banknote(Banknote.get_banknote_value_by_text(value), ATM.how_many_banknotes_of(value));
                    banknotes_stock_for_check.Add(next_banknote);
                    if (value <= max_small_value)
                    {
                        summ_of_small_values += next_banknote.get_summ();
                        // если посчитали всю сумму мелкими купюрами, и её не хватает, то добавляем к мелким следующую купюру
                        if ((value == max_small_value) && (summ_of_small_values < users_wish))
                        {
                            max_small_value++;  // мы не будем проверять здесь, что значение выйдет за предел диапазона, т.к. уже проверили, что всех денег банкомата для суммы хватит
                        }
                    }
                }
                max_value = max_small_value;  // ограничиваем максимальный номинал максимальной мелкой купюрой, которой хватит для выдачи суммы мелкими купюрами
            }

            // очистим массив снимаемых купюр, будем пополнять его по мере набора желаемой суммы
            try_to_withdraw.Clear();

            // сумма, которую снимаем:
            uint total_summ_to_withdraw = 0;

            // ЖАДНЫЙ АЛГОРИТМ, подбираем купюры для выдачи начиная с самой крупной подходящей:
            while (users_wish > 0) // будем уменьшать это значение по мере подбора банкнот
            {
                // идём от наиболее больших сумм, это же проверка, так мы быстрее наберём нужную сумму
                Banknote_values max_enum_value = max_available_value_less_than(users_wish, max_value);
                var             max_available_banknote_value = Banknote.get_banknote_value_by_text(max_enum_value);

                // максимально "доступный" номинал по факту может оказаться и не доступным:
                if (banknotes_stock_for_check[Convert.ToInt32(max_enum_value)].get_banknote_quantity() == 0)
                {
                    // тогда мы не можем эту купюру использовать и набор суммы завершён
                    label_no_result.Text  = "Не удаётся набрать запрашиваемую сумму, не хватает каких-то купюр.\n";
                    label_no_result.Text += "Попробуйте ввести сумму ";
                    label_no_result.Text += Convert.ToString(total_summ_to_withdraw);
                    // очистим уже частично заполненный массив снимаемых купюр:
                    try_to_withdraw.Clear();
                    return(false);           // проверка окончена
                }
                // ИНАЧЕ продолжаем, добавляем купюру в список для снятия:
                banknotes_stock_for_check[Convert.ToInt32(max_enum_value)].substract_banknote();
                try_to_withdraw.Add(max_available_banknote_value);
                total_summ_to_withdraw += max_available_banknote_value;
                users_wish             -= max_available_banknote_value;
            }
            // дошли до сюда, значит набрали всю сумму

            // скрываем кнопки и поле для суммы, готовим текст о результате
            textBox_for_summ.Visible      = false;
            button_by_small_value.Visible = false;
            button_by_large_value.Visible = false;

            // снимаем все подобранные банкноты по очереди, и печатаем их неповторяющиеся номиналы
            var    used_banknote            = try_to_withdraw[0]; // это для печати, сохраняем номинал первой банкноты на выдачу
            var    number_of_used_banknotes = 0;                  // это тоже для печати
            string info_about_banknotes     = "\nиспользованы купюры:\n" + used_banknote;

            foreach (var value in try_to_withdraw)
            {
                ATM.withdraw_banknote(value);
                if (value != used_banknote)           // показываем количество для выданной купюры
                {
                    info_about_banknotes    += " x " + number_of_used_banknotes + '\n' + value;
                    used_banknote            = value; // начинаем рассматривать следующую
                    number_of_used_banknotes = 0;
                }
                number_of_used_banknotes++;
            }
            info_about_banknotes += " x " + number_of_used_banknotes;   // добавляем информацию о количестве последней выданной купюры

            label_for_positive_result.Text    = "ВЫДАНА СУММА " + total_summ_to_withdraw;
            label_for_positive_result.Text   += info_about_banknotes;
            label_for_positive_result.Visible = true;

            return(true);
        }