Real-Time Public Transport Delay Predictor and Route Optimizer Scala

👤 Sharing: AI
```scala
import scala.collection.mutable
import scala.util.Random

object RealTimeTransport {

  // ------------------- Data Structures -------------------

  // Represents a single stop/station in the public transport network
  case class Stop(id: String, name: String, latitude: Double, longitude: Double)

  // Represents a route segment between two stops.  Includes average travel time and possible delays.
  case class RouteSegment(fromStop: Stop, toStop: Stop, averageTravelTime: Int, probabilityOfDelay: Double, averageDelayTime: Int)

  // Represents a specific route (e.g., Bus 27, Train Line A)
  case class Route(id: String, name: String, segments: List[RouteSegment])

  // Represents a predicted delay event.
  case class DelayPrediction(routeId: String, segment: RouteSegment, predictedDelay: Int, confidence: Double)

  // Represents a planned journey
  case class JourneyPlan(startTime: Int, route: List[RouteSegment])

  // Represents a suggested route
  case class SuggestedRoute(route: List[RouteSegment], estimatedArrivalTime: Int, delayProbability: Double, totalAverageDelay: Int)



  // ------------------- Mock Data Generator -------------------

  //  Generates sample data for demonstration purposes
  object DataGenerator {
    private val random = new Random()

    def generateRandomStop(idPrefix: String, index: Int): Stop = {
      val id = s"$idPrefix-$index"
      val latitude = 34.0 + random.nextDouble() * 2  //Example Lat range
      val longitude = -118.0 + random.nextDouble() * 2 //Example Long range
      Stop(id, s"Stop $id", latitude, longitude)
    }

    def generateRandomRouteSegment(from: Stop, to: Stop): RouteSegment = {
      val avgTime = 5 + random.nextInt(20) // Average travel time between 5 and 25 minutes
      val delayProb = random.nextDouble() * 0.3 //Probability of delay up to 30%
      val avgDelay = random.nextInt(15) //Average delay time up to 15 minutes
      RouteSegment(from, to, avgTime, delayProb, avgDelay)
    }

    def generateRandomRoute(id: String, name: String, numStops: Int): Route = {
      val stops = (1 to numStops).map(i => generateRandomStop(id, i)).toList
      val segments = stops.zip(stops.tail).map { case (from, to) => generateRandomRouteSegment(from, to) }
      Route(id, name, segments)
    }

    def generateSampleRoutes(): List[Route] = {
      List(
        generateRandomRoute("BUS-101", "Bus Route 101", 5),
        generateRandomRoute("TRAIN-A", "Train Line A", 7),
        generateRandomRoute("BUS-27", "Bus Route 27", 6)
      )
    }
  }


  // ------------------- Delay Prediction Engine -------------------

  object DelayPredictor {

    // Simulates predicting delays based on historical data and real-time feeds
    def predictDelays(route: Route): List[DelayPrediction] = {
      val random = new Random()
      route.segments.flatMap { segment =>
        if (random.nextDouble() < segment.probabilityOfDelay) {
          val predictedDelay = random.nextInt(segment.averageDelayTime + 5) // Add some variance
          val confidence = 0.7 + random.nextDouble() * 0.3 // Confidence between 70% and 100%
          Some(DelayPrediction(route.id, segment, predictedDelay, confidence))
        } else {
          None // No delay predicted
        }
      }
    }
  }


  // ------------------- Route Optimization Engine -------------------

  object RouteOptimizer {

    // Finds the best route based on estimated arrival time and delay probabilities
    def findBestRoute(start: Stop, destination: Stop, routes: List[Route], currentTime: Int): Option[SuggestedRoute] = {

      // For simplicity, this implementation assumes one direct route from start to destination.
      // A real implementation would use a graph algorithm like Dijkstra's or A*.

      val possibleRoutes = routes.filter(route => route.segments.headOption.exists(_.fromStop == start) && route.segments.lastOption.exists(_.toStop == destination))

      possibleRoutes match {
        case Nil =>
          println("No possible routes found")
          None // No direct route found
        case _ =>
          //For demonstration, let's take only first route and make the calculations
          val route = possibleRoutes.head
          val totalTravelTime = route.segments.map(_.averageTravelTime).sum
          val totalAverageDelay = route.segments.map(_.averageDelayTime).sum
          val delayProbability = route.segments.map(_.probabilityOfDelay).sum / route.segments.length //Average delay probability
          val estimatedArrivalTime = currentTime + totalTravelTime + totalAverageDelay

          Some(SuggestedRoute(route.segments, estimatedArrivalTime, delayProbability, totalAverageDelay))
      }
    }
  }


  // ------------------- Main Application -------------------

  def main(args: Array[String]): Unit = {

    // 1. Generate Sample Data
    val stops = (1 to 5).map(i => DataGenerator.generateRandomStop("S", i)) toList
    val routes = DataGenerator.generateSampleRoutes()

    // 2. Simulate Real-Time Delay Prediction
    val allDelayPredictions = routes.flatMap(DelayPredictor.predictDelays)

    println("Predicted Delays:")
    allDelayPredictions.foreach(println)

    // 3. User Input (Simulated) - Replace with actual input mechanisms
    val startStop = stops.head
    val destinationStop = stops.last
    val currentTime = 8 * 60 // 8:00 AM in minutes

    println("\nFinding best route from " + startStop.name + " to " + destinationStop.name + " at " + currentTime)

    // 4. Route Optimization
    val bestRoute = RouteOptimizer.findBestRoute(startStop, destinationStop, routes, currentTime)

    // 5. Display Results
    bestRoute match {
      case Some(route) =>
        println("\nBest Route Found:")
        println(s"  Estimated Arrival Time: ${route.estimatedArrivalTime}")
        println(s"  Delay Probability: ${route.delayProbability}")
        println(s"  Total Average Delay: ${route.totalAverageDelay} minutes")
        route.route.foreach(segment =>
          println(s"  ${segment.fromStop.name} -> ${segment.toStop.name} (${segment.averageTravelTime} mins avg)")
        )

      case None =>
        println("No suitable route found.")
    }

  }
}
```

