123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- package identify
- import (
- "encoding/json"
- "fmt"
- "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 ItemValue // 当前值
- ov ItemValue // 上一次的值
- rules map[EventName]Rule
- vars map[string]string
- }
- func (s *SingleItem) Check(ov, nv ItemValue) EventName {
- 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) checkForMulti(ov, nv ItemValue, rule Rule) bool {
- if ov == "" || nv == "" {
- return false
- }
- s.ov = ov
- s.nv = nv
- defer func() {
- s.nv = ""
- s.ov = ""
- }()
- 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) check(rule Rule) bool {
- if s.ov == "" || s.nv == "" {
- return false
- }
- 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 []ItemValue) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.ov) == false {
- b = false
- }
- return b
- }
- func (s *SingleItem) ovNotIn(slice []ItemValue) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.ov) == true {
- b = false
- }
- return b
- }
- func (s *SingleItem) nvIn(slice []ItemValue) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.nv) == false {
- b = false
- }
- return b
- }
- func (s *SingleItem) nvNotIn(slice []ItemValue) bool {
- b := true
- if slice != nil && s.inSlice(slice, s.nv) == true {
- b = false
- }
- return b
- }
- func (s *SingleItem) inSlice(slice []ItemValue, v ItemValue) 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 ItemValue) ItemValue {
- v = strings.Replace(v, "$nv", s.nv, 10)
- v = strings.Replace(v, "$ov", s.ov, 10)
- if strings.Index(v, "$") > -1 && len(s.vars) > 0 {
- for k, kv := range s.vars {
- v = strings.Replace(v, "$"+k, kv, 10)
- }
- //varName := v[1:len(v)]
- //if val, ok := s.vars[varName]; ok {
- // v = val
- //}
- }
- if strings.Index(v, "...") == -1 {
- v = s.calc(v)
- } else {
- vl := strings.Split(v, "...")
- if len(vl) != 2 {
- return v
- } else {
- return fmt.Sprintf("%s...%s", s.calc(vl[0]), s.calc(vl[1]))
- }
- }
- 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) SetVars(vars map[ItemName]ItemValue) {
- s.vars = vars
- }
- func (s *SingleItem) calc(v string) string {
- if strings.Index(v, "+") > 1 {
- vl := strings.Split(v, "+")
- if len(vl) != 2 {
- return v
- }
- var st, nd int64
- var err error
- if st, err = strconv.ParseInt(strings.TrimSpace(vl[0]), 10, 64); err != nil {
- return v
- }
- if nd, err = strconv.ParseInt(strings.TrimSpace(vl[1]), 10, 64); err != nil {
- return v
- }
- return fmt.Sprintf("%d", st+nd)
- }
- if strings.Index(v, "-") > 1 {
- vl := strings.Split(v, "-")
- if len(vl) != 2 {
- return v
- }
- var st, nd int64
- var err error
- if st, err = strconv.ParseInt(strings.TrimSpace(vl[0]), 10, 64); err != nil {
- return v
- }
- if nd, err = strconv.ParseInt(strings.TrimSpace(vl[1]), 10, 64); err != nil {
- return v
- }
- return fmt.Sprintf("%d", st-nd)
- }
- if strings.Index(v, "*") > 1 {
- vl := strings.Split(v, "*")
- if len(vl) != 2 {
- return v
- }
- var st, nd int64
- var err error
- if st, err = strconv.ParseInt(strings.TrimSpace(vl[0]), 10, 64); err != nil {
- return v
- }
- if nd, err = strconv.ParseInt(strings.TrimSpace(vl[1]), 10, 64); err != nil {
- return v
- }
- return fmt.Sprintf("%d", st*nd)
- }
- if strings.Index(v, "/") > 1 {
- vl := strings.Split(v, "/")
- if len(vl) != 2 {
- return v
- }
- var st, nd int64
- var err error
- if st, err = strconv.ParseInt(strings.TrimSpace(vl[0]), 10, 64); err != nil {
- return v
- }
- if nd, err = strconv.ParseInt(strings.TrimSpace(vl[1]), 10, 64); err != nil {
- return v
- }
- return fmt.Sprintf("%d", st/nd)
- }
- if strings.Index(v, "%") > 1 {
- vl := strings.Split(v, "%")
- if len(vl) != 2 {
- return v
- }
- var st, nd int64
- var err error
- if st, err = strconv.ParseInt(strings.TrimSpace(vl[0]), 10, 64); err != nil {
- return v
- }
- if nd, err = strconv.ParseInt(strings.TrimSpace(vl[1]), 10, 64); err != nil {
- return v
- }
- return fmt.Sprintf("%d", st%nd)
- }
- return v
- }
- 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[EventName]Rule) *SingleItem {
- return &SingleItem{
- rules: rules,
- vars: make(map[string]string),
- }
- }
- // NewSingleCheck 生成一个检测对象, 之后调用Check来获得事件名称
- func newSingleCheckForMultiItem() *SingleItem {
- return &SingleItem{}
- }
- 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)
- }
|