230 lines
5.0 KiB
Go
230 lines
5.0 KiB
Go
package modes
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/user/flexdxcluster2/internal/bands"
|
|
)
|
|
|
|
type ModeRange struct {
|
|
MinFreqMHz float64
|
|
MaxFreqMHz float64
|
|
Mode string
|
|
}
|
|
|
|
var BandModeRanges = map[string][]ModeRange{
|
|
"160M": {
|
|
{1.800, 1.838, "CW"},
|
|
{1.838, 1.843, "FT8"},
|
|
{1.843, 2.000, "LSB"},
|
|
},
|
|
"80M": {
|
|
{3.500, 3.560, "CW"},
|
|
{3.560, 3.575, "FT8"},
|
|
{3.575, 3.578, "FT4"},
|
|
{3.578, 3.590, "RTTY"},
|
|
{3.590, 3.800, "LSB"},
|
|
},
|
|
"60M": {
|
|
{5.330, 5.357, "CW"},
|
|
{5.357, 5.359, "FT8"},
|
|
{5.359, 5.405, "USB"},
|
|
},
|
|
"40M": {
|
|
{7.000, 7.040, "CW"},
|
|
{7.040, 7.047, "RTTY"},
|
|
{7.047, 7.050, "FT4"},
|
|
{7.050, 7.100, "FT8"},
|
|
{7.100, 7.300, "LSB"},
|
|
},
|
|
"30M": {
|
|
{10.100, 10.130, "CW"},
|
|
{10.130, 10.142, "FT8"},
|
|
{10.142, 10.150, "FT4"},
|
|
},
|
|
"20M": {
|
|
{14.000, 14.070, "CW"},
|
|
{14.070, 14.078, "FT8"},
|
|
{14.078, 14.083, "FT4"},
|
|
{14.083, 14.100, "FT8"},
|
|
{14.100, 14.112, "RTTY"},
|
|
{14.112, 14.350, "USB"},
|
|
},
|
|
"17M": {
|
|
{18.068, 18.090, "CW"},
|
|
{18.090, 18.104, "FT8"},
|
|
{18.104, 18.106, "FT4"},
|
|
{18.106, 18.110, "FT8"},
|
|
{18.110, 18.168, "USB"},
|
|
},
|
|
"15M": {
|
|
{21.000, 21.070, "CW"},
|
|
{21.070, 21.100, "FT8"},
|
|
{21.100, 21.130, "RTTY"},
|
|
{21.130, 21.143, "FT4"},
|
|
{21.143, 21.450, "USB"},
|
|
},
|
|
"12M": {
|
|
{24.890, 24.910, "CW"},
|
|
{24.910, 24.918, "FT8"},
|
|
{24.918, 24.930, "FT4"},
|
|
{24.930, 24.990, "USB"},
|
|
},
|
|
"10M": {
|
|
{28.000, 28.070, "CW"},
|
|
{28.070, 28.110, "FT8"},
|
|
{28.110, 28.179, "RTTY"},
|
|
{28.179, 28.190, "FT4"},
|
|
{28.190, 29.000, "USB"},
|
|
{29.000, 29.700, "FM"},
|
|
},
|
|
"6M": {
|
|
{50.000, 50.100, "CW"},
|
|
{50.100, 50.313, "USB"},
|
|
{50.313, 50.318, "FT8"},
|
|
{50.318, 50.323, "FT4"},
|
|
{50.323, 51.000, "USB"},
|
|
{51.000, 54.000, "FM"},
|
|
},
|
|
"QO-100": {
|
|
{10489.500, 10489.540, "CW"},
|
|
{10489.540, 10489.650, "FT8"},
|
|
{10489.650, 10489.990, "USB"},
|
|
},
|
|
}
|
|
|
|
func GuessMode(freqMHz float64) string {
|
|
band := bands.FrequencyToBand(freqMHz)
|
|
if band == "N/A" {
|
|
if freqMHz < 10.0 {
|
|
return "LSB"
|
|
}
|
|
return "USB"
|
|
}
|
|
return GuessModeForBand(freqMHz, band)
|
|
}
|
|
|
|
func GuessModeForBand(freqMHz float64, band string) string {
|
|
ranges, exists := BandModeRanges[band]
|
|
if !exists {
|
|
if bands.IsUSBBand(band) {
|
|
return "USB"
|
|
}
|
|
return "LSB"
|
|
}
|
|
for _, r := range ranges {
|
|
if freqMHz >= r.MinFreqMHz && freqMHz < r.MaxFreqMHz {
|
|
return r.Mode
|
|
}
|
|
}
|
|
if bands.IsUSBBand(band) {
|
|
return "USB"
|
|
}
|
|
return "LSB"
|
|
}
|
|
|
|
func ExtractModeFromComment(comment string) string {
|
|
if comment == "" {
|
|
return ""
|
|
}
|
|
commentUpper := strings.ToUpper(comment)
|
|
|
|
if strings.Contains(commentUpper, "FT8") ||
|
|
(strings.Contains(commentUpper, "DB") && strings.Contains(commentUpper, "HZ")) {
|
|
return "FT8"
|
|
}
|
|
if strings.Contains(commentUpper, "FT4") {
|
|
return "FT4"
|
|
}
|
|
if strings.Contains(commentUpper, "WPM") || strings.Contains(commentUpper, " CW ") ||
|
|
strings.HasSuffix(commentUpper, "CW") || strings.HasPrefix(commentUpper, "CW ") {
|
|
return "CW"
|
|
}
|
|
|
|
digitalModes := []string{"RTTY", "PSK31", "PSK63", "PSK", "MFSK", "OLIVIA", "JT65", "JT9"}
|
|
for _, mode := range digitalModes {
|
|
if strings.Contains(commentUpper, mode) {
|
|
return mode
|
|
}
|
|
}
|
|
|
|
voiceModes := []string{"USB", "LSB", "SSB", "FM", "AM"}
|
|
for _, mode := range voiceModes {
|
|
if strings.Contains(commentUpper, " "+mode+" ") ||
|
|
strings.HasPrefix(commentUpper, mode+" ") ||
|
|
strings.HasSuffix(commentUpper, " "+mode) ||
|
|
commentUpper == mode {
|
|
return mode
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// DetermineMode — priorité : mode explicite > commentaire > fréquence
|
|
func DetermineMode(explicitMode string, comment string, freqMHz float64) string {
|
|
if explicitMode != "" {
|
|
explicitMode = strings.ToUpper(explicitMode)
|
|
if explicitMode == "SSB" {
|
|
return bands.NormalizeSSBModeByFrequency(explicitMode, freqMHz)
|
|
}
|
|
return explicitMode
|
|
}
|
|
|
|
modeFromComment := ExtractModeFromComment(comment)
|
|
if modeFromComment != "" {
|
|
if modeFromComment == "SSB" {
|
|
return bands.NormalizeSSBModeByFrequency(modeFromComment, freqMHz)
|
|
}
|
|
return modeFromComment
|
|
}
|
|
|
|
return GuessMode(freqMHz)
|
|
}
|
|
|
|
func IsCWMode(mode string) bool { return strings.ToUpper(mode) == "CW" }
|
|
func IsSSBMode(mode string) bool {
|
|
m := strings.ToUpper(mode)
|
|
return m == "SSB" || m == "USB" || m == "LSB"
|
|
}
|
|
func IsDigitalMode(mode string) bool {
|
|
m := strings.ToUpper(mode)
|
|
for _, dm := range []string{"FT8", "FT4", "RTTY", "PSK31", "PSK63", "PSK", "MFSK", "OLIVIA", "JT65", "JT9"} {
|
|
if m == dm {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
func IsPhoneMode(mode string) bool {
|
|
m := strings.ToUpper(mode)
|
|
for _, pm := range []string{"SSB", "USB", "LSB", "FM", "AM"} {
|
|
if m == pm {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func ParseModeFromRawSpot(rawSpot string) string {
|
|
re := regexp.MustCompile(`\b(CW|SSB|USB|LSB|FM|AM|FT8|FT4|RTTY|PSK\d*)\b`)
|
|
return re.FindString(strings.ToUpper(rawSpot))
|
|
}
|
|
|
|
func GetModeColor(mode string) string {
|
|
switch strings.ToUpper(mode) {
|
|
case "CW":
|
|
return "#10b981"
|
|
case "FT8", "FT4":
|
|
return "#8b5cf6"
|
|
case "RTTY":
|
|
return "#f59e0b"
|
|
case "FM":
|
|
return "#ec4899"
|
|
}
|
|
if IsSSBMode(mode) {
|
|
return "#3b82f6"
|
|
}
|
|
return "#6b7280"
|
|
}
|