123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- package identify
- import (
- "encoding/json"
- "strconv"
- "strings"
- )
- // SingleItem Nv和Ov的组合规则:
- // 1. Nv是什么 || Nv不是什么
- // 2. Ov是什么 || Ov不是什么
- //
- // 1与2的布尔运行结果交叉后, 得到4种组合 00, 01, 10, 11.
- // 一个事件的判断, 就处在[00, 01, 10, 11]的其中, 有一项为nil, 则表示该项直接通过
- // 多个事件, 就判断多个[00, 01, 10, 11], 所以得出以下结论:
- // 针对设备配置如下规则:
- //
- // {
- // "EventName 1": {
- // "NvIn": [1,2,3,4],
- // "NvNotIn": [5,6,7,8],
- // "OvIn": [1,2,3,4],
- // "OvNotIn": [5,6,7,8],
- // },
- // "EventName 2": {
- // "NvIn": [1,2,3,4],
- // "NvNotIn": [5,6,7,8],
- // "OvNotIn": [5,6,7,8],
- // },
- // ......
- // }
- type SingleItem struct {
- nv string // 当前值
- ov string // 上一次的值
- rules map[string]Rule
- }
- func (s *SingleItem) Check(ov, nv string) string {
- defer func() {
- s.nv = ""
- s.ov = ""
- }()
- s.nv = nv
- s.ov = ov
- for event, rule := range s.rules {
- if s.check(rule) {
- return event
- }
- }
- return ""
- }
- func (s *SingleItem) check(rule Rule) bool {
- var ovIn, ovNotIn, nvIn, nvNotIn = true, true, true, true
- if rule.OvIn != nil {
- ovIn = s.ovIn(rule.OvIn)
- }
- if rule.OvNotIn != nil {
- ovNotIn = s.ovNotIn(rule.OvNotIn)
- }
- if rule.NvIn != nil {
- nvIn = s.nvIn(rule.NvIn)
- }
- if rule.NvNotIn != nil {
- nvNotIn = s.nvNotIn(rule.NvNotIn)
- }
- return ovIn && ovNotIn && nvIn && nvNotIn
- }
- func (s *SingleItem) ovIn(slice []string) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.ov) == false {
- b = false
- }
- return b
- }
- func (s *SingleItem) ovNotIn(slice []string) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.ov) == true {
- b = false
- }
- return b
- }
- func (s *SingleItem) nvIn(slice []string) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.nv) == false {
- b = false
- }
- return b
- }
- func (s *SingleItem) nvNotIn(slice []string) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.nv) == true {
- b = false
- }
- return b
- }
- func (s *SingleItem) inSlice(slice []string, v string) bool {
- for _, s2 := range slice {
- s1 := s.transVar(s2)
- if s1 == v {
- return true
- }
- // 数字比较
- if _, err := strconv.ParseInt(s1, 10, 64); err != nil {
- return s.compare(s1, v)
- }
- }
- return false
- }
- func (s *SingleItem) transVar(v string) string {
- if v == VAR_NV {
- v = s.nv
- }
- if v == VAR_OV {
- v = s.ov
- }
- return v
- }
- func (s *SingleItem) compare(r string, v string) bool {
- if strings.Index(r, "...") > -1 {
- return s.compareRange(r, v)
- } else if strings.Index(r, " ") > 1 {
- return s.compareLogic(r, v)
- }
- return false
- }
- func (s *SingleItem) compareRange(r string, v string) bool {
- rl := strings.Split(r, "...")
- if len(rl) != 2 {
- return false
- }
- var min, max, vi int64 = 0, 0, 0
- if tmin, err := strconv.ParseInt(strings.TrimSpace(rl[0]), 10, 64); err == nil {
- min = tmin
- } else {
- return false
- }
- if tmax, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
- max = tmax
- } else {
- return false
- }
- if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
- vi = tvi
- } else {
- return false
- }
- return min <= vi && vi <= max
- }
- func (s *SingleItem) compareLogic(r string, v string) bool {
- rl := strings.Split(r, " ")
- if len(rl) != 2 {
- return false
- }
- var ri, vi int64 = 0, 0
- if tri, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
- ri = tri
- } else {
- return false
- }
- if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
- vi = tvi
- } else {
- return false
- }
- switch rl[0] {
- case "<":
- return vi < ri
- case "<=":
- return vi <= ri
- case ">":
- return vi > ri
- case ">=":
- return vi >= ri
- case "!=":
- return vi != ri
- }
- return false
- }
- // NewSingleCheck 生成一个检测对象, 之后调用Check来获得事件名称
- func NewSingleCheck(rules map[string]Rule) *SingleItem {
- return &SingleItem{
- rules: rules,
- }
- }
- func StepTest(ov, nv, ruleString string) string {
- rules := make(map[string]Rule)
- err := json.Unmarshal([]byte(ruleString), &rules)
- if err != nil {
- println(err.Error())
- }
- return NewSingleCheck(rules).Check(ov, nv)
- }
|