2021-11-10 10:13:30 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
2021-11-16 17:01:11 +00:00
|
|
|
"log"
|
2021-11-10 10:13:30 +00:00
|
|
|
"math"
|
2022-02-16 12:02:08 +00:00
|
|
|
"strings"
|
2021-11-10 10:13:30 +00:00
|
|
|
|
|
|
|
"github.com/tkrajina/gpxgo/gpx"
|
|
|
|
"golang.org/x/text/language"
|
|
|
|
"golang.org/x/text/message"
|
|
|
|
)
|
|
|
|
|
2021-11-13 19:19:46 +00:00
|
|
|
const gpxParameter = "gpx"
|
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
func (p *post) HasTrack() bool {
|
2021-11-13 19:19:46 +00:00
|
|
|
return p.firstParameter(gpxParameter) != ""
|
2021-11-10 10:13:30 +00:00
|
|
|
}
|
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
type trackResult struct {
|
2021-11-22 15:36:17 +00:00
|
|
|
HasPoints bool
|
|
|
|
Paths [][]*trackPoint
|
|
|
|
PathsJSON string
|
|
|
|
Points []*trackPoint
|
|
|
|
PointsJSON string
|
|
|
|
Kilometers string
|
|
|
|
Hours string
|
|
|
|
Name string
|
|
|
|
MapAttribution string
|
|
|
|
MinZoom, MaxZoom int
|
2021-11-10 10:13:30 +00:00
|
|
|
}
|
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
func (a *goBlog) getTrack(p *post) (result *trackResult, err error) {
|
2021-11-13 19:19:46 +00:00
|
|
|
gpxString := p.firstParameter(gpxParameter)
|
2021-11-10 10:13:30 +00:00
|
|
|
if gpxString == "" {
|
|
|
|
return nil, errors.New("no gpx parameter in post")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse GPX
|
2021-11-10 15:27:27 +00:00
|
|
|
parseResult, err := trackParseGPX(gpxString)
|
2021-11-10 10:13:30 +00:00
|
|
|
if err != nil {
|
2021-11-16 17:01:11 +00:00
|
|
|
// Failed to parse, but just log error
|
|
|
|
log.Printf("failed to parse GPX: %v", err)
|
|
|
|
return nil, nil
|
2021-11-10 10:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
l, _ := language.Parse(a.cfg.Blogs[p.Blog].Lang)
|
|
|
|
lp := message.NewPrinter(l)
|
|
|
|
|
|
|
|
pathsJSON, err := json.Marshal(parseResult.paths)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-11-16 17:01:11 +00:00
|
|
|
pointsJSON, err := json.Marshal(parseResult.points)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
result = &trackResult{
|
2021-11-22 15:36:17 +00:00
|
|
|
HasPoints: len(parseResult.paths) > 0 && len(parseResult.paths[0]) > 0,
|
|
|
|
Paths: parseResult.paths,
|
|
|
|
PathsJSON: string(pathsJSON),
|
|
|
|
Points: parseResult.points,
|
|
|
|
PointsJSON: string(pointsJSON),
|
|
|
|
Name: parseResult.gpxData.Name,
|
|
|
|
MapAttribution: a.getMapAttribution(),
|
|
|
|
MinZoom: a.getMinZoom(),
|
|
|
|
MaxZoom: a.getMaxZoom(),
|
2021-11-16 17:01:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if parseResult.md != nil {
|
|
|
|
result.Kilometers = lp.Sprintf("%.2f", parseResult.md.MovingDistance/1000)
|
|
|
|
result.Hours = lp.Sprintf(
|
|
|
|
"%.0f:%02.0f:%02.0f",
|
2021-11-10 10:13:30 +00:00
|
|
|
math.Floor(parseResult.md.MovingTime/3600), // Hours
|
|
|
|
math.Floor(math.Mod(parseResult.md.MovingTime, 3600)/60), // Minutes
|
|
|
|
math.Floor(math.Mod(parseResult.md.MovingTime, 60)), // Seconds
|
2021-11-16 17:01:11 +00:00
|
|
|
)
|
2021-11-10 10:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
type trackPoint struct {
|
2021-11-10 10:13:30 +00:00
|
|
|
Lat, Lon float64
|
|
|
|
}
|
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
type trackParseResult struct {
|
|
|
|
paths [][]*trackPoint
|
2021-11-16 17:01:11 +00:00
|
|
|
points []*trackPoint
|
2021-11-10 10:13:30 +00:00
|
|
|
gpxData *gpx.GPX
|
|
|
|
md *gpx.MovingData
|
|
|
|
}
|
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
func trackParseGPX(gpxString string) (result *trackParseResult, err error) {
|
|
|
|
result = &trackParseResult{}
|
2021-11-10 10:13:30 +00:00
|
|
|
|
2021-11-10 15:27:27 +00:00
|
|
|
type trackPath struct {
|
2021-11-10 10:13:30 +00:00
|
|
|
gpxMovingData *gpx.MovingData
|
2021-11-10 15:27:27 +00:00
|
|
|
points []*trackPoint
|
2021-11-10 10:13:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-16 12:02:08 +00:00
|
|
|
result.gpxData, err = gpx.Parse(strings.NewReader(gpxString))
|
2021-11-10 10:13:30 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-11-16 17:01:11 +00:00
|
|
|
|
2022-02-22 09:14:48 +00:00
|
|
|
paths := make([]*trackPath, 0)
|
2021-11-10 10:13:30 +00:00
|
|
|
for _, track := range result.gpxData.Tracks {
|
|
|
|
for _, segment := range track.Segments {
|
|
|
|
md := segment.MovingData()
|
2021-11-10 15:27:27 +00:00
|
|
|
path := &trackPath{
|
2021-11-10 10:13:30 +00:00
|
|
|
gpxMovingData: &md,
|
|
|
|
}
|
|
|
|
for _, point := range segment.Points {
|
2021-11-10 15:27:27 +00:00
|
|
|
path.points = append(path.points, &trackPoint{
|
2021-11-10 10:13:30 +00:00
|
|
|
Lat: point.GetLatitude(), Lon: point.GetLongitude(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
paths = append(paths, path)
|
|
|
|
}
|
|
|
|
}
|
2021-11-16 17:01:11 +00:00
|
|
|
for _, route := range result.gpxData.Routes {
|
|
|
|
path := &trackPath{}
|
|
|
|
for _, point := range route.Points {
|
|
|
|
path.points = append(path.points, &trackPoint{
|
|
|
|
Lat: point.GetLatitude(), Lon: point.GetLongitude(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
paths = append(paths, path)
|
|
|
|
}
|
|
|
|
result.paths = make([][]*trackPoint, len(paths))
|
|
|
|
for i, path := range paths {
|
2021-11-10 10:13:30 +00:00
|
|
|
// Add points
|
2021-11-16 17:01:11 +00:00
|
|
|
result.paths[i] = path.points
|
|
|
|
// Combine moving data
|
|
|
|
if path.gpxMovingData != nil {
|
|
|
|
if result.md == nil {
|
|
|
|
result.md = &gpx.MovingData{}
|
|
|
|
}
|
|
|
|
result.md.MaxSpeed = math.Max(result.md.MaxSpeed, path.gpxMovingData.MaxSpeed)
|
|
|
|
result.md.MovingDistance = result.md.MovingDistance + path.gpxMovingData.MovingDistance
|
|
|
|
result.md.MovingTime = result.md.MovingTime + path.gpxMovingData.MovingTime
|
|
|
|
result.md.StoppedDistance = result.md.StoppedDistance + path.gpxMovingData.StoppedDistance
|
|
|
|
result.md.StoppedTime = result.md.StoppedTime + path.gpxMovingData.StoppedTime
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result.points = []*trackPoint{}
|
|
|
|
for _, point := range result.gpxData.Waypoints {
|
|
|
|
result.points = append(result.points, &trackPoint{
|
|
|
|
Lat: point.GetLatitude(), Lon: point.GetLongitude(),
|
|
|
|
})
|
2021-11-10 10:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|