| import requests |
| import folium |
|
|
| COUNTRIES_AND_CITIES = { |
| "Afghanistan": ["Kabul", "Kandahar", "Herat", "Mazar-i-Sharif", "Jalalabad"], |
| "Albania": ["Tirana", "Durrës", "Vlorë", "Shkodër", "Fier"], |
| "Algeria": ["Algiers", "Oran", "Constantine", "Annaba", "Blida"], |
| "Argentina": ["Buenos Aires", "Córdoba", "Rosario", "Mendoza", "La Plata"], |
| "Armenia": ["Yerevan", "Gyumri", "Vanadzor", "Vagharshapat", "Hrazdan"], |
| "Australia": [ |
| "Sydney", |
| "Melbourne", |
| "Brisbane", |
| "Perth", |
| "Adelaide", |
| "Gold Coast", |
| "Newcastle", |
| "Canberra", |
| "Sunshine Coast", |
| "Wollongong", |
| ], |
| "Austria": ["Vienna", "Graz", "Linz", "Salzburg", "Innsbruck"], |
| "Azerbaijan": ["Baku", "Ganja", "Sumqayit", "Mingachevir", "Lankaran"], |
| "Bahrain": ["Manama", "Riffa", "Muharraq", "Hamad Town", "A'ali"], |
| "Bangladesh": ["Dhaka", "Chittagong", "Sylhet", "Rajshahi", "Khulna"], |
| "Belarus": ["Minsk", "Gomel", "Mogilev", "Vitebsk", "Grodno"], |
| "Belgium": ["Brussels", "Antwerp", "Ghent", "Charleroi", "Liège"], |
| "Bolivia": ["La Paz", "Santa Cruz", "Cochabamba", "Sucre", "Oruro"], |
| "Bosnia and Herzegovina": ["Sarajevo", "Banja Luka", "Tuzla", "Zenica", "Mostar"], |
| "Brazil": [ |
| "São Paulo", |
| "Rio de Janeiro", |
| "Brasília", |
| "Salvador", |
| "Fortaleza", |
| "Belo Horizonte", |
| "Manaus", |
| "Curitiba", |
| "Recife", |
| "Goiânia", |
| ], |
| "Bulgaria": ["Sofia", "Plovdiv", "Varna", "Burgas", "Ruse"], |
| "Cambodia": ["Phnom Penh", "Siem Reap", "Battambang", "Sihanoukville", "Poipet"], |
| "Canada": [ |
| "Toronto", |
| "Montreal", |
| "Vancouver", |
| "Calgary", |
| "Edmonton", |
| "Ottawa", |
| "Winnipeg", |
| "Quebec City", |
| "Hamilton", |
| "Kitchener", |
| ], |
| "Chile": ["Santiago", "Valparaíso", "Concepción", "La Serena", "Antofagasta"], |
| "China": [ |
| "Shanghai", |
| "Beijing", |
| "Chongqing", |
| "Tianjin", |
| "Guangzhou", |
| "Shenzhen", |
| "Wuhan", |
| "Dongguan", |
| "Chengdu", |
| "Nanjing", |
| ], |
| "Colombia": ["Bogotá", "Medellín", "Cali", "Barranquilla", "Cartagena"], |
| "Croatia": ["Zagreb", "Split", "Rijeka", "Osijek", "Zadar"], |
| "Czech Republic": ["Prague", "Brno", "Ostrava", "Plzen", "Liberec"], |
| "Denmark": ["Copenhagen", "Aarhus", "Odense", "Aalborg", "Esbjerg"], |
| "Ecuador": ["Quito", "Guayaquil", "Cuenca", "Santo Domingo", "Machala"], |
| "Egypt": ["Cairo", "Alexandria", "Giza", "Shubra El Kheima", "Port Said"], |
| "Estonia": ["Tallinn", "Tartu", "Narva", "Pärnu", "Kohtla-Järve"], |
| "Ethiopia": ["Addis Ababa", "Dire Dawa", "Mekelle", "Adama", "Awassa"], |
| "Finland": ["Helsinki", "Espoo", "Tampere", "Vantaa", "Oulu"], |
| "France": [ |
| "Paris", |
| "Lyon", |
| "Marseille", |
| "Toulouse", |
| "Nice", |
| "Nantes", |
| "Strasbourg", |
| "Montpellier", |
| "Bordeaux", |
| "Lille", |
| ], |
| "Georgia": ["Tbilisi", "Batumi", "Kutaisi", "Rustavi", "Gori"], |
| "Germany": [ |
| "Berlin", |
| "Hamburg", |
| "Munich", |
| "Cologne", |
| "Frankfurt", |
| "Stuttgart", |
| "Düsseldorf", |
| "Dortmund", |
| "Essen", |
| "Leipzig", |
| ], |
| "Ghana": ["Accra", "Kumasi", "Tamale", "Takoradi", "Cape Coast"], |
| "Greece": ["Athens", "Thessaloniki", "Patras", "Heraklion", "Larissa"], |
| "Hungary": ["Budapest", "Debrecen", "Szeged", "Miskolc", "Pécs"], |
| "Iceland": ["Reykjavik", "Kópavogur", "Hafnarfjörður", "Akureyri", "Reykjanesbær"], |
| "India": [ |
| "Mumbai", |
| "Delhi", |
| "Bangalore", |
| "Hyderabad", |
| "Chennai", |
| "Kolkata", |
| "Ahmedabad", |
| "Pune", |
| "Surat", |
| "Jaipur", |
| ], |
| "Indonesia": [ |
| "Jakarta", |
| "Surabaya", |
| "Bandung", |
| "Bekasi", |
| "Medan", |
| "Tangerang", |
| "Depok", |
| "Semarang", |
| "Palembang", |
| "Makassar", |
| ], |
| "Iran": ["Tehran", "Mashhad", "Isfahan", "Karaj", "Shiraz"], |
| "Iraq": ["Baghdad", "Basra", "Mosul", "Erbil", "Najaf"], |
| "Ireland": ["Dublin", "Cork", "Limerick", "Galway", "Waterford"], |
| "Israel": ["Jerusalem", "Tel Aviv", "Haifa", "Rishon LeZion", "Petah Tikva"], |
| "Italy": [ |
| "Rome", |
| "Milan", |
| "Naples", |
| "Turin", |
| "Palermo", |
| "Genoa", |
| "Bologna", |
| "Florence", |
| "Bari", |
| "Catania", |
| ], |
| "Japan": [ |
| "Tokyo", |
| "Osaka", |
| "Yokohama", |
| "Nagoya", |
| "Sapporo", |
| "Fukuoka", |
| "Kobe", |
| "Kawasaki", |
| "Kyoto", |
| "Saitama", |
| ], |
| "Jordan": ["Amman", "Zarqa", "Irbid", "Russeifa", "Wadi as-Ser"], |
| "Kazakhstan": ["Almaty", "Nur-Sultan", "Shymkent", "Aktobe", "Taraz"], |
| "Kenya": ["Nairobi", "Mombasa", "Kisumu", "Nakuru", "Eldoret"], |
| "Kuwait": ["Kuwait City", "Al Ahmadi", "Hawalli", "As Salimiyah", "Sabah as Salim"], |
| "Latvia": ["Riga", "Daugavpils", "Liepāja", "Jelgava", "Jūrmala"], |
| "Lebanon": ["Beirut", "Tripoli", "Sidon", "Tyre", "Nabatieh"], |
| "Lithuania": ["Vilnius", "Kaunas", "Klaipėda", "Šiauliai", "Panevėžys"], |
| "Luxembourg": [ |
| "Luxembourg City", |
| "Esch-sur-Alzette", |
| "Differdange", |
| "Dudelange", |
| "Ettelbruck", |
| ], |
| "Malaysia": ["Kuala Lumpur", "George Town", "Ipoh", "Shah Alam", "Petaling Jaya"], |
| "Mexico": [ |
| "Mexico City", |
| "Guadalajara", |
| "Monterrey", |
| "Puebla", |
| "Tijuana", |
| "León", |
| "Juárez", |
| "Torreón", |
| "Querétaro", |
| "Mérida", |
| ], |
| "Morocco": ["Casablanca", "Rabat", "Fez", "Marrakech", "Agadir"], |
| "Nepal": ["Kathmandu", "Pokhara", "Lalitpur", "Bharatpur", "Biratnagar"], |
| "Netherlands": [ |
| "Amsterdam", |
| "Rotterdam", |
| "The Hague", |
| "Utrecht", |
| "Eindhoven", |
| "Tilburg", |
| "Groningen", |
| "Almere", |
| "Breda", |
| "Nijmegen", |
| ], |
| "New Zealand": ["Auckland", "Wellington", "Christchurch", "Hamilton", "Tauranga"], |
| "Nigeria": ["Lagos", "Abuja", "Kano", "Ibadan", "Port Harcourt"], |
| "Norway": [ |
| "Oslo", |
| "Bergen", |
| "Trondheim", |
| "Stavanger", |
| "Drammen", |
| "Fredrikstad", |
| "Kristiansand", |
| "Sandnes", |
| "Tromsø", |
| "Sarpsborg", |
| ], |
| "Pakistan": ["Karachi", "Lahore", "Faisalabad", "Rawalpindi", "Multan"], |
| "Peru": ["Lima", "Arequipa", "Trujillo", "Chiclayo", "Huancayo"], |
| "Philippines": ["Manila", "Quezon City", "Davao", "Cebu City", "Zamboanga"], |
| "Poland": ["Warsaw", "Kraków", "Łódź", "Wrocław", "Poznań"], |
| "Portugal": ["Lisbon", "Porto", "Vila Nova de Gaia", "Amadora", "Braga"], |
| "Qatar": ["Doha", "Al Rayyan", "Umm Salal", "Al Wakrah", "Al Khor"], |
| "Romania": ["Bucharest", "Cluj-Napoca", "Timișoara", "Iași", "Constanța"], |
| "Russia": [ |
| "Moscow", |
| "Saint Petersburg", |
| "Novosibirsk", |
| "Yekaterinburg", |
| "Kazan", |
| "Nizhny Novgorod", |
| "Chelyabinsk", |
| "Samara", |
| "Omsk", |
| "Rostov-on-Don", |
| ], |
| "Saudi Arabia": ["Riyadh", "Jeddah", "Mecca", "Medina", "Dammam"], |
| "Serbia": ["Belgrade", "Novi Sad", "Niš", "Kragujevac", "Subotica"], |
| "Singapore": ["Singapore"], |
| "Slovakia": ["Bratislava", "Košice", "Prešov", "Žilina", "Banská Bystrica"], |
| "Slovenia": ["Ljubljana", "Maribor", "Celje", "Kranj", "Velenje"], |
| "South Africa": [ |
| "Cape Town", |
| "Johannesburg", |
| "Durban", |
| "Pretoria", |
| "Port Elizabeth", |
| ], |
| "South Korea": [ |
| "Seoul", |
| "Busan", |
| "Incheon", |
| "Daegu", |
| "Daejeon", |
| "Gwangju", |
| "Suwon", |
| "Ulsan", |
| "Changwon", |
| "Goyang", |
| ], |
| "Spain": [ |
| "Madrid", |
| "Barcelona", |
| "Valencia", |
| "Seville", |
| "Zaragoza", |
| "Málaga", |
| "Murcia", |
| "Palma", |
| "Las Palmas", |
| "Bilbao", |
| ], |
| "Sri Lanka": [ |
| "Colombo", |
| "Dehiwala-Mount Lavinia", |
| "Moratuwa", |
| "Sri Jayawardenepura Kotte", |
| "Negombo", |
| ], |
| "Sweden": [ |
| "Stockholm", |
| "Gothenburg", |
| "Malmö", |
| "Uppsala", |
| "Västerås", |
| "Örebro", |
| "Linköping", |
| "Helsingborg", |
| "Jönköping", |
| "Norrköping", |
| ], |
| "Switzerland": [ |
| "Zurich", |
| "Geneva", |
| "Basel", |
| "Bern", |
| "Lausanne", |
| "Winterthur", |
| "Lucerne", |
| "St. Gallen", |
| "Lugano", |
| "Biel/Bienne", |
| ], |
| "Thailand": ["Bangkok", "Chiang Mai", "Pattaya", "Phuket", "Hat Yai"], |
| "Turkey": [ |
| "Istanbul", |
| "Ankara", |
| "Izmir", |
| "Bursa", |
| "Adana", |
| "Gaziantep", |
| "Konya", |
| "Antalya", |
| "Kayseri", |
| "Mersin", |
| ], |
| "Ukraine": ["Kyiv", "Kharkiv", "Odesa", "Dnipro", "Donetsk"], |
| "United Arab Emirates": ["Dubai", "Abu Dhabi", "Sharjah", "Al Ain", "Ajman"], |
| "United Kingdom": [ |
| "London", |
| "Birmingham", |
| "Manchester", |
| "Leeds", |
| "Liverpool", |
| "Sheffield", |
| "Bristol", |
| "Glasgow", |
| "Leicester", |
| "Edinburgh", |
| ], |
| "United States": [ |
| "New York", |
| "Los Angeles", |
| "Chicago", |
| "Houston", |
| "Phoenix", |
| "Philadelphia", |
| "San Antonio", |
| "San Diego", |
| "Dallas", |
| "San Jose", |
| ], |
| "Uruguay": ["Montevideo", "Salto", "Paysandú", "Las Piedras", "Rivera"], |
| "Venezuela": ["Caracas", "Maracaibo", "Valencia", "Barquisimeto", "Maracay"], |
| "Vietnam": ["Ho Chi Minh City", "Hanoi", "Da Nang", "Bien Hoa", "Hue"], |
| } |
|
|
| US_STATES = [ |
| "Alabama", |
| "Alaska", |
| "Arizona", |
| "Arkansas", |
| "California", |
| "Colorado", |
| "Connecticut", |
| "Delaware", |
| "Florida", |
| "Georgia", |
| "Hawaii", |
| "Idaho", |
| "Illinois", |
| "Indiana", |
| "Iowa", |
| "Kansas", |
| "Kentucky", |
| "Louisiana", |
| "Maine", |
| "Maryland", |
| "Massachusetts", |
| "Michigan", |
| "Minnesota", |
| "Mississippi", |
| "Missouri", |
| "Montana", |
| "Nebraska", |
| "Nevada", |
| "New Hampshire", |
| "New Jersey", |
| "New Mexico", |
| "New York", |
| "North Carolina", |
| "North Dakota", |
| "Ohio", |
| "Oklahoma", |
| "Oregon", |
| "Pennsylvania", |
| "Rhode Island", |
| "South Carolina", |
| "South Dakota", |
| "Tennessee", |
| "Texas", |
| "Utah", |
| "Vermont", |
| "Virginia", |
| "Washington", |
| "West Virginia", |
| "Wisconsin", |
| "Wyoming", |
| "District of Columbia", |
| ] |
|
|
|
|
| def get_coordinates_from_dropdown(country: str, city: str, state: str = None) -> tuple: |
| """Get coordinates using dropdown selections""" |
| if not country or not city: |
| return None, "Please select both country and city." |
|
|
| if country == "United States" and state: |
| query = f"{city}, {state}, United States" |
| else: |
| query = f"{city}, {country}" |
|
|
| try: |
| url = "https://nominatim.openstreetmap.org/search" |
| params = {"q": query, "format": "json", "limit": 1} |
| headers = {"User-Agent": "ClimateRiskTool/1.0"} |
|
|
| response = requests.get(url, params=params, headers=headers, timeout=10) |
| data = response.json() |
|
|
| if data: |
| lat = float(data[0]["lat"]) |
| lon = float(data[0]["lon"]) |
| return ( |
| lat, |
| lon, |
| ), f"✅ Location found: {data[0].get('display_name', query)}" |
| else: |
| return None, f"❌ Location '{city}' not found in {country}." |
|
|
| except Exception as e: |
| return None, f"❌ Error looking up location: {str(e)}" |
|
|
|
|
| def create_risk_map( |
| lat: float, lon: float, city: str, country: str, risk_analysis: dict = None |
| ) -> str: |
| import folium |
|
|
| |
| m = folium.Map(location=[lat, lon], zoom_start=10, tiles="OpenStreetMap") |
|
|
| |
| marker_color = "blue" |
| popup_html = f"<b>{city}, {country}</b><br>Lat: {lat:.4f}<br>Lon: {lon:.4f}" |
|
|
| |
| if risk_analysis and isinstance(risk_analysis, dict): |
| risks = risk_analysis.get("risk_analysis", {}) |
| popup_html += "<br><b>Risks for this location:</b><br>" |
| max_level = 0 |
| for risk_name, risk_data in risks.items(): |
| if isinstance(risk_data, dict): |
| risk_level = risk_data.get("risk_level", 0) |
| max_level = max(max_level, risk_level) |
| if risk_level > 80: |
| emoji = "🔴" |
| elif risk_level > 60: |
| emoji = "🟠" |
| elif risk_level > 40: |
| emoji = "🟡" |
| elif risk_level > 20: |
| emoji = "🟢" |
| else: |
| emoji = "⚪" |
| popup_html += f"{emoji} <b>{risk_name.title()}:</b> {risk_level}/100<br>" |
|
|
| |
| if max_level > 80: |
| marker_color = "red" |
| elif max_level > 60: |
| marker_color = "orange" |
| elif max_level > 40: |
| marker_color = "lightgreen" |
| elif max_level > 20: |
| marker_color = "green" |
| else: |
| marker_color = "blue" |
|
|
| |
| marker = folium.Marker( |
| [lat, lon], |
| popup=popup_html, |
| tooltip=f"Risks for {city}", |
| icon=folium.Icon(color=marker_color, icon="info-sign"), |
| ) |
| marker.add_to(m) |
|
|
| |
| script = f""" |
| <script> |
| var marker = {marker.get_name()}; |
| marker.openPopup(); |
| </script> |
| """ |
| m.get_root().html.add_child(folium.Element(script)) |
|
|
| |
| legend_html = """ |
| <div style="position: fixed; |
| top: 10px; right: 10px; width: 280px; height: auto; |
| background-color: white; border: 2px solid grey; z-index: 9999; |
| font-size: 13px; padding: 12px; border-radius: 10px; |
| box-shadow: 0 4px 8px rgba(0,0,0,0.1);"> |
| <h4 style="margin: 0 0 10px 0;">🗺️ Legend</h4> |
| <div><span style="color:red;">🔴</span> High risk<br> |
| <span style="color:orange;">🟠</span> Moderate risk<br> |
| <span style="color:yellow;">🟡</span> Mild risk<br> |
| <span style="color:green;">🟢</span> Low risk</div> |
| </div> |
| """ |
| m.get_root().html.add_child(folium.Element(legend_html)) |
|
|
| return m._repr_html_() |
|
|
| def get_city_suggestions(country: str) -> str: |
| """Return city suggestions for selected country""" |
| if country in COUNTRIES_AND_CITIES: |
| cities = COUNTRIES_AND_CITIES[country] |
| return f"💡 Popular cities in {country}: {', '.join(cities[:8])}..." |
| return "" |
|
|