Skip to content

Commit 84a0aa8

Browse files
authored
Add solution for Challenge 7 by onomica (#1884)
Auto-merged after 2 days with all checks passing. PR: #1884 Author: @onomica
1 parent 1f00353 commit 84a0aa8

1 file changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package challenge7
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
)
7+
8+
type BankAccount struct {
9+
ID string
10+
Owner string
11+
Balance float64
12+
MinBalance float64
13+
mu sync.Mutex
14+
}
15+
16+
const (
17+
MaxTransactionAmount = 10000.0
18+
)
19+
20+
type AccountError struct {
21+
ID string
22+
Owner string
23+
}
24+
25+
func (e *AccountError) Error() string {
26+
return fmt.Sprintf("account error: %s: %s", e.ID, e.Owner)
27+
}
28+
29+
type InsufficientFundsError struct {
30+
Balance float64
31+
Amount float64
32+
}
33+
34+
func (e *InsufficientFundsError) Error() string {
35+
return fmt.Sprintf("insufficient funds: balance $%.2f, attempted to withdraw $%.2f", e.Balance, e.Amount)
36+
}
37+
38+
type NegativeAmountError struct {
39+
Amount float64
40+
}
41+
42+
func (e *NegativeAmountError) Error() string {
43+
return fmt.Sprintf("negative amount: $%.2f", e.Amount)
44+
}
45+
46+
type ExceedsLimitError struct {
47+
Amount float64
48+
Limit float64
49+
}
50+
51+
func (e *ExceedsLimitError) Error() string {
52+
return fmt.Sprintf("amount $%.2f exceeds limit $%.2f", e.Amount, e.Limit)
53+
}
54+
55+
func NewBankAccount(id, owner string, initialBalance, minBalance float64) (*BankAccount, error) {
56+
if id == "" || owner == "" {
57+
return nil, &AccountError{
58+
ID: id,
59+
Owner: owner,
60+
}
61+
}
62+
63+
if initialBalance < 0 {
64+
return nil, &NegativeAmountError{Amount: initialBalance}
65+
}
66+
if minBalance < 0 {
67+
return nil, &NegativeAmountError{Amount: minBalance}
68+
}
69+
if initialBalance < minBalance {
70+
return nil, &InsufficientFundsError{
71+
Balance: initialBalance,
72+
Amount: minBalance,
73+
}
74+
}
75+
76+
return &BankAccount{
77+
ID: id,
78+
Owner: owner,
79+
Balance: initialBalance,
80+
MinBalance: minBalance,
81+
}, nil
82+
}
83+
84+
func (a *BankAccount) Deposit(amount float64) error {
85+
if err := validateAmount(amount); err != nil {
86+
return err
87+
}
88+
89+
a.mu.Lock()
90+
defer a.mu.Unlock()
91+
a.Balance += amount
92+
return nil
93+
}
94+
95+
func (a *BankAccount) Withdraw(amount float64) error {
96+
if err := validateAmount(amount); err != nil {
97+
return err
98+
}
99+
100+
a.mu.Lock()
101+
defer a.mu.Unlock()
102+
103+
if a.Balance-amount < a.MinBalance {
104+
return &InsufficientFundsError{
105+
Balance: a.Balance,
106+
Amount: amount,
107+
}
108+
}
109+
110+
a.Balance -= amount
111+
return nil
112+
}
113+
114+
func (a *BankAccount) Transfer(amount float64, target *BankAccount) error {
115+
if a == target {
116+
return nil
117+
}
118+
119+
if err := validateAmount(amount); err != nil {
120+
return err
121+
}
122+
123+
first, second := a, target
124+
if first.ID > second.ID {
125+
first, second = second, first
126+
}
127+
128+
first.mu.Lock()
129+
defer first.mu.Unlock()
130+
second.mu.Lock()
131+
defer second.mu.Unlock()
132+
133+
if a.Balance-amount < a.MinBalance {
134+
return &InsufficientFundsError{
135+
Balance: a.Balance,
136+
Amount: amount,
137+
}
138+
}
139+
140+
a.Balance -= amount
141+
target.Balance += amount
142+
143+
return nil
144+
}
145+
146+
func validateAmount(amount float64) error {
147+
if amount < 0 {
148+
return &NegativeAmountError{Amount: amount}
149+
}
150+
if amount > MaxTransactionAmount {
151+
return &ExceedsLimitError{Amount: amount, Limit: MaxTransactionAmount}
152+
}
153+
return nil
154+
}

0 commit comments

Comments
 (0)