From 8443c27b186121eeb2fc2abdb0d9df9d89c3bd5c Mon Sep 17 00:00:00 2001 From: Jean-Marc MEESSEN Date: Mon, 8 Jun 2020 22:13:58 +0200 Subject: [PATCH] Added SOTA, WWFF and QSLmsg parsing --- cmd/callsign.go | 2 +- cmd/load.go | 61 ++++++++++++++++++++++++++++++----- cmd/sota.go | 35 +++++++++++++++++++++ cmd/sota_test.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ cmd/wwff.go | 35 +++++++++++++++++++++ cmd/wwff_test.go | 43 +++++++++++++++++++++++++ 6 files changed, 250 insertions(+), 8 deletions(-) create mode 100644 cmd/sota.go create mode 100644 cmd/sota_test.go create mode 100644 cmd/wwff.go create mode 100644 cmd/wwff_test.go diff --git a/cmd/callsign.go b/cmd/callsign.go index 46e1dbc..de1c175 100644 --- a/cmd/callsign.go +++ b/cmd/callsign.go @@ -24,7 +24,7 @@ import ( 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}$`) -// ValidateCall veriffies whether the supplied string is a valid callsign. +// ValidateCall verifies whether the supplied string is a valid callsign. // prefix and suffix are not checked for validity // If it is not valid, the supicious string is prefixed with a * and an erroMsg is genrated. func ValidateCall(sign string) (call, errorMsg string) { diff --git a/cmd/load.go b/cmd/load.go index ce87dc3..1b3bbed 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -80,14 +80,17 @@ func loadFile() { regexpEndMultiLineComment, _ := regexp.Compile("}$") regexpHeaderMyCall, _ := regexp.Compile("(?i)^mycall ") regexpHeaderOperator, _ := regexp.Compile("(?i)^operator ") - // regexpHeaderMyWwff, _ := regexp.Compile("(?i)^mywwff ") - // regexpHeaderMySota, _ := regexp.Compile("(?i)^mysota ") - // regexpHeaderQslMsg, _ := regexp.Compile("(?i)^qslmsg ") + regexpHeaderMyWwff, _ := regexp.Compile("(?i)^mywwff ") + regexpHeaderMySota, _ := regexp.Compile("(?i)^mysota ") + regexpHeaderQslMsg, _ := regexp.Compile("(?i)^qslmsg ") // regexpHeaderNickname, _ := regexp.Compile("(?i)^nickname ") // regexpHeaderDate, _ := regexp.Compile("(?i)^date ") headerMyCall := "" headerOperator := "" + headerMyWWFF := "" + headerMySOTA := "" + //headerQslMsg := "" lineCount := 0 var isInMultiLine = false @@ -133,6 +136,7 @@ func loadFile() { // ** Process the Header block // **** + //My Call if(regexpHeaderMyCall.MatchString(eachline)) { errorMsg := "" myCallList := regexpHeaderMyCall.Split(eachline,-1) @@ -142,12 +146,12 @@ func loadFile() { if(len(errorMsg) != 0) { errorLog = append(errorLog, fmt.Sprintf("Invalid myCall at line %d: %s (%s)",lineCount, myCallList[1], errorMsg)) } - } else { - errorLog = append(errorLog, fmt.Sprintf("Undefined myCall at line %d",lineCount)) } + //If there is no data after the marker, we just skip the data. continue } + //Operator if(regexpHeaderOperator.MatchString(eachline)) { errorMsg := "" myOperatorList := regexpHeaderOperator.Split(eachline,-1) @@ -157,11 +161,51 @@ func loadFile() { if(len(errorMsg) != 0) { errorLog = append(errorLog, fmt.Sprintf("Invalid Operator at line %d: %s (%s)",lineCount, myOperatorList[1], errorMsg)) } - } else { - errorLog = append(errorLog, fmt.Sprintf("Undefined Operator at line %d",lineCount)) } + //If there is no data after the marker, we just skip the data. continue } + + // My WWFF + if(regexpHeaderMyWwff.MatchString(eachline)) { + errorMsg := "" + myWwffList := regexpHeaderMyWwff.Split(eachline,-1) + if(len(myWwffList[1]) > 0) { + headerMyWWFF, errorMsg = ValidateWwff(myWwffList[1]) + cleanedInput = append(cleanedInput, fmt.Sprintf("My WWFF: %s", headerMyWWFF)) + if(len(errorMsg) != 0) { + 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. + continue + } + + //My Sota + if(regexpHeaderMySota.MatchString(eachline)) { + errorMsg := "" + mySotaList := regexpHeaderMySota.Split(eachline,-1) + if(len(mySotaList[1]) > 0) { + headerMySOTA, errorMsg = ValidateSota(mySotaList[1]) + cleanedInput = append(cleanedInput, fmt.Sprintf("My Sota: %s", headerMySOTA)) + if(len(errorMsg) != 0) { + 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. + continue + } + + //QSL Message + if(regexpHeaderQslMsg.MatchString(eachline)) { + myQslMsgList := regexpHeaderQslMsg.Split(eachline,-1) + if(len(myQslMsgList[1]) > 0) { + cleanedInput = append(cleanedInput, fmt.Sprintf("QSL Message: %s", myQslMsgList[1])) + } + //If there is no data after the marker, we just skip the data. + continue + } + // **** // ** Process the data block // **** @@ -169,6 +213,9 @@ func loadFile() { } + //***** + //** display results + //***** for _, cleanedInputLine := range cleanedInput { fmt.Println(cleanedInputLine) } diff --git a/cmd/sota.go b/cmd/sota.go new file mode 100644 index 0000000..cfd5c87 --- /dev/null +++ b/cmd/sota.go @@ -0,0 +1,35 @@ +package cmd +/* +Copyright © 2020 Jean-Marc Meessen, ON4KJM + +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" +) + + +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. +// The syntax is: AA/NN-CCC: Association/Name-3-digit numeric Code (e.g. G/CE-001). +func ValidateSota(inputStr string) (ref, errorMsg string) { + inputStr = strings.ToUpper(strings.TrimSpace(inputStr)) + wrongInputStr := "*" + inputStr + if validSotaRegexp.MatchString(inputStr) { + return inputStr, "" + } + return wrongInputStr, "Invalid SOTA reference" +} \ No newline at end of file diff --git a/cmd/sota_test.go b/cmd/sota_test.go new file mode 100644 index 0000000..a3d8a56 --- /dev/null +++ b/cmd/sota_test.go @@ -0,0 +1,82 @@ +package cmd + +import "testing" + +func TestValidateSota(t *testing.T) { + type args struct { + inputStr string + } + tests := []struct { + name string + args args + wantRef string + wantErrorMsg string + }{ + { + "Good ref (simple)", + args{ inputStr: "on/ON-001", }, + "ON/ON-001", "", + }, + { + "Good ref (single digit prefix)", + args{ inputStr: "g/ON-001", }, + "G/ON-001", "", + }, + { + "Good ref (numerical prefix)", + args{ inputStr: "4x/ON-001", }, + "4X/ON-001", "", + }, + { + "Good ref (american style)", + args{ inputStr: "w4z/ON-001", }, + "W4Z/ON-001", "", + }, + { + "Bad ref (long prefix)", + args{ inputStr: "xxxx/ON-001", }, + "*XXXX/ON-001", "Invalid SOTA reference", + }, + { + "Bad ref (missing slash)", + args{ inputStr: "on ON-001", }, + "*ON ON-001", "Invalid SOTA reference", + }, + { + "Bad ref (numerical region)", + args{ inputStr: "on/9N-001", }, + "*ON/9N-001", "Invalid SOTA reference", + }, + { + "Bad ref (too long region)", + args{ inputStr: "on/ONA-001", }, + "*ON/ONA-001", "Invalid SOTA reference", + }, + { + "Bad ref (no dash)", + args{ inputStr: "on/ON/001", }, + "*ON/ON/001", "Invalid SOTA reference", + }, + { + "Bad ref (number too short)", + args{ inputStr: "on/ON-01", }, + "*ON/ON-01", "Invalid SOTA reference", + }, + { + "Bad ref (Number too long)", + args{ inputStr: "on/ON-9001", }, + "*ON/ON-9001", "Invalid SOTA reference", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotRef, gotErrorMsg := ValidateSota(tt.args.inputStr) + if gotRef != tt.wantRef { + t.Errorf("ValidateSota() gotRef = %v, want %v", gotRef, tt.wantRef) + } + if gotErrorMsg != tt.wantErrorMsg { + t.Errorf("ValidateSota() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg) + } + }) + } +} diff --git a/cmd/wwff.go b/cmd/wwff.go new file mode 100644 index 0000000..6ebefe8 --- /dev/null +++ b/cmd/wwff.go @@ -0,0 +1,35 @@ +package cmd +/* +Copyright © 2020 Jean-Marc Meessen, ON4KJM + +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" +) + + +var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`) + +// ValidateWwff verifies whether the supplied string is a valid WWFF reference. +// The syntax is: AAFF-CCCC: AA = national prefix, CCCC = 4-digit numeric code (e.g. ONFF-0001). +func ValidateWwff(inputStr string) (ref, errorMsg string) { + inputStr = strings.ToUpper(strings.TrimSpace(inputStr)) + wrongInputStr := "*" + inputStr + if validWwffRegexp.MatchString(inputStr) { + return inputStr, "" + } + return wrongInputStr, "Invalid WWFF reference" +} \ No newline at end of file diff --git a/cmd/wwff_test.go b/cmd/wwff_test.go new file mode 100644 index 0000000..8055a0f --- /dev/null +++ b/cmd/wwff_test.go @@ -0,0 +1,43 @@ +package cmd + +import "testing" + +func TestValidateWwff(t *testing.T) { + type args struct { + inputStr string + } + tests := []struct { + name string + args args + wantRef string + wantErrorMsg string + }{ + { + "Good call (simple)", + args{ inputStr: "onff-0258", }, + "ONFF-0258", "", + }, + { + "Good call (simple)", + args{ inputStr: "fff-0258", }, + "FFF-0258", "", + }, + { + "Good call (simple)", + args{ inputStr: "4xff-0258", }, + "4XFF-0258", "", + }, + //TODO: add the invalid cases + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotRef, gotErrorMsg := ValidateWwff(tt.args.inputStr) + if gotRef != tt.wantRef { + t.Errorf("ValidateWwff() gotRef = %v, want %v", gotRef, tt.wantRef) + } + if gotErrorMsg != tt.wantErrorMsg { + t.Errorf("ValidateWwff() gotErrorMsg = %v, want %v", gotErrorMsg, tt.wantErrorMsg) + } + }) + } +}