Skip to main content

"Банкомат" 💳🏦

Splash

Условие на задачата

Създайте конзолно приложение, което имитира функционалността на банкомат, позволяващ на потребителите да извършват различни банкови операции.

Цели на задачата

Целта на задачата е да се създаде приложение, което имитира основните функционалности на реален банкомат. Това включва възможността за проверка на баланс, депозитиране, теглене на средства, както и валидиране на потребителски данни.

Стъпки за Реализация

  1. Създайте клас Account, който представлява банкова сметка

    1. Той трябва да има следните полета:
      • balance: текущия баланс на сметката.
      • pin: PIN кодът на сметката.
      • accountNumber: номер на сметката.
    2. Трябва да има методи за:
      • getBalance(): връща текущия баланс на сметката.
      • deposit(amount): депозира сумата amount в сметката.
      • withdraw(amount): тегли сумата amount от сметката.
      • checkPin(pin): проверява дали pin съвпада с PIN кода на сметката.
    3. Трябва да има конструктор, който инициализира всички полета на класа.
  2. Създайте енумерация Commands със следните стойности:

    • WELCOME: съобщение за добре дошли.
    • ASK_ACCOUNT_NUMBER: съобщение за въвеждане на номер на сметка.
    • ACCOUNT_NUMBER: номер на сметка.
    • ASK_PIN: съобщение за въвеждане на PIN код.
    • PIN: PIN код.
    • WITHDRAW: съобщение за теглене на средства.
    • DEPOSIT: съобщение за депозиране на средства.
    • GET_BALANCE: съобщение за проверка на баланса.
    • ERROR: съобщение за грешка.
    • EXIT: съобщение за изход от приложението.
  3. Създайте енумерация Data със следните стойности:

    • ACCOUNT_NUMBER: съобщение за въвеждане на номер на сметка.
    • ACCOUNT: Сметка на потребителя.
  4. Създайте енумерация Status със следните стойности:

    • OK: съобщение за успешна транзакция.
    • ERROR: съобщение за неуспешна транзакция.
  5. Създайте клас ServerThread, който наследява Runnable и представлява сървър за банкомат.

    1. Той трябва да има следните полета:
      • accounts: списък с всички сметки.
      • sessionData: данни за текущата сесия, представлява HashMap с ключове от тип Data и стойности от тип Object.
      • socket: сокет за връзка с клиента.
      • reader: Scanner четец на вход от клиента.
      • writer: PrintStream писател на изход към клиента.
    2. Трябва да има конструктор, който получава сокет и го инициализира, инициализира списъка с всички аканти и инициализира sessionData.
    3. Трябва да има метод run(), който се изпълнява при стартиране на нишката.
      • Той трябва да изпълнява следните стъпки:
        1. Инициализира reader и writer със съответните потоци от сокета.
        2. Изпълнява метода ServerLogic().
        3. Затваря сокета.
    4. Трябва да има следните методи:
      • SendMessage - изпраща съобщение към клиента. Приема един аргумент от тип Commands и съобщение от тип String. Съобщението трябва да е командата, последвана от съобщението, разделени със :.
      • SendStatus - изпраща съобщение за статус към клиента. Приема един аргумент от тип Commands и статус от тип Status. Съобщението трябва да е командата, последван от статуса, разделени със :.
      • GetMessage - Служи за обработка на вход от клиента. Чака вход от клиента, разделя го на команда и съобщение и принтира командата и съобщението, след което извиква метод за обработка на командата.
      • ProcessMessage - Служи за обработка на команди от клиента. Приема един аргумент от тип Commands и съобщение от тип String. Използва switch конструкция за да извика съответния метод за обработка на командата.
      • ServerLogic - Входяща точка която еднократно изпраща съобщение за добре дошли и след това извиква GetMessage. Тук добавяме и последователност от стъпки за тестване на цялата функционалност на приложението.
  6. Създайте клас Server с метод main(), който създава сървър за банкомат и го стартира.

    • Сървърът трябва да слуша на порт 8080.
    • Създаваме нов ExecutorService с 3 нишки и изпълняваме сървъра в него. Това ни позволява да обработваме 3 клиента едновременно. При нужда можем да увеличим броя на нишките. ExecutorService executor = Executors.newFixedThreadPool(3);
    • В безкраен цикъл приемаме нови клиенти и стартираме нова нишка за всяка една от тях. executor.execute(new ServerThread(socket));
  7. Създайте клас Client с метод main(), който създава клиент за банкомат и го стартира.

    1. Той трябва да има следните полета:
      • socket: сокет за връзка със сървъра.
      • reader: Scanner четец на вход от сървъра.
      • writer: PrintStream писател на изход към сървъра.
      • scanner: Scanner четец на вход от конзолата.
    2. main метода трябва да изпълнява следните стъпки:
      1. Инициализира socket със сървъра на порт 8080 и IP адрес 127.0.0.1.
      2. Инициализира reader и writer със съответните потоци от сокета.
      3. Инициализира scanner със стандартния вход.
      4. Изпълнява метода RunLogic().
      5. Затваря сокета.
    3. Трябва да има следните методи:
      • PerformAction - Служи за обработка на командите от сървъра. Получава като аргумент цял ред от тип String и го разделя на команда и съобщение, :. Използва switch конструкция за да извика съответния метод за обработка на командата.
      • SendMessage - изпраща съобщение към сървъра. Приема един аргумент от тип Commands и съобщение от тип String. Съобщението трябва да е командата, последвана от съобщението, разделени със :.
      • SendStatus - изпраща съобщение за статус към сървъра. Приема един аргумент от тип Commands и статус от тип Status. Съобщението трябва да е командата, последван от статуса, разделени със :.
      • RunLogic - Входяща точка която в безкраен цикъл чака за входящо съобщение от сървъра и го обработва, чрез извикване на PerformAction.

Технически Аспекти

  • Вход и Изход: Използването на Scanner класа в Java за четене на вход от конзолата и PrintStream за извеждане на съобщения.
  • Обработка на Изключения: Проверка за валидност на въведените данни и обработка на потенциални грешки.

Решение на Задачата

Кликнете на снимката за да отворите примерният код

Splash