-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
150 lines (124 loc) · 4.05 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
package main
import (
"crypto/rand"
"encoding/binary"
"encoding/hex"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"github.com/tormoder/fit"
)
func main() {
// Define command line flags
filesFlag := flag.String("files", "", "Space-delimited set of filenames or a directory containing .fit files")
outputFlag := flag.String("output", ".", "Directory to output files to, defaults to current directory")
flag.Parse()
if len(os.Args) < 2 {
printUsage()
os.Exit(1)
}
if *filesFlag == "" {
log.Fatal("The -files flag is required")
}
// Get a list of .fit files
fileList := getFitFiles(*filesFlag)
// Ensure the output directory exists
err := os.MkdirAll(*outputFlag, os.ModePerm)
if err != nil {
log.Fatalf("Failed to create output directory: %v", err)
}
// Process each .fit file
for _, file := range fileList {
processFitFile(file, *outputFlag)
}
}
func printUsage() {
fmt.Printf("Usage: %s -files <files_or_directory> [-output <output_directory>]\n", os.Args[0])
fmt.Println("\nOptions:")
fmt.Println(" -files : Space-delimited set of filenames or a directory containing .fit files (required)")
fmt.Println(" -output : Directory to output files to, defaults to current directory (optional)")
}
// getFitFiles returns a list of .fit files based on the provided input (filesFlag)
func getFitFiles(filesFlag string) []string {
var files []string
// Check if the input is a directory
if info, err := os.Stat(filesFlag); err == nil && info.IsDir() {
files, err = filepath.Glob(filepath.Join(filesFlag, "*.[fF][iI][tT]"))
if err != nil {
log.Fatalf("Failed to list .fit files: %v", err)
}
} else {
files = append(files, filesFlag)
}
return files
}
// processFitFile processes the .fit file to remove GPS info and save it with a random name
func processFitFile(filePath, outputDir string) {
// Open the .fit file
fitFile, err := os.Open(filePath)
if err != nil {
log.Fatalf("Failed to open file %s: %v", filePath, err)
}
defer fitFile.Close()
// Decode the .fit file
fitData, err := fit.Decode(fitFile)
if err != nil {
log.Fatalf("Failed to decode .fit file %s: %v", filePath, err)
}
// Get the actual activity
// Remove GPS data from the file
removeGPSData(fitData)
// Generate a random filename
newFileName := generateRandomFilename() + ".fit"
newFilePath := filepath.Join(outputDir, newFileName)
// Save the modified .fit file
newFile, err := os.Create(newFilePath)
if err != nil {
log.Fatalf("Failed to create output file %s: %v", newFilePath, err)
}
defer newFile.Close()
err = fit.Encode(newFile, fitData, binary.LittleEndian)
if err != nil {
log.Fatalf("Failed to encode .fit file %s: %v", newFilePath, err)
}
fmt.Printf("Processed %s and saved as %s\n", filePath, newFilePath)
}
// removeGPSData strips the GPS information from the .fit data
func removeGPSData(fitData *fit.File) {
activity, err := fitData.Activity()
if err != nil {
log.Fatalf("Failed to decode activity %v", err)
return
}
for _, lap := range activity.Laps {
lap.StartPositionLat = fit.NewLatitudeInvalid()
lap.StartPositionLong = fit.NewLongitudeInvalid()
lap.EndPositionLat = fit.NewLatitudeInvalid()
lap.EndPositionLong = fit.NewLongitudeInvalid()
}
for _, sesh := range activity.Sessions {
sesh.StartPositionLat = fit.NewLatitudeInvalid()
sesh.StartPositionLong = fit.NewLongitudeInvalid()
sesh.EndPositionLat = fit.NewLatitudeInvalid()
sesh.EndPositionLong = fit.NewLongitudeInvalid()
sesh.NecLat = fit.NewLatitudeInvalid()
sesh.NecLong = fit.NewLongitudeInvalid()
sesh.SwcLat = fit.NewLatitudeInvalid()
sesh.SwcLong = fit.NewLongitudeInvalid()
}
for _, record := range activity.Records {
record.PositionLat = fit.NewLatitudeInvalid()
record.PositionLong = fit.NewLongitudeInvalid()
}
}
// generateRandomFilename generates a random 8-character alphanumeric string
func generateRandomFilename() string {
randBytes := make([]byte, 4) // 4 bytes will result in 8 hex characters
_, err := rand.Read(randBytes)
if err != nil {
log.Fatalf("Failed to generate random filename: %v", err)
}
return hex.EncodeToString(randBytes)
}