Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نظام مصرفي

جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 104 من 104.

challenge icon

التحدي

سهل

لنقم ببناء نظام بنكي يوضح نمط الحالة (State pattern)، والوراثة، وإدارة المؤشرات الذكية (smart pointers). ستقوم بإنشاء نظام يمكن أن تكون فيه الحسابات في حالات مختلفة (Active، Frozen، Closed)، ولكل منها سلوكيات متميزة للتعامل مع المعاملات.

ستقوم بتنظيم الكود الخاص بك عبر ستة ملفات:

  • AccountState.h: تحديد البنية التحتية لنمط الحالة لحالات الحساب.

    أنشئ فئة أساسية مجردة AccountState مع دوال افتراضية بحتة (pure virtual methods):

    • deposit(double amount) — تعيد true إذا كان الإيداع مسموحاً به، و false خلاف ذلك
    • withdraw(double amount) — تعيد true إذا كان السحب مسموحاً به، و false خلاف ذلك
    • getStateName() — تعيد اسم الحالة كسلسلة نصية (string)

    قم بتنفيذ ثلاث حالات ملموسة (concrete states):

    • ActiveState: تسمح بكل من الإيداعات والسحوبات، وتعيد "Active"
    • FrozenState: تسمح بالإيداعات ولكنها ترفض السحوبات، وتعيد "Frozen"
    • ClosedState: ترفض كل من الإيداعات والسحوبات، وتعيد "Closed"
  • Account.h: بناء هيكل هرمي للحساب مع إدارة الحالة.

    أنشئ فئة أساسية Account تحتوي على:

    • رقم الحساب (string)، واسم المالك، والرصيد
    • std::unique_ptr<AccountState> لإدارة الحالة الحالية
    • deposit(double amount) — تتحقق من الحالة أولاً، إذا كان مسموحاً تضيف إلى الرصيد وتطبع "Deposited [amount] to [accountNumber]"، وإلا تطبع "Deposit rejected: account is [stateName]"
    • withdraw(double amount) — تتحقق من الحالة، إذا كان مسموحاً وكان هناك رصيد كافٍ، تخصم وتطبع "Withdrew [amount] from [accountNumber]". إذا رفضت الحالة، تطبع "Withdrawal rejected: account is [stateName]". إذا كان الرصيد غير كافٍ، تطبع "Insufficient funds"
    • freeze() و activate() و close() — تغيير حالة الحساب
    • getInfo() — تعيد "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • دالة افتراضية getAccountType() تعيد "Basic"

    أنشئ نوعين من الحسابات المشتقة:

    • SavingsAccount: لديه متطلب حد أدنى للرصيد (يتم تمريره للمنشئ). قم بإعادة تعريف (override) دالة withdraw للتحقق أيضاً مما إذا كان السحب سيجعل الرصيد أقل من الحد الأدنى — إذا كان الأمر كذلك، اطبع "Cannot go below minimum balance of [minimum]". تعيد "Savings" لنوع الحساب.
    • CheckingAccount: لديه حد للسحب المكشوف (overdraft limit) (يتم تمريره للمنشئ). يسمح بالسحوبات حتى (balance + overdraftLimit). تعيد "Checking" لنوع الحساب.
  • Transaction.h: نمذجة المعاملات ككائنات.

    أنشئ فئة Transaction تسجل:

    • نوع المعاملة (string: "Deposit", "Withdrawal", "Transfer")
    • المبلغ
    • رقم الحساب المعني
    • حالة النجاح (bool)

    أضف دالة getDescription() تعيد "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h: إنشاء عميل يمتلك حسابات متعددة.

    العميل Customer لديه اسم، ومعرف (ID)، و vector من std::shared_ptr<Account>. قم بتنفيذ:

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber) — يعيد الحساب المطابق أو nullptr
    • getTotalBalance() — يجمع الأرصدة عبر جميع الحسابات
    • listAccounts() — يطبع معلومات كل حساب
  • Bank.h: تنسيق العمليات البنكية.

    تقوم فئة Bank بتخزين العملاء والاحتفاظ بسجل المعاملات. قم بتنفيذ:

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber) — يبحث في جميع العملاء عن الحساب
    • processDeposit(const std::string& accountNumber, double amount) — يجد الحساب، ينفذ الإيداع، ويسجل المعاملة
    • processWithdrawal(const std::string& accountNumber, double amount) — يجد الحساب، ينفذ السحب، ويسجل المعاملة
    • getTransactionCount() — يعيد إجمالي المعاملات التي تمت معالجتها
  • main.cpp: عرض نظامك البنكي.

    اقرأ أربعة مدخلات:

    1. تفاصيل العميل (تنسيق: name,customerId)
    2. تفاصيل حساب التوفير (تنسيق: accountNumber,minBalance)
    3. العملية 1 (تنسيق: action,accountNumber,amount حيث action هو deposit أو withdraw)
    4. العملية 2 (تنسيق: action,accountNumber,amount أو freeze,accountNumber)

    أنشئ البنك والعميل. أنشئ حساب توفير مع العميل كمالك وأضفه إلى العميل. أضف العميل إلى البنك. قم بمعالجة كلتا العمليتين (إذا كان أمر تجميد freeze، فقم بتجميد الحساب ثم حاول إجراء سحب صغير بقيمة $10 لتوضيح الحالة). أخيراً، اطبع قائمة حسابات العميل وإجمالي عدد المعاملات كـ "Transactions: [count]".

على سبيل المثال، مع المدخلات Alice,C001، و SAV001,100، و deposit,SAV001,500، و withdraw,SAV001,200:

Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2

مع المدخلات Bob,C002، و SAV002,50، و deposit,SAV002,100، و freeze,SAV002:

Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2

مع المدخلات Carol,C003، و SAV003,200، و deposit,SAV003,250، و withdraw,SAV003,100:

Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2

يجمع هذا التحدي بين نمط الحالة لإدارة سلوكيات الحساب، والوراثة لأنواع الحسابات المختلفة، والمؤشرات الذكية لعلاقات الملكية، وتتبع المعاملات — وهي جميعها مفاهيم أساسية أتقنتها طوال هذه الدورة.

جرّب بنفسك

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"

int main() {
    // قراءة المدخل 1: تفاصيل العميل (التنسيق: name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // قراءة المدخل 2: تفاصيل حساب التوفير (التنسيق: accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // قراءة المدخل 3: العملية 1 (التنسيق: action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // قراءة المدخل 4: العملية 2 (التنسيق: action,accountNumber,amount أو freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: تحليل تفاصيل العميل من customerInput
    // تلميح: استخدم find(',') لتقسيم السلسلة النصية
    
    // TODO: تحليل تفاصيل الحساب من accountInput
    
    // TODO: إنشاء البنك
    
    // TODO: إنشاء العميل
    
    // TODO: إنشاء حساب توفير مع تعيين العميل كمالك له
    
    // TODO: إضافة الحساب إلى العميل
    
    // TODO: إضافة العميل إلى البنك
    
    // TODO: تحليل ومعالجة العملية 1
    // التنسيق: action,accountNumber,amount (الـ action هو "deposit" أو "withdraw")
    
    // TODO: تحليل ومعالجة العملية 2
    // يمكن أن تكون: action,accountNumber,amount أو freeze,accountNumber
    // في حال freeze، قم بتجميد الحساب ثم حاول سحب مبلغ $10
    
    // TODO: طباعة قائمة حسابات العميل
    
    // TODO: طباعة عدد العمليات بصيغة "Transactions: [count]"
    
    return 0;
}

جميع دروس Object Oriented Programming