package utils import ( "encoding/json" "errors" "fmt" "github.com/paulmach/orb/geojson" "github.com/spf13/viper" "math" "net/http" "strings" ) func Haversine(lat1, lon1, lat2, lon2 float64) float64 { R := 6371.0 lat1 = lat1 * math.Pi / 180 lon1 = lon1 * math.Pi / 180 lat2 = lat2 * math.Pi / 180 lon2 = lon2 * math.Pi / 180 dlat := lat2 - lat1 dlon := lon2 - lon1 a := math.Sin(dlat/2)*math.Sin(dlat/2) + math.Cos(lat1)*math.Cos(lat2)*math.Sin(dlon/2)*math.Sin(dlon/2) c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a)) distance := R * c return distance } func CalculateDurationBetweenFeatures(feature1, feature2 *geojson.Feature) (int64, error) { coords1 := feature1.Point() coords2 := feature2.Point() v := viper.New() v.SetConfigName("config") v.AddConfigPath(".") v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) v.AutomaticEnv() _ = v.ReadInConfig() routingBaseUrl := v.GetString("routing.valhalla.base_url") url := fmt.Sprintf("%sroute?json=%s", routingBaseUrl, createJSONROUTERequest(coords1.X(), coords1.Y(), coords2.X(), coords2.Y())) response, err := http.Get(url) if err != nil { return 0, errors.New("routing service error") } var result map[string]interface{} decoder := json.NewDecoder(response.Body) if err := decoder.Decode(&result); err != nil { return 0, errors.New("routing response decoding error") } trip, ok := result["trip"].(map[string]interface{}) if !ok { return 0, errors.New("routing response decoding error") } summary, ok := trip["summary"].(map[string]interface{}) if !ok { return 0, errors.New("routing response decoding error") } duration, ok := summary["time"].(float64) if !ok { return 0, errors.New("routing response decoding error") } return int64(duration), nil } func createJSONROUTERequest(lat1, lon1, lat2, lon2 float64) string { request := map[string]interface{}{ "locations": []map[string]float64{ {"lat": lat1, "lon": lon1}, {"lat": lat2, "lon": lon2}, }, "costing": "auto", } jsonRequest, _ := json.Marshal(request) return string(jsonRequest) }