[BANKING] Fleshing out more banking information. Logic to populate fast-access bank account list added UNTESTED
Some checks failed
build / build (21) (push) Has been cancelled

This commit is contained in:
Jkibbels 2024-11-06 20:01:41 -05:00
parent d8a6b7ecd9
commit 87afc5c8ab
3 changed files with 149 additions and 24 deletions

View File

@ -27,7 +27,7 @@ import java.util.Random;
public class AccountNumberGenerator { public class AccountNumberGenerator {
// Callers of this function are required to verify the given number is unique. // Callers of this function are required to verify the given number is unique.
public static String NewAccountNumber(String symbol, Integer routingNumber, Integer accountType, String username) { public static String GenerateNewAccountNumber(String symbol, Integer routingNumber, Integer accountType, String username) {
String generatedAccountNumber = symbol + "-" + routingNumber + "-" + accountType + "-"; String generatedAccountNumber = symbol + "-" + routingNumber + "-" + accountType + "-";
// Block to translate part of username into number format // Block to translate part of username into number format
@ -48,4 +48,22 @@ public class AccountNumberGenerator {
return generatedAccountNumber; return generatedAccountNumber;
} }
// the below functions must be given a key generated from the above function or they will combust into
// not less than one million pieces! :)
public static String GetFinancialSymbolFromId(String accountId) {
return accountId.substring(0, 4);
}
public static Integer GetRoutingNumberFromId(String accountId) {
return Integer.parseInt(accountId.substring(5, 9));
}
public static Integer GetAccountNumberFromId(String accountId) {
return Integer.parseInt(accountId.substring(10, accountId.length()));
}
public static Integer GetAccountTypeFromId(String accountId) {
return (int) accountId.charAt(10);
}
} }

View File

@ -6,9 +6,9 @@ import java.util.List;
// TODO: Add ability to store NBT data of items in the future so we can store not just money but items too // TODO: Add ability to store NBT data of items in the future so we can store not just money but items too
// like a safety deposit box // like a safety deposit box
public class IndividualAccount { public class IndividualAccount {
private String accountNumber; private Integer accountNumber;
private String accountNumberAlias; private String accountNumberAlias;
private String routingNumber; // Will always be the bank it's in private Integer routingNumber; // Will always be the bank it's in
private List<String> accountHolders; private List<String> accountHolders;
private Integer accountBalance; private Integer accountBalance;
private Boolean allowNegativeBalance; private Boolean allowNegativeBalance;
@ -18,7 +18,7 @@ public class IndividualAccount {
public IndividualAccount() {} public IndividualAccount() {}
public IndividualAccount(String accountNumber, String routingNumber, List<String> holders, public IndividualAccount(Integer accountNumber, Integer routingNumber, List<String> holders,
Boolean allowNegativeBalance, Integer initialBalance, String alias) { Boolean allowNegativeBalance, Integer initialBalance, String alias) {
this.accountNumber = accountNumber; this.accountNumber = accountNumber;
this.routingNumber = routingNumber; this.routingNumber = routingNumber;
@ -28,6 +28,12 @@ public class IndividualAccount {
this.accountNumberAlias = alias; this.accountNumberAlias = alias;
} }
public void AddAccountHolder(String newHolder) {
if (!accountHolders.contains(newHolder)) {
accountHolders.add(newHolder);
}
}
public void AliasAccount(String newAlias) { public void AliasAccount(String newAlias) {
this.accountNumberAlias = newAlias; this.accountNumberAlias = newAlias;
} }
@ -36,6 +42,10 @@ public class IndividualAccount {
return accountLocked; return accountLocked;
} }
public void LockAccount() {
accountLocked = true;
}
public Boolean Deposit(Integer amount) { public Boolean Deposit(Integer amount) {
Boolean success = false; Boolean success = false;
if (!accountLocked) if (!accountLocked)
@ -96,11 +106,11 @@ public class IndividualAccount {
return accountBalance; return accountBalance;
} }
public String GetAccountNumber() { public Integer GetAccountNumber() {
return accountNumber; return accountNumber;
} }
public String GetRoutingNumber() { public Integer GetRoutingNumber() {
return routingNumber; return routingNumber;
} }

View File

@ -1,10 +1,11 @@
package jesse.keeblarcraft.BankMgr; package jesse.keeblarcraft.BankMgr;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import static java.util.Map.entry;
import jesse.keeblarcraft.ConfigMgr.ConfigManager; import jesse.keeblarcraft.ConfigMgr.ConfigManager;
// Contains the information of an individual bank // Contains the information of an individual bank
@ -12,9 +13,17 @@ import jesse.keeblarcraft.ConfigMgr.ConfigManager;
// The bank will keep track of all accounts within its facilities. In addition to accounts, the bank // The bank will keep track of all accounts within its facilities. In addition to accounts, the bank
// maintains its own identifier which is unique and other misc things. // maintains its own identifier which is unique and other misc things.
public class IndividualBank { public class IndividualBank {
private Map<String, Integer> ACCOUNT_TYPES = Map.ofEntries(
entry("checking", 0),
entry("savings", 1)
);
ConfigManager config = new ConfigManager(); ConfigManager config = new ConfigManager();
private String routingNumber; // this is the banks unique identifier private Integer routingNumber; // this is the banks unique identifier
private String numberOfAccounts; // Total number of accounts the bank has. This includes only active accounts private Integer numberOfAccounts; // Total number of accounts the bank has. This includes only active accounts inside accountsList.
private String bankFourLetterIdentifier;
private Integer maxBankAccounts = 100_000_000; // Making this simple for myself any one type of account has 8 random numbers genereated so 10^8 possible accounts
// Think FDIC but from the servers account (keeblarcraft insurance corporation) // Think FDIC but from the servers account (keeblarcraft insurance corporation)
// KBIC will ensure an amount of money based on its trustworthiness to a bank and the number of holders it has. // KBIC will ensure an amount of money based on its trustworthiness to a bank and the number of holders it has.
@ -38,30 +47,118 @@ public class IndividualBank {
// READ IN BANK CONFIG // READ IN BANK CONFIG
// A modified config reader is needed here for when each IndividualAccount is read in - the name is taken from that and is attached to the // A modified config reader is needed here for when each IndividualAccount is read in - the name is taken from that and is attached to the
// 'accountsListFromName' structure. This makes it no worse than O(n) to fill these two structures in // 'accountsListFromName' structure. This makes it no worse than O(n) to fill these two structures in.
} // NOTE: This is an *EXPENSIVE* operation! Future us might need to update this. Also note a method is needed for everytime a player opens a new account
// or gets put on one to update the map every time
public Boolean CreateAccount(String holderName, String accountType) { for (Entry<Integer, IndividualAccount> account : accountsList.entrySet()) {
if (accountType.toLowerCase() != "checking" || accountType.toLowerCase() != "savings") { // We must loop over the string of holders for each account as well to make the flattened accountsListFromName map
return false; List<String> accountHolders = account.getValue().GetAccountHolders();
} // TODO: Replace String with enum type in future and remove this early return
Boolean success = false;
// Verify this isn't a blacklisted user
if (!lockedUsers.contains(holderName)) {
// Match each user to the secondary map & add to list-value if not existing
for (Integer holderIndex = 0; holderIndex < accountHolders.size(); holderIndex++) {
if (accountsListFromName.containsKey(accountHolders.get(holderIndex))) {
// Case 1: User exists, update map entry
accountsListFromName.get(accountHolders.get(holderIndex)).add(account.getKey()); // Add a new account id to this person in the new flat map
} else {
// Case 2: User does not already exist; add a new map entry
accountsListFromName.put(accountHolders.get(holderIndex), List.of(account.getKey())); // Store name as key, and new List with the value of ACCOUNT #
}
}
} }
numberOfAccounts = accountsList.size();
}
// Updates the regular bank account list & the fast-access bank account list
// NO values are allowed to be null. Manually update lists separately if that's the behaviour you want!
public void UpdateBankAccounts(String newHolderName, Integer accountIdentifier, IndividualAccount newAccountOnly) {
// Update the fast-access map first
if (accountsListFromName.containsKey(newHolderName)) {
// Check if user is already in map
accountsListFromName.get(newHolderName).add(accountIdentifier);
} else {
// Add new entry to map
accountsListFromName.put(newHolderName, List.of(accountIdentifier));
}
// Update regular account list
if (accountsList.containsKey(accountIdentifier)) {
// This path assumes we are adding a holder as opposed to adding an account (else, how else would this work?)
accountsList.get(accountIdentifier).AddAccountHolder(newHolderName);
} else {
// Non-existent account means a new one!
accountsList.put(accountIdentifier, newAccountOnly);
numberOfAccounts++;
}
}
public Boolean CreateAccount(String holderName, String accountTypeStr) {
Boolean success = false;
if (accountsList.size() <= maxBankAccounts && ACCOUNT_TYPES.containsKey(accountTypeStr.toLowerCase())) {
// Verify this isn't a blacklisted user
if (!lockedUsers.contains(holderName)) {
Integer maxAttempts = 1000; // Reasonably a unique bank account should pop up within 1000 generations. If not, the user may try again.
String accountId = AccountNumberGenerator.GenerateNewAccountNumber(bankFourLetterIdentifier, routingNumber, ACCOUNT_TYPES.get(accountTypeStr), holderName);
// TODO: Fix in future with a method that will guarentee a one-time necessary number generator. Statistically speaking; this will be okay for the
// entire life time of the server. BUT, you never know!
while (maxAttempts != 0 && !accountsList.containsKey(AccountNumberGenerator.GetAccountNumberFromId(accountId))) {
accountId = AccountNumberGenerator.GenerateNewAccountNumber(bankFourLetterIdentifier, routingNumber, ACCOUNT_TYPES.get(accountTypeStr), holderName);
maxAttempts--;
}
// Final check to add the account
Integer actualAccountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId);
if (!accountsList.containsKey(actualAccountNumber)) {
IndividualAccount newAccount = new IndividualAccount(actualAccountNumber, this.routingNumber, List.of(holderName), false, 0, "");
UpdateBankAccounts(holderName, actualAccountNumber, newAccount);
success = true;
}
}
}
return success; return success;
} }
public Boolean HasAccount(String accountIdentifier) { public void AliasAccount(String accountId, String newAlias) {
Integer accountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId);
if (accountsList.containsKey(accountNumber)) {
accountsList.get(accountNumber).AliasAccount(newAlias);
}
}
public Boolean LockAccountHolder(String holderName) {
Boolean success = false;
Integer accountIter = 0;
for (Entry<String, List<Integer>> holderAccounts : accountsListFromName.entrySet()) {
accountsList.get(holderAccounts.getValue().get(accountIter++)).LockAccount();
}
return success;
}
public Boolean CloseAccount(String accountId) {
Boolean success = false;
Integer accountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId);
if (accountsList.get(accountNumber).GetAccountBalance() == 0) {
accountsList.remove(accountNumber);
success = true;
}
return success;
}
public Boolean HasAccount(Integer accountIdentifier) {
Boolean containsAccount = false; Boolean containsAccount = false;
if (accountsList.containsKey(accountIdentifier)) { if (accountsList.containsKey(accountIdentifier)) {
containsAccount = true; containsAccount = true;
} }
return true; return containsAccount;
} }
} }