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
analytics.py
utils/analytics.py
Raw Download
Find: Go to:
#!/usr/bin/env python3
"""
Weather Chatbot Analytics Module
================================

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: Advanced weather analytics and data visualization utilities
"""

import json
import math
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
from collections import defaultdict
import statistics

class WeatherAnalytics:
    """Advanced weather analytics and insights generator"""
    
    def __init__(self):
        self.temp_unit = 'celsius'
        self.wind_unit = 'ms'
    
    def calculate_weather_trends(self, historical_data: List[Dict]) -> Dict:
        """
        Calculate weather trends from historical data.
        
        Args:
            historical_data: List of historical weather data points
            
        Returns:
            Dictionary containing trend analysis
        """
        if not historical_data:
            return {'error': 'No historical data available'}
        
        # Extract temperature data
        temperatures = [data.get('temperature', 0) for data in historical_data]
        humidity_data = [data.get('humidity', 0) for data in historical_data]
        wind_data = [data.get('wind_speed', 0) for data in historical_data]
        
        # Calculate statistics
        trends = {
            'temperature': {
                'current': temperatures[-1] if temperatures else 0,
                'average': statistics.mean(temperatures) if temperatures else 0,
                'min': min(temperatures) if temperatures else 0,
                'max': max(temperatures) if temperatures else 0,
                'trend': self._calculate_trend(temperatures),
                'volatility': statistics.stdev(temperatures) if len(temperatures) > 1 else 0
            },
            'humidity': {
                'current': humidity_data[-1] if humidity_data else 0,
                'average': statistics.mean(humidity_data) if humidity_data else 0,
                'trend': self._calculate_trend(humidity_data),
                'volatility': statistics.stdev(humidity_data) if len(humidity_data) > 1 else 0
            },
            'wind_speed': {
                'current': wind_data[-1] if wind_data else 0,
                'average': statistics.mean(wind_data) if wind_data else 0,
                'trend': self._calculate_trend(wind_data),
                'volatility': statistics.stdev(wind_data) if len(wind_data) > 1 else 0
            },
            'data_points': len(historical_data),
            'period': self._get_period_description(historical_data)
        }
        
        return trends
    
    def _calculate_trend(self, data_points: List[float]) -> str:
        """Calculate trend direction from data points"""
        if len(data_points) < 2:
            return 'stable'
        
        # Simple linear regression to determine trend
        n = len(data_points)
        x = list(range(n))
        
        # Calculate slope
        x_mean = statistics.mean(x)
        y_mean = statistics.mean(data_points)
        
        numerator = sum((x[i] - x_mean) * (data_points[i] - y_mean) for i in range(n))
        denominator = sum((x[i] - x_mean) ** 2 for i in range(n))
        
        if denominator == 0:
            return 'stable'
        
        slope = numerator / denominator
        
        # Determine trend based on slope
        if abs(slope) < 0.1:
            return 'stable'
        elif slope > 0:
            return 'rising'
        else:
            return 'falling'
    
    def _get_period_description(self, data_points: List[Dict]) -> str:
        """Get human-readable period description"""
        if not data_points:
            return 'No data'
        
        timestamps = [data.get('timestamp') for data in data_points if data.get('timestamp')]
        if not timestamps:
            return 'Unknown period'
        
        try:
            # Parse timestamps (assuming ISO format)
            dates = [datetime.fromisoformat(ts.replace('Z', '+00:00')) for ts in timestamps]
            start_date = min(dates)
            end_date = max(dates)
            
            duration = end_date - start_date
            
            if duration.days == 0:
                return f"{duration.seconds // 3600} hours"
            elif duration.days < 7:
                return f"{duration.days} days"
            elif duration.days < 30:
                return f"{duration.days // 7} weeks"
            else:
                return f"{duration.days // 30} months"
        except:
            return f"{len(data_points)} data points"
    
    def generate_weather_insights(self, current_weather: Dict, forecast_data: Dict) -> List[Dict]:
        """
        Generate intelligent weather insights and recommendations.
        
        Args:
            current_weather: Current weather data
            forecast_data: Forecast weather data
            
        Returns:
            List of weather insights and recommendations
        """
        insights = []
        
        if not current_weather or 'error' in current_weather:
            return insights
        
        temp = current_weather.get('temperature', 0)
        humidity = current_weather.get('humidity', 0)
        wind_speed = current_weather.get('wind_speed', 0)
        description = current_weather.get('description', '').lower()
        
        # Temperature insights
        if temp > 35:
            insights.append({
                'type': 'warning',
                'category': 'temperature',
                'title': 'Extreme Heat Alert',
                'message': f"Temperature is {temp}°C. Stay hydrated and avoid prolonged sun exposure.",
                'icon': '🔥',
                'priority': 'high'
            })
        elif temp < 0:
            insights.append({
                'type': 'warning',
                'category': 'temperature',
                'title': 'Freezing Conditions',
                'message': f"Temperature is {temp}°C. Dress warmly and watch for ice.",
                'icon': '❄️',
                'priority': 'medium'
            })
        
        # Humidity insights
        if humidity > 85:
            insights.append({
                'type': 'info',
                'category': 'humidity',
                'title': 'High Humidity',
                'message': f"Humidity is {humidity}%. It may feel warmer than actual temperature.",
                'icon': '💧',
                'priority': 'low'
            })
        
        # Wind insights
        if wind_speed > 15:
            insights.append({
                'type': 'warning',
                'category': 'wind',
                'title': 'Strong Winds',
                'message': f"Wind speed is {wind_speed} m/s. Secure loose objects outdoors.",
                'icon': '💨',
                'priority': 'medium'
            })
        
        # Weather condition insights
        if 'rain' in description or 'shower' in description:
            insights.append({
                'type': 'info',
                'category': 'precipitation',
                'title': 'Rain Expected',
                'message': "Carry an umbrella and allow extra travel time.",
                'icon': '🌧️',
                'priority': 'low'
            })
        elif 'snow' in description:
            insights.append({
                'type': 'warning',
                'category': 'precipitation',
                'title': 'Snow Conditions',
                'message': "Drive carefully and dress warmly for snow conditions.",
                'icon': '❄️',
                'priority': 'medium'
            })
        elif 'clear' in description:
            insights.append({
                'type': 'info',
                'category': 'conditions',
                'title': 'Clear Skies',
                'message': "Great weather for outdoor activities!",
                'icon': '☀️',
                'priority': 'low'
            })
        
        # Forecast-based insights
        if forecast_data and 'forecasts' in forecast_data:
            forecasts = forecast_data['forecasts'][:8]  # Next 24 hours
            
            # Check for temperature changes
            if forecasts:
                temps = [f.get('temperature', 0) for f in forecasts]
                temp_change = max(temps) - min(temps)
                
                if temp_change > 10:
                    insights.append({
                        'type': 'info',
                        'category': 'forecast',
                        'title': 'Significant Temperature Change',
                        'message': f"Temperature will vary by {round(temp_change)}°C in the next 24 hours.",
                        'icon': '🌡️',
                        'priority': 'medium'
                    })
                
                # Check for rain in forecast
                rain_forecasts = [f for f in forecasts if 'rain' in f.get('description', '').lower()]
                if rain_forecasts:
                    insights.append({
                        'type': 'info',
                        'category': 'forecast',
                        'title': 'Rain in Forecast',
                        'message': f"Rain expected in {len(rain_forecasts)} of the next 8 forecast periods.",
                        'icon': '🌦️',
                        'priority': 'low'
                    })
        
        return insights
    
    def calculate_comfort_index(self, weather_data: Dict) -> Dict:
        """
        Calculate weather comfort index based on multiple factors.
        
        Args:
            weather_data: Weather data dictionary
            
        Returns:
            Comfort index information
        """
        if not weather_data or 'error' in weather_data:
            return {'error': 'Invalid weather data'}
        
        temp = weather_data.get('temperature', 20)
        humidity = weather_data.get('humidity', 50)
        wind_speed = weather_data.get('wind_speed', 0)
        
        # Temperature comfort score (optimal: 20-25°C)
        if 20 <= temp <= 25:
            temp_score = 100
        elif 15 <= temp <= 30:
            temp_score = 80
        elif 10 <= temp <= 35:
            temp_score = 60
        else:
            temp_score = 30
        
        # Humidity comfort score (optimal: 40-60%)
        if 40 <= humidity <= 60:
            humidity_score = 100
        elif 30 <= humidity <= 70:
            humidity_score = 80
        elif 20 <= humidity <= 80:
            humidity_score = 60
        else:
            humidity_score = 30
        
        # Wind comfort score (optimal: 0-5 m/s)
        if 0 <= wind_speed <= 5:
            wind_score = 100
        elif 5 <= wind_speed <= 10:
            wind_score = 80
        elif 10 <= wind_speed <= 15:
            wind_score = 60
        else:
            wind_score = 30
        
        # Calculate overall comfort index
        comfort_index = (temp_score * 0.5 + humidity_score * 0.3 + wind_score * 0.2)
        
        # Determine comfort level
        if comfort_index >= 80:
            comfort_level = 'Excellent'
            color = 'green'
            recommendation = 'Perfect weather for most activities!'
        elif comfort_index >= 60:
            comfort_level = 'Good'
            color = 'blue'
            recommendation = 'Comfortable conditions for outdoor activities.'
        elif comfort_index >= 40:
            comfort_level = 'Fair'
            color = 'yellow'
            recommendation = 'Acceptable conditions with some discomfort possible.'
        else:
            comfort_level = 'Poor'
            color = 'red'
            recommendation = 'Uncomfortable conditions. Consider indoor activities.'
        
        return {
            'comfort_index': round(comfort_index),
            'comfort_level': comfort_level,
            'color': color,
            'recommendation': recommendation,
            'components': {
                'temperature': round(temp_score),
                'humidity': round(humidity_score),
                'wind': round(wind_score)
            }
        }
    
    def compare_cities_weather(self, cities_data: Dict[str, Dict]) -> Dict:
        """
        Compare weather between multiple cities.
        
        Args:
            cities_data: Dictionary with city names as keys and weather data as values
            
        Returns:
            Comparison analysis
        """
        if not cities_data:
            return {'error': 'No city data provided'}
        
        comparison = {
            'cities': list(cities_data.keys()),
            'metrics': {},
            'rankings': {},
            'best_for': {},
            'summary': {}
        }
        
        # Extract metrics for comparison
        temperatures = {}
        humidity_levels = {}
        wind_speeds = {}
        
        for city, data in cities_data.items():
            if 'error' not in data:
                temperatures[city] = data.get('temperature', 0)
                humidity_levels[city] = data.get('humidity', 0)
                wind_speeds[city] = data.get('wind_speed', 0)
        
        # Temperature comparison
        if temperatures:
            comparison['metrics']['temperature'] = temperatures
            comparison['rankings']['hottest'] = max(temperatures, key=temperatures.get)
            comparison['rankings']['coldest'] = min(temperatures, key=temperatures.get)
            comparison['best_for']['warm_weather'] = max(temperatures, key=temperatures.get)
            comparison['best_for']['cool_weather'] = min(temperatures, key=temperatures.get)
        
        # Humidity comparison
        if humidity_levels:
            comparison['metrics']['humidity'] = humidity_levels
            comparison['rankings']['most_humid'] = max(humidity_levels, key=humidity_levels.get)
            comparison['rankings']['least_humid'] = min(humidity_levels, key=humidity_levels.get)
            comparison['best_for']['dry_conditions'] = min(humidity_levels, key=humidity_levels.get)
        
        # Wind comparison
        if wind_speeds:
            comparison['metrics']['wind_speed'] = wind_speeds
            comparison['rankings']['windiest'] = max(wind_speeds, key=wind_speeds.get)
            comparison['rankings']['calmest'] = min(wind_speeds, key=wind_speeds.get)
            comparison['best_for']['calm_conditions'] = min(wind_speeds, key=wind_speeds.get)
        
        # Generate summary
        comparison['summary'] = {
            'total_cities': len(cities_data),
            'data_available': len([c for c in cities_data.values() if 'error' not in c]),
            'average_temperature': round(statistics.mean(temperatures.values()), 1) if temperatures else 0,
            'average_humidity': round(statistics.mean(humidity_levels.values()), 1) if humidity_levels else 0,
            'average_wind': round(statistics.mean(wind_speeds.values()), 1) if wind_speeds else 0
        }
        
        return comparison
    
    def generate_weather_report(self, weather_data: Dict, forecast_data: Dict = None) -> str:
        """
        Generate comprehensive weather report.
        
        Args:
            weather_data: Current weather data
            forecast_data: Forecast data (optional)
            
        Returns:
            Formatted weather report string
        """
        if not weather_data or 'error' in weather_data:
            return "Unable to generate weather report due to data errors."
        
        city = weather_data.get('city', 'Unknown')
        temp = weather_data.get('temperature', 0)
        feels_like = weather_data.get('feels_like', 0)
        humidity = weather_data.get('humidity', 0)
        pressure = weather_data.get('pressure', 0)
        wind_speed = weather_data.get('wind_speed', 0)
        visibility = weather_data.get('visibility', 0)
        description = weather_data.get('description', 'unknown')
        timestamp = weather_data.get('timestamp', '')
        
        # Generate comfort index
        comfort = self.calculate_comfort_index(weather_data)
        
        # Generate insights
        insights = self.generate_weather_insights(weather_data, forecast_data)
        
        # Build report
        report = f"""
🌍 WEATHER REPORT FOR {city.upper()}
{'='*50}

📊 CURRENT CONDITIONS:
  • Temperature: {temp}°C (feels like {feels_like}°C)
  • Conditions: {description}
  • Humidity: {humidity}%
  • Pressure: {pressure} hPa
  • Wind Speed: {wind_speed} m/s
  • Visibility: {visibility} km
  • Updated: {timestamp}

🎯 COMFORT INDEX: {comfort['comfort_index']}/100 - {comfort['comfort_level']}
  • Recommendation: {comfort['recommendation']}

💡 INSIGHTS & RECOMMENDATIONS:
"""
        
        for insight in insights[:5]:  # Limit to top 5 insights
            report += f"  • {insight['icon']} {insight['title']}: {insight['message']}\n"
        
        if forecast_data and 'forecasts' in forecast_data:
            report += f"\n📅 24-HOUR FORECAST:\n"
            for forecast in forecast_data['forecasts'][:8]:  # Next 24 hours
                dt = forecast.get('datetime', '')
                temp_f = forecast.get('temperature', 0)
                desc = forecast.get('description', '')
                report += f"  • {dt}: {temp_f}°C - {desc}\n"
        
        report += f"\n{'='*50}\n"
        report += f"Report generated by Weather Chatbot - RSK World (https://rskworld.in)\n"
        report += f"© 2026 RSK World. All rights reserved.\n"
        
        return report.strip()
    
    def calculate_weather_statistics(self, data_points: List[Dict]) -> Dict:
        """
        Calculate comprehensive weather statistics.
        
        Args:
            data_points: List of weather data points
            
        Returns:
            Statistical analysis
        """
        if not data_points:
            return {'error': 'No data available for analysis'}
        
        # Extract all metrics
        temperatures = [d.get('temperature', 0) for d in data_points]
        humidity = [d.get('humidity', 0) for d in data_points]
        pressure = [d.get('pressure', 0) for d in data_points]
        wind_speed = [d.get('wind_speed', 0) for d in data_points]
        
        stats = {
            'data_points_count': len(data_points),
            'period_analysis': self._get_period_description(data_points),
            'temperature': self._calculate_metric_stats(temperatures, 'Temperature'),
            'humidity': self._calculate_metric_stats(humidity, 'Humidity'),
            'pressure': self._calculate_metric_stats(pressure, 'Pressure'),
            'wind_speed': self._calculate_metric_stats(wind_speed, 'Wind Speed'),
            'correlations': self._calculate_correlations(data_points)
        }
        
        return stats
    
    def _calculate_metric_stats(self, values: List[float], metric_name: str) -> Dict:
        """Calculate statistics for a specific metric"""
        if not values:
            return {'error': f'No {metric_name.lower()} data available'}
        
        return {
            'mean': round(statistics.mean(values), 2),
            'median': round(statistics.median(values), 2),
            'min': min(values),
            'max': max(values),
            'std_dev': round(statistics.stdev(values), 2) if len(values) > 1 else 0,
            'variance': round(statistics.variance(values), 2) if len(values) > 1 else 0,
            'range': max(values) - min(values),
            'quartiles': {
                'q1': round(statistics.quantiles(values, n=4)[0], 2) if len(values) > 3 else 0,
                'q2': round(statistics.median(values), 2),
                'q3': round(statistics.quantiles(values, n=4)[2], 2) if len(values) > 3 else 0
            }
        }
    
    def _calculate_correlations(self, data_points: List[Dict]) -> Dict:
        """Calculate correlations between weather metrics"""
        correlations = {}
        
        # Extract metrics
        temps = [d.get('temperature', 0) for d in data_points]
        humidity = [d.get('humidity', 0) for d in data_points]
        pressure = [d.get('pressure', 0) for d in data_points]
        wind = [d.get('wind_speed', 0) for d in data_points]
        
        # Calculate correlations
        if len(temps) > 1 and len(humidity) > 1:
            correlations['temperature_humidity'] = self._correlation_coefficient(temps, humidity)
        
        if len(temps) > 1 and len(pressure) > 1:
            correlations['temperature_pressure'] = self._correlation_coefficient(temps, pressure)
        
        if len(temps) > 1 and len(wind) > 1:
            correlations['temperature_wind'] = self._correlation_coefficient(temps, wind)
        
        if len(humidity) > 1 and len(pressure) > 1:
            correlations['humidity_pressure'] = self._correlation_coefficient(humidity, pressure)
        
        return correlations
    
    def _correlation_coefficient(self, x: List[float], y: List[float]) -> float:
        """Calculate Pearson correlation coefficient"""
        if len(x) != len(y) or len(x) < 2:
            return 0.0
        
        n = len(x)
        x_mean = statistics.mean(x)
        y_mean = statistics.mean(y)
        
        numerator = sum((x[i] - x_mean) * (y[i] - y_mean) for i in range(n))
        
        x_std = math.sqrt(sum((x[i] - x_mean) ** 2 for i in range(n)))
        y_std = math.sqrt(sum((y[i] - y_mean) ** 2 for i in range(n)))
        
        if x_std == 0 or y_std == 0:
            return 0.0
        
        return numerator / (x_std * y_std)
564 lines•22 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