summaryrefslogtreecommitdiff
path: root/pkg/model/place.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/model/place.go')
-rw-r--r--pkg/model/place.go84
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
+}