aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--geldschieberbot.py25
-rwxr-xr-xtest.py28
-rw-r--r--test/state_minimize.json34
3 files changed, 87 insertions, 0 deletions
diff --git a/geldschieberbot.py b/geldschieberbot.py
index 745731f..51571c0 100644
--- a/geldschieberbot.py
+++ b/geldschieberbot.py
@@ -23,6 +23,7 @@ import typing as T
from models import MessageContext, Modification, Change, GeldschieberbotJSONEncoder, Reply
from utils import to_euro, to_cent
+from minimize import minimize
class Geldschieberbot:
@@ -268,6 +269,8 @@ class Geldschieberbot:
transfer amount source destination - transfer amount of your balance from source to destination
+ minimize - minimize the total balance by moving money in cycles
+
cars [cmd] - interact with the available cars
cars [list | ls] - list available cars and their service charge
cars add car-name service-charge - add new car
@@ -515,6 +518,27 @@ class Geldschieberbot:
Change(msg.args, modifications, msg.timestamp))
return {'msg': out}
+ def minimize(self, msg: MessageContext) -> dict[str, str]:
+ """Message handler wrapping the minimize function"""
+ if not msg.sender:
+ return {'err': 'you must register first'}
+
+ cycles = minimize(self.balance)
+ if not cycles:
+ return {'msg': 'No cycles to minimize found'}
+
+ out = ''
+ for suggestion in cycles:
+ cycle, delta = suggestion
+ for i, user in enumerate(cycle):
+ other = cycle[i - 1]
+ self.balance[other][user] -= delta
+ self.balance[user][other] += delta
+ out += f'{user} -> '
+ out = f'{out[:-4]} {delta}\n'
+
+ return {'msg': f'minimize:\n{out[:-1]}'}
+
def cars(self, msg: MessageContext) -> dict[str, str]:
"""Manage available cars
@@ -1032,6 +1056,7 @@ class Geldschieberbot:
'help': self.usage,
'usage': self.usage,
'transfer': self.transfer,
+ 'minimize': self.minimize,
'cars': self.cars,
'tanken': self.tanken,
'fuck': self.fuck,
diff --git a/test.py b/test.py
index 602be6d..cd5b9bb 100755
--- a/test.py
+++ b/test.py
@@ -1437,5 +1437,33 @@ class TestStateLoadStore(unittest.TestCase):
self.assertTrue(compare_state(sp, state=bot.state))
+class TestMinimize(unittest.TestCase):
+ """Test the minimize command"""
+
+ def setUp(self):
+ reset_state("test/state_minimize.json")
+
+ def test_minimize(self):
+ res = run_bot(self, num[alice], "!minimize")
+ # The found cycle is not deterministic yet
+ # exp = "minimize:\nbob -> charlie -> alice 10"
+ # self.assertEqual( res.stdout, exp )
+ self.assertTrue("alice" in res.stdout)
+ self.assertTrue("bob" in res.stdout)
+ self.assertTrue("charlie" in res.stdout)
+ self.assertTrue("10" in res.stdout)
+
+ res = run_bot(self, num[alice], "!full-sum")
+ o =\
+"""Summary:
+alice:
+\tAll fine :)
+bob:
+\tAll fine :)
+charlie:
+\tAll fine :)"""
+ self.assertEqual(res.stdout, o)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/test/state_minimize.json b/test/state_minimize.json
new file mode 100644
index 0000000..1828a94
--- /dev/null
+++ b/test/state_minimize.json
@@ -0,0 +1,34 @@
+{
+ "balance": {
+ "alice": {
+ "bob": 10,
+ "charlie": -10
+ },
+ "bob": {
+ "alice": -10,
+ "charlie": 10
+ },
+ "charlie": {
+ "alice": 10,
+ "bob": -10
+ }
+ },
+ "name2num": {
+ "alice": "+49123456",
+ "bob": "+49654321",
+ "charlie": "+49615243"
+ },
+ "num2name": {
+ "+49123456": "alice",
+ "+49654321": "bob",
+ "+49615243": "charlie"
+ },
+ "available_cars": {},
+ "scheduled_cmds": {},
+ "changes": {
+ "alice": [],
+ "bob": [],
+ "charlie": []
+ },
+ "aliases": {}
+}