Menu
CoddyTech
flag Ar iconالعربيةdown icon

نظام مصرفي

جزء من قسم البرمجة كائنية التوجّه في رحلة GDScript على Coddy. الدرس 63 من 65.

challenge icon

التحدي

صعب

أنشئ بنكًا يضم نوعين من الحسابات. تُعيد كل عملية قاموس نتيجة {"ok": bool, "message": String}؛ ويطبع الكود المرفق النتيجة بصيغة OK: MESSAGE أو Failed: MESSAGE. جميع المبالغ من النوع float، ويظهر كل مبلغ في الرسالة بمنزلتين عشريتين بعد $.

Transaction في transaction.gd: يأخذ المُنشئ kind ("deposit" أو "withdrawal" أو "interest") وamount. تُعيد _to_string() النوع بحرفه الأول كبيرًا، ثم المبلغ: Deposit - $200.00. لا يخزّن سجل المعاملة الحساب المرتبط به.

Account في account.gd فئة @abstract:

  • يأخذ المُنشئ account_number وowner_name وinitial_balance. تُخزّن الأموال في _balance الخاص؛ أما balance فهي خاصية للقراءة فقط، ويُعيد مُسترجعها قيمة _balance. و_history هي Array[Transaction]، وتُعيد get_history() هذه المصفوفة.
  • توجد طريقتان مجردتان: account_type() -> String وwithdrawal_error(amount: float) -> String، التي تُعيد سبب رفض السحب، أو "".
  • deposit(amount): إذا كان المبلغ 0 أو أقل، تفشل العملية مع Deposit amount must be positive. وإلا تُضاف الأموال، ويُسجّل سجل معاملة من نوع deposit، وتُعاد الرسالة Deposited $A. New balance: $B.
  • withdraw(amount): إذا كان المبلغ 0 أو أقل، تفشل العملية مع Withdrawal amount must be positive؛ وإذا أعادت withdrawal_error() نصًا غير فارغ، تفشل العملية مع ذلك النص. وإلا تُسحب الأموال، ويُسجّل سجل معاملة من نوع withdrawal، وتُعاد الرسالة Withdrew $A. New balance: $B، ويتبعها (Overdraft) عندما يصبح الرصيد أقل من 0.
  • تُعيد _to_string() القيمة TYPE NUMBER (OWNER): $BALANCE.

SavingsAccount في savings_account.gd ترث من Account، مع الثابتين INTEREST_RATE = 0.02 وMIN_BALANCE = 100.0. نوعها هو Savings. يُرفض السحب الذي سيجعل الرصيد أقل من MIN_BALANCE مع الرسالة Cannot withdraw below minimum balance of $100.00. تضيف apply_interest() قيمة balance * INTEREST_RATE، وتسجّل سجل معاملة من نوع interest، وتُعيد الرسالة Applied interest: $I. New balance: $B.

CheckingAccount في checking_account.gd ترث من Account، مع الثابت OVERDRAFT_LIMIT = 200.0. نوعها هو Checking. يمكن أن ينخفض الرصيد حتى -200.00؛ ويُرفض السحب الذي سيخفضه أكثر من ذلك مع الرسالة Cannot exceed overdraft limit of $200.00.

يحتفظ Bank في bank.gd بالحسابات في قاموس خاص، ويكون رقم الحساب هو المفتاح:

  • يأخذ المُنشئ bank_name.
  • create_account(kind, account_number, owner_name, initial_balance) هي دالة مصنع: تكون قيمة kind إما savings أو checking، بأي حالة للأحرف. وتفشل مع Account number already exists أو Invalid account type، وإلا فتُعيد Savings account created successfully (أو Checking).
  • تُعيد get_account(account_number) -> Account الحساب، أو null.
  • transfer(from_number, to_number, amount): تفشل مع One or both accounts not found؛ وتسحب من الحساب الأول، وإذا فشل السحب، تفشل مع Transfer failed: متبوعًا برسالة السحب. وإلا فتودع المبلغ في الحساب الثاني وتُعيد Transferred $A from FROM to TO.
  • تُعيد total_holdings() -> float مجموع جميع الأرصدة.

يقرأ الكود المرفق اسم البنك، ثم الأوامر. بالنسبة إلى هذا الإدخال:

First Bank
open savings|S1|Alice|1000
open checking|C1|Bob|50
withdraw S1|950
transfer S1|C1|300
withdraw C1|400
history C1
total

يكون الناتج:

OK: Savings account created successfully
OK: Checking account created successfully
Failed: Cannot withdraw below minimum balance of $100.00
OK: Transferred $300.00 from S1 to C1
OK: Withdrew $400.00. New balance: $-50.00 (Overdraft)
History of C1:
1. Deposit - $300.00
2. Withdrawal - $400.00
Total held by First Bank: $650.00

ضع الكود في transaction.gd وaccount.gd وsavings_account.gd وchecking_account.gd وbank.gd. يحتوي main.gd على كود الإدخال/الإخراج المرفق، ولا يمكن تعديله.

جرّب بنفسك

extends Node

func _ready():
	# شيفرة الإدخال/الإخراج المقدَّمة: اتركها كما هي

	var bank := Bank.new(OS.read_string_from_stdin())

	var line := OS.read_string_from_stdin()
	while line != "":
		var parts := line.split(" ", true, 1)
		var f: PackedStringArray = parts[1].split("|") if parts.size() > 1 else PackedStringArray()
		match parts[0]:
			"open":
				show_result(bank.create_account(f[0], f[1], f[2], float(f[3])))
			"deposit":
				show_result(bank.get_account(f[0]).deposit(float(f[1])))
			"withdraw":
				show_result(bank.get_account(f[0]).withdraw(float(f[1])))
			"interest":
				var account: Account = bank.get_account(f[0])
				if account is SavingsAccount:
					var savings := account as SavingsAccount
					show_result(savings.apply_interest())
				else:
					print("Failed: ", f[0], " is not a savings account")
			"transfer":
				show_result(bank.transfer(f[0], f[1], float(f[2])))
			"history":
				var history: Array = bank.get_account(f[0]).get_history()
				print("History of ", f[0], ":")
				for i in history.size():
					print(i + 1, ". ", history[i])
			"account":
				print(bank.get_account(f[0]))
			"total":
				print("Total held by %s: $%.2f" % [bank.bank_name, bank.total_holdings()])

		line = OS.read_string_from_stdin()

func show_result(result: Dictionary) -> void:
	print(("OK: " if result["ok"] else "Failed: ") + result["message"])

جميع دروس البرمجة كائنية التوجّه

تدرّب بنفسك: مترجم GDScript عبر الإنترنت