File size: 8,810 Bytes
9be4956
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from tools.accommodations.apis import Accommodations
from tools.flights.apis import Flights
from tools.restaurants.apis import Restaurants
from tools.rank.apis import Rank
from tools.filter.apis import Filter
from tools.googleDistanceMatrix.apis import GoogleDistanceMatrix
import pandas as pd

hotel = Accommodations()
flight = Flights()
flight.load_db()
restaurant = Restaurants()
rank = Rank()
filter = Filter()
distanceMatrix = GoogleDistanceMatrix()


def estimate_budget(data, mode):
    """
    Estimate the budget based on the mode (lowest, highest, average) for flight, hotel, or restaurant data.
    """
    if mode == "lowest":
        return min(data)
    elif mode == "highest":
        return max(data)
    elif mode == "average":
        # filter the nan values
        data = [x for x in data if str(x) != 'nan']
        return sum(data) / len(data)
    

def budget_calc(org, dest, days, date:list , people_number=None, local_constraint = None):
    """
    Calculate the estimated budget for all three modes: lowest, highest, average.
    grain: city, state
    """
    if days == 3:
        grain = "city"
    elif days in [5,7]:
        grain = "state"

    if grain not in ["city", "state"]:
        raise ValueError("grain must be one of city, state")
    
    # Multipliers based on days
    multipliers = {
        3: {"flight": 2, "hotel": 3, "restaurant": 9},
        5: {"flight": 3, "hotel": 5, "restaurant": 15},
        7: {"flight": 4, "hotel": 7, "restaurant": 21}
    }
    
    if grain == "city":
        hotel_data = hotel.run(dest)
        restaurant_data = restaurant.run(dest)
        flight_data = flight.data[(flight.data["DestCityName"] == dest) & (flight.data["OriginCityName"] == org)]


    elif grain == "state":
        city_set = open('../database/background/citySet_with_states.txt').read().strip().split('\n')
        
        all_hotel_data = []
        all_restaurant_data = []
        all_flight_data = []
        
        for city in city_set:
            if dest == city.split('\t')[1]:
                candidate_city = city.split('\t')[0]
                
                # Fetch data for the current city
                current_hotel_data = hotel.run(candidate_city)
                current_restaurant_data = restaurant.run(candidate_city)
                current_flight_data = flight.data[(flight.data["DestCityName"] == candidate_city) & (flight.data["OriginCityName"] == org)]
                
                # Append the dataframes to the lists
                all_hotel_data.append(current_hotel_data)
                all_restaurant_data.append(current_restaurant_data)
                all_flight_data.append(current_flight_data)
        
        # Use concat to combine all dataframes in the lists
        hotel_data = pd.concat(all_hotel_data, axis=0)
        restaurant_data = pd.concat(all_restaurant_data, axis=0)
        flight_data = pd.concat(all_flight_data, axis=0)
        # flight_data should be in the range of supported date
        flight_data = flight_data[flight_data['FlightDate'].isin(date)]

    if people_number:
        hotel_data = hotel_data[hotel_data['maximum occupancy'] >= people_number]

    if local_constraint:

        if local_constraint['transportation'] == 'no self-driving':
            if grain == "city":
                if len(flight_data[flight_data['FlightDate'] == date[0]]) < 2:
                    raise ValueError("No flight data available for the given constraints.")
            elif grain == "state":
                if len(flight_data[flight_data['FlightDate'] == date[0]]) < 10:
                    raise ValueError("No flight data available for the given constraints.")
                
        elif local_constraint['transportation'] == 'no flight':
            if len(flight_data[flight_data['FlightDate'] == date[0]]) < 2 or flight_data.iloc[0]['Distance'] > 800:
                raise ValueError("Impossible")
            
        # if local_constraint['flgiht time']:
        #     if local_constraint['flgiht time'] == 'morning':
        #         flight_data = flight_data[flight_data['DepTime'] < '12:00']
        #     elif local_constraint['flgiht time'] == 'afternoon':
        #         flight_data = flight_data[(flight_data['DepTime'] >= '12:00') & (flight_data['DepTime'] < '18:00')]
        #     elif local_constraint['flgiht time'] == 'evening':
        #         flight_data = flight_data[flight_data['DepTime'] >= '18:00']

        if local_constraint['room type']:
            if local_constraint['room type'] == 'shared room':
                hotel_data = hotel_data[hotel_data['room type'] == 'Shared room']
            elif local_constraint['room type'] == 'not shared room':
                hotel_data = hotel_data[(hotel_data['room type'] == 'Private room') | (hotel_data['room type'] == 'Entire home/apt')]
            elif local_constraint['room type'] == 'private room':
                hotel_data = hotel_data[hotel_data['room type'] == 'Private room']
            elif local_constraint['room type'] == 'entire room':
                hotel_data = hotel_data[hotel_data['room type'] == 'Entire home/apt']

            if days == 3:
                if len(hotel_data) < 3:
                    raise ValueError("No hotel data available for the given constraints.")
            elif days == 5:
                if len(hotel_data) < 5:
                    raise ValueError("No hotel data available for the given constraints.")
            elif days == 7:
                if len(hotel_data) < 7:
                    raise ValueError("No hotel data available for the given constraints.")
        
        if local_constraint['house rule']:
            if local_constraint['house rule'] == 'parties':
                # the house rule should not contain 'parties'
                hotel_data = hotel_data[~hotel_data['house_rules'].str.contains('No parties')]
            elif local_constraint['house rule'] == 'smoking':
                hotel_data = hotel_data[~hotel_data['house_rules'].str.contains('No smoking')]
            elif local_constraint['house rule'] == 'children under 10':
                hotel_data = hotel_data[~hotel_data['house_rules'].str.contains('No children under 10')]
            elif local_constraint['house rule'] == 'pets':
                hotel_data = hotel_data[~hotel_data['house_rules'].str.contains('No pets')]
            elif local_constraint['house rule'] == 'visitors':
                hotel_data = hotel_data[~hotel_data['house_rules'].str.contains('No visitors')]
        
            if days == 3:
                if len(hotel_data) < 3:
                    raise ValueError("No hotel data available for the given constraints.")
            elif days == 5:
                if len(hotel_data) < 5:
                    raise ValueError("No hotel data available for the given constraints.")
            elif days == 7:
                if len(hotel_data) < 7:
                    raise ValueError("No hotel data available for the given constraints.")
                
        if local_constraint['cuisine']:
            # judge whether the cuisine is in the cuisine list
            restaurant_data = restaurant_data[restaurant_data['Cuisines'].str.contains('|'.join(local_constraint['cuisine']))]
            
            if days == 3:
                if len(restaurant_data) < 3:
                    raise ValueError("No restaurant data available for the given constraints.")
            elif days == 5:
                if len(restaurant_data) < 5:
                    raise ValueError("No restaurant data available for the given constraints.")
            elif days == 7:
                if len(restaurant_data) < 7:
                    raise ValueError("No restaurant data available for the given constraints.")
                
        # hotel_data = filter.run(hotel_data, local_constraint)
        # restaurant_data = filter.run(restaurant_data, local_constraint)
        # flight_data = filter.run(flight_data, local_constraint)

    # Calculate budgets for all three modes

    budgets = {}
    for mode in ["lowest", "highest", "average"]:
        if local_constraint and local_constraint['transportation'] == 'self driving':
            flight_budget = eval(distanceMatrix.run(org, dest)['cost'].replace("$","")) * multipliers[days]["flight"]
        else:
            flight_budget = estimate_budget(flight_data["Price"].tolist(), mode) * multipliers[days]["flight"]
        hotel_budget = estimate_budget(hotel_data["price"].tolist(), mode) * multipliers[days]["hotel"]
        restaurant_budget = estimate_budget(restaurant_data["Average Cost"].tolist(), mode) * multipliers[days]["restaurant"]
        total_budget = flight_budget + hotel_budget + restaurant_budget
        budgets[mode] = total_budget

    return budgets