-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
179 lines (140 loc) · 5.13 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
178
179
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"sort"
"strconv"
"strings"
"time"
"github.com/grounded042/hike_map_translator/garmin"
"github.com/grounded042/hike_map_translator/models"
"github.com/spf13/cobra"
)
var source string
var sourceURL string
var startDate string
var endDate string
var tripName string
var password string
const timestampFormat = "01/02/2006"
const tripsFolder = "trips/"
const tripDetailsFolder = "details/"
func main() {
rootCmd := &cobra.Command{
Use: "hike_map_translator",
Short: "hike_map_translator translates data into a format for hike_map",
}
rootCmd.Flags().StringVarP(&source, "source", "s", "", "The source type to translate data from")
rootCmd.Flags().StringVarP(&sourceURL, "source_url", "u", "", "The url used to pull the data to translate")
rootCmd.Flags().StringVarP(&startDate, "start_date", "d", "", "The day on which to start pulling data from in the format of <month>/<day>/<year> with leading zeros")
rootCmd.Flags().StringVarP(&endDate, "end_date", "e", "", "The day on which to stop pulling data from in the format of <month>/<day>/<year> with leading zeros")
rootCmd.Flags().StringVarP(&tripName, "trip_name", "n", "", "The name of the trip")
rootCmd.Flags().StringVarP(&password, "password", "p", "", "The username, if any, for pulling the data from the source_url")
rootCmd.Run = func(cmd *cobra.Command, args []string) {
timeStartDate := convertDate(startDate, "`start_date` was not supplied - will not filter based on a start date")
timeEndDate := convertDate(endDate, "`end_date` was not supplied - will not filter based on a end date")
if !timeEndDate.IsZero() {
timeEndDate = timeEndDate.AddDate(0, 0, 1)
}
translate(source, sourceURL, timeStartDate, timeEndDate, tripName, password)
}
err := rootCmd.Execute()
if err != nil {
os.Exit(2)
}
}
func convertDate(date string, errMessage string) time.Time {
if date == "" {
fmt.Println(errMessage)
return time.Time{}
}
t, err := time.Parse(timestampFormat, date)
if err != nil {
panic(err)
}
return getStartOfDayTime(t)
}
func getStartOfDayTime(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
}
// buildDaysFromPoints takes a slice of points and groups a slice of points
// into a day. It returns a map of the days with their corresponding slice of
// points and an ordered slice of map keys of days.
func buildDaysFromPoints(points []models.Point) (map[string][]models.Point, []string) {
// sort the points so they are in order by timestamp
sort.Sort(models.ByTimestamp(points))
previousDay := points[0].Timestamp.Format(timestampFormat)
dayStartingIndex := 0
days := map[string][]models.Point{}
dayKeys := []string{}
for i := 0; i < len(points); i++ {
curDay := points[i].Timestamp.Format(timestampFormat)
if curDay != previousDay {
days[previousDay] = points[dayStartingIndex : i-1]
dayKeys = append(dayKeys, previousDay)
previousDay = curDay
dayStartingIndex = i
}
}
days[previousDay] = points[dayStartingIndex:len(points)]
dayKeys = append(dayKeys, previousDay)
return days, dayKeys
}
// writeDayJSON writes the passed in day info to a JSON file and returns the
// location of the file
func writeDayJSON(day *models.Day, dayName string) string {
dJSON, _ := json.MarshalIndent(day, "", " ")
detailsFilePath := tripDetailsFolder + dayName + ".json"
ioutil.WriteFile(tripsFolder+detailsFilePath, dJSON, 0644)
return detailsFilePath
}
// generateJSON takes a map of days and their points along with the ordered
// slice of the map keys so the days can be properly ordered
func generateJSON(days map[string][]models.Point, dayKeys []string, tName string) {
os.MkdirAll(tripsFolder+tripDetailsFolder, os.ModePerm)
cumulativeCoords := [][]float64{}
index := make([]models.IndexDay, len(dayKeys)+1)
// create the individual days
for i, key := range dayKeys {
dayNum := i + 1
day := models.DayFromSliceOfPoints(key, dayNum, days[key])
cumulativeCoords = append(cumulativeCoords, day.Coordinates...)
dayName := "Day " + strconv.Itoa(dayNum)
detailsFilePath := writeDayJSON(day, dayName)
index[dayNum] = models.NewIndexDay(dayNum, dayName, key, detailsFilePath)
}
// create the all day
allDay := models.DayFromCoords("All", 0, cumulativeCoords)
dayName := "All"
detailsFilePath := writeDayJSON(allDay, dayName)
index[0] = models.NewIndexDay(0, dayName, tName, detailsFilePath)
// write the index
iJSON, _ := json.MarshalIndent(index, "", " ")
indexFilePath := tripsFolder + "index.json"
ioutil.WriteFile(indexFilePath, iJSON, 0644)
}
type generateFrom interface {
GetAllPoints(time.Time, time.Time) []models.Point
}
func translate(tSource, url string, sDate, eDate time.Time, tName, pword string) {
var gFrom generateFrom
var err error
switch strings.ToLower(tSource) {
case "garmin":
gFrom, err = garmin.LoadURL(url, pword)
default:
panic(fmt.Sprintf("unknown source: %v", source))
}
if err != nil {
panic(err)
}
points := gFrom.GetAllPoints(sDate, eDate)
if len(points) == 0 {
fmt.Println("No points to translate!")
return
}
days, dayKeys := buildDaysFromPoints(points)
generateJSON(days, dayKeys, tName)
}