|
@@ -3,9 +3,12 @@ package crontab
|
|
|
import (
|
|
|
"fmt"
|
|
|
"kpt-pasture/model"
|
|
|
+ "math"
|
|
|
"sort"
|
|
|
"time"
|
|
|
|
|
|
+ pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
|
|
|
+
|
|
|
"gitee.com/xuyiping_admin/pkg/logger/zaplog"
|
|
|
"go.uber.org/zap"
|
|
|
)
|
|
@@ -31,113 +34,107 @@ func (e *Entry) UpdatePenBehavior() error {
|
|
|
// PenBehavior 栏舍行为曲线
|
|
|
func (e *Entry) PenBehavior(pastureId, maxPenBehavior int64) {
|
|
|
// 1. 获取颈环原始数据
|
|
|
- neckRingOriginalList, err := e.getNeckRingOriginalList(pastureId, maxPenBehavior)
|
|
|
+ penBehaviorModelList, err := e.getNeckRingOriginalList(pastureId, maxPenBehavior)
|
|
|
if err != nil {
|
|
|
- zaplog.Error("PenBehavior", zap.Any("pastureId", pastureId), zap.Any("maxPenBehavior", maxPenBehavior), zap.Any("err", err))
|
|
|
+ zaplog.Error("PenBehavior",
|
|
|
+ zap.Any("pastureId", pastureId),
|
|
|
+ zap.Any("maxPenBehavior", maxPenBehavior),
|
|
|
+ zap.Any("err", err),
|
|
|
+ )
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- if len(neckRingOriginalList) <= 0 {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 2. 获取牛只信息
|
|
|
- cowMap, err := e.getCowMap(pastureId, neckRingOriginalList)
|
|
|
- if err != nil {
|
|
|
- zaplog.Error("PenBehavior", zap.Any("pastureId", pastureId), zap.Any("neckRingOriginalList", neckRingOriginalList), zap.Any("err", err))
|
|
|
+ if len(penBehaviorModelList) <= 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // 3. 处理栏舍行为数据
|
|
|
- penData := e.processPenBehaviorData(neckRingOriginalList, cowMap)
|
|
|
+ // 2. 处理栏舍行为数据
|
|
|
+ penData := e.processPenBehaviorData(penBehaviorModelList)
|
|
|
|
|
|
- // 4. 计算平均值和百分比
|
|
|
+ // 3. 计算平均值和百分比
|
|
|
e.calculateAveragesAndRates(penData)
|
|
|
|
|
|
- // 5. 保存数据
|
|
|
+ // 4. 保存数据
|
|
|
if err = e.savePenBehaviorData(penData); err != nil {
|
|
|
zaplog.Error("PenBehavior", zap.Any("penData", penData), zap.Any("err", err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- sort.Slice(neckRingOriginalList, func(i, j int) bool {
|
|
|
- return neckRingOriginalList[i].Id > neckRingOriginalList[j].Id
|
|
|
+ sort.Slice(penBehaviorModelList, func(i, j int) bool {
|
|
|
+ return penBehaviorModelList[i].Id > penBehaviorModelList[j].Id
|
|
|
})
|
|
|
-
|
|
|
- if err = e.UpdateSystemNeckRingConfigure(pastureId, model.MaxPenBehavior, neckRingOriginalList[0].Id); err != nil {
|
|
|
- zaplog.Error("PenBehavior", zap.Any("UpdateSystemNeckRingConfigure", err), zap.Any("neckRingOriginalList", neckRingOriginalList))
|
|
|
+ if err = e.UpdateSystemNeckRingConfigure(pastureId, model.MaxPenBehavior, penBehaviorModelList[0].Id); err != nil {
|
|
|
+ zaplog.Error("PenBehavior", zap.Any("MaxPenBehavior", err), zap.Any("penBehaviorModelList", penBehaviorModelList))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// getNeckRingOriginalList 获取颈环原始数据
|
|
|
-func (e *Entry) getNeckRingOriginalList(pastureId, maxPenBehavior int64) ([]*model.NeckRingOriginal, error) {
|
|
|
- var neckRingOriginalList []*model.NeckRingOriginal
|
|
|
- if err := e.DB.Model(new(model.NeckRingOriginal)).
|
|
|
- Where("id > ? AND pasture_id = ?", maxPenBehavior, pastureId).
|
|
|
- Order("active_date,neck_ring_number,frameid").
|
|
|
+func (e *Entry) getNeckRingOriginalList(pastureId, maxPenBehavior int64) ([]*model.PenBehaviorModel, error) {
|
|
|
+ var penBehaviorModelList []*model.PenBehaviorModel
|
|
|
+ if err := e.DB.Table(fmt.Sprintf("%s as h", new(model.NeckRingOriginal).TableName())).
|
|
|
+ Joins("JOIN cow as c ON h.pasture_id = c.pasture_id AND h.neck_ring_number = c.neck_ring_number").
|
|
|
+ Select("h.id,c.pasture_id, c.pen_id, c.pen_name, h.active_date, h.frameid, h.high, h.rumina, h.intake, h.inactive, h.gasp").
|
|
|
+ Where("h.id > ? AND h.pasture_id = ?", maxPenBehavior, pastureId).
|
|
|
+ Order("h.active_date,h.frameid").
|
|
|
Limit(int(defaultLimit)).
|
|
|
- Find(&neckRingOriginalList).Error; err != nil {
|
|
|
+ Find(&penBehaviorModelList).Error; err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- return neckRingOriginalList, nil
|
|
|
+ return penBehaviorModelList, nil
|
|
|
}
|
|
|
|
|
|
-// getCowMap 获取牛只信息映射
|
|
|
-func (e *Entry) getCowMap(pastureId int64, neckRingOriginalList []*model.NeckRingOriginal) (map[string]*model.Cow, error) {
|
|
|
- // 提取牛只ID
|
|
|
- neckRingNumberList := make([]string, 0, len(neckRingOriginalList))
|
|
|
- for _, v := range neckRingOriginalList {
|
|
|
- neckRingNumberList = append(neckRingNumberList, v.NeckRingNumber)
|
|
|
- }
|
|
|
-
|
|
|
- // 获取牛只信息
|
|
|
- cowInfoList, err := e.GetCowByNeckRingNumbers(pastureId, neckRingNumberList)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // 构建牛只信息映射
|
|
|
- cowMap := make(map[string]*model.Cow, len(cowInfoList))
|
|
|
- for _, v := range cowInfoList {
|
|
|
- if v.NeckRingNumber == "" {
|
|
|
- continue
|
|
|
+// processPenBehaviorData 处理栏舍行为数据
|
|
|
+func (e *Entry) processPenBehaviorData(penBehaviorModelList []*model.PenBehaviorModel) map[string]*model.PenBehaviorData {
|
|
|
+ // 按active_date和frameid分组
|
|
|
+ activeDateFrameIdMap := make(map[string][]*model.PenBehaviorModel)
|
|
|
+ for _, v := range penBehaviorModelList {
|
|
|
+ key := fmt.Sprintf("%s_%d", v.ActiveDate, v.Frameid)
|
|
|
+ if activeDateFrameIdMap[key] == nil {
|
|
|
+ activeDateFrameIdMap[key] = make([]*model.PenBehaviorModel, 0)
|
|
|
}
|
|
|
- cowMap[v.NeckRingNumber] = v
|
|
|
+ activeDateFrameIdMap[key] = append(activeDateFrameIdMap[key], v)
|
|
|
}
|
|
|
|
|
|
- return cowMap, nil
|
|
|
-}
|
|
|
-
|
|
|
-// processPenBehaviorData 处理栏舍行为数据
|
|
|
-func (e *Entry) processPenBehaviorData(neckRingOriginalList []*model.NeckRingOriginal, cowMap map[string]*model.Cow) map[string]*model.PenBehaviorData {
|
|
|
- penData := make(map[string]*model.PenBehaviorData, len(neckRingOriginalList))
|
|
|
- for _, v := range neckRingOriginalList {
|
|
|
- cowInfo, ok := cowMap[v.NeckRingNumber]
|
|
|
- if !ok {
|
|
|
- zaplog.Error("PenBehavior", zap.Any("neckRingNumber", v.NeckRingNumber))
|
|
|
- continue
|
|
|
+ // 按pen_id分组统计
|
|
|
+ penData := make(map[string]*model.PenBehaviorData)
|
|
|
+ for _, v := range activeDateFrameIdMap {
|
|
|
+ // 按pen_id分组
|
|
|
+ penIdMap := make(map[int32]*model.PenBehaviorData)
|
|
|
+ for _, item := range v {
|
|
|
+ if data, exists := penIdMap[item.PenId]; exists {
|
|
|
+ // 更新计数
|
|
|
+ data.CowCount++
|
|
|
+ // 更新平均值
|
|
|
+ data.AvgHigh += item.High
|
|
|
+ // 更新行为统计
|
|
|
+ data.SumRumina += ifThenElse(item.Rumina >= 8, 1, 0)
|
|
|
+ data.SumIntake += ifThenElse(item.Intake >= 8, 1, 0)
|
|
|
+ data.SumRest += ifThenElse(item.Inactive >= 8, 1, 0)
|
|
|
+ data.SumGasp += ifThenElse(item.Gasp >= 8, 1, 0)
|
|
|
+ } else {
|
|
|
+ penIdMap[item.PenId] = &model.PenBehaviorData{
|
|
|
+ PastureId: item.PastureId,
|
|
|
+ PenId: item.PenId,
|
|
|
+ PenName: item.PenName,
|
|
|
+ HeatDate: item.ActiveDate,
|
|
|
+ Frameid: item.Frameid,
|
|
|
+ CowCount: 1,
|
|
|
+ AvgHigh: item.High,
|
|
|
+ SumRumina: ifThenElse(item.Rumina >= 8, 1, 0),
|
|
|
+ SumIntake: ifThenElse(item.Intake >= 8, 1, 0),
|
|
|
+ SumRest: ifThenElse(item.Inactive >= 8, 1, 0),
|
|
|
+ SumGasp: ifThenElse(item.Gasp >= 8, 1, 0),
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- key := fmt.Sprintf("%s_%d_%d", v.ActiveDate, cowInfo.PenId, v.Frameid)
|
|
|
- if data, exists := penData[key]; exists {
|
|
|
- data.CowCount++
|
|
|
- data.AvgHigh += v.High
|
|
|
- data.SumRumina += ifThenElse(v.Rumina >= 8, 1, 0)
|
|
|
- data.SumIntake += ifThenElse(v.Intake >= 8, 1, 0)
|
|
|
- data.SumRest += ifThenElse(v.Inactive >= 8, 1, 0)
|
|
|
- data.SumGasp += ifThenElse(v.Gasp >= 8, 1, 0)
|
|
|
- } else {
|
|
|
- penData[key] = &model.PenBehaviorData{
|
|
|
- PastureId: cowInfo.PastureId,
|
|
|
- PenId: cowInfo.PenId,
|
|
|
- PenName: cowInfo.PenName,
|
|
|
- HeatDate: v.ActiveDate,
|
|
|
- Frameid: v.Frameid,
|
|
|
- CowCount: 1,
|
|
|
- AvgHigh: v.High,
|
|
|
- }
|
|
|
+ // 将penIdMap的数据合并到penData中
|
|
|
+ for penId, data := range penIdMap {
|
|
|
+ key := fmt.Sprintf("%s_%d_%d", data.HeatDate, penId, data.Frameid)
|
|
|
+ penData[key] = data
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
return penData
|
|
|
}
|
|
|
|
|
@@ -146,7 +143,6 @@ func (e *Entry) calculateAveragesAndRates(penData map[string]*model.PenBehaviorD
|
|
|
for _, data := range penData {
|
|
|
// 计算平均值
|
|
|
data.AvgHigh = data.AvgHigh / data.CowCount
|
|
|
-
|
|
|
// 计算百分比
|
|
|
if data.CowCount > 0 {
|
|
|
data.RuminaRate = int32(float64(data.SumRumina) / float64(data.CowCount) * 100)
|
|
@@ -166,73 +162,191 @@ func (e *Entry) savePenBehaviorData(penData map[string]*model.PenBehaviorData) e
|
|
|
// 构建保存数据
|
|
|
penBehavior := model.NewPenBehavior(data, activeTime)
|
|
|
|
|
|
+ if e.isExistByPenBehavior(data.PastureId, data.HeatDate, data.PenId, data.Frameid) {
|
|
|
+ historyData := e.findPenBehavior(data.PastureId, data.HeatDate, data.PenId, data.Frameid)
|
|
|
+ if historyData == nil || historyData.Id <= 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 计算新的总和和平均值
|
|
|
+ newCowCount := historyData.CowCount + penBehavior.CowCount
|
|
|
+ newAvgHigh := (historyData.AvgHigh*historyData.CowCount + penBehavior.AvgHigh*penBehavior.CowCount) / newCowCount
|
|
|
+ newSumRumina := historyData.SumRumina + penBehavior.SumRumina
|
|
|
+ newSumIntake := historyData.SumIntake + penBehavior.SumIntake
|
|
|
+ newSumRest := historyData.SumRest + penBehavior.SumRest
|
|
|
+ newSumGasp := historyData.SumGasp + penBehavior.SumGasp
|
|
|
+
|
|
|
+ if err := e.DB.Model(new(model.PenBehavior)).
|
|
|
+ Where("id = ?", historyData.Id).
|
|
|
+ Updates(map[string]interface{}{
|
|
|
+ "cow_count": newCowCount,
|
|
|
+ "avg_high": newAvgHigh,
|
|
|
+ "sum_rumina": newSumRumina,
|
|
|
+ "sum_intake": newSumIntake,
|
|
|
+ "sum_rest": newSumRest,
|
|
|
+ "sum_gasp": newSumGasp,
|
|
|
+ "rumina_rate": int32(float64(newSumRumina) / float64(newCowCount) * 100),
|
|
|
+ "intake_rate": int32(float64(newSumIntake) / float64(newCowCount) * 100),
|
|
|
+ "rest_rate": int32(float64(newSumRest) / float64(newCowCount) * 100),
|
|
|
+ "gasp_rate": int32(float64(newSumGasp) / float64(newCowCount) * 100),
|
|
|
+ }).Error; err != nil {
|
|
|
+ zaplog.Error("savePenBehaviorData", zap.Any("penBehavior", penBehavior), zap.Any("err", err))
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
// 使用 Upsert 操作
|
|
|
if err := e.DB.Model(new(model.PenBehavior)).
|
|
|
- Where("pasture_id = ? AND heat_date = ? AND pen_id = ? AND active_time = ?",
|
|
|
- penBehavior.PastureId, penBehavior.HeatDate, penBehavior.PenId, penBehavior.ActiveTime).
|
|
|
- Assign(map[string]interface{}{
|
|
|
- "frameid": penBehavior.Frameid,
|
|
|
- "cow_count": penBehavior.CowCount,
|
|
|
- "avg_high": penBehavior.AvgHigh,
|
|
|
- "sum_rumina": penBehavior.SumRumina,
|
|
|
- "sum_intake": penBehavior.SumIntake,
|
|
|
- "sum_rest": penBehavior.SumRest,
|
|
|
- "sum_gasp": penBehavior.SumGasp,
|
|
|
- "rumina_rate": penBehavior.RuminaRate,
|
|
|
- "intake_rate": penBehavior.IntakeRate,
|
|
|
- "rest_rate": penBehavior.RestRate,
|
|
|
- "gasp_rate": penBehavior.GaspRate,
|
|
|
- }).
|
|
|
- FirstOrCreate(penBehavior).Error; err != nil {
|
|
|
- return err
|
|
|
+ Create(penBehavior).Error; err != nil {
|
|
|
+ zaplog.Error("savePenBehaviorData", zap.Any("penBehavior", penBehavior), zap.Any("err", err))
|
|
|
}
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
func (e *Entry) UpdatePenBehaviorWeekData(pastureId int64) {
|
|
|
- nowTime := time.Now().Local()
|
|
|
- currTime := nowTime.Format(model.LayoutDate2)
|
|
|
- startTime := nowTime.AddDate(0, 0, -7).Format(model.LayoutDate2)
|
|
|
- endTime := nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
|
|
|
- penBehaviorList := make([]*model.PenBehavior, 0)
|
|
|
- if err := e.DB.Table(fmt.Sprintf("%s as b1", new(model.PenBehavior).TableName())).
|
|
|
- Joins(fmt.Sprintf("JOIN %s as b0 ON b1.pen_id = b0.pen_id", new(model.PenBehavior).TableName())).
|
|
|
- Select(`b1.id, ROUND(AVG(b0.rumina_rate)) AS week_rumina_rate,
|
|
|
- ROUND(AVG(b0.intake_rate)) AS week_intake_rate,
|
|
|
- ROUND(AVG(b0.rest_rate)) AS week_rest_rate,
|
|
|
- ROUND(AVG(b0.gasp_rate)) AS week_gasp_rate,
|
|
|
- ROUND(STD(b0.rumina_rate)) AS rumina_std,
|
|
|
- ROUND(STD(b0.intake_rate)) AS intake_std,
|
|
|
- ROUND(STD(b0.rest_rate)) AS rest_std,
|
|
|
- ROUND(STD(b0.gasp_rate)) AS gasp_std`).
|
|
|
- Where("b1.pasture_id = ?", pastureId).
|
|
|
- Where("b1.heat_date = ?", currTime).
|
|
|
- Where("b1.week_rumina_rate = ?", 0).
|
|
|
- Where("b1.frameid = b0.frameid").
|
|
|
- Where("b0.heat_date BETWEEN ? AND ?", startTime, endTime).
|
|
|
- Find(&penBehaviorList).Error; err != nil {
|
|
|
- zaplog.Error("PenBehavior", zap.Any("penBehaviorList", penBehaviorList), zap.Any("err", err))
|
|
|
+ penBehaviorList := e.findWeekPenBehaviorList(pastureId)
|
|
|
+ if len(penBehaviorList) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- for _, v := range penBehaviorList {
|
|
|
- if err := e.DB.Model(new(model.PenBehavior)).
|
|
|
- Where("id = ?", v.Id).
|
|
|
- Updates(map[string]interface{}{
|
|
|
- "week_rumina_rate": v.WeekRuminaRate,
|
|
|
- "week_intake_rate": v.WeekIntakeRate,
|
|
|
- "week_rest_rate": v.WeekRestRate,
|
|
|
- "week_gasp_rate": v.WeekGaspRate,
|
|
|
- "rumina_std": v.RuminaStd,
|
|
|
- "intake_std": v.IntakeStd,
|
|
|
- "rest_std": v.RestStd,
|
|
|
- "gasp_std": v.GaspStd,
|
|
|
- }).Error; err != nil {
|
|
|
- zaplog.Error("PenBehavior", zap.Any("penBehaviorWeekData", v), zap.Any("err", err))
|
|
|
+ // 按日期和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的数据
|
|
|
+ for _, item := range penBehaviorList {
|
|
|
+ currDate := item.HeatDate
|
|
|
+ currFrameid := item.Frameid
|
|
|
+ // 计算开始和结束日期
|
|
|
+ currTime, err := time.Parse(model.LayoutDate2, currDate)
|
|
|
+ if err != nil {
|
|
|
+ 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.RuminaRate)),
|
|
|
+ "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 计算活动时间
|
|
@@ -255,6 +369,40 @@ func (e *Entry) calculateActiveTime(heatDate string, frameid int32) string {
|
|
|
return finalTime.Format(model.LayoutTime)
|
|
|
}
|
|
|
|
|
|
+// isExistByPenBehavior 是否存在
|
|
|
+func (e *Entry) isExistByPenBehavior(pastureId int64, heatDate string, penId int32, frameid int32) bool {
|
|
|
+ var count int64
|
|
|
+ if err := e.DB.Model(new(model.PenBehavior)).
|
|
|
+ Where("pasture_id = ? AND heat_date = ? AND frameid = ? AND pen_id = ?", pastureId, heatDate, penId, frameid).
|
|
|
+ Count(&count).Error; err != nil {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return count > 0
|
|
|
+}
|
|
|
+
|
|
|
+func (e *Entry) findPenBehavior(pastureId int64, heatDate string, penId int32, frameid int32) *model.PenBehavior {
|
|
|
+ res := &model.PenBehavior{}
|
|
|
+ if err := e.DB.Model(new(model.PenBehavior)).
|
|
|
+ Where("pasture_id = ? AND heat_date = ? AND frameid = ? AND pen_id = ?", pastureId, heatDate, penId, frameid).
|
|
|
+ First(res).Error; err != nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ 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 {
|