|  | @@ -7,6 +7,8 @@ import (
 | 
	
		
			
				|  |  |  	"math"
 | 
	
		
			
				|  |  |  	"time"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	"gorm.io/gorm"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 | 
	
		
			
				|  |  |  	"go.uber.org/zap"
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -17,9 +19,9 @@ import (
 | 
	
		
			
				|  |  |  const (
 | 
	
		
			
				|  |  |  	MinChangeFilter = -99
 | 
	
		
			
				|  |  |  	MinRuminaFilter = -99
 | 
	
		
			
				|  |  | -	MinChewFilter   = -99
 | 
	
		
			
				|  |  |  	MinChangeHigh   = -99
 | 
	
		
			
				|  |  |  	DefaultNb       = 30
 | 
	
		
			
				|  |  | +	DefaultScore    = 100
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (e *Entry) PastureUpdateActiveHabit() {
 | 
	
	
		
			
				|  | @@ -63,7 +65,7 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 获取这段执行数据内最大日期和最小日期
 | 
	
		
			
				|  |  | -	xToday := &crontab.XToday{}
 | 
	
		
			
				|  |  | +	xToday := &XToday{}
 | 
	
		
			
				|  |  |  	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  		Select(`MIN(heat_date) as x_beg_date, MAX(heat_date) as x_end_date`).
 | 
	
		
			
				|  |  |  		Where("id BETWEEN ? AND ?", lastMaxHabitId, currentMaxHabit.Id).
 | 
	
	
		
			
				|  | @@ -71,10 +73,10 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	xToday.LastMaxHabitId = lastMaxHabitId
 | 
	
		
			
				|  |  | -	xToday.CurrMaxHabitId = currentMaxHabit.Id
 | 
	
		
			
				|  |  | +	xToday.LastMaxHabitId = lastMaxHabitId     // 上次执行的id
 | 
	
		
			
				|  |  | +	xToday.CurrMaxHabitId = currentMaxHabit.Id // 本次执行的id
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	minHeatDateParse, err := time.Parse(model.LayoutDate2, xToday.XBegDate)
 | 
	
		
			
				|  |  | +	minHeatDateParse, err := time.Parse(model.LayoutDate2, xToday.XBegDate) // 开始日期
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -89,6 +91,7 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	defer func() {
 | 
	
		
			
				|  |  |  		// 更新最后一次执行的id值
 | 
	
		
			
				|  |  |  		if err == nil {
 | 
	
	
		
			
				|  | @@ -135,30 +138,58 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 | 
	
		
			
				|  |  |  	xToday.ActiveLowest = activeLowest.Value
 | 
	
		
			
				|  |  |  	xToday.RuminaLowest = ruminaLowest.Value
 | 
	
		
			
				|  |  |  	// 更新活动滤波
 | 
	
		
			
				|  |  | -	if err = e.FilterUpdate(pastureId, xToday); err != nil {
 | 
	
		
			
				|  |  | -		zaplog.Error("EntryUpdateActiveHabit", zap.Any("FilterUpdate", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | -		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	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))
 | 
	
		
			
				|  |  | -		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err = e.SecondUpdateChangeFilter(pastureId, xToday); err != nil {
 | 
	
		
			
				|  |  | +		zaplog.Error("EntryUpdateActiveHabit", zap.Any("SecondUpdateChangeFilter", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if err = e.ActivityVolumeChanges(pastureId, xToday); err != nil {
 | 
	
		
			
				|  |  |  		zaplog.Error("EntryUpdateActiveHabit", zap.Any("ActivityVolumeChanges", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | -		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | +		Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  | +		Updates(map[string]interface{}{
 | 
	
		
			
				|  |  | +			"change_filter": model.DefaultChangeFilter,
 | 
	
		
			
				|  |  | +			"rumina_filter": model.DefaultRuminaFilter,
 | 
	
		
			
				|  |  | +			"chew_filter":   model.DefaultChewFilter,
 | 
	
		
			
				|  |  | +		}).Error; err != nil {
 | 
	
		
			
				|  |  | +		zaplog.Error("EntryUpdateActiveHabit", zap.Any("change_filter", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | +		Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("change_filter < ?", 0).
 | 
	
		
			
				|  |  | +		Where("filter_correct < ?", model.DefaultFilterCorrect).
 | 
	
		
			
				|  |  | +		Updates(map[string]interface{}{
 | 
	
		
			
				|  |  | +			"filter_correct": model.DefaultFilterCorrect,
 | 
	
		
			
				|  |  | +		}).Error; err != nil {
 | 
	
		
			
				|  |  | +		zaplog.Error("EntryUpdateActiveHabit", zap.Any("filter_correct", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 插入群体校正表
 | 
	
		
			
				|  |  | +	if err = e.UpdateChangeAdJust(pastureId, xToday); err != nil {
 | 
	
		
			
				|  |  | +		zaplog.Error("EntryUpdateActiveHabit", zap.Any("UpdateChangeAdJust", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// FilterUpdate 更新活动滤波
 | 
	
		
			
				|  |  | -func (e *Entry) FilterUpdate(pastureId int64, xToDay *crontab.XToday) error {
 | 
	
		
			
				|  |  | +// FirstFilterUpdate 首次更新活动滤波
 | 
	
		
			
				|  |  | +func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) error {
 | 
	
		
			
				|  |  |  	newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
 | 
	
		
			
				|  |  |  	if err := e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  |  		Where(e.DB.Where("change_filter = ?", model.InitChangeFilter).Or("is_max_time = ?", pasturePb.IsShow_Ok)).
 | 
	
		
			
				|  |  | -		Where(e.DB.Where("high >= ?", xToDay.ActiveLowest).Or("rumina >= ?", xToDay.RuminaLowest)).
 | 
	
		
			
				|  |  |  		Order("neck_ring_number,id").
 | 
	
		
			
				|  |  |  		Find(&newNeckActiveHabitList).Error; err != nil {
 | 
	
		
			
				|  |  |  		return xerr.WithStack(err)
 | 
	
	
		
			
				|  | @@ -167,6 +198,10 @@ func (e *Entry) FilterUpdate(pastureId int64, xToDay *crontab.XToday) error {
 | 
	
		
			
				|  |  |  	var filterValues = make(map[string]*model.NeckActiveHabit)
 | 
	
		
			
				|  |  |  	// 活动量滤波
 | 
	
		
			
				|  |  |  	for _, v := range newNeckActiveHabitList {
 | 
	
		
			
				|  |  | +		// 活动量过低牛只不参与计算
 | 
	
		
			
				|  |  | +		if v.High < int32(xToDay.ActiveLowest) || v.Rumina < int32(xToDay.RuminaLowest) {
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  		prev, ok := filterValues[v.NeckRingNumber]
 | 
	
		
			
				|  |  |  		if !ok {
 | 
	
		
			
				|  |  |  			if v.FilterHigh <= 0 {
 | 
	
	
		
			
				|  | @@ -203,132 +238,152 @@ func (e *Entry) FilterUpdate(pastureId int64, xToDay *crontab.XToday) error {
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (e *Entry) WeeklyActiveAvgUpdate(pastureId int64, xToday *crontab.XToday) error {
 | 
	
		
			
				|  |  | -	beginDayDate, err := time.Parse(model.LayoutDate2, xToday.XBegDate)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	before7DayDate := beginDayDate.AddDate(0, 0, -7).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | -	before1DayDate := beginDayDate.AddDate(0, 0, -1).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +// 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)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	xframeId := int64(0)
 | 
	
		
			
				|  |  | -	maxXframeId := int64(11)
 | 
	
		
			
				|  |  | -	xStartDate, _ := time.Parse(model.LayoutDate2, xToday.XBegDate)
 | 
	
		
			
				|  |  | -	xEndDate, _ := time.Parse(model.LayoutDate2, xToday.XEndDate)
 | 
	
		
			
				|  |  | -	for xStartDate.Format(model.LayoutDate2) < xEndDate.Format(model.LayoutDate2) || (xStartDate == xEndDate && xframeId <= maxXframeId) {
 | 
	
		
			
				|  |  | -		//  时间点周平均
 | 
	
		
			
				|  |  | -		AvgHabitList := make([]*crontab.AvgHabit, 0)
 | 
	
		
			
				|  |  | -		if err = e.DB.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("id BETWEEN ? AND ?", xToday.XMin7Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -			Where("heat_date BETWEEN ? AND ?", before7DayDate, before1DayDate).
 | 
	
		
			
				|  |  | -			Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	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.XMin2Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  |  			Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  |  			Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  |  			Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina > ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | -			Group("neck_ring_number").
 | 
	
		
			
				|  |  | -			Find(&AvgHabitList).Error; err != nil {
 | 
	
		
			
				|  |  | +			Group("neck_ring_number,frameid").
 | 
	
		
			
				|  |  | +			Find(&neckActiveHabitList).Error; err != nil {
 | 
	
		
			
				|  |  | +			zaplog.Error("WeeklyActiveAvgUpdate-0", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  			return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		for _, v := range AvgHabitList {
 | 
	
		
			
				|  |  | -			if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -				Select("avg_high_habit", "avg_rumina_habit", "avg_chew_habit", "avg_intake_habit", "avg_inactive_habit").
 | 
	
		
			
				|  |  | -				Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  | -				Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -				Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | -				Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  | -				Where("heat_date = ?", xStartDate).
 | 
	
		
			
				|  |  | -				Updates(v).Error; err != nil {
 | 
	
		
			
				|  |  | -				return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +		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)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			avgHabitData := &crontab.AvgHabit{}
 | 
	
		
			
				|  |  | +			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("id BETWEEN ? AND ?", xToday.XMin7Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +				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)).
 | 
	
		
			
				|  |  | +				First(avgHabitData).Error; err != nil {
 | 
	
		
			
				|  |  | +				zaplog.Error("WeeklyActiveAvgUpdate-1", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		// 累计24小时数值
 | 
	
		
			
				|  |  | -		sumHabitList := make([]*crontab.SumHabit, 0)
 | 
	
		
			
				|  |  | -		if err = e.DB.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, 0)) as sum_min_high", MinChangeFilter).
 | 
	
		
			
				|  |  | -			Select("MIN( CASE WHEN filter_chew > ? THEN filter_chew WHEN filter_rumina >= ? THEN filter_rumina ELSE 0 END) as sum_min_chew", MinChangeFilter, MinRuminaFilter).
 | 
	
		
			
				|  |  | -			Where("id BETWEEN ? AND ?", xToday.XMin2Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -			Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -			Where("heat_date BETWEEN ? AND ?", xStartDate.AddDate(0, 0, -1).Format(model.LayoutDate2), xStartDate.Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  | -			Where("created_at BETWEEN ? AND ?", xStartDate.Add(-23*time.Hour).Unix(), xStartDate.Unix()).
 | 
	
		
			
				|  |  | -			Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina >= ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | -			Group("neck_ring_number").
 | 
	
		
			
				|  |  | -			Find(&sumHabitList).Error; err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +			// 累计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("id BETWEEN ? AND ?", xToday.XMin2Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +				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).
 | 
	
		
			
				|  |  | +				First(sumHabitData).Error; err != nil {
 | 
	
		
			
				|  |  | +				zaplog.Error("WeeklyActiveAvgUpdate-2", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			// 变化百分比
 | 
	
		
			
				|  |  | +			if v.AvgHighHabit > 0 {
 | 
	
		
			
				|  |  | +				if v.FilterHigh-v.AvgHighHabit > 0 {
 | 
	
		
			
				|  |  | +					v.ChangeHigh = (v.FilterHigh - v.AvgHighHabit) / int32(float64(v.WeekHigh)*0.6+float64(v.AvgHighHabit)*0.2+float64(weeklyActive.Value)*0.2)
 | 
	
		
			
				|  |  | +				} else {
 | 
	
		
			
				|  |  | +					v.ChangeHigh = v.FilterHigh - v.AvgHighHabit/v.AvgHighHabit*100
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +				v.ChangeRumina = v.RuminaFilter - v.AvgRuminaHabit/v.AvgHighHabit*100
 | 
	
		
			
				|  |  | +				v.ChangeChew = v.FilterChew - v.AvgChewHabit/v.AvgHighHabit*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)
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		for _, v := range sumHabitList {
 | 
	
		
			
				|  |  | +			// 三天前的反刍和采食
 | 
	
		
			
				|  |  | +			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", "sum_inactive", "sum_active", "sum_max_high", "sum_min_high", "sum_min_chew").
 | 
	
		
			
				|  |  | +				Select("sum_rumina", "sum_intake").
 | 
	
		
			
				|  |  | +				Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  |  				Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  | -				Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -				Where("heat_date = ?", xStartDate.Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  | -				Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | -				Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  | -				Updates(v).Error; err != nil {
 | 
	
		
			
				|  |  | -				return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +				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))
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		// 变化百分比
 | 
	
		
			
				|  |  | -		changeHabitList := make([]*model.NeckActiveHabit, 0)
 | 
	
		
			
				|  |  | -		if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -			Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -			Where("heat_date = ?", xStartDate.Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  | -			Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | -			Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -			Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  | -			Where("avg_high_habit > ?", 0).
 | 
	
		
			
				|  |  | -			Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina >= ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | -			Find(&changeHabitList).Error; err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		for _, v := range changeHabitList {
 | 
	
		
			
				|  |  | -			if v.FilterHigh-v.AvgHighHabit > 0 {
 | 
	
		
			
				|  |  | -				v.ChangeHigh = (v.FilterHigh - v.AvgHighHabit) / int32(float64(v.WeekHigh)*0.6+float64(v.AvgHighHabit)*0.2+float64(weeklyActive.Value)*0.2)
 | 
	
		
			
				|  |  | +			cowId := int64(0)
 | 
	
		
			
				|  |  | +			Lact := int32(0)
 | 
	
		
			
				|  |  | +			calvingAge := int64(0)
 | 
	
		
			
				|  |  | +			cow := e.GetCowInfoByNeckRingNumber(pastureId, v.NeckRingNumber)
 | 
	
		
			
				|  |  | +			if cow != nil {
 | 
	
		
			
				|  |  | +				cowId = cow.Id
 | 
	
		
			
				|  |  | +				Lact = cow.Lact
 | 
	
		
			
				|  |  | +				calvingAge = cow.CalvingAge
 | 
	
		
			
				|  |  |  			} else {
 | 
	
		
			
				|  |  | -				v.ChangeHigh = v.FilterHigh - v.AvgHighHabit/v.AvgHighHabit*100
 | 
	
		
			
				|  |  | +				zaplog.Error("WeeklyActiveAvgUpdate-4", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			v.ChangeRumina = v.RuminaFilter - v.AvgRuminaHabit/v.AvgHighHabit*100
 | 
	
		
			
				|  |  | -			v.ChangeChew = v.FilterChew - v.AvgChewHabit/v.AvgHighHabit*100
 | 
	
		
			
				|  |  | -			if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -				Select("change_high", "change_rumina", "change_chew").
 | 
	
		
			
				|  |  | +			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", "cow_id", "lact", "calving_age").
 | 
	
		
			
				|  |  | +				Select("sum_rumina_before_three_day,sum_intake_before_three_day").
 | 
	
		
			
				|  |  |  				Where("id = ?", v.Id).
 | 
	
		
			
				|  |  | -				Updates(v).Error; err != nil {
 | 
	
		
			
				|  |  | -				return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +				Updates(map[string]interface{}{
 | 
	
		
			
				|  |  | +					"cow_id":                      cowId,
 | 
	
		
			
				|  |  | +					"lact":                        Lact,
 | 
	
		
			
				|  |  | +					"calving_age":                 calvingAge,
 | 
	
		
			
				|  |  | +					"avg_high_habit":              avgHabitData.AvgHighHabit,
 | 
	
		
			
				|  |  | +					"avg_rumina_habit":            avgHabitData.AvgRuminaHabit,
 | 
	
		
			
				|  |  | +					"avg_chew_habit":              avgHabitData.AvgChewHabit,
 | 
	
		
			
				|  |  | +					"avg_intake_habit":            avgHabitData.AvgIntakeHabit,
 | 
	
		
			
				|  |  | +					"avg_inactive_habit":          avgHabitData.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))
 | 
	
		
			
				|  |  | +				continue
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if xframeId == maxXframeId {
 | 
	
		
			
				|  |  | -			xframeId = 0
 | 
	
		
			
				|  |  | -			xStartDate = xStartDate.AddDate(0, 0, 1)
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			xframeId++
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}); err != nil {
 | 
	
		
			
				|  |  | +		return xerr.WithStack(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	zaplog.Info("EntryUpdateActiveHabit-WeeklyActiveAvgUpdate-Success")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// UpdateChangeFilter  变化趋势滤波
 | 
	
		
			
				|  |  | -func (e *Entry) UpdateChangeFilter(pastureId int64, xToday *crontab.XToday) (err error) {
 | 
	
		
			
				|  |  | +// SecondUpdateChangeFilter 第二次更新变化趋势滤波
 | 
	
		
			
				|  |  | +func (e *Entry) SecondUpdateChangeFilter(pastureId int64, xToday *XToday) (err error) {
 | 
	
		
			
				|  |  |  	xRuminaDisc, err := e.GetSystemConfigure2(pastureId, model.XRuminaDisc)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return err
 | 
	
	
		
			
				|  | @@ -340,7 +395,7 @@ func (e *Entry) UpdateChangeFilter(pastureId int64, xToday *crontab.XToday) (err
 | 
	
		
			
				|  |  |  	newChangeFilterList := make([]*crontab.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").
 | 
	
		
			
				|  |  | -		Select("IF(lact=0,0.8,1) as xlc_dis_count").
 | 
	
		
			
				|  |  | +		Select("IF(lact = 0, 0.8, 1) as xlc_dis_count").
 | 
	
		
			
				|  |  |  		Where("id BETWEEN ? AND ?", xToday.XMin2Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  |  		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  |  		Where(e.DB.Where("change_filter = ?", model.InitChangeFilter).Or("is_max_time = ?", pasturePb.IsShow_Ok)).
 | 
	
	
		
			
				|  | @@ -407,114 +462,194 @@ func (e *Entry) UpdateChangeFilter(pastureId int64, xToday *crontab.XToday) (err
 | 
	
		
			
				|  |  |  			Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  |  			Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  |  			Updates(v).Error; err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +			zaplog.Error("SecondUpdateChangeFilter-1", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		filterValues[v.NeckRingNumber] = v
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // ActivityVolumeChanges 计算活动量变化趋势校正值(活跃度校正)
 | 
	
		
			
				|  |  | -func (e *Entry) ActivityVolumeChanges(pastureId int64, xToday *crontab.XToday) error {
 | 
	
		
			
				|  |  | -	currDate, _ := time.Parse(model.LayoutDate2, xToday.XBegDate)
 | 
	
		
			
				|  |  | -	XEndDateTime, _ := time.Parse(model.LayoutDate2, xToday.XEndDate)
 | 
	
		
			
				|  |  | -	xframeId := int64(0)
 | 
	
		
			
				|  |  | -	maxXframeId := int64(11)
 | 
	
		
			
				|  |  | -	dayTimes := int64(1)
 | 
	
		
			
				|  |  | -	for currDate.Format(model.LayoutDate2) < XEndDateTime.Format(model.LayoutDate2) || (currDate == XEndDateTime && xframeId <= maxXframeId) {
 | 
	
		
			
				|  |  | -		activityVolumeList := make([]*crontab.ActivityVolume, 0)
 | 
	
		
			
				|  |  | -		activeTime := fmt.Sprintf("%s %02d:00:00", currDate.Format(model.LayoutDate2), xframeId*2)
 | 
	
		
			
				|  |  | -		activeTimeParse, err := time.Parse(model.LayoutTime, activeTime)
 | 
	
		
			
				|  |  | -		if err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		if dayTimes == 1 {
 | 
	
		
			
				|  |  | -			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").
 | 
	
		
			
				|  |  | -				Where("id BETWEEN ? AND ?", xToday.XMin7Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -				Where("heat_date BETWEEN ? AND ?", currDate.AddDate(0, 0, -7).Format(model.LayoutDate2), currDate.AddDate(0, 0, -1).Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  | -				Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | -				Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | -				Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina >= ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | -				Where("active_time <= ?", activeTimeParse.Add(-12*time.Hour)).
 | 
	
		
			
				|  |  | -				Where("change_filter > ?", MinChangeFilter).
 | 
	
		
			
				|  |  | -				Having("nb > ?", DefaultNb).
 | 
	
		
			
				|  |  | -				Group("neck_ring_number").
 | 
	
		
			
				|  |  | -				Find(&activityVolumeList).Error; err != nil {
 | 
	
		
			
				|  |  | -				return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +func (e *Entry) ActivityVolumeChanges(pastureId int64, xToday *XToday) error {
 | 
	
		
			
				|  |  | +	beginDayDate, err := time.Parse(model.LayoutDate2, xToday.XBegDate)
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return xerr.WithStack(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)
 | 
	
		
			
				|  |  | +	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").
 | 
	
		
			
				|  |  | +		Where("id BETWEEN ? AND ?", xToday.XMin7Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("heat_date BETWEEN ? AND ?", before7DayDate, before1DayDate).
 | 
	
		
			
				|  |  | +		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | +		Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina >= ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | +		Where("active_time <= ?", beginDayDate.Add(-12*time.Hour).Format(model.LayoutTime)).
 | 
	
		
			
				|  |  | +		Where("change_filter > ?", MinChangeFilter).
 | 
	
		
			
				|  |  | +		Having("nb > ?", DefaultNb).
 | 
	
		
			
				|  |  | +		Group("neck_ring_number").
 | 
	
		
			
				|  |  | +		Find(&activityVolumeList).Error; err != nil {
 | 
	
		
			
				|  |  | +		zaplog.Error("ActivityVolumeChanges-0", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if len(activityVolumeList) > 0 {
 | 
	
		
			
				|  |  |  		for _, v := range activityVolumeList {
 | 
	
		
			
				|  |  | -			filterCorrect := model.DefaultFilterCorrect - int(math.Floor(float64(v.AvgFilter)/3+float64(v.StdFilter)/2))
 | 
	
		
			
				|  |  | +			activityVolumeMap[v.NeckRingNumber] = v
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
 | 
	
		
			
				|  |  | +	if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +		Where("id BETWEEN ? AND ?", xToday.XMin2Id, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | +		Where("pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | +		Where(e.DB.Where("high > ?", xToday.ActiveLowest).Or("rumina > ?", xToday.RuminaLowest)).
 | 
	
		
			
				|  |  | +		Find(&neckActiveHabitList).Error; err != nil {
 | 
	
		
			
				|  |  | +		zaplog.Error("ActivityVolumeChanges-1", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +		return xerr.WithStack(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))
 | 
	
		
			
				|  |  | +			v.FilterCorrect = int32(filterCorrect)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			// 活动量校正系数
 | 
	
		
			
				|  |  |  			if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | +				Where("id = ?", v.Id).
 | 
	
		
			
				|  |  |  				Where("neck_ring_number = ?", v.NeckRingNumber).
 | 
	
		
			
				|  |  | -				Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -				Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | -				Where("head_date = ?", currDate.Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  |  				Update("filter_correct", filterCorrect).Error; err != nil {
 | 
	
		
			
				|  |  | -				return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +				zaplog.Error("ActivityVolumeChanges-2", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +				continue
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		/*n := 0
 | 
	
		
			
				|  |  | -		if n <= 10 {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			// todo
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			n += 2
 | 
	
		
			
				|  |  | -		}*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		zaplog.Info("ActivityVolumeChanges",
 | 
	
		
			
				|  |  | -			zap.Any("xToday", xToday),
 | 
	
		
			
				|  |  | -			zap.Any("currDate", currDate.Format(model.LayoutDate2)),
 | 
	
		
			
				|  |  | -			zap.Any("xframeId", xframeId),
 | 
	
		
			
				|  |  | -			zap.Any("activityVolumeList", activityVolumeList),
 | 
	
		
			
				|  |  | -		)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -			Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -			Where("heat_date = ?", currDate.Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  | -			Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | -			Where("change_filter = ?", model.InitChangeFilter).
 | 
	
		
			
				|  |  | -			Updates(map[string]interface{}{
 | 
	
		
			
				|  |  | -				"change_filter":  MinChangeFilter,
 | 
	
		
			
				|  |  | -				"rumina_filter":  MinRuminaFilter,
 | 
	
		
			
				|  |  | -				"chew_filter":    MinChewFilter,
 | 
	
		
			
				|  |  | -				"filter_correct": model.DefaultFilterCorrect,
 | 
	
		
			
				|  |  | -			}).Error; err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +		// 健康评分
 | 
	
		
			
				|  |  | +		if v.Score != 0 {
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		if xframeId == maxXframeId {
 | 
	
		
			
				|  |  | -			xframeId = 0
 | 
	
		
			
				|  |  | -			currDate = currDate.AddDate(0, 0, 1)
 | 
	
		
			
				|  |  | -			dayTimes = 1
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			xframeId++
 | 
	
		
			
				|  |  | -			dayTimes++
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		cow := e.GetCowInfoByNeckRingNumber(v.PastureId, v.NeckRingNumber)
 | 
	
		
			
				|  |  | +		if cow == nil {
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		/*// 更新评分
 | 
	
		
			
				|  |  | -		newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
 | 
	
		
			
				|  |  | +		cowScore := calculateScore(v)
 | 
	
		
			
				|  |  |  		if err = e.DB.Model(new(model.NeckActiveHabit)).
 | 
	
		
			
				|  |  | -			Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 | 
	
		
			
				|  |  | -			Where("heat_date = ?", currDate.Format(model.LayoutDate2)).
 | 
	
		
			
				|  |  | -			Where("frameid = ?", xframeId).
 | 
	
		
			
				|  |  | -			Where("score = ?", 0).
 | 
	
		
			
				|  |  | -			Find(&newNeckActiveHabitList).Error; err != nil {
 | 
	
		
			
				|  |  | -			return xerr.WithStack(err)
 | 
	
		
			
				|  |  | -		}*/
 | 
	
		
			
				|  |  | -		// todo 待开发
 | 
	
		
			
				|  |  | +			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
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	zaplog.Info("EntryUpdateActiveHabit-ActivityVolumeChanges-Success")
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// UpdateChangeAdJust 更新群体校正数据
 | 
	
		
			
				|  |  | +func (e *Entry) UpdateChangeAdJust(pastureId int64, xToday *XToday) error {
 | 
	
		
			
				|  |  | +	res := make([]*model.NeckRingBarChange, 0)
 | 
	
		
			
				|  |  | +	oneDayAgo := time.Now().AddDate(0, 0, -1).Format(model.LayoutDate2)
 | 
	
		
			
				|  |  | +	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").
 | 
	
		
			
				|  |  | +		Where("h.pasture_id = ?", pastureId).
 | 
	
		
			
				|  |  | +		Where("h.heat_date >= ?", oneDayAgo).
 | 
	
		
			
				|  |  | +		Where("h.cow_id >= ?", 0).
 | 
	
		
			
				|  |  | +		Group("h.heat_date, h.frameid, c.pen_id").
 | 
	
		
			
				|  |  | +		Order("h.heat_date, h.frameid, c.pen_name").
 | 
	
		
			
				|  |  | +		Find(&res).Error; err != nil {
 | 
	
		
			
				|  |  | +		return xerr.WithStack(err)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for _, v := range res {
 | 
	
		
			
				|  |  | +		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 {
 | 
	
		
			
				|  |  | +			zaplog.Error("UpdateChangeAdJust-1", zap.Any("error", err), zap.Any("xToday", xToday))
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // 辅助函数来计算过滤值
 | 
	
		
			
				|  |  |  func computeIfPositiveElse(newValue, prevFilterValue float64, weightPrev, weightNew float64) float64 {
 | 
	
		
			
				|  |  |  	return math.Ceil((prevFilterValue * weightPrev) + (weightNew * newValue))
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 计算 score 的逻辑
 | 
	
		
			
				|  |  | +func calculateScore(habit *model.NeckActiveHabit) int {
 | 
	
		
			
				|  |  | +	// 第一部分逻辑
 | 
	
		
			
				|  |  | +	var part1 float64
 | 
	
		
			
				|  |  | +	switch {
 | 
	
		
			
				|  |  | +	case (habit.CalvingAge <= 1 && habit.Lact >= 1) ||
 | 
	
		
			
				|  |  | +		(habit.CalvingAge >= 2 && habit.CalvingAge <= 13 && (habit.SumRumina+habit.SumIntake) == 0) ||
 | 
	
		
			
				|  |  | +		((habit.Lact == 0 || habit.CalvingAge >= 14) && habit.ChangeFilter == -99):
 | 
	
		
			
				|  |  | +		part1 = -199
 | 
	
		
			
				|  |  | +	case habit.CalvingAge >= 2 && habit.CalvingAge <= 13:
 | 
	
		
			
				|  |  | +		part1 = math.Min((float64(habit.SumRumina+habit.SumIntake)-(100+math.Min(7, float64(habit.CalvingAge))*60))/10*2, 0)
 | 
	
		
			
				|  |  | +	case habit.ChangeFilter > -99:
 | 
	
		
			
				|  |  | +		part1 = math.Min(0, math.Min(getValueOrDefault(float64(habit.ChangeFilter), 0), getValueOrDefault(float64(habit.SumMinHigh), 0)))*0.2 +
 | 
	
		
			
				|  |  | +			math.Min(0, math.Min(getValueOrDefault(float64(habit.ChangeFilter), 0), getValueOrDefault(float64(habit.SumMinChew), 0)))*0.2 +
 | 
	
		
			
				|  |  | +			getRuminaSumIntakeSumScore(float64(habit.SumRumina+habit.SumIntake)) + getAdditionalScore(habit)
 | 
	
		
			
				|  |  | +	default:
 | 
	
		
			
				|  |  | +		part1 = -299
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 第二部分逻辑
 | 
	
		
			
				|  |  | +	var part2 float64
 | 
	
		
			
				|  |  | +	switch {
 | 
	
		
			
				|  |  | +	case habit.FirmwareVersion%100 >= 52:
 | 
	
		
			
				|  |  | +		part2 = 1
 | 
	
		
			
				|  |  | +	case habit.FirmwareVersion%100 >= 30 && habit.FirmwareVersion%100 <= 43:
 | 
	
		
			
				|  |  | +		part2 = 0.8
 | 
	
		
			
				|  |  | +	default:
 | 
	
		
			
				|  |  | +		part2 = 0.6
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 最终 score
 | 
	
		
			
				|  |  | +	return DefaultScore + int(math.Floor(part1*part2))
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 获取值或默认值
 | 
	
		
			
				|  |  | +func getValueOrDefault(value, defaultValue float64) float64 {
 | 
	
		
			
				|  |  | +	if value > -99 {
 | 
	
		
			
				|  |  | +		return value
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return defaultValue
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 计算累计反刍得分
 | 
	
		
			
				|  |  | +func getRuminaSumIntakeSumScore(sum float64) float64 {
 | 
	
		
			
				|  |  | +	switch {
 | 
	
		
			
				|  |  | +	case sum < 80:
 | 
	
		
			
				|  |  | +		return -30
 | 
	
		
			
				|  |  | +	case sum < 180:
 | 
	
		
			
				|  |  | +		return -20
 | 
	
		
			
				|  |  | +	case sum < 280:
 | 
	
		
			
				|  |  | +		return -10
 | 
	
		
			
				|  |  | +	default:
 | 
	
		
			
				|  |  | +		return 0
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 计算额外得分
 | 
	
		
			
				|  |  | +func getAdditionalScore(habit *model.NeckActiveHabit) float64 {
 | 
	
		
			
				|  |  | +	var score float64
 | 
	
		
			
				|  |  | +	if (habit.SumRumina+habit.SumIntake < 280 || habit.SumMinHigh+habit.SumMinChew < -50) && habit.SumMaxHigh > 50 {
 | 
	
		
			
				|  |  | +		score += 10
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if habit.ChangeFilter < -30 && habit.ChangeFilter <= habit.SumMinHigh && habit.ChewFilter < -30 && habit.ChewFilter <= habit.SumMinChew {
 | 
	
		
			
				|  |  | +		score -= 5
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return score
 | 
	
		
			
				|  |  | +}
 |