refactor Points class + tests
continuous-integration/drone/push Build is passing

This commit is contained in:
2022-12-11 16:19:05 +01:00
parent c4ba63b83b
commit 25e38b6b5f
2 changed files with 193 additions and 42 deletions
+56 -41
View File
@@ -18,6 +18,9 @@ class Points(commands.Cog):
self.BANK_ID = 42 self.BANK_ID = 42
self.init() self.init()
self.pointsCount = {}
self.reloadPointsCount()
def __check(self, ctx): def __check(self, ctx):
return True return True
@@ -31,6 +34,8 @@ class Points(commands.Cog):
De eerste 10 punten zijn on the house. (Als er genoeg in de bank zit.) De eerste 10 punten zijn on the house. (Als er genoeg in de bank zit.)
""" """
self.reloadPointsCount()
if points == 0: if points == 0:
yield from ctx.channel.send("0 punten? Gul hoor.") yield from ctx.channel.send("0 punten? Gul hoor.")
return return
@@ -58,21 +63,26 @@ class Points(commands.Cog):
return return
# Execute the transaction: # Execute the transaction:
# First, try to give a away (at most 10) bankpoints self.execute_geefpunten(ctx.author.id, userObj.id, points)
areBeingGivenFromBank = min(points, self.getUsersRemainingBankPointsToGiveAwayToday(ctx.author.id))
areBeingGivenFromBank = min(areBeingGivenFromBank, self.getBankBalance()) self.savePointsCount()
if areBeingGivenFromBank > 0:
self.transferPoints(self.BANK_ID, userObj.id, areBeingGivenFromBank)
self.increaseUsersBankPointGivenAwayToday(ctx.author.id, areBeingGivenFromBank)
remainingPointsToGive = points - areBeingGivenFromBank
else:
remainingPointsToGive = points
# The remaining points come out of your own pocket
if remainingPointsToGive > 0:
self.transferPoints(ctx.author.id, userObj.id, remainingPointsToGive)
message = self.getMessageForAwardingPoints(ctx.author.name, userObj.name, points) message = self.getMessageForAwardingPoints(ctx.author.name, userObj.name, points)
yield from ctx.channel.send(message) yield from ctx.channel.send(message)
def execute_geefpunten(self, giverId, recieverId, points):
# First, try to give away (at most 10) bankpoints
areBeingGivenFromBank = min(points, self.getUsersRemainingBankPointsToGiveAwayToday(giverId))
areBeingGivenFromBank = min(areBeingGivenFromBank, self.getBankBalance())
if areBeingGivenFromBank > 0:
self.transferPoints(self.BANK_ID, recieverId, areBeingGivenFromBank)
self.increaseUsersBankPointGivenAwayToday(giverId, areBeingGivenFromBank)
remainingPointsToGive = points - areBeingGivenFromBank
else:
remainingPointsToGive = points
# The remaining points come out of your own pocket
if remainingPointsToGive > 0:
self.transferPoints(giverId, recieverId, remainingPointsToGive)
@commands.command(pass_context=True, hidden=False) @commands.command(pass_context=True, hidden=False)
@@ -85,6 +95,8 @@ class Points(commands.Cog):
Let op: je moet iemand taggen om punten weg te nemen. Let op: je moet iemand taggen om punten weg te nemen.
""" """
self.reloadPointsCount()
if points < 1: if points < 1:
yield from ctx.channel.send("Volgens mij snap je het niet.") yield from ctx.channel.send("Volgens mij snap je het niet.")
return return
@@ -110,11 +122,16 @@ class Points(commands.Cog):
return return
# Execute the transaction: # Execute the transaction:
self.increaseUsersPointTakenOnDate(ctx.author.id, points) self.execute_neempunten(ctx.author.id, userObj.id, points);
self.transferPoints(userObj.id, self.BANK_ID, points)
self.savePointsCount()
message = self.getMessageForTakingPoints(userObj.name, ctx.author.name, points) message = self.getMessageForTakingPoints(userObj.name, ctx.author.name, points)
yield from ctx.channel.send(message) yield from ctx.channel.send(message)
def execute_neempunten(self, takerId, victimId, points):
self.increaseUsersPointTakenOnDate(takerId, points)
self.transferPoints(victimId, self.BANK_ID, points)
@commands.command(pass_context=True, hidden=False) @commands.command(pass_context=True, hidden=False)
@@ -123,14 +140,14 @@ class Points(commands.Cog):
"""Hoeveel punten heeft iedereen? """Hoeveel punten heeft iedereen?
""" """
self.reloadPointsCount()
message = "**De puntentelling:** \n```" message = "**De puntentelling:** \n```"
pointsCount = np.load('pointscount.npy', allow_pickle=True).item() pointsCountSorted = sorted(self.pointsCount.items(), key=lambda i: i[1]['points'], reverse=True)
pointsCountSorted = sorted(pointsCount.items(), key=lambda i: i[1]['points'], reverse=True)
for user in pointsCountSorted: for user in pointsCountSorted:
if user[0] != self.BANK_ID: if user[0] != self.BANK_ID:
message += str(user[1]["points"]).rjust(4) + " " + user[1]["name"] + "\n" message += str(user[1]["points"]).rjust(4) + " " + user[1]["name"] + "\n"
message += str(pointsCount[self.BANK_ID]["points"]).rjust(4) + " " + pointsCount[self.BANK_ID]["name"] + "```" message += str(self.pointsCount[self.BANK_ID]["points"]).rjust(4) + " " + self.pointsCount[self.BANK_ID]["name"] + "```"
#message += "```"
yield from ctx.channel.send(message) yield from ctx.channel.send(message)
@@ -146,40 +163,42 @@ class Points(commands.Cog):
except: except:
print("No permission to send DM") print("No permission to send DM")
# Get the points count object from the file
def reloadPointsCount(self):
self.pointsCount = np.load('pointscount.npy', allow_pickle=True).item()
# Save the points count to the file
def savePointsCount(self):
np.save("pointscount.npy", self.pointsCount)
# Transfer points form one user to another # Transfer points form one user to another
def transferPoints(self, fromUserId, toUserId, points): def transferPoints(self, fromUserId, toUserId, points):
pointsCount = np.load('pointscount.npy', allow_pickle=True).item() self.pointsCount[fromUserId]["points"] -= points
pointsCount[fromUserId]["points"] -= points self.pointsCount[toUserId]["points"] += points
pointsCount[toUserId]["points"] += points
np.save("pointscount.npy", pointsCount)
# Do we know this user? # Do we know this user?
def isUserOnList(self, user): def isUserOnList(self, user):
pointsCount = np.load('pointscount.npy', allow_pickle=True).item() return user.id in self.pointsCount.keys()
return user.id in pointsCount.keys()
# Get a user's point balance # Get a user's point balance
def getUserBalance(self, user): def getUserBalance(self, user):
pointsCount = np.load('pointscount.npy', allow_pickle=True).item() return self.pointsCount[user.id]["points"]
return pointsCount[user.id]["points"]
# Get the balance of the bank # Get the balance of the bank
def getBankBalance(self): def getBankBalance(self):
pointsCount = np.load('pointscount.npy', allow_pickle=True).item() return self.pointsCount[self.BANK_ID]["points"]
return pointsCount[self.BANK_ID]["points"]
# To keep track if a user used some points today, we look at when the last time was he/she used them # To keep track if a user used some points today, we look at when the last time was he/she used them
# If this was in the past: reset # If this was in the past: reset
# Also, return the updated object. Why not. # Also, return the updated object. Why not.
def refreshDateVarsAndReturnUserVars(self, userId): def refreshDateVarsAndReturnUserVars(self, userId):
pointsCount = np.load('pointscount.npy', allow_pickle=True).item()
currentDateStr = datetime.now().strftime("%Y%m%d") currentDateStr = datetime.now().strftime("%Y%m%d")
if pointsCount[userId]["theDate"] != currentDateStr: if self.pointsCount[userId]["theDate"] != currentDateStr:
pointsCount[userId]["theDate"] = currentDateStr self.pointsCount[userId]["theDate"] = currentDateStr
pointsCount[userId]["pointTakenOnDate"] = 0 self.pointsCount[userId]["pointTakenOnDate"] = 0
pointsCount[userId]["bankPointsGivenOnDate"] = 0 self.pointsCount[userId]["bankPointsGivenOnDate"] = 0
np.save("pointscount.npy", pointsCount) return self.pointsCount[userId]
return pointsCount[userId]
# How many points can this user still take away today? # How many points can this user still take away today?
def getUsersRemainingPointsToTakeToday(self, userId): def getUsersRemainingPointsToTakeToday(self, userId):
@@ -194,16 +213,12 @@ class Points(commands.Cog):
# Increase the number of points this user has taken away today. # Increase the number of points this user has taken away today.
# Warning: assumes you executed refreshDateVarsAndReturnUserVars() # Warning: assumes you executed refreshDateVarsAndReturnUserVars()
def increaseUsersPointTakenOnDate(self, userId, points): def increaseUsersPointTakenOnDate(self, userId, points):
pointsCount = np.load('pointscount.npy', allow_pickle=True).item() self.pointsCount[userId]["pointTakenOnDate"] += points
pointsCount[userId]["pointTakenOnDate"] += points
np.save("pointscount.npy", pointsCount)
# Increase the number of bank points this user has given today # Increase the number of bank points this user has given today
# Warning: assumes you executed refreshDateVarsAndReturnUserVars() # Warning: assumes you executed refreshDateVarsAndReturnUserVars()
def increaseUsersBankPointGivenAwayToday(self, userId, points): def increaseUsersBankPointGivenAwayToday(self, userId, points):
pointsCount = np.load('pointscount.npy', allow_pickle=True).item() self.pointsCount[userId]["bankPointsGivenOnDate"] += points
pointsCount[userId]["bankPointsGivenOnDate"] += points
np.save("pointscount.npy", pointsCount)
# Generate a semi-random text to tell somebody they got some shiny new points # Generate a semi-random text to tell somebody they got some shiny new points
+137 -1
View File
@@ -8,6 +8,11 @@ from discord.ext import commands
import Points import Points
class User:
def __init__(self, id, name):
self.id = id
self.name = name
class TestPoints(unittest.TestCase): class TestPoints(unittest.TestCase):
def setUp(self): def setUp(self):
dotenv.load_dotenv() dotenv.load_dotenv()
@@ -16,6 +21,137 @@ class TestPoints(unittest.TestCase):
intents.members = True intents.members = True
bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents) bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'), description='Stroopwafel. Shitpost bot extraordinaire.', pm_help=True, intents=intents)
self.cog = Points.Points(bot) self.cog = Points.Points(bot)
self.user1 = User(10001, "Alice")
self.user2 = User(10002, "Bob")
def test_getUserBalance(self): def test_getUserBalance(self):
self.assertEqual(2, 1+1) self.cog.pointsCount = {}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 69}
self.assertEqual(69, self.cog.getUserBalance(self.user1))
def test_getBankBalance(self):
self.cog.pointsCount = {}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 1}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 999}
self.assertEqual(999, self.cog.getBankBalance())
def test_isUserOnList(self):
self.cog.pointsCount = {}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 1}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 999}
self.assertTrue(self.cog.isUserOnList(self.user1))
self.assertFalse(self.cog.isUserOnList(self.user2))
def test_transferPoints(self):
self.cog.pointsCount = {}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 50}
self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 30}
self.cog.transferPoints(self.user1.id, self.user2.id, 4)
self.assertEqual(46, self.cog.getUserBalance(self.user1))
self.assertEqual(34, self.cog.getUserBalance(self.user2))
def test_given_bankHasBalanceAndUserHasNotGivenPointsYetToday_when_givingPoints_then_tenPointComeFromBank(self):
self.cog.pointsCount = {}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.execute_geefpunten(self.user1.id, self.user2.id, 12)
self.assertEqual(990, self.cog.getBankBalance())
self.assertEqual(198, self.cog.getUserBalance(self.user1))
self.assertEqual(112, self.cog.getUserBalance(self.user2))
def test_given_bankHasBalanceButUserHasNoBalanceAndUserHasNotGivenPointsYetToday_when_givingPoints_then_pointComeFromBank(self):
currentDateStr = datetime.now().strftime("%Y%m%d")
self.cog.pointsCount = {}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 0, "pointTakenOnDate":10, "bankPointsGivenOnDate":0, "theDate":currentDateStr}
self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":10, "bankPointsGivenOnDate":10, "theDate":currentDateStr}
self.cog.execute_geefpunten(self.user1.id, self.user2.id, 5)
self.assertEqual(995, self.cog.getBankBalance())
self.assertEqual(0, self.cog.getUserBalance(self.user1))
self.assertEqual(105, self.cog.getUserBalance(self.user2))
def test_given_bankIsEmpty_when_givingPoints_then_AllPointsComeFromUser(self):
self.cog.pointsCount = {}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 0}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.execute_geefpunten(self.user1.id, self.user2.id, 15)
self.assertEqual(0, self.cog.getBankBalance())
self.assertEqual(185, self.cog.getUserBalance(self.user1))
self.assertEqual(115, self.cog.getUserBalance(self.user2))
def test_given_userHasAlreadyGivenSomeBankPointsToday_when_givingPoints_then_NotAllPointsComeFromBank(self):
currentDateStr = datetime.now().strftime("%Y%m%d")
self.cog.pointsCount = {}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":currentDateStr}
self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
# First a normal transaction:
self.cog.execute_geefpunten(self.user1.id, self.user2.id, 5)
self.assertEqual(995, self.cog.getBankBalance())
self.assertEqual(200, self.cog.getUserBalance(self.user1))
self.assertEqual(105, self.cog.getUserBalance(self.user2))
# Then another one:
self.cog.execute_geefpunten(self.user1.id, self.user2.id, 8)
self.assertEqual(990, self.cog.getBankBalance()) # Only the first 5 come from the bank
self.assertEqual(197, self.cog.getUserBalance(self.user1))
self.assertEqual(113, self.cog.getUserBalance(self.user2))
# One more:
self.cog.execute_geefpunten(self.user1.id, self.user2.id, 3)
self.assertEqual(990, self.cog.getBankBalance()) # All points come out of the user's pocket now
self.assertEqual(194, self.cog.getUserBalance(self.user1))
self.assertEqual(116, self.cog.getUserBalance(self.user2))
def test_given_usersWithPoints_when_takingPoints_then_pointsGoToTheBank(self):
self.cog.pointsCount = {}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.refreshDateVarsAndReturnUserVars(self.user1.id) #usually happens in !neempunten, so this unittest is a bit poor
self.cog.execute_neempunten(self.user1.id, self.user2.id, 2)
self.assertEqual(1002, self.cog.getBankBalance())
self.assertEqual(200, self.cog.getUserBalance(self.user1))
self.assertEqual(98, self.cog.getUserBalance(self.user2))
# The user should only have 8 points left to give away today:
self.assertEqual(8, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id))
def test_given_user_when_takingPoints_then_pointsToTakeAreLimited(self):
self.cog.pointsCount = {}
self.cog.pointsCount[self.cog.BANK_ID] = {"name": "DE BANK", "points": 1000}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 200, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.pointsCount[self.user2.id] = {"name": self.user2.name, "points": 100, "pointTakenOnDate":0, "bankPointsGivenOnDate":0, "theDate":"20220101"}
self.cog.refreshDateVarsAndReturnUserVars(self.user1.id) #usually happens in !neempunten, so this unittest is a bit poor
self.cog.execute_neempunten(self.user1.id, self.user2.id, 6)
self.assertEqual(94, self.cog.getUserBalance(self.user2))
# The user should only have 4 points left to give away today:
self.assertEqual(4, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id))
self.cog.execute_neempunten(self.user1.id, self.user2.id, 3)
self.assertEqual(91, self.cog.getUserBalance(self.user2))
# The user should only have 1 point left to give away today:
self.assertEqual(1, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id))
self.cog.execute_neempunten(self.user1.id, self.user2.id, 1)
self.assertEqual(90, self.cog.getUserBalance(self.user2))
# The user should have 0 points left to take away:
self.assertEqual(0, self.cog.getUsersRemainingPointsToTakeToday(self.user1.id))
# The actual check whether or not a user can keep on taking points away happens in !neempunten and is not tested here
def test_refreshDateVarsAndReturnUserVars(self):
with self.subTest("Should not be updated yet. Update was just today."):
currentDateStr = datetime.now().strftime("%Y%m%d")
self.cog.pointsCount = {}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 100, "pointTakenOnDate":2, "bankPointsGivenOnDate":1, "theDate":currentDateStr}
self.cog.refreshDateVarsAndReturnUserVars(self.user1.id)
# Still today. Values should stay the same:
self.assertEqual(2, self.cog.pointsCount[self.user1.id]["pointTakenOnDate"])
self.assertEqual(1, self.cog.pointsCount[self.user1.id]["bankPointsGivenOnDate"])
with self.subTest("Should be reset. Update was in the past."):
currentDateStr = datetime.now().strftime("%Y%m%d")
self.cog.pointsCount = {}
self.cog.pointsCount[self.user1.id] = {"name": self.user1.name, "points": 100, "pointTakenOnDate":2, "bankPointsGivenOnDate":1, "theDate":"20150101"}
self.cog.refreshDateVarsAndReturnUserVars(self.user1.id)
# A new day. Values should be set to 0 again:
self.assertEqual(0, self.cog.pointsCount[self.user1.id]["pointTakenOnDate"])
self.assertEqual(0, self.cog.pointsCount[self.user1.id]["bankPointsGivenOnDate"])
self.assertNotEqual("20150101", self.cog.pointsCount[self.user1.id]["theDate"])