neck_ring_estrus_warning.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package model
  2. import (
  3. "kpt-pasture/util"
  4. "time"
  5. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  6. )
  7. type NeckRingEstrusWarning struct {
  8. Id int64 `json:"id"`
  9. NeckRingEstrusId int64 `json:"neckRingEstrusId"`
  10. PastureId int64 `json:"pastureId"`
  11. CowId int64 `json:"cowId"`
  12. EarNumber string `json:"earNumber"`
  13. NeckRingNumber string `json:"neckRingNumber"`
  14. FirstTime string `json:"firstTime"`
  15. DateTime string `json:"dateTime"`
  16. LastTime string `json:"lastTime"`
  17. IsPeak pasturePb.IsShow_Kind `json:"isPeak"`
  18. WarningKind pasturePb.Warning_Kind `json:"warningKind"`
  19. Level pasturePb.EstrusLevel_Kind `json:"level"`
  20. HighChange string `json:"highChange"`
  21. IsShow pasturePb.IsShow_Kind `json:"isShow"`
  22. CreatedAt int64 `json:"createdAt"`
  23. UpdatedAt int64 `json:"updatedAt"`
  24. }
  25. func (n *NeckRingEstrusWarning) TableName() string {
  26. return "neck_ring_estrus_warning"
  27. }
  28. func NewNeckRingEstrusWarning(
  29. neckRingEstrusId, pastureId, cowId int64,
  30. earNumber, neckRingNumber, firstTime, dateTime, lastTime string,
  31. warningKind pasturePb.Warning_Kind,
  32. level pasturePb.EstrusLevel_Kind,
  33. ) *NeckRingEstrusWarning {
  34. return &NeckRingEstrusWarning{
  35. NeckRingEstrusId: neckRingEstrusId,
  36. PastureId: pastureId,
  37. CowId: cowId,
  38. EarNumber: earNumber,
  39. NeckRingNumber: neckRingNumber,
  40. FirstTime: firstTime,
  41. DateTime: dateTime,
  42. LastTime: lastTime,
  43. WarningKind: warningKind,
  44. Level: level,
  45. IsShow: pasturePb.IsShow_Ok,
  46. }
  47. }
  48. // CalculatePzHour 计算最佳配置时间
  49. func (n *NeckRingEstrusWarning) CalculatePzHour(lact int32) time.Time {
  50. var pzHour time.Time
  51. dateTime, _ := util.TimeParseLocal(LayoutTime, n.DateTime)
  52. firstTime, _ := util.TimeParseLocal(LayoutTime, n.FirstTime)
  53. // 条件判断
  54. if n.IsPeak == pasturePb.IsShow_Ok || dateTime.Sub(firstTime).Hours() >= 8 {
  55. pzHour = dateTime.Add(8 * time.Hour) // v.datetime + INTERVAL 8 HOUR
  56. } else {
  57. pzHour = firstTime.Add(16 * time.Hour) // v.firsttime + INTERVAL 16 HOUR
  58. }
  59. // 胎次调整
  60. if lact >= 3 {
  61. pzHour = pzHour.Add(-1 * time.Hour) // 减去 1 小时
  62. }
  63. return pzHour
  64. }
  65. type NeckRingEstrusWarningSlice []*NeckRingEstrusWarning
  66. func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[int64]string, matingWindowPeriodKind pasturePb.MatingWindowPeriod_Kind) []*pasturePb.EstrusItem {
  67. res := make([]*pasturePb.EstrusItem, 0)
  68. nowTime := time.Now().Local()
  69. for _, v := range n {
  70. cow, ok := cowMap[v.CowId]
  71. if !ok {
  72. cow = &Cow{Id: v.CowId}
  73. }
  74. lastBreedEventDetails := ""
  75. desc, ok := eventLogMap[cow.Id]
  76. if ok {
  77. lastBreedEventDetails = desc
  78. }
  79. pzHour := v.CalculatePzHour(cow.Lact)
  80. estrusInterval := int32(0)
  81. if v.LastTime != "" {
  82. lastTime, _ := util.TimeParseLocal(LayoutTime, v.LastTime)
  83. diff := pzHour.Sub(lastTime)
  84. estrusInterval = int32(diff.Hours() / 24)
  85. }
  86. optimumMatingStartTime := pzHour.Add(-4 * time.Hour)
  87. optimumMatingEndTime := pzHour.Add(4 * time.Hour)
  88. switch matingWindowPeriodKind {
  89. case pasturePb.MatingWindowPeriod_Front:
  90. if !nowTime.Before(optimumMatingStartTime) {
  91. continue
  92. }
  93. case pasturePb.MatingWindowPeriod_Middle:
  94. if !(nowTime.After(optimumMatingStartTime) && nowTime.Before(optimumMatingEndTime)) {
  95. continue
  96. }
  97. case pasturePb.MatingWindowPeriod_Behind:
  98. if !nowTime.After(optimumMatingEndTime) {
  99. continue
  100. }
  101. }
  102. firstTimeParseLocal, _ := util.TimeParseLocal(LayoutTime, v.FirstTime)
  103. afterAlarmTimeForHours := int32(nowTime.Sub(firstTimeParseLocal).Hours())
  104. postPeakTimeForHours := int32(0)
  105. if v.IsPeak == pasturePb.IsShow_Ok {
  106. dateTimeParseLocal, _ := util.TimeParseLocal(LayoutTime, v.DateTime)
  107. postPeakTimeForHours = int32(nowTime.Sub(dateTimeParseLocal).Hours())
  108. }
  109. data := &pasturePb.EstrusItem{
  110. Id: int32(v.Id),
  111. CowId: int32(v.CowId),
  112. EarNumber: v.EarNumber,
  113. PenId: cow.PenId,
  114. PenName: cow.PenName,
  115. MatingTimes: cow.MatingTimes,
  116. Lact: cow.Lact,
  117. CalvingAge: cow.CalvingAge,
  118. AbortionAge: cow.AbortionAge,
  119. OptimumMatingStartTime: optimumMatingStartTime.Format(LayoutTime),
  120. OptimumMatingEndTime: optimumMatingEndTime.Format(LayoutTime),
  121. LastBreedEventDetails: lastBreedEventDetails,
  122. Level: v.Level,
  123. EstrusInterval: estrusInterval,
  124. BestMatingTime: pzHour.Format(LayoutTime),
  125. EstrusStartTime: pzHour.Add(-8 * time.Hour).Format(LayoutTime),
  126. EstrusEndTime: pzHour.Add(8 * time.Hour).Format(LayoutTime),
  127. AfterAlarmTimeForHours: afterAlarmTimeForHours,
  128. PostPeakTimeForHours: postPeakTimeForHours,
  129. }
  130. res = append(res, data)
  131. }
  132. return res
  133. }
  134. const (
  135. Nb1 = 12
  136. Nb2 = 8
  137. MinNb1 = 10
  138. )
  139. type EstrusWarning struct {
  140. NeckRingEstrusId int64 `json:"neckRingEstrusId"`
  141. HighChange string `json:"highChange"`
  142. CowId int64 `json:"cowId"`
  143. DateTime string `json:"dateTime"`
  144. Nb1 int32 `json:"nb1"`
  145. Nb2 int32 `json:"nb2"`
  146. }