|
@@ -4,8 +4,6 @@ import (
|
|
"fmt"
|
|
"fmt"
|
|
"kpt-pasture/model"
|
|
"kpt-pasture/model"
|
|
"kpt-pasture/util"
|
|
"kpt-pasture/util"
|
|
- "math"
|
|
|
|
- "sort"
|
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
"gitee.com/xuyiping_admin/pkg/xerr"
|
|
"gitee.com/xuyiping_admin/pkg/xerr"
|
|
@@ -23,20 +21,51 @@ func (e *Entry) UpdatePenBehavior() error {
|
|
}
|
|
}
|
|
|
|
|
|
for _, pasture := range pastureList {
|
|
for _, pasture := range pastureList {
|
|
- e.PenBehavior(pasture.Id)
|
|
|
|
- e.UpdatePenBehaviorWeekData(pasture.Id)
|
|
|
|
|
|
+ conf, err := e.GetSystemNeckRingConfigure(pasture.Id, model.MaxPenBehavior)
|
|
|
|
+ if err != nil {
|
|
|
|
+ zaplog.Error("UpdatePenBehavior", zap.Any("pasture", pasture), zap.Any("err", err))
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ e.PenBehaviorEnter(pasture.Id, conf.Value)
|
|
}
|
|
}
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// PenBehaviorEnter 栏舍行为曲线 对数据进行查缺补漏
|
|
|
|
+func (e *Entry) PenBehaviorEnter(pastureId int64, maxValue int64) {
|
|
|
|
+ var minHeatDate string
|
|
|
|
+ if err := e.DB.Model(new(model.NeckRingOriginal)).
|
|
|
|
+ Select("min(active_date) as min_heat_date").
|
|
|
|
+ Where("pasture_id = ?", pastureId).
|
|
|
|
+ Where("id >= ?", maxValue).
|
|
|
|
+ Scan(&minHeatDate).Error; err != nil {
|
|
|
|
+ zaplog.Error("PenBehaviorEnter", zap.Any("pastureId", pastureId), zap.Any("err", err))
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ e.PenBehavior(pastureId, minHeatDate)
|
|
|
|
+ var maxId int64
|
|
|
|
+ if err := e.DB.Model(new(model.NeckRingOriginal)).
|
|
|
|
+ Select("MAX(id) as id").
|
|
|
|
+ Where("pasture_id = ?", pastureId).
|
|
|
|
+ Where("id >= ?", maxValue).
|
|
|
|
+ Where("active_date = ?", minHeatDate).
|
|
|
|
+ Scan(&maxId).Error; err != nil {
|
|
|
|
+ zaplog.Error("PenBehaviorEnter", zap.Any("pastureId", pastureId), zap.Any("err", err))
|
|
|
|
+ }
|
|
|
|
+ if maxId > maxValue {
|
|
|
|
+ if err := e.UpdateSystemNeckRingConfigure(pastureId, model.MaxPenBehavior, maxId); err != nil {
|
|
|
|
+ zaplog.Error("UpdateSystemNeckRingConfigure", zap.Any("err", err))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ e.UpdatePenBehaviorWeekData(pastureId, minHeatDate)
|
|
|
|
+}
|
|
|
|
+
|
|
// PenBehavior 栏舍行为曲线
|
|
// PenBehavior 栏舍行为曲线
|
|
-func (e *Entry) PenBehavior(pastureId int64) {
|
|
|
|
- heatDate := time.Now().Local().AddDate(0, 0, -1).Format(model.LayoutDate2)
|
|
|
|
|
|
+func (e *Entry) PenBehavior(pastureId int64, heatDate string) {
|
|
frameIds := util.FrameIdSlice
|
|
frameIds := util.FrameIdSlice
|
|
-
|
|
|
|
penBehaviorList := make([]*model.PenBehaviorData, 0)
|
|
penBehaviorList := make([]*model.PenBehaviorData, 0)
|
|
for _, frameId := range frameIds {
|
|
for _, frameId := range frameIds {
|
|
- // 1. 获取颈环原始数据
|
|
|
|
penBehaviorModel, err := e.getNeckRingOriginalList(pastureId, heatDate, frameId)
|
|
penBehaviorModel, err := e.getNeckRingOriginalList(pastureId, heatDate, frameId)
|
|
if err != nil {
|
|
if err != nil {
|
|
zaplog.Error("PenBehavior",
|
|
zaplog.Error("PenBehavior",
|
|
@@ -138,150 +167,43 @@ func (e *Entry) savePenBehaviorData(penDataList []*model.PenBehaviorData) error
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (e *Entry) UpdatePenBehaviorWeekData(pastureId int64) {
|
|
|
|
- penBehaviorList := e.findWeekPenBehaviorList(pastureId)
|
|
|
|
|
|
+func (e *Entry) UpdatePenBehaviorWeekData(pastureId int64, dateTime string) {
|
|
|
|
+ dateTime1, _ := util.TimeParseLocal(model.LayoutDate2, dateTime)
|
|
|
|
+ startTime := dateTime1.AddDate(0, 0, -7).Format(model.LayoutDate2)
|
|
|
|
+ endTime := dateTime1.AddDate(0, 0, -1).Format(model.LayoutDate2)
|
|
|
|
+ penBehaviorList, err := e.findWeekPenBehaviorList(pastureId, dateTime, startTime, endTime)
|
|
|
|
+ if err != nil {
|
|
|
|
+ zaplog.Error("UpdatePenBehaviorWeekData",
|
|
|
|
+ zap.Any("err", err),
|
|
|
|
+ zap.Any("pastureId", pastureId),
|
|
|
|
+ zap.Any("dateTime", dateTime),
|
|
|
|
+ zap.Any("startTime", startTime),
|
|
|
|
+ zap.Any("endTime", endTime),
|
|
|
|
+ )
|
|
|
|
+ return
|
|
|
|
+ }
|
|
if len(penBehaviorList) == 0 {
|
|
if len(penBehaviorList) == 0 {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
- // 按日期和frameid排序
|
|
|
|
- sort.Slice(penBehaviorList, func(i, j int) bool {
|
|
|
|
- if penBehaviorList[i].HeatDate == penBehaviorList[j].HeatDate {
|
|
|
|
- return penBehaviorList[i].Frameid < penBehaviorList[j].Frameid
|
|
|
|
- }
|
|
|
|
- return penBehaviorList[i].HeatDate < penBehaviorList[j].HeatDate
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
// 处理每个日期和frameid的数据
|
|
// 处理每个日期和frameid的数据
|
|
for _, item := range penBehaviorList {
|
|
for _, item := range penBehaviorList {
|
|
- currDate := item.HeatDate
|
|
|
|
- currFrameid := item.Frameid
|
|
|
|
- // 计算开始和结束日期
|
|
|
|
- currTime, err := time.Parse(model.LayoutDate2, currDate)
|
|
|
|
- if err != nil {
|
|
|
|
|
|
+ if err = e.DB.Model(new(model.PenBehavior)).
|
|
|
|
+ Where("id = ?", item.Id).
|
|
|
|
+ Updates(map[string]interface{}{
|
|
|
|
+ "week_rumina_rate": item.WeekRuminaRate,
|
|
|
|
+ "week_intake_rate": item.WeekIntakeRate,
|
|
|
|
+ "week_rest_rate": item.WeekRestRate,
|
|
|
|
+ "week_gasp_rate": item.WeekGaspRate,
|
|
|
|
+ "rumina_std": item.RuminaStd,
|
|
|
|
+ "intake_std": item.IntakeStd,
|
|
|
|
+ "rest_std": item.RestStd,
|
|
|
|
+ "gasp_std": item.GaspStd,
|
|
|
|
+ "is_show": pasturePb.IsShow_Ok,
|
|
|
|
+ }).Error; err != nil {
|
|
zaplog.Error("UpdatePenBehaviorWeekData", zap.Error(err))
|
|
zaplog.Error("UpdatePenBehaviorWeekData", zap.Error(err))
|
|
- continue
|
|
|
|
}
|
|
}
|
|
- startTime := currTime.AddDate(0, 0, -7).Format(model.LayoutDate2)
|
|
|
|
- endTime := currTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
|
|
|
|
-
|
|
|
|
- // 获取历史数据
|
|
|
|
- historyList := e.findHistoryPenBehaviorList(pastureId, startTime, endTime, currFrameid)
|
|
|
|
- if len(historyList) == 0 {
|
|
|
|
- // 如果没有历史数据,将所有记录标记为-1
|
|
|
|
- if err = e.DB.Model(new(model.PenBehavior)).
|
|
|
|
- Where("id = ?", item.Id).
|
|
|
|
- Updates(map[string]interface{}{
|
|
|
|
- "week_rumina_rate": -1,
|
|
|
|
- "week_intake_rate": -1,
|
|
|
|
- "week_rest_rate": -1,
|
|
|
|
- "week_gasp_rate": -1,
|
|
|
|
- "is_show": pasturePb.IsShow_Ok,
|
|
|
|
- }).Error; err != nil {
|
|
|
|
- zaplog.Error("UpdatePenBehaviorWeekData", zap.Error(err))
|
|
|
|
- }
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 按pen_id分组计算统计数据
|
|
|
|
- penStats := make(map[int32]*model.PenBehaviorWeekModel)
|
|
|
|
- for _, v := range historyList {
|
|
|
|
- if stats, exists := penStats[v.PenId]; exists {
|
|
|
|
- stats.CowCount++
|
|
|
|
- stats.SumRumina += v.RuminaRate
|
|
|
|
- stats.SumIntake += v.IntakeRate
|
|
|
|
- stats.SumRest += v.RestRate
|
|
|
|
- stats.SumGasp += v.GaspRate
|
|
|
|
- // 计算标准差
|
|
|
|
- stats.RuminaRate = append(stats.RuminaRate, float64(v.RuminaRate))
|
|
|
|
- stats.IntakeRate = append(stats.IntakeRate, float64(v.IntakeRate))
|
|
|
|
- stats.RestRate = append(stats.RestRate, float64(v.RestRate))
|
|
|
|
- stats.GaspRate = append(stats.GaspRate, float64(v.GaspRate))
|
|
|
|
- } else {
|
|
|
|
- penStats[v.PenId] = &model.PenBehaviorWeekModel{
|
|
|
|
- CowCount: 1,
|
|
|
|
- SumRumina: v.RuminaRate,
|
|
|
|
- SumIntake: v.IntakeRate,
|
|
|
|
- SumRest: v.RestRate,
|
|
|
|
- SumGasp: v.GaspRate,
|
|
|
|
- RuminaRate: []float64{float64(v.RuminaRate)},
|
|
|
|
- IntakeRate: []float64{float64(v.IntakeRate)},
|
|
|
|
- RestRate: []float64{float64(v.RestRate)},
|
|
|
|
- GaspRate: []float64{float64(v.GaspRate)},
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 更新当前记录
|
|
|
|
- if stats, exists := penStats[item.PenId]; exists {
|
|
|
|
- if err = e.DB.Model(new(model.PenBehavior)).
|
|
|
|
- Where("id = ?", item.Id).
|
|
|
|
- Updates(map[string]interface{}{
|
|
|
|
- "week_rumina_rate": int32(float64(stats.SumRumina) / float64(stats.CowCount)),
|
|
|
|
- "week_intake_rate": int32(float64(stats.SumIntake) / float64(stats.CowCount)),
|
|
|
|
- "week_rest_rate": int32(float64(stats.SumRest) / float64(stats.CowCount)),
|
|
|
|
- "week_gasp_rate": int32(float64(stats.SumGasp) / float64(stats.CowCount)),
|
|
|
|
- "rumina_std": int32(calculateStd(stats.RuminaRate)),
|
|
|
|
- "intake_std": int32(calculateStd(stats.IntakeRate)),
|
|
|
|
- "rest_std": int32(calculateStd(stats.RestRate)),
|
|
|
|
- "gasp_std": int32(calculateStd(stats.GaspRate)),
|
|
|
|
- "is_show": pasturePb.IsShow_Ok,
|
|
|
|
- }).Error; err != nil {
|
|
|
|
- zaplog.Error("UpdatePenBehaviorWeekData", zap.Error(err))
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- // 如果没有历史数据,标记为-1
|
|
|
|
- if err = e.DB.Model(new(model.PenBehavior)).
|
|
|
|
- Where("id = ?", item.Id).
|
|
|
|
- Updates(map[string]interface{}{
|
|
|
|
- "week_rumina_rate": -1,
|
|
|
|
- "week_intake_rate": -1,
|
|
|
|
- "week_rest_rate": -1,
|
|
|
|
- "week_gasp_rate": -1,
|
|
|
|
- "is_show": pasturePb.IsShow_Ok,
|
|
|
|
- }).Error; err != nil {
|
|
|
|
- zaplog.Error("UpdatePenBehaviorWeekData", zap.Error(err))
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// findHistoryPenBehaviorList 获取历史数据
|
|
|
|
-func (e *Entry) findHistoryPenBehaviorList(pastureId int64, startTime, endTime string, frameid int32) []*model.PenBehavior {
|
|
|
|
- res := make([]*model.PenBehavior, 0)
|
|
|
|
- if err := e.DB.Model(new(model.PenBehavior)).
|
|
|
|
- Where("pasture_id = ?", pastureId).
|
|
|
|
- Where("heat_date BETWEEN ? AND ?", startTime, endTime).
|
|
|
|
- Where("frameid = ?", frameid).
|
|
|
|
- Find(&res).Error; err != nil {
|
|
|
|
- zaplog.Error("findHistoryPenBehaviorList", zap.Error(err))
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
- return res
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// calculateStd 计算标准差
|
|
|
|
-func calculateStd(values []float64) float64 {
|
|
|
|
- if len(values) == 0 {
|
|
|
|
- return 0
|
|
|
|
- }
|
|
|
|
- // 计算平均值
|
|
|
|
- var sum float64
|
|
|
|
- for _, v := range values {
|
|
|
|
- sum += v
|
|
|
|
- }
|
|
|
|
- mean := sum / float64(len(values))
|
|
|
|
-
|
|
|
|
- // 计算方差
|
|
|
|
- var variance float64
|
|
|
|
- for _, v := range values {
|
|
|
|
- diff := v - mean
|
|
|
|
- variance += diff * diff
|
|
|
|
}
|
|
}
|
|
- variance /= float64(len(values))
|
|
|
|
-
|
|
|
|
- // 返回标准差
|
|
|
|
- return math.Sqrt(variance)
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// calculateActiveTime 计算活动时间
|
|
// calculateActiveTime 计算活动时间
|
|
@@ -325,23 +247,26 @@ func (e *Entry) findPenBehavior(pastureId int64, heatDate string, penId int32, f
|
|
return res
|
|
return res
|
|
}
|
|
}
|
|
|
|
|
|
-func (e *Entry) findWeekPenBehaviorList(pastureId int64) []*model.PenBehavior {
|
|
|
|
- res := make([]*model.PenBehavior, 0)
|
|
|
|
- if err := e.DB.Model(new(model.PenBehavior)).
|
|
|
|
- Where("pasture_id = ?", pastureId).
|
|
|
|
- Where("is_show = ?", pasturePb.IsShow_No).
|
|
|
|
- Where("cow_count >= ?", model.PenBehaviorMinCowCount).
|
|
|
|
- Limit(int(defaultLimit)).
|
|
|
|
- Find(&res).Error; err != nil {
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
- return res
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// ifThenElse 条件判断函数
|
|
|
|
-func ifThenElse(condition bool, a, b int32) int32 {
|
|
|
|
- if condition {
|
|
|
|
- return a
|
|
|
|
|
|
+func (e *Entry) findWeekPenBehaviorList(pastureId int64, heatDate, startTime, endTime string) ([]*model.PenBehavior, error) {
|
|
|
|
+ penBehaviorList := make([]*model.PenBehavior, 0)
|
|
|
|
+ sql := fmt.Sprintf(`
|
|
|
|
+ SELECT b1.id,
|
|
|
|
+ ROUND(AVG(b0.rumina_rate)) week_rumina_rate,
|
|
|
|
+ ROUND(STD(b0.rumina_rate)) rumina_std,
|
|
|
|
+ ROUND(AVG( b0.intake_rate)) week_intake_rate,
|
|
|
|
+ ROUND(STD( b0.intake_rate)) intake_std,
|
|
|
|
+ ROUND(AVG( b0.rest_rate)) week_rest_rate,
|
|
|
|
+ ROUND(STD( b0.rest_rate)) rest_std,
|
|
|
|
+ ROUND(AVG( b0.gasp_rate)) week_gasp_rate,
|
|
|
|
+ ROUND(STD( b0.gasp_rate)) gasp_std
|
|
|
|
+ FROM pen_behavior b1 JOIN pen_behavior b0
|
|
|
|
+ ON b1.pen_id=b0.pen_id AND b1.heat_date='%s'
|
|
|
|
+ AND b1.frameid=b0.frameid AND b0.heat_date BETWEEN '%s' AND '%s'
|
|
|
|
+ WHERE b1.cow_count>= %d AND b1.pasture_id = %d
|
|
|
|
+ GROUP BY b1.id
|
|
|
|
+ `, heatDate, startTime, endTime, model.PenBehaviorMinCowCount, pastureId)
|
|
|
|
+ if err := e.DB.Raw(sql).Find(&penBehaviorList).Error; err != nil {
|
|
|
|
+ return nil, xerr.WithStack(err)
|
|
}
|
|
}
|
|
- return b
|
|
|
|
|
|
+ return penBehaviorList, nil
|
|
}
|
|
}
|