| | |
| | | |
| | | import ( |
| | | "fmt" |
| | | "regexp" |
| | | "ruleModelEngine/config" |
| | | "ruleModelEngine/db" |
| | | "strings" |
| | | "time" |
| | | ) |
| | | |
| | |
| | | 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) |
| | | |
| | | // 构建快速查找索引,方便查找对应的人员状态和规则 |
| | |
| | | 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 |
| | | } |