neck_ring_estrus_warning.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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(
  67. cowMap map[int64]*Cow,
  68. eventLogMap map[int64]string,
  69. matingWindowPeriodKind pasturePb.MatingWindowPeriod_Kind,
  70. matingWindowPeriodKindList []pasturePb.MatingWindowPeriod_Kind,
  71. ) []*pasturePb.EstrusItem {
  72. res := make([]*pasturePb.EstrusItem, 0)
  73. nowTime := time.Now().Local()
  74. for _, v := range n {
  75. cow, ok := cowMap[v.CowId]
  76. if !ok {
  77. cow = &Cow{Id: v.CowId}
  78. }
  79. lastBreedEventDetails := ""
  80. desc, ok := eventLogMap[cow.Id]
  81. if ok {
  82. lastBreedEventDetails = desc
  83. }
  84. pzHour := v.CalculatePzHour(cow.Lact)
  85. estrusInterval := int32(0)
  86. if v.LastTime != "" {
  87. lastTime, _ := util.TimeParseLocal(LayoutTime, v.LastTime)
  88. diff := pzHour.Sub(lastTime)
  89. estrusInterval = int32(diff.Hours() / 24)
  90. }
  91. optimumMatingStartTime := pzHour.Add(-4 * time.Hour)
  92. optimumMatingEndTime := pzHour.Add(4 * time.Hour)
  93. found := false
  94. if len(matingWindowPeriodKindList) > 0 && len(matingWindowPeriodKindList) <= 2 {
  95. for _, periodKind := range matingWindowPeriodKindList {
  96. if isIPeriod(periodKind, nowTime, optimumMatingStartTime, optimumMatingEndTime) {
  97. found = true
  98. break
  99. }
  100. }
  101. }
  102. if matingWindowPeriodKind > pasturePb.MatingWindowPeriod_Invalid {
  103. found = isIPeriod(matingWindowPeriodKind, nowTime, optimumMatingStartTime, optimumMatingEndTime)
  104. }
  105. if found {
  106. continue
  107. }
  108. firstTimeParseLocal, _ := util.TimeParseLocal(LayoutTime, v.FirstTime)
  109. afterAlarmTimeForHours := int32(nowTime.Sub(firstTimeParseLocal).Hours())
  110. postPeakTimeForHours := int32(0)
  111. if v.IsPeak == pasturePb.IsShow_Ok {
  112. dateTimeParseLocal, _ := util.TimeParseLocal(LayoutTime, v.DateTime)
  113. postPeakTimeForHours = int32(nowTime.Sub(dateTimeParseLocal).Hours())
  114. }
  115. data := &pasturePb.EstrusItem{
  116. Id: int32(v.Id),
  117. CowId: int32(v.CowId),
  118. EarNumber: v.EarNumber,
  119. PenId: cow.PenId,
  120. PenName: cow.PenName,
  121. MatingTimes: cow.MatingTimes,
  122. Lact: cow.Lact,
  123. CalvingAge: cow.CalvingAge,
  124. AbortionAge: cow.AbortionAge,
  125. OptimumMatingStartTime: optimumMatingStartTime.Format(LayoutTime),
  126. OptimumMatingEndTime: optimumMatingEndTime.Format(LayoutTime),
  127. LastBreedEventDetails: lastBreedEventDetails,
  128. Level: v.Level,
  129. EstrusInterval: estrusInterval,
  130. BestMatingTime: pzHour.Format(LayoutTime),
  131. EstrusStartTime: pzHour.Add(-8 * time.Hour).Format(LayoutTime),
  132. EstrusEndTime: pzHour.Add(8 * time.Hour).Format(LayoutTime),
  133. AfterAlarmTimeForHours: afterAlarmTimeForHours,
  134. PostPeakTimeForHours: postPeakTimeForHours,
  135. }
  136. res = append(res, data)
  137. }
  138. return res
  139. }
  140. func isIPeriod(periodKind pasturePb.MatingWindowPeriod_Kind, nowTime, optimumMatingStartTime, optimumMatingEndTime time.Time) bool {
  141. switch periodKind {
  142. case pasturePb.MatingWindowPeriod_Front:
  143. return !nowTime.Before(optimumMatingStartTime)
  144. case pasturePb.MatingWindowPeriod_Middle:
  145. return !(nowTime.After(optimumMatingStartTime) && nowTime.Before(optimumMatingEndTime))
  146. case pasturePb.MatingWindowPeriod_Behind:
  147. return !(nowTime.After(optimumMatingEndTime))
  148. default:
  149. return false
  150. }
  151. }
  152. const (
  153. Nb1 = 12
  154. Nb2 = 8
  155. MinNb1 = 10
  156. )
  157. type EstrusWarning struct {
  158. NeckRingEstrusId int64 `json:"neckRingEstrusId"`
  159. HighChange string `json:"highChange"`
  160. CowId int64 `json:"cowId"`
  161. DateTime string `json:"dateTime"`
  162. Nb1 int32 `json:"nb1"`
  163. Nb2 int32 `json:"nb2"`
  164. }