neck_ring_health.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package crontab
  2. import (
  3. "kpt-pasture/model"
  4. "kpt-pasture/util"
  5. "math"
  6. "time"
  7. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  8. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  9. "go.uber.org/zap"
  10. )
  11. // HealthWarning 健康预警 create_jbq_update_2024
  12. func (e *Entry) HealthWarning(pastureId int64, processIds []int64) {
  13. healthWarningList := make([]*model.NeckRingHealth, 0)
  14. sqlQuery := `SELECT aa.pasture_id,aa.cow_id,aa.ear_number,aa.neck_ring_number,aa.lact,aa.calving_age,aa.heat_date,aa.frameid,aa.active_time,
  15. aa.change_filter,aa.chew_filter,aa.sum_chew,aa.sum_inactive,aa.before_three_sum_chew,aa.min_high,aa.max_high,aa.min_chew,aa.score
  16. FROM (
  17. SELECT h.id,h.cow_id,h.pasture_id,h.ear_number,h.neck_ring_number,h.calving_age,h.heat_date,h.frameid,h.lact,
  18. IF(h.change_filter>-99, h.change_filter, 0) AS change_filter,
  19. IF(h.filter_chew>-99, h.filter_chew, 0) AS chew_filter,
  20. (h.sum_rumina +h.sum_intake) AS sum_chew,
  21. h.sum_inactive,
  22. (h.before_three_sum_rumina +h.before_three_sum_intake) AS before_three_sum_chew,
  23. IF(h.sum_min_high>-99, h.sum_min_high, 0) AS min_high,
  24. IF(h.sum_max_high>-99, h.sum_max_high, 0) AS max_high,
  25. IF(h.sum_min_chew>-99, h.sum_min_chew, 0) AS min_chew,
  26. h.score,h.active_time,
  27. IF(h.cow_id=@cow AND h.heat_date=@date AND h.score>=@score, 0, 1) is_worse, @cow:=h.cow_id, @date:=h.heat_date, @score:=h.score
  28. FROM neck_active_habit h, (SELECT @cow:=0, @date:='2001-01-01', @score:=100) aaa
  29. WHERE h.id IN ?
  30. AND h.score BETWEEN ? AND ?
  31. AND h.pasture_id = ?
  32. ) aa WHERE aa.is_worse = ?
  33. ORDER BY aa.id;`
  34. if err := e.DB.Raw(sqlQuery, processIds, model.MinScore, model.MaxScore, pastureId, pasturePb.IsShow_Ok).
  35. Find(&healthWarningList).Error; err != nil {
  36. zaplog.Error("HealthWarning", zap.Any("error", err), zap.Any("processIds", processIds))
  37. }
  38. if len(healthWarningList) > 0 {
  39. e.updateNeckRingHealth(pastureId, healthWarningList)
  40. }
  41. }
  42. func (e *Entry) updateNeckRingHealth(pastureId int64, healthWarningList []*model.NeckRingHealth) {
  43. for _, v := range healthWarningList {
  44. if ok := e.CalculateNeckRingData(pastureId, v.CowId); !ok {
  45. continue
  46. }
  47. startAt := util.TimeParseLocalUnix(v.HeatDate)
  48. endAt := util.TimeParseLocalEndUnix(v.HeatDate)
  49. isMove := e.isEventCowLog(pastureId, v.CowId, startAt, endAt, pasturePb.EventType_Transfer_Ben)
  50. if isMove {
  51. v.IsTransferGroup = pasturePb.IsShow_Ok
  52. } else {
  53. v.IsTransferGroup = pasturePb.IsShow_No
  54. }
  55. isDryMilk := e.isEventCowLog(pastureId, v.CowId, startAt, endAt, pasturePb.EventType_Dry_Milk)
  56. if isDryMilk {
  57. v.IsDryMilk = pasturePb.IsShow_Ok
  58. } else {
  59. v.IsDryMilk = pasturePb.IsShow_No
  60. }
  61. isImmunization := e.isEventCowLog(pastureId, v.CowId, startAt, endAt, pasturePb.EventType_Immunication)
  62. if isImmunization {
  63. v.IsImmunization = pasturePb.IsShow_Ok
  64. } else {
  65. v.IsImmunization = pasturePb.IsShow_No
  66. }
  67. v.IsShow = pasturePb.IsShow_Ok
  68. v.IsWorse = pasturePb.IsShow_Invalid
  69. v.CheckResult = pasturePb.CheckResult_Pending
  70. }
  71. zaplog.Info("HealthWarning", zap.Any("healthWarningList", healthWarningList))
  72. if err := e.DB.Model(new(model.NeckRingHealth)).
  73. Create(&healthWarningList).Error; err != nil {
  74. zaplog.Error("HealthWarning", zap.Any("error", err), zap.Any("healthWarningList", healthWarningList))
  75. }
  76. }
  77. func (e *Entry) isEventCowLog(pastureId int64, CowId int64, startAt, endAt int64, eventType pasturePb.EventType_Kind) bool {
  78. var count int64
  79. eventCowLog := &model.EventCowLog{CowId: CowId}
  80. if err := e.DB.Table(eventCowLog.TableName()).
  81. Where("pasture_id = ?", pastureId).
  82. Where("cow_id = ?", CowId).
  83. Where("event_at BETWEEN ? AND ?", startAt, endAt).
  84. Where("event_type = ?", eventType).
  85. Count(&count).Error; err != nil {
  86. return false
  87. }
  88. return count > 0
  89. }
  90. // CalculateNeckRingData 判断牛只脖环数据是否大于3天
  91. func (e *Entry) CalculateNeckRingData(pastureId, cowId int64) bool {
  92. var count int64
  93. before3DaysDate := time.Now().AddDate(0, 0, -3).Local().Format(model.LayoutDate2)
  94. if err := e.DB.Model(new(model.NeckActiveHabit)).
  95. Where("pasture_id = ?", pastureId).
  96. Where("cow_id = ?", cowId).
  97. Where("heat_date = ?", before3DaysDate).
  98. Count(&count).Error; err != nil {
  99. return false
  100. }
  101. if count > 12 {
  102. return true
  103. }
  104. return false
  105. }
  106. func calculateNewScore(data *model.NeckRingHealth) int32 {
  107. otherScore := int32(0)
  108. otherScore += calculateMilkFilterScore(data.FilterMilk, data.MaxHigh)
  109. if data.IsTransferGroup == pasturePb.IsShow_Ok {
  110. otherScore += 3
  111. }
  112. if data.IsDryMilk == pasturePb.IsShow_Ok {
  113. otherScore += 5
  114. }
  115. if data.IsImmunization == pasturePb.IsShow_Ok {
  116. otherScore += 12
  117. }
  118. return data.Score + otherScore
  119. }
  120. func calculateMilkFilterScore(milkFilter int32, maxHigh int32) int32 {
  121. // 处理NULL值,默认为0
  122. milkFilterValue := int32(0)
  123. if milkFilter != 0 {
  124. milkFilterValue = milkFilter
  125. }
  126. // 计算系数:如果maxHigh>50则为0.5,否则为1
  127. coefficient := 1.0
  128. if maxHigh > 50 {
  129. coefficient = 0.5
  130. }
  131. // 计算中间值:milkFilterValue * 0.3 * coefficient
  132. intermediateValue := float64(milkFilterValue) * 0.3 * coefficient
  133. // 四舍五入
  134. roundedValue := math.Round(intermediateValue)
  135. // 取最小值(roundedValue和0中的较小值)
  136. result := int32(math.Min(roundedValue, 0))
  137. return result
  138. }