single.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. package identify
  2. import (
  3. "encoding/json"
  4. "strconv"
  5. "strings"
  6. )
  7. // SingleItem Nv和Ov的组合规则:
  8. // 1. Nv是什么 || Nv不是什么
  9. // 2. Ov是什么 || Ov不是什么
  10. //
  11. // 1与2的布尔运行结果交叉后, 得到4种组合 00, 01, 10, 11.
  12. // 一个事件的判断, 就处在[00, 01, 10, 11]的其中, 有一项为nil, 则表示该项直接通过
  13. // 多个事件, 就判断多个[00, 01, 10, 11], 所以得出以下结论:
  14. // 针对设备配置如下规则:
  15. //
  16. // {
  17. // "EventName 1": {
  18. // "NvIn": [1,2,3,4],
  19. // "NvNotIn": [5,6,7,8],
  20. // "OvIn": [1,2,3,4],
  21. // "OvNotIn": [5,6,7,8],
  22. // },
  23. // "EventName 2": {
  24. // "NvIn": [1,2,3,4],
  25. // "NvNotIn": [5,6,7,8],
  26. // "OvNotIn": [5,6,7,8],
  27. // },
  28. // ......
  29. // }
  30. type SingleItem struct {
  31. nv string // 当前值
  32. ov string // 上一次的值
  33. rules map[string]Rule
  34. }
  35. func (s *SingleItem) Check(ov, nv string) string {
  36. defer func() {
  37. s.nv = ""
  38. s.ov = ""
  39. }()
  40. s.nv = nv
  41. s.ov = ov
  42. for event, rule := range s.rules {
  43. if s.check(rule) {
  44. return event
  45. }
  46. }
  47. return ""
  48. }
  49. func (s *SingleItem) check(rule Rule) bool {
  50. var ovIn, ovNotIn, nvIn, nvNotIn = true, true, true, true
  51. if rule.OvIn != nil {
  52. ovIn = s.ovIn(rule.OvIn)
  53. }
  54. if rule.OvNotIn != nil {
  55. ovNotIn = s.ovNotIn(rule.OvNotIn)
  56. }
  57. if rule.NvIn != nil {
  58. nvIn = s.nvIn(rule.NvIn)
  59. }
  60. if rule.NvNotIn != nil {
  61. nvNotIn = s.nvNotIn(rule.NvNotIn)
  62. }
  63. return ovIn && ovNotIn && nvIn && nvNotIn
  64. }
  65. func (s *SingleItem) ovIn(slice []string) bool {
  66. b := true
  67. if slice != nil && s.inSlice(slice, s.ov) == false {
  68. b = false
  69. }
  70. return b
  71. }
  72. func (s *SingleItem) ovNotIn(slice []string) bool {
  73. b := true
  74. if slice != nil && s.inSlice(slice, s.ov) == true {
  75. b = false
  76. }
  77. return b
  78. }
  79. func (s *SingleItem) nvIn(slice []string) bool {
  80. b := true
  81. if slice != nil && s.inSlice(slice, s.nv) == false {
  82. b = false
  83. }
  84. return b
  85. }
  86. func (s *SingleItem) nvNotIn(slice []string) bool {
  87. b := true
  88. if slice != nil && s.inSlice(slice, s.nv) == true {
  89. b = false
  90. }
  91. return b
  92. }
  93. func (s *SingleItem) inSlice(slice []string, v string) bool {
  94. for _, s2 := range slice {
  95. s1 := s.transVar(s2)
  96. if s1 == v {
  97. return true
  98. }
  99. // 数字比较
  100. if _, err := strconv.ParseInt(s1, 10, 64); err != nil {
  101. return s.compare(s1, v)
  102. }
  103. }
  104. return false
  105. }
  106. func (s *SingleItem) transVar(v string) string {
  107. if v == VAR_NV {
  108. v = s.nv
  109. }
  110. if v == VAR_OV {
  111. v = s.ov
  112. }
  113. return v
  114. }
  115. func (s *SingleItem) compare(r string, v string) bool {
  116. if strings.Index(r, "...") > -1 {
  117. return s.compareRange(r, v)
  118. } else if strings.Index(r, " ") > 1 {
  119. return s.compareLogic(r, v)
  120. }
  121. return false
  122. }
  123. func (s *SingleItem) compareRange(r string, v string) bool {
  124. rl := strings.Split(r, "...")
  125. if len(rl) != 2 {
  126. return false
  127. }
  128. var min, max, vi int64 = 0, 0, 0
  129. if tmin, err := strconv.ParseInt(strings.TrimSpace(rl[0]), 10, 64); err == nil {
  130. min = tmin
  131. } else {
  132. return false
  133. }
  134. if tmax, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
  135. max = tmax
  136. } else {
  137. return false
  138. }
  139. if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
  140. vi = tvi
  141. } else {
  142. return false
  143. }
  144. return min <= vi && vi <= max
  145. }
  146. func (s *SingleItem) compareLogic(r string, v string) bool {
  147. rl := strings.Split(r, " ")
  148. if len(rl) != 2 {
  149. return false
  150. }
  151. var ri, vi int64 = 0, 0
  152. if tri, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
  153. ri = tri
  154. } else {
  155. return false
  156. }
  157. if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
  158. vi = tvi
  159. } else {
  160. return false
  161. }
  162. switch rl[0] {
  163. case "<":
  164. return vi < ri
  165. case "<=":
  166. return vi <= ri
  167. case ">":
  168. return vi > ri
  169. case ">=":
  170. return vi >= ri
  171. case "!=":
  172. return vi != ri
  173. }
  174. return false
  175. }
  176. // NewSingleCheck 生成一个检测对象, 之后调用Check来获得事件名称
  177. func NewSingleCheck(rules map[string]Rule) *SingleItem {
  178. return &SingleItem{
  179. rules: rules,
  180. }
  181. }
  182. func StepTest(ov, nv, ruleString string) string {
  183. rules := make(map[string]Rule)
  184. err := json.Unmarshal([]byte(ruleString), &rules)
  185. if err != nil {
  186. println(err.Error())
  187. }
  188. return NewSingleCheck(rules).Check(ov, nv)
  189. }