forked from leenlab2/trip-planner-paris
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathschedule.py
119 lines (92 loc) · 4.21 KB
/
schedule.py
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
"""This module builds the schedule for the trip
This file is Copyright (c) 2021 Leen Al Lababidi, Michael Rubenstein, Maria Becerra and Nada Eldin
"""
from __future__ import annotations
from typing import Optional
from datetime import datetime
from location import Location, Landmark, Restaurant, SubwayStation
class TimeBlock:
"""A class that holds start_time, end_time and location_visited. Schedule is represented by a
a list of TimeBlock objects
Instance Attributes:
- start_time: An attribute representing when the user leaves the hotel
- end_time: An attribute representing when the user returns to the hotel
- location_visited: An attribute representing the place visited during that timeblock
Representation Invariants:
- 1 < self.start_time.month < 12
"""
start_time: datetime
end_time: datetime
location_visited: Restaurant or Landmark or SubwayStation
def __init__(self, start: datetime, loc: Restaurant or Landmark or SubwayStation,
end: Optional[datetime] = None) -> None:
"""Initialize a new TimeBlock object"""
self.start_time = start
self.location_visited = loc
if end is not None:
self.end_time = end
else:
self.end_time = start + loc.time_spent
def build_schedule(path: list[Location or Restaurant or Landmark or SubwayStation],
start: datetime, end: datetime) -> list[TimeBlock]:
"""Return a schedule in the form of a list of TimeBlock objects based on the path.
Preconditions:
- the only hotel in path is at the start/end
"""
locations_to_visit = path[1:-1] # remove the hotel from path
schedule = []
print('Building Schedule....')
for location in locations_to_visit:
new_time_block = TimeBlock(start, location)
start += location.time_spent
schedule.append(new_time_block)
# if we overflow beyond the planned time
altered = set()
i = 0
while schedule[-1].end_time > end:
print('Fixing Schedule....')
schedule, altered = fix_schedule(schedule, altered)
print(schedule[-1].end_time)
i += 1
return schedule
def fix_schedule(schedule: list[TimeBlock], altered: set) -> tuple[list[TimeBlock], set]:
""""Return a fixed copy of the schedule accounting for if we cross the inputted return time.
This is done by reducing time spent at the lowest rated location.
"""
fixed_schedule = schedule.copy()
# find lowest rated location
lowest_index = None
for i in range(0, len(schedule)):
if schedule[i].location_visited.name not in altered and \
not isinstance(schedule[i].location_visited, SubwayStation):
if lowest_index is None:
lowest_index = i
elif schedule[i].location_visited.rating < \
schedule[lowest_index].location_visited.rating:
lowest_index = i
if lowest_index is None:
return fix_schedule(schedule, set())
# reduce time spent there by 50%
start = fixed_schedule[lowest_index].start_time
fixed_schedule[lowest_index].location_visited.time_spent = schedule[
lowest_index].location_visited.time_spent // 2
end = start + fixed_schedule[lowest_index].location_visited.time_spent
# fixed_schedule[lowest_index] = TimeBlock(start, schedule[lowest_index].location_visited, end)
fixed_schedule[lowest_index].end_time = end
altered.add(schedule[lowest_index].location_visited.name)
# shift the rest of the schedule
for j in range(lowest_index + 1, len(schedule)):
fixed_schedule[j].start_time = end
fixed_schedule[j].end_time = end + fixed_schedule[j].location_visited.time_spent
end = fixed_schedule[j].end_time
if len(altered) == len(fixed_schedule):
altered = set()
return (fixed_schedule, altered)
if __name__ == "__main__":
import python_ta
python_ta.check_all(config={
'extra-imports': ['datetime', 'location'],
'allowed-io': ['build_schedule'],
'max-line-length': 100,
'disable': ['E1136']
})