Menu
CoddyTech

Sistema bancario

Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 63 di 65.

challenge icon

Sfida

Difficile

Crea una banca con due tipi di conto. Ogni operazione restituisce un dizionario di risultato {"ok": bool, "message": String}; il codice fornito lo stampa come OK: MESSAGE oppure Failed: MESSAGE. Tutti gli importi sono float e ogni importo in un messaggio ha due cifre decimali dopo un $.

Transaction in transaction.gd: il costruttore accetta kind ("deposit", "withdrawal" oppure "interest") e amount. _to_string() restituisce il tipo con la prima lettera maiuscola, seguito dall’importo: Deposit - $200.00. Una transazione non memorizza il proprio conto.

Account in account.gd è una classe @abstract:

  • Il costruttore accetta account_number, owner_name e initial_balance. Il denaro è conservato in _balance, che è privato; balance è una proprietà di sola lettura il cui getter restituisce _balance. _history è un Array[Transaction] e get_history() lo restituisce.
  • Due metodi astratti: account_type() -> String e withdrawal_error(amount: float) -> String, che restituisce il motivo per cui un prelievo viene rifiutato, oppure "".
  • deposit(amount): un importo pari a 0 o inferiore non va a buon fine e restituisce Deposit amount must be positive. Altrimenti aggiunge il denaro, registra una transazione deposit e restituisce Deposited $A. New balance: $B.
  • withdraw(amount): un importo pari a 0 o inferiore non va a buon fine e restituisce Withdrawal amount must be positive; un withdrawal_error() non vuoto non va a buon fine e restituisce quel testo. Altrimenti preleva il denaro, registra una transazione withdrawal e restituisce Withdrew $A. New balance: $B, seguito da (Overdraft) quando il saldo è inferiore a 0.
  • _to_string() restituisce TYPE NUMBER (OWNER): $BALANCE.

SavingsAccount in savings_account.gd estende Account, con le costanti INTEREST_RATE = 0.02 e MIN_BALANCE = 100.0. Il suo tipo è Savings. Un prelievo che lascerebbe un saldo inferiore a MIN_BALANCE viene rifiutato con Cannot withdraw below minimum balance of $100.00. apply_interest() aggiunge balance * INTEREST_RATE, registra una transazione interest e restituisce Applied interest: $I. New balance: $B.

CheckingAccount in checking_account.gd estende Account, con la costante OVERDRAFT_LIMIT = 200.0. Il suo tipo è Checking. Il saldo può scendere fino a -200.00; un prelievo che lo farebbe scendere ulteriormente viene rifiutato con Cannot exceed overdraft limit of $200.00.

Bank in bank.gd conserva i conti in un dizionario privato indicizzato per numero di conto:

  • Il costruttore accetta bank_name.
  • create_account(kind, account_number, owner_name, initial_balance) è una factory: kind può essere savings oppure checking, indipendentemente dalle maiuscole e minuscole. Restituisce un errore con Account number already exists oppure Invalid account type; altrimenti restituisce Savings account created successfully (oppure Checking).
  • get_account(account_number) -> Account restituisce il conto oppure null.
  • transfer(from_number, to_number, amount): restituisce un errore con One or both accounts not found; preleva dal primo conto e, se l’operazione non va a buon fine, restituisce un errore con Transfer failed: seguito dal messaggio del prelievo. Altrimenti deposita sul secondo conto e restituisce Transferred $A from FROM to TO.
  • total_holdings() -> float restituisce la somma di tutti i saldi.

Il codice fornito legge il nome della banca e poi i comandi. Per questo input:

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

l’output è:

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

Il tuo codice va inserito in transaction.gd, account.gd, savings_account.gd, checking_account.gd e bank.gd. main.gd contiene il codice fornito per input/output e non può essere modificato.

Provalo tu

extends Node

func _ready():
	# Codice di input/output fornito: lascialo così com'è

	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"])

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore GDScript online