123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- package crontab
- import (
- "kpt-pasture/model"
- "kpt-pasture/util"
- "math"
- "time"
- pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
- "gitee.com/xuyiping_admin/pkg/xerr"
- "gitee.com/xuyiping_admin/pkg/logger/zaplog"
- "go.uber.org/zap"
- )
- // HealthWarning 健康预警 create_jbq_update_2024
- func (e *Entry) HealthWarning(pastureId int64, processIds []int64) {
- newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
- if err := e.DB.Model(new(model.NeckActiveHabit)).
- Where("pasture_id = ?", pastureId).
- Where("id IN (?)", processIds).
- Where("score BETWEEN ? AND ?", model.MinScore, model.MaxScore).
- Order("neck_ring_number,heat_date,frameid").
- Find(&newNeckActiveHabitList).Error; err != nil {
- zaplog.Error("HealthWarning", zap.Any("error", err), zap.Any("processIds", processIds))
- }
- var (
- lastCowID int64 = 0
- lastHeatDate string = "2001-01-01"
- lastScore int32 = 100
- healthWarningList []*model.NeckRingHealth
- )
- for _, habit := range newNeckActiveHabitList {
- if habit.ChangeFilter <= -99 {
- habit.ChangeFilter = 0
- }
- if habit.ChewFilter <= -99 {
- habit.ChewFilter = 0
- }
- if habit.SumMinHigh <= -99 {
- habit.SumMinHigh = 0
- }
- if habit.SumMaxHigh <= -99 {
- habit.SumMaxHigh = 0
- }
- if habit.SumMinChew <= -99 {
- habit.SumMinChew = 0
- }
- sumChew := habit.SumRumina + habit.SumIntake
- chew3dago := habit.BeforeThreeSumRumina + habit.BeforeThreeSumIntake
- isWorse := 1
- if habit.CowId == lastCowID && habit.HeatDate == lastHeatDate && habit.Score >= lastScore {
- isWorse = 0
- }
- lastCowID = habit.CowId
- lastHeatDate = habit.HeatDate
- lastScore = habit.Score
- if isWorse == 1 {
- newHealthWarning := model.NewNeckRingHealth(habit, sumChew, chew3dago)
- healthWarningList = append(healthWarningList, newHealthWarning)
- }
- }
- if len(healthWarningList) > 0 {
- e.updateNeckRingHealth(pastureId, healthWarningList)
- }
- }
- func (e *Entry) updateNeckRingHealth(pastureId int64, healthWarningList []*model.NeckRingHealth) {
- for _, v := range healthWarningList {
- startAt := util.TimeParseLocalUnix(v.HeatDate)
- endAt := util.TimeParseLocalEndUnix(v.HeatDate)
- isMove := e.isEventCowLog(pastureId, v.CowId, startAt, endAt, pasturePb.EventType_Transfer_Ben)
- if isMove {
- v.IsTransferGroup = pasturePb.IsShow_Ok
- }
- isDryMilk := e.isEventCowLog(pastureId, v.CowId, startAt, endAt, pasturePb.EventType_Dry_Milk)
- if isDryMilk {
- v.IsDryMilk = pasturePb.IsShow_Ok
- }
- isImmunization := e.isEventCowLog(pastureId, v.CowId, startAt, endAt, pasturePb.EventType_Immunication)
- if isImmunization {
- v.IsImmunization = pasturePb.IsShow_Ok
- }
- }
- zaplog.Info("HealthWarning", zap.Any("healthWarningList", healthWarningList))
- if err := e.DB.Model(new(model.NeckRingHealth)).Create(&healthWarningList).Error; err != nil {
- zaplog.Error("HealthWarning", zap.Any("error", err), zap.Any("healthWarningList", healthWarningList))
- }
- }
- func (e *Entry) isEventCowLog(pastureId int64, CowId int64, startAt, endAt int64, eventType pasturePb.EventType_Kind) bool {
- var count int64
- eventCowLog := &model.EventCowLog{CowId: CowId}
- if err := e.DB.Table(eventCowLog.TableName()).
- Where("pasture_id = ?", pastureId).
- Where("cow_id = ?", CowId).
- Where("event_at BETWEEN ? AND ?", startAt, endAt).
- Where("event_type = ?", eventType).
- Count(&count).Error; err != nil {
- return false
- }
- return count > 0
- }
- func (e *Entry) NeckRingHealthWarning() error {
- pastureList := e.FindPastureList()
- if pastureList == nil || len(pastureList) == 0 {
- return nil
- }
- for _, pasture := range pastureList {
- e.DB.Model(new(model.NeckRingHealthWarning)).
- Where("pasture_id = ?", pasture.Id).
- Delete(new(model.NeckRingHealthWarning))
- if err := e.UpdateNeckRingHealth(pasture.Id); err != nil {
- zaplog.Error("NeckRingHealthWarning",
- zap.Any("UpdateNeckRingHealth", err),
- zap.Any("pasture", pasture),
- )
- }
- }
- return nil
- }
- func (e *Entry) UpdateNeckRingHealth(pastureId int64) error {
- neckRingConfigureList, err := e.FindSystemNeckRingConfigure(pastureId)
- if err != nil {
- return xerr.WithStack(err)
- }
- healthValue := int32(0)
- for _, v := range neckRingConfigureList {
- if v.Name != model.HealthWarning {
- continue
- }
- healthValue = int32(v.Value)
- }
- newNeckRingHealthWarningList, err := e.FindNewNeckRingHealthWarning(pastureId, healthValue)
- if err != nil {
- return xerr.WithStack(err)
- }
- if len(newNeckRingHealthWarningList) > 0 {
- if err = e.DB.Model(new(model.NeckRingHealthWarning)).
- Create(&newNeckRingHealthWarningList).Error; err != nil {
- zaplog.Error("UpdateNeckRingHealth",
- zap.Any("error", err),
- zap.Any("newNeckRingHealthWarningList", newNeckRingHealthWarningList),
- )
- }
- }
- return nil
- }
- func calculateNewScore(data *model.NeckRingHealth) int32 {
- otherScore := int32(0)
- otherScore += calculateMilkFilterScore(data.FilterMilk, data.MaxHigh)
- if data.IsTransferGroup == pasturePb.IsShow_Ok {
- otherScore += 3
- }
- if data.IsDryMilk == pasturePb.IsShow_Ok {
- otherScore += 5
- }
- if data.IsImmunization == pasturePb.IsShow_Ok {
- otherScore += 12
- }
- return data.Score + otherScore
- }
- func calculateMilkFilterScore(milkFilter int32, maxHigh int32) int32 {
- // 处理NULL值,默认为0
- milkFilterValue := int32(0)
- if milkFilter != 0 {
- milkFilterValue = milkFilter
- }
- // 计算系数:如果maxHigh>50则为0.5,否则为1
- coefficient := 1.0
- if maxHigh > 50 {
- coefficient = 0.5
- }
- // 计算中间值:milkFilterValue * 0.3 * coefficient
- intermediateValue := float64(milkFilterValue) * 0.3 * coefficient
- // 四舍五入
- roundedValue := math.Round(intermediateValue)
- // 取最小值(roundedValue和0中的较小值)
- result := int32(math.Min(roundedValue, 0))
- return result
- }
- func (e *Entry) FindNewNeckRingHealthWarning(pastureId int64, healthValue int32) ([]*model.NeckRingHealthWarning, error) {
- nowTime := time.Now().Local()
- //endTime := nowTime.Format(model.LayoutDate2)
- startTime := nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
- neckRingHealthList := make([]*model.NeckRingHealth, 0)
- if err := e.DB.Model(new(model.NeckRingHealth)).
- Select(`MAX(id) AS id,heat_date,neck_ring_number,cow_id,score,max_high,created_at,min_high,min_chew,
- min_intake,sum_chew,before_three_sum_chew`).
- Where("pasture_id = ?", pastureId).
- Where("heat_date >= ?", startTime).
- Group("neck_ring_number").
- Find(&neckRingHealthList).Error; err != nil {
- return nil, xerr.WithStack(err)
- }
- newNeckRingHealthWarningList := make([]*model.NeckRingHealthWarning, 0)
- for _, v := range neckRingHealthList {
- if v.HeatDate == "" {
- continue
- }
- cowInfo, err := e.GetCowById(pastureId, v.CowId)
- if err != nil || cowInfo == nil {
- continue
- }
- newScore := calculateNewScore(v)
- zaplog.Info("calculateNewScore",
- zap.Any("newScore", newScore),
- zap.Any("v", v),
- zap.Any("healthValue", healthValue),
- zap.Any("cowInfo", cowInfo),
- )
- if newScore > healthValue {
- continue
- }
- if e.HistoryNeckRingHealthWarning(pastureId, cowInfo.NeckRingNumber, v.HeatDate) {
- continue
- }
- if e.FindNeckRingError(pastureId, cowInfo.NeckRingNumber) {
- continue
- }
- newNeckRingHealthWarning := model.NewNeckRingHealthWarning(pastureId, v, cowInfo, newScore)
- zaplog.Info("newNeckRingHealthWarning",
- zap.Any("newNeckRingHealthWarning", newNeckRingHealthWarning),
- zap.Any("pastureId", pastureId),
- zap.Any("neckRingHealth", v),
- zap.Any("cowInfo", cowInfo),
- zap.Any("newScore", newScore),
- )
- newNeckRingHealthWarningList = append(newNeckRingHealthWarningList, newNeckRingHealthWarning)
- }
- return newNeckRingHealthWarningList, nil
- }
- func (e *Entry) HistoryNeckRingHealthWarning(pastureId int64, neckRingNumber string, heatDate string) bool {
- var count int64
- if err := e.DB.Model(new(model.NeckRingHealthWarning)).
- Where("pasture_id = ?", pastureId).
- Where("neck_ring_number = ?", neckRingNumber).
- Where("heat_date = ?", heatDate).
- Where("is_show = ?", pasturePb.IsShow_Ok).
- Count(&count).Error; err != nil {
- return false
- }
- return count > 0
- }
- func (e *Entry) FindNeckRingError(pastureId int64, neckRingNumber string) bool {
- var count int64
- if err := e.DB.Model(new(model.NeckRing)).
- Where("pasture_id = ?", pastureId).
- Where("neck_ring_number = ?", neckRingNumber).
- Where("status = ?", pasturePb.IsShow_No).
- Where("error_kind = ?", pasturePb.NeckRingNumberError_Suspected_Fall_Off).
- Count(&count).Error; err != nil {
- return false
- }
- return count > 0
- }
|