-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathController.java
318 lines (248 loc) · 8.63 KB
/
Controller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
import java.util.Date;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class Controller {
// Input stream scanner
private static Scanner scanner;
// List of banks
private static Bank[] banks;
// Delimiter used to separate card fields when card is read
private final static String CARD_DELIMITER = "@";
// Number of fields in the card data
private final static int NUM_CARD_DATA = 3;
// Index of each field after parsing the card data
private final static int CARD_NUMBER_I = 0;
private final static int EXPIRATION_I = 1;
private final static int BANK_NAME_I = 2;
// Date parser
private final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/yy");
// Choices for accounts
private final static String CHECKING = "1";
private final static String SAVINGS = "2";
// Choice for account actions
private final static String SEE_BALANCE = "1";
private final static String DEPOSIT = "2";
private final static String WITHDRAW = "3";
private final static String SWITCH = "4";
private final static String DONE = "D";
public static void main(String[] args) {
// Initialize scanner
scanner = new Scanner(System.in);
// Initialize an array of banks with clients
initializeBanks();
// Be strict with the date format being parsed
DATE_FORMAT.setLenient(false);
// Controller loop
while (true) {
String[] card;
String cardNumber;
Bank bank;
boolean pinValid;
try {
do {
// wait for card
card = waitForCard();
cardNumber = card[CARD_NUMBER_I];
bank = getBank(card[BANK_NAME_I]);
// wait for a valid pin number
pinValid = waitForPin(cardNumber, bank);
} while (!pinValid);
// loop while the user wants to switch accounts
String action;
do {
// wait for account choice
String account = waitForAccountChoice(cardNumber);
action = DONE; // default to done to avoid unexitable loop
if (!account.equals(DONE)) {
// Loop while the user is not done with the current account
do {
// wait for choice of see balance/deposit/withdraw/done/switch account
action = waitForActionChoice();
if (!action.equals(DONE) && !action.equals(SWITCH)) {
performAction(action, account, cardNumber, bank);
}
} while (!action.equals(DONE) && !action.equals(SWITCH));
}
} while (action.equals(SWITCH));
System.out.println("Goodbye!");
} catch (NoSuchElementException e) {
System.out.println("Reached end of input.");
System.exit(0);
}
}
}
private static void initializeBanks() {
Bank bank1 = new Bank("BoA");
bank1.addClient("123", "123", 0, 0);
bank1.addClient("1234", "1234", 262, 4353);
Bank bank2 = new Bank("Fargo");
bank2.addClient("321", "321", 50, 25);
bank2.addClient("4321", "4321", 6547, 769085);
banks = new Bank[] { bank1, bank2 };
}
// Wait for a valid card to be inserted and return card's data
private static String[] waitForCard() {
String[] card;
do {
System.out.println("Insert your card.");
// Read a line and parse its fields by a delimiter
String line = scanner.nextLine();
System.out.println(line);
card = line.split(CARD_DELIMITER);
} while (!cardValid(card)); // Loop while the card is invalid
return card;
}
// Check if the card is valid
private static boolean cardValid(String[] card) {
Date expiration;
Bank bank;
// Check if card has the correct number of fields
if (card.length < NUM_CARD_DATA) {
System.out.println("Your card is missing fields.");
return false;
}
// Check if the bank exists
bank = getBank(card[BANK_NAME_I]);
if (bank == null) {
System.out.println("Your bank is not supported here.");
return false;
}
// Check if the card number is numeric
if (!card[CARD_NUMBER_I].matches("[0-9]+")) {
System.out.println("You card number doesn't contain only digits.");
return false;
}
// Check if the card number exists in the bank
if (!bank.cardExists(card[CARD_NUMBER_I])) {
System.out.println("Your card isn't registered with the bank.");
return false;
}
// Parse the expiration date and check if it's formatted correctly
try {
expiration = DATE_FORMAT.parse(card[EXPIRATION_I]);
} catch (ParseException e) {
System.out.println("The format of your card's expiration date is invalid.");
return false;
}
// Check if the card is expired
if (expiration.before(new Date())) {
System.out.println("Your card is expired.");
return false;
}
return true;
}
// Search for and return the bank that matches the given name
private static Bank getBank(String bankName) {
for (Bank bank : banks) {
if (bank.getName().equals(bankName)) {
return bank;
}
}
return null;
}
// Wait for a valid pin to be given or timeout after three attempts
private static boolean waitForPin(String cardNumber, Bank bank) {
boolean pinValid;
int counter = 0;
do {
String pin;
System.out.println("Enter your PIN number.");
pin = scanner.nextLine();
System.out.println(pin);
pinValid = pinValid(pin, cardNumber, bank);
if (!pinValid) {
counter++;
}
if (counter == 3) {
System.out.println("Ending session after too many attempts.");
return false;
}
} while (!pinValid); // Loop while pin is invalid
return true;
}
private static boolean pinValid(String pin, String cardNumber, Bank bank) {
// Check if the pin is numeric
if (!pin.matches("[0-9]+")) {
System.out.println("You pin doesn't contain only digits.");
return false;
}
// Check if the entered pin matches the card's pin
if (!bank.pinCorrect(pin, cardNumber)) {
System.out.println("Incorrect pin.");
return false;
}
return true;
}
// Wait for an account choice of checking or savings
private static String waitForAccountChoice(String cardNumber) {
String choice;
do {
System.out.println("Pick an account (1 checking, 2 savings, D done).");
choice = scanner.nextLine();
System.out.println(choice);
} while (!accountValid(choice)); // Loop until a valid choice is given
return choice;
}
private static boolean accountValid(String choice) {
if (choice.equals(SAVINGS) || choice.equals(CHECKING) || choice.equals(DONE)) {
return true;
}
System.out.println("That's not a valid account choice.");
return false;
}
private static String waitForActionChoice() {
String choice;
do {
System.out.println("What would you like to do? (1 see balance, 2 deposit, 3 withdraw, 4 switch account, D done)");
choice = scanner.nextLine();
System.out.println(choice);
} while (!actionValid(choice)); // Loop until a valid action is given
return choice;
}
private static boolean actionValid(String choice) {
if (choice.equals(SEE_BALANCE) || choice.equals(DEPOSIT) || choice.equals(WITHDRAW) || choice.equals(SWITCH)
|| choice.equals(DONE)) {
return true;
}
System.out.println("That is not a valid action.");
return false;
}
private static void performAction(String action, String account, String cardNumber, Bank bank) {
if (action.equals(SEE_BALANCE)) {
int balance;
if (account.equals(CHECKING)) {
balance = bank.getCheckingBalance(cardNumber);
} else {
balance = bank.getSavingsBalance(cardNumber);
}
System.out.println("Balance is: " + balance);
} else {
int quantity = 0;
boolean validInput;
do {
validInput = true;
System.out.println("Enter a quantity.");
try {
quantity = scanner.nextInt();
System.out.println(quantity);
quantity = Math.abs(quantity);
} catch (InputMismatchException e) { // In case input isn't an int
System.out.println("Invalid quantity.");
validInput = false;
}
scanner.nextLine(); // Clear the line
} while (!validInput); // Loop until a valid quantity is given
if (action.equals(WITHDRAW)) {
quantity = -1 * quantity;
}
if (account.equals(CHECKING)) {
bank.updateChecking(quantity, cardNumber);
} else {
bank.updateSavings(quantity, cardNumber);
}
}
}
}