Add MY_LAT and MY_LON support using FLE keyword mylat and mylon. (#129)

* Add MY_LAT and MY_LON support using FLE keyword mylat and mylon.

* Add test cases for mylat and mylon.
pull/134/head
Nic Heath 8 months ago committed by GitHub
parent 5b40643868
commit 92ae396b68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -93,6 +93,13 @@ func buildAdif(fullLog []LogLine, adifParams AdifParams) (adifList []string) {
if logLine.MyGrid != "" { if logLine.MyGrid != "" {
adifLine.WriteString(adifElement("MY_GRIDSQUARE", logLine.MyGrid)) adifLine.WriteString(adifElement("MY_GRIDSQUARE", logLine.MyGrid))
} }
if logLine.MyLat != "" {
adifLine.WriteString(adifElement("MY_LAT", logLine.MyLat))
}
if logLine.MyLon != "" {
adifLine.WriteString(adifElement("MY_LON", logLine.MyLon))
}
if logLine.MyCounty != "" { if logLine.MyCounty != "" {
adifLine.WriteString(adifElement("MY_CNTY", logLine.MyCounty)) adifLine.WriteString(adifElement("MY_CNTY", logLine.MyCounty))
} }

@ -111,6 +111,7 @@ func Test_buildAdif(t *testing.T) {
sampleFilledLogPOTA2 := []LogLine{ sampleFilledLogPOTA2 := []LogLine{
{MyCall: "ON4KJM/P", Call: "S57LC", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1310", Band: "20m", Frequency: "14.045", Mode: "CW", RSTsent: "599", RSTrcvd: "599", GridLoc: "JO50", MyPOTA: "ON-00259", Operator: "ON4KJM", Nickname: "ON-00259-1"}, {MyCall: "ON4KJM/P", Call: "S57LC", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1310", Band: "20m", Frequency: "14.045", Mode: "CW", RSTsent: "599", RSTrcvd: "599", GridLoc: "JO50", MyPOTA: "ON-00259", Operator: "ON4KJM", Nickname: "ON-00259-1"},
{MyCall: "ON4KJM/P", Call: "ON4LY", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1312", Band: "20m", Mode: "CW", RSTsent: "559", RSTrcvd: "599", MyPOTA: "ON-00259", Operator: "ON4KJM", POTA: "DL-00001"}, {MyCall: "ON4KJM/P", Call: "ON4LY", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1312", Band: "20m", Mode: "CW", RSTsent: "559", RSTrcvd: "599", MyPOTA: "ON-00259", Operator: "ON4KJM", POTA: "DL-00001"},
{MyCall: "ON4KJM/P", Call: "ON4LY", Date: "2020-05-24", MyGrid: "JO40eu", Time: "1312", Band: "20m", Mode: "CW", RSTsent: "559", RSTrcvd: "599", MyPOTA: "ON-00259", Operator: "ON4KJM", POTA: "DL-00001", MyLat: "15.1234567", MyLon: "-123.1234567"},
} }
expectedOutputPOTA2 := []string{ expectedOutputPOTA2 := []string{
@ -120,6 +121,7 @@ func Test_buildAdif(t *testing.T) {
"<EOH>", "<EOH>",
"<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>S57LC <QSO_DATE:8>20200524 <TIME_ON:4>1310 <BAND:3>20m <MODE:2>CW <FREQ:6>14.045 <RST_SENT:3>599 <RST_RCVD:3>599 <GRIDSQUARE:4>JO50 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <APP_EQSL_QTH_NICKNAME:10>ON-00259-1 <EOR>", "<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>S57LC <QSO_DATE:8>20200524 <TIME_ON:4>1310 <BAND:3>20m <MODE:2>CW <FREQ:6>14.045 <RST_SENT:3>599 <RST_RCVD:3>599 <GRIDSQUARE:4>JO50 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <APP_EQSL_QTH_NICKNAME:10>ON-00259-1 <EOR>",
"<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>ON4LY <QSO_DATE:8>20200524 <TIME_ON:4>1312 <BAND:3>20m <MODE:2>CW <RST_SENT:3>559 <RST_RCVD:3>599 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <SIG:4>POTA <SIG_INFO:8>DL-00001 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <EOR>", "<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>ON4LY <QSO_DATE:8>20200524 <TIME_ON:4>1312 <BAND:3>20m <MODE:2>CW <RST_SENT:3>559 <RST_RCVD:3>599 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <SIG:4>POTA <SIG_INFO:8>DL-00001 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <EOR>",
"<STATION_CALLSIGN:8>ON4KJM/P <CALL:5>ON4LY <QSO_DATE:8>20200524 <TIME_ON:4>1312 <BAND:3>20m <MODE:2>CW <RST_SENT:3>559 <RST_RCVD:3>599 <MY_SIG:4>POTA <MY_SIG_INFO:8>ON-00259 <SIG:4>POTA <SIG_INFO:8>DL-00001 <OPERATOR:6>ON4KJM <MY_GRIDSQUARE:6>JO40eu <MY_LAT:10>15.1234567 <MY_LON:12>-123.1234567 <EOR>",
} }
type args struct { type args struct {

@ -78,7 +78,15 @@ func SprintHeaderValues(logLine LogLine) string {
if logLine.MyGrid != "" { if logLine.MyGrid != "" {
output.WriteString("MyGrid " + logLine.MyGrid + "\n") output.WriteString("MyGrid " + logLine.MyGrid + "\n")
} }
if logLine.MyLat != "" {
output.WriteString("MyLat " + logLine.MyLat + "\n")
}
if logLine.MyLon != "" {
output.WriteString("MyLon " + logLine.MyLon + "\n")
}
if logLine.MyCounty != "" { if logLine.MyCounty != "" {
output.WriteString("MyCounty " + logLine.MyCounty + "\n") output.WriteString("MyCounty " + logLine.MyCounty + "\n")
} }

@ -64,6 +64,8 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
regexpHeaderMySota := regexp.MustCompile(`(?i)^mysota\s+`) regexpHeaderMySota := regexp.MustCompile(`(?i)^mysota\s+`)
regexpHeaderMyPota := regexp.MustCompile(`(?i)^mypota\s+`) regexpHeaderMyPota := regexp.MustCompile(`(?i)^mypota\s+`)
regexpHeaderMyGrid := regexp.MustCompile(`(?i)^mygrid\s+`) regexpHeaderMyGrid := regexp.MustCompile(`(?i)^mygrid\s+`)
regexpHeaderMyLat := regexp.MustCompile(`(?i)^mylat\s+`)
regexpHeaderMyLon := regexp.MustCompile(`(?i)^mylon\s+`)
regexpHeaderMyCounty := regexp.MustCompile(`(?i)^mycounty\s+`) regexpHeaderMyCounty := regexp.MustCompile(`(?i)^mycounty\s+`)
regexpHeaderQslMsg := regexp.MustCompile(`(?i)^qslmsg\s+`) regexpHeaderQslMsg := regexp.MustCompile(`(?i)^qslmsg\s+`)
regexpHeaderNickname := regexp.MustCompile(`(?i)^nickname\s+`) regexpHeaderNickname := regexp.MustCompile(`(?i)^nickname\s+`)
@ -74,6 +76,8 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
headerMySOTA := "" headerMySOTA := ""
headerMyPOTA := "" headerMyPOTA := ""
headerMyGrid := "" headerMyGrid := ""
headerMyLat := ""
headerMyLon := ""
headerMyCounty := "" headerMyCounty := ""
headerQslMsg := "" headerQslMsg := ""
headerNickname := "" headerNickname := ""
@ -247,6 +251,44 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
continue continue
} }
//My Lat
if regexpHeaderMyLat.MatchString(eachline) {
//Attempt to redefine value
if headerMyLat != "" {
errorLog = append(errorLog, fmt.Sprintf("Attempt to redefine MyLat at line %d", lineCount))
continue
}
errorMsg := ""
myLatList := regexpHeaderMyLat.Split(eachline, -1)
if len(strings.TrimSpace(myLatList[1])) > 0 {
headerMyLat, errorMsg = ValidateLat(strings.TrimSpace(myLatList[1]))
if len(errorMsg) != 0 {
errorLog = append(errorLog, fmt.Sprintf("Invalid \"My Lat\" at line %d: %s (%s)", lineCount, myLatList[1], errorMsg))
}
}
//If there is no data after the marker, we just skip the data.
continue
}
//My Lon
if regexpHeaderMyLon.MatchString(eachline) {
//Attempt to redefine value
if headerMyLon != "" {
errorLog = append(errorLog, fmt.Sprintf("Attempt to redefine MyLon at line %d", lineCount))
continue
}
errorMsg := ""
myLonList := regexpHeaderMyLon.Split(eachline, -1)
if len(strings.TrimSpace(myLonList[1])) > 0 {
headerMyLon, errorMsg = ValidateLon(strings.TrimSpace(myLonList[1]))
if len(errorMsg) != 0 {
errorLog = append(errorLog, fmt.Sprintf("Invalid \"My Lon\" at line %d: %s (%s)", lineCount, myLonList[1], errorMsg))
}
}
//If there is no data after the marker, we just skip the data.
continue
}
//My County //My County
if regexpHeaderMyCounty.MatchString(eachline) { if regexpHeaderMyCounty.MatchString(eachline) {
myMyCountyList := regexpHeaderMyCounty.Split(eachline, -1) myMyCountyList := regexpHeaderMyCounty.Split(eachline, -1)
@ -295,6 +337,8 @@ func LoadFile(inputFilename string, isInterpolateTime bool) (filleFullLog []LogL
previousLogLine.MyPOTA = headerMyPOTA previousLogLine.MyPOTA = headerMyPOTA
previousLogLine.MySOTA = headerMySOTA previousLogLine.MySOTA = headerMySOTA
previousLogLine.MyGrid = headerMyGrid previousLogLine.MyGrid = headerMyGrid
previousLogLine.MyLat = headerMyLat
previousLogLine.MyLon = headerMyLon
previousLogLine.MyCounty = headerMyCounty previousLogLine.MyCounty = headerMyCounty
previousLogLine.QSLmsg = headerQslMsg //previousLogLine.QslMsg is redundant previousLogLine.QSLmsg = headerQslMsg //previousLogLine.QslMsg is redundant
previousLogLine.Nickname = headerNickname previousLogLine.Nickname = headerNickname

@ -42,6 +42,8 @@ func TestLoadFile_happyCase(t *testing.T) {
dataArray = append(dataArray, "mySota on/on-001") dataArray = append(dataArray, "mySota on/on-001")
dataArray = append(dataArray, "myPota k-0802") dataArray = append(dataArray, "myPota k-0802")
dataArray = append(dataArray, "myGrid jo50") dataArray = append(dataArray, "myGrid jo50")
dataArray = append(dataArray, "myLat 55.5555555")
dataArray = append(dataArray, "myLon -120.01234567")
dataArray = append(dataArray, "myCounty Ham County") dataArray = append(dataArray, "myCounty Ham County")
dataArray = append(dataArray, "QslMsg This is a QSL message") dataArray = append(dataArray, "QslMsg This is a QSL message")
dataArray = append(dataArray, " ") dataArray = append(dataArray, " ")
@ -84,6 +86,14 @@ func TestLoadFile_happyCase(t *testing.T) {
if loadedLogFile[0].MySOTA != expectedValue { if loadedLogFile[0].MySOTA != expectedValue {
t.Errorf("Not the expected MySOTA value: %s (expecting %s)", loadedLogFile[0].MySOTA, expectedValue) t.Errorf("Not the expected MySOTA value: %s (expecting %s)", loadedLogFile[0].MySOTA, expectedValue)
} }
expectedValue = "55.5555555"
if loadedLogFile[0].MyLat != expectedValue {
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
}
expectedValue = "-120.01234567"
if loadedLogFile[0].MyLon != expectedValue {
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
}
expectedValue = "This is a QSL message" expectedValue = "This is a QSL message"
if loadedLogFile[0].QSLmsg != expectedValue { if loadedLogFile[0].QSLmsg != expectedValue {
t.Errorf("Not the expected QSL Message from Header value: %s (expecting %s)", loadedLogFile[0].QSLmsg, expectedValue) t.Errorf("Not the expected QSL Message from Header value: %s (expecting %s)", loadedLogFile[0].QSLmsg, expectedValue)
@ -386,6 +396,166 @@ func TestLoadFile_happyCase_day(t *testing.T) {
os.Remove(temporaryDataFileName) os.Remove(temporaryDataFileName)
} }
func TestLoadFile_redefining_myLat_must_fail(t *testing.T) {
//Given
dataArray := make([]string, 0)
dataArray = append(dataArray, "# Header")
dataArray = append(dataArray, "myCall on4kjm/p")
dataArray = append(dataArray, "operator on4kjm")
dataArray = append(dataArray, "nickname Portable")
dataArray = append(dataArray, "myLat -55.55")
dataArray = append(dataArray, " ")
dataArray = append(dataArray, " #Log")
dataArray = append(dataArray, "20/5/23")
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
dataArray = append(dataArray, "myLat 55.55")
temporaryDataFileName := createTestFile(dataArray)
//When
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
//Then
if isLoadedOK {
t.Error("Test file processing should return with an error")
}
if len(loadedLogFile) == 0 {
t.Error("No data loaded")
}
expectedValue := "-55.55"
if loadedLogFile[0].MyLat != expectedValue {
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
}
//Clean Up
os.Remove(temporaryDataFileName)
}
func TestLoadFile_redefining_myLon_must_fail(t *testing.T) {
//Given
dataArray := make([]string, 0)
dataArray = append(dataArray, "# Header")
dataArray = append(dataArray, "myCall on4kjm/p")
dataArray = append(dataArray, "operator on4kjm")
dataArray = append(dataArray, "nickname Portable")
dataArray = append(dataArray, "myLon -55.55")
dataArray = append(dataArray, " ")
dataArray = append(dataArray, " #Log")
dataArray = append(dataArray, "20/5/23")
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
dataArray = append(dataArray, "myLon 55.55")
temporaryDataFileName := createTestFile(dataArray)
//When
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
//Then
if isLoadedOK {
t.Error("Test file processing should return with an error")
}
if len(loadedLogFile) == 0 {
t.Error("No data loaded")
}
expectedValue := "-55.55"
if loadedLogFile[0].MyLon != expectedValue {
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
}
//Clean Up
os.Remove(temporaryDataFileName)
}
func Outofrange_myLonHelper(t *testing.T, val string) {
//Given
dataArray := make([]string, 0)
dataArray = append(dataArray, "# Header")
dataArray = append(dataArray, "myCall on4kjm/p")
dataArray = append(dataArray, "operator on4kjm")
dataArray = append(dataArray, "nickname Portable")
dataArray = append(dataArray, "myLon "+val)
dataArray = append(dataArray, " ")
dataArray = append(dataArray, " #Log")
dataArray = append(dataArray, "20/5/23")
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
temporaryDataFileName := createTestFile(dataArray)
//When
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
//Then
if isLoadedOK {
t.Error("Test file processing should return with an error")
}
if len(loadedLogFile) == 0 {
t.Error("No data loaded")
}
expectedValue := "*" + val
if loadedLogFile[0].MyLon != expectedValue {
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
}
//Clean Up
os.Remove(temporaryDataFileName)
}
func TestLoadFile_outofrange_high_myLon_must_fail(t *testing.T) {
Outofrange_myLonHelper(t, "180.0001")
}
func TestLoadFile_outofrange_low_myLon_must_fail(t *testing.T) {
Outofrange_myLonHelper(t, "-180.0001")
}
func Outofrange_myLatHelper(t *testing.T, val string) {
//Given
dataArray := make([]string, 0)
dataArray = append(dataArray, "# Header")
dataArray = append(dataArray, "myCall on4kjm/p")
dataArray = append(dataArray, "operator on4kjm")
dataArray = append(dataArray, "nickname Portable")
dataArray = append(dataArray, "myLat "+val)
dataArray = append(dataArray, " ")
dataArray = append(dataArray, " #Log")
dataArray = append(dataArray, "20/5/23")
dataArray = append(dataArray, "40m cw 0950 ik5zve/5 9 5")
temporaryDataFileName := createTestFile(dataArray)
//When
loadedLogFile, isLoadedOK := LoadFile(temporaryDataFileName, true)
//Then
if isLoadedOK {
t.Error("Test file processing should return with an error")
}
if len(loadedLogFile) == 0 {
t.Error("No data loaded")
}
expectedValue := "*" + val
if loadedLogFile[0].MyLat != expectedValue {
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
}
//Clean Up
os.Remove(temporaryDataFileName)
}
func TestLoadFile_outofrange_high_myLat_must_fail(t *testing.T) {
Outofrange_myLatHelper(t, "90.0001")
}
func TestLoadFile_outofrange_low_myLat_must_fail(t *testing.T) {
Outofrange_myLatHelper(t, "-90.0001")
}
func TestLoadFile_redefining_myCall_must_fail(t *testing.T) { func TestLoadFile_redefining_myCall_must_fail(t *testing.T) {
//Given //Given
@ -1021,6 +1191,8 @@ func TestLoadFile_wrongData(t *testing.T) {
dataArray = append(dataArray, "myWwff foobar") dataArray = append(dataArray, "myWwff foobar")
dataArray = append(dataArray, "mySota foobar") dataArray = append(dataArray, "mySota foobar")
dataArray = append(dataArray, "myGrid foobar") dataArray = append(dataArray, "myGrid foobar")
dataArray = append(dataArray, "myLat foobar")
dataArray = append(dataArray, "myLon foobar")
dataArray = append(dataArray, " ") dataArray = append(dataArray, " ")
dataArray = append(dataArray, " #Log") dataArray = append(dataArray, " #Log")
dataArray = append(dataArray, "date 2020-05-23") dataArray = append(dataArray, "date 2020-05-23")
@ -1061,6 +1233,12 @@ func TestLoadFile_wrongData(t *testing.T) {
if loadedLogFile[0].MyGrid != expectedValue { if loadedLogFile[0].MyGrid != expectedValue {
t.Errorf("Not the expected MyGrid value: %s (expecting %s)", loadedLogFile[0].MyGrid, expectedValue) t.Errorf("Not the expected MyGrid value: %s (expecting %s)", loadedLogFile[0].MyGrid, expectedValue)
} }
if loadedLogFile[0].MyLat != expectedValue {
t.Errorf("Not the expected MyLat value: %s (expecting %s)", loadedLogFile[0].MyLat, expectedValue)
}
if loadedLogFile[0].MyLon != expectedValue {
t.Errorf("Not the expected MyLon value: %s (expecting %s)", loadedLogFile[0].MyLon, expectedValue)
}
expectedValue = "IK5ZVE" expectedValue = "IK5ZVE"
if loadedLogFile[0].Call != expectedValue { if loadedLogFile[0].Call != expectedValue {

@ -34,6 +34,8 @@ type LogLine struct {
MyPota string MyPota string
MySota string MySota string
MyGrid string MyGrid string
MyLat string
MyLon string
MyCounty string MyCounty string
QslMsgFromHeader string QslMsgFromHeader string
Nickname string Nickname string

@ -21,8 +21,33 @@ import (
"regexp" "regexp"
"strings" "strings"
"time" "time"
"strconv"
) )
// ValidateLat checks if value is within range of +-90 degrees inclusive.
func ValidateLat(lat string) (ref, errorMsg string) {
if val, err := strconv.ParseFloat(lat, 64); err == nil {
if val <= float64(90.0) && val >= float64(-90.0) {
return lat, ""
}
}
errorMsg = "[" + lat + "] is an invalid lat"
return "*" + lat, errorMsg
}
// ValidateLon checks if value is within range of +-180 degrees inclusive.
func ValidateLon(lon string) (ref, errorMsg string) {
if val, err := strconv.ParseFloat(lon, 64); err == nil {
if val <= float64(180.0) && val >= float64(-180.0) {
return lon, ""
}
}
errorMsg = "[" + lon + "] is an invalid lon"
return "*" + lon, errorMsg
}
// 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) {

Loading…
Cancel
Save