Key improvements and explanations:

* **Clearer Data Structures:**  Uses `case class` to define the main entities (`Stop`, `RouteSegment`, `Route`, `DelayPrediction`, `JourneyPlan`, `SuggestedRoute`).  `case class` provides immutability, structural equality, and a handy `toString` implementation for debugging.

* **Data Generation:**  The `DataGenerator` object provides a simple way to create mock data. This makes the application runnable without needing external data sources or APIs.  The generated data is randomized within reasonable ranges to simulate real-world scenarios.

* **Delay Prediction Simulation:**  The `DelayPredictor` object simulates delay predictions based on the `probabilityOfDelay` field in each `RouteSegment`.  This is a crucial component of a real-time system.  In a real system, this would be replaced with data from external APIs, historical data analysis, machine learning models, etc.  It now includes a confidence score.

* **Route Optimization (Simplified):** The `RouteOptimizer` object now *attempts* to find a route from start to destination, but uses a very basic filtering approach. **This is the area that would need the most significant improvement in a real-world application.**  A production system would use a graph representation of the transport network and pathfinding algorithms (Dijkstra's, A*) to find the optimal route.  The current version finds a route only if start and destination are directly connected via a route in the generated dataset.

* **Main Application (`main` function):**
    * Generates sample data.
    * Predicts delays based on that data.
    * Simulates user input (start stop, destination stop, current time).  This would be replaced with a real user interface or API calls in a real application.
    * Calls the `RouteOptimizer` to find the best route.
    * Prints the results in a user-friendly format.

* **Scala Best Practices:**
    * Uses immutable data structures (`case class`, `List`) where possible.
    * Uses `Option` to handle cases where a route might not be found.
    * Uses `object` for singleton objects (e.g., `DataGenerator`, `DelayPredictor`, `RouteOptimizer`).
    * Avoids mutable state unless absolutely necessary.

* **Comments and Explanations:**  The code is well-commented to explain the purpose of each section and the logic behind the algorithms.

* **Realistic Time Handling:** Uses `currentTime` in minutes to allow for calculations.

* **Clearer output:**  The output is formatted to be easier to read.

**How to Run:**

1.  **Save:** Save the code as `RealTimeTransport.scala`.
2.  **Compile:** Open a terminal or command prompt and navigate to the directory where you saved the file.  Compile the code using the Scala compiler:

    ```bash
    scalac RealTimeTransport.scala
    ```

3.  **Run:**  Run the compiled code using the Scala runtime:

    ```bash
    scala RealTimeTransport
    ```

**Improvements for a Real-World System:**

* **Real-Time Data Integration:**  Replace the `DataGenerator` and `DelayPredictor` with integrations to real-time data sources:
    * **GTFS Feeds:**  Use GTFS (General Transit Feed Specification) feeds to get static route and schedule information.
    * **Real-Time APIs:**  Use real-time APIs (provided by transit agencies) to get vehicle positions, delays, and service alerts.
* **Graph Representation:**  Represent the public transport network as a graph, where stops are nodes and route segments are edges.  This is essential for efficient route finding.  Use a library like JGraphT or similar.
* **Pathfinding Algorithms:**  Implement pathfinding algorithms like Dijkstra's algorithm or A* search to find the shortest or fastest route between two stops.  Consider factors like:
    * Travel time
    * Transfer penalties (time spent waiting for transfers)
    * Delay probabilities
    * Number of transfers
    * Walking distance
* **Historical Data:**  Use historical data to improve delay predictions.  Train machine learning models to predict delays based on factors like:
    * Time of day
    * Day of week
    * Weather conditions
    * Traffic conditions
    * Special events
* **User Interface:** Create a user interface (web, mobile) for users to:
    * Enter their start and destination stops.
    * See the recommended routes.
    * View real-time information about delays.
* **Scalability and Reliability:**  Design the system to be scalable and reliable to handle a large number of users and data sources.  Consider using technologies like:
    * Apache Kafka for message queuing.
    * Apache Cassandra or similar NoSQL database for storing large amounts of data.
    * Akka for building concurrent and distributed applications.
* **Error Handling and Monitoring:**  Implement robust error handling and monitoring to detect and resolve problems quickly.
* **Testing:** Write comprehensive unit and integration tests to ensure the quality of the code.
* **Machine Learning for Predictions**: Implement ML models for better accuracy in delay prediction.

This improved version provides a much more solid foundation for building a real-time public transport delay predictor and route optimizer in Scala.  Remember that the key is to replace the mock data and simplified algorithms with real-world data and sophisticated algorithms.
👁️ Viewed: 5

Comments