help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
weather-chatbot
/
utils
RSK World
weather-chatbot
Weather Chatbot - Python + Flask + OpenWeatherMap + OpenAI + Weather Forecast + Weather Alerts + Natural Language Processing
utils
  • __pycache__
  • __init__.py3.9 KB
  • advanced_nlp.py28.4 KB
  • analytics.py22 KB
  • auth.py17.8 KB
  • comparison.py24.2 KB
  • database.py24.6 KB
  • geolocation.py20.1 KB
  • multilang.py22 KB
  • notifications.py34.1 KB
  • rate_limiting.py24.3 KB
  • weather_maps.py29.6 KB
  • weather_utils.py12.9 KB
weather_utils.py
utils/weather_utils.py
Raw Download
Find: Go to:
#!/usr/bin/env python3
"""
Weather Chatbot Utility Functions
==================================

Author: RSK World (https://rskworld.in)
Founded by: Molla Samser
Designer & Tester: Rima Khatun
Contact: +91 93305 39277, hello@rskworld.in, support@rskworld.in
Location: Nutanhat, Mongolkote, Purba Burdwan, West Bengal, India, 713147
Year: 2026

Description: Utility functions for weather data processing and formatting
"""

import json
import math
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Union

def format_temperature(temp_celsius: float, unit: str = 'metric') -> str:
    """
    Format temperature with appropriate unit.
    
    Args:
        temp_celsius (float): Temperature in Celsius
        unit (str): Temperature unit (metric, imperial, kelvin)
        
    Returns:
        str: Formatted temperature string
    """
    if unit == 'imperial':
        temp_fahrenheit = (temp_celsius * 9/5) + 32
        return f"{round(temp_fahrenheit)}°F"
    elif unit == 'kelvin':
        temp_kelvin = temp_celsius + 273.15
        return f"{round(temp_kelvin)}K"
    else:
        return f"{round(temp_celsius)}°C"

def format_wind_speed(speed_ms: float, unit: str = 'metric') -> str:
    """
    Format wind speed with appropriate unit.
    
    Args:
        speed_ms (float): Wind speed in meters per second
        unit (str): Speed unit (metric, imperial)
        
    Returns:
        str: Formatted wind speed string
    """
    if unit == 'imperial':
        speed_mph = speed_ms * 2.237
        return f"{round(speed_mph, 1)} mph"
    else:
        return f"{round(speed_ms, 1)} m/s"

def format_pressure(pressure_hpa: float) -> str:
    """
    Format atmospheric pressure.
    
    Args:
        pressure_hpa (float): Pressure in hectopascals
        
    Returns:
        str: Formatted pressure string
    """
    return f"{round(pressure_hpa)} hPa"

def format_visibility(visibility_meters: float) -> str:
    """
    Format visibility distance.
    
    Args:
        visibility_meters (float): Visibility in meters
        
    Returns:
        str: Formatted visibility string
    """
    if visibility_meters >= 1000:
        visibility_km = visibility_meters / 1000
        return f"{round(visibility_km, 1)} km"
    else:
        return f"{round(visibility_meters)} m"

def get_weather_icon_url(icon_code: str) -> str:
    """
    Get OpenWeatherMap icon URL.
    
    Args:
        icon_code (str): Weather icon code
        
    Returns:
        str: Icon URL
    """
    return f"https://openweathermap.org/img/wn/{icon_code}@2x.png"

def get_weather_description(description: str) -> str:
    """
    Format weather description with proper capitalization.
    
    Args:
        description (str): Weather description
        
    Returns:
        str: Formatted description
    """
    return description.capitalize()

def calculate_heat_index(temp_celsius: float, humidity: float) -> float:
    """
    Calculate heat index (apparent temperature).
    
    Args:
        temp_celsius (float): Temperature in Celsius
        humidity (float): Relative humidity percentage
        
    Returns:
        float: Heat index in Celsius
    """
    # Convert to Fahrenheit for calculation
    temp_f = (temp_celsius * 9/5) + 32
    
    # Heat index formula (simplified)
    if temp_f < 80:
        return temp_celsius
    
    hi = (-42.379 + 2.04901523 * temp_f + 10.14333127 * humidity 
          - 0.22475541 * temp_f * humidity - 6.83783e-3 * temp_f * temp_f 
          - 5.481717e-2 * humidity * humidity + 1.22874e-3 * temp_f * temp_f * humidity 
          + 8.5282e-4 * temp_f * humidity * humidity - 1.99e-6 * temp_f * temp_f * humidity * humidity)
    
    # Convert back to Celsius
    hi_celsius = (hi - 32) * 5/9
    return round(hi_celsius, 1)

