zhaoqingang
2025-02-11 699dbde008569e88d7d53da196656b07be1755eb
Merge branch 'dev' of http://192.168.5.5:10010/r/CloudAI/model-engine into dev
7个文件已修改
148 ■■■■ 已修改文件
.gitignore 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/db.go 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/model_rule.go 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/accessRegularity.go 121 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/locationAnalysis.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/model.go 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/esSearch.go 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -2,6 +2,6 @@
go.sum
.so
logs
model-engine
model-engine*
vendor
*.lock
db/db.go
@@ -351,8 +351,9 @@
                Unit:     "",
                Range:    "",
                Value:    "",
                ValType:  "[{\"label\":\"进\", \"value\":\"in\"},{\"label\":\"出\", \"value\":\"out\"}]",
                ValType:  "string",
                Operator: "==",
                Options:  "[{\"label\":\"进\", \"value\":\"in\"},{\"label\":\"出\", \"value\":\"out\"}]",
                Sort:     3,
            },
        },
db/model_rule.go
@@ -17,19 +17,20 @@
    RuleArg struct {
        Alias    string `gorm:"column:alias" json:"alias"`         // 参数的别名
        Name     string `gorm:"column:name" json:"name"`           // 参数名称
        Type     string `gorm:"column:type" json:"type"`           // 参数类型: input, option, range, image
        Type     string `gorm:"column:type" json:"type"`           // 参数类型: input, select, range, image
        Must     bool   `gorm:"column:must" json:"must"`           // 是否必填
        Unit     string `gorm:"column:unit" json:"unit"`           // 单位
        Range    string `gorm:"column:range" json:"range"`         // 值的范围,eg:0,100表示从0到100
        Value    string `gorm:"column:value" json:"value"`         // 参数值
        ValType  string `gorm:"column:val_type" json:"valType"`    // 参数值类型 int, string, bool
        Operator string `gorm:"column:operator" json:"operator"`   // 运算符
        Options  string `gorm:"column:options" json:"options"`     // 选项的备选参数
        Sort     int    `gorm:"column:sort;default:0" json:"sort"` // 参数顺序
    }
    ModelRuleSet struct {
        Alias    string      `json:"alias"`    // 参数的别名
        Type     string      `json:"type"`     // 参数类型: input, option, range, image
        Type     string      `json:"type"`     // 参数类型: input, select, range, image
        Name     string      `json:"name"`     // 参数名称
        Value    interface{} `json:"value"`    // 参数值
        ValType  string      `json:"valType"`  // 值类型
models/accessRegularity.go
@@ -94,7 +94,7 @@
        return fmt.Errorf("task id:%s, %s timeRange Time range setting error. %+v", task.ID, task.Name, task.Rules)
    }
    logger.Debugf("LocationModel init finish ...task id:%s, name:%s, rule:%+v", task.ID, task.Name, m)
    logger.Debugf("AccessRegularity init finish ...task id:%s, name:%s, rule:%+v", task.ID, task.Name, m)
    return nil
}
@@ -106,55 +106,61 @@
    // 查找指定时间范围内出行过的档案编号
    now := time.Now()
    startDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).AddDate(0, 0, -m.Duration)
    endDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
    err := db.GetDB().Raw(`
        SELECT
            document_number,
            frequent_address,
            community_id,
            org_id
        FROM
            snapshot_count_summary
        WHERE
            last_appearance_time > ? ""
            AND (p.community_id IN ?
            OR p.org_id IN ?)
            AND p.status IN ?
            last_appearance_time > ?
            AND (community_id IN ?
            OR org_id IN ?)
            AND status IN ?
        `, startDate.Unix(), m.AreaIds, m.OrgIds, m.IdentityType).Scan(&baseFilter).Error
    if err != nil {
        logger.Warnf(err.Error())
    }
    logger.Debugf("task %s base filter result %d", m.Task.Name, len(baseFilter))
    esCli := db.GetEsClient()
    // 调用es分析此人的出行规律是否符合条件, 返回符合条件的次数和最后一次符合条件的时间
    sTime := startDate.Format(time.DateTime)
    eTime := endDate.Format(time.DateTime)
    for _, p := range baseFilter {
        // 调用es分析此人的出行规律是否符合条件, 返回符合条件的次数和最后一次符合条件的时间
        sTime := startDate.Format(time.DateTime)
        eTime := time.Now().Format(time.DateTime)
        captures, err := service.QueryEsRecord(esCli, sTime, eTime, nil, []interface{}{p.CommunityId}, []string{p.DocumentNumber})
        //logger.Debugf("task %s person %s captures %d", m.Task.Name, p.DocumentNumber, len(captures))
        if len(captures) == 0 || err != nil {
            continue
        }
        //logger.Debugf("task %s person %s captures %+v", m.Task.Name, p.DocumentNumber, captures[0])
        // 根据抓拍时间和出入方向,计算符合规则内的出入次数
        hitCount := 0
        hitCount, pd := countValidDays(captures, m.StartHour, m.EndHour, m.LastDirection)
        //for _, c := range captures {
        //    captureTime, err := time.ParseInLocation(time.DateTime, c.PicDate, time.Local)
        //}
        if hitCount > m.Appearances {
            // 写数据库
            result := &db.ModelTaskResults{
                Title:         m.Task.Name,
                Event:         fmt.Sprintf("%s - %s 时间段内, %s %d次", sTime, eTime, m.Task.Name, hitCount),
                ModelID:       m.Task.ModelID,
                ModelTaskID:   m.Task.ID,
                CommunityId:   p.CommunityId,
                OrgID:         p.OrgId,
                ObjectIds:     p.DocumentNumber,
                Location:      p.FrequentAddress,
                PicDate:       pd,
                FirstPersonID: p.DocumentNumber,
            }
        // 写数据库
        result := &db.ModelTaskResults{
            Title:         m.Task.Name,
            Event:         fmt.Sprintf("%s %d次", m.Task.Name, hitCount),
            ModelID:       m.Task.ModelID,
            ModelTaskID:   m.Task.ID,
            CommunityId:   p.CommunityId,
            OrgID:         p.OrgId,
            ObjectIds:     p.DocumentNumber,
            Location:      p.FrequentAddress,
            PicDate:       time.Unix(p.LastAppearanceTime, 0).Format(time.DateTime),
            FirstPersonID: p.DocumentNumber,
            results = append(results, result)
        }
        results = append(results, result)
    }
    logger.Debugf("task %s last filter result %d", m.Task.Name, len(results))
@@ -168,10 +174,71 @@
func (m *RegularityModel) Shutdown() error {
    // 清理资源
    fmt.Println("Shutting down LocationModel Model")
    fmt.Println("Shutting down accessRegularityS Model")
    return nil
}
func (m *RegularityModel) eventFormat() string {
    return ""
}
func countValidDays(records []*service.ESRecordInfo, startHour, endHour int, direction string) (int, string) {
    layout := "2006-01-02 15:04:05"             // 时间格式
    lastDirectionMap := make(map[string]string) // 记录最后一条 Direction
    lastTimeMap := make(map[string]time.Time)   // 记录最后一条时间
    lastPicDate := ""
    // 判断是否跨天
    var isCrossDay bool
    if endHour < startHour {
        isCrossDay = true
    }
    for _, record := range records {
        // 解析时间
        t, err := time.ParseInLocation(layout, record.PicDate, time.Local)
        if err != nil {
            fmt.Println("解析时间失败:", err)
            continue
        }
        // 获取小时
        hour := t.Hour()
        var key string
        if !isCrossDay {
            // 判断时间范围,并归属到某一天
            if hour >= startHour && hour <= endHour {
                key = t.Format("2006-01-02")
            } else {
                continue // 不在统计范围内
            }
        } else {
            // 判断时间范围,并归属到某一天
            if hour >= startHour { // 21:00-23:59 归属当天
                key = t.Format("2006-01-02")
            } else if hour <= endHour { // 00:00-02:59 归属前一天
                key = t.AddDate(0, 0, -1).Format("2006-01-02")
            } else {
                continue // 不在统计范围内
            }
        }
        // 记录该时间段内的最后一条数据
        if lastTime, exists := lastTimeMap[key]; !exists || t.After(lastTime) {
            lastTimeMap[key] = t
            lastDirectionMap[key] = record.CameraLocation.Direction
            lastPicDate = record.PicDate
        }
    }
    // 统计符合条件
    count := 0
    for _, dir := range lastDirectionMap {
        if dir == direction || direction == "" {
            count++
        }
    }
    return count, lastPicDate
}
models/locationAnalysis.go
@@ -230,7 +230,7 @@
    if err != nil {
        return err
    }
    logger.Debugf("records %s last result %s", m.Task.Name, records)
    logger.Debugf("records %s last result %+v", m.Task.Name, records)
    domains, err := domainToLocation(records)
    if err != nil {
        return err
models/model.go
@@ -14,10 +14,11 @@
}
var modelRegistry = map[string]func() Model{
    "gather":    func() Model { return &GatherModel{} },
    "disappear": func() Model { return &DisappearModel{} },
    "location":  func() Model { return &LocationModel{} },
    "night":     func() Model { return &nightModel{} },
    "gather":           func() Model { return &GatherModel{} },
    "disappear":        func() Model { return &DisappearModel{} },
    "location":         func() Model { return &LocationModel{} },
    "night":            func() Model { return &nightModel{} },
    "accessRegularity": func() Model { return &RegularityModel{} },
    // 添加其他模型
}
service/esSearch.go
@@ -89,9 +89,9 @@
                "filter": filters,
            },
        },
        "size":    0,
        "size":    10000000,
        "sort":    []interface{}{map[string]interface{}{"picDate": map[string]interface{}{"order": "asc"}}},
        "_source": map[string]interface{}{"includes": []interface{}{}, "excludes": []interface{}{"*.feature"}},
        "_source": map[string]interface{}{"includes": []interface{}{}, "excludes": []interface{}{"*.feature", "targetInfo"}},
    }
    if err := json.NewEncoder(&buf).Encode(query); err != nil {
@@ -148,7 +148,7 @@
            PicMaxUrl:      source["picMaxUrl"].(string),
        }
        cameraLocation := source["cameraId"].(map[string]interface{})
        cameraLocation := source["cameraLocation"].(map[string]interface{})
        record.CameraLocation = CameraLocation{
            Building:  cameraLocation["building"].(string),
            Unit:      cameraLocation["unit"].(string),