gridsq/ft8/ft8.go

162 lines
2.9 KiB
Go

package ft8
import (
"bufio"
"git.wntrmute.dev/kyle/goutils/die"
"os"
"os/user"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
)
func getHomeDirectory() string {
u, err := user.Current()
if err != nil {
return ""
}
return u.HomeDir
}
func GetDefaultDirectory() string {
switch runtime.GOOS {
case "linux":
return filepath.Join(
getHomeDirectory(),
".local",
"share",
"WSJT-X",
)
case "windows":
return filepath.Join(
getHomeDirectory(),
"AppData",
"Local",
"WSJT-X",
)
default:
die.With("Operating system '%s' isn't supported.", runtime.GOOS)
}
return ""
}
const (
RecordTypeCQ = iota + 1
RecordTypeCQReply
RecordTypeSignal
RecordTypeSignoff
)
// call ([\w\d/]+)
// grid (\w{2}\d{2})
var (
RegexpCQ = regexp.MustCompile(`^CQ ([\w/]+) (\w{2}\d{2})$`)
RegexpCQReply = regexp.MustCompile(`^([\w/]+) ([\w/]+) (\w{2}\d{2})$`)
RegexpRR73 = regexp.MustCompile(`^([\w\d/]+) ([\w\d/]+) RR73$`)
)
type Record struct {
Type uint8
Time time.Time
Freq float64
Tone int
Mode string
IsTX bool
De string
To string
Received int
Grid string
}
func (rec *Record) HasGrid() bool {
return rec.Grid != ""
}
func ParseRecordHeader(line string) (rec *Record, err error) {
// 0 1 2 3 4 5 6 7
// 231215_021330 14.074 Rx FT8 -6 0.1 1713 CQ N6ACA CM97
fields := strings.Fields(line)
rec = &Record{}
rec.Time, err = time.Parse("060102_150405", fields[0])
if err != nil {
return
}
rec.Freq, err = strconv.ParseFloat(fields[1], 64)
if err != nil {
return
}
if fields[2] == "Tx" {
rec.IsTX = true
}
rec.Mode = fields[3]
rec.Received, err = strconv.Atoi(fields[4])
if err != nil {
return
}
rec.Tone, err = strconv.Atoi(fields[6])
if err != nil {
return
}
return
}
func ParseRecord(line string) (*Record, error) {
rec, err := ParseRecordHeader(line)
if err != nil {
return nil, err
}
fields := strings.Fields(line)
line = strings.Join(fields[7:len(fields)], " ")
switch {
case RegexpRR73.MatchString(line):
rec.Type = RecordTypeSignoff
match := RegexpRR73.FindStringSubmatch(line)
rec.De = match[2]
rec.To = match[1]
case RegexpCQ.MatchString(line):
rec.Type = RecordTypeCQ
match := RegexpCQ.FindStringSubmatch(line)
rec.De = match[1]
rec.Grid = match[2]
case RegexpCQReply.MatchString(line):
rec.Type = RecordTypeCQReply
match := RegexpCQReply.FindStringSubmatch(line)
rec.To = match[1]
rec.De = match[2]
rec.Grid = match[3]
}
return rec, err
}
func ProcessFile(path string) ([]*Record, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var records []*Record
scanner := bufio.NewScanner(file)
for scanner.Scan() {
rec, err := ParseRecord(scanner.Text())
if err != nil {
return nil, err
}
records = append(records, rec)
}
return records, nil
}