123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- package crontab
- import (
- "kpt-pasture/model"
- "time"
- pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
- "gitee.com/xuyiping_admin/pkg/logger/zaplog"
- "go.uber.org/zap"
- "gitee.com/xuyiping_admin/pkg/xerr"
- )
- const (
- MaxRuminaAdJust = 20
- XAdjust21 = 15
- XAdjust42 = 10
- RumtoHeat = 0.5
- MinCalvingAge = 20
- MinLact = 0
- NormalChangJust = 10
- )
- func (e *Entry) PastureUpdateCowEstrus() (err error) {
- pastureList := e.FindPastureList()
- if pastureList == nil || len(pastureList) == 0 {
- return nil
- }
- for _, pasture := range pastureList {
- if err = e.EntryCowEstrus(pasture.Id); err != nil {
- zaplog.Error("EntryCrontab", zap.Any("PastureUpdateCowEstrus", err), zap.Any("pasture", pasture))
- }
- zaplog.Error("PastureUpdateCowEstrus-success", zap.Any("pasture", pasture.Id))
- }
- return nil
- }
- func (e *Entry) EntryCowEstrus(pastureId int64) (err error) {
- activeLow, err := e.GetSystemConfigure(pastureId, model.ActiveLow)
- if err != nil {
- return xerr.WithStack(err)
- }
- activeLowValue := int64(activeLow.Value)
- activeMiddle, err := e.GetSystemConfigure(pastureId, model.ActiveMiddle)
- if err != nil {
- return xerr.WithStack(err)
- }
- activeMiddleValue := int64(activeMiddle.Value)
- activeHigh, err := e.GetSystemConfigure(pastureId, model.ActiveHigh)
- if err != nil {
- return xerr.WithStack(err)
- }
- activeHighValue := int64(activeHigh.Value)
- lastMaxEstrus, err := e.GetSystemConfigure(pastureId, model.MaxEstrus)
- if err != nil {
- return xerr.WithStack(err)
- }
- lastMaxEstrusId := int64(lastMaxEstrus.Value)
- zaplog.Info("EntryCowEstrus-001", zap.Any("lastMaxEstrusId", lastMaxEstrusId))
- currentMaxHabit := &model.NeckActiveHabit{}
- if err = e.DB.Model(new(model.NeckActiveHabit)).
- Where("id > ?", lastMaxEstrusId).
- Order("id desc").
- First(currentMaxHabit).Error; err != nil {
- return xerr.WithStack(err)
- }
- zaplog.Info("EntryCowEstrus-002", zap.Any("currentMaxHabit", currentMaxHabit))
- defer func() {
- if err == nil {
- e.DB.Model(new(model.SystemConfigure)).
- Where("name = ?", model.MaxEstrus).
- Update("value", currentMaxHabit.Id)
- }
- }()
- 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 ?", lastMaxEstrusId, currentMaxHabit.Id).
- First(xToday).Error; err != nil {
- return xerr.WithStack(err)
- }
- zaplog.Info("EntryCowEstrus-003", zap.Any("xToday", xToday))
- // 当前Id<=上次执行的id,则不执行
- if currentMaxHabit.Id <= int64(lastMaxEstrusId) {
- return nil
- }
- xToday.LastMaxHabitId = int64(lastMaxEstrusId)
- xToday.CurrMaxHabitId = currentMaxHabit.Id
- xToday.ActiveLow = int64(activeLowValue)
- xToday.ActiveMiddle = int64(activeMiddleValue)
- xToday.ActiveHigh = int64(activeHighValue)
- zaplog.Info("EntryCowEstrus-005", zap.Any("xToday", xToday))
- if err = e.CowEstrusWarning(xToday); err != nil {
- return xerr.WithStack(err)
- }
- zaplog.Info("EntryCowEstrus-006", zap.Any("xToday", xToday))
- return nil
- }
- func (e *Entry) CowEstrusWarning(xToday *XToday) error {
- startDate, err := time.Parse(model.LayoutDate2, xToday.XBegDate)
- if err != nil {
- return xerr.WithStack(err)
- }
- endDate, err := time.Parse(model.LayoutDate2, xToday.XEndDate)
- if err != nil {
- return xerr.WithStack(err)
- }
- for startDate.Format(model.LayoutDate2) <= endDate.Format(model.LayoutDate2) {
- neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
- if err = e.DB.Model(new(model.NeckActiveHabit)).
- Select("*,MAX(filter_high) as filter_high").
- Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
- Where("heat_date = ?", startDate.Format(model.LayoutDate2)).
- Where("cow_id > ?", 0).
- Where(e.DB.Where("calving_age > ?", MinCalvingAge).Or("lact = ?", MinLact)).
- Group("cow_id").
- Find(&neckActiveHabitList).
- Error; err != nil {
- return xerr.WithStack(err)
- }
- eventEstrusList := make([]*model.EventEstrus, 0)
- for _, v := range neckActiveHabitList {
- if ok := e.IsAdJustLow(xToday, v); ok {
- continue
- }
- cft := float32(0)
- if v.ChangeAdjust > 10 {
- cft = float32(v.ChangeFilter) - float32(v.ChangeAdjust) + 3
- } else {
- value := float32(0)
- switch {
- case v.RuminaFilter > MaxRuminaAdJust:
- value = float32(5)
- case v.RuminaFilter > 0:
- value = float32(v.RuminaFilter) * 0.25
- case v.RuminaFilter < -MaxRuminaAdJust:
- value = -MaxRuminaAdJust * RumtoHeat
- default:
- value = float32(v.RuminaFilter) * RumtoHeat
- }
- cft = float32(v.ChangeFilter)*float32(v.FilterCorrect)/100 - value
- }
- cowInfo := e.FindCowInfoByNeckRingNumber(v.NeckRingNumber)
- if cowInfo == nil {
- zaplog.Error("CowEstrusWarning", zap.Any("FindCowInfoByNeckRingNumber", err), zap.Any("NeckRingNumber", v.NeckRingNumber))
- continue
- }
- // 最近3天最大发情记录,小于该变化趋势的不再插入
- eventEstrus := e.GetBeforeThreeDaysCowEstrus(cowInfo.Id, startDate.AddDate(0, 0, -2).Format(model.LayoutTime))
- if eventEstrus.CowId != cowInfo.Id {
- if int32(cft) <= eventEstrus.PerTwentyFourHigh {
- continue
- }
- }
- // 判断最近50天内是否存在发情记录(发情等级>=2),如果18~25天@xadjust21,如果36~50天@xadjust42
- cowEstrus := e.GetTwoEstrus(cowInfo.Id, startDate.AddDate(0, 0, -100).Format(model.LayoutTime), startDate.AddDate(0, 0, -2).Format(model.LayoutTime))
- if cowEstrus.CowId == cowInfo.Id {
- activeDateTime, _ := time.Parse(model.LayoutTime, cowEstrus.ActiveDate)
- if activeDateTime.Unix() >= startDate.AddDate(0, 0, -25).Unix() && activeDateTime.Unix() <= startDate.AddDate(0, 0, -18).Unix() {
- cowEstrus.HadJust = XAdjust21
- }
- if activeDateTime.Unix() >= startDate.AddDate(0, 0, -50).Unix() && activeDateTime.Unix() <= startDate.AddDate(0, 0, -36).Unix() {
- cowEstrus.HadJust = XAdjust42
- }
- }
- if int32(cft)+cowEstrus.HadJust <= int32(xToday.ActiveLow) {
- continue
- }
- level := pasturePb.EstrusLevel_High
- if int32(cft)+cowEstrus.HadJust < int32(xToday.ActiveMiddle) {
- level = pasturePb.EstrusLevel_Low
- }
- if int32(cft)+cowEstrus.HadJust >= int32(xToday.ActiveHigh) {
- level = pasturePb.EstrusLevel_Middle
- }
- result := pasturePb.EstrusResult_Invalid
- if eventEstrus.Result == pasturePb.EstrusResult_Fail && eventEstrus.PerTwentyFourHigh > int32(cft)+cowEstrus.HadJust {
- result = pasturePb.EstrusResult_Fail
- }
- // todo 待定
- if result == pasturePb.EstrusResult_Invalid {
- result = pasturePb.EstrusResult_Correct
- }
- isShow := pasturePb.IsShow_Ok
- if cowInfo.IsPregnant == pasturePb.IsShow_Ok {
- isShow = pasturePb.IsShow_No
- }
- eventEstrusList = append(eventEstrusList, &model.EventEstrus{
- CowId: cowInfo.Id,
- Lact: cowInfo.Lact,
- ExposeEstrusType: pasturePb.ExposeEstrusType_Natural_Estrus,
- FilterHigh: v.FilterHigh,
- EstrusDate: v.ActiveTime,
- ActiveDate: v.ActiveTime,
- LastEstrusDate: cowEstrus.ActiveDate,
- Level: level,
- IsPeak: pasturePb.IsShow_No,
- PerTwentyFourHigh: int32(cft) + cowEstrus.HadJust,
- Result: result,
- IsShow: isShow,
- })
- }
- if len(eventEstrusList) > 0 {
- if err = e.DB.Create(eventEstrusList).Error; err != nil {
- zaplog.Error("CowEstrusWarning", zap.Any("eventEstrusList", eventEstrusList), zap.Any("err", err))
- }
- }
- startDate.AddDate(0, 0, 1)
- }
- return nil
- }
- // IsAdJustLow 是否低于最低活动量
- func (e *Entry) IsAdJustLow(xToday *XToday, habit *model.NeckActiveHabit) bool {
- ruminaAdJust := float64(0)
- switch {
- case habit.RuminaFilter > MaxRuminaAdJust:
- ruminaAdJust = 5
- case habit.RuminaFilter > 0:
- ruminaAdJust = float64(habit.RuminaFilter) * 0.25
- case habit.RuminaFilter < -MaxRuminaAdJust:
- ruminaAdJust = -MaxRuminaAdJust * RumtoHeat
- default:
- ruminaAdJust = float64(habit.RuminaFilter) * RumtoHeat
- }
- ruminaAdJustSum := int32(float64(habit.FilterCorrect)/100 - ruminaAdJust)
- isContinue := int32(0)
- activeLow := xToday.ActiveLow - XAdjust21
- if habit.ChangeFilter >= NormalChangJust {
- isContinue = habit.ChangeFilter - habit.ChangeAdjust + 3*ruminaAdJustSum
- } else {
- isContinue = habit.ChangeFilter * ruminaAdJustSum
- }
- if isContinue < int32(activeLow) {
- return true
- }
- return false
- }
|