From 08f50826ec76442d2a010bb23fda0ce66efad99d Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Thu, 6 Nov 2025 09:50:44 +0100 Subject: export the minimize command from the geldschieberbot --- geldschieberbot.py | 25 +++++++++++++++++++++++++ test.py | 28 ++++++++++++++++++++++++++++ test/state_minimize.json | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 test/state_minimize.json 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": {} +} -- cgit v1.2.3