You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FLEcli/cmd/parse_line.go

268 lines
6.4 KiB

package cmd
/*
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 (
"regexp"
"strings"
"fmt"
)
// LogLine is used to store all the data of a single log line
type LogLine struct {
Date string
MyCall string
Operator string
MyWWFF string
MySOTA string
QslMsg string
Nickname string
Mode string
Band string
BandLowerLimit float32
BandUpperLimit float32
Frequency string
Time string
Call string
Comment string
QSLmsg string
OMname string
GridLoc string
RSTsent string
RSTrcvd string
}
var regexpIsBand = regexp.MustCompile("m$")
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("^#")
// ParseLine cuts a FLE line into useful bits
func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg string){
//TODO: input null protection?
//Flag telling that we are processing data to the right of the callsign
isRightOfCall := false
//TODO: Make something more intelligent
//TODO: What happens if we have partial lines
previousLine.Call = ""
previousLine.RSTsent = ""
previousLine.RSTrcvd = ""
logLine = previousLine
//TODO: what happens when we have <> or when there are multiple comments
//TODO: Refactor this! it is ugly
comment,inputStr := getBraketedData(inputStr, COMMENT)
if comment != "" {
logLine.Comment = comment
fmt.Println("Cleaned input string: ", inputStr)
}
QSLmsg,inputStr := getBraketedData(inputStr, QSL)
if QSLmsg != "" {
logLine.QSLmsg = QSLmsg
fmt.Println("Cleaned input string: ", inputStr)
}
elements := strings.Fields(inputStr)
for _, element := range elements {
// Is it a mode?
if lookupMode( strings.ToUpper(element)) {
logLine.Mode = strings.ToUpper(element)
// Set the default RST depending of the mode
if (logLine.RSTsent == "") || (logLine.RSTrcvd == "") {
switch logLine.Mode {
case "SSB", "AM", "FM" :
logLine.RSTsent = "59"
logLine.RSTrcvd = "59"
case "CW", "RTTY", "PSK":
logLine.RSTsent = "599"
logLine.RSTrcvd = "599"
case "JT65", "JT9", "JT6M", "JT4", "JT44", "FSK441", "FT8", "ISCAT", "MSK144", "QRA64", "T10", "WSPR" :
logLine.RSTsent = "-10"
logLine.RSTrcvd = "-10"
}
} else {
errorMsg = errorMsg + "Double definitiion of RST"
}
continue
}
// Is it a band?
isBandElement, bandLowerLimit, bandUpperLimit := IsBand(element)
if isBandElement {
logLine.Band = strings.ToLower(element)
logLine.BandLowerLimit = bandLowerLimit
logLine.BandUpperLimit = bandUpperLimit
continue
}
// Is it a call sign ?
if validCallRegexp.MatchString(strings.ToUpper(element)) {
callErrorMsg := ""
logLine.Call, callErrorMsg = ValidateCall(element)
errorMsg = errorMsg + callErrorMsg
isRightOfCall = true
continue
}
// Is it a "full" time ?
if isRightOfCall == false {
if regexpIsFullTime.MatchString(element) {
logLine.Time = element
continue
}
// Is it a partial time ?
if regexpIsTimePart.MatchString(element) {
if logLine.Time == "" {
logLine.Time = element
} else {
goodPart := logLine.Time[:len(logLine.Time)-len(element)]
logLine.Time = goodPart + element
}
continue
}
}
// Is it the OM's name (starting with "@")
if regexpIsOMname.MatchString(element) {
logLine.OMname = strings.TrimLeft(element, "@")
continue
}
// Is it the Grid Locator (starting with "#")
if regexpIsGridLoc.MatchString(element) {
logLine.GridLoc = strings.TrimLeft(element, "#")
continue
}
if isRightOfCall {
//This is probably a RST
//TODO: is it a number (or a data report)
//TODO: it is sent or rcvd
}
//If we come here, we could not make sense of what we found
errorMsg = errorMsg + "Unable to parse " + element + " "
}
fmt.Println(elements, len(elements))
fmt.Println("\n", SprintLogRecord(logLine))
return logLine, errorMsg
}
// SprintLogRecord outputs the content of a logline
func SprintLogRecord(logLine LogLine) (output string){
output = ""
output = output + "Date " + logLine.Date + "\n"
output = output + "MyCall " + logLine.MyCall + "\n"
output = output + "Operator " + logLine.Operator + "\n"
output = output + "MyWWFF " + logLine.MyWWFF + "\n"
output = output + "MySOTA " + logLine.MySOTA + "\n"
output = output + "QslMsg " + logLine.QslMsg + "\n"
output = output + "Nickname " + logLine.Nickname + "\n"
output = output + "Mode " + logLine.Mode + "\n"
output = output + "Band " + logLine.Band + "\n"
output = output + " Lower " + fmt.Sprintf("%f", logLine.BandLowerLimit) + "\n"
output = output + " Upper " + fmt.Sprintf("%f", logLine.BandLowerLimit) + "\n"
output = output + "Frequency " + logLine.Frequency + "\n"
output = output + "Time " + logLine.Time + "\n"
output = output + "Call " + logLine.Call + "\n"
output = output + "Comment " + logLine.Comment + "\n"
output = output + "QSLmsg " + logLine.QSLmsg + "\n"
output = output + "OMname " + logLine.OMname + "\n"
output = output + "GridLoc " + logLine.GridLoc + "\n"
output = output + "RSTsent " + logLine.RSTsent + "\n"
output = output + "RSTrcvd " + logLine.RSTrcvd + "\n"
return output
}
func lookupMode(lookup string) bool {
switch lookup {
case
"CW",
"SSB",
"AM",
"FM",
"RTTY",
"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",
"WSPR":
return true
}
return false
}