Carpark {
  id: UUID
  name: "Central Plaza Basement"
  location: { lat: number, lng: number }
  is_outdoor: boolean
}

Map {
  id: UUID                 // Unique identifier for each map
  carpark_id: UUID
  level_name: string     // Human-readable (L1,L2,L3,L3.1)
  svg_url: string          // URL or path to the SVG file for the map
	default_center: {        // The default center position for the map when loaded
  x_ratio: number,       // Horizontal center position as a percentage (0-1) of the map width
  y_ratio: number        // Vertical center position as a percentage (0-1) of the map height
}

  default_zoom: number     // The default zoom scale (e.g., 1.0 = normal, 2.0 = zoomed in)
}

Cluster {
  id: UUID                   // Unique identifier for each cluster
  map_id: UUID               // Reference to the Map (the SVG map this cluster belongs to)
  cluster_name: string       // The human-readable name for this cluster (e.g., "CL + Num", CL1)
  svg_position: {            // Position of the cluster on the map, stored as ratios relative to the viewBox
    x_ratio: number,         // Horizontal position as a percentage (0-1) of the map width
    y_ratio: number          // Vertical position as a percentage (0-1) of the map height
  }
  cluster_type: string       // Optional: Type of cluster, e.g., "VIP", "Standard", etc.
    capacity: number       // Optional: Number of parking spots in this cluster (e.g., 3-6 spots)
  gps_coordinate: {          // Optional: GPS coordinates for outdoor clusters
    lat: number,
    lng: number
  }
}

MapElement {
  id: UUID
  map_id: UUID
  type: "cluster" | "entrance" | "exit" | "icon" | "label"
  label: string               // displayed on map or used to match with cluster_name
  x_ratio: number
  y_ratio: number
  path_data?: string;           // e.g., for <path d="...">
  metadata?: JSON             // shape, size, color, iconName, rotation, etc.
}


Availability Track

Observation {
  

TimeBucketStat {
  

Prediction {
  

ErrorRecord {