sunty
2024-05-24 de37adb6dec5e9da70f9cc11b234176ee6fda986
添加布控模块,合并person_status和snapshot_count_summary数据库等
6个文件已添加
8个文件已修改
724 ■■■■ 已修改文件
api/analysisApi/server.go 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cache/device.go 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/app.yaml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/config.go 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
data/prepare.go 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/repository.go 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
go.mod 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.go 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rule/engine.go 104 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rule/identityEngine.go 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rule/service.go 119 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
task/engine.go 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
task/service.go 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
task/tool.go 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/analysisApi/server.go
New file
@@ -0,0 +1,16 @@
package analysisApi
import (
    "basic.com/CloudAI/protomsg.git/analysis"
    "context"
    "ruleModelEngine/task"
)
type Server struct {
    analysis.UnimplementedAnalysisServiceServer
}
func (s *Server) GetCodeList(ctx context.Context, params *analysis.SendAnalysisRequest) (*analysis.EmptyResponse, error) {
    go task.TaskAnalysisService(params.DocumentNumber)
    return &analysis.EmptyResponse{}, nil
}
cache/device.go
New file
@@ -0,0 +1,22 @@
package cache
import (
    "basic.com/valib/logger.git"
    "ruleModelEngine/db"
)
var Device = make(map[string]db.Device)
func DeviceCacheInit() error {
    var err error
    var Devices []db.Device
    Devices, err = db.GetDeviceData()
    if err != nil {
        logger.Error("GetDeviceData", err)
        return err
    }
    for _, device := range Devices {
        Device[device.DeviceCode] = device
    }
    return nil
}
config/app.yaml
@@ -24,3 +24,6 @@
  maxSize: 128
  maxBackups: 30
  maxAge: 15
api:
  host: 192.168.20.115
  port: 4101
config/config.go
@@ -38,10 +38,16 @@
    LogLevel string `mapstructure: "logLevel"`
}
type api struct {
    Host string `mapstructure: "host"`
    Port string `mapstructure: "port"`
}
var LogConf = &LogConfig{}
var DataBase = &database{}
var Elastic = &elastic{}
var App = &app{}
var Api = &api{}
var LogBasePath string
var LogLevel int
@@ -57,6 +63,7 @@
    viper.UnmarshalKey("elastic", Elastic)
    viper.UnmarshalKey("database", DataBase)
    viper.UnmarshalKey("app", App)
    viper.UnmarshalKey("api", Api)
    viper.UnmarshalKey("log", LogConf)
    logger.SetLevel(LogConf.Level)
    if viper.GetString("LogBasePath") != "" {
data/prepare.go
@@ -7,10 +7,14 @@
)
// 计算抓拍天数
func CalculateCaptureDays(details []db.CaptureDetail) int {
func CalculateCaptureDays(details []db.CaptureDetail) (int, int) {
    // 使用 map 来存储每天是否有抓拍记录
    captureMap := make(map[string]bool)
    for _, detail := range details {
    //pointDate := ""
    //pointTime := ""
    //pointDirection := ""
    overnightCount := 0
    for i, detail := range details {
        // 解析抓拍日期
        layout := "2006-01-02 15:04:05"
        captureTime, err := time.Parse(layout, detail.CaptureDate)
@@ -18,10 +22,27 @@
            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++
            }
        }
    }
    // 统计有抓拍记录的天数
@@ -30,7 +51,7 @@
        captureDays++
    }
    return captureDays
    return captureDays, overnightCount
}
// 设置状态
@@ -103,7 +124,7 @@
        person, ok := statusIndex[info.DocumentNumber]
        if !ok {
            // 不存在对应的人员状态为新数据
            filteredInfos = append(filteredInfos, db.PersonStatus{CommunityID: communityID, DocumentNumber: info.DocumentNumber, Status: info.Status, FrequentAddress: info.FrequentAddress})
            filteredInfos = append(filteredInfos, db.PersonStatus{OrgId: info.OrgId, CommunityID: communityID, DocumentNumber: info.DocumentNumber, Status: info.Status, FrequentAddress: info.FrequentAddress})
            continue
        }
@@ -114,7 +135,7 @@
        }
        // 更新过滤后的信息列表
        filteredInfos = append(filteredInfos, db.PersonStatus{CommunityID: communityID, DocumentNumber: info.DocumentNumber, Status: info.Status, FrequentAddress: info.FrequentAddress})
        filteredInfos = append(filteredInfos, db.PersonStatus{OrgId: info.OrgId, CommunityID: communityID, DocumentNumber: info.DocumentNumber, Status: info.Status, FrequentAddress: info.FrequentAddress})
    }
