Restore original CFBank API

Moving accounts to player files added unnecessary complexity. Restore
original API and add code to migrate accounts back from player files.

While here, wrap CFBank with a context manager so it can be used with
the Python 'with' statement.

git-svn-id: svn://svn.code.sf.net/p/crossfire/code/maps/trunk@20449 282e977c-c81d-0410-88c4-b93c2d0d6712
master
partmedia 2017-07-27 06:35:06 +00:00
parent 45f873736b
commit 739ca3508b
3 changed files with 47 additions and 64 deletions

View File

@ -1,12 +1,7 @@
""" """
Created by: Joris Bontje <jbontje@suespammers.org> Created by: Joris Bontje <jbontje@suespammers.org>
This module stores bank account information. Player accounts are stored in This module stores bank account information.
the player file using the 'balance' key. Other accounts (for guilds) are
stored in the original bank file using the 'shelve' library.
Since the original implementation stored player accounts using the 'shelve'
library as well, this module also converts old bank accounts to new ones.
""" """
import os.path import os.path
@ -16,10 +11,15 @@ import Crossfire
class CFBank: class CFBank:
def __init__(self, bankfile): def __init__(self, bankfile):
self.bankdb_file = os.path.join(Crossfire.LocalDirectory(), self.bankdb_file = os.path.join(Crossfire.LocalDirectory(), bankfile)
bankfile)
self.bankdb = shelve.open(self.bankdb_file) self.bankdb = shelve.open(self.bankdb_file)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def deposit(self, user, amount): def deposit(self, user, amount):
if not user in self.bankdb: if not user in self.bankdb:
self.bankdb[user] = amount self.bankdb[user] = amount
@ -29,13 +29,14 @@ class CFBank:
def withdraw(self, user, amount): def withdraw(self, user, amount):
if user in self.bankdb: if user in self.bankdb:
if self.bankdb[user] >= amount: balance = self.getbalance(user)
balance = self.bankdb[user] if balance >= amount:
self.bankdb[user] = balance - amount self.bankdb[user] = balance - amount
return 1 return 1
return 0 return 0
def getbalance(self, user): def getbalance(self, user):
self._convert(user)
if user in self.bankdb: if user in self.bankdb:
return self.bankdb[user] return self.bankdb[user]
else: else:
@ -53,43 +54,26 @@ class CFBank:
def close(self): def close(self):
self.bankdb.close() self.bankdb.close()
def _convert(self, name):
def convert_bank(player): """Move a player's balance from the player file to the bank."""
"""Move a player's balance from the bank file to the player file.""" player = Crossfire.FindPlayer(name)
bank = CFBank('ImperialBank_DB') if player is None:
old_balance = bank.getbalance(player.Name) return 0
old_balance = _balance_legacy(player)
if old_balance > 0: if old_balance > 0:
Crossfire.Log(Crossfire.LogInfo, Crossfire.Log(Crossfire.LogInfo,
"Converting bank account for %s with %d silver" \ "Converting bank account for %s with %d silver" \
% (player.Name, old_balance)) % (name, old_balance))
player.WriteKey("balance", str(old_balance), 1) self.deposit(name, old_balance)
bank.remove_account(player.Name) player.WriteKey("balance", "moved-to-bank-file", 1)
bank.close()
return old_balance
def balance(player): def open():
return CFBank('ImperialBank_DB')
def _balance_legacy(player):
"""Return the balance of the given player's bank account.""" """Return the balance of the given player's bank account."""
try: try:
balance_str = player.ReadKey("balance") balance_str = player.ReadKey("balance")
return int(balance_str) return int(balance_str)
except ValueError: except ValueError:
# If 'balance' key does not exist, try to convert from bank file. return 0
return convert_bank(player)
def deposit(player, amount):
"""Deposit the given amount to the player's bank account."""
if amount < 0:
raise ValueError("Deposits must be positive")
new_balance = balance(player) + int(amount)
player.WriteKey("balance", str(new_balance), 1)
def withdraw(player, amount):
"""Withdraw the given amount from the player's bank account."""
if amount < 0:
raise ValueError("Withdrawals must be positive")
new_balance = balance(player) - int(amount)
if new_balance < 0:
return False
else:
player.WriteKey("balance", str(new_balance), 1)
return True

View File

@ -11,8 +11,6 @@ import Crossfire
import CFBank import CFBank
import CFItemBroker import CFItemBroker
bank = CFBank.CFBank('ImperialBank_DB')
activator = Crossfire.WhoIsActivator() activator = Crossfire.WhoIsActivator()
whoami = Crossfire.WhoAmI() whoami = Crossfire.WhoAmI()
x = activator.X x = activator.X
@ -82,7 +80,8 @@ def get_inventory(obj):
def do_deposit(player, amount): def do_deposit(player, amount):
"""Deposit the given amount for the player.""" """Deposit the given amount for the player."""
CFBank.deposit(player, amount) with CFBank.open() as bank:
bank.deposit(player.Name, amount)
whoami.Say("%s credited to your account." \ whoami.Say("%s credited to your account." \
% Crossfire.CostStringFromValue(amount)) % Crossfire.CostStringFromValue(amount))
@ -105,7 +104,9 @@ def cmd_help():
def cmd_balance(argv): def cmd_balance(argv):
"""Find out how much money the player has in his/her account.""" """Find out how much money the player has in his/her account."""
balance = CFBank.balance(activator) balance = 0
with CFBank.open() as bank:
balance = bank.getbalance(activator.Name)
if len(argv) >= 2: if len(argv) >= 2:
# Give balance using the desired coin type. # Give balance using the desired coin type.
coinName = getCoinNameFromArgs(argv[1:]) coinName = getCoinNameFromArgs(argv[1:])
@ -159,7 +160,8 @@ def cmd_withdraw(argv):
return return
# Make sure the player has sufficient funds. # Make sure the player has sufficient funds.
if CFBank.withdraw(activator, amount * exchange_rate): with CFBank.open() as bank:
if bank.withdraw(activator.Name, amount * exchange_rate):
message = "%d %s withdrawn from your account. %s" \ message = "%d %s withdrawn from your account. %s" \
% (amount, coinName, random.choice(thanks_message)) % (amount, coinName, random.choice(thanks_message))
@ -201,6 +203,3 @@ else:
main_employee() main_employee()
except ValueError: except ValueError:
whoami.Say("I don't know how much money that is.") whoami.Say("I don't know how much money that is.")
# Close bank database (required) and return.
bank.close()

View File

@ -29,5 +29,5 @@ name = activator.Name
#If you add a new bank database add an entry here to remove their account #If you add a new bank database add an entry here to remove their account
#when the player quits #when the player quits
bank = CFBank.CFBank('ImperialBank_DB') with CFBank.open() as bank:
bank.remove_account(name) bank.remove_account(name)