Wideband autonomous SDR analysis engine forked from sdr-visual-suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
3.6KB

  1. package pipeline
  2. import (
  3. "strings"
  4. )
  5. const (
  6. PriorityTierCritical = "critical"
  7. PriorityTierHigh = "high"
  8. PriorityTierMedium = "medium"
  9. PriorityTierLow = "low"
  10. PriorityTierBackground = "background"
  11. )
  12. const (
  13. AdmissionClassPlanned = "plan"
  14. AdmissionClassAdmit = "admit"
  15. AdmissionClassHold = "hold"
  16. AdmissionClassDefer = "defer"
  17. AdmissionClassDisplace = "displace"
  18. AdmissionClassDrop = "drop"
  19. )
  20. type PriorityAdmission struct {
  21. Tier string `json:"tier,omitempty"`
  22. TierFloor string `json:"tier_floor,omitempty"`
  23. Family string `json:"family,omitempty"`
  24. FamilyRank int `json:"family_rank,omitempty"`
  25. Class string `json:"class,omitempty"`
  26. Score float64 `json:"score,omitempty"`
  27. Cutoff float64 `json:"cutoff,omitempty"`
  28. Basis string `json:"basis,omitempty"`
  29. Reason string `json:"reason,omitempty"`
  30. }
  31. func PriorityTierFromRange(score, min, max float64) string {
  32. if max <= min {
  33. return PriorityTierHigh
  34. }
  35. norm := (score - min) / (max - min)
  36. switch {
  37. case norm >= 0.85:
  38. return PriorityTierCritical
  39. case norm >= 0.65:
  40. return PriorityTierHigh
  41. case norm >= 0.45:
  42. return PriorityTierMedium
  43. case norm >= 0.25:
  44. return PriorityTierLow
  45. default:
  46. return PriorityTierBackground
  47. }
  48. }
  49. func priorityTierRank(tier string) int {
  50. switch tier {
  51. case PriorityTierCritical:
  52. return 4
  53. case PriorityTierHigh:
  54. return 3
  55. case PriorityTierMedium:
  56. return 2
  57. case PriorityTierLow:
  58. return 1
  59. default:
  60. return 0
  61. }
  62. }
  63. func admissionReason(base string, policy Policy, holdPolicy HoldPolicy, extras ...string) string {
  64. tags := uniqueReasonTags(policy, holdPolicy, extras...)
  65. if len(tags) == 0 {
  66. return base
  67. }
  68. return base + ":" + strings.Join(tags, ":")
  69. }
  70. func uniqueReasonTags(policy Policy, holdPolicy HoldPolicy, extras ...string) []string {
  71. seen := map[string]struct{}{}
  72. tags := make([]string, 0, 6)
  73. add := func(tag string) {
  74. if tag == "" {
  75. return
  76. }
  77. if _, ok := seen[tag]; ok {
  78. return
  79. }
  80. seen[tag] = struct{}{}
  81. tags = append(tags, tag)
  82. }
  83. if policy.Profile != "" {
  84. add("profile:" + slugToken(policy.Profile))
  85. }
  86. if policy.Intent != "" {
  87. add("intent:" + slugToken(policy.Intent))
  88. }
  89. if policy.RefinementStrategy != "" {
  90. add("strategy:" + slugToken(policy.RefinementStrategy))
  91. }
  92. for _, reason := range holdPolicy.Reasons {
  93. add(reason)
  94. }
  95. for _, extra := range extras {
  96. add(extra)
  97. }
  98. return tags
  99. }
  100. func slugToken(input string) string {
  101. input = strings.TrimSpace(strings.ToLower(input))
  102. if input == "" {
  103. return ""
  104. }
  105. parts := strings.Fields(input)
  106. return strings.Join(parts, "-")
  107. }
  108. func signalPriorityMatch(policy Policy, hint string, class string) (string, int) {
  109. tag := strings.ToLower(strings.TrimSpace(hint))
  110. if tag == "" {
  111. tag = strings.ToLower(strings.TrimSpace(class))
  112. }
  113. if tag == "" || len(policy.SignalPriorities) == 0 {
  114. return "", -1
  115. }
  116. for i, want := range policy.SignalPriorities {
  117. w := strings.ToLower(strings.TrimSpace(want))
  118. if w == "" {
  119. continue
  120. }
  121. if strings.Contains(tag, w) || strings.Contains(w, tag) {
  122. return w, i
  123. }
  124. }
  125. return "", -1
  126. }
  127. func signalPriorityTierFloor(rank int) string {
  128. switch rank {
  129. case 0:
  130. return PriorityTierHigh
  131. case 1:
  132. return PriorityTierMedium
  133. case 2:
  134. return PriorityTierLow
  135. default:
  136. return ""
  137. }
  138. }
  139. func applyTierFloor(tier string, floor string) string {
  140. if floor == "" {
  141. return tier
  142. }
  143. if priorityTierRank(tier) < priorityTierRank(floor) {
  144. return floor
  145. }
  146. return tier
  147. }
  148. func familyRankForOutput(rank int) int {
  149. if rank < 0 {
  150. return 0
  151. }
  152. return rank + 1
  153. }
  154. func familyDisplaceOrder(rank int) int {
  155. if rank < 0 {
  156. return 100
  157. }
  158. return rank
  159. }