2024-11-05 00:45:28 +00:00
package jesse.keeblarcraft.BankMgr ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
2024-11-07 01:01:41 +00:00
import java.util.Map.Entry ;
2024-11-05 00:45:28 +00:00
2024-11-07 01:01:41 +00:00
import static java.util.Map.entry ;
2024-11-05 00:45:28 +00:00
import jesse.keeblarcraft.ConfigMgr.ConfigManager ;
// Contains the information of an individual 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.
public class IndividualBank {
2024-11-07 01:01:41 +00:00
private Map < String , Integer > ACCOUNT_TYPES = Map . ofEntries (
entry ( " checking " , 0 ) ,
entry ( " savings " , 1 )
) ;
2024-11-05 00:45:28 +00:00
ConfigManager config = new ConfigManager ( ) ;
2024-11-07 01:01:41 +00:00
private Integer routingNumber ; // this is the banks unique identifier
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
2024-11-05 00:45:28 +00:00
// 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.
private Integer kbicInsuredAmount ;
private Boolean kbicInsured ;
// bankMoney is the total amount of money the bank possesses itself. The bank itself is personally responsible
// for backing the amount of money it claims it has and this is the balance that is withdrawn from for credits.
// A bank can have a sum of money that is less than the total amount of money of all its account holders
private Integer bankMoney ;
// Key = ACCOUNT NUMBER
// Value = ACCOUNT
private HashMap < Integer , IndividualAccount > accountsList ;
private HashMap < String , List < Integer > > accountsListFromName ; // This is a list that just points to a list of account numbers by person. USEFUL
private List < String > lockedUsers ; // A list of users who are locked out of the bank and are incapable of performing more actions within it
public IndividualBank ( String routingNumber ) {
accountsList = new HashMap < Integer , IndividualAccount > ( ) ;
accountsListFromName = new HashMap < String , List < Integer > > ( ) ;
// READ IN BANK CONFIG
2024-11-07 01:01:41 +00:00
2024-11-05 00:45:28 +00:00
// 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
2024-11-07 01:01:41 +00:00
// '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
for ( Entry < Integer , IndividualAccount > account : accountsList . entrySet ( ) ) {
// We must loop over the string of holders for each account as well to make the flattened accountsListFromName map
List < String > accountHolders = account . getValue ( ) . GetAccountHolders ( ) ;
// 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 ( ) ;
2024-11-05 00:45:28 +00:00
}
2024-11-07 01:01:41 +00:00
// 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 + + ;
}
}
2024-11-05 00:45:28 +00:00
2024-11-07 01:01:41 +00:00
public Boolean CreateAccount ( String holderName , String accountTypeStr ) {
2024-11-05 00:45:28 +00:00
Boolean success = false ;
2024-11-07 01:01:41 +00:00
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 ) ;
2024-11-05 00:45:28 +00:00
2024-11-07 01:01:41 +00:00
// 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 - - ;
}
2024-11-05 00:45:28 +00:00
2024-11-07 01:01:41 +00:00
// 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 ;
}
}
2024-11-05 00:45:28 +00:00
}
2024-11-07 01:01:41 +00:00
return success ;
}
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 ;
2024-11-05 00:45:28 +00:00
2024-11-07 01:01:41 +00:00
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 ;
}
2024-11-05 00:45:28 +00:00
return success ;
}
2024-11-07 01:01:41 +00:00
public Boolean HasAccount ( Integer accountIdentifier ) {
2024-11-05 00:45:28 +00:00
Boolean containsAccount = false ;
if ( accountsList . containsKey ( accountIdentifier ) ) {
containsAccount = true ;
}
2024-11-07 01:01:41 +00:00
return containsAccount ;
2024-11-05 00:45:28 +00:00
}
2024-11-07 01:01:41 +00:00
}