single.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. if s.ov == "" || s.nv == "" {
  51. return false
  52. }
  53. var ovIn, ovNotIn, nvIn, nvNotIn = true, true, true, true
  54. if rule.OvIn != nil {
  55. ovIn = s.ovIn(rule.OvIn)
  56. }
  57. if rule.OvNotIn != nil {
  58. ovNotIn = s.ovNotIn(rule.OvNotIn)
  59. }
  60. if rule.NvIn != nil {
  61. nvIn = s.nvIn(rule.NvIn)
  62. }
  63. if rule.NvNotIn != nil {
  64. nvNotIn = s.nvNotIn(rule.NvNotIn)
  65. }
  66. return ovIn && ovNotIn && nvIn && nvNotIn
  67. }
  68. func (s *SingleItem) ovIn(slice []string) bool {
  69. b := true
  70. if slice != nil && s.inSlice(slice, s.ov) == false {
  71. b = false
  72. }
  73. return b
  74. }
  75. func (s *SingleItem) ovNotIn(slice []string) bool {
  76. b := true
  77. if slice != nil && s.inSlice(slice, s.ov) == true {
  78. b = false
  79. }
  80. return b
  81. }
  82. func (s *SingleItem) nvIn(slice []string) bool {
  83. b := true
  84. if slice != nil && s.inSlice(slice, s.nv) == false {
  85. b = false
  86. }
  87. return b
  88. }
  89. func (s *SingleItem) nvNotIn(slice []string) bool {
  90. b := true
  91. if slice != nil && s.inSlice(slice, s.nv) == true {
  92. b = false
  93. }
  94. return b
  95. }
  96. func (s *SingleItem) inSlice(slice []string, v string) bool {
  97. for _, s2 := range slice {
  98. s1 := s.transVar(s2)
  99. if s1 == v {
  100. return true
  101. }
  102. // 数字比较
  103. if _, err := strconv.ParseInt(s1, 10, 64); err != nil {
  104. return s.compare(s1, v)
  105. }
  106. }
  107. return false
  108. }
  109. func (s *SingleItem) transVar(v string) string {
  110. if v == VAR_NV {
  111. v = s.nv
  112. }
  113. if v == VAR_OV {
  114. v = s.ov
  115. }
  116. return v
  117. }
  118. func (s *SingleItem) compare(r string, v string) bool {
  119. if strings.Index(r, "...") > -1 {
  120. return s.compareRange(r, v)
  121. } else if strings.Index(r, " ") > 1 {
  122. return s.compareLogic(r, v)
  123. }
  124. return false
  125. }
  126. func (s *SingleItem) compareRange(r string, v string) bool {
  127. rl := strings.Split(r, "...")
  128. if len(rl) != 2 {
  129. return false
  130. }
  131. var min, max, vi int64 = 0, 0, 0
  132. if tmin, err := strconv.ParseInt(strings.TrimSpace(rl[0]), 10, 64); err == nil {
  133. min = tmin
  134. } else {
  135. return false
  136. }
  137. if tmax, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
  138. max = tmax
  139. } else {
  140. return false
  141. }
  142. if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
  143. vi = tvi
  144. } else {
  145. return false
  146. }
  147. return min <= vi && vi <= max
  148. }
  149. func (s *SingleItem) compareLogic(r string, v string) bool {
  150. rl := strings.Split(r, " ")
  151. if len(rl) != 2 {
  152. return false
  153. }
  154. var ri, vi int64 = 0, 0
  155. if tri, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
  156. ri = tri
  157. } else {
  158. return false
  159. }
  160. if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
  161. vi = tvi
  162. } else {
  163. return false
  164. }
  165. switch rl[0] {
  166. case "<":
  167. return vi < ri
  168. case "<=":
  169. return vi <= ri
  170. case ">":
  171. return vi > ri
  172. case ">=":
  173. return vi >= ri
  174. case "!=":
  175. return vi != ri
  176. }
  177. return false
  178. }
  179. // NewSingleCheck 生成一个检测对象, 之后调用Check来获得事件名称
  180. func NewSingleCheck(rules map[string]Rule) *SingleItem {
  181. return &SingleItem{
  182. rules: rules,
  183. }
  184. }
  185. func StepTest(ov, nv, ruleString string) string {
  186. rules := make(map[string]Rule)
  187. err := json.Unmarshal([]byte(ruleString), &rules)
  188. if err != nil {
  189. println(err.Error())
  190. }
  191. return NewSingleCheck(rules).Check(ov, nv)
  192. }