-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathigcParser.go
146 lines (125 loc) · 3.38 KB
/
igcParser.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
package gtbackend
import (
"bufio"
"github.com/pkg/errors"
"os"
"regexp"
"strings"
)
// fileNameIP file name
const fileNameIP = "igcParser.go"
// Record is the metadata information about a IGC approved FR recorded flight.
// Contains information about the flight recorder itself, as well as some selected header
// information from the flight.
type Record struct {
Manufacturer A
Header H
}
// A A record in IGC spec, always the first record in a IGC File. Contains information about
// FR manufacturer and ID, as well as some additional information (dunno what it is though).
type A struct {
ManufacturerID string
UniqueID string
Additional string
}
// H record, Metadata/header information from a FR recorded flight.
type H struct {
Pilot string
FlightRecorderType string
GliderType string
GliderID string
FirmwareVersion string
HardwareVersion string
Date string
}
// Parser holds a file, mostly done to keep as much as possible private,
// while also support testing.
type Parser struct {
Parsed string
}
// Parse - main routine for parsing a IGC-track. Returns a Record.
func (parser Parser) Parse() (rec Record, err error) {
log := DebugLogPrepareHeader(fileNameIP, "Parse")
if parser.Parsed == "" {
err = errors.New("Empty file")
DebugLogErrMsg(log, err, "No lines in file")
return
}
lines := strings.Split(parser.Parsed, "\n")
h := parser.getHRecords(lines)
rec.Manufacturer = parseA(lines[0])
rec.Header = parser.parseH(h)
return
}
// parseA processes different Axxxxxx... fields into a A object, which is returned.
func parseA(record string) (man A) {
r := record[1:]
man.ManufacturerID = r[0:3]
man.UniqueID = r[3:6]
man.Additional = r[6:]
return man
}
// parseH processes different Hxxxxxx... fields into a H object, which is returned.
// Unsupported encountered keys is stdouted on DebugLvl info.
func (parser Parser) parseH(hRecords []string) (header H) {
log := DebugLogPrepareHeader(fileNameIP, "parseH")
keys := make(map[string]string)
for i := 0; i < len(hRecords); i++ {
keys[hRecords[i][2:5]] = parser.strip(hRecords[i][5:], ":")
}
for k, v := range keys {
switch k {
case "PLT":
header.Pilot = v
break
case "FTY":
header.FlightRecorderType = v
break
case "GTY":
header.GliderType = v
break
case "GID":
header.GliderID = v
break
case "RFW":
header.FirmwareVersion = v
break
case "RHW":
header.HardwareVersion = v
break
case "DTE":
header.Date = v[0:6]
default:
DebugLogNoErrMsg(log, "Unsupported key: "+k)
}
}
return
}
// FileToLines will traverse and return
// an array with all file lines.
func FileToLines(file *os.File) (lines []string, err error) {
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
err = scanner.Err()
return
}
// strip will take a string and remove everything before the first occurrence of the substring.
func (parser Parser) strip(s string, sub string) (data string) {
i := strings.Index(s, sub)
if i == -1 {
return s
}
return s[i+1:]
}
// getHRecords will traverse a list of strings and return a new array with only.
// the lines starting with an capital h
func (parser Parser) getHRecords(records []string) (h []string) {
for i := 0; i < len(records); i++ {
if m, _ := regexp.MatchString("^H", records[i]); m {
h = append(h, records[i])
}
}
return
}