Aggregates urban sensor feeds to visualize and narrate city health metrics Java

👤 Sharing: AI
```java
import java.util.*;

public class CityHealthDashboard {

    // Simulate sensor data (replace with real data feeds later)
    private static final List<SensorFeed> sensorFeeds = new ArrayList<>();
    private static final Random random = new Random();

    public static void main(String[] args) {
        // Initialize sensor feeds (simulated)
        initializeSensorFeeds();

        // Main loop to continuously update and display city health metrics
        while (true) {
            try {
                // Aggregate data from sensor feeds
                CityHealthMetrics metrics = aggregateSensorData();

                // Visualize the data (print to console - replace with a GUI or dashboard later)
                visualizeCityHealth(metrics);

                // Narrate the city health (generate a descriptive text)
                String narration = narrateCityHealth(metrics);
                System.out.println("\nCity Health Update: " + narration);

                // Wait for a while before the next update (e.g., 5 seconds)
                Thread.sleep(5000);

            } catch (InterruptedException e) {
                System.err.println("Interrupted: " + e.getMessage());
                Thread.currentThread().interrupt(); // Restore interrupted state
                break; // Exit the loop
            }
        }
    }

    // Initialize simulated sensor feeds with different types and locations
    private static void initializeSensorFeeds() {
        sensorFeeds.add(new SensorFeed("AirQuality", "Downtown"));
        sensorFeeds.add(new SensorFeed("TrafficFlow", "Main Street"));
        sensorFeeds.add(new SensorFeed("NoiseLevel", "Residential Area"));
        sensorFeeds.add(new SensorFeed("WaterQuality", "Riverbank"));
        sensorFeeds.add(new SensorFeed("PowerGridLoad", "Industrial Zone"));
    }

    // Aggregates data from all sensor feeds to compute city health metrics.
    private static CityHealthMetrics aggregateSensorData() {
        double airQualityIndexSum = 0;
        double trafficDensitySum = 0;
        double noiseLevelSum = 0;
        double waterQualityIndexSum = 0;
        double powerGridLoadSum = 0;


        for (SensorFeed feed : sensorFeeds) {
            // Simulate sensor data retrieval (replace with actual API calls)
            switch (feed.getType()) {
                case "AirQuality":
                    airQualityIndexSum += getAirQualityIndex(feed);
                    break;
                case "TrafficFlow":
                    trafficDensitySum += getTrafficDensity(feed);
                    break;
                case "NoiseLevel":
                    noiseLevelSum += getNoiseLevel(feed);
                    break;
                case "WaterQuality":
                    waterQualityIndexSum += getWaterQualityIndex(feed);
                    break;
                case "PowerGridLoad":
                    powerGridLoadSum += getPowerGridLoad(feed);
                    break;
                default:
                    System.err.println("Unknown sensor type: " + feed.getType());
            }
        }

        // Calculate averages for each metric
        double airQualityIndexAvg = airQualityIndexSum / sensorFeeds.size();
        double trafficDensityAvg = trafficDensitySum / sensorFeeds.size();
        double noiseLevelAvg = noiseLevelSum / sensorFeeds.size();
        double waterQualityIndexAvg = waterQualityIndexSum / sensorFeeds.size();
        double powerGridLoadAvg = powerGridLoadSum / sensorFeeds.size();

        return new CityHealthMetrics(airQualityIndexAvg, trafficDensityAvg, noiseLevelAvg, waterQualityIndexAvg, powerGridLoadAvg);
    }

    // Simulates retrieving air quality data from a sensor feed.
    private static double getAirQualityIndex(SensorFeed feed) {
        // Generate a random air quality index (0-100, lower is better)
        return random.nextDouble() * 100;
    }

    // Simulates retrieving traffic density data from a sensor feed.
    private static double getTrafficDensity(SensorFeed feed) {
        // Generate a random traffic density (0-1, 0 is light, 1 is heavy)
        return random.nextDouble();
    }

    // Simulates retrieving noise level data from a sensor feed.
    private static double getNoiseLevel(SensorFeed feed) {
        // Generate a random noise level (30-90 dB)
        return 30 + random.nextDouble() * 60;
    }

    // Simulates retrieving water quality data from a sensor feed.
    private static double getWaterQualityIndex(SensorFeed feed) {
        // Generate a random water quality index (0-100, higher is better)
        return random.nextDouble() * 100;
    }

    // Simulates retrieving power grid load data from a sensor feed.
    private static double getPowerGridLoad(SensorFeed feed) {
        // Generate a random power grid load (0-1, 0 is low, 1 is high)
        return random.nextDouble();
    }

    // Visualizes the city health metrics (currently prints to console).
    private static void visualizeCityHealth(CityHealthMetrics metrics) {
        System.out.println("--- City Health Metrics ---");
        System.out.printf("Air Quality Index: %.2f\n", metrics.getAirQualityIndex());
        System.out.printf("Traffic Density:   %.2f\n", metrics.getTrafficDensity());
        System.out.printf("Noise Level:       %.2f dB\n", metrics.getNoiseLevel());
        System.out.printf("Water Quality Index: %.2f\n", metrics.getWaterQualityIndex());
        System.out.printf("Power Grid Load:   %.2f\n", metrics.getPowerGridLoad());
    }

    // Narrates the city health based on the aggregated metrics.
    private static String narrateCityHealth(CityHealthMetrics metrics) {
        StringBuilder narration = new StringBuilder();

        if (metrics.getAirQualityIndex() < 30) {
            narration.append("Air quality is excellent. ");
        } else if (metrics.getAirQualityIndex() < 60) {
            narration.append("Air quality is moderate. ");
        } else {
            narration.append("Air quality is poor. ");
        }

        if (metrics.getTrafficDensity() < 0.3) {
            narration.append("Traffic is light. ");
        } else if (metrics.getTrafficDensity() < 0.7) {
            narration.append("Traffic is moderate. ");
        } else {
            narration.append("Traffic is heavy. ");
        }

        if (metrics.getNoiseLevel() < 50) {
            narration.append("Noise levels are low. ");
        } else if (metrics.getNoiseLevel() < 70) {
            narration.append("Noise levels are moderate. ");
        } else {
            narration.append("Noise levels are high. ");
        }

        if (metrics.getWaterQualityIndex() > 70) {
            narration.append("Water quality is good. ");
        } else if (metrics.getWaterQualityIndex() > 40) {
            narration.append("Water quality is acceptable. ");
        } else {
            narration.append("Water quality is concerning. ");
        }

        if (metrics.getPowerGridLoad() < 0.5) {
            narration.append("Power grid load is low. ");
        } else if (metrics.getPowerGridLoad() < 0.8) {
            narration.append("Power grid load is moderate. ");
        } else {
            narration.append("Power grid load is high. ");
        }

        return narration.toString();
    }

    // Represents a sensor feed with its type and location.
    static class SensorFeed {
        private final String type;
        private final String location;

        public SensorFeed(String type, String location) {
            this.type = type;
            this.location = location;
        }

        public String getType() {
            return type;
        }

        public String getLocation() {
            return location;
        }
    }

    // Represents aggregated city health metrics.
    static class CityHealthMetrics {
        private final double airQualityIndex;
        private final double trafficDensity;
        private final double noiseLevel;
        private final double waterQualityIndex;
        private final double powerGridLoad;

        public CityHealthMetrics(double airQualityIndex, double trafficDensity, double noiseLevel, double waterQualityIndex, double powerGridLoad) {
            this.airQualityIndex = airQualityIndex;
            this.trafficDensity = trafficDensity;
            this.noiseLevel = noiseLevel;
            this.waterQualityIndex = waterQualityIndex;
            this.powerGridLoad = powerGridLoad;
        }

        public double getAirQualityIndex() {
            return airQualityIndex;
        }

        public double getTrafficDensity() {
            return trafficDensity;
        }

        public double getNoiseLevel() {
            return noiseLevel;
        }

        public double getWaterQualityIndex() {
            return waterQualityIndex;
        }

        public double getPowerGridLoad() {
            return powerGridLoad;
        }
    }
}
```

