diff options
Diffstat (limited to 'pkg/model/place.go')
-rw-r--r-- | pkg/model/place.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/pkg/model/place.go b/pkg/model/place.go new file mode 100644 index 0000000..54ce038 --- /dev/null +++ b/pkg/model/place.go @@ -0,0 +1,84 @@ +package model + +import ( + "database/sql/driver" + "fmt" + "math" + "regexp" + "strconv" + "time" + + "github.com/uptrace/bun" +) + +type Place struct { + bun.BaseModel `bun:"table:places,alias:p"` + + GUID string `bun:",pk,unique"` + Position *Point `bun:"type:geometry(Point, 4326)"` + Img string + Name string + Count int + CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` + UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` + DeletedAt time.Time `bun:",soft_delete,nullzero"` +} + +type Point struct { + Lat float64 + Lon float64 +} + +func (p *Point) Value() (driver.Value, error) { + return fmt.Sprintf(`SRID=4326;POINT(%f %f)`, p.Lon, p.Lat), nil +} + +func (p *Point) Scan(src any) (err error) { + re := regexp.MustCompile(`/\((.+?) (.+?)\)/`) + s := "" + //nolint:revive + switch src := src.(type) { + case string: + s = src + case []uint8: + s = string(src) + default: + return fmt.Errorf("unsupported data type: %T", src) + } + //nolint:gomnd + subs := re.FindAllString(s, 2) + + lon, err := strconv.ParseFloat(subs[0], 64) + if err != nil { + return err + } + + lat, err := strconv.ParseFloat(subs[1], 64) + if err != nil { + return err + } + + p.Lat = lat + p.Lon = lon + + return nil +} + +const radius = 6371 // Earth's mean radius in kilometers + +func degrees2radians(degrees float64) float64 { + return degrees * math.Pi / 180 +} + +func (p *Point) Distance(destination *Point) float64 { + degreesLat := degrees2radians(destination.Lat - p.Lat) + degreesLong := degrees2radians(destination.Lon - p.Lon) + a := (math.Sin(degreesLat/2)*math.Sin(degreesLat/2) + + math.Cos(degrees2radians(p.Lat))* + math.Cos(degrees2radians(destination.Lat))*math.Sin(degreesLong/2)* + math.Sin(degreesLong/2)) + c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a)) + d := radius * c + + return d +} |