Wideband autonomous SDR analysis engine forked from sdr-visual-suite
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

166 行
4.0KB

  1. package pipeline
  2. import "strings"
  3. func WantsClass(values []string, class string) bool {
  4. if len(values) == 0 || class == "" {
  5. return false
  6. }
  7. for _, v := range values {
  8. if strings.EqualFold(strings.TrimSpace(v), class) {
  9. return true
  10. }
  11. }
  12. return false
  13. }
  14. func CandidatePriorityBoost(policy Policy, hint string) float64 {
  15. boost := hintMatchBoost(policy.SignalPriorities, hint, 3.0)
  16. boost += hintMatchBoost(policy.AutoRecordClasses, hint, 1.5)
  17. boost += hintMatchBoost(policy.AutoDecodeClasses, hint, 1.0)
  18. boost += intentHintBoost(policy.Intent, hint, 2.0)
  19. return boost
  20. }
  21. func DecisionPriorityBoost(policy Policy, hint string, class string, queue string) float64 {
  22. tag := strings.TrimSpace(hint)
  23. if tag == "" {
  24. tag = strings.TrimSpace(class)
  25. }
  26. boost := CandidatePriorityBoost(policy, tag)
  27. switch strings.ToLower(strings.TrimSpace(queue)) {
  28. case "record":
  29. boost += hintMatchBoost(policy.AutoRecordClasses, tag, 3.0)
  30. case "decode":
  31. boost += hintMatchBoost(policy.AutoDecodeClasses, tag, 3.0)
  32. }
  33. boost += intentQueueBoost(policy.Intent, queue)
  34. boost += queueStrategyBoost(policy, queue)
  35. return boost
  36. }
  37. func hintMatchBoost(values []string, hint string, weight float64) float64 {
  38. h := strings.ToLower(strings.TrimSpace(hint))
  39. if h == "" || len(values) == 0 {
  40. return 0
  41. }
  42. for i, want := range values {
  43. w := strings.ToLower(strings.TrimSpace(want))
  44. if w == "" {
  45. continue
  46. }
  47. if strings.Contains(h, w) || strings.Contains(w, h) {
  48. return float64(len(values)-i) * weight
  49. }
  50. }
  51. return 0
  52. }
  53. func intentHintBoost(intent string, hint string, weight float64) float64 {
  54. tokens := intentTokens(intent)
  55. if len(tokens) == 0 {
  56. return 0
  57. }
  58. return hintMatchBoost(tokens, hint, weight)
  59. }
  60. func intentQueueBoost(intent string, queue string) float64 {
  61. if intent == "" {
  62. return 0
  63. }
  64. intent = strings.ToLower(intent)
  65. queue = strings.ToLower(strings.TrimSpace(queue))
  66. boost := 0.0
  67. switch queue {
  68. case "record":
  69. if strings.Contains(intent, "archive") || strings.Contains(intent, "record") {
  70. boost += 2.0
  71. }
  72. if strings.Contains(intent, "triage") {
  73. boost += 1.0
  74. }
  75. case "decode":
  76. if strings.Contains(intent, "triage") {
  77. boost += 1.5
  78. }
  79. if strings.Contains(intent, "decode") || strings.Contains(intent, "analysis") || strings.Contains(intent, "classif") {
  80. boost += 1.0
  81. }
  82. }
  83. return boost
  84. }
  85. func queueStrategyBoost(policy Policy, queue string) float64 {
  86. queue = strings.ToLower(strings.TrimSpace(queue))
  87. if queue == "" {
  88. return 0
  89. }
  90. boost := 0.0
  91. profile := strings.ToLower(strings.TrimSpace(policy.Profile))
  92. strategy := strings.ToLower(strings.TrimSpace(policy.RefinementStrategy))
  93. if strings.Contains(profile, "archive") || strings.Contains(strategy, "archive") {
  94. if queue == "record" {
  95. boost += 1.5
  96. } else if queue == "decode" {
  97. boost += 0.5
  98. }
  99. }
  100. if strings.Contains(profile, "digital") || strings.Contains(strategy, "digital") {
  101. if queue == "decode" {
  102. boost += 1.5
  103. } else if queue == "record" {
  104. boost += 0.3
  105. }
  106. }
  107. return boost
  108. }
  109. func refinementIntentWeights(intent string) (float64, float64, float64) {
  110. if intent == "" {
  111. return 1.0, 1.0, 1.0
  112. }
  113. intent = strings.ToLower(intent)
  114. snrWeight := 1.0
  115. bwWeight := 1.0
  116. peakWeight := 1.0
  117. if strings.Contains(intent, "wideband") {
  118. bwWeight = 1.25
  119. }
  120. if strings.Contains(intent, "high-density") || strings.Contains(intent, "highdensity") {
  121. bwWeight = 1.4
  122. peakWeight = 1.1
  123. }
  124. if strings.Contains(intent, "archive") || strings.Contains(intent, "triage") {
  125. snrWeight = 1.15
  126. peakWeight = 1.1
  127. }
  128. return snrWeight, bwWeight, peakWeight
  129. }
  130. func intentTokens(intent string) []string {
  131. if intent == "" {
  132. return nil
  133. }
  134. fields := strings.FieldsFunc(intent, func(r rune) bool {
  135. if r >= 'a' && r <= 'z' {
  136. return false
  137. }
  138. if r >= 'A' && r <= 'Z' {
  139. return false
  140. }
  141. if r >= '0' && r <= '9' {
  142. return false
  143. }
  144. return true
  145. })
  146. tokens := make([]string, 0, len(fields))
  147. for _, f := range fields {
  148. t := strings.ToLower(strings.TrimSpace(f))
  149. if len(t) < 2 {
  150. continue
  151. }
  152. tokens = append(tokens, t)
  153. }
  154. return tokens
  155. }