aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fl.fischer@fau.de>2019-06-09 16:14:46 +0200
committerFlorian Fischer <florian.fl.fischer@fau.de>2019-06-09 16:14:46 +0200
commitecac9d9c0714c7ec3a63d67e077af15cacd3f02b (patch)
tree4158f873bf82de289109c0d56bb022569bcb75a4
parenta32b04a623d13badac51ffeca9cc991033fc8001 (diff)
downloadgeldschieberbot-ecac9d9c0714c7ec3a63d67e077af15cacd3f02b.tar.gz
geldschieberbot-ecac9d9c0714c7ec3a63d67e077af15cacd3f02b.zip
add new car commands and make tanken aware of cars
Cars are names associated to a service charge. They are stored in the state file in a dict called "cars". Each car has its own balance from which money can be pulled or pushed. Because of this cars and users can't share a name. Service charges are calculated per drive and split among all drivers similar to fuel cost. If a driver is not known by geldschieberbot the recipient of the "tanken" cmd is held accountable and has to collect the service charge manually just like fuel cost. NOTE: This change breaks geldschieberbot if the state file does not contain the field "cars" !!! You have to add it manually !!!
-rw-r--r--geldschieberbot.py117
-rw-r--r--tanken.py19
2 files changed, 120 insertions, 16 deletions
diff --git a/geldschieberbot.py b/geldschieberbot.py
index dc03d93..fe1f210 100644
--- a/geldschieberbot.py
+++ b/geldschieberbot.py
@@ -17,12 +17,14 @@ else:
"""Dict containing the whole state of geldschieberbot
balance - dict of dicts associating two persons to an amount
name2num, num2name - dicts associating numbers to names and vice versa
+ cars - dict associating car names to their service charge
scheduled_cmds - dict associating names to cmds, their schedule, and the last execution
changes - dict associating users with their changes"""
state = {
"balance" : {},
"name2num" : {},
"num2name" : {},
+ "cars" : {},
"scheduled_cmds" : {},
"changes" : {},
}
@@ -48,6 +50,7 @@ else:
balance = state["balance"]
name2num = state["name2num"]
num2name = state["num2name"]
+available_cars = state["cars"]
scheduled_cmds = state["scheduled_cmds"]
changes = state["changes"]
@@ -146,7 +149,11 @@ gib amount recipient - give money to recipient
zieh amount donor - get money from donor
nimm amount donor - get money from donor
-tanken amount [person] [info] - calculate fuel costs and add them to the balance
+cars [cmd] - interact with the available cars
+cars [list | ls] - list available cars and their service charge
+cars <add | new> <car-name> <service-charge> - add new car
+
+tanken amount [person] [car] [info] - calculate fuel costs, service charge and add them to the person's and car's balance respectively
fuck - rewind last change
@@ -320,9 +327,67 @@ cmds["gib"] = transaction
cmds["zieh"] = transaction
cmds["nimm"] = transaction
+def cars(sender, args, msg):
+ # list cars
+ if len(args) < 2 or args[1] in ["ls", "list"]:
+ ret_msg = ""
+ header_fmt = "{} - service charge {}ct/km\n"
+ if len(args) > 2:
+ cars_to_list = args[2:]
+ else:
+ cars_to_list = available_cars
+
+ for car in cars_to_list:
+ if car in available_cars:
+ ret_msg += header_fmt.format(car, available_cars[car])
+ ret_msg += create_summary(car)
+ else:
+ ret_msg += "Error {} is no available car\n".format(car)
+
+ send(ret_msg)
+ # add car
+ elif args[1] in ["add", "new"]:
+ if len(args) < 4:
+ send('ERROR: not in form "{} {} car-name service-charge"'.format(args[0], args[1]))
+ return 1
+
+ car = args[2]
+ if car in available_cars:
+ send('ERROR: {} already registered'.format(car))
+ return 1
+
+ if car in balance:
+ send('ERROR: A user named {} already exists. Please use a different name for this car'.format(car))
+ return 1
+
+ try:
+ service_charge = to_cent(args[3])
+ except:
+ send("ERROR: service_charge must be a number")
+ return 1
+
+ if not service_charge > 0:
+ send("ERROR: service-charge must be greater than 0")
+ return 1
+
+ available_cars[car] = service_charge
+
+ # add car special user
+ # add to balance
+ nb = {}
+ for m in balance:
+ balance[m][car] = 0
+ nb[m] = 0
+ balance[car] = nb
+ send("added {} as an available car".format(car))
+
+ return 0
+
+cmds["cars"] = cars
+
def _tanken(sender, args, msg):
if len(args) < 2:
- send('ERROR: not in form "{} amount [person] [info]"'.format(args[0]))
+ send('ERROR: not in form "{} amount [person] [car] [info]"'.format(args[0]))
return 1
try:
amount = to_cent(args[1])
@@ -330,6 +395,7 @@ def _tanken(sender, args, msg):
send("ERROR: amount must be a number")
return 1
+ # find recipient
if len(args) > 2 and args[2] in name2num:
recipient = args[2]
elif sender in num2name:
@@ -338,7 +404,18 @@ def _tanken(sender, args, msg):
send("ERROR: recipient unknown")
return 1
- parts, err = tanken.tanken(msg[1:], amount)
+ # find car
+ car = None
+ if len(args) > 2 and args[2] in available_cars:
+ car = args[2]
+ elif len(args) > 3 and args[3] in available_cars:
+ car = args[3]
+
+ service_charge = 0
+ if car:
+ service_charge = available_cars[car]
+
+ parts, err = tanken.tanken(msg[1:], amount, service_charge)
if err != None:
send("ERROR: " + err)
@@ -346,20 +423,38 @@ def _tanken(sender, args, msg):
output = ""
change = [args]
- for p in parts.items():
- output += p[0] + ": {}km = {}\n".format(p[1][0], to_euro(p[1][1]))
- if p[0] != recipient:
- if p[0] in name2num:
- record(recipient, p[0], p[1][1])
- change.append([recipient, p[0], p[1][1]])
- else:
- output += p[0] + " not known. Please take care manually\n"
+ for pname, values in parts.items():
+ output += pname + ": {}km = fuel: {}, service charge: {}\n".format(values["distance"], to_euro(values["cost"]), to_euro(values["service_charge"]))
+ # record service charges
+ if pname not in name2num:
+ output += pname + " not known."
+ if car:
+ person_to_charge = pname
+ if pname not in name2num:
+ person_to_charge = recipient
+ output += " {} held accountable for service charge.".format(recipient)
+
+ record(car, person_to_charge, values["service_charge"])
+ change.append([car, person_to_charge, values["service_charge"]])
+
+ # recipient paid the fuel -> don't charge them
+ if pname == recipient:
+ continue
+
+ if pname in name2num:
+ record(recipient, pname, values["cost"])
+ change.append([recipient, pname, values["cost"]])
+ else:
+ output += " Please collect fuel cost manually\n"
if record_changes and not dry_run:
changes[num2name[sender]].append(change)
output += "New Balance:\n"
output += create_summary(recipient)
+ if car:
+ output += "\nCar "
+ output += create_summary(car)
send(output)
return 0
diff --git a/tanken.py b/tanken.py
index 2ca80bd..b7064cd 100644
--- a/tanken.py
+++ b/tanken.py
@@ -1,8 +1,9 @@
#!/bin/env python3
# cost should be given in cents
-def tanken(drives, cost):
+def tanken(drives, cost, service_charge=0):
passengers = {}
+ service_charges = {}
distance = 0.
drives = [d.split(' ') for d in drives]
@@ -18,19 +19,27 @@ def tanken(drives, cost):
# collect distances per passenger
for p in d[1:]:
if p not in passengers:
- passengers[p] = [d[0],0]
+ passengers[p] = {"distance": d[0],
+ "cost": 0,
+ "service_charge": 0}
else:
- passengers[p][0] += d[0]
+ passengers[p]["distance"] += d[0]
# calculate cost per kilometer
if distance <= 0:
return None, "Driven distance must be greater than 0!"
+
c = cost/distance
for d in drives:
- # calculate cost per drive split through passengers
+ # calculate cost per drive split among passengers
c_d = int(c * d[0] / (len(d) - 1))
for p in d[1:]:
- passengers[p][1] += c_d
+ passengers[p]["cost"] += c_d
+
+ # calculate service charge per drive split among passengers
+ sc_d = int(service_charge * d[0] / (len(d) - 1))
+ for p in d[1:]:
+ passengers[p]["service_charge"] += sc_d
return passengers, None