neck_active_habit.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package model
  2. import (
  3. "fmt"
  4. "kpt-pasture/util"
  5. "math"
  6. "strconv"
  7. "strings"
  8. "time"
  9. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  10. )
  11. const (
  12. InitChangeFilter = -10000
  13. DefaultChangeFilter = -99
  14. DefaultRuminaFilter = -99
  15. DefaultChewFilter = -99
  16. DefaultFilterCorrect = 100
  17. DefaultWeeklyActive = 1500
  18. )
  19. type NeckActiveHabit struct {
  20. Id int64 `json:"id"`
  21. PastureId int64 `json:"pastureId"`
  22. NeckRingNumber string `json:"neckRingNumber"`
  23. CowId int64 `json:"cowId"`
  24. Lact int32 `json:"lact"`
  25. CalvingAge int32 `json:"calvingAge"`
  26. ActiveTime string `json:"activeTime"`
  27. Frameid int32 `json:"frameid"`
  28. HeatDate string `json:"heatDate"`
  29. Rumina int32 `json:"rumina"`
  30. Intake int32 `json:"intake"`
  31. Inactive int32 `json:"inactive"`
  32. Gasp int32 `json:"gasp"`
  33. Other int32 `json:"other"`
  34. High int32 `json:"high"`
  35. Active int32 `json:"active"`
  36. FilterHigh int32 `json:"filterHigh"`
  37. FilterRumina int32 `json:"filterRumina"`
  38. FilterChew int32 `json:"filterChew"`
  39. WeekHigh int32 `json:"weekHigh"`
  40. WeekHighHabit int32 `json:"weekHighHabit"`
  41. WeekRuminaHabit int32 `json:"weekRuminaHabit"`
  42. WeekIntakeHabit int32 `json:"weekIntakeHabit"`
  43. WeekChewHabit int32 `json:"weekChewHabit"`
  44. WeekInactiveHabit int32 `json:"weekInactiveHabit"`
  45. WeekOtherHabit int32 `json:"weekOtherHabit"`
  46. ChangeHigh int32 `json:"changeHigh"`
  47. ChangeRumina int32 `json:"changeRumina"`
  48. ChangeChew int32 `json:"changeChew"`
  49. ChangeAdjust int32 `json:"changeAdjust"`
  50. ChangeFilter int32 `json:"changeFilter"`
  51. RuminaFilter int32 `json:"ruminaFilter"`
  52. ChewFilter int32 `json:"chewFilter"`
  53. FilterCorrect int32 `json:"filterCorrect"`
  54. SumRumina int32 `json:"sumRumina"`
  55. SumIntake int32 `json:"sumIntake"`
  56. SumInactive int32 `json:"sumInactive"`
  57. SumActive int32 `json:"sumActive"`
  58. SumMinHigh int32 `json:"sumMinHigh"`
  59. SumMaxHigh int32 `json:"sumMaxHigh"`
  60. SumMinChew int32 `json:"SumMinChew"`
  61. BeforeThreeSumRumina int32 `json:"beforeThreeSumRumina"`
  62. BeforeThreeSumIntake int32 `json:"beforeThreeSumIntake"`
  63. Score int32 `json:"score"`
  64. IsMaxTime pasturePb.IsShow_Kind `json:"isMaxTime"`
  65. IsShow pasturePb.IsShow_Kind `json:"isShow"`
  66. RecordCount int32 `json:"recordCount"`
  67. FirmwareVersion int32 `json:"firmwareVersion"`
  68. CreatedAt int64 `json:"createdAt"`
  69. UpdatedAt int64 `json:"updatedAt"`
  70. }
  71. func (n *NeckActiveHabit) TableName() string {
  72. return "neck_active_habit"
  73. }
  74. func NewNeckActiveHabit(data *NeckRingOriginalMerge) *NeckActiveHabit {
  75. return &NeckActiveHabit{
  76. PastureId: data.PastureId,
  77. Frameid: data.XframeId,
  78. HeatDate: data.ActiveDate,
  79. NeckRingNumber: data.NeckRingNumber,
  80. Active: data.Active,
  81. Gasp: data.Gasp,
  82. High: data.High,
  83. Inactive: data.Inactive,
  84. Intake: data.Intake,
  85. Other: data.Other,
  86. Rumina: data.Rumina,
  87. IsShow: data.IsShow,
  88. WeekHigh: DefaultWeeklyActive,
  89. IsMaxTime: pasturePb.IsShow_No,
  90. ChangeFilter: InitChangeFilter,
  91. FilterCorrect: InitChangeFilter,
  92. RuminaFilter: InitChangeFilter,
  93. ChewFilter: InitChangeFilter,
  94. ActiveTime: fmt.Sprintf("%s %02d:00:00", data.ActiveDate, data.XframeId*2+1),
  95. RecordCount: data.RecordCount,
  96. FirmwareVersion: data.FirmwareVersion,
  97. }
  98. }
  99. type NeckActiveHabitSlice []*NeckActiveHabit
  100. func (n NeckActiveHabitSlice) Len() int { return len(n) }
  101. func (n NeckActiveHabitSlice) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
  102. func (n NeckActiveHabitSlice) Less(i, j int) bool {
  103. if n[i].HeatDate != n[j].HeatDate {
  104. return n[i].HeatDate < n[j].HeatDate
  105. }
  106. return n[i].Frameid < n[j].Frameid
  107. }
  108. func (n NeckActiveHabitSlice) ToPB(curveName, startDateTime, endDateTime string) *CowBehaviorCurveData {
  109. res := &CowBehaviorCurveData{
  110. OriginalDateList: make([]int32, 0),
  111. ChangeDateList: make([]int32, 0),
  112. SumDateList: make([]int32, 0),
  113. DateTimeList: make([]string, 0),
  114. EstrusList: make(map[pasturePb.EstrusLevel_Kind][]string),
  115. EventList: make(map[string][]string),
  116. EventMap: make(map[pasturePb.EventType_Kind]string),
  117. }
  118. //dayTimeRange, _ := util.GetDaysBetween(startDateTime, endDateTime)
  119. initFrameId := int32(0)
  120. dateFrameMap := make(map[string][]int32)
  121. for _, v := range n {
  122. if dateFrameMap[v.HeatDate] == nil {
  123. initFrameId = 0
  124. dateFrameMap[v.HeatDate] = make([]int32, 0)
  125. }
  126. // 补全结尾不够的数据
  127. if initFrameId == 0 && len(res.DateTimeList) > 0 {
  128. lastDateTime := res.DateTimeList[len(res.DateTimeList)-1]
  129. lastDatePase := strings.Split(lastDateTime, " ")
  130. if len(lastDatePase) == 2 {
  131. lastDay := lastDatePase[0]
  132. lastHourStr := lastDatePase[1]
  133. lastHour, _ := strconv.ParseInt(lastHourStr, 10, 64)
  134. maxHour := util.ExpectedFrameIDs[len(util.ExpectedFrameIDs)-1]
  135. xframeId := int32(lastHour-1)/2 + 1
  136. if xframeId != maxHour {
  137. for ; xframeId <= maxHour; xframeId++ {
  138. res.DateTimeList = append(res.DateTimeList, fmt.Sprintf("%s %02d", lastDay, util.ExpectedFrameIDs[xframeId]*2+1))
  139. res.OriginalDateList = append(res.OriginalDateList, 0)
  140. res.ChangeDateList = append(res.ChangeDateList, 0)
  141. res.SumDateList = append(res.SumDateList, 0)
  142. }
  143. }
  144. }
  145. }
  146. expectedFrameId := util.ExpectedFrameIDs[initFrameId]
  147. if expectedFrameId != v.Frameid {
  148. maxFrameId := int32(math.Abs(float64(expectedFrameId - v.Frameid)))
  149. for ; expectedFrameId < maxFrameId; expectedFrameId++ {
  150. res.DateTimeList = append(res.DateTimeList, fmt.Sprintf("%s %02d", v.HeatDate, util.ExpectedFrameIDs[expectedFrameId]*2+1))
  151. res.OriginalDateList = append(res.OriginalDateList, 0)
  152. res.ChangeDateList = append(res.ChangeDateList, 0)
  153. res.SumDateList = append(res.SumDateList, 0)
  154. }
  155. initFrameId = expectedFrameId
  156. }
  157. // 格式化为到小时的字符串
  158. parsedTime, _ := time.Parse(LayoutTime, v.ActiveTime)
  159. hourStr := parsedTime.Format(LayoutHour)
  160. res.DateTimeList = append(res.DateTimeList, hourStr)
  161. switch curveName {
  162. case "active": // 活动量
  163. res.OriginalDateList = append(res.OriginalDateList, v.High)
  164. res.ChangeDateList = append(res.ChangeDateList, v.ChangeFilter)
  165. case "rumina": // 反刍
  166. res.OriginalDateList = append(res.OriginalDateList, v.Rumina)
  167. res.ChangeDateList = append(res.ChangeDateList, v.ChangeRumina)
  168. res.SumDateList = append(res.SumDateList, v.SumRumina)
  169. case "intake": // 采食
  170. res.OriginalDateList = append(res.OriginalDateList, v.Intake)
  171. res.SumDateList = append(res.SumDateList, v.SumIntake)
  172. case "inactive": // 休息
  173. res.OriginalDateList = append(res.OriginalDateList, v.Inactive)
  174. res.SumDateList = append(res.SumDateList, v.SumInactive)
  175. case "chew": // 咀嚼
  176. res.OriginalDateList = append(res.OriginalDateList, v.FilterChew)
  177. res.ChangeDateList = append(res.ChangeDateList, v.ChangeChew)
  178. res.SumDateList = append(res.SumDateList, 0)
  179. case "immobility": // 静止
  180. res.OriginalDateList = append(res.OriginalDateList, 0)
  181. res.SumDateList = append(res.SumDateList, 0)
  182. }
  183. initFrameId++
  184. }
  185. return res
  186. }
  187. func (n *NeckActiveHabit) SumAvg() {
  188. n.Rumina = n.Rumina / n.RecordCount * n.RecordCount
  189. n.Inactive = n.Inactive / n.RecordCount * n.RecordCount
  190. n.Active = n.Active / n.RecordCount * n.RecordCount
  191. n.Intake = n.Intake / n.RecordCount * n.RecordCount
  192. n.Other = n.Other / n.RecordCount * n.RecordCount
  193. n.Gasp = n.Gasp / n.RecordCount * n.RecordCount
  194. n.High = n.High / n.RecordCount * n.RecordCount
  195. }
  196. type MaxHabitIdModel struct {
  197. Id int64 `json:"id"`
  198. }