212 lines
7.3 KiB
Go
212 lines
7.3 KiB
Go
package helper
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"users_management/m/model/dto/res"
|
|
"users_management/m/model/entity"
|
|
"users_management/m/repository"
|
|
"users_management/m/utils/service"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func ConvertToNearestDeviceResponses(devices []entity.DeviceWithDistance, repo repository.NearestDeviceRepo, geocoder service.GeocodingService) ([]res.NearestDeviceResponse, error) {
|
|
var responses []res.NearestDeviceResponse
|
|
|
|
for _, device := range devices {
|
|
// Get address
|
|
address := ""
|
|
if geocoder != nil {
|
|
addr, err := geocoder.GetAddressFromCoordinates(device.Latitude, device.Longitude)
|
|
if err != nil {
|
|
log.Printf("Geocoding error for device %s: %v", device.DeviceCode, err)
|
|
address = fmt.Sprintf("Coordinates: %.6f, %.6f", device.Latitude, device.Longitude)
|
|
} else {
|
|
address = addr
|
|
}
|
|
}
|
|
|
|
// Count connections
|
|
backboneCount, fishboneCount, towerCount, err := repo.CountConnectionsByDeviceID(device.ID)
|
|
if err != nil {
|
|
log.Printf("Error counting connections for device %s: %v", device.DeviceCode, err)
|
|
backboneCount, fishboneCount, towerCount = 0, 0, 0
|
|
}
|
|
|
|
response := res.NearestDeviceResponse{
|
|
ID: device.ID,
|
|
DeviceCode: device.DeviceCode,
|
|
DeviceType: string(device.DeviceType),
|
|
Distance: device.Distance, // Use the calculated distance from query
|
|
Address: address,
|
|
Longitude: device.Longitude,
|
|
Latitude: device.Latitude,
|
|
Status: string(device.Status),
|
|
PortAmount: device.PortAmount,
|
|
Region: device.Region,
|
|
Province: device.Province,
|
|
City: device.City,
|
|
District: device.District,
|
|
BackboneCount: backboneCount,
|
|
FishboneCount: fishboneCount,
|
|
TowerCount: towerCount,
|
|
CreatedAt: device.CreatedAt,
|
|
}
|
|
|
|
responses = append(responses, response)
|
|
}
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
func ConvertToNearestDeviceDetailResponse(device entity.Device, distance float64, repo repository.NearestDeviceRepo, geocoder service.GeocodingService) (res.NearestDeviceDetailResponse, error) {
|
|
// Get address
|
|
address := ""
|
|
if geocoder != nil {
|
|
addr, err := geocoder.GetAddressFromCoordinates(device.Latitude, device.Longitude)
|
|
if err != nil {
|
|
log.Printf("Geocoding error for device %s: %v", device.DeviceCode, err)
|
|
address = fmt.Sprintf("Coordinates: %.6f, %.6f", device.Latitude, device.Longitude)
|
|
} else {
|
|
address = addr
|
|
}
|
|
}
|
|
|
|
// Get detailed connection information
|
|
backbones, err := repo.GetBackbonesByDeviceID(device.ID)
|
|
if err != nil {
|
|
return res.NearestDeviceDetailResponse{}, err
|
|
}
|
|
|
|
fishbones, err := repo.GetFishbonesByDeviceID(device.ID)
|
|
if err != nil {
|
|
return res.NearestDeviceDetailResponse{}, err
|
|
}
|
|
|
|
towers, err := repo.GetTowersByDeviceID(device.ID)
|
|
if err != nil {
|
|
return res.NearestDeviceDetailResponse{}, err
|
|
}
|
|
|
|
// Convert to response format
|
|
backboneInfos := convertToBackboneConnectionInfos(backbones, device.ID)
|
|
fishboneInfos := convertToFishboneConnectionInfos(fishbones, device.ID)
|
|
towerInfos := convertToTowerConnectionInfos(towers, device.Latitude, device.Longitude)
|
|
|
|
response := res.NearestDeviceDetailResponse{
|
|
ID: device.ID,
|
|
DeviceCode: device.DeviceCode,
|
|
DeviceType: string(device.DeviceType),
|
|
Distance: distance,
|
|
Address: address,
|
|
Longitude: device.Longitude,
|
|
Latitude: device.Latitude,
|
|
Status: string(device.Status),
|
|
PortAmount: device.PortAmount,
|
|
Province: device.Province,
|
|
City: device.City,
|
|
District: device.District,
|
|
ImageURL: device.ImageURL,
|
|
Backbones: backboneInfos,
|
|
Fishbones: fishboneInfos,
|
|
Towers: towerInfos,
|
|
CreatedAt: device.CreatedAt,
|
|
UpdatedAt: device.UpdatedAt,
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func convertToBackboneConnectionInfos(backbones []entity.Backbone, deviceID uuid.UUID) []res.BackboneConnectionInfo {
|
|
var infos []res.BackboneConnectionInfo
|
|
|
|
for _, backbone := range backbones {
|
|
isStartDevice := backbone.DeviceStartID == deviceID
|
|
connectedTo := ""
|
|
|
|
if isStartDevice && backbone.DeviceEnd.DeviceCode != "" {
|
|
connectedTo = backbone.DeviceEnd.DeviceCode
|
|
} else if !isStartDevice && backbone.DeviceStart.DeviceCode != "" {
|
|
connectedTo = backbone.DeviceStart.DeviceCode
|
|
}
|
|
|
|
info := res.BackboneConnectionInfo{
|
|
ID: backbone.ID,
|
|
BackboneCode: backbone.BackboneCode,
|
|
CoreAmount: backbone.CoreAmount,
|
|
IsStartDevice: isStartDevice,
|
|
ConnectedTo: connectedTo,
|
|
}
|
|
|
|
infos = append(infos, info)
|
|
}
|
|
|
|
return infos
|
|
}
|
|
|
|
func convertToFishboneConnectionInfos(fishbones []entity.Fishbone, deviceID uuid.UUID) []res.FishboneConnectionInfo {
|
|
var infos []res.FishboneConnectionInfo
|
|
|
|
for _, fishbone := range fishbones {
|
|
isStartDevice := fishbone.DeviceStartID == deviceID
|
|
connectedTo := ""
|
|
|
|
if isStartDevice && fishbone.DeviceEnd.DeviceCode != "" {
|
|
connectedTo = fishbone.DeviceEnd.DeviceCode
|
|
} else if !isStartDevice && fishbone.DeviceStart.DeviceCode != "" {
|
|
connectedTo = fishbone.DeviceStart.DeviceCode
|
|
}
|
|
|
|
info := res.FishboneConnectionInfo{
|
|
ID: fishbone.ID,
|
|
FishboneCode: fishbone.FishboneCode,
|
|
CoreAmount: fishbone.CoreAmount,
|
|
BackboneCode: fishbone.Backbone.BackboneCode,
|
|
IsStartDevice: isStartDevice,
|
|
ConnectedTo: connectedTo,
|
|
}
|
|
|
|
infos = append(infos, info)
|
|
}
|
|
|
|
return infos
|
|
}
|
|
|
|
func convertToTowerConnectionInfos(towers []entity.Tower, deviceLat, deviceLng float64) []res.TowerConnectionInfo {
|
|
var infos []res.TowerConnectionInfo
|
|
|
|
for _, tower := range towers {
|
|
// Calculate distance from device to tower
|
|
distance := calculateDistance(deviceLat, deviceLng, tower.Latitude, tower.Longitude)
|
|
|
|
info := res.TowerConnectionInfo{
|
|
ID: tower.ID,
|
|
TowerCode: tower.TowerCode,
|
|
Distance: distance,
|
|
ImageURL: &tower.ImageURL,
|
|
}
|
|
|
|
infos = append(infos, info)
|
|
}
|
|
|
|
return infos
|
|
}
|
|
|
|
func calculateDistance(lat1, lng1, lat2, lng2 float64) float64 {
|
|
const earthRadius = 6371 // Earth's radius in kilometers
|
|
|
|
lat1Rad := lat1 * math.Pi / 180
|
|
lng1Rad := lng1 * math.Pi / 180
|
|
lat2Rad := lat2 * math.Pi / 180
|
|
lng2Rad := lng2 * math.Pi / 180
|
|
|
|
dlat := lat2Rad - lat1Rad
|
|
dlng := lng2Rad - lng1Rad
|
|
|
|
a := math.Sin(dlat/2)*math.Sin(dlat/2) + math.Cos(lat1Rad)*math.Cos(lat2Rad)*math.Sin(dlng/2)*math.Sin(dlng/2)
|
|
c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
|
|
|
|
return earthRadius * c
|
|
} |