def calculate_wind_chill(temp_celsius: float, wind_speed_ms: float) -> float:
    """
    Calculate wind chill temperature.
    
    Args:
        temp_celsius (float): Temperature in Celsius
        wind_speed_ms (float): Wind speed in meters per second
        
    Returns:
        float: Wind chill in Celsius
    """
    # Convert to Fahrenheit and mph for calculation
    temp_f = (temp_celsius * 9/5) + 32
    wind_mph = wind_speed_ms * 2.237
    
    if temp_f > 50 or wind_mph < 3:
        return temp_celsius
    
    # Wind chill formula
    wc = 35.74 + 0.6215 * temp_f - 35.75 * (wind_mph ** 0.16) + 0.4275 * temp_f * (wind_mph ** 0.16)
    
    # Convert back to Celsius
    wc_celsius = (wc - 32) * 5/9
    return round(wc_celsius, 1)

def get_uv_index_level(uv_index: float) -> Dict[str, str]:
    """
    Get UV index level and recommendations.
    
    Args:
        uv_index (float): UV index value
        
    Returns:
        dict: UV index information
    """
    if uv_index <= 2:
        return {
            'level': 'Low',
            'color': 'green',
            'protection': 'No protection needed'
        }
    elif uv_index <= 5:
        return {
            'level': 'Moderate',
            'color': 'yellow',
            'protection': 'Wear sunglasses'
        }
    elif uv_index <= 7:
        return {
            'level': 'High',
            'color': 'orange',
            'protection': 'Use sunscreen'
        }
    elif uv_index <= 10:
        return {
            'level': 'Very High',
            'color': 'red',
            'protection': 'Seek shade'
        }
    else:
        return {
            'level': 'Extreme',
            'color': 'purple',
            'protection': 'Avoid sun exposure'
        }

def get_air_quality_description(aqi: int) -> Dict[str, str]:
    """
    Get air quality description based on AQI.
    
    Args:
        aqi (int): Air Quality Index
        
    Returns:
        dict: Air quality information
    """
    if aqi <= 50:
        return {
            'level': 'Good',
            'color': 'green',
            'health': 'Air quality is satisfactory'
        }
    elif aqi <= 100:
        return {
            'level': 'Moderate',
            'color': 'yellow',
            'health': 'Air quality is acceptable'
        }
    elif aqi <= 150:
        return {
            'level': 'Unhealthy for Sensitive Groups',
            'color': 'orange',
            'health': 'Sensitive individuals may experience effects'
        }
    elif aqi <= 200:
        return {
            'level': 'Unhealthy',
            'color': 'red',
            'health': 'Everyone may experience effects'
        }
    elif aqi <= 300:
        return {
            'level': 'Very Unhealthy',
            'color': 'purple',
            'health': 'Health warnings of emergency conditions'
        }
    else:
        return {
            'level': 'Hazardous',
            'color': 'maroon',
            'health': 'Emergency conditions'
        }

def format_timestamp(timestamp: str, format_type: str = 'datetime') -> str:
    """
    Format timestamp for display.
    
    Args:
        timestamp (str): ISO timestamp
        format_type (str): Format type (datetime, date, time)
        
    Returns:
        str: Formatted timestamp
    """
    try:
        dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
        
        if format_type == 'date':
            return dt.strftime('%Y-%m-%d')
        elif format_type == 'time':
            return dt.strftime('%H:%M:%S')
        else:
            return dt.strftime('%Y-%m-%d %H:%M:%S')
    except (ValueError, AttributeError):
        return timestamp

