1
0
Fork 0
mirror of https://github.com/on4kjm/FLEcli.git synced 2025-02-19 21:20:12 +01:00
FLEcli/cmd/parse_line.go

318 lines
7.5 KiB
Go
Raw Normal View History

2020-06-09 21:50:39 +02:00
package cmd
2020-06-25 21:05:54 +02:00
2020-06-09 21:50:39 +02:00
/*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import (
2020-06-23 22:30:59 +02:00
"fmt"
2020-06-09 21:50:39 +02:00
"regexp"
2020-06-23 22:30:59 +02:00
"strconv"
2020-06-09 21:50:39 +02:00
"strings"
2020-06-23 22:30:59 +02:00
//"fmt"
2020-06-09 21:50:39 +02:00
)
2020-06-22 23:00:01 +02:00
//TODO: validate a record for minimal values
2020-06-09 21:50:39 +02:00
// LogLine is used to store all the data of a single log line
type LogLine struct {
2020-07-12 22:33:01 +02:00
Date string
MyCall string
Operator string
MyWWFF string
MySOTA string
QslMsgFromHeader string
Nickname string
Mode string
ModeType string
Band string
BandLowerLimit float64
BandUpperLimit float64
Frequency string
Time string
ActualTime string //time actually recorded in FLE
Call string
Comment string
QSLmsg string
OMname string
GridLoc string
RSTsent string
RSTrcvd string
WWFF string
SOTA string
2020-06-09 21:50:39 +02:00
}
2020-06-12 21:15:19 +02:00
var regexpIsFullTime = regexp.MustCompile("^[0-2]{1}[0-9]{3}$")
var regexpIsTimePart = regexp.MustCompile("^[0-5]{1}[0-9]{1}$|^[1-9]{1}$")
var regexpIsOMname = regexp.MustCompile("^@")
var regexpIsGridLoc = regexp.MustCompile("^#")
var regexpIsRst = regexp.MustCompile("^[\\d]{1,3}$")
2020-06-23 22:30:59 +02:00
var regexpIsFreq = regexp.MustCompile("^[\\d]+\\.[\\d]+$")
2020-06-09 21:50:39 +02:00
// ParseLine cuts a FLE line into useful bits
2020-06-25 21:05:54 +02:00
func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg string) {
2020-06-09 21:50:39 +02:00
//TODO: input null protection?
2020-06-13 21:51:53 +02:00
//Flag telling that we are processing data to the right of the callsign
2020-06-20 14:49:18 +02:00
isRightOfCall := false
2020-06-13 21:51:53 +02:00
//Flag used to know if we are parsing the Sent RST (first) or received RST (second)
haveSentRST := false
2020-06-12 21:15:19 +02:00
//TODO: Make something more intelligent
2020-06-20 14:49:18 +02:00
//TODO: What happens if we have partial lines
2020-06-13 21:51:53 +02:00
previousLine.Call = ""
previousLine.RSTsent = ""
previousLine.RSTrcvd = ""
previousLine.SOTA = ""
previousLine.WWFF = ""
previousLine.OMname = ""
previousLine.GridLoc = ""
previousLine.Comment = ""
2020-07-10 22:49:28 +02:00
previousLine.ActualTime = ""
2020-06-09 21:50:39 +02:00
logLine = previousLine
2020-06-10 22:58:47 +02:00
//TODO: what happens when we have <> or when there are multiple comments
2020-06-11 09:11:04 +02:00
//TODO: Refactor this! it is ugly
2020-06-25 21:05:54 +02:00
comment, inputStr := getBraketedData(inputStr, COMMENT)
2020-06-10 22:58:47 +02:00
if comment != "" {
logLine.Comment = comment
}
2020-06-25 21:05:54 +02:00
QSLmsg, inputStr := getBraketedData(inputStr, QSL)
2020-06-11 22:44:22 +02:00
if QSLmsg != "" {
logLine.QSLmsg = QSLmsg
2020-06-11 09:11:04 +02:00
}
2020-06-09 21:50:39 +02:00
elements := strings.Fields(inputStr)
for _, element := range elements {
// Is it a mode?
2020-06-25 21:05:54 +02:00
if lookupMode(strings.ToUpper(element)) {
2020-06-09 21:50:39 +02:00
logLine.Mode = strings.ToUpper(element)
//TODO: improve this: what if the band is at the end of the line
2020-06-13 21:51:53 +02:00
// Set the default RST depending of the mode
if (logLine.RSTsent == "") || (logLine.RSTrcvd == "") {
// get default RST and Mode category
modeType, defaultReport := getDefaultReport(logLine.Mode)
logLine.ModeType = modeType
logLine.RSTsent = defaultReport
logLine.RSTrcvd = defaultReport
2020-06-13 21:51:53 +02:00
} else {
errorMsg = errorMsg + "Double definitiion of RST"
}
2020-06-09 21:50:39 +02:00
continue
}
// Is it a band?
2020-07-14 21:39:31 +02:00
isBandElement, bandLowerLimit, bandUpperLimit, _ := IsBand(element)
2020-06-20 20:38:09 +02:00
if isBandElement {
logLine.Band = strings.ToLower(element)
logLine.BandLowerLimit = bandLowerLimit
logLine.BandUpperLimit = bandUpperLimit
2020-06-09 21:50:39 +02:00
continue
}
2020-06-23 14:03:23 +02:00
// Is it a Frequency?
if regexpIsFreq.MatchString(element) {
2020-06-23 22:30:59 +02:00
var qrg float64
2020-06-25 21:05:54 +02:00
qrg, _ = strconv.ParseFloat(element, 32)
if (logLine.BandLowerLimit != 0.0) && (logLine.BandUpperLimit != 0.0) {
2020-06-23 22:30:59 +02:00
if (qrg >= logLine.BandLowerLimit) && (qrg <= logLine.BandUpperLimit) {
2020-06-25 21:05:54 +02:00
logLine.Frequency = fmt.Sprintf("%.3f", qrg)
2020-06-23 22:30:59 +02:00
} else {
logLine.Frequency = ""
errorMsg = errorMsg + " Frequency " + element + " is invalid for " + logLine.Band + " band"
}
} else {
errorMsg = errorMsg + " Unable to load frequency " + element + ": no band defined."
}
2020-06-23 14:03:23 +02:00
continue
}
2020-06-11 22:44:22 +02:00
// Is it a call sign ?
if validCallRegexp.MatchString(strings.ToUpper(element)) {
callErrorMsg := ""
logLine.Call, callErrorMsg = ValidateCall(element)
errorMsg = errorMsg + callErrorMsg
2020-06-20 14:49:18 +02:00
isRightOfCall = true
2020-06-11 22:44:22 +02:00
continue
}
2020-06-12 21:15:19 +02:00
// Is it a "full" time ?
2020-06-20 14:49:18 +02:00
if isRightOfCall == false {
if regexpIsFullTime.MatchString(element) {
2020-06-12 21:15:19 +02:00
logLine.Time = element
2020-07-10 22:49:28 +02:00
logLine.ActualTime = element
2020-06-20 14:49:18 +02:00
continue
}
// Is it a partial time ?
if regexpIsTimePart.MatchString(element) {
if logLine.Time == "" {
logLine.Time = element
2020-07-10 22:49:28 +02:00
logLine.ActualTime = element
2020-06-20 14:49:18 +02:00
} else {
goodPart := logLine.Time[:len(logLine.Time)-len(element)]
logLine.Time = goodPart + element
2020-07-10 22:49:28 +02:00
logLine.ActualTime = goodPart + element
2020-06-20 14:49:18 +02:00
}
continue
2020-06-12 21:15:19 +02:00
}
}
// Is it the OM's name (starting with "@")
if regexpIsOMname.MatchString(element) {
2020-06-25 21:05:54 +02:00
logLine.OMname = strings.TrimLeft(element, "@")
continue
}
// Is it the Grid Locator (starting with "#")
if regexpIsGridLoc.MatchString(element) {
2020-06-25 21:05:54 +02:00
logLine.GridLoc = strings.TrimLeft(element, "#")
continue
}
2020-06-12 21:15:19 +02:00
2020-06-20 14:49:18 +02:00
if isRightOfCall {
//This is probably a RST
if regexpIsRst.MatchString(element) {
workRST := ""
switch len(element) {
case 1:
if logLine.ModeType == "CW" {
workRST = "5" + element + "9"
2020-06-25 21:05:54 +02:00
} else {
if logLine.ModeType == "PHONE" {
workRST = "5" + element
2020-06-25 21:05:54 +02:00
}
}
case 2:
if logLine.ModeType == "CW" {
workRST = element + "9"
2020-06-25 21:05:54 +02:00
} else {
if logLine.ModeType == "PHONE" {
workRST = element
2020-06-25 21:05:54 +02:00
}
}
case 3:
if logLine.ModeType == "CW" {
workRST = element
} else {
workRST = "*" + element
errorMsg = errorMsg + "Invalid report (" + element + ") for " + logLine.ModeType + " mode "
}
}
if haveSentRST {
logLine.RSTrcvd = workRST
} else {
logLine.RSTsent = workRST
haveSentRST = true
}
continue
}
// Is it a WWFF to WWFF reference?
2020-06-25 21:05:54 +02:00
workRef, wwffErr := ValidateWwff(element)
if wwffErr == "" {
logLine.WWFF = workRef
continue
}
// Is it a WWFF to WWFF reference?
2020-06-25 21:05:54 +02:00
workRef, sotaErr := ValidateSota(element)
if sotaErr == "" {
logLine.SOTA = workRef
continue
}
2020-06-20 14:49:18 +02:00
}
2020-06-09 21:50:39 +02:00
//If we come here, we could not make sense of what we found
errorMsg = errorMsg + "Unable to parse " + element + " "
}
//If no report is present, let's fill it with mode default
if logLine.RSTsent == "" {
_, logLine.RSTsent = getDefaultReport(logLine.Mode)
}
if logLine.RSTrcvd == "" {
_, logLine.RSTrcvd = getDefaultReport(logLine.Mode)
}
2020-06-09 21:50:39 +02:00
2020-06-23 22:30:59 +02:00
//For debug purposes
//fmt.Println("\n", SprintLogRecord(logLine))
2020-06-09 21:50:39 +02:00
return logLine, errorMsg
}
func lookupMode(lookup string) bool {
switch lookup {
case
2020-06-25 21:05:54 +02:00
"CW",
"SSB",
2020-06-09 21:50:39 +02:00
"AM",
"FM",
2020-06-25 21:05:54 +02:00
"RTTY",
2020-06-09 21:50:39 +02:00
"FT8",
"PSK",
"JT65",
"JT9",
"FT4",
"JS8",
"ARDOP",
"ATV",
"C4FM",
"CHIP",
"CLO",
"CONTESTI",
"DIGITALVOICE",
"DOMINO",
"DSTAR",
"FAX",
"FSK441",
"HELL",
"ISCAT",
"JT4",
"JT6M",
"JT44",
"MFSK",
"MSK144",
"MT63",
"OLIVIA",
"OPERA",
"PAC",
"PAX",
"PKT",
"PSK2K",
"Q15",
"QRA64",
"ROS",
"RTTYM",
"SSTV",
"T10",
"THOR",
"THRB",
"TOR",
"V4",
"VOI",
"WINMOR",
2020-06-25 21:05:54 +02:00
"WSPR":
2020-06-09 21:50:39 +02:00
return true
}
return false
}