添加布控模块,合并person_status和snapshot_count_summary数据库等
New file |
| | |
| | | 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 |
| | | } |
New file |
| | |
| | | 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 |
| | | } |
| | |
| | | level: -1 |
| | | maxSize: 128 |
| | | maxBackups: 30 |
| | | maxAge: 15 |
| | | maxAge: 15 |
| | | api: |
| | | host: 192.168.20.115 |
| | | port: 4101 |
| | |
| | | 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 |
| | | |
| | |
| | | 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") != "" { |
| | |
| | | ) |
| | | |
| | | // 计算抓拍天数 |
| | | 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) |
| | |
| | | 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++ |
| | | } |
| | | |
| | | return captureDays |
| | | return captureDays, overnightCount |
| | | } |
| | | |
| | | // 设置状态 |
| | |
| | | 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 |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // 更新过滤后的信息列表 |
| | | 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}) |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | // 查询小区表 |
| | | 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 { |
| | |
| | | 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 |
| | |
| | | |
| | | // 查询住户时间数据 |
| | | 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 |
| | |
| | | // 遍历查询结果 |
| | | 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 { |
| | |
| | | |
| | | // 查询人物属性 |
| | | 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"). |
| | |
| | | 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 docNum, nil |
| | | return age, 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"). |
| | |
| | | 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 { |
| | | |
| | |
| | | |
| | | // 如果记录存在,则更新 |
| | | 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). |
| | |
| | | } |
| | | } else { |
| | | // 如果记录不存在,则插入新记录 |
| | | err := db.Create(&personsMoveInout).Error |
| | | //fmt.Println("插入记录失败") |
| | | //fmt.Println("data", &personMoveInout) |
| | | err := db.Create(&personMoveInout).Error |
| | | if err != nil { |
| | | return err |
| | | } |
| | |
| | | |
| | | // UpdatePersonInfo 更新或插入多个人员身份信息 |
| | | func UpdateDBPersonLabel(personsIdentity []Identity) error { |
| | | // 数据库连接信息 |
| | | db, err := ConnectDB() |
| | | if err != nil { |
| | | return err |
| | | } |
| | | var db = DB |
| | | // 遍历人员信息 |
| | | for _, personIdentity := range personsIdentity { |
| | | |
| | |
| | | |
| | | // 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") |
| | |
| | | // 如果记录存在,则更新 |
| | | 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, |
| | | "status": person.Status, |
| | | "frequent_address": person.FrequentAddress, |
| | | }).Error |
| | | if err != nil { |
| | | return err |
| | |
| | | ) |
| | | |
| | | 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 |
| | |
| | | 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 |
| | | ) |
| | |
| | | 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" |
| | |
| | | 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() { |
| | |
| | | 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 { |
| | |
| | | |
| | | import ( |
| | | "basic.com/valib/logger.git" |
| | | "errors" |
| | | "fmt" |
| | | "math" |
| | | "ruleModelEngine/db" |
| | |
| | | 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, |
| | |
| | | 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 { |
| | |
| | | identity = append(identity, db.Identity{ |
| | | CommunityID: communityID, |
| | | DocumentNumber: info.DocumentNumber, |
| | | LabelId: 3, |
| | | LabelId: labelId, |
| | | ExpireTime: GetCurrentDateAddDaysTimestamp(validDays)}) |
| | | continue |
| | | } |
| | |
| | | fmt.Println(addrData) |
| | | } |
| | | |
| | | func CreateProcessModel(personInfos []db.CaptureInfo, days int) { |
| | | timeTOIndex := getIndexForTime(24 * 60) |
| | | dateTOIndex := getIndexForDate(days) |
| | | //fmt.Println(dateTOIndex) |
| | | inModelMatrix := make([][]int, days) |
| | | for i := range inModelMatrix { |
| | | inModelMatrix[i] = make([]int, 24*60) |
| | | 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 |
| | | } |
| | | outModelMatrix := make([][]int, days) |
| | | for i := range outModelMatrix { |
| | | outModelMatrix[i] = make([]int, 24*60) |
| | | } |
| | | identity := make([]db.Identity, 0) |
| | | for _, info := range personInfos { |
| | | timeTOIndex := getIndexForTime(24 * 60) |
| | | dateTOIndex := getIndexForDate(days) |
| | | //fmt.Println(dateTOIndex) |
| | | inModelMatrix := make([][]int, days) |
| | | for i := range inModelMatrix { |
| | | inModelMatrix[i] = make([]int, 24*60) |
| | | } |
| | | outModelMatrix := make([][]int, days) |
| | | for i := range outModelMatrix { |
| | | outModelMatrix[i] = make([]int, 24*60) |
| | | } |
| | | //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 |
| | |
| | | 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("上班族", 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) |
| | | } |
| | | fmt.Println(outModelMatrix) |
| | | fmt.Println(inModelMatrix) |
| | | return identity |
| | | } |
| | | |
| | | // 计算一阶导数 |
New file |
| | |
| | | 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 |
| | | } |
| | |
| | | "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) |
| | | //// 检查规则表书否存在异常 |
| | | //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 |
| | | // } |
| | | // } |
| | | // fmt.Println() |
| | | // } |
| | | // return true |
| | | //} |
| | | |
| | | // 计算常用地址 |
| | | //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 |
| | | // } |
| | | // } |
| | | // } |
| | | // personnelInfo[i].FrequentAddress = maxAddress |
| | | // } |
| | | // 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) |
| | |
| | | if err != nil { |
| | | logger.Error("GetCommunityIDs Error", err) |
| | | } |
| | | labeManage, err := db.GetLabelManageIdentity(2) |
| | | if err != nil { |
| | | logger.Error("GetDBPersonStatusData Error", err) |
| | | } |
| | | //fmt.Println(labeManage) |
| | | for _, communityID := range communityIDs { |
| | | //万全社区 |
| | | //if communityID != "50010101010000001001" { |
| | | // continue |
| | | //} |
| | | //查询社区内人员档案,方便数据更新 |
| | | personStatus, err := db.GetDBPersonStatusData(communityID) |
| | | if err != nil { |
| | | logger.Error("GetDBPersonStatusData Error", err) |
| | | } |
| | | labeManage, err := db.GetLabelManageIdentity(2) |
| | | if err != nil { |
| | | logger.Error("GetDBPersonStatusData Error", err) |
| | | } |
| | |
| | | //按社区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 |
| | | //fmt.Println("该人员出现天数为", captureInfos[i].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) |
| | | 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) |
| | | } |
| | |
| | | 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) |
| | |
| | | |
| | | } |
| | | } |
| | | //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) |
| | |
| | | } |
| | | |
| | | 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) |
| | |
| | | logger.Error("UpdateMoveInoutErr Error: ", UpdateMoveInoutErr) |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | 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 |
| | | } |
New file |
| | |
| | | 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 |
| | | |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | 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) |
| | | } |