def get_daily_forecast_summary(forecasts: List[Dict]) -> List[Dict]:
    """
    Summarize hourly forecasts into daily summaries.
    
    Args:
        forecasts (List[Dict]): Hourly forecast data
        
    Returns:
        List[Dict]: Daily forecast summaries
    """
    daily_data = {}
    
    for forecast in forecasts:
        date = forecast['datetime'][:10]  # Extract date part
        
        if date not in daily_data:
            daily_data[date] = {
                'date': date,
                'temps': [],
                'humidity': [],
                'wind_speed': [],
                'descriptions': [],
                'rain': 0,
                'snow': 0
            }
        
        day_data = daily_data[date]
        day_data['temps'].append(forecast['temperature'])
        day_data['humidity'].append(forecast['humidity'])
        day_data['wind_speed'].append(forecast['wind_speed'])
        day_data['descriptions'].append(forecast['description'])
        day_data['rain'] += forecast.get('rain', 0)
        day_data['snow'] += forecast.get('snow', 0)
    
    # Calculate daily summaries
    summaries = []
    for date, data in daily_data.items():
        summary = {
            'date': date,
            'temp_min': min(data['temps']),
            'temp_max': max(data['temps']),
            'temp_avg': sum(data['temps']) / len(data['temps']),
            'humidity_avg': sum(data['humidity']) / len(data['humidity']),
            'wind_speed_avg': sum(data['wind_speed']) / len(data['wind_speed']),
            'description': max(set(data['descriptions']), key=data['descriptions'].count),
            'rain_total': data['rain'],
            'snow_total': data['snow']
        }
        summaries.append(summary)
    
    return sorted(summaries, key=lambda x: x['date'])

def validate_city_name(city: str) -> bool:
    """
    Validate city name format.
    
    Args:
        city (str): City name to validate
        
    Returns:
        bool: True if valid, False otherwise
    """
    if not city or not isinstance(city, str):
        return False
    
    # Remove extra whitespace and check length
    city_clean = city.strip()
    
    if len(city_clean) < 2 or len(city_clean) > 50:
        return False
    
    # Check for valid characters (letters, spaces, hyphens, apostrophes)
    import re
    pattern = r"^[a-zA-Z\s\-']+$"
    return bool(re.match(pattern, city_clean))

def extract_city_from_query(query: str) -> Optional[str]:
    """
    Extract city name from natural language query.
    
    Args:
        query (str): Natural language query
        
    Returns:
        Optional[str]: Extracted city name or None
    """
    import re
    
    # Common patterns for city extraction
    patterns = [
        r'weather (?:in|for|at) ([A-Za-z\s\-\'\.]+)',
        r'(?:in|for|at) ([A-Za-z\s\-\'\.]+) weather',
        r'([A-Za-z\s\-\'\.]+) weather',
        r'forecast (?:for|in) ([A-Za-z\s\-\'\.]+)',
        r'alerts (?:for|in) ([A-Za-z\s\-\'\.]+)',
    ]
    
    for pattern in patterns:
        match = re.search(pattern, query, re.IGNORECASE)
        if match:
            city = match.group(1).strip()
            if validate_city_name(city):
                return city
    
    return None

def get_weather_emoji(description: str) -> str:
    """
    Get appropriate emoji for weather description.
    
    Args:
        description (str): Weather description
        
    Returns:
        str: Weather emoji
    """
    description_lower = description.lower()
    
    if 'clear' in description_lower:
        return '☀️'
    elif 'cloud' in description_lower:
        if 'few' in description_lower:
            return '🌤️'
        else:
            return '☁️'
    elif 'rain' in description_lower:
        if 'light' in description_lower:
            return '🌦️'
        else:
            return '🌧️'
    elif 'snow' in description_lower:
        return '❄️'
    elif 'thunderstorm' in description_lower:
        return '⛈️'
    elif 'mist' in description_lower or 'fog' in description_lower:
        return '🌫️'
    elif 'wind' in description_lower:
        return '💨'
    else:
        return '🌡️'

def create_weather_summary(weather_data: Dict) -> str:
    """
    Create a human-readable weather summary.
    
    Args:
        weather_data (Dict): Weather data dictionary
        
    Returns:
        str: Weather summary string
    """
    if 'error' in weather_data:
        return f"Error: {weather_data['error']}"
    
    city = weather_data.get('city', 'Unknown')
    temp = weather_data.get('temperature', 0)
    feels_like = weather_data.get('feels_like', 0)
    description = weather_data.get('description', 'unknown conditions')
    humidity = weather_data.get('humidity', 0)
    wind_speed = weather_data.get('wind_speed', 0)
    
    emoji = get_weather_emoji(description)
    
    summary = (
        f"{emoji} Current weather in {city}:\n"
        f"🌡️ Temperature: {round(temp)}°C (feels like {round(feels_like)}°C)\n"
        f"☁️ Conditions: {description}\n"
        f"💧 Humidity: {humidity}%\n"
        f"💨 Wind: {round(wind_speed, 1)} m/s"
    )
    
    return summary
445 lines•12.9 KB
python

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer