|  | @@ -1,20 +1,16 @@
 | 
	
		
			
				|  |  | -package mqtt
 | 
	
		
			
				|  |  | +package crontab
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import (
 | 
	
		
			
				|  |  |  	"fmt"
 | 
	
		
			
				|  |  |  	"kpt-pasture/model"
 | 
	
		
			
				|  |  | -	"kpt-pasture/module/crontab"
 | 
	
		
			
				|  |  | +	"kpt-pasture/util"
 | 
	
		
			
				|  |  |  	"math"
 | 
	
		
			
				|  |  |  	"time"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	"gorm.io/gorm"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 | 
	
		
			
				|  |  | -	"go.uber.org/zap"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	"gitee.com/xuyiping_admin/pkg/xerr"
 | 
	
		
			
				|  |  | +	"go.uber.org/zap"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const (
 | 
	
	
		
			
				|  | @@ -26,22 +22,159 @@ const (
 | 
	
		
			
				|  |  |  	DefaultScore    = 100
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (e *Entry) PastureUpdateActiveHabit() {
 | 
	
		
			
				|  |  | +var (
 | 
	
		
			
				|  |  | +	defaultLimit = int32(1000)
 | 
	
		
			
				|  |  | +	isDelete     bool
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// NeckRingOriginalMergeData 把脖环数据合并成2个小时的
 | 
	
		
			
				|  |  | +func (e *Entry) NeckRingOriginalMergeData() error {
 | 
	
		
			
				|  |  | +	var err error
 | 
	
		
			
				|  |  | +	limit := e.Cfg.NeckRingLimit
 | 
	
		
			
				|  |  | +	if limit <= 0 {
 | 
	
		
			
				|  |  | +		limit = defaultLimit
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	newTime := time.Now()
 | 
	
		
			
				|  |  | +	createdAt := newTime.Add(-1 * time.Hour)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	neckRingList := make([]*model.NeckRingOriginal, 0)
 | 
	
		
			
				|  |  | +	if err = e.DB.Model(new(model.NeckRingOriginal)).
 | 
	
		
			
				|  |  | +		Where("is_show <= ?", pasturePb.IsShow_No).
 | 
	
		
			
				|  |  | +		Where("created_at <= ?", createdAt.Unix()).
 | 
	
		
			
				|  |  | +		Order("neck_ring_number,active_date,frameid").
 | 
	
		
			
				|  |  | +		Limit(int(limit)).Find(&neckRingList).Error; err != nil {
 | 
	
		
			
				|  |  | +		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if len(neckRingList) <= 0 {
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	defer func() {
 | 
	
		
			
				|  |  | +		if newTime.Day()%15 == 0 && !isDelete {
 | 
	
		
			
				|  |  | +			// 原始数据删除15天前的
 | 
	
		
			
				|  |  | +			e.DB.Model(new(model.NeckRingOriginal)).
 | 
	
		
			
				|  |  | +				Where("created_at < ?", newTime.AddDate(0, 0, -15).Unix()).
 | 
	
		
			
				|  |  | +				Delete(new(model.NeckRingOriginal))
 | 
	
		
			
				|  |  | +			// 活动数据删除6个月前的数据
 | 
	
		
			
				|  |  | +			e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +				Where("created_at < ?", newTime.AddDate(0, -6, 0).Unix()).
 | 
	
		
			
				|  |  | +				Delete(new(model.NeckActiveHabit))
 | 
	
		
			
				|  |  | +			isDelete = true
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}()
 | 
	
		
			
				|  |  | +	// 计算合并
 | 
	
		
			
				|  |  | +	neckActiveHabitList := e.recalculate(neckRingList)
 | 
	
		
			
				|  |  | +	if len(neckActiveHabitList) <= 0 {
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 批量插入和更新
 | 
	
		
			
				|  |  | +	var newNeckRingProcessList []*model.NeckRingProcess
 | 
	
		
			
				|  |  | +	for _, neckActiveHabit := range neckActiveHabitList {
 | 
	
		
			
				|  |  | +		//更新脖环牛只相关信息 新数据直接插入
 | 
	
		
			
				|  |  | +		historyNeckActiveHabit, ct := e.IsExistNeckActiveHabit(neckActiveHabit.NeckRingNumber, neckActiveHabit.HeatDate, neckActiveHabit.Frameid)
 | 
	
		
			
				|  |  | +		if ct <= 0 {
 | 
	
		
			
				|  |  | +			if err = e.DB.Create(neckActiveHabit).Error; err != nil {
 | 
	
		
			
				|  |  | +				zaplog.Info("NeckRingOriginalMergeData-1", zap.Any("err", err), zap.Any("neckActiveHabit", neckActiveHabit))
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			newNeckRingProcess := model.NewNeckRingProcess(neckActiveHabit)
 | 
	
		
			
				|  |  | +			newNeckRingProcessList = append(newNeckRingProcessList, newNeckRingProcess)
 | 
	
		
			
				|  |  | +			if err = e.UpdateNeckRingOriginalIsShow(neckActiveHabit); err != nil {
 | 
	
		
			
				|  |  | +				zaplog.Error("NeckRingOriginalMergeData-3", zap.Any("err", err), zap.Any("neckActiveHabit", neckActiveHabit))
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if historyNeckActiveHabit == nil || historyNeckActiveHabit.Id <= 0 {
 | 
	
		
			
				|  |  | +			zaplog.Error("NeckRingOriginalMergeData-4", zap.Any("historyNeckActiveHabit", historyNeckActiveHabit), zap.Any("ct", ct), zap.Any("neckActiveHabit", neckActiveHabit))
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 重新计算
 | 
	
		
			
				|  |  | +		newNeckActiveHabit := e.againRecalculate(historyNeckActiveHabit)
 | 
	
		
			
				|  |  | +		if newNeckActiveHabit != nil {
 | 
	
		
			
				|  |  | +			if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +				Select("rumina", "intake", "inactive", "gasp", "other", "high", "active").
 | 
	
		
			
				|  |  | +				Where("id = ?", historyNeckActiveHabit.Id).
 | 
	
		
			
				|  |  | +				Updates(newNeckActiveHabit).Error; err != nil {
 | 
	
		
			
				|  |  | +				zaplog.Error("NeckRingOriginalMergeData-5", zap.Any("historyNeckActiveHabit", historyNeckActiveHabit), zap.Any("ct", ct), zap.Any("newNeckActiveHabit", newNeckActiveHabit))
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if len(newNeckRingProcessList) > 0 {
 | 
	
		
			
				|  |  | +		if err = e.DB.Create(newNeckRingProcessList).Error; err != nil {
 | 
	
		
			
				|  |  | +			zaplog.Error("newNeckRingProcessList", zap.Any("err", err))
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (e *Entry) NeckRingCalculate() error {
 | 
	
		
			
				|  |  |  	pastureList := e.FindPastureList()
 | 
	
		
			
				|  |  |  	if pastureList == nil || len(pastureList) == 0 {
 | 
	
		
			
				|  |  | -		return
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	for _, pasture := range pastureList {
 | 
	
		
			
				|  |  |  		if err := e.EntryUpdateActiveHabit(pasture.Id); err != nil {
 | 
	
		
			
				|  |  | -			zaplog.Error("PastureUpdateActiveHabit", zap.Any("PastureUpdateActiveHabit", err), zap.Any("pasture", pasture))
 | 
	
		
			
				|  |  | +			zaplog.Error("PastureUpdateActiveHabit", zap.Any("err", err), zap.Any("pasture", pasture))
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		zaplog.Info(fmt.Sprintf("PastureUpdateActiveHabit Success %d", pasture.Id))
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// recalculate 合并计算
 | 
	
		
			
				|  |  | +func (e *Entry) recalculate(neckRingList []*model.NeckRingOriginal) []*model.NeckActiveHabit {
 | 
	
		
			
				|  |  | +	originalMapData := make(map[string]*model.NeckRingOriginalMerge)
 | 
	
		
			
				|  |  | +	// 合并成2个小时的
 | 
	
		
			
				|  |  | +	for _, v := range neckRingList {
 | 
	
		
			
				|  |  | +		xframeId := util.XFrameId(v.Frameid)
 | 
	
		
			
				|  |  | +		mapKey := fmt.Sprintf("%s%s%s%s%d", v.NeckRingNumber, model.JoinKey, v.ActiveDate, model.JoinKey, xframeId) // 0001/2023-12-04/0 0001/2023-12-03/4
 | 
	
		
			
				|  |  | +		if originalMapData[mapKey] == nil {
 | 
	
		
			
				|  |  | +			originalMapData[mapKey] = new(model.NeckRingOriginalMerge)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		originalMapData[mapKey].IsMageData(v, xframeId)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	currTime := time.Now()
 | 
	
		
			
				|  |  | +	// 算平均值
 | 
	
		
			
				|  |  | +	for k, v := range originalMapData {
 | 
	
		
			
				|  |  | +		// 过滤掉合并后不满6条数据
 | 
	
		
			
				|  |  | +		if v.RecordCount != 6 {
 | 
	
		
			
				|  |  | +			currMaxXframeId := util.FrameIdMapReverse[int32(currTime.Hour())]
 | 
	
		
			
				|  |  | +			activeDateString := fmt.Sprintf("%s %02d:00:00", v.ActiveDate, v.XframeId*2+1)
 | 
	
		
			
				|  |  | +			activeDate, _ := time.Parse(model.LayoutTime, activeDateString)
 | 
	
		
			
				|  |  | +			if currMaxXframeId-v.XframeId <= 1 && currTime.Add(-1*time.Hour).Unix() < activeDate.Unix() {
 | 
	
		
			
				|  |  | +				delete(originalMapData, k)
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		v.SumAvg()
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return model.NeckRingOriginalMap(originalMapData).ForMatData()
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (e *Entry) againRecalculate(data *model.NeckActiveHabit) *model.NeckActiveHabit {
 | 
	
		
			
				|  |  | +	originalList := make([]*model.NeckRingOriginal, 0)
 | 
	
		
			
				|  |  | +	frameIds := util.FrameIds(data.Frameid)
 | 
	
		
			
				|  |  | +	if err := e.DB.Model(new(model.NeckRingOriginal)).
 | 
	
		
			
				|  |  | +		Where("neck_ring_number = ?", data.NeckRingNumber).
 | 
	
		
			
				|  |  | +		Where("active_date = ?", data.HeatDate).
 | 
	
		
			
				|  |  | +		Where("frameid IN (?)", frameIds).
 | 
	
		
			
				|  |  | +		Find(&originalList).Error; err != nil {
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	newDataList := e.recalculate(originalList)
 | 
	
		
			
				|  |  | +	if len(newDataList) != 1 {
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return newDataList[0]
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  | -	lastMaxHabitData, err := e.GetSystemConfigure2(pastureId, model.MaxHabit)
 | 
	
		
			
				|  |  | +	lastMaxHabitData, err := e.GetSystemConfigure(pastureId, model.MaxHabit)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -51,7 +184,7 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  		Where("id > ?", lastMaxHabitId).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -		Where(e.DB.Where("record_count = ?", model.AvgHours).Or("is_show = ?", pasturePb.IsShow_Ok)).
 | 
	
		
			
				|  |  | +		Where("is_show = ?", pasturePb.IsShow_No).
 | 
	
		
			
				|  |  |  		Order("id desc").First(currMaxHabit).Error; err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -70,37 +203,41 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	}()
 | 
	
		
			
				|  |  |  	// 获取这段执行数据内最大日期和最小日期
 | 
	
		
			
				|  |  |  	xToday := &XToday{}
 | 
	
		
			
				|  |  | -	activeLowest, err := e.GetSystemConfigure2(pastureId, model.ActiveLowest)
 | 
	
		
			
				|  |  | +	activeLowest, err := e.GetSystemConfigure(pastureId, model.High)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	ruminaLowest, err := e.GetSystemConfigure2(pastureId, model.RuminaLowest)
 | 
	
		
			
				|  |  | +	ruminaLowest, err := e.GetSystemConfigure(pastureId, model.Rumina)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	xRuminaDisc, err := e.GetSystemConfigure2(pastureId, model.XRuminaDisc)
 | 
	
		
			
				|  |  | +	xRuminaDisc, err := e.GetSystemConfigure(pastureId, model.XRuminaDisc)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return err
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	xChangeDiscount, err := e.GetSystemConfigure2(pastureId, model.XChangeDiscount)
 | 
	
		
			
				|  |  | +	xChangeDiscount, err := e.GetSystemConfigure(pastureId, model.XChangeDiscount)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return err
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	xToday.ActiveLowest = int32(activeLowest.Value)
 | 
	
		
			
				|  |  | -	xToday.RuminaLowest = int32(ruminaLowest.Value)
 | 
	
		
			
				|  |  | +	weeklyActive, err := e.GetSystemConfigure(pastureId, model.WeeklyActive)
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	xToday.High = int32(activeLowest.Value)
 | 
	
		
			
				|  |  | +	xToday.Rumina = int32(ruminaLowest.Value)
 | 
	
		
			
				|  |  |  	xToday.XRuminaDisc = int32(xRuminaDisc.Value)
 | 
	
		
			
				|  |  |  	xToday.XChangeDiscount = int32(xChangeDiscount.Value)
 | 
	
		
			
				|  |  | -	xToday.LastMaxHabitId = lastMaxHabitId  // 上次执行的id
 | 
	
		
			
				|  |  | -	xToday.CurrMaxHabitId = currMaxHabit.Id // 本次执行的id
 | 
	
		
			
				|  |  | +	xToday.CurrMaxHabitId = currMaxHabit.Id
 | 
	
		
			
				|  |  | +	xToday.LastMaxHabitId = lastMaxHabitId
 | 
	
		
			
				|  |  | +	xToday.WeeklyActive = int32(weeklyActive.Value)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	// 更新活动滤波
 | 
	
		
			
				|  |  |  	if err = e.FirstFilterUpdate(pastureId, xToday); err != nil {
 | 
	
		
			
				|  |  |  		zaplog.Error("EntryUpdateActiveHabit", zap.Any("FirstFilterUpdate", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	// 更新周平均值
 | 
	
		
			
				|  |  | -	if err = e.WeeklyActiveAvgUpdate(pastureId, xToday); err != nil {
 | 
	
		
			
				|  |  | -		zaplog.Error("EntryUpdateActiveHabit", zap.Any("WeeklyActiveAvgUpdate", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	// 二次更新滤波
 | 
	
		
			
				|  |  |  	if err = e.SecondUpdateChangeFilter(pastureId, xToday); err != nil {
 | 
	
		
			
				|  |  |  		zaplog.Error("EntryUpdateActiveHabit", zap.Any("SecondUpdateChangeFilter", err), zap.Any("xToday", xToday))
 | 
	
	
		
			
				|  | @@ -112,8 +249,9 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +		Where("id BETWEEN ? AND  ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -		Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("is_show = ?", pasturePb.IsShow_No).
 | 
	
		
			
				|  |  |  		Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  |  		Updates(map[string]interface{}{
 | 
	
		
			
				|  |  |  			"change_filter": model.DefaultChangeFilter,
 | 
	
	
		
			
				|  | @@ -124,12 +262,14 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +		Where("id BETWEEN ? AND  ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -		Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("is_show = ?", pasturePb.IsShow_No).
 | 
	
		
			
				|  |  |  		Where("change_filter < ?", 0).
 | 
	
		
			
				|  |  |  		Where("filter_correct < ?", model.DefaultFilterCorrect).
 | 
	
		
			
				|  |  |  		Updates(map[string]interface{}{
 | 
	
		
			
				|  |  |  			"filter_correct": model.DefaultFilterCorrect,
 | 
	
		
			
				|  |  | +			"is_show":        pasturePb.IsShow_Ok,
 | 
	
		
			
				|  |  |  		}).Error; err != nil {
 | 
	
		
			
				|  |  |  		zaplog.Error("EntryUpdateActiveHabit", zap.Any("filter_correct", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -141,21 +281,44 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// CurrentMaxXFrameId 当前最大frameid
 | 
	
		
			
				|  |  | +func (e *Entry) CurrentMaxXFrameId(neckRingNumber, activeDate string) (frameid int32) {
 | 
	
		
			
				|  |  | +	type Fm struct {
 | 
	
		
			
				|  |  | +		Frameid int32
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	maxFx := &Fm{}
 | 
	
		
			
				|  |  | +	if err := e.DB.Model(new(model.NeckRingOriginal)).
 | 
	
		
			
				|  |  | +		Select("frameid").
 | 
	
		
			
				|  |  | +		Where("neck_ring_number = ?", neckRingNumber).
 | 
	
		
			
				|  |  | +		Where("active_date = ?", activeDate).
 | 
	
		
			
				|  |  | +		Order("frameid DESC").First(maxFx).Error; err != nil {
 | 
	
		
			
				|  |  | +		zaplog.Error("CurrentMaxXFrameId", zap.Any("err", err))
 | 
	
		
			
				|  |  | +		return 0
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return maxFx.Frameid
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // FirstFilterUpdate 首次更新活动滤波
 | 
	
		
			
				|  |  | -func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) error {
 | 
	
		
			
				|  |  | +func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) (err error) {
 | 
	
		
			
				|  |  |  	newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
 | 
	
		
			
				|  |  | -	if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  		Where("id BETWEEN ? AND ?", xToDay.LastMaxHabitId, xToDay.CurrMaxHabitId).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | +		Where("is_show = ?", pasturePb.IsShow_No).
 | 
	
		
			
				|  |  |  		Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  | -		Where(e.DB.Where("high >= ?", xToDay.ActiveLowest).Or("rumina >= ?", xToDay.RuminaLowest)). // 活动量过低牛只不参与计算
 | 
	
		
			
				|  |  | +		Where(e.DB.Where("high >= ?", xToDay.High).Or("rumina >= ?", xToDay.Rumina)).
 | 
	
		
			
				|  |  |  		Order("neck_ring_number,heat_date,frameid").
 | 
	
		
			
				|  |  |  		Limit(int(defaultLimit)).Find(&newNeckActiveHabitList).Error; err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	// 活动量滤波
 | 
	
		
			
				|  |  |  	for _, v := range newNeckActiveHabitList {
 | 
	
		
			
				|  |  | -		firstFilterData := &FirstFilterData{}
 | 
	
		
			
				|  |  | +		// 过滤牛只未绑定的脖环的数据
 | 
	
		
			
				|  |  | +		cowInfo := e.GetCowInfoByNeckRingNumber(v.PastureId, v.NeckRingNumber)
 | 
	
		
			
				|  |  | +		if cowInfo == nil || cowInfo.Id <= 0 {
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		frameId := v.Frameid
 | 
	
		
			
				|  |  |  		heatDate := v.HeatDate
 | 
	
		
			
				|  |  |  		if v.Frameid == 0 {
 | 
	
	
		
			
				|  | @@ -163,15 +326,8 @@ func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) error {
 | 
	
		
			
				|  |  |  			heatDateParse, _ := time.Parse(model.LayoutDate2, heatDate)
 | 
	
		
			
				|  |  |  			heatDate = heatDateParse.AddDate(0, 0, -1).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -			Select("neck_ring_number", "filter_high", "filter_rumina", "filter_chew").
 | 
	
		
			
				|  |  | -			Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  | -			Where("heat_date = ?", heatDate).
 | 
	
		
			
				|  |  | -			Where("frameid = ?", frameId).
 | 
	
		
			
				|  |  | -			First(&firstFilterData).Error; err != nil {
 | 
	
		
			
				|  |  | -			zaplog.Error("EntryUpdateActiveHabit", zap.Any("FirstFilterUpdate", err))
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +		firstFilterData := e.FindFirstFilter(pastureId, v.NeckRingNumber, heatDate, frameId)
 | 
	
		
			
				|  |  |  		if v.FilterHigh > 0 {
 | 
	
		
			
				|  |  |  			firstFilterData.FilterHigh = v.FilterHigh
 | 
	
		
			
				|  |  |  		} else {
 | 
	
	
		
			
				|  | @@ -200,155 +356,68 @@ func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) error {
 | 
	
		
			
				|  |  |  				firstFilterData.FilterChew = v.Rumina + v.Intake
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		// 更新过滤值
 | 
	
		
			
				|  |  | -		if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -			Select("filter_high", "filter_rumina", "filter_chew").
 | 
	
		
			
				|  |  | -			Where("id = ?", v.Id).
 | 
	
		
			
				|  |  | -			Updates(map[string]interface{}{
 | 
	
		
			
				|  |  | -				"filter_high":   firstFilterData.FilterHigh,
 | 
	
		
			
				|  |  | -				"filter_rumina": firstFilterData.FilterRumina,
 | 
	
		
			
				|  |  | -				"filter_chew":   firstFilterData.FilterChew,
 | 
	
		
			
				|  |  | -			}).Error; err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	zaplog.Info("EntryUpdateActiveHabit-FilterUpdate-Success")
 | 
	
		
			
				|  |  | -	return nil
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// WeeklyActiveAvgUpdate 更新周平均值
 | 
	
		
			
				|  |  | -func (e *Entry) WeeklyActiveAvgUpdate(pastureId int64, xToday *XToday) (err error) {
 | 
	
		
			
				|  |  | -	weeklyActive, err := e.GetSystemConfigure2(pastureId, model.WeeklyActive)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if err = e.DB.Transaction(func(tx *gorm.DB) error {
 | 
	
		
			
				|  |  | -		neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
 | 
	
		
			
				|  |  | -		if err = tx.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -			Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -			Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -			Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  | -			Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina > ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | -			Order("neck_ring_number,frameid").
 | 
	
		
			
				|  |  | -			Limit(int(defaultLimit)).Find(&neckActiveHabitList).Error; err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +		// 前七天的
 | 
	
		
			
				|  |  | +		weekHabitData := e.FindWeekHabitData(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid, xToDay)
 | 
	
		
			
				|  |  | +		highDiff := v.FilterHigh - weekHabitData.WeekHighHabit
 | 
	
		
			
				|  |  | +		denominator := float64(v.WeekHigh)*0.6 + float64(weekHabitData.WeekHighHabit)*0.2 + float64(xToDay.WeeklyActive)*0.2
 | 
	
		
			
				|  |  | +		if highDiff > 0 {
 | 
	
		
			
				|  |  | +			v.ChangeHigh = int32(math.Round((float64(highDiff) / denominator) * 100))
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			v.ChangeHigh = int32(math.Round(float64(highDiff) / denominator * 100))
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		zaplog.Info("WeeklyActiveAvgUpdate-0", zap.Any("neckActiveHabitList", neckActiveHabitList))
 | 
	
		
			
				|  |  | -		for _, v := range neckActiveHabitList {
 | 
	
		
			
				|  |  | -			beginDayDate, _ := time.Parse(model.LayoutDate2, v.HeatDate)
 | 
	
		
			
				|  |  | -			before7DayDate := beginDayDate.AddDate(0, 0, -7).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | -			before1DayDate := beginDayDate.AddDate(0, 0, -1).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			weekHabitData := &crontab.WeekHabit{}
 | 
	
		
			
				|  |  | -			if err = tx.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -				Select("neck_ring_number").
 | 
	
		
			
				|  |  | -				Select("IF(COUNT(1)>=3, ROUND((SUM(filter_high) -MIN(filter_high) -MAX(filter_high))/ABS(COUNT(1) -2),0), -1) as avg_high_habit").
 | 
	
		
			
				|  |  | -				Select("IF(COUNT(1)>=3, ROUND((SUM(filter_rumina) -MIN(filter_rumina) -MAX(filter_rumina))/ABS(COUNT(1) -2),0), -1) as avg_rumina_habit").
 | 
	
		
			
				|  |  | -				Select("IF(COUNT(1)>=3, ROUND((SUM(filter_chew) -MIN(filter_chew) -MAX(filter_chew))/ABS(COUNT(1) -2),0), -1) as avg_chew_habit").
 | 
	
		
			
				|  |  | -				Select("ROUND(AVG(intake),0) as avg_intake_habit").
 | 
	
		
			
				|  |  | -				Select("ROUND(AVG(inactive),0) as avg_inactive_habit").
 | 
	
		
			
				|  |  | -				Where("heat_date BETWEEN ? AND ?", before7DayDate, before1DayDate).
 | 
	
		
			
				|  |  | -				Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -				Where("neck_ring_number = ? AND frameid = ?", v.NeckRingNumber, v.Frameid).
 | 
	
		
			
				|  |  | -				Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina > ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | -				Group("neck_ring_number").First(weekHabitData).Error; err != nil {
 | 
	
		
			
				|  |  | -				zaplog.Error("WeeklyActiveAvgUpdate-1", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			// 累计24小时数值
 | 
	
		
			
				|  |  | -			sumHabitData := &SumHabit{}
 | 
	
		
			
				|  |  | -			if err = tx.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -				Select("neck_ring_number").
 | 
	
		
			
				|  |  | -				Select("IF(COUNT(1)>6, ROUND(AVG( h2.filter_rumina)*12,0), 0) as sum_rumina").
 | 
	
		
			
				|  |  | -				Select("IF(COUNT(1)>6, ROUND(AVG( h2.intake)*12,0), 0) as sum_intake").
 | 
	
		
			
				|  |  | -				Select("IF(COUNT(1)>6, ROUND(AVG( h2.inactive)*12,0), 0) as sum_inactive").
 | 
	
		
			
				|  |  | -				Select("IF(COUNT(1)>6, ROUND(AVG( h2.active)*12,0), 0) as sum_active").
 | 
	
		
			
				|  |  | -				Select("MAX(h2.change_filter) as sum_max_high").
 | 
	
		
			
				|  |  | -				Select("MIN(IF(change_filter > ?, change_filter, ?)) as sum_min_high", model.DefaultChangeFilter, model.InitChangeFilter).
 | 
	
		
			
				|  |  | -				Select("MIN( CASE WHEN filter_chew > ? THEN filter_chew WHEN filter_rumina >= ? THEN filter_rumina ELSE 0 END) as sum_min_chew", model.DefaultChangeFilter, model.DefaultRuminaFilter).
 | 
	
		
			
				|  |  | -				Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -				Where("heat_date BETWEEN ? AND ?", before1DayDate, beginDayDate).
 | 
	
		
			
				|  |  | -				Where("active_time BETWEEN ? AND ?", beginDayDate.Add(-23*time.Hour).Format(model.LayoutTime), beginDayDate.Format(model.LayoutTime)).
 | 
	
		
			
				|  |  | -				Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina >= ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | -				Where("neck_ring_number = ? AND frameid = ?", v.NeckRingNumber, v.Frameid).
 | 
	
		
			
				|  |  | -				Group("neck_ring_number").
 | 
	
		
			
				|  |  | -				First(sumHabitData).Error; err != nil {
 | 
	
		
			
				|  |  | -				zaplog.Error("WeeklyActiveAvgUpdate-2", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			// 变化百分比
 | 
	
		
			
				|  |  | -			if v.WeekHighHabit > 0 {
 | 
	
		
			
				|  |  | -				if v.FilterHigh-v.WeekHighHabit > 0 {
 | 
	
		
			
				|  |  | -					v.ChangeHigh = (v.FilterHigh - v.WeekHighHabit) / int32(float64(v.WeekHigh)*0.6+float64(v.WeekHighHabit)*0.2+float64(weeklyActive.Value)*0.2)
 | 
	
		
			
				|  |  | -				} else {
 | 
	
		
			
				|  |  | -					v.ChangeHigh = v.FilterHigh - v.WeekHighHabit/v.WeekHighHabit*100
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -				v.ChangeRumina = v.RuminaFilter - v.WeekRuminaHabit/v.WeekHighHabit*100
 | 
	
		
			
				|  |  | -				v.ChangeChew = v.FilterChew - v.WeekChewHabit/v.WeekHighHabit*100
 | 
	
		
			
				|  |  | -				if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -					Select("change_high", "change_rumina", "change_chew").
 | 
	
		
			
				|  |  | -					Where("id = ?", v.Id).
 | 
	
		
			
				|  |  | -					Updates(v).Error; err != nil {
 | 
	
		
			
				|  |  | -					return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			// 三天前的反刍和采食
 | 
	
		
			
				|  |  | -			before3DaysNeckActiveHabit := &model.NeckActiveHabit{}
 | 
	
		
			
				|  |  | -			before3DayDate := beginDayDate.AddDate(0, 0, -3).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | -			if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -				Select("sum_rumina", "sum_intake").
 | 
	
		
			
				|  |  | -				Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -				Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  | -				Where("heat_date = ?", before3DayDate).
 | 
	
		
			
				|  |  | -				Where("frameid = ? ", v.Frameid).
 | 
	
		
			
				|  |  | -				First(before3DaysNeckActiveHabit).Error; err != nil {
 | 
	
		
			
				|  |  | -				zaplog.Error("WeeklyActiveAvgUpdate-3", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | +		if weekHabitData.WeekRuminaHabit != 0 {
 | 
	
		
			
				|  |  | +			v.ChangeRumina = int32(math.Round(float64(v.FilterRumina-weekHabitData.WeekRuminaHabit) / float64(weekHabitData.WeekRuminaHabit) * 100))
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			v.ChangeRumina = 0
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if weekHabitData.WeekChewHabit != 0 {
 | 
	
		
			
				|  |  | +			v.ChangeChew = int32(math.Round(float64(v.FilterChew-weekHabitData.WeekChewHabit) / float64(weekHabitData.WeekChewHabit) * 100))
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			v.ChangeChew = 0
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			if err = tx.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -				Select("avg_high_habit", "avg_rumina_habit", "avg_chew_habit", "avg_intake_habit", "avg_inactive_habit").
 | 
	
		
			
				|  |  | -				Select("sum_rumina", "sum_intake", "sum_inactive", "sum_active", "sum_max_high", "sum_min_high", "sum_min_chew").
 | 
	
		
			
				|  |  | -				Select("change_high", "change_rumina", "change_chew", "sum_rumina_before_three_day", "sum_intake_before_three_day").
 | 
	
		
			
				|  |  | -				Where("id = ?", v.Id).
 | 
	
		
			
				|  |  | -				Updates(map[string]interface{}{
 | 
	
		
			
				|  |  | -					"week_high_habit":             weekHabitData.AvgHighHabit,
 | 
	
		
			
				|  |  | -					"week_rumina_habit":           weekHabitData.AvgRuminaHabit,
 | 
	
		
			
				|  |  | -					"week_chew_habit":             weekHabitData.AvgChewHabit,
 | 
	
		
			
				|  |  | -					"week_intake_habit":           weekHabitData.AvgIntakeHabit,
 | 
	
		
			
				|  |  | -					"week_inactive_habit":         weekHabitData.AvgIntakeHabit,
 | 
	
		
			
				|  |  | -					"sum_rumina":                  sumHabitData.SumRumina,
 | 
	
		
			
				|  |  | -					"sum_intake":                  sumHabitData.SumIntake,
 | 
	
		
			
				|  |  | -					"sum_inactive":                sumHabitData.SumInactive,
 | 
	
		
			
				|  |  | -					"sum_active":                  sumHabitData.SumActive,
 | 
	
		
			
				|  |  | -					"sum_max_high":                sumHabitData.SumMaxHigh,
 | 
	
		
			
				|  |  | -					"sum_min_high":                sumHabitData.SumMinHigh,
 | 
	
		
			
				|  |  | -					"sum_min_chew":                sumHabitData.SumMinChew,
 | 
	
		
			
				|  |  | -					"change_high":                 v.ChangeHigh,
 | 
	
		
			
				|  |  | -					"change_rumina":               v.ChangeRumina,
 | 
	
		
			
				|  |  | -					"change_chew":                 v.ChangeChew,
 | 
	
		
			
				|  |  | -					"sum_rumina_before_three_day": before3DaysNeckActiveHabit.SumRumina,
 | 
	
		
			
				|  |  | -					"sum_intake_before_three_day": before3DaysNeckActiveHabit.SumIntake,
 | 
	
		
			
				|  |  | -				}).Error; err != nil {
 | 
	
		
			
				|  |  | -				zaplog.Error("WeeklyActiveAvgUpdate-6", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | +		sumHabitData := e.FindSumHabitData(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid, xToDay)
 | 
	
		
			
				|  |  | +		before3DaysNeckActiveHabit := e.FindBefore3DaysNeckActiveHabit(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			zaplog.Info("WeeklyActiveAvgUpdate-7",
 | 
	
		
			
				|  |  | -				zap.Any("v", v),
 | 
	
		
			
				|  |  | -				zap.Any("xToday", xToday),
 | 
	
		
			
				|  |  | -				zap.Any("before3DaysNeckActiveHabit", before3DaysNeckActiveHabit),
 | 
	
		
			
				|  |  | -				zap.Any("sumHabitData", sumHabitData),
 | 
	
		
			
				|  |  | -				zap.Any("weekHabitData", weekHabitData),
 | 
	
		
			
				|  |  | -			)
 | 
	
		
			
				|  |  | +		// 更新过滤值
 | 
	
		
			
				|  |  | +		if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +			Select(
 | 
	
		
			
				|  |  | +				"filter_high", "filter_rumina", "filter_chew", "cow_id", "lact", "calving_age",
 | 
	
		
			
				|  |  | +				"week_high_habit", "week_rumina_habit", "week_chew_habit", "week_intake_habit", "week_inactive_habit",
 | 
	
		
			
				|  |  | +				"sum_rumina", "sum_intake", "sum_inactive", "sum_active", "sum_max_high", "sum_min_high", "sum_min_chew",
 | 
	
		
			
				|  |  | +				"change_high", "change_rumina", "change_chew", "before_three_sum_rumina", "before_three_sum_intake",
 | 
	
		
			
				|  |  | +			).Where("id = ?", v.Id).
 | 
	
		
			
				|  |  | +			Updates(map[string]interface{}{
 | 
	
		
			
				|  |  | +				"filter_high":             firstFilterData.FilterHigh,
 | 
	
		
			
				|  |  | +				"filter_rumina":           firstFilterData.FilterRumina,
 | 
	
		
			
				|  |  | +				"filter_chew":             firstFilterData.FilterChew,
 | 
	
		
			
				|  |  | +				"cow_id":                  cowInfo.Id,
 | 
	
		
			
				|  |  | +				"lact":                    cowInfo.Lact,
 | 
	
		
			
				|  |  | +				"calving_age":             cowInfo.CalvingAge,
 | 
	
		
			
				|  |  | +				"week_high_habit":         weekHabitData.WeekHighHabit,
 | 
	
		
			
				|  |  | +				"week_rumina_habit":       weekHabitData.WeekRuminaHabit,
 | 
	
		
			
				|  |  | +				"week_chew_habit":         weekHabitData.WeekChewHabit,
 | 
	
		
			
				|  |  | +				"week_intake_habit":       weekHabitData.WeekIntakeHabit,
 | 
	
		
			
				|  |  | +				"week_inactive_habit":     weekHabitData.WeekIntakeHabit,
 | 
	
		
			
				|  |  | +				"sum_rumina":              sumHabitData.SumRumina,
 | 
	
		
			
				|  |  | +				"sum_intake":              sumHabitData.SumIntake,
 | 
	
		
			
				|  |  | +				"sum_inactive":            sumHabitData.SumInactive,
 | 
	
		
			
				|  |  | +				"sum_active":              sumHabitData.SumActive,
 | 
	
		
			
				|  |  | +				"sum_max_high":            sumHabitData.SumMaxHigh,
 | 
	
		
			
				|  |  | +				"sum_min_high":            sumHabitData.SumMinHigh,
 | 
	
		
			
				|  |  | +				"sum_min_chew":            sumHabitData.SumMinChew,
 | 
	
		
			
				|  |  | +				"change_high":             v.ChangeHigh,
 | 
	
		
			
				|  |  | +				"change_rumina":           v.ChangeRumina,
 | 
	
		
			
				|  |  | +				"change_chew":             v.ChangeChew,
 | 
	
		
			
				|  |  | +				"before_three_sum_rumina": before3DaysNeckActiveHabit.SumRumina,
 | 
	
		
			
				|  |  | +				"before_three_sum_intake": before3DaysNeckActiveHabit.SumIntake,
 | 
	
		
			
				|  |  | +			}).Error; err != nil {
 | 
	
		
			
				|  |  | +			return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		return nil
 | 
	
		
			
				|  |  | -	}); err != nil {
 | 
	
		
			
				|  |  | -		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	zaplog.Info("WeeklyActiveAvgUpdate-Success", zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +	zaplog.Info("EntryUpdateActiveHabit-FilterUpdate-Success")
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -356,9 +425,9 @@ func (e *Entry) WeeklyActiveAvgUpdate(pastureId int64, xToday *XToday) (err erro
 | 
	
		
			
				|  |  |  func (e *Entry) SecondUpdateChangeFilter(pastureId int64, xToday *XToday) (err error) {
 | 
	
		
			
				|  |  |  	newChangeFilterList := make([]*ChangeFilterData, 0)
 | 
	
		
			
				|  |  |  	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -		Select("id,neck_ring_number,change_high,change_filter,rumina_filter,change_rumina,chew_filter,change_chew,heat_date,frameid").
 | 
	
		
			
				|  |  | -		Select("IF(lact = 0, 0.8, 1) as xlc_dis_count").
 | 
	
		
			
				|  |  | -		Where("id BETWEEN ? AND ?", xToday.XMin2Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Select("id", "neck_ring_number", "change_high", "change_filter", "rumina_filter", "change_rumina",
 | 
	
		
			
				|  |  | +			"chew_filter", "change_chew", "heat_date", "frameid", "IF(lact = 0, 0.8, 1) as xlc_dis_count").
 | 
	
		
			
				|  |  | +		Where("heat_date >= ?", time.Now().AddDate(0, 0, -2).Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  |  		Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  |  		Where("change_high > ?", MinChangeHigh).
 | 
	
	
		
			
				|  | @@ -430,8 +499,6 @@ func (e *Entry) SecondUpdateChangeFilter(pastureId int64, xToday *XToday) (err e
 | 
	
		
			
				|  |  |  		if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  			Select("change_filter", "rumina_filter", "chew_filter").
 | 
	
		
			
				|  |  |  			Where("id = ?", v.Id).
 | 
	
		
			
				|  |  | -			Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  | -			Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  |  			Updates(map[string]interface{}{
 | 
	
		
			
				|  |  |  				"change_filter": secondFilterData.ChangeFilter,
 | 
	
		
			
				|  |  |  				"rumina_filter": secondFilterData.RuminaFilter,
 | 
	
	
		
			
				|  | @@ -439,12 +506,8 @@ func (e *Entry) SecondUpdateChangeFilter(pastureId int64, xToday *XToday) (err e
 | 
	
		
			
				|  |  |  			}).Error; err != nil {
 | 
	
		
			
				|  |  |  			zaplog.Error("SecondUpdateChangeFilter-1", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		zaplog.Info("SecondUpdateChangeFilter",
 | 
	
		
			
				|  |  | -			zap.Any("secondFilterData", secondFilterData),
 | 
	
		
			
				|  |  | -			zap.Any("xToday", xToday),
 | 
	
		
			
				|  |  | -			zap.Any("v", v),
 | 
	
		
			
				|  |  | -		)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	zaplog.Info("SecondUpdateChangeFilter-Success")
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -454,16 +517,14 @@ func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, xToday *XToday) err
 | 
	
		
			
				|  |  |  	before7DayDate := beginDayDate.AddDate(0, 0, -7).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  |  	before1DayDate := beginDayDate.AddDate(0, 0, -1).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	activityVolumeList := make([]*crontab.ActivityVolume, 0)
 | 
	
		
			
				|  |  | -	activityVolumeMap := make(map[string]*crontab.ActivityVolume)
 | 
	
		
			
				|  |  | +	activityVolumeList := make([]*ActivityVolume, 0)
 | 
	
		
			
				|  |  | +	activityVolumeMap := make(map[string]*ActivityVolume)
 | 
	
		
			
				|  |  |  	if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -		Select("neck_ring_number").
 | 
	
		
			
				|  |  | -		Select("AVG(IF(change_filter>=60, 60, change_filter)) as avg_filter").
 | 
	
		
			
				|  |  | -		Select("ROUND(STD(IF(change_filter>=60, 60, change_filter))) as std_filter").
 | 
	
		
			
				|  |  | -		Select("COUNT(1) as nb").
 | 
	
		
			
				|  |  | +		Select("neck_ring_number", "AVG(IF(change_filter>=60, 60, change_filter)) as avg_filter",
 | 
	
		
			
				|  |  | +			"ROUND(STD(IF(change_filter>=60, 60, change_filter))) as std_filter", "COUNT(1) as nb").
 | 
	
		
			
				|  |  |  		Where("heat_date BETWEEN ? AND ?", before7DayDate, before1DayDate).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -		Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina >= ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | +		Where(e.DB.Where("high > ?", xToday.High).Or("rumina >= ?", xToday.Rumina)).
 | 
	
		
			
				|  |  |  		Where("active_time <= ?", beginDayDate.Add(-12*time.Hour).Format(model.LayoutTime)).
 | 
	
		
			
				|  |  |  		Where("change_filter > ?", MinChangeFilter).
 | 
	
		
			
				|  |  |  		Having("nb > ?", DefaultNb).
 | 
	
	
		
			
				|  | @@ -480,9 +541,10 @@ func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, xToday *XToday) err
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
 | 
	
		
			
				|  |  |  	if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -		Where("id BETWEEN ? AND ?", xToday.XMin2Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("id <= ?", xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("heat_date >= ?", before1DayDate).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -		Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina > ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | +		Where(e.DB.Where("high > ?", xToday.High).Or("rumina > ?", xToday.Rumina)).
 | 
	
		
			
				|  |  |  		Find(&neckActiveHabitList).Error; err != nil {
 | 
	
		
			
				|  |  |  		zaplog.Error("ActivityVolumeChanges-1", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
	
		
			
				|  | @@ -490,7 +552,7 @@ func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, xToday *XToday) err
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	for _, v := range neckActiveHabitList {
 | 
	
		
			
				|  |  |  		if filterCorrectMap, ok := activityVolumeMap[v.NeckRingNumber]; ok {
 | 
	
		
			
				|  |  | -			filterCorrect := model.DefaultFilterCorrect - int(math.Floor(float64(filterCorrectMap.AvgFilter)/3+float64(filterCorrectMap.StdFilter)/2))
 | 
	
		
			
				|  |  | +			filterCorrect := model.DefaultFilterCorrect - int(math.Floor(filterCorrectMap.AvgFilter/3+float64(filterCorrectMap.StdFilter)/2))
 | 
	
		
			
				|  |  |  			// 活动量校正系数
 | 
	
		
			
				|  |  |  			if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  				Where("id = ?", v.Id).
 | 
	
	
		
			
				|  | @@ -500,15 +562,10 @@ func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, xToday *XToday) err
 | 
	
		
			
				|  |  |  				continue
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		// 健康评分
 | 
	
		
			
				|  |  | -		if v.Score != 0 {
 | 
	
		
			
				|  |  | -			continue
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		cowScore := calculateScore(v)
 | 
	
		
			
				|  |  |  		if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  			Where("id = ?", v.Id).
 | 
	
		
			
				|  |  | -			Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  |  			Update("score", cowScore).Error; err != nil {
 | 
	
		
			
				|  |  |  			zaplog.Error("ActivityVolumeChanges-2", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  			continue
 | 
	
	
		
			
				|  | @@ -522,6 +579,11 @@ func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, xToday *XToday) err
 | 
	
		
			
				|  |  |  func (e *Entry) UpdateChangeAdJust(pastureId int64, xToday *XToday) error {
 | 
	
		
			
				|  |  |  	res := make([]*model.NeckRingBarChange, 0)
 | 
	
		
			
				|  |  |  	oneDayAgo := time.Now().AddDate(0, 0, -1).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | +	//SELECT h.neck_ring_number,h.heat_date, h.frameid, c.pen_id, c.pen_name, COUNT(*) as nb, ROUND(AVG(h.change_high)) as change_high,
 | 
	
		
			
				|  |  | +	//ROUND(AVG(h.change_filter)) as change_filter F
 | 
	
		
			
				|  |  | +	//ROM neck_active_habit as h JOIN cow as c ON h.neck_ring_number = c.neck_ring_number
 | 
	
		
			
				|  |  | +	//WHERE h.pasture_id = 1 AND h.heat_date >= '2025-01-16' AND h.cow_id >= 0
 | 
	
		
			
				|  |  | +	//GROUP BY h.heat_date, h.frameid, c.pen_id ORDER BY h.heat_date, h.frameid, c.pen_name
 | 
	
		
			
				|  |  |  	if err := e.DB.Table(fmt.Sprintf("%s as h", new(model.NeckActiveHabit).TableName())).
 | 
	
		
			
				|  |  |  		Select("h.neck_ring_number,h.heat_date, h.frameid, c.pen_id, c.pen_name, COUNT(*) as nb, ROUND(AVG(h.change_high)) as change_high, ROUND(AVG(h.change_filter)) as change_filter").
 | 
	
		
			
				|  |  |  		Joins("JOIN cow as c ON h.neck_ring_number = c.neck_ring_number").
 | 
	
	
		
			
				|  | @@ -538,7 +600,6 @@ func (e *Entry) UpdateChangeAdJust(pastureId int64, xToday *XToday) error {
 | 
	
		
			
				|  |  |  		if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  			Where("id > ?", xToday.LastMaxHabitId).
 | 
	
		
			
				|  |  |  			Where("heat_date = ?", v.HeatDate).
 | 
	
		
			
				|  |  | -			Where("heat_date >= ?", oneDayAgo).
 | 
	
		
			
				|  |  |  			Where("frameid = ?", v.FrameId).
 | 
	
		
			
				|  |  |  			Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  |  			Update("change_adjust", v.ChangeHigh).Error; err != nil {
 | 
	
	
		
			
				|  | @@ -548,7 +609,18 @@ func (e *Entry) UpdateChangeAdJust(pastureId int64, xToday *XToday) error {
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// 辅助函数来计算过滤值
 | 
	
		
			
				|  |  | +func (e *Entry) UpdateNeckRingOriginalIsShow(neckRingList *model.NeckActiveHabit) error {
 | 
	
		
			
				|  |  | +	if err := e.DB.Model(new(model.NeckRingOriginal)).
 | 
	
		
			
				|  |  | +		Where("neck_ring_number = ?", neckRingList.NeckRingNumber).
 | 
	
		
			
				|  |  | +		Where("active_date = ?", neckRingList.HeatDate).
 | 
	
		
			
				|  |  | +		Where("frameid IN (?)", util.FrameIds(neckRingList.Frameid)).
 | 
	
		
			
				|  |  | +		Update("is_show", pasturePb.IsShow_Ok).Error; err != nil {
 | 
	
		
			
				|  |  | +		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// computeIfPositiveElse 辅助函数来计算过滤值
 | 
	
		
			
				|  |  |  func computeIfPositiveElse(newValue, prevFilterValue float64, weightPrev, weightNew float64) float64 {
 | 
	
		
			
				|  |  |  	return math.Ceil((prevFilterValue * weightPrev) + (weightNew * newValue))
 | 
	
		
			
				|  |  |  }
 |