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

298 lines
6.6 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
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
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?
if regexpIsBand.MatchString(element) {
logLine.Band = element
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 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 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 + "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
}
// func lookupBand(lookup string) bool {
// switch lookup {
// case
// "900898296857",
// "900898302052",
// "900898296492",
// "900898296850",
// "900898296703",
// "900898296633",
// "900898296613",
// "900898296615",
// "900898296620",
// "900898296636":
// return true
// }
// return false
// }
// 2190m .1357 .1378
// 630m .472 .479
// 560m .501 .504
// 160m 1.8 2.0
// 80m 3.5 4.0
// 60m 5.06 5.45
// 40m 7.0 7.3
// 30m 10.1 10.15
// 20m 14.0 14.35
// 17m 18.068 18.168
// 15m 21.0 21.45
// 12m 24.890 24.99
// 10m 28.0 29.7
// 6m 50 54
// 4m 70 71
// 2m 144 148
// 1.25m 222 225
// 70cm 420 450
// 33cm 902 928
// 23cm 1240 1300
// 13cm 2300 2450
// 9cm 3300 3500
// 6cm 5650 5925
// 3cm 10000 10500
// 1.25cm 24000 24250
// 6mm 47000 47200
// 4mm 75500 81000
// 2.5mm 119980 120020
// 2mm 142000 149000
// 1mm 241000 250000