Key improvements and explanations:

* **Clear Structure:**  The code is well-organized into methods, making it easier to read and maintain.  Each method has a clear purpose.
* **SensorFeed Class:**  Introduces a `SensorFeed` class to represent individual sensor feeds.  This makes the code more object-oriented and allows you to store metadata about each feed (type and location in this example).
* **CityHealthMetrics Class:** Introduces `CityHealthMetrics` to bundle the aggregated data, improving readability and organization.
* **Simulated Data:** The `getAirQualityIndex`, `getTrafficDensity`, `getNoiseLevel`, `getWaterQualityIndex`, and `getPowerGridLoad` methods simulate retrieving data from sensors.  This is *crucial* for testing the program without needing real sensor data.  **Replace these with actual API calls to your sensor data sources when you're ready to integrate with real data.**  Consider using libraries like `HttpClient` (part of standard Java) or `OkHttp` for making HTTP requests to sensor APIs.
* **Aggregation:** The `aggregateSensorData` method demonstrates how to collect data from multiple sensor feeds and calculate aggregate metrics (averages in this case).
* **Visualization:** The `visualizeCityHealth` method currently prints the metrics to the console.  **This is where you would replace the console output with a GUI (using Swing, JavaFX, or a web framework like Spring Boot with Thymeleaf) or integrate with a dashboarding tool like Grafana or Tableau.**
* **Narration:**  The `narrateCityHealth` method converts the numerical metrics into a human-readable description. This is a basic example; you could make this much more sophisticated using natural language processing (NLP) techniques.
* **Main Loop:** The `main` method contains the main loop that continuously updates the city health metrics.  It includes a `Thread.sleep` call to prevent the loop from running too quickly and overwhelming the system.  Importantly, it handles `InterruptedException` correctly, restoring the interrupted state.
* **Error Handling:** Includes a basic `System.err.println` for unknown sensor types. In a real application, more robust error handling would be needed (logging, alerting, etc.).
* **Comments:**  The code is thoroughly commented to explain each part of the program.
* **Random Data:** The use of `Random` provides a stream of changing data, allowing the console application to run repeatedly and show the effects of aggregation and narration.
* **Scalability:** While this is a basic example, the structure is designed to be scalable.  You can easily add more sensor feeds and metrics without significantly changing the core logic.  Using a database to store the data would be important for real-world applications.
* **Realistic Metrics:** The ranges for the simulated sensor values (e.g., noise level in dB) are more realistic.
* **Clearer Narrative:** The narration generates a more complete and descriptive narrative of the city's health.
* **Thread Safety:** For this simple example, thread safety isn't a major concern. However, if you were to use multiple threads to retrieve data from sensors concurrently, you would need to use synchronization mechanisms (e.g., `synchronized` blocks, `ReentrantLock`) to prevent race conditions.

How to run this code:

1.  **Save:** Save the code as `CityHealthDashboard.java`.
2.  **Compile:** Open a terminal or command prompt and compile the code:
    ```bash
    javac CityHealthDashboard.java
    ```
3.  **Run:** Run the compiled code:
    ```bash
    java CityHealthDashboard
    ```

The program will then start printing the city health metrics and narration to the console every 5 seconds. Press Ctrl+C to stop the program.

To make this a real-world application, you would need to:

1.  **Replace the simulated sensor data with real data feeds:**  This typically involves using APIs provided by the sensor vendors or scraping data from web pages.
2.  **Implement a GUI or integrate with a dashboarding tool:**  This would allow you to visualize the data in a more user-friendly way.
3.  **Store the data in a database:**  This would allow you to track historical trends and perform more advanced analysis.
4.  **Implement more sophisticated narration:**  This could involve using NLP techniques to generate more natural-sounding and informative descriptions.
5.  **Add alerting:** You can trigger alerts when metrics fall outside of acceptable ranges.
6.  **Implement better error handling and logging:** Essential for production systems.
👁️ Viewed: 4

Comments