sunty
2024-09-04 b88f052edf3c6921aa7a52f53144c202af266957
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package data
 
import (
    "fmt"
    "regexp"
    "ruleModelEngine/db"
    "strings"
    "time"
)
 
// 计算抓拍天数
func CalculateCaptureDays(details []db.CaptureDetail) (int, int) {
    // 使用 map 来存储每天是否有抓拍记录
    captureMap := make(map[string]bool)
    //pointDate := ""
    //pointTime := ""
    //pointDirection := ""
    overnightCount := 0
    for i, detail := range details {
        // 解析抓拍日期
        layout := "2006-01-02 15:04:05"
        captureTime, err := time.Parse(layout, detail.CaptureDate)
        if err != nil {
            fmt.Println("解析抓拍日期时出错:", err)
            continue
        }
        //fmt.Println(captureTime, detail.Direction)
        // 获取日期部分
        date := captureTime.Format("2006-01-02")
        //time := captureTime.Format("15:04:05")
        // 在 map 中标记这一天有抓拍记录
        captureMap[date] = true
        if i == len(details)-1 {
            break
        }
 
        // 第一个验证条件:当前为 in,时间在下午 16 点以后
        currTime, _ := time.Parse("2006-01-02 15:04:05", detail.CaptureDate)
        if detail.Direction == "in" && currTime.Hour() >= 16 {
            // 第二个验证条件:下一个为 out,时间在上午 5 点之后 12 点之前
            nextDetail := details[i+1]
            nextTime, _ := time.Parse("2006-01-02 15:04:05", nextDetail.CaptureDate)
            nextDay := nextTime.AddDate(0, 0, -1).Format("2006-01-02")
            if nextDetail.Direction == "out" && nextTime.Hour() >= 5 && nextTime.Hour() < 12 && nextDay == detail.CaptureDate[:10] {
                overnightCount++
            }
        }
    }
 
    // 统计有抓拍记录的天数
    captureDays := 0
    for range captureMap {
        captureDays++
    }
 
    return captureDays, overnightCount
}
 
// 设置状态
func SetStatus(captureDays int, rules []db.PersonnelStatusRule) string {
    for _, rule := range rules {
        if captureDays >= rule.DetectionDaysStart && captureDays <= rule.DetectionDaysEnd {
            return rule.Name
        }
    }
    return rules[1].Name
}
 
// 获取常用地址
func getfrAddress(pointAddress map[string]int) string {
    maxCount := 0
    maxCountAddress := ""
    re, _ := regexp.Compile(`\b1F\b`)
    for address, count := range pointAddress {
        matchFlag := re.MatchString(address)
        if address == "" || matchFlag == true {
            continue
        }
        if count > maxCount {
            maxCount = count
            maxCountAddress = address
        }
    }
    return maxCountAddress
}
 
// SetFrequentAddress 方法计算出现最频繁的出行地址并设置为常用地址
func GetFrequentAddress(captureDetail []db.CaptureDetail) string {
    // 统计每个出行地址的出现次数
    pointDate := ""
    pointAddress := make(map[string]int, 0)
    dateAddress := make(map[string]string, 0)
    floor1Address := ""
    captureDays := make(map[string]int, 0)
    var frequentAddress string
    re, _ := regexp.Compile(`\b1F\b`)
    for index, detail := range captureDetail {
        //fmt.Println("抓拍地址:", detail.CaptureAddress)
        //fmt.Println("抓拍日期:", detail.CaptureDate)
        dateStr := strings.Split(detail.CaptureDate, " ")[0]
        captureDays[dateStr]++
        matchFlag := re.MatchString(detail.CaptureAddress)
        if matchFlag {
            floor1Address = detail.CaptureAddress
        }
        //判断日期标是否满足条件
        if pointDate == "" {
            pointDate = dateStr
            pointAddress[detail.CaptureAddress]++
            //若为最后一条则计算常用地址
            if index == len(captureDetail)-1 {
                //fmt.Println("处理前pointAddress表:", pointAddress)
                dateAddress[pointDate] = detail.CaptureAddress
            }
            continue
        }
        //若日期标相等则为同一天,地址标数组楼层计数+1
        if pointDate == dateStr {
            pointAddress[detail.CaptureAddress]++
            if index == len(captureDetail)-1 {
                //fmt.Println("处理前pointAddress表:", pointAddress)
                dateAddress[pointDate] = getfrAddress(pointAddress)
            }
            //不相等则为新的日期,首先计算出当日的常用地址,然后重新初始化日期标和地址标数组
        } else {
            if index == len(captureDetail)-1 {
                pointAddress[detail.CaptureAddress]++
                //fmt.Println("处理前pointAddress表:", pointAddress)
                dateAddress[pointDate] = getfrAddress(pointAddress)
                continue
            }
            dateAddress[pointDate] = getfrAddress(pointAddress)
            pointDate = dateStr
            pointAddress = make(map[string]int, 0)
        }
    }
    //fmt.Println("抓拍地址待处理结构表:", dateAddress)
    //fmt.Println("dareAddress len: ", len(dateAddress))
    if float64(len(dateAddress))/float64(len(captureDays))*100 >= 50 {
        addressCount := make(map[string]int)
        for _, address := range dateAddress {
            addressCount[address]++
        }
        frequentAddress = getfrAddress(addressCount)
    } else {
        frequentAddress = floor1Address
    }
    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 {
    filteredInfos := make([]db.PersonStatus, 0)
 
    // 构建快速查找索引,方便查找对应的人员状态和规则
    statusIndex := make(map[string]db.PersonStatus)
    ruleIndex := make(map[string]db.PersonnelStatusRule)
 
    for _, person := range personStatus {
        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 := 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
        //}
        // 更新过滤后的信息列表
        //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
}