db/repository.go
@@ -8,12 +8,8 @@
// 查询小区表
func GetCommunityIDs() ([]string, error) {
    db, err := ConnectDB()
    if err != nil {
        return nil, err
    }
    // 查询数据
    var db = DB
    var communityIDs []string
    result := db.Table("domain_unit").Where("domainType = ?", 1).Pluck("id", &communityIDs)
    if result.Error != nil {
@@ -23,13 +19,33 @@
    return communityIDs, nil
}
// 查询设备表
func GetDeviceData() ([]Device, error) {
    // 查询数据
    var db = DB
    var device []Device
    result := db.Table("device").Where("communityID != ?", "").Find(&device)
    if result.Error != nil {
        return nil, result.Error
    }
    return device, nil
}
// 查询全部数据
func GetAllData() ([]PersonnelStatusRule, error) {
    db, err := ConnectDB()
    if err != nil {
func GetAllTaskData() ([]Task, error) {
    var db = DB
    var task []Task
    if err := db.Find(&task).Error; err != nil {
        return nil, err
    }
    return task, nil
}
// 查询全部数据
func GetAllData() ([]PersonnelStatusRule, error) {
    var db = DB
    var rules []PersonnelStatusRule
    if err := db.Find(&rules).Error; err != nil {
        return nil, err
@@ -40,18 +56,14 @@
// 查询住户时间数据
func GetResidentData(status, communityID string) ([]Resident, error) {
    db, err := ConnectDB()
    if err != nil {
        return nil, err
    }
    var residents []Resident
    //var db = DB.Debug()
    var db = DB
    // 执行查询
    rows, err := db.Table("person_status").
        Select("person_status.documentNumber", "person_status.communityID", "snapshot_count_summary.last_appearance_time", "snapshot_count_summary.created_at").
        Joins("INNER JOIN snapshot_count_summary ON person_status.documentNumber = snapshot_count_summary.document_number AND person_status.communityID = snapshot_count_summary.community_id").
        Where("person_status.status = ? AND person_status.communityID = ?", status, communityID).
    rows, err := db.Table("snapshot_count_summary").
        Select("document_number", "community_id", "last_appearance_time", "created_at").
        Where("status = ? AND community_id = ?", status, communityID).
        //Where("snapshot_count_summary.created_at is not null").
        Rows()
    if err != nil {
        return nil, err
@@ -61,10 +73,12 @@
    // 遍历查询结果
    for rows.Next() {
        var resident Resident
        err := rows.Scan(&resident.DocumentNumber, &resident.CommunityID, &resident.LastAppearanceTime, &resident.CreateAt)
        err := rows.Scan(&resident.DocumentNumber, &resident.CommunityId, &resident.LastAppearanceTime, &resident.CreateAt)
        if err != nil {
            logger.Error("err: ", err)
            return nil, err
        }
        //fmt.Println("resident111: ", resident)
        residents = append(residents, resident)
    }
    if err := rows.Err(); err != nil {
@@ -76,11 +90,7 @@
// 查询人物属性
func GetDBPersonStatusData(id string) ([]PersonStatus, error) {
    db, err := ConnectDB()
    if err != nil {
        return nil, err
    }
    var db = DB
    // 查询数据
    var personStatusList []PersonStatus
    if err := db.Table("person_status").
@@ -93,37 +103,44 @@
    return personStatusList, nil
}
// 根据社区id和住户属性查询住户档案编号
func GetDocNumberFromPersonStatus(id, status string) ([]string, error) {
    db, err := ConnectDB()
    if err != nil {
        return nil, err
    }
// 查询人物年龄
func GetAgeById(id string) (int, error) {
    var db = DB
    // 查询数据
    var personStatusList []PersonStatus
    if err := db.Table("person_status").
        Select("documentNumber, status, frequentAddress").
        Where("communityID = ? AND status = ?", id, status).
        Find(&personStatusList).Error; err != nil {
        return nil, err
    var age int
    if err := db.Table("dbtablepersons").
        Select("age").
        Where("id = ?", id).
        Find(&age).Error; err != nil {
        return 0, err
    }
    docNum := make([]string, 0)
    for _, ps := range personStatusList {
        docNum = append(docNum, ps.DocumentNumber)
    return age, nil
    }
    return docNum, nil
}
//// 根据社区id和住户属性查询住户档案编号
//func GetDocNumberFromPersonStatus(id, status string) ([]string, error) {
//    var db = DB
//    // 查询数据
//    var personStatusList []PersonStatus
//    if err := db.Table("person_status").
//        Select("documentNumber, status, frequentAddress").
//        Where("communityID = ? AND status = ?", id, status).
//        Find(&personStatusList).Error; err != nil {
//        return nil, err
//    }
//
//    docNum := make([]string, 0)
//    for _, ps := range personStatusList {
//        docNum = append(docNum, ps.DocumentNumber)
//    }
//
//    return docNum, nil
//}
// 查询人物身份属性表
func GetLabelManageIdentity(IdentityType int) ([]LabelManage, error) {
    db, err := ConnectDB()
    if err != nil {
        return nil, err
    }
    var db = DB
    // 查询数据
    var labelManageIdentity []LabelManage
    if err := db.Table("label_manage").
@@ -136,13 +153,23 @@
    return labelManageIdentity, nil
}
// 根据dbtablepersons表id查询目标档案年龄
func QueryAgeById(id string) (int, error) {
    var db = DB
    var age int
    err := db.Table("dbtablepersons").
        Select("age").
        Where("id = ?", id).
        Scan(&age).Error
    if err != nil {
        return 0, err
    }
    return age, nil
}
// UpdatePersonInfo 更新或插入多个人员信息
func UpdateMoveInout(personsMoveInout []MoveInout) error {
    // 数据库连接信息
    db, err := ConnectDB()
    if err != nil {
        return err
    }
    var db = DB
    // 遍历人员信息
    for _, personMoveInout := range personsMoveInout {
@@ -158,6 +185,7 @@
        // 如果记录存在,则更新
        if existingPerson.DocumentNumber != "" {
            //fmt.Println("existingPerson.DocumentNumber: ", existingPerson.DocumentNumber)
            if existingPerson.Status != "Verified" {
                err := db.Model(&MoveInout{}).
                    Where("document_number = ? AND community_id = ?", personMoveInout.DocumentNumber, personMoveInout.CommunityID).
@@ -180,7 +208,9 @@
            }
        } else {
            // 如果记录不存在,则插入新记录
            err := db.Create(&personsMoveInout).Error
            //fmt.Println("插入记录失败")
            //fmt.Println("data", &personMoveInout)
            err := db.Create(&personMoveInout).Error
            if err != nil {
                return err
            }
@@ -193,11 +223,7 @@
// UpdatePersonInfo 更新或插入多个人员身份信息
func UpdateDBPersonLabel(personsIdentity []Identity) error {
    // 数据库连接信息
    db, err := ConnectDB()
    if err != nil {
        return err
    }
    var db = DB
    // 遍历人员信息
    for _, personIdentity := range personsIdentity {
@@ -247,17 +273,13 @@
// UpdatePersonInfo 更新或插入多个人员信息
func UpdatePersonInfo(persons []PersonStatus, communityID string) error {
    // 数据库连接信息
    db, err := ConnectDB()
    if err != nil {
        return err
    }
    var db = DB
    // 遍历人员信息
    for _, person := range persons {
        // 检查记录是否存在
        var existingPerson PersonStatus
        err := db.Where("documentNumber = ? AND communityID = ?", person.DocumentNumber, communityID).First(&existingPerson).Error
        err := db.Where("document_number = ? AND community_id = ?", person.DocumentNumber, communityID).First(&existingPerson).Error
        if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
            logger.Error("Query person error:", err, person.DocumentNumber, communityID)
            //fmt.Println("asdasfasfasf")
@@ -268,10 +290,10 @@
        // 如果记录存在,则更新
        if existingPerson.DocumentNumber != "" {
            err := db.Model(&PersonStatus{}).
                Where("documentNumber = ? AND communityID = ?", person.DocumentNumber, communityID).
                Where("document_number = ? AND community_id = ?", person.DocumentNumber, communityID).
                Updates(map[string]interface{}{
                    "status":          person.Status,
                    "frequentAddress": person.FrequentAddress,
                    "frequent_address": person.FrequentAddress,
                }).Error
            if err != nil {
                return err
go.mod
@@ -11,6 +11,7 @@
)
require (
    basic.com/CloudAI/protomsg.git v0.0.0-20240523091240-77f661e9c66f // indirect
    basic.com/pubsub/protomsg.git v0.0.0-20230210092337-5f1e6cdae7c3 // indirect
    filippo.io/edwards25519 v1.1.0 // indirect
    github.com/fsnotify/fsnotify v1.7.0 // indirect
@@ -39,8 +40,8 @@
    golang.org/x/sys v0.19.0 // indirect
    golang.org/x/text v0.14.0 // indirect
    google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
    google.golang.org/grpc v1.63.2 // indirect
    google.golang.org/protobuf v1.33.0 // indirect
    google.golang.org/grpc v1.64.0 // indirect
    google.golang.org/protobuf v1.34.1 // indirect
    gopkg.in/ini.v1 v1.67.0 // indirect
    gopkg.in/yaml.v3 v3.0.1 // indirect
)
main.go
@@ -1,7 +1,16 @@
package main
import (
    "basic.com/CloudAI/protomsg.git/analysis"
    "google.golang.org/grpc"
    "net"
    "ruleModelEngine/api/analysisApi"
    "ruleModelEngine/cache"
    "ruleModelEngine/config"
    "ruleModelEngine/db"
    //"ruleModelEngine/task"
    //"annotation_service/db"
    "basic.com/valib/logger.git"
    "flag"
@@ -16,7 +25,33 @@
    var logFile = config.LogConf.Path + "annotation_service.log"
    logger.InitLogger(logFile, config.LogConf.Level, config.LogConf.MaxSize, config.LogConf.MaxBackups, config.LogConf.MaxAge)
    logger.Info("loginit success !")
    dbErr := db.ConnectDB()
    if dbErr != nil {
        logger.Error("数据库连接失败", dbErr)
        return
    }
    logger.Info("ConnectDB success !")
    cacheErr := cache.DeviceCacheInit()
    if cacheErr != nil {
        logger.Error("设备表缓存失败", cacheErr)
        return
    }
    logger.Info("cache device success !")
}
func initApiServer() {
    ln, err := net.Listen("tcp", config.Api.Host+":"+config.Api.Port)
    if err != nil {
        logger.Fatal("grpc server init error: %v", err.Error())
        //panic(fmt.Sprintf("grpc server init error: %v", err.Error()))
    }
    s := grpc.NewServer()
    analysis.RegisterAnalysisServiceServer(s, &analysisApi.Server{})
    err = s.Serve(ln)
    if err != nil {
        logger.Fatal("grpc server init error: %v", err.Error())
        //panic(fmt.Sprintf("grpc server init error: %v", err.Error()))
    }
}
func main() {
@@ -28,11 +63,12 @@
        logger.Info("Executing immediately...")
        rule.ExecuteTask()
    }
    //task.TaskAnalysisService("3407b20e-6343-4832-88fa-a8e986552532")
    //go initApiServer()
    //return
    now := time.Now()
    next := time.Date(now.Year(), now.Month(), now.Day()+1, 1, 0, 0, 0, now.Location())
    duration := next.Sub(now)
    timer := time.NewTimer(duration)
    logger.Info("The program has started and will execute at one o'clock in the early morning every night.")
    for {
rule/engine.go
@@ -2,7 +2,6 @@
import (
    "basic.com/valib/logger.git"
    "errors"
    "fmt"
    "math"
    "ruleModelEngine/db"
@@ -56,11 +55,13 @@
                status = "Confirmed"
            }
        }
        if status == "" {
            continue
        }
        //fmt.Println("status: ", status)
        moveInout = append(moveInout, db.MoveInout{
            DocumentNumber: resident.DocumentNumber,
            CommunityID:    resident.CommunityID,
            CommunityID:    resident.CommunityId,
            MoveInDate:     createdAt,           // 存储年月日
            MoveOutDate:    &lastAppearanceDate, // 存储年月日
            MoveType:       moveType,
@@ -71,18 +72,18 @@
    return moveInout
}
func ProcessRuleEngine(personInfos []db.CaptureInfo, ruleInfo []db.PersonnelStatusRule, cmmunityID string) (bool, error) {
    ruleInfoCheck := checkRuleValidity(ruleInfo)
    if ruleInfoCheck == false {
        logger.Error("规则库数据异常")
        return false, errors.New("规则库数据异常")
    }
    fmt.Println("清洗前: ", len(personInfos))
    logger.Info("规则算法执行完毕!!!")
    return true, nil
}
//func ProcessRuleEngine(personInfos []db.CaptureInfo, ruleInfo []db.PersonnelStatusRule, cmmunityID string) (bool, error) {
//    ruleInfoCheck := checkRuleValidity(ruleInfo)
//    if ruleInfoCheck == false {
//        logger.Error("规则库数据异常")
//        return false, errors.New("规则库数据异常")
//    }
//    fmt.Println("清洗前: ", len(personInfos))
//    logger.Info("规则算法执行完毕!!!")
//    return true, nil
//}
func CreateLinearModel(personInfos []db.CaptureInfo, communityID string, threshold float64, validDays int) ([]db.Identity, []db.CaptureInfo) {
func CreateLinearModel(personInfos []db.CaptureInfo, communityID string, threshold float64, validDays int, labelId int) ([]db.Identity, []db.CaptureInfo) {
    identity := make([]db.Identity, 0)
    captureInfo := make([]db.CaptureInfo, 0)
    for _, info := range personInfos {
@@ -116,7 +117,7 @@
                identity = append(identity, db.Identity{
                    CommunityID:    communityID,
                    DocumentNumber: info.DocumentNumber,
                    LabelId:        3,
                    LabelId:        labelId,
                    ExpireTime:     GetCurrentDateAddDaysTimestamp(validDays)})
                continue
            }
@@ -149,7 +150,13 @@
    fmt.Println(addrData)
}
func CreateProcessModel(personInfos []db.CaptureInfo, days int) {
func CreateProcessModel(personInfos []db.CaptureInfo, days int, communityID string, labelManage []db.LabelManage) []db.Identity {
    labelIndexMap := make(map[string]int)
    for index, labelManageInfo := range labelManage {
        labelIndexMap[labelManageInfo.Name] = index
    }
    identity := make([]db.Identity, 0)
    for _, info := range personInfos {
    timeTOIndex := getIndexForTime(24 * 60)
    dateTOIndex := getIndexForDate(days)
    //fmt.Println(dateTOIndex)
@@ -161,14 +168,14 @@
    for i := range outModelMatrix {
        outModelMatrix[i] = make([]int, 24*60)
    }
    for _, info := range personInfos {
        //fmt.Println("info: ", info)
        for _, captureInfo := range info.CaptureDetail {
            captrueDateTime := captureInfo.CaptureDate
            dateTimeObj, err := time.Parse("2006-01-02 15:04:05", captrueDateTime)
            if err != nil {
                logger.Error("Parse time error", err)
                return
                continue
                //return n/**/il, err
            }
            if isWeekend(dateTimeObj) {
                continue
@@ -184,9 +191,66 @@
                continue
            }
        }
        countMaxRows, colS, colE := CountMaxRows(outModelMatrix, 30, 30)
        logger.Info("规律出勤时间段:", colS, colE, "\t次数: ", countMaxRows)
        if countMaxRows >= 10 {
            if info.Age <= 22 && info.Age >= 7 {
                lIndex := labelIndexMap["学生"]
                identity = append(identity, db.Identity{
                    CommunityID:    communityID,
                    DocumentNumber: info.DocumentNumber,
                    LabelId:        labelManage[lIndex].Id,
                    ExpireTime:     GetCurrentDateAddDaysTimestamp(labelManage[lIndex].ValidDays)})
            } else if info.Age >= 23 && info.Age <= 60 {
                lIndex := labelIndexMap["上班族"]
                identity = append(identity, db.Identity{
                    CommunityID:    communityID,
                    DocumentNumber: info.DocumentNumber,
                    LabelId:        labelManage[lIndex].Id,
                    ExpireTime:     GetCurrentDateAddDaysTimestamp(labelManage[lIndex].ValidDays)})
            } else if info.Age > 60 {
                lIndex := labelIndexMap["离退休人员"]
                identity = append(identity, db.Identity{
                    CommunityID:    communityID,
                    DocumentNumber: info.DocumentNumber,
                    LabelId:        labelManage[lIndex].Id,
                    ExpireTime:     GetCurrentDateAddDaysTimestamp(labelManage[lIndex].ValidDays)})
    }
    fmt.Println(outModelMatrix)
    fmt.Println(inModelMatrix)
            //fmt.Println("上班族", info.DocumentNumber, info.Age, countMaxRows, colS, colE)
        } else {
            countMaxRows, colS, colE := CountMaxRows(inModelMatrix, 30, 30)
            logger.Info("规律出勤时间段:", colS, colE, "\t次数: ", countMaxRows)
            if countMaxRows >= 10 {
                if info.Age <= 22 && info.Age >= 7 {
                    lIndex := labelIndexMap["学生"]
                    identity = append(identity, db.Identity{
                        CommunityID:    communityID,
                        DocumentNumber: info.DocumentNumber,
                        LabelId:        labelManage[lIndex].Id,
                        ExpireTime:     GetCurrentDateAddDaysTimestamp(labelManage[lIndex].ValidDays)})
                } else if info.Age >= 23 && info.Age <= 60 {
                    lIndex := labelIndexMap["上班族"]
                    identity = append(identity, db.Identity{
                        CommunityID:    communityID,
                        DocumentNumber: info.DocumentNumber,
                        LabelId:        labelManage[lIndex].Id,
                        ExpireTime:     GetCurrentDateAddDaysTimestamp(labelManage[lIndex].ValidDays)})
                } else if info.Age > 60 {
                    lIndex := labelIndexMap["离退休人员"]
                    identity = append(identity, db.Identity{
                        CommunityID:    communityID,
                        DocumentNumber: info.DocumentNumber,
                        LabelId:        labelManage[lIndex].Id,
                        ExpireTime:     GetCurrentDateAddDaysTimestamp(labelManage[lIndex].ValidDays)})
                }
                //fmt.Println("上班族", info.DocumentNumber, info.Age, countMaxRows, colS, colE)
            }
        }
        //fmt.Println("outModelMatrix: ", outModelMatrix)
        //fmt.Println("inModelMatrix: ", inModelMatrix)
    }
    return identity
}
// 计算一阶导数
rule/identityEngine.go
New file
@@ -0,0 +1,80 @@
package rule
import (
    "math/rand"
    "time"
)
// 滑块组件-初始化并控制概率赋值1的二维数组
func initializeArrayWithProbability(rows, cols int, probability float64) [][]int {
    array := make([][]int, rows)
    rand.Seed(time.Now().UnixNano()) // 使用当前时间作为随机数种子
    for i := range array {
        array[i] = make([]int, cols)
        for j := range array[i] {
            // 生成0到99之间的随机数,如果小于等于概率*100,则赋值为1
            if rand.Intn(100) <= int(probability*100) {
                array[i][j] = 1
            }
        }
    }
    return array
}
// 滑块组件-统计滑动窗口内值为1的元素数量
func countOnesInWindow(window [][]int) int {
    count := 0
    for _, row := range window {
        for _, val := range row {
            if val == 1 {
                count++
                break // 一旦找到一个元素为1,跳出内层循环
            }
        }
    }
    return count
}
// 滑块组件-统计滑动窗口内至少有一个元素为1的行数
func countRowsWithOneInWindow(window [][]int) int {
    count := 0
    for _, row := range window {
        for _, val := range row {
            if val == 1 {
                count++
                break // 一旦找到一个元素为1,跳出内层循环
            }
        }
    }
    return count
}
// 滑块组件-统计最高行数以及滑块坐标
func CountMaxRows(modelMatrix [][]int, windowRows, windowCols int) (int, int, int) {
    maxRowCountWindowCols := 0
    maxRowCount := 0
    // 统计滑动窗口内值为1的元素数量和至少有一个元素为1的行数
    for i := 0; i <= 1440-windowCols; i++ {
        window := make([][]int, windowRows)
        for j := range window {
            window[j] = modelMatrix[j][i : i+windowCols]
        }
        //onesCount := countOnesInWindow(window)
        rowsWithOneCount := countRowsWithOneInWindow(window)
        if rowsWithOneCount == 0 {
            continue
        }
        if rowsWithOneCount > maxRowCount {
            maxRowCount = rowsWithOneCount
            maxRowCountWindowCols = i
        }
        //fmt.Printf("从第 %d 列到第 %d 列,值为1的元素数量为:%d,至少有一个元素为1的行数为:%d\n", i, i+windowCols-1, onesCount, rowsWithOneCount)
    }
    //fmt.Println("documentNumber: ", info.DocumentNumber)
    //fmt.Println("maxRowCount: ", maxRowCount)
    //fmt.Println("maxRowCountWindowCols: ", maxRowCountWindowCols, maxRowCountWindowCols+windowCols-1)
    return maxRowCount, maxRowCountWindowCols, maxRowCountWindowCols + windowCols - 1
}
rule/service.go
@@ -7,67 +7,28 @@
    "ruleModelEngine/db"
)
//func PrintFilteredPersonnelInfo(filteredPersonnelInfo []db.PersonnelInfo) {
//    for _, pi := range filteredPersonnelInfo {
//        fmt.Printf("DocumentNumber: %s\n", pi.DocumentNumber)
//        fmt.Printf("TotalCaptureCount: %d\n", pi.TotalCaptureCount)
//        fmt.Printf("TotalCaptureDays: %d\n", pi.TotalCaptureDays)
//        fmt.Printf("PersonnelStatus: %s\n", pi.PersonnelStatus)
//
//        fmt.Println("CaptureDetails:")
//        for _, cd := range pi.CaptureDetails {
//            fmt.Printf("  Date: %s\n", cd.Date)
//            fmt.Printf("  TotalCaptureCount: %d\n", cd.TotalCaptureCount)
//            fmt.Println("  Captures:")
//            for _, c := range cd.Captures {
//                fmt.Printf("    DataTime: %s\n", c.DataTime)
//                fmt.Printf("    Location: %s\n", c.Location)
//            }
//        }
//        fmt.Println()
//    }
//}
// 计算常用地址
//func assignFrequentAddress(personnelInfo []db.PersonnelInfo) []db.PersonnelInfo {
//    for i := range personnelInfo {
//        addressCounts := make(map[string]int)
//        var maxAddress string
//        maxCount := 0
//        for _, detail := range personnelInfo[i].CaptureDetails {
//            for _, capture := range detail.Captures {
//                addressCounts[capture.Location]++
//                if addressCounts[capture.Location] > maxCount {
//                    maxCount = addressCounts[capture.Location]
//                    maxAddress = capture.Location
//// 检查规则表书否存在异常
//func checkRuleValidity(rules []db.PersonnelStatusRule) bool {
//    for i := 0; i < len(rules); i++ {
//        for j := i + 1; j < len(rules); j++ {
//            ruleI := rules[i]
//            ruleJ := rules[j]
//            //fmt.Println(ruleI.DetectionDaysStart,ruleI.DetectionDaysEnd)
//            //fmt.Println(ruleJ.DetectionDaysStart,ruleJ.DetectionDaysEnd)
//            if (ruleI.DetectionDaysStart <= ruleJ.DetectionDaysEnd && ruleI.DetectionDaysStart >= ruleJ.DetectionDaysStart) ||
//                (ruleI.DetectionDaysEnd <= ruleJ.DetectionDaysEnd && ruleI.DetectionDaysEnd >= ruleJ.DetectionDaysStart) ||
//                (ruleI.DetectionDaysStart <= ruleJ.DetectionDaysStart && ruleI.DetectionDaysEnd >= ruleJ.DetectionDaysEnd) {
//                return false
//                }
//            }
//        }
//        personnelInfo[i].FrequentAddress = maxAddress
//    return true
//    }
//    return personnelInfo
//}
// 检查规则表书否存在异常
func checkRuleValidity(rules []db.PersonnelStatusRule) bool {
    for i := 0; i < len(rules); i++ {
        for j := i + 1; j < len(rules); j++ {
            ruleI := rules[i]
            ruleJ := rules[j]
            //fmt.Println(ruleI.DetectionDaysStart,ruleI.DetectionDaysEnd)
            //fmt.Println(ruleJ.DetectionDaysStart,ruleJ.DetectionDaysEnd)
            if (ruleI.DetectionDaysStart <= ruleJ.DetectionDaysEnd && ruleI.DetectionDaysStart >= ruleJ.DetectionDaysStart) ||
                (ruleI.DetectionDaysEnd <= ruleJ.DetectionDaysEnd && ruleI.DetectionDaysEnd >= ruleJ.DetectionDaysStart) ||
                (ruleI.DetectionDaysStart <= ruleJ.DetectionDaysStart && ruleI.DetectionDaysEnd >= ruleJ.DetectionDaysEnd) {
                return false
            }
        }
    }
    return true
}
// 执行程序入口
func ExecuteTask() {
    //return
    ruleInfo, err := db.GetAllData()
    if err != nil {
        logger.Error("GetAllData Error", err)
@@ -78,13 +39,18 @@
    if err != nil {
        logger.Error("GetCommunityIDs Error", err)
    }
    for _, communityID := range communityIDs {
        //查询社区内人员档案,方便数据更新
        personStatus, err := db.GetDBPersonStatusData(communityID)
    labeManage, err := db.GetLabelManageIdentity(2)
        if err != nil {
            logger.Error("GetDBPersonStatusData Error", err)
        }
        labeManage, err := db.GetLabelManageIdentity(2)
    //fmt.Println(labeManage)
    for _, communityID := range communityIDs {
        //万全社区
        //if communityID != "50010101010000001001" {
        //    continue
        //}
        //查询社区内人员档案,方便数据更新
        personStatus, err := db.GetDBPersonStatusData(communityID)
        if err != nil {
            logger.Error("GetDBPersonStatusData Error", err)
        }
@@ -94,13 +60,35 @@
        //按社区id查询近一个月es数据
        captureInfos, err := db.Query1MDataByCommunityId(communityID)
        //fmt.Println("captureInfos: ", captureInfos)
        //residentCount := 0
        for i := range captureInfos {
            captureDays := data.CalculateCaptureDays(captureInfos[i].CaptureDetail)
            //fmt.Println(captureInfos[i].DocumentNumber)
            captureDays, overnightCount := data.CalculateCaptureDays(captureInfos[i].CaptureDetail)
            captureInfos[i].CaptureDays = captureDays
            captureInfos[i].OvernightStays = overnightCount
            //if captureInfos[i].CaptureDays <= 10 && captureInfos[i].OvernightStays >= 1 {
            //    fmt.Println(captureInfos[i].DocumentNumber)
            //fmt.Println("该人员出现天数为", captureInfos[i].CaptureDays)
            //    fmt.Println("该人员过夜天数为", captureInfos[i].OvernightStays)
            //}
            captureInfos[i].Status = data.SetStatus(captureDays, ruleInfo)
            data.SetFrequentAddress(&captureInfos[i])
            if captureInfos[i].OvernightStays >= 5 && (captureInfos[i].CaptureDays <= 14 && captureInfos[i].CaptureDays >= 5) {
                captureInfos[i].Status = "resident"
        }
            //if captureInfos[i].Status == "resident" {
            //    residentCount++
            //}
            age, err := db.QueryAgeById(captureInfos[i].DocumentNumber)
            if err != nil {
                logger.Error("QueryAgeById ERROR", err)
            }
            captureInfos[i].Age = age
            data.SetFrequentAddress(&captureInfos[i])
            //fmt.Println("captureInfos[i].Age: ", captureInfos[i].Age)
        }
        //fmt.Println("residentCount: ", residentCount)
        if err != nil {
            logger.Error("MatchAllTargets Error", err)
        }
@@ -111,7 +99,7 @@
        for _, identity := range labeManage {
            switch identity.Name {
            case "服务人员":
                identity, attribute := CreateLinearModel(captureInfos, communityID, 2.68, identity.ValidDays)
                identity, attribute := CreateLinearModel(captureInfos, communityID, 2.68, identity.ValidDays, identity.Id)
                errIdentity := db.UpdateDBPersonLabel(identity)
                if errIdentity != nil {
                    logger.Error("UpdateDBPersonLabel Error", errIdentity)
@@ -120,7 +108,11 @@
            }
        }
        //CreateProcessModel(captureInfos, 30)
        identity := CreateProcessModel(captureInfos, 30, communityID, labeManage)
        errIdentity := db.UpdateDBPersonLabel(identity)
        if errIdentity != nil {
            logger.Error("UpdateDBPersonLabel Error", errIdentity)
        }
        //continue
        //fmt.Println("captureInfos: ", captureInfos)
        postCaptureInfos := data.ProcessData(captureInfos, personStatus, ruleInfo, communityID)
@@ -132,10 +124,14 @@
        }
        resident, DocNumberErr := db.GetResidentData("resident", communityID)
        //fmt.Println(resident)
        //return
        if DocNumberErr != nil {
            logger.Error("GetDocNumberFromPersonStatus Error: ", DocNumberErr)
        }
        //fmt.Println(resident)
        //fmt.Println("resident: ", resident)
        mio := processResidentStatus(resident)
        //fmt.Println("mip: ", mio)
        UpdateMoveInoutErr := db.UpdateMoveInout(mio)
@@ -143,5 +139,4 @@
            logger.Error("UpdateMoveInoutErr Error: ", UpdateMoveInoutErr)
        }
    }
}
task/engine.go
New file
@@ -0,0 +1,43 @@
package task
import (
    "basic.com/valib/logger.git"
    "ruleModelEngine/cache"
    "ruleModelEngine/db"
)
func UnderageClimbingToRooftop(taskPerson db.TaskPerson) bool {
    age, err := db.GetAgeById(taskPerson.DocumentNumber)
    if err != nil {
        logger.Error("GetAgeById: ", err)
        return false
    }
    floor, _ := extractFloorNumber(taskPerson.Floor)
    if age <= 16 && floor == cache.Device[taskPerson.CameraId].MaxBuildingFloor && taskPerson.TargetType == "body" {
        return true
    }
    return false
}
func UnderageEnteringCommercialBuilding(taskPerson db.TaskPerson) bool {
    age, err := db.GetAgeById(taskPerson.DocumentNumber)
    if err != nil {
        logger.Error("GetAgeById: ", err)
        return false
    }
    //floor, _ := extractFloorNumber(taskPerson.Floor)
    if age <= 16 && taskPerson.TargetType == "face" && cache.Device[taskPerson.CameraId].BuildingType == db.BuildingTypeMixedUse {
        return true
    }
    return false
}
func ClimbingFloorsIllegally(taskPerson db.TaskPerson) bool {
    return true
}
func EnteringButNotLeaving(taskPerson db.TaskPerson) bool {
    return true
}
func registeredAddressNotMatchActualResidence(taskPerson db.TaskPerson) bool {
    return true
}
task/service.go
New file
@@ -0,0 +1,72 @@
package task
import (
    "basic.com/valib/logger.git"
    "fmt"
    "ruleModelEngine/cache"
    "ruleModelEngine/db"
    "time"
)
type alarmRule struct {
    ruleId   int
    ruleText string
}
func TaskAnalysisService(id string) {
    alarmRules := make([]alarmRule, 0)
    time.Sleep(time.Second * 2)
    var taskPerson db.TaskPerson
    var err error
    for i := 0; i <= 2; i++ {
        taskPerson, err = db.QueryById(id)
        if err != nil {
            logger.Error("QueryById Error", err)
        }
        if taskPerson.Id != "" {
            break
        }
        time.Sleep(time.Second * 15)
    }
    fmt.Println("personInfo: ", taskPerson)
    fmt.Println("device: ", cache.Device)
    tasks, err := db.GetAllTaskData()
    if err != nil {
        logger.Error("GetAllTaskData Error", err)
    }
    fmt.Println(tasks)
    for _, task := range tasks {
        switch task.Name {
        case "未成年出顶楼":
            flag := UnderageClimbingToRooftop(taskPerson)
            if flag == true {
                alarmRules = append(alarmRules, alarmRule{ruleId: task.Id, ruleText: task.Name})
            }
        case "未成年入商住楼":
            flag := UnderageEnteringCommercialBuilding(taskPerson)
            if flag == true {
                alarmRules = append(alarmRules, alarmRule{ruleId: task.Id, ruleText: task.Name})
            }
        case "窜楼":
            flag := ClimbingFloorsIllegally(taskPerson)
            if flag == true {
                alarmRules = append(alarmRules, alarmRule{ruleId: task.Id, ruleText: task.Name})
            }
        case "只进不出":
            flag := EnteringButNotLeaving(taskPerson)
            if flag == true {
                alarmRules = append(alarmRules, alarmRule{ruleId: task.Id, ruleText: task.Name})
            }
        case "申住不一":
            flag := registeredAddressNotMatchActualResidence(taskPerson)
            if flag == true {
                alarmRules = append(alarmRules, alarmRule{ruleId: task.Id, ruleText: task.Name})
            }
        default:
            continue
        }
    }
}
task/tool.go
New file
@@ -0,0 +1,28 @@
package task
import (
    "fmt"
    "regexp"
    "strconv"
)
func extractFloorNumber(input string) (int, error) {
    // 定义匹配楼层数字的正则表达式
    re := regexp.MustCompile(`-?\d+`)
    // 查找第一个匹配的楼层数字
    matches := re.FindStringSubmatch(input)
    // 如果找到匹配的楼层数字
    if len(matches) > 0 {
        // 将匹配的楼层数字转换为整数
        floorNumber, err := strconv.Atoi(matches[0])
        if err != nil {
            return 0, err
        }
        return floorNumber, nil
    }
    // 如果未找到匹配的楼层数字,则返回错误
    return 0, fmt.Errorf("No floor number found in input: %s", input)
}