Menu
CoddyTech

מערכת בנקאית

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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 הוא מאפיין לקריאה בלבד, שה-getter שלו מחזיר את _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) היא פונקציית factory: הערך של 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 אונליין