diff options
| -rw-r--r-- | geldschieberbot.py | 57 | ||||
| -rw-r--r-- | tanken.py | 57 | ||||
| -rwxr-xr-x | test.py | 24 |
3 files changed, 72 insertions, 66 deletions
diff --git a/geldschieberbot.py b/geldschieberbot.py index 79cb643..969540f 100644 --- a/geldschieberbot.py +++ b/geldschieberbot.py @@ -7,8 +7,6 @@ import os import subprocess import sys -import tanken - # Path where our data is stored persistent on disk STATE_FILE = os.environ["GSB_STATE_FILE"] @@ -591,7 +589,51 @@ class Geldschieberbot: return {'err': f'unknown car subcommand "{args[1]}".'} - def _tanken(self, sender, args, msg) -> dict[str, str]: + def parse_tank_bill(self, _drives: list[str], fuel_charge: int, + service_charge: int): + """Parse and distribute the tank bill across all passangers""" + passengers: dict[str, dict[str, int]] = {} + distance = 0. + drives = [d.split(' ') for d in _drives] + + for drive in drives: + try: + drive_distance = int(drive[0]) + except (IndexError, ValueError): + return None, "Lines have to start with the driven distance!" + + # calculate overall distance + distance += drive_distance + + # collect distances per passenger + drive_passengers = self.expand_aliases(drive[1:]) + for passenger in drive_passengers: + passengers.setdefault(passenger, { + "distance": 0, + "cost": 0, + "service_charge": 0 + })["distance"] += drive_distance + + # calculate cost per kilometer + if distance <= 0: + return None, "Driven distance must be greater than 0!" + + c_km = fuel_charge / distance + + for drive in drives: + drive_distance = int(drive[0]) + drive_passengers = self.expand_aliases(drive[1:]) + # calculate cost per drive split among passengers + c_d = int(c_km * drive_distance / (len(drive_passengers))) + sc_d = int(service_charge * drive_distance / + (len(drive_passengers))) + for passenger in drive_passengers: + passengers[passenger]["cost"] += c_d + passengers[passenger]["service_charge"] += sc_d + + return passengers, None + + def tanken(self, sender, args, msg) -> dict[str, str]: """Split a tank across all passengers""" if len(args) < 2: return { @@ -617,12 +659,9 @@ class Geldschieberbot: elif len(args) > 3 and args[3] in self.available_cars: car = args[3] - service_charge = 0 - if car: - service_charge = self.available_cars[car] - - parts, err = tanken.tanken(msg[1:], amount, service_charge) + service_charge = self.available_cars.get(car, 0) + parts, err = self.parse_tank_bill(msg[1:], amount, service_charge) if err: return {'err': err} @@ -925,7 +964,7 @@ class Geldschieberbot: 'usage': self.usage, 'transfer': self.transfer, 'cars': self.cars, - 'tanken': self._tanken, + 'tanken': self.tanken, 'fuck': self.fuck, 'rewind': self.fuck, 'undo': self.fuck, diff --git a/tanken.py b/tanken.py deleted file mode 100644 index 2c65c73..0000000 --- a/tanken.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Utilities to support splitting fuel and car maintainance costs""" - -import typing as T - -PassengerResult = dict[str, int] -Results = dict[str, PassengerResult] -TankenFailure = T.Tuple[None, str] -TankenSuccess = T.Tuple[Results, None] -TankenResult = T.Union[TankenSuccess, TankenFailure] - - -# cost should be given in cents -def tanken(_drives: list[str], cost: int, service_charge=0) -> TankenResult: - """calculate costs per passange for one tank load""" - passengers = {} - distance = 0. - drives = [d.split(' ') for d in _drives] - - for drive in drives: - try: - drive_distance = int(drive[0]) - except (IndexError, ValueError): - return None, "Lines have to start with the driven distance!" - - # calculate overall distance - distance += drive_distance - - # collect distances per passenger - for passenger in drive[1:]: - if passenger not in passengers: - passengers[passenger] = { - "distance": drive_distance, - "cost": 0, - "service_charge": 0 - } - else: - passengers[passenger]["distance"] += drive_distance - - # calculate cost per kilometer - if distance <= 0: - return None, "Driven distance must be greater than 0!" - - c_km = cost / distance - - for drive in drives: - drive_distance = int(drive[0]) - # calculate cost per drive split among passengers - c_d = int(c_km * drive_distance / (len(drive) - 1)) - for passenger in drive[1:]: - passengers[passenger]["cost"] += c_d - - # calculate service charge per drive split among passengers - sc_d = int(service_charge * drive_distance / (len(drive) - 1)) - for passenger in drive[1:]: - passengers[passenger]["service_charge"] += sc_d - - return passengers, None @@ -514,6 +514,30 @@ charlie: \t<- bob 3.00 \tBalance: 6.00""") + def test_tanken_all(self): + res = run_bot(self, num[alice], "!tanken 10\n10 all") + self.assertEqual(res.stdout, \ +"""alice: 10km = fuel: 3.33, service charge: 0.00 +bob: 10km = fuel: 3.33, service charge: 0.00 +charlie: 10km = fuel: 3.33, service charge: 0.00 +New Balance: +alice: +\t<- bob 3.33 +\t<- charlie 3.33 +\tBalance: 6.66""") + + def test_tanken_alias(self): + run_bot(self, num[alice], f"!alias alob {alice} {bob}") + res = run_bot(self, num[charlie], "!tanken 8\n10 alob") + self.assertEqual(res.stdout, \ +"""alice: 10km = fuel: 4.00, service charge: 0.00 +bob: 10km = fuel: 4.00, service charge: 0.00 +New Balance: +charlie: +\t<- alice 4.00 +\t<- bob 4.00 +\tBalance: 8.00""") + class TestCarsAdd(unittest.TestCase): |
