sunty
2024-09-05 78c5692e45a4357adffb864dfe105fa36c814ed3
data/prepare.go
@@ -2,7 +2,10 @@
import (
   "fmt"
   "regexp"
   "ruleModelEngine/config"
   "ruleModelEngine/db"
   "strings"
   "time"
)
@@ -64,44 +67,140 @@
   return rules[1].Name
}
// SetFrequentAddress 方法计算出现最频繁的出行地址并设置为常用地址
func SetFrequentAddress(c *db.CaptureInfo) {
   outAddressCounts := make(map[string]int)
   inAddressCounts := make(map[string]int)
   // 统计每个出行地址的出现次数
   for _, detail := range c.CaptureDetail {
      if detail.Direction == "out" {
         outAddressCounts[detail.CaptureAddress]++
// 获取常用地址
func getfrAddress(pointAddress map[string]int) string {
   maxCount := 0
   maxCountAddress := ""
   re1F, _ := regexp.Compile(`\b1F\b`)
   reNoF, _ := regexp.Compile(`^[^F]*$`)
   reNegF := regexp.MustCompile(`-`)
   for address, count := range pointAddress {
      matchFlag1F := re1F.MatchString(address)
      matchFlagNoF := reNoF.MatchString(address)
      matchFlagNegF := reNegF.MatchString(address)
      if address == "" || matchFlag1F || matchFlagNoF || matchFlagNegF {
         continue
      }
      if detail.Direction == "in" {
         inAddressCounts[detail.CaptureAddress]++
      if count > maxCount {
         maxCount = count
         maxCountAddress = address
      }
   }
   return maxCountAddress
}
   // 找到出现次数最多的出行地址
   maxOutCount := 0
// SetFrequentAddress 方法计算出现最频繁的出行地址并设置为常用地址
func GetFrequentAddress(captureDetail []db.CaptureDetail) string {
   // 统计每个出行地址的出现次数
   //pointDate 靶标日期,pointAddress靶标地址
   pointDate := ""
   pointAddress := make(map[string]int, 0)
   //dateAddress 按日期汇总单日常用地址
   dateAddress := make(map[string]string, 0)
   //floor1Address 后备地址,为1楼地址
   floor1Address := ""
   //captureDays 按日期去重统计总抓拍天数
   captureDays := make(map[string]int, 0)
   //frequentAddress 最终设置的常用地址
   var frequentAddress string
   for address, count := range outAddressCounts {
      if count > maxOutCount {
         maxOutCount = count
         frequentAddress = address
   //正则 判断地址是否包含1F字样,完全匹配
   re1F, _ := regexp.Compile(`\b1F\b`)
   reNoF, _ := regexp.Compile(`^[^F]*$`)
   // 遍历所有抓拍数据
   for index, detail := range captureDetail {
      //fmt.Println("抓拍地址:", detail.CaptureAddress)
      //fmt.Println("抓拍日期:", detail.CaptureDate)
      //dateStr截取的日期,为YYYY-MM-DD
      dateStr := strings.Split(detail.CaptureDate, " ")[0]
      //去重统计抓拍天数 captureDays
      captureDays[dateStr]++
      //匹配是否是1F
      matchFlag1F := re1F.MatchString(detail.CaptureAddress)
      matchFlagNoF := reNoF.MatchString(detail.CaptureAddress)
      if matchFlag1F {
         //如果是, 提前设置好备用地址 floor1Address = detail.CaptureAddress
         floor1Address = detail.CaptureAddress
      }
   }
   if frequentAddress == "" {
      maxInCount := 0
      for address, count := range inAddressCounts {
         if count > maxInCount {
            maxInCount = count
            frequentAddress = address
      if matchFlagNoF && floor1Address == "" {
         //如果是, 提前设置好备用地址 floor1Address = detail.CaptureAddress
         floor1Address = detail.CaptureAddress
      }
      //fmt.Println("now floor1Address:", floor1Address,"\tnow detail CaptureAddress",detail.CaptureAddress)
      //判断日期标是否满足条件 判断日期标是否为空,若为空表示是第一个元素,初始化日期靶标
      if pointDate == "" {
         //初始化日期靶标为当前日期
         pointDate = dateStr
         //把当前日期的
         pointAddress[detail.CaptureAddress]++
         //若为最后一条则计算单日常用地址
         if index == len(captureDetail)-1 {
            //fmt.Println("处理前pointAddress表:", pointAddress)
            //这代表仅有一条数据,将会直接把当前地址加入dateAddress 日期汇总单日常用地址表内 下方continue会直接结束循环
            //否则会初始化pointDate和pointAddress
            dateAddress[pointDate] = detail.CaptureAddress
         }
         continue
      }
      //若日期标相等则为同一天
      if pointDate == dateStr {
         //pointAddress靶标日期数组对应楼层地址数+1
         pointAddress[detail.CaptureAddress]++
         //若为最后一条则计算单日常用地址
         if index == len(captureDetail)-1 {
            //fmt.Println("处理前pointAddress表:", pointAddress)
            //计算单日常用地址 若地址内都为1F或者空地址,会返回空地址
            dateAddress[pointDate] = getfrAddress(pointAddress)
            continue
         }
         //不相等则为新的日期,首先计算出当日的常用地址,然后重新初始化日期标和地址标数组
      } else {
         //若为最后一条则计算单日常用地址
         if index == len(captureDetail)-1 {
            //把当前最后一条加入   pointAddress靶标地址
            pointAddress[detail.CaptureAddress]++
            //
            //fmt.Println("处理前pointAddress表:", pointAddress)
            //计算单日常用地址 若地址内都为1F或者空地址,会返回空地址
            dateAddress[pointDate] = getfrAddress(pointAddress)
            continue
         }
         //不为最后一条表示这是新的一天的抓拍地址数据,需要计算之前一天的单日常用地址
         dateAddress[pointDate] = getfrAddress(pointAddress)
         //初始化新的一天的靶标日期和pointAddress 靶标地址数组
         pointDate = dateStr
         pointAddress = make(map[string]int, 0)
      }
   }
   // 将出现次数最多的出行地址设置为常用地址
   c.FrequentAddress = frequentAddress
   //fmt.Println("抓拍地址待处理结构表:", dateAddress)
   //fmt.Println("dareAddress len: ", len(dateAddress))
   //判断抓拍的非1楼非空非地下的天数占比总天数
   if float64(len(dateAddress))/float64(len(captureDays))*100 >= float64(config.Api.CapAddrDaysThreshold) {
      //fmt.Println("非1楼非空抓拍占比: ", float64(len(dateAddress))/float64(len(captureDays))*100)
      //初始化地址列表,按地址计数
      addressCount := make(map[string]int)
      //遍历之前汇总的单日常用地址列表
      for _, address := range dateAddress {
         //对应地址数+1
         addressCount[address]++
      }
      //复制常用地址给最终结果,若地址内都为1F或者空地址,会返回空地址
      frequentAddress = getfrAddress(addressCount)
   } else {
      //若不满足非1楼非空抓拍占比,则直接把备用地址(1F)赋值给最终结果
      frequentAddress = floor1Address
   }
   //若存在满足非1楼非空抓拍占比,但是最终结果是空地址,则赋值备用地址(1F)为最终结果
   if frequentAddress == "" {
      frequentAddress = floor1Address
   }
   //fmt.Println("in address: ", inAddressCounts)
   //fmt.Println("out address: ", outAddressCounts)
   //fmt.Println("final address: ", frequentAddress)
   return frequentAddress
}
// processData 函数处理数据,根据要求过滤掉数据并根据规则更新状态
func ProcessData(captureInfos []db.CaptureInfo, personStatus []db.PersonStatus, ruleInfos []db.PersonnelStatusRule, communityID string) []db.PersonStatus {
func ProcessData(captureInfos []db.CaptureInfo, personStatus []*db.PersonStatus, ruleInfos []db.PersonnelStatusRule, communityID string) []db.PersonStatus {
   filteredInfos := make([]db.PersonStatus, 0)
   // 构建快速查找索引,方便查找对应的人员状态和规则
@@ -109,35 +208,31 @@
   ruleIndex := make(map[string]db.PersonnelStatusRule)
   for _, person := range personStatus {
      statusIndex[person.DocumentNumber] = person
      statusIndex[person.DocumentNumber] = *person
   }
   for _, rule := range ruleInfos {
      ruleIndex[rule.Name] = rule
   }
   //fmt.Println("statusIndex: ", statusIndex)
   //fmt.Println("ruleIndex: ", ruleIndex)
   // 处理每个抓拍信息
   for _, info := range captureInfos {
      //fmt.Println("info", info.DocumentNumber, info.Status, info.FrequentAddress)
      //fmt.Println("person", statusIndex[info.DocumentNumber].DocumentNumber, statusIndex[info.DocumentNumber].Status, statusIndex[info.DocumentNumber].FrequentAddress)
      // 检查是否存在对应的人员状态
      person, ok := statusIndex[info.DocumentNumber]
      if !ok {
         // 不存在对应的人员状态为新数据
         filteredInfos = append(filteredInfos, db.PersonStatus{OrgId: info.OrgId, CommunityID: communityID, DocumentNumber: info.DocumentNumber, Status: info.Status, FrequentAddress: info.FrequentAddress})
         continue
      }
      person := statusIndex[info.DocumentNumber]
      //fmt.Println("person: ", person.DocumentNumber, person.Status, person.FrequentAddress, person.LastAppearanceTime, person.LastAppearanceStatusTime)
      // 判断状态和常用地址是否相等,如果相等则忽略
      if (info.Status == person.Status || info.CaptureDays <= ruleIndex[person.DocumentNumber].DetectionDaysEnd) &&
         info.FrequentAddress == person.FrequentAddress {
         continue
      }
      //if (info.Status == person.Status || info.CaptureDays <= ruleIndex[person.DocumentNumber].DetectionDaysEnd) &&
      //   info.FrequentAddress == person.FrequentAddress {
      //   continue
      //}
      // 更新过滤后的信息列表
      filteredInfos = append(filteredInfos, db.PersonStatus{OrgId: info.OrgId, CommunityID: communityID, DocumentNumber: info.DocumentNumber, Status: info.Status, FrequentAddress: info.FrequentAddress})
      //fmt.Println("LastAppearanceTime: ", person.LastAppearanceTime)
      filteredInfos = append(filteredInfos, db.PersonStatus{CommunityID: communityID, DocumentNumber: info.DocumentNumber, Status: info.Status, FrequentAddress: info.FrequentAddress, LastAppearanceStatusTime: person.LastAppearanceTime})
   }
   //fmt.Println("filteredInfos: ", filteredInfos)
   return filteredInfos
}