neck_active_habit.go 9.7 KB

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