dragndrop_hld/oldqc/Backend/qc/site_connectivity.go
alex 12407b74e4 Initial commit - Stage 1 working version
Saving current working state before proceeding to Stage 2.
Includes:
- Backend: Python-based QC validator with shapefile processing
- Frontend: Drag-and-drop file upload interface
- Sample files for testing
- Documentation and revision history

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 13:43:57 -07:00

126 lines
3.6 KiB
Go

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)
})
}