-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
177 lines (149 loc) · 4.76 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package main
import (
"os"
"fmt"
"strings"
"time"
"encoding/json"
"github.com/tkrajina/gpxgo/gpx"
)
func usage() {
fmt.Println("Create a GPX files based on a certain data export format.")
fmt.Println("Usage: go run . <folder name>")
os.Exit(0)
}
func check(e error) {
if e != nil {
panic(e)
}
}
type TrackDataRef struct {
Type string `json:"__type"`
Name string `json:"name"`
Iso string `json:"iso"`
}
// track data structure for one track
type TrackData struct {
Distance int64 `json:"distance"`
AltitudeMax int64 `json:"altitudeMax"`
SpeedAverage float64 `json:"speedAverage"`
Language string `json:"language"`
Points TrackDataRef `json:"points"`
Duration int64 `json:"duration"`
RatingRoadCondition int64 `json:"ratingRoadCondition"`
Altitudes TrackDataRef `json:"altitudes"`
TimeCreated TrackDataRef `json:"timeCreated"`
Speeds TrackDataRef `json:"speeds"`
Image TrackDataRef `json:"image"`
AltitudeIncline int64 `json:"altitudeIncline"`
SpeedMax float64 `json:"speedMax"`
Preview200 TrackDataRef `json:"preview200"`
Timestamps TrackDataRef `json:"dates"`
RatingFun int64 `json:"ratingFun"`
AltitudeDecline int64 `json:"altitudeDecline"`
Tags []string `json:"tags"`
Preview400 TrackDataRef `json:"preview400"`
RatingScenery int64 `json:"ratingScenery"`
Name string `json:"name"`
Comment string `json:"comment"`
AltitudeMin int64 `json:"altitudeMin"`
TourFeed bool `json:"tourFeed"`
}
// default empty author name
var Author string = ""
func main(){
if len(os.Args) < 2 {
usage()
}
// folder with export data, extracted
dirName := os.Args[1]
// read author name from folder name
if len(strings.Split(dirName, " ")) > 2 {
Author = strings.Split(dirName, " ")[2]
}
// read overview file out of export directory
payload,err := os.ReadFile(dirName + "/track data.json" )
check(err)
// all tracks availbale from the overview
var Tracks []TrackData
// read JSON all tracks, parse track structure with JSON file references
err = json.Unmarshal(payload, &Tracks)
check(err)
// create a GPX file for each track
for _,Track := range Tracks {
createGpx(Track, dirName)
}
}
// points JSON read structure
type Points struct {
Points [][]float64 `json:"points"`
}
// elevations JSON read structure
type Elevations struct {
Elevations []int64 `json:"altitudes"`
}
// timestamps JSON read structure
type Timestamps struct {
Timestamps []int64 `json:"dates"`
}
// create one track GPX file
func createGpx(Track TrackData, dirName string){
var Gpx gpx.GPX
// identify track with name, fill meta data
fmt.Println(Track.Name)
Gpx.Name = Track.Name
Gpx.Description = Track.Comment
Gpx.AuthorName = Author
startTime,err := time.Parse("2006-01-02T15:04:05.000Z", Track.TimeCreated.Iso)
check(err)
Gpx.Time = &startTime
// create the output gpx file into same folder as source data, use track name for file
gpxFile,err := os.Create(dirName + "/" + Gpx.Name + ".gpx")
check(err)
defer gpxFile.Close()
// read points from points JSON file
pointsFile,err := os.ReadFile(dirName + "/" + Track.Points.Name)
check(err)
var points Points
err = json.Unmarshal(pointsFile, &points)
check(err)
// read elevations from elevations JSON file
elevationsFile,err := os.ReadFile(dirName + "/" + Track.Altitudes.Name)
check(err)
var elevations Elevations
err = json.Unmarshal(elevationsFile, &elevations)
check(err)
// read timestamps from timestamps JSON file
timestampsFile,err := os.ReadFile(dirName + "/" + Track.Timestamps.Name)
check(err)
var timestamps Timestamps
err = json.Unmarshal(timestampsFile, ×tamps)
check(err)
// number of points from number read in points JSON file, dimensions for elevation and timestamps are to be the same
gpxPoints := make([]gpx.GPXPoint, len(points.Points))
// combine threee source into one GPX point data item
for i,_ := range gpxPoints {
gpxPoints[i].Point.Latitude = points.Points[i][0]
gpxPoints[i].Point.Longitude = points.Points[i][1]
gpxPoints[i].Point.Elevation = *gpx.NewNullableFloat64(float64(elevations.Elevations[i]))
gpxPoints[i].Timestamp = startTime.Add(time.Millisecond * time.Duration(timestamps.Timestamps[i]))
}
// create a Track segment and set all points into it
gpxSegment := gpx.GPXTrackSegment{
Points: gpxPoints,
}
// create a track and set the track segment into it
gpxTrack := gpx.GPXTrack{
Name: Track.Name,
Comment: Track.Comment,
Segments: []gpx.GPXTrackSegment{gpxSegment},
}
// set the track into the GPX
Gpx.Tracks = []gpx.GPXTrack{gpxTrack}
// generate XML for the GPX file
payload, err := Gpx.ToXml( gpx.ToXmlParams{ Indent: true} )
check(err)
// write GPX file with XML content
_,err = gpxFile.Write(payload)
check(err)
}