Files
Tatami/running_dinner/running_dinner.py
T

660 lines
23 KiB
Python

import copy
import datetime
import random
import os
import pandas
import requests
import xlsxwriter
from progress.bar import IncrementalBar
EXCEL_DIR = "C:/Daten/RunningDinner/running_dinner/running_dinner.xlsx"
# Set the base url for the Google Maps Distance Matrix API
base_url = "https://maps.googleapis.com/maps/api/distancematrix/json?"
# Google Maps API Key
api_key = os.environ["MAPS_API_KEY"]
# Excel Sheet muss 7 Spalten haben:
# Zeitstempel (Erzeugt von Google Forms, wird in Zeile 30 entfernt) | Name | | Zimmergröße | Handynummer | Adresse | Entfernung zu Afterparty
# Spalte mit Namen muss 'Namen' als Header haben
# Maximale Distanz von Nachspeise zu Afterparty
max_dist_to_ap = 2
rd = pandas.read_excel(EXCEL_DIR)
appendants = rd.set_index("Name").T.to_dict("list")
addresses = []
address_indices = []
for i, app in enumerate(appendants):
appendants[app].pop(0)
if "passen" in appendants[app][1]: # Zimmergröße sehr gut
appendants[app][1] = 2
elif "gehen" in appendants[app][1]: # Zimmergröße gut
appendants[app][1] = 1
else: # Zimmergröße passt nicht
appendants[app][1] = 0
if type(appendants[app][3]) == str:
adr = appendants[app][3]
addresses.append(adr)
address_indices.append(i)
names = list(appendants.keys())
# print(appendants['Fabio Rodrigues'])
ind = 0
distances = []
for _ in range(len(names)):
distances.append([float("inf")] * len(names))
for i, adr in enumerate(addresses):
addresses_wo_adr = addresses.copy()
addresses_wo_adr.pop(i)
address_indices_wo_adr = address_indices.copy()
address_indices_wo_adr.pop(i)
# Build the request parameters
params = {
"origins": [adr],
"destinations": "|".join(addresses_wo_adr),
"key": api_key,
"mode": "bicycling",
}
# Make the request to the Google Maps Distance Matrix API
response = requests.get(base_url, params=params)
# Extract the distance matrix from the response
distance_matrix = response.json()["rows"][0]["elements"]
distances[address_indices[i]][address_indices[i]] = 0.0
for j in range(len(distance_matrix)):
distances[address_indices[i]][address_indices_wo_adr[j]] = distance_matrix[j][
"duration"
]["value"]
top1_max_distance = float("inf")
top1_total_distance = float("inf")
top1_teams = {}
top1_loc = {}
top2_max_distance = float("inf")
top2_total_distance = float("inf")
top2_teams = {}
top2_loc = {}
top3_max_distance = float("inf")
top3_total_distance = float("inf")
top3_teams = {}
top3_loc = {}
top4_max_distance = float("inf")
top4_total_distance = float("inf")
top4_teams = {}
top4_loc = {}
top5_max_distance = float("inf")
top5_total_distance = float("inf")
top5_teams = {}
top5_loc = {}
iterations = 1000
bar = IncrementalBar("Searching optimal Route", max=iterations)
for _ in range(iterations):
searching = True
while searching == True:
random.shuffle(names)
teams = dict()
for i in range(len(names)):
if i % 2 == 0 and i < len(names) - (len(names) % 6):
teams["Team " + str(int(i / 2 + 1))] = {
"Namen": [names[i], names[i + 1]]
}
if i >= len(names) - (len(names) % 6):
teams["Team " + str(i - (len(names) - (len(names) % 6)) + 1)][
"Namen"
].append(names[i])
for t in teams:
teams[t]["Location"] = []
for n in teams[t]["Namen"]:
if type(appendants[n][3]) == str:
teams[t]["Location"].append(appendants[n][3])
num_teams = len(teams)
t = list(range(1, num_teams + 1))
num_groups = int(num_teams / 3)
Hauptspeisen = t[0:num_groups]
Vorspeisen = t[num_groups : num_groups * 2]
Nachspeisen = t[num_groups * 2 : num_groups * 3]
for i in Vorspeisen + Hauptspeisen + Nachspeisen:
if i in Vorspeisen:
index = Vorspeisen.index(i)
teams["Team " + str(i)]["Gang"] = "Vorspeise"
teams["Team " + str(i)]["Gäste"] = [
"Team " + str(Hauptspeisen[index]),
"Team " + str(Nachspeisen[index]),
]
teams["Team " + str(i)]["Route"] = ["Team " + str(i)]
teams["Team " + str(Hauptspeisen[index])]["Route"] = ["Team " + str(i)]
teams["Team " + str(Nachspeisen[index])]["Route"] = ["Team " + str(i)]
teams["Team " + str(i)]["Unverträglichkeiten der Gäste"] = []
for g in teams["Team " + str(i)]["Gäste"]:
for n in teams[g]["Namen"]:
teams["Team " + str(i)]["Unverträglichkeiten der Gäste"].append(
appendants[n][0]
)
elif i in Hauptspeisen:
index = Hauptspeisen.index(i)
teams["Team " + str(i)]["Gang"] = "Hauptspeise"
teams["Team " + str(i)]["Gäste"] = [
"Team " + str(Vorspeisen[(index - 1) % num_groups]),
"Team " + str(Nachspeisen[(index + 1) % num_groups]),
]
teams["Team " + str(i)]["Route"].append("Team " + str(i))
teams["Team " + str(Vorspeisen[(index - 1) % num_groups])][
"Route"
].append("Team " + str(i))
teams["Team " + str(Nachspeisen[(index + 1) % num_groups])][
"Route"
].append("Team " + str(i))
teams["Team " + str(i)]["Unverträglichkeiten der Gäste"] = []
for g in teams["Team " + str(i)]["Gäste"]:
for n in teams[g]["Namen"]:
teams["Team " + str(i)]["Unverträglichkeiten der Gäste"].append(
appendants[n][0]
)
elif i in Nachspeisen:
index = Nachspeisen.index(i)
teams["Team " + str(i)]["Gang"] = "Nachspeise"
teams["Team " + str(i)]["Gäste"] = [
"Team " + str(Vorspeisen[(index - 1) % num_groups]),
"Team " + str(Hauptspeisen[(index + 1) % num_groups]),
]
teams["Team " + str(i)]["Route"].append("Team " + str(i))
teams["Team " + str(Vorspeisen[(index - 1) % num_groups])][
"Route"
].append("Team " + str(i))
teams["Team " + str(Hauptspeisen[(index + 1) % num_groups])][
"Route"
].append("Team " + str(i))
teams["Team " + str(i)]["Unverträglichkeiten der Gäste"] = []
for g in teams["Team " + str(i)]["Gäste"]:
for n in teams[g]["Namen"]:
teams["Team " + str(i)]["Unverträglichkeiten der Gäste"].append(
appendants[n][0]
)
searching = False
for t in teams:
size = 0
for n in teams[t]["Namen"]:
size = size + appendants[n][1]
if size == 0:
# print(str(teams[t]['Namen']) + ' Raum zu klein')
searching = True
break
max_room = 0
for n in teams[t]["Namen"]:
max_room = max(max_room, appendants[n][1])
dist = 6
for n in teams[t]["Namen"]:
if appendants[n][1] == max_room:
dist = min(dist, int(appendants[n][4]))
if dist > max_dist_to_ap and teams[t]["Gang"] == "Nachspeise":
# print(str(teams[t]['Namen']) + ' Nachspeise, aber zu weit von Afterparty entfernt')
searching = True
break
# if 'Fabio Rodrigues' in teams[t]['Namen'] and len(teams[t]['Namen']) == 3:
# print('Fabio in 3er Gruppe')
# searching = True
# break
# if 'Fabio Rodrigues' in teams[t]['Namen'] and teams[t]['Gang'] != 'Nachspeise':
# print('Fabio macht nicht Nachspeise')
# searching = True
# break
# if 'Fabio Rodrigues' in teams[t]['Namen'] and 'Alex Peeters' not in teams[t]['Namen']:
# print('Fabio nicht mit Alex')
# searching = True
# break
possible_location_permutations = 1
number_locations = []
for t in teams:
n_loc = len(teams[t]["Location"])
number_locations.append(n_loc)
possible_location_permutations *= n_loc
perm = [0] * len(number_locations)
for j in range(possible_location_permutations):
if j > 0:
i = 0
adding = True
while adding:
if perm[i] + 1 < number_locations[i]:
perm[i] += 1
adding = False
elif perm[i] + 1 == number_locations[i] and perm[i] > 0:
perm[i] = 0
i += 1
loc = {}
for k, l in enumerate(teams):
loc[l] = perm[k]
max_distance = 0.0
total_distance = 0.0
for t in teams:
way1 = distances[
address_indices[
addresses.index(
teams[teams[t]["Route"][0]]["Location"][
loc[teams[t]["Route"][0]]
]
)
]
][
address_indices[
addresses.index(
teams[teams[t]["Route"][1]]["Location"][
loc[teams[t]["Route"][1]]
]
)
]
]
way2 = distances[
address_indices[
addresses.index(
teams[teams[t]["Route"][1]]["Location"][
loc[teams[t]["Route"][1]]
]
)
]
][
address_indices[
addresses.index(
teams[teams[t]["Route"][2]]["Location"][
loc[teams[t]["Route"][2]]
]
)
]
]
way3 = distances[
address_indices[
addresses.index(
teams[teams[t]["Route"][2]]["Location"][
loc[teams[t]["Route"][2]]
]
)
]
][
address_indices[
addresses.index("Sebastian-Kneipp-Straße 6, 76131 Karlsruhe")
]
]
team_distance = way1 + way2 + way3
total_distance += team_distance
max_distance = max(max_distance, way1, way2)
teams[t]["Zeit"] = str(datetime.timedelta(seconds=team_distance))
if total_distance < top1_total_distance:
top5_max_distance = top4_max_distance
top5_total_distance = top4_total_distance
top5_teams = copy.deepcopy(top4_teams)
top5_loc = copy.deepcopy(top4_loc)
top4_max_distance = top3_max_distance
top4_total_distance = top3_total_distance
top4_teams = copy.deepcopy(top3_teams)
top4_loc = copy.deepcopy(top3_loc)
top3_max_distance = top2_max_distance
top3_total_distance = top2_total_distance
top3_teams = copy.deepcopy(top2_teams)
top3_loc = copy.deepcopy(top2_loc)
top2_max_distance = top1_max_distance
top2_total_distance = top1_total_distance
top2_teams = copy.deepcopy(top1_teams)
top2_loc = copy.deepcopy(top1_loc)
top1_max_distance = max_distance
top1_total_distance = total_distance
top1_teams = copy.deepcopy(teams)
top1_loc = copy.deepcopy(loc)
elif total_distance < top2_total_distance:
top5_max_distance = top4_max_distance
top5_total_distance = top4_total_distance
top5_teams = copy.deepcopy(top4_teams)
top5_loc = copy.deepcopy(top4_loc)
top4_max_distance = top3_max_distance
top4_total_distance = top3_total_distance
top4_teams = copy.deepcopy(top3_teams)
top4_loc = copy.deepcopy(top3_loc)
top3_max_distance = top2_max_distance
top3_total_distance = top2_total_distance
top3_teams = copy.deepcopy(top2_teams)
top3_loc = copy.deepcopy(top2_loc)
top2_max_distance = max_distance
top2_total_distance = total_distance
top2_teams = copy.deepcopy(teams)
top2_loc = copy.deepcopy(loc)
elif total_distance < top3_total_distance:
top5_max_distance = top4_max_distance
top5_total_distance = top4_total_distance
top5_teams = copy.deepcopy(top4_teams)
top5_loc = copy.deepcopy(top4_loc)
top4_max_distance = top3_max_distance
top4_total_distance = top3_total_distance
top4_teams = copy.deepcopy(top3_teams)
top4_loc = copy.deepcopy(top3_loc)
top3_max_distance = max_distance
top3_total_distance = total_distance
top3_teams = copy.deepcopy(teams)
top3_loc = copy.deepcopy(loc)
elif total_distance < top4_total_distance:
top5_max_distance = top4_max_distance
top5_total_distance = top4_total_distance
top5_teams = copy.deepcopy(top4_teams)
top5_loc = copy.deepcopy(top4_loc)
top4_max_distance = max_distance
top4_total_distance = total_distance
top4_teams = copy.deepcopy(teams)
top4_loc = copy.deepcopy(loc)
elif total_distance < top5_total_distance:
top5_max_distance = max_distance
top5_total_distance = total_distance
top5_teams = copy.deepcopy(teams)
top5_loc = copy.deepcopy(loc)
bar.next()
bar.finish()
for t in top5_teams:
top5_teams[t]["Location"] = top5_teams[t]["Location"][top5_loc[t]]
for t in top4_teams:
top4_teams[t]["Location"] = top4_teams[t]["Location"][top4_loc[t]]
for t in top3_teams:
top3_teams[t]["Location"] = top3_teams[t]["Location"][top3_loc[t]]
for t in top2_teams:
top2_teams[t]["Location"] = top2_teams[t]["Location"][top2_loc[t]]
for t in top1_teams:
top1_teams[t]["Location"] = top1_teams[t]["Location"][top1_loc[t]]
print("######################################################")
print("Top 5 Team:")
print(top3_teams)
print(
"The max time of one single route is: {}".format(
str(datetime.timedelta(seconds=top5_max_distance))
)
)
print(
"The total time spent on bike is: {}".format(
str(datetime.timedelta(seconds=top5_total_distance))
)
)
print("Top 4 Team:")
print(top3_teams)
print(
"The max time of one single route is: {}".format(
str(datetime.timedelta(seconds=top4_max_distance))
)
)
print(
"The total time spent on bike is: {}".format(
str(datetime.timedelta(seconds=top4_total_distance))
)
)
print("Top 3 Team:")
print(top3_teams)
print(
"The max time of one single route is: {}".format(
str(datetime.timedelta(seconds=top3_max_distance))
)
)
print(
"The total time spent on bike is: {}".format(
str(datetime.timedelta(seconds=top3_total_distance))
)
)
print("Top 2 Team:")
print(top2_teams)
print(
"The max time of one single route is: {}".format(
str(datetime.timedelta(seconds=top2_max_distance))
)
)
print(
"The total time spent on bike is: {}".format(
str(datetime.timedelta(seconds=top2_total_distance))
)
)
print("Top 1 Team:")
print(top1_teams)
print(
"The max time of one single route is: {}".format(
str(datetime.timedelta(seconds=top1_max_distance))
)
)
print(
"The total time spent on bike is: {}".format(
str(datetime.timedelta(seconds=top1_total_distance))
)
)
print("Type 1, 2, 3, 4 or 5 to choose the teams configuration:")
inp = int(input())
if inp == 1:
print("You chose the 1st option.")
teams = copy.deepcopy(top1_teams)
elif inp == 2:
print("You chose the 2nd option.")
teams = copy.deepcopy(top2_teams)
elif inp == 3:
print("You chose the 3rd option.")
teams = copy.deepcopy(top3_teams)
elif inp == 4:
print("You chose the 4th option.")
teams = copy.deepcopy(top4_teams)
elif inp == 5:
print("You chose the 5th option.")
teams = copy.deepcopy(top5_teams)
else:
print("Input could not be resolved, choosing number 1.")
teams = copy.deepcopy(top1_teams)
for t in teams:
if "Fabio Rodrigues" in teams[t]["Namen"]:
print(t + ": " + str(teams[t]["Namen"]) + " machen " + str(teams[t]["Gang"]))
if "Arnold Resch" in teams[t]["Namen"]:
print(t + ": " + str(teams[t]["Namen"]) + " machen " + str(teams[t]["Gang"]))
print("######################################################")
# Creating xlsx file
workbook = xlsxwriter.Workbook("running_dinner_masterplan.xlsx")
bold = workbook.add_format({"bold": True})
worksheet = workbook.add_worksheet("Übersicht")
worksheet.set_column(0, 0, 20)
worksheet.set_column(1, 1, 30)
worksheet.set_column(2, 2, 20)
worksheet.set_column(3, 3, 40)
worksheet.set_column(4, 4, 80)
row = 0
col = 0
header = workbook.add_format(
{
"bold": 1,
"border": 1,
"align": "center",
"valign": "vcenter",
"fg_color": "yellow",
}
)
worksheet.merge_range("A1:E1", "Der große Running-Dinner Masterplan", header)
row += 2
worksheet.write(row, col, "Teams", bold)
worksheet.write(row, col + 1, "Namen", bold)
worksheet.write(row, col + 2, "Telefonnummer", bold)
worksheet.write(row, col + 3, "Adresse", bold)
worksheet.write(row, col + 4, "Unverträglichkeiten", bold)
row += 1
for t in teams:
worksheet.write(row, col, t, bold)
worksheet.write(row + 1, col, teams[t]["Gang"])
for name in teams[t]["Namen"]:
worksheet.write(row, col + 1, name)
worksheet.write(row, col + 2, appendants[name][2])
if type(appendants[name][3]) == str:
worksheet.write(row, col + 3, appendants[name][3])
worksheet.write(row, col + 4, appendants[name][0])
row += 1
row += 3
worksheet.merge_range("A" + str(row) + ":E" + str(row), "Die Routen", header)
row += 1
worksheet.write(row, col, "18:30 Uhr", bold)
worksheet.write(row + 6, col, "20:00 Uhr", bold)
worksheet.write(row + 12, col, "22:00 Uhr", bold)
row += 1
vor_g = 1
haupt_g = 1
nach_g = 1
for t in teams:
if teams[t]["Gang"] == "Vorspeise":
worksheet.write(row, col + vor_g - 1, "Vorspeise Gruppe " + str(vor_g), bold)
worksheet.write(row + 1, col + vor_g - 1, t, bold)
for i, g in enumerate(teams[t]["Gäste"]):
worksheet.write(row + 2 + i, col + vor_g - 1, g)
vor_g += 1
elif teams[t]["Gang"] == "Hauptspeise":
worksheet.write(
row + 6, col + haupt_g - 1, "Hauptspeise Gruppe " + str(haupt_g), bold
)
worksheet.write(row + 7, col + haupt_g - 1, t, bold)
for i, g in enumerate(teams[t]["Gäste"]):
worksheet.write(row + 8 + i, col + haupt_g - 1, g)
haupt_g += 1
elif teams[t]["Gang"] == "Nachspeise":
worksheet.write(
row + 12, col + nach_g - 1, "Nachspeise Gruppe " + str(nach_g), bold
)
worksheet.write(row + 13, col + nach_g - 1, t, bold)
for i, g in enumerate(teams[t]["Gäste"]):
worksheet.write(row + 14 + i, col + nach_g - 1, g)
nach_g += 1
for t in teams:
worksheet = workbook.add_worksheet(t)
worksheet.set_column(0, 0, 60)
worksheet.set_column(1, 1, 100)
row = 0
col = 0
worksheet.merge_range("A1:B1", t, header)
row += 2
for n in [
"Namen",
"Gang",
"Location",
"Route",
"Gäste",
"Unverträglichkeiten der Gäste",
"Zeit",
]:
if n == "Namen":
for i, name in enumerate(teams[t][n]):
if i == 0:
text = name
else:
text += " und " + name
worksheet.write(row, col, "Namen", bold)
worksheet.write(row, col + 1, text)
row += 1
elif n == "Gang":
worksheet.write(row, col, "Euer Gang", bold)
worksheet.write(row, col + 1, teams[t][n])
row += 1
elif n == "Location":
worksheet.write(row, col, "Location (automatisch optimal gewählt)", bold)
worksheet.write(row, col + 1, teams[t][n])
row += 1
elif n == "Gäste":
for i, gaeste in enumerate(teams[t][n]):
if i == 0:
text = gaeste
else:
text += " und " + gaeste
worksheet.write(row, col, "Eure Gäste", bold)
worksheet.write(row, col + 1, text)
row += 1
for i, gaeste in enumerate(teams[t][n]):
for j, namen in enumerate(teams[gaeste]["Namen"]):
if i == 0 and j == 0:
text = namen
elif (
i == len(teams[t][n]) - 1
and j == len(teams[gaeste]["Namen"]) - 1
):
text += " und " + namen
else:
text += ", " + namen
worksheet.write(row, col + 1, text)
row += 2
elif n == "Route":
for i, route in enumerate(teams[t][n]):
if i == 0:
text = "Zuerst bei " + route
else:
text += ", dann bei " + route
worksheet.write(row, col, "Eure Route", bold)
worksheet.write(row, col + 1, text)
row += 2
elif n == "Unverträglichkeiten der Gäste":
for i, unv in enumerate(teams[t][n]):
if i == 0:
text = unv
else:
text += " und " + unv
worksheet.write(row, col, "Achtet auf diese Eigenarten eurer Gäste", bold)
worksheet.write(row, col + 1, text)
row += 2
elif n == "Zeit":
worksheet.write(
row,
col,
"Gesamtzeit für eure Route von Vorspeise bis Afterparty (per Fahrrad)",
bold,
)
worksheet.write(row, col + 1, teams[t][n])
workbook.close()