-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
270 lines (207 loc) · 8.67 KB
/
main.py
File metadata and controls
270 lines (207 loc) · 8.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
import csv
from package import Package
from hash_table import ChainingHashTable
from truck import Truck
import datetime
# creating the hash table instance
package_hash_table = ChainingHashTable()
# load packages from csv into hash table
def load_packages(file_name, hash_table):
with open(file_name, 'r') as file:
reader = csv.reader(file)
next(reader)
for row in reader:
package_id = int(row[0])
address = row[1]
city = row[2]
state = row[3]
zip_code = row[4]
deadline = row[5]
weight = row[6]
notes = row[7] if len(row) > 7 else ""
package = Package(package_id, address, city, state, zip_code, deadline, weight, notes)
hash_table.insert(package_id, package)
# load the packages
load_packages("packages.csv", package_hash_table)
# look up a package by id and print its details
def lookup_package(package_id):
package = package_hash_table.search(package_id)
if package:
print(package)
else:
print(f"Package with ID {package_id} not found")
# load address data from csv into the dictionary
address_dict = {}
with open("addresses.csv", encoding="utf-8-sig") as file:
reader = csv.reader(file)
for row in reader:
index = int(row[0])
address = row[2].strip()
address_dict[address] = index
# load distances into a distance matrix
distance_data = []
with open("distances.csv", encoding="utf-8-sig") as file:
reader = csv.reader(file)
for row in reader:
distance_row = [float(value) if value != '' else 0.0 for value in row]
distance_data.append(distance_row)
1
# function to get distance between the two addresses
def get_distance(index1, index2):
if index1 > index2:
return distance_data[index1][index2]
else:
return distance_data[index2][index1]
# manually loading the trucks
truck1 = Truck(
speed=18,
start_location="4001 South 700 East",
departure_time=datetime.timedelta(hours=8, minutes=0),
packages=[15, 20, 13, 14, 1, 29, 30, 31, 34, 37, 40, 16, 19]
)
truck1.truck_id = 1
truck2 = Truck(
speed=18,
start_location="4001 South 700 East",
departure_time=datetime.timedelta(hours=9, minutes=5),
packages=[3, 6, 18, 25, 26, 28, 32, 33, 35, 36, 38, 39, 27]
)
truck2.truck_id = 2
truck3 = Truck(
speed=18,
start_location="4001 South 700 East",
departure_time=datetime.timedelta(hours=10, minutes=25),
packages=[2, 4, 5, 7, 8, 9, 10, 11, 12, 17, 21, 22, 23, 24]
)
truck3.truck_id = 3
# update package status, delivery time and truck mileage
def deliver_packages(truck, package_table, address_dict, distance_data):
# set the truck's starting location and departure time
current_location = truck.start_location
current_index = address_dict[current_location]
truck_time = truck.departure_time
delivered = []
packages_to_deliver = list(truck.packages)
while packages_to_deliver:
# address correction for package 9
if truck_time >= datetime.timedelta(hours=10, minutes=20):
package_9 = package_table.search(9)
if package_9 and package_9.address != "410 S State St":
package_9.address = "410 S State St"
nearest_package = None
nearest_distance = float('inf')
nearest_index = None
# loop through packages on the truck and find the nearest one
for package_id in packages_to_deliver:
package = package_table.search(package_id)
destination_index = address_dict[package.address]
distance = get_distance(current_index, destination_index)
if distance < nearest_distance:
nearest_distance = distance
nearest_package = package
nearest_index = destination_index
# skip package #9 if its before 10:20 am (because of wrong address)
if nearest_package.id == 9 and truck_time < datetime.timedelta(hours=10, minutes=20):
packages_to_deliver.remove(nearest_package.id)
packages_to_deliver.append(nearest_package.id)
continue
# update the trucks mileage and time after delivery
truck.miles += nearest_distance
travel_time = datetime.timedelta(hours=nearest_distance / truck.speed)
truck_time += travel_time
# update the delivered packages information
nearest_package.status = "Delivered"
nearest_package.time_delivered = truck_time
nearest_package.truck_id = truck.truck_id
# prepare for next delivery
delivered.append(nearest_package.id)
packages_to_deliver.remove(nearest_package.id)
current_index = nearest_index
current_location = nearest_package.address
# once all deliveries are complete, return truck to hub
return_to_hub = get_distance(current_index, address_dict[truck.start_location])
truck.miles += return_to_hub
# running the delivery simulation
deliver_packages(truck1, package_hash_table, address_dict, distance_data)
deliver_packages(truck3, package_hash_table, address_dict, distance_data)
deliver_packages(truck2, package_hash_table, address_dict, distance_data)
# print the total miles of all the trucks
total_miles = truck1.miles + truck2.miles + truck3.miles
print(f"\nTotal miles of all trucks: {total_miles: .2f}")
print(f"Truck 1 mileage: {truck1.miles:.2f}")
print(f"Truck 2 mileage: {truck2.miles:.2f}")
print(f"Truck 3 mileage: {truck3.miles:.2f}")
# convert user input (HH:MM) to timedelta
def parse_time(time_str):
try:
hour, minute = map(int, time_str.split(':'))
return datetime.timedelta(hours=hour, minutes=minute)
except ValueError:
print("Invalid time format. Use HH:MM (e.g., 9:30).")
return None
# show all packages at a specific time
def print_package_statuses_at(time_to_check):
for package_id in range(1, 41):
package = package_hash_table.search(package_id)
# fixing the address for package no 9 only after 10:20am
if package.id == 9:
if time_to_check >= datetime.timedelta(hours=10, minutes=20):
package.address = "410 S State St"
else:
package.address = "300 State St" # wrong address until 10:20
if package.time_delivered is not None:
if time_to_check >= package.time_delivered:
package.status = "Delivered"
elif time_to_check >= truck1.departure_time and package_id in truck1.packages:
package.status = "En Route"
elif time_to_check >= truck2.departure_time and package_id in truck2.packages:
package.status = "En Route"
elif time_to_check >= truck3.departure_time and package_id in truck3.packages:
package.status = "En Route"
else:
package.status = "At Hub"
print(package)
# show all packages and total mileage for all trucks.
def print_all_deliveries_and_mileage():
for truck in [truck1, truck2, truck3]:
# time, package id for each package on this truck
truck_deliveries = []
for package_id in truck.packages:
package = package_hash_table.search(package_id)
if package and package.time_delivered:
truck_deliveries.append((package.time_delivered, package.id))
truck_deliveries.sort()
# print each delivery
for time_delivered, package_id in truck_deliveries:
print(f"Truck {truck.truck_id} delivered package {package_id} at {time_delivered}")
print("\nPackage Parcel Delivery Service")
print(f"Route completed in: {total_miles:.1f} miles")
print(f"Truck 1 miles: {truck1.miles:.1f}")
print(f"Truck 2 miles: {truck2.miles:.1f}")
print(f"Truck 3 miles: {truck3.miles:.1f}")
# system for package id
while True:
print("\nPackage Delivery System")
print("1. View all package statuses at a specific time")
print("2. Look up a package by ID")
print("3. View all deliveries and mileage summary")
print("4. Exit")
choice = input("Enter your selection (1-4): ")
if choice == "1":
time_input = input("Enter time (HH:MM): ")
parsed_time = parse_time(time_input)
if parsed_time:
print_package_statuses_at(parsed_time)
elif choice == "2":
try:
package_id = int(input("Enter the package ID (1-40): "))
lookup_package(package_id)
except ValueError:
print("Please enter a valid package ID number.")
elif choice == "3":
print_all_deliveries_and_mileage()
elif choice == "4":
print("Exiting program.")
break
else:
print("Invalid option. Please enter 1–4.")