mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-08-23 18:47:34 +02:00
Added 6+4m and 10G and up frequency detection patterns
This commit is contained in:
@@ -101,102 +101,143 @@ public class Utils4KST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes a chatmembers frequency-string for cluster usage<br/>
|
* Converts a frequency detected in a chat message into the kHz representation
|
||||||
* <b>returns a frequency String in KHz like = "144300" or "144300.0" to match DXC protocol needs</b>
|
* used by the DX Cluster protocol.
|
||||||
*
|
*
|
||||||
* @param optionalPrefix: if there is a value like ".300", it have to be decided, wich ".300": 144.300, 432.300, 1296.300 .... prefix means for example "144."
|
* <p>Complete frequencies with two to five MHz digits are supported, for
|
||||||
|
* example 50.200, 144.205, 1296.338, 10368.100 and 24048.100. An optional
|
||||||
|
* second fractional group is retained as sub-kHz precision, for example
|
||||||
|
* 144.205.2 becomes 144205.2 kHz.</p>
|
||||||
|
*
|
||||||
|
* <p>Relative values such as .205 or 205 use the configured fallback-band
|
||||||
|
* prefix. The method only performs this fallback conversion after the general
|
||||||
|
* message parser has already accepted the value as a frequency.</p>
|
||||||
|
*
|
||||||
|
* @param qrgString frequency as detected by the chat parser
|
||||||
|
* @param optionalPrefix fallback MHz prefix for relative frequencies
|
||||||
|
* @return frequency in kHz for a DX Cluster spot, or an empty string if the
|
||||||
|
* value cannot be converted safely
|
||||||
*/
|
*/
|
||||||
public static String normalizeFrequencyString(String qrgString, SimpleStringProperty optionalPrefix) {
|
public static String normalizeFrequencyString(
|
||||||
|
String qrgString,
|
||||||
// final String PTRN_QRG_CAT2 = "(([0-9]{3,4}[\\.|,| ]?[0-9]{3})([\\.|,][\\d]{1,2})?)|(([a-zA-Z][0-4]{1}[\\d]{2}\\b)([\\.|,][\\d]{1,2}\\b)?)|((\\b[0-4]{1}[\\d]{2}\\b)([\\.|,][\\d]{1,2}\\b)?)";
|
SimpleStringProperty optionalPrefix
|
||||||
|
) {
|
||||||
try {
|
if (qrgString == null || qrgString.isBlank()) {
|
||||||
qrgString = qrgString.replace(" ","");
|
return "";
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("UTILS: QRG NULL, nothing to convert");
|
|
||||||
// e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A comma is accepted as a decimal separator. Spaces are removed so older
|
||||||
|
* stored formats such as "432 088" remain usable.
|
||||||
|
*/
|
||||||
|
String normalizedValue = qrgString
|
||||||
|
.trim()
|
||||||
|
.replace(" ", "")
|
||||||
|
.replace(',', '.');
|
||||||
|
|
||||||
final String PTRN_QRG_CAT2_wholeQRGMHz4Digits = "(([0-9]{4}[\\.|,| ]?[0-9]{3})([\\.|,][\\d]{1,2})?)"; //1296.300.3 etc
|
/*
|
||||||
final String PTRN_QRG_CAT2_wholeQRGMHz3Digits = "(([0-9]{3}[\\.|,| ]?[0-9]{3})([\\.][\\d]{1,2})?)"; //144.300.3 etc
|
* Complete frequency with an explicit separator:
|
||||||
final String PTRN_QRG_CAT2_QRGwithoutPrefix = "((\\b[0-4]{1}[\\d]{2}\\b)([\\.|,][\\d]{1,2}\\b)?)"; //144.300.3 etc
|
*
|
||||||
|
* 50.200
|
||||||
|
* 144.205
|
||||||
|
* 1296.338
|
||||||
|
* 10368.100
|
||||||
|
* 144.205.2
|
||||||
|
*/
|
||||||
|
Matcher completeFrequencyMatcher = Pattern.compile(
|
||||||
|
"^(\\d{2,5})\\.(\\d{1,3})(?:\\.(\\d{1,2}))?$"
|
||||||
|
).matcher(normalizedValue);
|
||||||
|
|
||||||
String stringAggregation = "";
|
if (completeFrequencyMatcher.matches()) {
|
||||||
|
return formatDxClusterFrequency(
|
||||||
if (testPattern(qrgString, PTRN_QRG_CAT2_wholeQRGMHz4Digits)) {//case 1296.200 or 1296.200.2 etc.
|
completeFrequencyMatcher.group(1),
|
||||||
stringAggregation = qrgString;
|
completeFrequencyMatcher.group(2),
|
||||||
|
completeFrequencyMatcher.group(3)
|
||||||
stringAggregation = stringAggregation.replace(".","");
|
);
|
||||||
stringAggregation = stringAggregation.replace(",","");
|
|
||||||
stringAggregation = stringAggregation.replace(" ", "");
|
|
||||||
|
|
||||||
if (stringAggregation.length() == 8) {
|
|
||||||
String stringAggregationNew = stringAggregation.substring(0, stringAggregation.length()-1) + "." + stringAggregation.substring(stringAggregation.length()-1, stringAggregation.length());
|
|
||||||
stringAggregation = stringAggregationNew + ".0";
|
|
||||||
return stringAggregation;
|
|
||||||
|
|
||||||
} else if (stringAggregation.length() == 9) {
|
|
||||||
String stringAggregationNew = stringAggregation.substring(0, stringAggregation.length()-2) + "." + stringAggregation.substring(stringAggregation.length()-2, stringAggregation.length());
|
|
||||||
stringAggregation = stringAggregationNew;
|
|
||||||
return stringAggregation;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (testPattern(qrgString, PTRN_QRG_CAT2_wholeQRGMHz3Digits)) { //case 144.300 or 144.300.2
|
|
||||||
stringAggregation = qrgString;
|
|
||||||
|
|
||||||
stringAggregation = stringAggregation.replace(".","");
|
|
||||||
stringAggregation = stringAggregation.replace(",","");
|
|
||||||
stringAggregation = stringAggregation.replace(" ", "");
|
|
||||||
|
|
||||||
if (stringAggregation.length() == 6) {
|
|
||||||
stringAggregation = stringAggregation + ".0";
|
|
||||||
return stringAggregation;
|
|
||||||
}
|
|
||||||
if (stringAggregation.length() == 7) {
|
|
||||||
String stringAggregationNew = stringAggregation.substring(0, stringAggregation.length()-1) + "." + stringAggregation.substring(stringAggregation.length()-1, stringAggregation.length());
|
|
||||||
stringAggregation = stringAggregationNew + ".0";
|
|
||||||
return stringAggregation;
|
|
||||||
|
|
||||||
} else if (stringAggregation.length() == 8) {
|
|
||||||
String stringAggregationNew = stringAggregation.substring(0, stringAggregation.length()-2) + "." + stringAggregation.substring(stringAggregation.length()-2, stringAggregation.length());
|
|
||||||
stringAggregation = stringAggregationNew;
|
|
||||||
return stringAggregation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
|
|
||||||
if (testPattern(qrgString, PTRN_QRG_CAT2_QRGwithoutPrefix)) { //case ".050 or .300 or something like that"
|
|
||||||
stringAggregation = qrgString;
|
|
||||||
|
|
||||||
stringAggregation = stringAggregation.replace(".", "");
|
|
||||||
stringAggregation = stringAggregation.replace(",", "");
|
|
||||||
stringAggregation = stringAggregation.replace(" ", "");
|
|
||||||
|
|
||||||
if (stringAggregation.length() == 3) { // like 050 or 300
|
|
||||||
String stringAggregationNew = optionalPrefix.getValue() + stringAggregation;
|
|
||||||
stringAggregation = stringAggregationNew + ".0";
|
|
||||||
return stringAggregation;
|
|
||||||
|
|
||||||
} else if (stringAggregation.length() == 4) { //like 050.2 --> 0502
|
|
||||||
|
|
||||||
stringAggregation = optionalPrefix.getValue() + stringAggregation;
|
|
||||||
String stringAggregationNew = stringAggregation.substring(0, stringAggregation.length() - 1) + "." + stringAggregation.substring(stringAggregation.length() - 1, stringAggregation.length());
|
|
||||||
stringAggregation = stringAggregationNew;
|
|
||||||
return stringAggregation;
|
|
||||||
|
|
||||||
} else if (stringAggregation.length() == 5) { //like 050.20 --> 05020
|
|
||||||
|
|
||||||
stringAggregation = optionalPrefix.getValue() + stringAggregation;
|
|
||||||
String stringAggregationNew = stringAggregation.substring(0, stringAggregation.length() - 2) + "." + stringAggregation.substring(stringAggregation.length() - 2, stringAggregation.length());
|
|
||||||
stringAggregation = stringAggregationNew;
|
|
||||||
return stringAggregation;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stringAggregation; //if nothing else helps
|
/*
|
||||||
|
* Compact complete frequency retained for compatibility:
|
||||||
|
*
|
||||||
|
* 144205
|
||||||
|
* 1296338
|
||||||
|
* 10368100
|
||||||
|
* 432088.2
|
||||||
|
*/
|
||||||
|
Matcher compactFrequencyMatcher = Pattern.compile(
|
||||||
|
"^(\\d{2,5})(\\d{3})(?:\\.(\\d{1,2}))?$"
|
||||||
|
).matcher(normalizedValue);
|
||||||
|
|
||||||
|
if (compactFrequencyMatcher.matches()) {
|
||||||
|
return formatDxClusterFrequency(
|
||||||
|
compactFrequencyMatcher.group(1),
|
||||||
|
compactFrequencyMatcher.group(2),
|
||||||
|
compactFrequencyMatcher.group(3)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Relative frequency. Values above 499 are deliberately rejected, matching
|
||||||
|
* the previous behaviour and preventing a report such as 599 from becoming
|
||||||
|
* a plausible-looking cluster frequency.
|
||||||
|
*/
|
||||||
|
Matcher relativeFrequencyMatcher = Pattern.compile(
|
||||||
|
"^\\.?([0-4]\\d{2})(?:\\.(\\d{1,2}))?$"
|
||||||
|
).matcher(normalizedValue);
|
||||||
|
|
||||||
|
if (!relativeFrequencyMatcher.matches()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String fallbackPrefix = optionalPrefix == null
|
||||||
|
? null
|
||||||
|
: optionalPrefix.getValue();
|
||||||
|
|
||||||
|
if (fallbackPrefix == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
fallbackPrefix = fallbackPrefix.trim();
|
||||||
|
|
||||||
|
if (!fallbackPrefix.matches("\\d{2,5}")) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatDxClusterFrequency(
|
||||||
|
fallbackPrefix,
|
||||||
|
relativeFrequencyMatcher.group(1),
|
||||||
|
relativeFrequencyMatcher.group(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats an MHz part, a fractional MHz part and optional sub-kHz digits as a
|
||||||
|
* DX Cluster frequency in kHz.
|
||||||
|
*
|
||||||
|
* <p>The fractional MHz part is padded on the right because 144.2 means
|
||||||
|
* 144.200 MHz, while 144.21 means 144.210 MHz.</p>
|
||||||
|
*
|
||||||
|
* @param mhzPart complete MHz part
|
||||||
|
* @param fractionalMhzPart one to three digits following the first separator
|
||||||
|
* @param subKhzPart optional digits following a second separator
|
||||||
|
* @return DX Cluster frequency in kHz
|
||||||
|
*/
|
||||||
|
private static String formatDxClusterFrequency(
|
||||||
|
String mhzPart,
|
||||||
|
String fractionalMhzPart,
|
||||||
|
String subKhzPart
|
||||||
|
) {
|
||||||
|
String paddedFraction =
|
||||||
|
(fractionalMhzPart + "000").substring(0, 3);
|
||||||
|
|
||||||
|
String subKhz = subKhzPart == null
|
||||||
|
? "0"
|
||||||
|
: subKhzPart;
|
||||||
|
|
||||||
|
return mhzPart
|
||||||
|
+ paddedFraction
|
||||||
|
+ "."
|
||||||
|
+ subKhz;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package kst4contest.test;
|
||||||
|
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import kst4contest.controller.Utils4KST;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class Utils4KSTFrequencyTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void convertsCompleteFrequenciesAcrossAllSupportedPrefixLengths() {
|
||||||
|
assertEquals("50200.0", convert("50.200", "144"));
|
||||||
|
assertEquals("70250.0", convert("70,250", "144"));
|
||||||
|
assertEquals("144205.0", convert("144.205", "432"));
|
||||||
|
assertEquals("432088.0", convert("432.088", "144"));
|
||||||
|
assertEquals("1296338.0", convert("1296.338", "144"));
|
||||||
|
assertEquals("10368100.0", convert("10368.100", "144"));
|
||||||
|
assertEquals("24048100.0", convert("24048.100", "144"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void retainsSubKhzPrecision() {
|
||||||
|
assertEquals("144205.2", convert("144.205.2", "432"));
|
||||||
|
assertEquals("1296338.25", convert("1296.338.25", "144"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void convertsCompactLegacyFormats() {
|
||||||
|
assertEquals("432088.0", convert("432088", "144"));
|
||||||
|
assertEquals("10368100.0", convert("10368100", "144"));
|
||||||
|
assertEquals("432088.2", convert("432088.2", "144"));
|
||||||
|
assertEquals("432088.0", convert("432 088", "144"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void appliesFallbackOnlyToRelativeFrequencies() {
|
||||||
|
assertEquals("432205.0", convert(".205", "432"));
|
||||||
|
assertEquals("144205.0", convert("205", "144"));
|
||||||
|
assertEquals("10368300.0", convert(".300", "10368"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsMissingOrUnsupportedValues() {
|
||||||
|
assertEquals("", convert(null, "144"));
|
||||||
|
assertEquals("", convert("", "144"));
|
||||||
|
assertEquals("", convert("not-a-frequency", "144"));
|
||||||
|
assertEquals("", convert("599", "144"));
|
||||||
|
assertEquals("", convert(".205", null));
|
||||||
|
assertEquals("", convert(".205", "invalid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String convert(String frequency, String fallbackPrefix) {
|
||||||
|
SimpleStringProperty fallback = fallbackPrefix == null
|
||||||
|
? null
|
||||||
|
: new SimpleStringProperty(fallbackPrefix);
|
||||||
|
|
||||||
|
return Utils4KST.normalizeFrequencyString(
|
||||||
|
frequency,
|
||||||
|
fallback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user