Files
2026-03-17 20:20:23 +01:00

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"
}