package qc import ( "fmt" "net/http" "strconv" "verofy-backend/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) func SiteConnectivityRoute(router *gin.Engine, db *gorm.DB, schema string) { router.GET("/api/qc/site-connectivity", func(c *gin.Context) { mapID := c.Query("map_id") zone := c.Query("zone") maxDistanceStr := c.Query("max_distance") if mapID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "map_id is required"}) return } // Default max distance is 50 meters maxDistance := 50.0 if maxDistanceStr != "" { if dist, err := strconv.ParseFloat(maxDistanceStr, 64); err == nil { maxDistance = dist } } // Get all sites for the market (and zone if specified) var sites []models.SitesGeoJSON siteQuery := db.Table(fmt.Sprintf("%s.sites", schema)). Select("gid, id, mapprojectid, name, address1, city, state, zip, ST_AsGeoJSON(geom)::json AS geometry") if mapID != "" { siteQuery = siteQuery.Where("mapprojectid = ?", mapID) } siteQuery.Find(&sites) // Get all segments for connectivity analysis var segments []models.SegmentGeoJSON segmentQuery := db.Table(fmt.Sprintf("%s.segment2", schema)). Select("id_0, mapid, segment_type, segment_status, id, protection_status, qc_flag, ST_AsGeoJSON(geom)::json AS geometry") if mapID != "" { segmentQuery = segmentQuery.Where("mapid = ?", mapID) } if zone != "" { segmentQuery = segmentQuery.Where("group_1 = ?", zone) } segmentQuery.Find(&segments) // Analyze connectivity for each site results := []map[string]interface{}{} connectedCount := 0 disconnectedCount := 0 for _, site := range sites { if len(site.Geometry) == 0 { continue } // Use PostGIS to find the nearest segment within max distance var nearestDistance float64 nearestQuery := fmt.Sprintf(` SELECT ST_Distance( ST_Transform(sites.geom, 3857), ST_Transform(segments.geom, 3857) ) as distance FROM %s.sites sites, %s.segment2 segments WHERE sites.gid = ? AND segments.mapid = ? ORDER BY ST_Distance( ST_Transform(sites.geom, 3857), ST_Transform(segments.geom, 3857) ) LIMIT 1 `, schema, schema) db.Raw(nearestQuery, site.GID, mapID).Scan(&nearestDistance) isConnected := nearestDistance <= maxDistance status := "connected" if !isConnected { status = "disconnected" disconnectedCount++ } else { connectedCount++ } // Update the site's connectivity status in the database updateQuery := fmt.Sprintf("UPDATE %s.sites SET connectivity_status = ?, connectivity_distance = ? WHERE gid = ?", schema) db.Exec(updateQuery, status, nearestDistance, site.GID) siteResult := map[string]interface{}{ "site_id": site.GID, "site_name": site.Name, "mapprojectid": site.MapProjectID, "is_connected": isConnected, "nearest_distance": nearestDistance, "connectivity_status": status, "geometry": site.Geometry, "address": site.Address1, "city": site.City, "state": site.State, } results = append(results, siteResult) } response := map[string]interface{}{ "total_sites": len(sites), "connected_sites": connectedCount, "disconnected_sites": disconnectedCount, "connectivity_rate": float64(connectedCount) / float64(len(sites)) * 100, "max_distance_meters": maxDistance, "results": results, } c.JSON(http.StatusOK, response) }) }