Upload 4 files
Browse files- tools/currency_converter_tool.py +91 -0
- tools/local_time_tool.py +112 -0
- tools/weather_forecast_tool.py +168 -0
tools/currency_converter_tool.py
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Optional
|
2 |
+
from smolagents.tools import Tool
|
3 |
+
import os
|
4 |
+
import requests
|
5 |
+
|
6 |
+
class ConvertCurrencyTool(Tool):
|
7 |
+
name = "convert_currency"
|
8 |
+
description = "Converts an amount between currencies for travel budgeting."
|
9 |
+
inputs = {
|
10 |
+
'amount': {'type': 'number', 'description': 'The amount to convert'},
|
11 |
+
'from_currency': {'type': 'string', 'description': 'Source currency code (e.g., USD, EUR)'},
|
12 |
+
'to_currency': {'type': 'string', 'description': 'Target currency code (e.g., JPY, GBP)'}
|
13 |
+
}
|
14 |
+
output_type = "string"
|
15 |
+
|
16 |
+
def __init__(self, api_key=None):
|
17 |
+
super().__init__()
|
18 |
+
# You can set an API key for a real currency API
|
19 |
+
self.api_key = api_key or os.environ.get("EXCHANGE_RATE_API_KEY")
|
20 |
+
|
21 |
+
# Common exchange rates (as of early 2025, for demo/fallback purposes)
|
22 |
+
self.exchange_rates = {
|
23 |
+
"USD": {"EUR": 0.92, "GBP": 0.79, "JPY": 149.50, "CAD": 1.35, "AUD": 1.52, "CNY": 7.20, "INR": 83.20, "MXN": 17.05},
|
24 |
+
"EUR": {"USD": 1.09, "GBP": 0.86, "JPY": 163.00, "CAD": 1.47, "AUD": 1.66, "CNY": 7.85, "INR": 90.70, "MXN": 18.60},
|
25 |
+
"GBP": {"USD": 1.27, "EUR": 1.16, "JPY": 189.30, "CAD": 1.71, "AUD": 1.92, "CNY": 9.10, "INR": 105.30, "MXN": 21.60},
|
26 |
+
"JPY": {"USD": 0.0067, "EUR": 0.0061, "GBP": 0.0053, "CAD": 0.0090, "AUD": 0.0102, "CNY": 0.0482, "INR": 0.5565, "MXN": 0.1141},
|
27 |
+
"CAD": {"USD": 0.74, "EUR": 0.68, "GBP": 0.58, "JPY": 110.70, "AUD": 1.13, "CNY": 5.33, "INR": 61.60, "MXN": 12.60},
|
28 |
+
"AUD": {"USD": 0.66, "EUR": 0.60, "GBP": 0.52, "JPY": 98.40, "CAD": 0.89, "CNY": 4.73, "INR": 54.70, "MXN": 11.20},
|
29 |
+
"CNY": {"USD": 0.14, "EUR": 0.13, "GBP": 0.11, "JPY": 20.80, "CAD": 0.19, "AUD": 0.21, "INR": 11.60, "MXN": 2.37},
|
30 |
+
"INR": {"USD": 0.012, "EUR": 0.011, "GBP": 0.0095, "JPY": 1.80, "CAD": 0.016, "AUD": 0.018, "CNY": 0.086, "MXN": 0.205},
|
31 |
+
"MXN": {"USD": 0.059, "EUR": 0.054, "GBP": 0.046, "JPY": 8.77, "CAD": 0.079, "AUD": 0.089, "CNY": 0.422, "INR": 4.88}
|
32 |
+
}
|
33 |
+
|
34 |
+
def forward(self, amount: float, from_currency: str, to_currency: str) -> str:
|
35 |
+
try:
|
36 |
+
# Normalize currency codes
|
37 |
+
from_currency = from_currency.upper().strip()
|
38 |
+
to_currency = to_currency.upper().strip()
|
39 |
+
|
40 |
+
# Try to use a real currency API if the API key is available
|
41 |
+
if self.api_key:
|
42 |
+
try:
|
43 |
+
url = f"https://v6.exchangerate-api.com/v6/{self.api_key}/pair/{from_currency}/{to_currency}/{amount}"
|
44 |
+
response = requests.get(url)
|
45 |
+
data = response.json()
|
46 |
+
|
47 |
+
if data.get('result') == 'success':
|
48 |
+
converted_amount = data.get('conversion_result')
|
49 |
+
rate = data.get('conversion_rate')
|
50 |
+
|
51 |
+
return f"💱 {amount:,.2f} {from_currency} = {converted_amount:,.2f} {to_currency}\n\nExchange rate: 1 {from_currency} = {rate} {to_currency}\n\n(Data from ExchangeRate-API)"
|
52 |
+
else:
|
53 |
+
# Fall back to stored rates if API call fails
|
54 |
+
return self._convert_with_stored_rates(amount, from_currency, to_currency)
|
55 |
+
|
56 |
+
except Exception:
|
57 |
+
# Fall back to stored rates if any error occurs
|
58 |
+
return self._convert_with_stored_rates(amount, from_currency, to_currency)
|
59 |
+
|
60 |
+
# If no API key is available, use the stored rates
|
61 |
+
return self._convert_with_stored_rates(amount, from_currency, to_currency)
|
62 |
+
|
63 |
+
except Exception as e:
|
64 |
+
return f"Error converting currency: {str(e)}"
|
65 |
+
|
66 |
+
def _convert_with_stored_rates(self, amount: float, from_currency: str, to_currency: str) -> str:
|
67 |
+
# Validate currencies
|
68 |
+
if from_currency not in self.exchange_rates:
|
69 |
+
return f"Sorry, I don't have exchange rate data for {from_currency}."
|
70 |
+
|
71 |
+
# If same currency, return original amount
|
72 |
+
if from_currency == to_currency:
|
73 |
+
return f"{amount} {from_currency} = {amount} {to_currency}"
|
74 |
+
|
75 |
+
# Direct conversion
|
76 |
+
if to_currency in self.exchange_rates[from_currency]:
|
77 |
+
rate = self.exchange_rates[from_currency][to_currency]
|
78 |
+
converted_amount = amount * rate
|
79 |
+
return f"💱 {amount:,.2f} {from_currency} = {converted_amount:,.2f} {to_currency}\n\nExchange rate: 1 {from_currency} = {rate} {to_currency}\n\n(Note: Rates are approximations for planning purposes only)"
|
80 |
+
|
81 |
+
# Try conversion through USD
|
82 |
+
if to_currency in self.exchange_rates and "USD" in self.exchange_rates[from_currency]:
|
83 |
+
usd_amount = amount * self.exchange_rates[from_currency]["USD"]
|
84 |
+
rate_to_target = self.exchange_rates["USD"].get(to_currency)
|
85 |
+
|
86 |
+
if rate_to_target:
|
87 |
+
converted_amount = usd_amount * rate_to_target
|
88 |
+
effective_rate = converted_amount / amount
|
89 |
+
return f"💱 {amount:,.2f} {from_currency} = {converted_amount:,.2f} {to_currency}\n\nExchange rate: 1 {from_currency} = {effective_rate:.4f} {to_currency}\n\n(Note: Rates are approximations for planning purposes only)"
|
90 |
+
|
91 |
+
return f"Sorry, I don't have exchange rate data from {from_currency} to {to_currency}."
|
tools/local_time_tool.py
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Optional
|
2 |
+
from smolagents.tools import Tool
|
3 |
+
import datetime
|
4 |
+
import pytz
|
5 |
+
|
6 |
+
class GetLocalTimeTool(Tool):
|
7 |
+
name = "get_local_time"
|
8 |
+
description = "Gets the current local time at a travel destination."
|
9 |
+
inputs = {'destination': {'type': 'string', 'description': 'A city or location name (e.g., "Paris", "Tokyo", "New York").'}}
|
10 |
+
output_type = "string"
|
11 |
+
|
12 |
+
def __init__(self):
|
13 |
+
super().__init__()
|
14 |
+
try:
|
15 |
+
import pytz
|
16 |
+
except ImportError as e:
|
17 |
+
raise ImportError(
|
18 |
+
"You must install package `pytz` to run this tool: for instance run `pip install pytz`."
|
19 |
+
) from e
|
20 |
+
|
21 |
+
# Map of common tourist destinations to their timezones
|
22 |
+
self.destination_timezones = {
|
23 |
+
"london": "Europe/London",
|
24 |
+
"paris": "Europe/Paris",
|
25 |
+
"rome": "Europe/Rome",
|
26 |
+
"madrid": "Europe/Madrid",
|
27 |
+
"berlin": "Europe/Berlin",
|
28 |
+
"amsterdam": "Europe/Amsterdam",
|
29 |
+
"athens": "Europe/Athens",
|
30 |
+
"istanbul": "Europe/Istanbul",
|
31 |
+
"dubai": "Asia/Dubai",
|
32 |
+
"new delhi": "Asia/Kolkata",
|
33 |
+
"mumbai": "Asia/Kolkata",
|
34 |
+
"bangkok": "Asia/Bangkok",
|
35 |
+
"singapore": "Asia/Singapore",
|
36 |
+
"tokyo": "Asia/Tokyo",
|
37 |
+
"seoul": "Asia/Seoul",
|
38 |
+
"beijing": "Asia/Shanghai",
|
39 |
+
"shanghai": "Asia/Shanghai",
|
40 |
+
"hong kong": "Asia/Hong_Kong",
|
41 |
+
"sydney": "Australia/Sydney",
|
42 |
+
"melbourne": "Australia/Melbourne",
|
43 |
+
"auckland": "Pacific/Auckland",
|
44 |
+
"fiji": "Pacific/Fiji",
|
45 |
+
"honolulu": "Pacific/Honolulu",
|
46 |
+
"anchorage": "America/Anchorage",
|
47 |
+
"los angeles": "America/Los_Angeles",
|
48 |
+
"san francisco": "America/Los_Angeles",
|
49 |
+
"las vegas": "America/Los_Angeles",
|
50 |
+
"denver": "America/Denver",
|
51 |
+
"chicago": "America/Chicago",
|
52 |
+
"houston": "America/Chicago",
|
53 |
+
"new york": "America/New_York",
|
54 |
+
"miami": "America/New_York",
|
55 |
+
"toronto": "America/Toronto",
|
56 |
+
"mexico city": "America/Mexico_City",
|
57 |
+
"rio de janeiro": "America/Sao_Paulo",
|
58 |
+
"sao paulo": "America/Sao_Paulo",
|
59 |
+
"buenos aires": "America/Argentina/Buenos_Aires",
|
60 |
+
"cairo": "Africa/Cairo",
|
61 |
+
"cape town": "Africa/Johannesburg",
|
62 |
+
"johannesburg": "Africa/Johannesburg",
|
63 |
+
"nairobi": "Africa/Nairobi"
|
64 |
+
}
|
65 |
+
|
66 |
+
def forward(self, destination: str) -> str:
|
67 |
+
try:
|
68 |
+
# Normalize the destination name
|
69 |
+
normalized_dest = destination.lower().strip()
|
70 |
+
|
71 |
+
# Find the closest matching timezone
|
72 |
+
timezone = None
|
73 |
+
for city, tz in self.destination_timezones.items():
|
74 |
+
if city in normalized_dest or normalized_dest in city:
|
75 |
+
timezone = tz
|
76 |
+
break
|
77 |
+
|
78 |
+
if not timezone:
|
79 |
+
# If we don't have a direct match, try to find it through pytz
|
80 |
+
try:
|
81 |
+
# Try web search for timezone if available
|
82 |
+
import importlib
|
83 |
+
if importlib.util.find_spec("duckduckgo_search"):
|
84 |
+
from duckduckgo_search import DDGS
|
85 |
+
ddgs = DDGS()
|
86 |
+
results = ddgs.text(f"{destination} timezone")
|
87 |
+
if results:
|
88 |
+
# Simple heuristic to extract timezone from search results
|
89 |
+
for result in results:
|
90 |
+
body = result.get('body', '').lower()
|
91 |
+
if 'utc' in body or 'gmt' in body:
|
92 |
+
timezone_pos = body.find('utc') if 'utc' in body else body.find('gmt')
|
93 |
+
timezone_info = body[timezone_pos:timezone_pos+8]
|
94 |
+
return f"Based on web search, the timezone in {destination} appears to be around {timezone_info.upper()}. Current time information is not available."
|
95 |
+
except:
|
96 |
+
pass
|
97 |
+
|
98 |
+
return f"I don't have timezone information for {destination}. Please try a major city nearby."
|
99 |
+
|
100 |
+
# Get current time in that timezone
|
101 |
+
tz = pytz.timezone(timezone)
|
102 |
+
local_time = datetime.datetime.now(tz)
|
103 |
+
|
104 |
+
# Format the result
|
105 |
+
formatted_time = local_time.strftime("%I:%M %p on %A, %B %d, %Y")
|
106 |
+
time_diff = local_time.utcoffset().total_seconds() / 3600
|
107 |
+
sign = "+" if time_diff >= 0 else ""
|
108 |
+
|
109 |
+
return f"The current local time in {destination} is {formatted_time} (UTC{sign}{int(time_diff)})"
|
110 |
+
|
111 |
+
except Exception as e:
|
112 |
+
return f"Error getting local time for {destination}: {str(e)}"
|
tools/weather_forecast_tool.py
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Optional
|
2 |
+
from smolagents.tools import Tool
|
3 |
+
import datetime
|
4 |
+
import random
|
5 |
+
import os
|
6 |
+
import requests
|
7 |
+
|
8 |
+
class GetWeatherForecastTool(Tool):
|
9 |
+
name = "get_weather_forecast"
|
10 |
+
description = "Gets the weather forecast for a travel destination."
|
11 |
+
inputs = {
|
12 |
+
'destination': {'type': 'string', 'description': 'City or location name'},
|
13 |
+
'days': {'type': 'integer', 'description': 'Number of days to forecast (default: 3)'}
|
14 |
+
}
|
15 |
+
output_type = "string"
|
16 |
+
|
17 |
+
def __init__(self, api_key=None):
|
18 |
+
super().__init__()
|
19 |
+
# You can set an API key for a real weather service like OpenWeatherMap
|
20 |
+
self.api_key = api_key or os.environ.get("WEATHER_API_KEY")
|
21 |
+
|
22 |
+
# Weather conditions for demo/fallback
|
23 |
+
self.weather_conditions = [
|
24 |
+
"Sunny", "Partly Cloudy", "Cloudy", "Light Rain",
|
25 |
+
"Heavy Rain", "Thunderstorms", "Windy", "Foggy", "Snow", "Clear"
|
26 |
+
]
|
27 |
+
|
28 |
+
def forward(self, destination: str, days: int = 3) -> str:
|
29 |
+
try:
|
30 |
+
# Try to use a real weather API if the API key is available
|
31 |
+
if self.api_key:
|
32 |
+
try:
|
33 |
+
url = f"http://api.openweathermap.org/data/2.5/forecast?q={destination}&appid={self.api_key}&units=metric"
|
34 |
+
response = requests.get(url)
|
35 |
+
data = response.json()
|
36 |
+
|
37 |
+
if response.status_code != 200:
|
38 |
+
# Fall back to demo method if API call fails
|
39 |
+
return self._generate_demo_forecast(destination, days)
|
40 |
+
|
41 |
+
# Process and format forecast data
|
42 |
+
forecast_text = f"🌦️ Weather forecast for {destination}:\n\n"
|
43 |
+
|
44 |
+
# Group forecasts by day
|
45 |
+
forecasts_by_day = {}
|
46 |
+
for item in data['list'][:days * 8]: # API returns data in 3-hour intervals
|
47 |
+
date = item['dt_txt'].split(' ')[0]
|
48 |
+
if date not in forecasts_by_day:
|
49 |
+
forecasts_by_day[date] = []
|
50 |
+
forecasts_by_day[date].append(item)
|
51 |
+
|
52 |
+
# Format each day's forecast
|
53 |
+
for date, items in list(forecasts_by_day.items())[:days]:
|
54 |
+
day_name = datetime.datetime.strptime(date, "%Y-%m-%d").strftime("%A")
|
55 |
+
temps = [item['main']['temp'] for item in items]
|
56 |
+
avg_temp = sum(temps) / len(temps)
|
57 |
+
conditions = [item['weather'][0]['main'] for item in items]
|
58 |
+
most_common = max(set(conditions), key=conditions.count)
|
59 |
+
|
60 |
+
precipitation = any('Rain' in item['weather'][0]['main'] or 'Snow' in item['weather'][0]['main'] for item in items)
|
61 |
+
precipitation_chance = "60%" if precipitation else "0%"
|
62 |
+
|
63 |
+
forecast_text += f"• {day_name}, {date}: {most_common}, {min(temps):.1f}°C to {max(temps):.1f}°C"
|
64 |
+
if precipitation:
|
65 |
+
forecast_text += f", {precipitation_chance} chance of precipitation"
|
66 |
+
forecast_text += "\n"
|
67 |
+
|
68 |
+
# Add packing recommendations
|
69 |
+
forecast_text += self._generate_packing_tips(forecasts_by_day)
|
70 |
+
|
71 |
+
return forecast_text
|
72 |
+
|
73 |
+
except Exception:
|
74 |
+
# Fall back to demo method if any error occurs
|
75 |
+
return self._generate_demo_forecast(destination, days)
|
76 |
+
|
77 |
+
# If no API key is available, use the demo method
|
78 |
+
return self._generate_demo_forecast(destination, days)
|
79 |
+
|
80 |
+
except Exception as e:
|
81 |
+
return f"Error retrieving weather data for {destination}: {str(e)}"
|
82 |
+
|
83 |
+
def _generate_demo_forecast(self, destination: str, days: int) -> str:
|
84 |
+
# Create a deterministic but seemingly random forecast based on destination name
|
85 |
+
seed = sum(ord(c) for c in destination)
|
86 |
+
random.seed(seed)
|
87 |
+
|
88 |
+
# Generate forecast data
|
89 |
+
forecast_text = f"🌦️ Weather forecast for {destination}:\n\n"
|
90 |
+
|
91 |
+
today = datetime.datetime.now()
|
92 |
+
temp_base = random.randint(10, 25) # Base temperature varies by destination
|
93 |
+
|
94 |
+
for i in range(days):
|
95 |
+
day = today + datetime.timedelta(days=i)
|
96 |
+
day_name = day.strftime("%A")
|
97 |
+
date = day.strftime("%b %d")
|
98 |
+
|
99 |
+
# "Random" but deterministic weather for the demo
|
100 |
+
condition = self.weather_conditions[random.randint(0, len(self.weather_conditions)-1)]
|
101 |
+
temp_high = temp_base + random.randint(0, 10) # Celsius
|
102 |
+
temp_low = temp_high - random.randint(5, 15)
|
103 |
+
precipitation = random.randint(0, 100) if "Rain" in condition or "Snow" in condition or "Thunder" in condition else 0
|
104 |
+
|
105 |
+
forecast_text += f"• {day_name}, {date}: {condition}, {temp_low}°C to {temp_high}°C"
|
106 |
+
if precipitation > 0:
|
107 |
+
forecast_text += f", {precipitation}% chance of precipitation"
|
108 |
+
forecast_text += "\n"
|
109 |
+
|
110 |
+
# Add packing recommendations
|
111 |
+
cold_days = sum(1 for i in range(days) if temp_base + 5 < 15)
|
112 |
+
rainy_days = sum(1 for i in range(days) if "Rain" in self.weather_conditions[random.randint(0, len(self.weather_conditions)-1)])
|
113 |
+
hot_days = sum(1 for i in range(days) if temp_base + 5 > 25)
|
114 |
+
|
115 |
+
forecast_text += "\n🧳 Packing tips: "
|
116 |
+
if cold_days > days/2:
|
117 |
+
forecast_text += "Bring warm layers and a jacket. "
|
118 |
+
elif cold_days > 0:
|
119 |
+
forecast_text += "Pack a light jacket for cooler periods. "
|
120 |
+
|
121 |
+
if rainy_days > 0:
|
122 |
+
forecast_text += "Don't forget an umbrella or rain gear. "
|
123 |
+
|
124 |
+
if hot_days > days/2:
|
125 |
+
forecast_text += "Bring sunscreen, sunglasses, and light clothing. "
|
126 |
+
|
127 |
+
return forecast_text
|
128 |
+
|
129 |
+
def _generate_packing_tips(self, forecasts_by_day):
|
130 |
+
# Extract temperature ranges across all days
|
131 |
+
all_temps = []
|
132 |
+
has_rain = False
|
133 |
+
has_snow = False
|
134 |
+
|
135 |
+
for day_items in forecasts_by_day.values():
|
136 |
+
for item in day_items:
|
137 |
+
all_temps.append(item['main']['temp'])
|
138 |
+
if 'Rain' in item['weather'][0]['main']:
|
139 |
+
has_rain = True
|
140 |
+
if 'Snow' in item['weather'][0]['main']:
|
141 |
+
has_snow = True
|
142 |
+
|
143 |
+
min_temp = min(all_temps) if all_temps else 0
|
144 |
+
max_temp = max(all_temps) if all_temps else 30
|
145 |
+
|
146 |
+
# Generate packing tips based on conditions
|
147 |
+
tips = "\n🧳 Packing tips: "
|
148 |
+
|
149 |
+
if min_temp < 5:
|
150 |
+
tips += "Bring a heavy winter coat, gloves, and hat. "
|
151 |
+
elif min_temp < 15:
|
152 |
+
tips += "Pack a warm jacket and layers. "
|
153 |
+
elif min_temp < 20:
|
154 |
+
tips += "Bring a light jacket for evenings. "
|
155 |
+
|
156 |
+
if max_temp > 25:
|
157 |
+
tips += "Pack light, breathable clothing for warm days. "
|
158 |
+
|
159 |
+
if has_rain:
|
160 |
+
tips += "Don't forget an umbrella and waterproof footwear. "
|
161 |
+
|
162 |
+
if has_snow:
|
163 |
+
tips += "Bring waterproof boots and warm socks. "
|
164 |
+
|
165 |
+
if max_temp > 22:
|
166 |
+
tips += "Sunscreen and sunglasses are recommended. "
|
167 |
+
|
168 |
+
return tips
|