Reformat the sources with go fmt

pull/2/head
Jean-Marc MEESSEN 4 years ago
parent 590988f3ad
commit ab925ad2dd

@ -1,4 +1,5 @@
package cmd package cmd
/* /*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com> Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
@ -24,8 +25,8 @@ type BraketType int
//Enumeration of the valid Bracket Types //Enumeration of the valid Bracket Types
const ( const (
COMMENT BraketType = iota COMMENT BraketType = iota
QSL QSL
) )
func getBraketedData(inputLine string, braketType BraketType) (braketedData, cleanedLine string) { func getBraketedData(inputLine string, braketType BraketType) (braketedData, cleanedLine string) {
@ -37,26 +38,26 @@ func getBraketedData(inputLine string, braketType BraketType) (braketedData, cle
if braketType == COMMENT { if braketType == COMMENT {
a = "<" a = "<"
b = ">" b = ">"
} }
if braketType == QSL { if braketType == QSL {
a = "[" a = "["
b = "]" b = "]"
} }
posFirst := strings.Index(inputLine, a) posFirst := strings.Index(inputLine, a)
if posFirst == -1 { if posFirst == -1 {
return "",inputLine return "", inputLine
} }
posLast := strings.Index(inputLine, b) posLast := strings.Index(inputLine, b)
if posLast == -1 { if posLast == -1 {
return "",inputLine return "", inputLine
} }
posFirstAdjusted := posFirst + 1 posFirstAdjusted := posFirst + 1
if posFirstAdjusted > posLast { if posFirstAdjusted > posLast {
return "",inputLine return "", inputLine
} }
braketedData = inputLine[posFirstAdjusted:posLast] braketedData = inputLine[posFirstAdjusted:posLast]
cleanedLine = strings.Replace(inputLine, a + braketedData + b, "",1) cleanedLine = strings.Replace(inputLine, a+braketedData+b, "", 1)
return braketedData, cleanedLine return braketedData, cleanedLine
} }

@ -14,45 +14,45 @@ func Test_getBraketedData(t *testing.T) {
wantCleanedLine string wantCleanedLine string
}{ }{
{ {
"Happy case: comment", "Happy case: comment",
args{ inputLine: "aaaa <bracketed text> bbbbb", braketType: COMMENT}, args{inputLine: "aaaa <bracketed text> bbbbb", braketType: COMMENT},
"bracketed text", "bracketed text",
"aaaa bbbbb", "aaaa bbbbb",
}, },
{ {
"Happy case: QSL", "Happy case: QSL",
args{ inputLine: "aaaa [bracketed text] bbbbb", braketType: QSL}, args{inputLine: "aaaa [bracketed text] bbbbb", braketType: QSL},
"bracketed text", "bracketed text",
"aaaa bbbbb", "aaaa bbbbb",
}, },
{ {
"Happy case: nothing", "Happy case: nothing",
args{ inputLine: "aaaa bbbbb cccccc", braketType: QSL}, args{inputLine: "aaaa bbbbb cccccc", braketType: QSL},
"", "",
"aaaa bbbbb cccccc", "aaaa bbbbb cccccc",
}, },
{ {
"Empty brackets", "Empty brackets",
args{ inputLine: "aaaa <> bbbbb", braketType: COMMENT}, args{inputLine: "aaaa <> bbbbb", braketType: COMMENT},
"", "",
"aaaa bbbbb", "aaaa bbbbb",
}, },
{ {
"Brackets at right", "Brackets at right",
args{ inputLine: "aaaa bbbbb <bracketed text>", braketType: COMMENT}, args{inputLine: "aaaa bbbbb <bracketed text>", braketType: COMMENT},
"bracketed text", "bracketed text",
"aaaa bbbbb ", "aaaa bbbbb ",
}, },
{ {
"concatenated", "concatenated",
args{ inputLine: "aaaa<bracketed text>bbbbb", braketType: COMMENT}, args{inputLine: "aaaa<bracketed text>bbbbb", braketType: COMMENT},
"bracketed text", "bracketed text",
"aaaabbbbb", "aaaabbbbb",
}, },
{ {
"duplicated", "duplicated",
args{ inputLine: "aaaa <bracketed text> bbbbb < double > cccc", braketType: COMMENT}, args{inputLine: "aaaa <bracketed text> bbbbb < double > cccc", braketType: COMMENT},
"bracketed text", "bracketed text",
"aaaa bbbbb < double > cccc", "aaaa bbbbb < double > cccc",
}, },
} }

@ -1,4 +1,5 @@
package cmd package cmd
/* /*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com> Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
@ -19,7 +20,7 @@ import (
) )
// SprintLogRecord outputs the content of a logline // SprintLogRecord outputs the content of a logline
func SprintLogRecord(logLine LogLine) (output string){ func SprintLogRecord(logLine LogLine) (output string) {
output = "" output = ""
output = output + "Date " + logLine.Date + "\n" output = output + "Date " + logLine.Date + "\n"
output = output + "MyCall " + logLine.MyCall + "\n" output = output + "MyCall " + logLine.MyCall + "\n"
@ -49,10 +50,10 @@ func SprintLogRecord(logLine LogLine) (output string){
} }
// SprintHeaderValues displays the header values // SprintHeaderValues displays the header values
func SprintHeaderValues(logLine LogLine) (output string){ func SprintHeaderValues(logLine LogLine) (output string) {
output = "" output = ""
output = output + "MyCall " + logLine.MyCall output = output + "MyCall " + logLine.MyCall
if logLine.Operator != "" { if logLine.Operator != "" {
output = output + " (" + logLine.Operator + ")" output = output + " (" + logLine.Operator + ")"
} }
@ -66,21 +67,21 @@ func SprintHeaderValues(logLine LogLine) (output string){
output = output + "MySOTA " + logLine.MySOTA + "\n" output = output + "MySOTA " + logLine.MySOTA + "\n"
} }
return output return output
} }
// Date, Time, band, mode, call, report sent, report rcvd, Notes // Date, Time, band, mode, call, report sent, report rcvd, Notes
var logLineFormat = "%-10s %-4s %-4s %-4s %-10s %-4s %-4s %s \n" var logLineFormat = "%-10s %-4s %-4s %-4s %-10s %-4s %-4s %s \n"
// SprintColumnTitles displays the column titles for a log line // SprintColumnTitles displays the column titles for a log line
func SprintColumnTitles(logLine LogLine) (output string){ func SprintColumnTitles(logLine LogLine) (output string) {
output = fmt.Sprintf(logLineFormat, "Date", "Time", "Band", "Mode", "Call", "Sent", "Rcvd", "Notes") output = fmt.Sprintf(logLineFormat, "Date", "Time", "Band", "Mode", "Call", "Sent", "Rcvd", "Notes")
output = output + fmt.Sprintf(logLineFormat, "----", "----", "----", "----", "----", "----", "----", "----") output = output + fmt.Sprintf(logLineFormat, "----", "----", "----", "----", "----", "----", "----", "----")
return output return output
} }
// SprintLogInColumn displays the logLine in column mode // SprintLogInColumn displays the logLine in column mode
func SprintLogInColumn(logLine LogLine) (output string){ func SprintLogInColumn(logLine LogLine) (output string) {
notes := "" notes := ""
if logLine.Frequency != "" { if logLine.Frequency != "" {
notes = notes + "QRG: " + logLine.Frequency + " " notes = notes + "QRG: " + logLine.Frequency + " "
@ -107,4 +108,4 @@ func SprintLogInColumn(logLine LogLine) (output string){
output = fmt.Sprintf(logLineFormat, logLine.Date, logLine.Time, logLine.Band, logLine.Mode, logLine.Call, logLine.RSTsent, logLine.RSTrcvd, notes) output = fmt.Sprintf(logLineFormat, logLine.Date, logLine.Time, logLine.Band, logLine.Mode, logLine.Call, logLine.RSTsent, logLine.RSTrcvd, notes)
return output return output
} }

@ -1,4 +1,5 @@
package cmd package cmd
/* /*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com> Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
@ -16,9 +17,9 @@ limitations under the License.
*/ */
import ( import (
"bufio"
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"bufio"
"log" "log"
"os" "os"
"regexp" "regexp"
@ -29,12 +30,12 @@ import (
var loadCmd = &cobra.Command{ var loadCmd = &cobra.Command{
Use: "load", Use: "load",
Short: "Loads and validates a FLE type logfile", Short: "Loads and validates a FLE type logfile",
// Long: `A longer description that spans multiple lines and likely contains examples // Long: `A longer description that spans multiple lines and likely contains examples
// and usage of using your command. For example: // and usage of using your command. For example:
// Cobra is a CLI library for Go that empowers applications. // Cobra is a CLI library for Go that empowers applications.
// This application is a tool to generate the needed files // This application is a tool to generate the needed files
// to quickly create a Cobra application.`, // to quickly create a Cobra application.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
//fmt.Println("load called") //fmt.Println("load called")
//fmt.Println("Inputfile: ",inputFilename) //fmt.Println("Inputfile: ",inputFilename)
@ -58,19 +59,19 @@ func init() {
func loadFile() { func loadFile() {
file, err := os.Open(inputFilename) file, err := os.Open(inputFilename)
if err != nil { if err != nil {
log.Fatalf("failed opening file: %s", err) log.Fatalf("failed opening file: %s", err)
} }
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines) scanner.Split(bufio.ScanLines)
var txtlines []string var txtlines []string
for scanner.Scan() { for scanner.Scan() {
txtlines = append(txtlines, scanner.Text()) txtlines = append(txtlines, scanner.Text())
} }
file.Close() file.Close()
regexpLineComment, _ := regexp.Compile("^#") regexpLineComment, _ := regexp.Compile("^#")
@ -79,14 +80,13 @@ func loadFile() {
regexpStartMultiLineComment, _ := regexp.Compile("^{") regexpStartMultiLineComment, _ := regexp.Compile("^{")
regexpEndMultiLineComment, _ := regexp.Compile("}$") regexpEndMultiLineComment, _ := regexp.Compile("}$")
regexpHeaderMyCall, _ := regexp.Compile("(?i)^mycall ") regexpHeaderMyCall, _ := regexp.Compile("(?i)^mycall ")
regexpHeaderOperator, _ := regexp.Compile("(?i)^operator ") regexpHeaderOperator, _ := regexp.Compile("(?i)^operator ")
regexpHeaderMyWwff, _ := regexp.Compile("(?i)^mywwff ") regexpHeaderMyWwff, _ := regexp.Compile("(?i)^mywwff ")
regexpHeaderMySota, _ := regexp.Compile("(?i)^mysota ") regexpHeaderMySota, _ := regexp.Compile("(?i)^mysota ")
regexpHeaderQslMsg, _ := regexp.Compile("(?i)^qslmsg ") regexpHeaderQslMsg, _ := regexp.Compile("(?i)^qslmsg ")
regexpHeaderNickname, _ := regexp.Compile("(?i)^nickname ") regexpHeaderNickname, _ := regexp.Compile("(?i)^nickname ")
regexpHeaderDate, _ := regexp.Compile("(?i)^date ") regexpHeaderDate, _ := regexp.Compile("(?i)^date ")
headerMyCall := "" headerMyCall := ""
headerOperator := "" headerOperator := ""
headerMyWWFF := "" headerMyWWFF := ""
@ -96,14 +96,13 @@ func loadFile() {
headerDate := "" headerDate := ""
lineCount := 0 lineCount := 0
var isInMultiLine = false var isInMultiLine = false
var cleanedInput []string var cleanedInput []string
var errorLog []string var errorLog []string
var previousLogLine LogLine var previousLogLine LogLine
var fullLog []LogLine var fullLog []LogLine
//Loop through all the stored lined //Loop through all the stored lined
for _, eachline := range txtlines { for _, eachline := range txtlines {
lineCount++ lineCount++
@ -113,25 +112,25 @@ func loadFile() {
// **** // ****
//Skip the line if it starts with "#" //Skip the line if it starts with "#"
if(regexpLineComment.MatchString(eachline)) { if regexpLineComment.MatchString(eachline) {
continue continue
} }
//Skip if line is empty or blank //Skip if line is empty or blank
if((len(eachline) == 0) || (regexpOnlySpaces.MatchString(eachline))) { if (len(eachline) == 0) || (regexpOnlySpaces.MatchString(eachline)) {
continue continue
} }
// Process multi-line comments // Process multi-line comments
if(regexpStartMultiLineComment.MatchString(eachline)) { if regexpStartMultiLineComment.MatchString(eachline) {
//Single-line "multi-line" coment //Single-line "multi-line" coment
if(regexpSingleMultiLineComment.MatchString(eachline)) { if regexpSingleMultiLineComment.MatchString(eachline) {
continue continue
} }
isInMultiLine = true isInMultiLine = true
continue continue
} }
if(isInMultiLine) { if isInMultiLine {
if(regexpEndMultiLineComment.MatchString(eachline)) { if regexpEndMultiLineComment.MatchString(eachline) {
isInMultiLine = false isInMultiLine = false
} }
continue continue
@ -142,29 +141,29 @@ func loadFile() {
// **** // ****
//My Call //My Call
if(regexpHeaderMyCall.MatchString(eachline)) { if regexpHeaderMyCall.MatchString(eachline) {
errorMsg := "" errorMsg := ""
myCallList := regexpHeaderMyCall.Split(eachline,-1) myCallList := regexpHeaderMyCall.Split(eachline, -1)
if(len(myCallList[1]) > 0) { if len(myCallList[1]) > 0 {
headerMyCall, errorMsg = ValidateCall(myCallList[1]) headerMyCall, errorMsg = ValidateCall(myCallList[1])
cleanedInput = append(cleanedInput, fmt.Sprintf("My call: %s", headerMyCall)) cleanedInput = append(cleanedInput, fmt.Sprintf("My call: %s", headerMyCall))
if(len(errorMsg) != 0) { if len(errorMsg) != 0 {
errorLog = append(errorLog, fmt.Sprintf("Invalid myCall at line %d: %s (%s)",lineCount, myCallList[1], errorMsg)) errorLog = append(errorLog, fmt.Sprintf("Invalid myCall at line %d: %s (%s)", lineCount, myCallList[1], errorMsg))
} }
} }
//If there is no data after the marker, we just skip the data. //If there is no data after the marker, we just skip the data.
continue continue
} }
//Operator //Operator
if(regexpHeaderOperator.MatchString(eachline)) { if regexpHeaderOperator.MatchString(eachline) {
errorMsg := "" errorMsg := ""
myOperatorList := regexpHeaderOperator.Split(eachline,-1) myOperatorList := regexpHeaderOperator.Split(eachline, -1)
if(len(myOperatorList[1]) > 0) { if len(myOperatorList[1]) > 0 {
headerOperator, errorMsg = ValidateCall(myOperatorList[1]) headerOperator, errorMsg = ValidateCall(myOperatorList[1])
cleanedInput = append(cleanedInput, fmt.Sprintf("Operator: %s", headerOperator)) cleanedInput = append(cleanedInput, fmt.Sprintf("Operator: %s", headerOperator))
if(len(errorMsg) != 0) { if len(errorMsg) != 0 {
errorLog = append(errorLog, fmt.Sprintf("Invalid Operator at line %d: %s (%s)",lineCount, myOperatorList[1], errorMsg)) errorLog = append(errorLog, fmt.Sprintf("Invalid Operator at line %d: %s (%s)", lineCount, myOperatorList[1], errorMsg))
} }
} }
//If there is no data after the marker, we just skip the data. //If there is no data after the marker, we just skip the data.
@ -172,29 +171,29 @@ func loadFile() {
} }
// My WWFF // My WWFF
if(regexpHeaderMyWwff.MatchString(eachline)) { if regexpHeaderMyWwff.MatchString(eachline) {
errorMsg := "" errorMsg := ""
myWwffList := regexpHeaderMyWwff.Split(eachline,-1) myWwffList := regexpHeaderMyWwff.Split(eachline, -1)
if(len(myWwffList[1]) > 0) { if len(myWwffList[1]) > 0 {
headerMyWWFF, errorMsg = ValidateWwff(myWwffList[1]) headerMyWWFF, errorMsg = ValidateWwff(myWwffList[1])
cleanedInput = append(cleanedInput, fmt.Sprintf("My WWFF: %s", headerMyWWFF)) cleanedInput = append(cleanedInput, fmt.Sprintf("My WWFF: %s", headerMyWWFF))
if(len(errorMsg) != 0) { if len(errorMsg) != 0 {
errorLog = append(errorLog, fmt.Sprintf("Invalid \"My WWFF\" at line %d: %s (%s)",lineCount, myWwffList[1], errorMsg)) errorLog = append(errorLog, fmt.Sprintf("Invalid \"My WWFF\" at line %d: %s (%s)", lineCount, myWwffList[1], errorMsg))
} }
} }
//If there is no data after the marker, we just skip the data. //If there is no data after the marker, we just skip the data.
continue continue
} }
//My Sota //My Sota
if(regexpHeaderMySota.MatchString(eachline)) { if regexpHeaderMySota.MatchString(eachline) {
errorMsg := "" errorMsg := ""
mySotaList := regexpHeaderMySota.Split(eachline,-1) mySotaList := regexpHeaderMySota.Split(eachline, -1)
if(len(mySotaList[1]) > 0) { if len(mySotaList[1]) > 0 {
headerMySOTA, errorMsg = ValidateSota(mySotaList[1]) headerMySOTA, errorMsg = ValidateSota(mySotaList[1])
cleanedInput = append(cleanedInput, fmt.Sprintf("My Sota: %s", headerMySOTA)) cleanedInput = append(cleanedInput, fmt.Sprintf("My Sota: %s", headerMySOTA))
if(len(errorMsg) != 0) { if len(errorMsg) != 0 {
errorLog = append(errorLog, fmt.Sprintf("Invalid \"My SOTA\" at line %d: %s (%s)",lineCount, mySotaList[1], errorMsg)) errorLog = append(errorLog, fmt.Sprintf("Invalid \"My SOTA\" at line %d: %s (%s)", lineCount, mySotaList[1], errorMsg))
} }
} }
//If there is no data after the marker, we just skip the data. //If there is no data after the marker, we just skip the data.
@ -202,9 +201,9 @@ func loadFile() {
} }
//QSL Message //QSL Message
if(regexpHeaderQslMsg.MatchString(eachline)) { if regexpHeaderQslMsg.MatchString(eachline) {
myQslMsgList := regexpHeaderQslMsg.Split(eachline,-1) myQslMsgList := regexpHeaderQslMsg.Split(eachline, -1)
if(len(myQslMsgList[1]) > 0) { if len(myQslMsgList[1]) > 0 {
headerQslMsg = myQslMsgList[1] headerQslMsg = myQslMsgList[1]
cleanedInput = append(cleanedInput, fmt.Sprintf("QSL Message: %s", headerQslMsg)) cleanedInput = append(cleanedInput, fmt.Sprintf("QSL Message: %s", headerQslMsg))
} }
@ -213,9 +212,9 @@ func loadFile() {
} }
//Nickname //Nickname
if(regexpHeaderNickname.MatchString(eachline)) { if regexpHeaderNickname.MatchString(eachline) {
myNicknameList := regexpHeaderNickname.Split(eachline,-1) myNicknameList := regexpHeaderNickname.Split(eachline, -1)
if(len(myNicknameList[1]) > 0) { if len(myNicknameList[1]) > 0 {
headerNickname = myNicknameList[1] headerNickname = myNicknameList[1]
cleanedInput = append(cleanedInput, fmt.Sprintf("eQSL Nickmane: %s", headerNickname)) cleanedInput = append(cleanedInput, fmt.Sprintf("eQSL Nickmane: %s", headerNickname))
} }
@ -224,23 +223,23 @@ func loadFile() {
} }
// Date // Date
if(regexpHeaderDate.MatchString(eachline)) { if regexpHeaderDate.MatchString(eachline) {
errorMsg := "" errorMsg := ""
myDateList := regexpHeaderDate.Split(eachline,-1) myDateList := regexpHeaderDate.Split(eachline, -1)
if(len(myDateList[1]) > 0) { if len(myDateList[1]) > 0 {
headerDate, errorMsg = ValidateDate(myDateList[1]) headerDate, errorMsg = ValidateDate(myDateList[1])
if(len(errorMsg) != 0) { if len(errorMsg) != 0 {
errorLog = append(errorLog, fmt.Sprintf("Invalid Date at line %d: %s (%s)",lineCount, myDateList[1], errorMsg)) errorLog = append(errorLog, fmt.Sprintf("Invalid Date at line %d: %s (%s)", lineCount, myDateList[1], errorMsg))
} }
} }
//If there is no data after the marker, we just skip the data. //If there is no data after the marker, we just skip the data.
continue continue
} }
// **** // ****
// ** Process the data block // ** Process the data block
// **** // ****
// Load the header values in the previousLogLine // Load the header values in the previousLogLine
previousLogLine.MyCall = headerMyCall previousLogLine.MyCall = headerMyCall
previousLogLine.Operator = headerOperator previousLogLine.Operator = headerOperator
@ -256,7 +255,7 @@ func loadFile() {
fullLog = append(fullLog, logline) fullLog = append(fullLog, logline)
} }
if errorLine != "" { if errorLine != "" {
errorLog = append(errorLog, fmt.Sprintf("Parsing error at line %d: %s ",lineCount,errorLine)) errorLog = append(errorLog, fmt.Sprintf("Parsing error at line %d: %s ", lineCount, errorLine))
} }
previousLogLine = logline previousLogLine = logline
//Go back to the top (Continue not necessary) //Go back to the top (Continue not necessary)
@ -279,14 +278,13 @@ func loadFile() {
fmt.Print(SprintLogInColumn(filledLogLine)) fmt.Print(SprintLogInColumn(filledLogLine))
} }
if(len(errorLog) != 0){ if len(errorLog) != 0 {
fmt.Println("\nProcessing errors:") fmt.Println("\nProcessing errors:")
for _, errorLogLine := range errorLog { for _, errorLogLine := range errorLog {
fmt.Println(errorLogLine) fmt.Println(errorLogLine)
} }
} else { } else {
fmt.Println("\nSuccesfuly parsed ",lineCount, " lines.") fmt.Println("\nSuccesfuly parsed ", lineCount, " lines.")
} }
} }

@ -1,4 +1,5 @@
package cmd package cmd
/* /*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com> Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
@ -15,7 +16,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import ( import (
"fmt" "fmt"
"regexp" "regexp"
@ -26,32 +26,31 @@ import (
//TODO: validate a record for minimal values //TODO: validate a record for minimal values
// LogLine is used to store all the data of a single log line // LogLine is used to store all the data of a single log line
type LogLine struct { type LogLine struct {
Date string Date string
MyCall string MyCall string
Operator string Operator string
MyWWFF string MyWWFF string
MySOTA string MySOTA string
QslMsg string QslMsg string
Nickname string Nickname string
Mode string Mode string
ModeType string ModeType string
Band string Band string
BandLowerLimit float64 BandLowerLimit float64
BandUpperLimit float64 BandUpperLimit float64
Frequency string Frequency string
Time string Time string
Call string Call string
Comment string Comment string
QSLmsg string QSLmsg string
OMname string OMname string
GridLoc string GridLoc string
RSTsent string RSTsent string
RSTrcvd string RSTrcvd string
WWFF string WWFF string
SOTA string SOTA string
} }
var regexpIsFullTime = regexp.MustCompile("^[0-2]{1}[0-9]{3}$") var regexpIsFullTime = regexp.MustCompile("^[0-2]{1}[0-9]{3}$")
@ -62,7 +61,7 @@ var regexpIsRst = regexp.MustCompile("^[\\d]{1,3}$")
var regexpIsFreq = regexp.MustCompile("^[\\d]+\\.[\\d]+$") var regexpIsFreq = regexp.MustCompile("^[\\d]+\\.[\\d]+$")
// ParseLine cuts a FLE line into useful bits // ParseLine cuts a FLE line into useful bits
func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg string){ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg string) {
//TODO: input null protection? //TODO: input null protection?
//Flag telling that we are processing data to the right of the callsign //Flag telling that we are processing data to the right of the callsign
@ -85,23 +84,22 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
//TODO: what happens when we have <> or when there are multiple comments //TODO: what happens when we have <> or when there are multiple comments
//TODO: Refactor this! it is ugly //TODO: Refactor this! it is ugly
comment,inputStr := getBraketedData(inputStr, COMMENT) comment, inputStr := getBraketedData(inputStr, COMMENT)
if comment != "" { if comment != "" {
logLine.Comment = comment logLine.Comment = comment
} }
QSLmsg,inputStr := getBraketedData(inputStr, QSL) QSLmsg, inputStr := getBraketedData(inputStr, QSL)
if QSLmsg != "" { if QSLmsg != "" {
logLine.QSLmsg = QSLmsg logLine.QSLmsg = QSLmsg
} }
elements := strings.Fields(inputStr) elements := strings.Fields(inputStr)
for _, element := range elements { for _, element := range elements {
// Is it a mode? // Is it a mode?
if lookupMode( strings.ToUpper(element)) { if lookupMode(strings.ToUpper(element)) {
logLine.Mode = strings.ToUpper(element) logLine.Mode = strings.ToUpper(element)
//TODO: improve this: what if the band is at the end of the line //TODO: improve this: what if the band is at the end of the line
// Set the default RST depending of the mode // Set the default RST depending of the mode
@ -119,7 +117,7 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
} }
// Is it a band? // Is it a band?
isBandElement, bandLowerLimit, bandUpperLimit := IsBand(element) isBandElement, bandLowerLimit, bandUpperLimit := IsBand(element)
if isBandElement { if isBandElement {
logLine.Band = strings.ToLower(element) logLine.Band = strings.ToLower(element)
logLine.BandLowerLimit = bandLowerLimit logLine.BandLowerLimit = bandLowerLimit
@ -130,10 +128,10 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
// Is it a Frequency? // Is it a Frequency?
if regexpIsFreq.MatchString(element) { if regexpIsFreq.MatchString(element) {
var qrg float64 var qrg float64
qrg,_ = strconv.ParseFloat(element, 32) qrg, _ = strconv.ParseFloat(element, 32)
if (logLine.BandLowerLimit != 0.0) && (logLine.BandUpperLimit != 0.0){ if (logLine.BandLowerLimit != 0.0) && (logLine.BandUpperLimit != 0.0) {
if (qrg >= logLine.BandLowerLimit) && (qrg <= logLine.BandUpperLimit) { if (qrg >= logLine.BandLowerLimit) && (qrg <= logLine.BandUpperLimit) {
logLine.Frequency = fmt.Sprintf("%.3f",qrg) logLine.Frequency = fmt.Sprintf("%.3f", qrg)
} else { } else {
logLine.Frequency = "" logLine.Frequency = ""
errorMsg = errorMsg + " Frequency " + element + " is invalid for " + logLine.Band + " band" errorMsg = errorMsg + " Frequency " + element + " is invalid for " + logLine.Band + " band"
@ -171,18 +169,16 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
continue continue
} }
} }
// Is it the OM's name (starting with "@") // Is it the OM's name (starting with "@")
if regexpIsOMname.MatchString(element) { if regexpIsOMname.MatchString(element) {
logLine.OMname = strings.TrimLeft(element, "@") logLine.OMname = strings.TrimLeft(element, "@")
continue continue
} }
// Is it the Grid Locator (starting with "#") // Is it the Grid Locator (starting with "#")
if regexpIsGridLoc.MatchString(element) { if regexpIsGridLoc.MatchString(element) {
logLine.GridLoc = strings.TrimLeft(element, "#") logLine.GridLoc = strings.TrimLeft(element, "#")
continue continue
} }
@ -194,18 +190,18 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
case 1: case 1:
if logLine.ModeType == "CW" { if logLine.ModeType == "CW" {
workRST = "5" + element + "9" workRST = "5" + element + "9"
} else { } else {
if logLine.ModeType == "PHONE" { if logLine.ModeType == "PHONE" {
workRST = "5" + element workRST = "5" + element
} }
} }
case 2: case 2:
if logLine.ModeType == "CW" { if logLine.ModeType == "CW" {
workRST = element + "9" workRST = element + "9"
} else { } else {
if logLine.ModeType == "PHONE" { if logLine.ModeType == "PHONE" {
workRST = element workRST = element
} }
} }
case 3: case 3:
if logLine.ModeType == "CW" { if logLine.ModeType == "CW" {
@ -225,14 +221,14 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
} }
// Is it a WWFF to WWFF reference? // Is it a WWFF to WWFF reference?
workRef, wwffErr := ValidateWwff(element) workRef, wwffErr := ValidateWwff(element)
if wwffErr == "" { if wwffErr == "" {
logLine.WWFF = workRef logLine.WWFF = workRef
continue continue
} }
// Is it a WWFF to WWFF reference? // Is it a WWFF to WWFF reference?
workRef, sotaErr := ValidateSota(element) workRef, sotaErr := ValidateSota(element)
if sotaErr == "" { if sotaErr == "" {
logLine.SOTA = workRef logLine.SOTA = workRef
continue continue
@ -258,15 +254,14 @@ func ParseLine(inputStr string, previousLine LogLine) (logLine LogLine, errorMsg
return logLine, errorMsg return logLine, errorMsg
} }
func lookupMode(lookup string) bool { func lookupMode(lookup string) bool {
switch lookup { switch lookup {
case case
"CW", "CW",
"SSB", "SSB",
"AM", "AM",
"FM", "FM",
"RTTY", "RTTY",
"FT8", "FT8",
"PSK", "PSK",
"JT65", "JT65",
@ -310,11 +305,8 @@ func lookupMode(lookup string) bool {
"V4", "V4",
"VOI", "VOI",
"WINMOR", "WINMOR",
"WSPR": "WSPR":
return true return true
} }
return false return false
} }

@ -5,7 +5,6 @@ import (
"testing" "testing"
) )
func TestParseLine(t *testing.T) { func TestParseLine(t *testing.T) {
type args struct { type args struct {
inputStr string inputStr string
@ -18,94 +17,94 @@ func TestParseLine(t *testing.T) {
wantErrorMsg string wantErrorMsg string
}{ }{
{ {
"Parse band and mode only", "Parse band and mode only",
args{ inputStr: "40M cw", previousLine: LogLine{ Mode: "SSB", }}, args{inputStr: "40M cw", previousLine: LogLine{Mode: "SSB"}},
LogLine{ Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3, Mode: "CW", ModeType: "CW", RSTsent: "599", RSTrcvd: "599"}, "", LogLine{Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3, Mode: "CW", ModeType: "CW", RSTsent: "599", RSTrcvd: "599"}, "",
}, },
{ {
"Parse for time", "Parse for time",
args{ inputStr: "1314 g3noh", previousLine: LogLine{ Mode: "SSB", }}, args{inputStr: "1314 g3noh", previousLine: LogLine{Mode: "SSB"}},
LogLine{ Time: "1314", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Time: "1314", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Parse partial time - 1", "Parse partial time - 1",
args{ inputStr: "4 g3noh", previousLine: LogLine{ Time: "", Mode: "SSB", }}, args{inputStr: "4 g3noh", previousLine: LogLine{Time: "", Mode: "SSB"}},
LogLine{ Time: "4", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", //TODO: should fail LogLine{Time: "4", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", //TODO: should fail
}, },
{ {
"Parse partial time - 2", "Parse partial time - 2",
args{ inputStr: "15 g3noh", previousLine: LogLine{ Time: "1200", Mode: "SSB", }}, args{inputStr: "15 g3noh", previousLine: LogLine{Time: "1200", Mode: "SSB"}},
LogLine{ Time: "1215", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Time: "1215", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Parse partial time - 3", "Parse partial time - 3",
args{ inputStr: "4 g3noh", previousLine: LogLine{ Time: "1200", Mode: "SSB", }}, args{inputStr: "4 g3noh", previousLine: LogLine{Time: "1200", Mode: "SSB"}},
LogLine{ Time: "1204", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Time: "1204", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Parse for comment", "Parse for comment",
args{ inputStr: "4 g3noh <PSE QSL Direct>", previousLine: LogLine{ Mode: "SSB", }}, args{inputStr: "4 g3noh <PSE QSL Direct>", previousLine: LogLine{Mode: "SSB"}},
LogLine{ Time: "4", Comment: "PSE QSL Direct", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Time: "4", Comment: "PSE QSL Direct", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Parse for QSL", "Parse for QSL",
args{ inputStr: "g3noh [Custom QSL message]", previousLine: LogLine{ Mode: "SSB", }}, args{inputStr: "g3noh [Custom QSL message]", previousLine: LogLine{Mode: "SSB"}},
LogLine{ QSLmsg: "Custom QSL message", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{QSLmsg: "Custom QSL message", Call: "G3NOH", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Wrong mode", "Wrong mode",
args{ inputStr: "cww", previousLine: LogLine{ Mode: "SSB", }}, args{inputStr: "cww", previousLine: LogLine{Mode: "SSB"}},
LogLine{ Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "Unable to parse cww ", LogLine{Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "Unable to parse cww ",
}, },
{ {
"Parse OM name", "Parse OM name",
args{ inputStr: "@Jean", previousLine: LogLine{ Mode: "SSB", }}, args{inputStr: "@Jean", previousLine: LogLine{Mode: "SSB"}},
LogLine{ OMname: "Jean", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{OMname: "Jean", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Parse Grid locator", "Parse Grid locator",
args{ inputStr: "#grid", previousLine: LogLine{ Mode: "SSB", }}, args{inputStr: "#grid", previousLine: LogLine{Mode: "SSB"}},
LogLine{ GridLoc: "grid", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{GridLoc: "grid", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Parse frequency", "Parse frequency",
args{ inputStr: "14.153 on4kjm", previousLine: LogLine{ Mode: "SSB", Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35}}, args{inputStr: "14.153 on4kjm", previousLine: LogLine{Mode: "SSB", Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35}},
LogLine{ Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35, Frequency: "14.153", Call: "ON4KJM" ,Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35, Frequency: "14.153", Call: "ON4KJM", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"Parse frequency out of limit", "Parse frequency out of limit",
args{ inputStr: "14.453 on4kjm", previousLine: LogLine{ Mode: "SSB", Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35}}, args{inputStr: "14.453 on4kjm", previousLine: LogLine{Mode: "SSB", Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35}},
LogLine{ Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35, Call: "ON4KJM" ,Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, " Frequency 14.453 is invalid for 20m band", LogLine{Band: "20m", BandLowerLimit: 14.0, BandUpperLimit: 14.35, Call: "ON4KJM", Mode: "SSB", RSTsent: "59", RSTrcvd: "59"}, " Frequency 14.453 is invalid for 20m band",
}, },
{ {
"parse partial RST (sent) - CW", "parse partial RST (sent) - CW",
args{ inputStr: "1230 on4kjm 5", previousLine: LogLine{ Mode: "CW", ModeType: "CW"}}, args{inputStr: "1230 on4kjm 5", previousLine: LogLine{Mode: "CW", ModeType: "CW"}},
LogLine{ Call: "ON4KJM", Time: "1230", RSTsent: "559", RSTrcvd: "599", Mode: "CW", ModeType: "CW"}, "", LogLine{Call: "ON4KJM", Time: "1230", RSTsent: "559", RSTrcvd: "599", Mode: "CW", ModeType: "CW"}, "",
}, },
{ {
"parse partial RST (received) - CW", "parse partial RST (received) - CW",
args{ inputStr: "1230 on4kjm 5 44", previousLine: LogLine{ Mode: "CW", ModeType: "CW"}}, args{inputStr: "1230 on4kjm 5 44", previousLine: LogLine{Mode: "CW", ModeType: "CW"}},
LogLine{ Call: "ON4KJM", Time: "1230", RSTsent: "559", RSTrcvd: "449", Mode: "CW", ModeType: "CW"}, "", LogLine{Call: "ON4KJM", Time: "1230", RSTsent: "559", RSTrcvd: "449", Mode: "CW", ModeType: "CW"}, "",
}, },
{ {
"parse full RST (received) - CW", "parse full RST (received) - CW",
args{ inputStr: "1230 on4kjm 5 448", previousLine: LogLine{ Mode: "CW", ModeType: "CW"}}, args{inputStr: "1230 on4kjm 5 448", previousLine: LogLine{Mode: "CW", ModeType: "CW"}},
LogLine{ Call: "ON4KJM", Time: "1230", RSTsent: "559", RSTrcvd: "448", Mode: "CW", ModeType: "CW"}, "", LogLine{Call: "ON4KJM", Time: "1230", RSTsent: "559", RSTrcvd: "448", Mode: "CW", ModeType: "CW"}, "",
}, },
{ {
"parse partial report (sent) - FM", "parse partial report (sent) - FM",
args{ inputStr: "1230 on4kjm 5", previousLine: LogLine{ Mode: "FM", ModeType: "PHONE"}}, args{inputStr: "1230 on4kjm 5", previousLine: LogLine{Mode: "FM", ModeType: "PHONE"}},
LogLine{ Call: "ON4KJM", Time: "1230", RSTsent: "55", RSTrcvd: "59", Mode: "FM", ModeType: "PHONE"}, "", LogLine{Call: "ON4KJM", Time: "1230", RSTsent: "55", RSTrcvd: "59", Mode: "FM", ModeType: "PHONE"}, "",
}, },
{ {
"parse partial report (received) - FM", "parse partial report (received) - FM",
args{ inputStr: "1230 on4kjm 5 44", previousLine: LogLine{ Mode: "FM", ModeType: "PHONE"}}, args{inputStr: "1230 on4kjm 5 44", previousLine: LogLine{Mode: "FM", ModeType: "PHONE"}},
LogLine{ Call: "ON4KJM", Time: "1230", RSTsent: "55", RSTrcvd: "44", Mode: "FM", ModeType: "PHONE"}, "", LogLine{Call: "ON4KJM", Time: "1230", RSTsent: "55", RSTrcvd: "44", Mode: "FM", ModeType: "PHONE"}, "",
}, },
{ {
"Incompatible report", "Incompatible report",
args{ inputStr: "1230 on4kjm 5 599", previousLine: LogLine{ Mode: "FM", ModeType: "PHONE"}}, args{inputStr: "1230 on4kjm 5 599", previousLine: LogLine{Mode: "FM", ModeType: "PHONE"}},
LogLine{ Call: "ON4KJM", Time: "1230", RSTsent: "55", RSTrcvd: "*599", Mode: "FM", ModeType: "PHONE"}, "Invalid report (599) for PHONE mode ", LogLine{Call: "ON4KJM", Time: "1230", RSTsent: "55", RSTrcvd: "*599", Mode: "FM", ModeType: "PHONE"}, "Invalid report (599) for PHONE mode ",
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -133,34 +132,34 @@ func TestHappyParseLine(t *testing.T) {
wantErrorMsg string wantErrorMsg string
}{ }{
{ {
"test1", "test1",
args{ inputStr: "1202 g4elz", args{inputStr: "1202 g4elz",
previousLine: LogLine{ Mode: "CW", ModeType: "CW", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3}}, previousLine: LogLine{Mode: "CW", ModeType: "CW", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3}},
LogLine{ Time: "1202", Call: "G4ELZ", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3, Mode: "CW", ModeType: "CW", RSTsent: "599", RSTrcvd: "599"}, "", LogLine{Time: "1202", Call: "G4ELZ", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3, Mode: "CW", ModeType: "CW", RSTsent: "599", RSTrcvd: "599"}, "",
}, },
{ {
"test2", "test2",
args{ inputStr: "4 g3noh <PSE QSL Direct>", args{inputStr: "4 g3noh <PSE QSL Direct>",
previousLine: LogLine{ Time: "1202", Mode: "CW", ModeType: "CW", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3}}, previousLine: LogLine{Time: "1202", Mode: "CW", ModeType: "CW", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3}},
LogLine{ Time: "1204", Call: "G3NOH", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3, Mode: "CW", ModeType: "CW", Comment: "PSE QSL Direct", RSTsent: "599", RSTrcvd: "599"}, "", LogLine{Time: "1204", Call: "G3NOH", Band: "40m", BandLowerLimit: 7, BandUpperLimit: 7.3, Mode: "CW", ModeType: "CW", Comment: "PSE QSL Direct", RSTsent: "599", RSTrcvd: "599"}, "",
}, },
{ {
"test3", "test3",
args{ inputStr: "1227 gw4gte <Dave>", args{inputStr: "1227 gw4gte <Dave>",
previousLine: LogLine{ Time: "1202", Mode: "FM", ModeType: "PHONE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148}}, previousLine: LogLine{Time: "1202", Mode: "FM", ModeType: "PHONE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148}},
LogLine{ Time: "1227", Call: "GW4GTE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148, Mode: "FM", ModeType: "PHONE", Comment: "Dave", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Time: "1227", Call: "GW4GTE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148, Mode: "FM", ModeType: "PHONE", Comment: "Dave", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"test4", "test4",
args{ inputStr: "8 gw0tlk/m gwff-0021", args{inputStr: "8 gw0tlk/m gwff-0021",
previousLine: LogLine{ Time: "1227", Mode: "FM", ModeType: "PHONE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148}}, previousLine: LogLine{Time: "1227", Mode: "FM", ModeType: "PHONE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148}},
LogLine{ Time: "1228", Call: "GW0TLK/M", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148, Mode: "FM", ModeType: "PHONE", WWFF: "GWFF-0021", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Time: "1228", Call: "GW0TLK/M", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148, Mode: "FM", ModeType: "PHONE", WWFF: "GWFF-0021", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
{ {
"test5", "test5",
args{ inputStr: "7 dl0dan/p dlff-0002 dl/al-044", args{inputStr: "7 dl0dan/p dlff-0002 dl/al-044",
previousLine: LogLine{ Time: "1220", Mode: "FM", ModeType: "PHONE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148}}, previousLine: LogLine{Time: "1220", Mode: "FM", ModeType: "PHONE", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148}},
LogLine{ Time: "1227", Call: "DL0DAN/P", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148, Mode: "FM", ModeType: "PHONE", WWFF: "DLFF-0002", SOTA: "DL/AL-044", RSTsent: "59", RSTrcvd: "59"}, "", LogLine{Time: "1227", Call: "DL0DAN/P", Band: "2m", BandLowerLimit: 144, BandUpperLimit: 148, Mode: "FM", ModeType: "PHONE", WWFF: "DLFF-0002", SOTA: "DL/AL-044", RSTsent: "59", RSTrcvd: "59"}, "",
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -174,4 +173,4 @@ func TestHappyParseLine(t *testing.T) {
} }
}) })
} }
} }

@ -1,4 +1,5 @@
package cmd package cmd
/* /*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com> Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
@ -36,15 +37,15 @@ var inputFilename string
// rootCmd represents the base command when called without any subcommands // rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "FLEcli", Use: "FLEcli",
Short: "A Command Line \"Fast Log Entry\" (FLE) processor", Short: "A Command Line \"Fast Log Entry\" (FLE) processor",
TraverseChildren: true, TraverseChildren: true,
// Long: `A longer description that spans multiple lines and likely contains // Long: `A longer description that spans multiple lines and likely contains
// examples and usage of using your application. For example: // examples and usage of using your application. For example:
// Cobra is a CLI library for Go that empowers applications. // Cobra is a CLI library for Go that empowers applications.
// This application is a tool to generate the needed files // This application is a tool to generate the needed files
// to quickly create a Cobra application.`, // to quickly create a Cobra application.`,
// Uncomment the following line if your bare application // Uncomment the following line if your bare application
// has an action associated with it: // has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { }, // Run: func(cmd *cobra.Command, args []string) { },

@ -1,4 +1,5 @@
package cmd package cmd
/* /*
Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com> Copyright © 2020 Jean-Marc Meessen, ON4KJM <on4kjm@gmail.com>
@ -16,24 +17,23 @@ limitations under the License.
*/ */
import ( import (
"fmt"
"regexp" "regexp"
"strings" "strings"
"fmt"
"time" "time"
) )
var validSotaRegexp = regexp.MustCompile(`^[0-9A-Z]{1,3}/[A-Z]{2}-[\d]{3}$`) var validSotaRegexp = regexp.MustCompile(`^[0-9A-Z]{1,3}/[A-Z]{2}-[\d]{3}$`)
// ValidateSota verifies whether the supplied string is a valid SOTA reference. // ValidateSota verifies whether the supplied string is a valid SOTA reference.
// The syntax is: AA/NN-CCC: Association/Name-3-digit numeric Code (e.g. G/CE-001). // The syntax is: AA/NN-CCC: Association/Name-3-digit numeric Code (e.g. G/CE-001).
func ValidateSota(inputStr string) (ref, errorMsg string) { func ValidateSota(inputStr string) (ref, errorMsg string) {
inputStr = strings.ToUpper(strings.TrimSpace(inputStr)) inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr wrongInputStr := "*" + inputStr
if validSotaRegexp.MatchString(inputStr) { if validSotaRegexp.MatchString(inputStr) {
return inputStr, "" return inputStr, ""
} }
return wrongInputStr, "Invalid SOTA reference" return wrongInputStr, "Invalid SOTA reference"
} }
var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`) var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`)
@ -43,14 +43,12 @@ var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`)
func ValidateWwff(inputStr string) (ref, errorMsg string) { func ValidateWwff(inputStr string) (ref, errorMsg string) {
inputStr = strings.ToUpper(strings.TrimSpace(inputStr)) inputStr = strings.ToUpper(strings.TrimSpace(inputStr))
wrongInputStr := "*" + inputStr wrongInputStr := "*" + inputStr
if validWwffRegexp.MatchString(inputStr) { if validWwffRegexp.MatchString(inputStr) {
return inputStr, "" return inputStr, ""
} }
return wrongInputStr, "Invalid WWFF reference" return wrongInputStr, "Invalid WWFF reference"
} }
var validCallRegexp = regexp.MustCompile(`[\d]{0,1}[A-Z]{1,2}\d([A-Z]{1,4}|\d{3,3}|\d{1,3}[A-Z])[A-Z]{0,5}`) var validCallRegexp = regexp.MustCompile(`[\d]{0,1}[A-Z]{1,2}\d([A-Z]{1,4}|\d{3,3}|\d{1,3}[A-Z])[A-Z]{0,5}`)
var validPrefixRegexp = regexp.MustCompile(`\A\d?[a-zA-Z]{1,2}$`) var validPrefixRegexp = regexp.MustCompile(`\A\d?[a-zA-Z]{1,2}$`)
@ -72,9 +70,9 @@ func ValidateCall(sign string) (call, errorMsg string) {
if validCallRegexp.MatchString(sp[0]) { if validCallRegexp.MatchString(sp[0]) {
//Callisign with suffix (unchecked) //Callisign with suffix (unchecked)
return sign, "" return sign, ""
} }
//else we are dealing with a prefixed Callsign //else we are dealing with a prefixed Callsign
//validate the part that should contain the call (sp[1]) //validate the part that should contain the call (sp[1])
if !validCallRegexp.MatchString(sp[1]) { if !validCallRegexp.MatchString(sp[1]) {
return wrongSign, "Invalid call" return wrongSign, "Invalid call"
} }
@ -84,7 +82,7 @@ func ValidateCall(sign string) (call, errorMsg string) {
} }
return sign, "" return sign, ""
case 3: case 3:
//validate the part that should contain the call (sp[1]) //validate the part that should contain the call (sp[1])
if !validCallRegexp.MatchString(sp[1]) { if !validCallRegexp.MatchString(sp[1]) {
return wrongSign, "Invalid call" return wrongSign, "Invalid call"
} }
@ -117,85 +115,84 @@ func ValidateDate(inputStr string) (ref, errorMsg string) {
//IsBand retuns true if the passed input string is a valid string //IsBand retuns true if the passed input string is a valid string
func IsBand(inputStr string) (result bool, lowerLimit, upperLimit float64) { func IsBand(inputStr string) (result bool, lowerLimit, upperLimit float64) {
switch strings.ToLower(inputStr) { switch strings.ToLower(inputStr) {
case "2190m": case "2190m":
return true, 0.1357, 0.1378 return true, 0.1357, 0.1378
case "630m": case "630m":
return true, 0.472, 0.479 return true, 0.472, 0.479
case "560m": case "560m":
return true, 0.501, 0.504 return true, 0.501, 0.504
case "160m": case "160m":
return true, 1.8, 2.0 return true, 1.8, 2.0
case "80m": case "80m":
return true, 3.5, 4.0 return true, 3.5, 4.0
case "60m": case "60m":
return true, 5.06, 5.45 return true, 5.06, 5.45
case "40m": case "40m":
return true, 7.0, 7.3 return true, 7.0, 7.3
case "30m": case "30m":
return true, 10.1, 10.15 return true, 10.1, 10.15
case "20m": case "20m":
return true, 14.0, 14.35 return true, 14.0, 14.35
case "17m": case "17m":
return true, 18.068, 18.168 return true, 18.068, 18.168
case "15m": case "15m":
return true, 21.0, 21.45 return true, 21.0, 21.45
case "12m": case "12m":
return true, 24.890, 24.99 return true, 24.890, 24.99
case "10m": case "10m":
return true, 28.0, 29.7 return true, 28.0, 29.7
case "6m": case "6m":
return true, 50, 54 return true, 50, 54
case "4m": case "4m":
return true, 70, 71 return true, 70, 71
case "2m": case "2m":
return true, 144, 148 return true, 144, 148
case "1.25m": case "1.25m":
return true, 222, 225 return true, 222, 225
case "70cm": case "70cm":
return true, 420, 450 return true, 420, 450
case "33cm": case "33cm":
return true, 902, 928 return true, 902, 928
case "23cm": case "23cm":
return true, 1240, 1300 return true, 1240, 1300
case "13cm": case "13cm":
return true, 2300, 2450 return true, 2300, 2450
case "9cm": case "9cm":
return true, 3300, 3500 return true, 3300, 3500
case "6cm": case "6cm":
return true, 5650, 5925 return true, 5650, 5925
case "3cm": case "3cm":
return true, 10000, 10500 return true, 10000, 10500
case "1.25cm": case "1.25cm":
return true, 24000, 24250 return true, 24000, 24250
case "6mm": case "6mm":
return true, 47000, 47200 return true, 47000, 47200
case "4mm": case "4mm":
return true, 75500, 81000 return true, 75500, 81000
case "2.5mm": case "2.5mm":
return true, 119980, 120020 return true, 119980, 120020
case "2mm": case "2mm":
return true, 142000, 149000 return true, 142000, 149000
case "1mm": case "1mm":
return true, 241000, 250000 return true, 241000, 250000
} }
return false, 0, 0 return false, 0, 0
} }
func getDefaultReport(mode string) (modeType, defaultReport string) { func getDefaultReport(mode string) (modeType, defaultReport string) {
modeType = "" modeType = ""
defaultReport = "" defaultReport = ""
switch mode { switch mode {
case "SSB", "AM", "FM" : case "SSB", "AM", "FM":
modeType = "PHONE" modeType = "PHONE"
defaultReport = "59" defaultReport = "59"
case "CW", "RTTY", "PSK": case "CW", "RTTY", "PSK":
modeType = "CW" modeType = "CW"
defaultReport = "599" defaultReport = "599"
case "JT65", "JT9", "JT6M", "JT4", "JT44", "FSK441", "FT8", "ISCAT", "MSK144", "QRA64", "T10", "WSPR" : case "JT65", "JT9", "JT6M", "JT4", "JT44", "FSK441", "FT8", "ISCAT", "MSK144", "QRA64", "T10", "WSPR":
modeType = "DIGITAL" modeType = "DIGITAL"
defaultReport = "-10" defaultReport = "-10"
} }
return modeType, defaultReport return modeType, defaultReport
} }

Loading…
Cancel
Save