cow.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. package model
  2. import (
  3. "fmt"
  4. "kpt-pasture/util"
  5. "math"
  6. "time"
  7. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  8. )
  9. type Cow struct {
  10. Id int64 `json:"id"`
  11. Sex pasturePb.Genders_Kind `json:"sex"`
  12. NeckRingNumber string `json:"neckRingNumber"`
  13. EarNumber string `json:"earNumber"`
  14. EarOldNumber string `json:"earOldNumber"`
  15. PenId int32 `json:"penId"`
  16. Lact int32 `json:"lact"`
  17. DayAge int32 `json:"dayAge"`
  18. CalvingAge int64 `json:"calvingAge"`
  19. PregnancyAge int32 `json:"pregnancyAge"` // 怀孕天数 孕检结果有阳性更新,产犊后至0
  20. AdmissionAge int32 `json:"admissionAge"`
  21. AbortionAge int64 `json:"abortionAge"` // 流产天数
  22. CowType pasturePb.CowType_Kind `json:"cowType"`
  23. BreedStatus pasturePb.BreedStatus_Kind `json:"breedStatus"`
  24. CowKind pasturePb.CowKind_Kind `json:"cowKind"`
  25. BirthWeight int64 `json:"birthWeight"`
  26. CurrentWeight int64 `json:"currentWeight"`
  27. AdmissionWeight int64 `json:"admissionWeight"`
  28. SourceId pasturePb.CowSource_Kind `json:"sourceId"`
  29. FatherNumber string `json:"fatherNumber"`
  30. MotherNumber string `json:"motherNumber"`
  31. AdmissionStatus pasturePb.AdmissionStatus_Kind `json:"admissionStatus"`
  32. IsPregnant pasturePb.IsShow_Kind `json:"isPregnant"`
  33. HealthStatus pasturePb.HealthStatus_Kind `json:"healthStatus"`
  34. WeaningAt int64 `json:"weaningAt"`
  35. CalvingAt int64 `json:"calvingAt"`
  36. BirthAt int64 `json:"birthAti"`
  37. AdmissionAt int64 `json:"admissionAt"`
  38. FirstMatingAt int64 `json:"firstMatingAt"`
  39. LastEstrusAt int64 `json:"lastEstrusAt"`
  40. LastCalvingAt int64 `json:"lastCalvingAt"`
  41. LastMatingAt int64 `json:"lastMatingAt"`
  42. LastBullNumber string `json:"lastBullNumber"`
  43. LastPregnantCheckAt int64 `json:"lastPregnantCheckAt"`
  44. LastDryMilkAt int64 `json:"lastDryMilkAt"`
  45. LastSecondWeight int64 `json:"lastSecondWeight"`
  46. LastSecondWeightAt int64 `json:"lastSecondWeightAt"`
  47. LastAbortionAt int64 `json:"lastAbortionAt"`
  48. LastWeightAt int64 `json:"lastWeightAt"`
  49. CreatedAt int64 `json:"createdAt"`
  50. UpdatedAt int64 `json:"updatedAt"`
  51. }
  52. func (c *Cow) TableName() string {
  53. return "cow"
  54. }
  55. type CowSlice []*Cow
  56. func (c CowSlice) ToPB(
  57. penMap map[int32]*Pen,
  58. cowTypeMap map[pasturePb.CowType_Kind]string,
  59. breedStatusMap map[pasturePb.BreedStatus_Kind]string,
  60. cowKindMap map[pasturePb.CowKind_Kind]string,
  61. ) []*pasturePb.SearchCowList {
  62. res := make([]*pasturePb.SearchCowList, len(c))
  63. for i, v := range c {
  64. penName := ""
  65. if pen, ok := penMap[v.PenId]; ok {
  66. penName = pen.Name
  67. }
  68. res[i] = &pasturePb.SearchCowList{
  69. CowId: int32(v.Id),
  70. Sex: v.Sex,
  71. NeckRingNumber: v.NeckRingNumber,
  72. EarNumber: v.EarNumber,
  73. PenId: v.PenId,
  74. PenName: penName,
  75. CowType: int32(v.CowType),
  76. Lact: v.Lact,
  77. CowTypeName: cowTypeMap[v.CowType],
  78. BreedStatus: v.BreedStatus,
  79. BreedStatusName: breedStatusMap[v.BreedStatus],
  80. CowKind: v.CowKind,
  81. CowKindName: cowKindMap[v.CowKind],
  82. BirthAt: int32(v.BirthAt),
  83. BirthWeight: int32(v.BirthWeight) / 1000,
  84. CurrentWeight: int32(v.CurrentWeight) / 1000,
  85. LastWeightAt: int32(v.LastWeightAt),
  86. }
  87. }
  88. return res
  89. }
  90. func (c CowSlice) ToPB2(penMap map[int32]*Pen, penWeightSlice PenWeightSlice) []*pasturePb.CowList {
  91. res := make([]*pasturePb.CowList, len(c))
  92. for i, v := range c {
  93. penName := ""
  94. if pen, ok := penMap[v.PenId]; ok {
  95. penName = pen.Name
  96. }
  97. penWeight := penWeightSlice.GetPenWeight(v.PenId)
  98. lastWeightDay := util.Ceil(float64(v.LastWeightAt-v.LastSecondWeightAt) / 86400)
  99. penAvgWeight := float32(0)
  100. previousStageDailyWeight := float32(0)
  101. cowPenAvgWeightDiffValue := float32(0)
  102. if penWeight != nil {
  103. penAvgWeight = float32(penWeight.AvgWeight) / 1000
  104. cowPenAvgWeightDiffValue = float32(v.CurrentWeight-int64(penWeight.AvgWeight)) / 1000
  105. if lastWeightDay > 0 {
  106. previousStageDailyWeight = float32(v.CurrentWeight-v.LastSecondWeight) / 1000 / float32(lastWeightDay)
  107. }
  108. }
  109. res[i] = &pasturePb.CowList{
  110. CowId: int32(v.Id),
  111. DayAge: v.DayAge,
  112. DailyWeightGain: float32(v.GetDayWeight()),
  113. AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
  114. EarNumber: v.EarNumber,
  115. PenName: penName,
  116. BirthAt: int32(v.BirthAt),
  117. BirthWeight: float32(v.BirthWeight) / 1000,
  118. CurrentWeight: float32(v.CurrentWeight) / 1000,
  119. LastWeightAt: int32(v.LastWeightAt),
  120. AdmissionAge: int32(v.AdmissionAge),
  121. AdmissionWeight: float32(v.AbortionAge) / 1000,
  122. PreviousStageDailyWeight: previousStageDailyWeight,
  123. PenAvgWeight: penAvgWeight,
  124. CowPenAvgWeightDiffValue: cowPenAvgWeightDiffValue,
  125. }
  126. }
  127. return res
  128. }
  129. func NewCow(req *pasturePb.EventEnterRequest) *Cow {
  130. var isPregnant = pasturePb.IsShow_No
  131. if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
  132. isPregnant = pasturePb.IsShow_Ok
  133. }
  134. return &Cow{
  135. Sex: req.Sex,
  136. EarNumber: req.EarNumber,
  137. PenId: req.PenId,
  138. Lact: req.Lact,
  139. CowType: req.CowType,
  140. BreedStatus: req.BreedStatus,
  141. CowKind: req.CowKind,
  142. SourceId: req.CowSource,
  143. FatherNumber: req.FatherNumber,
  144. MotherNumber: req.MotherNumber,
  145. AdmissionStatus: pasturePb.AdmissionStatus_Admission,
  146. HealthStatus: pasturePb.HealthStatus_Health,
  147. IsPregnant: isPregnant,
  148. WeaningAt: int64(req.WeaningAt),
  149. BirthAt: int64(req.BirthAt),
  150. AdmissionWeight: int64(req.Weight * 1000),
  151. FirstMatingAt: int64(req.MatingAt),
  152. LastMatingAt: int64(req.MatingAt),
  153. LastPregnantCheckAt: int64(req.PregnancyCheckAt),
  154. }
  155. }
  156. func NewCalfCow(motherId int64, fatherNumber string, calf *CalvingCalf) *Cow {
  157. return &Cow{
  158. Sex: calf.Sex,
  159. EarNumber: calf.EarNumber,
  160. PenId: calf.PenId,
  161. CowType: pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
  162. BreedStatus: pasturePb.BreedStatus_UnBreed, // 未配
  163. CowKind: calf.CowKind, // 牛只品种
  164. BirthWeight: calf.BirthWeight,
  165. BirthAt: calf.BirthAt,
  166. SourceId: pasturePb.CowSource_Calving, // 产犊方式
  167. FatherNumber: fatherNumber,
  168. MotherNumber: fmt.Sprintf("%d", motherId),
  169. AdmissionStatus: pasturePb.AdmissionStatus_Admission,
  170. IsPregnant: pasturePb.IsShow_No,
  171. }
  172. }
  173. type BarCowStruct struct {
  174. Number int32 `json:"number"`
  175. TypeId pasturePb.CowType_Kind `json:"type_id"`
  176. }
  177. // BarCowStructSlice 首页牛群结构
  178. type BarCowStructSlice []*BarCowStruct
  179. func (b BarCowStructSlice) ToPB(cowTypeMap map[pasturePb.CowType_Kind]string, count int32) []*pasturePb.BarCowStruct {
  180. var pb []*pasturePb.BarCowStruct
  181. for _, v := range b {
  182. name := fmt.Sprintf("%s", cowTypeMap[v.TypeId])
  183. pb = append(pb, &pasturePb.BarCowStruct{Name: name, Value: v.Number})
  184. }
  185. return pb
  186. }
  187. // GetDayAge 日龄
  188. func (c *Cow) GetDayAge() int32 {
  189. if c.BirthAt <= 0 {
  190. return 0
  191. }
  192. return int32(math.Floor(float64(time.Now().Unix()-c.BirthAt) / 86400))
  193. }
  194. // GetCalvingAge 产后天数
  195. func (c *Cow) GetCalvingAge() int64 {
  196. if c.CalvingAt <= 0 {
  197. return 0
  198. }
  199. return int64(math.Floor(float64(time.Now().Unix()-c.CalvingAt) / 86400))
  200. }
  201. // GetDaysPregnant 怀孕天数
  202. func (c *Cow) GetDaysPregnant() int32 {
  203. if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
  204. c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
  205. c.IsPregnant == pasturePb.IsShow_Ok {
  206. return int32(math.Floor(float64(time.Now().Unix()-c.LastMatingAt) / 86400))
  207. }
  208. return 0
  209. }
  210. // GetLactationDays 泌乳天数
  211. func (c *Cow) GetLactationDays() int32 {
  212. if c.BreedStatus == pasturePb.BreedStatus_Calving && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  213. return int32(math.Floor(float64(time.Now().Unix()-c.LastCalvingAt) / 86400))
  214. }
  215. return 0
  216. }
  217. // GetAdmissionAge 入场天数
  218. func (c *Cow) GetAdmissionAge() int32 {
  219. if c.AdmissionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  220. return int32(math.Floor(float64(time.Now().Unix()-c.AdmissionAt) / 86400))
  221. }
  222. return 0
  223. }
  224. // GetDayWeight 日增重
  225. func (c *Cow) GetDayWeight() float64 {
  226. if c.CurrentWeight-c.LastSecondWeight > 0 && c.LastWeightAt > c.LastSecondWeightAt {
  227. days := int32(math.Floor(float64(c.LastWeightAt-c.LastSecondWeightAt) / 86400))
  228. if days <= 0 {
  229. return 0
  230. }
  231. dayWeight := math.Round(1.0 * float64(c.CurrentWeight-c.LastSecondWeight) / float64(days))
  232. return dayWeight / 1000
  233. }
  234. return 0
  235. }
  236. // GetAverageDailyWeight 平均日增重
  237. func (c *Cow) GetAverageDailyWeight() float64 {
  238. if c.CurrentWeight-c.BirthWeight > 0 && c.LastWeightAt > c.BirthAt {
  239. days := int32(math.Floor(float64(c.LastWeightAt-c.BirthAt) / 86400))
  240. if days <= 0 {
  241. return 0
  242. }
  243. dailyWeight := math.Round(1.0 * float64(c.CurrentWeight-c.BirthWeight) / float64(days))
  244. return dailyWeight / 1000
  245. }
  246. return 0
  247. }
  248. func (c *Cow) GetAbortionAge() int32 {
  249. if c.LastAbortionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  250. return int32(math.Floor(float64(time.Now().Unix()-c.LastAbortionAt) / 86400))
  251. }
  252. return 0
  253. }
  254. type CowWeightRange struct {
  255. WeightRange string `json:"weight_range"`
  256. Count int32 `json:"count"`
  257. }
  258. func (c CowSlice) WeightRangeToPB(penMap map[int32]*Pen) []*pasturePb.CowList {
  259. res := make([]*pasturePb.CowList, len(c))
  260. for i, v := range c {
  261. penName := ""
  262. if pen, ok := penMap[v.PenId]; ok {
  263. penName = pen.Name
  264. }
  265. res[i] = &pasturePb.CowList{
  266. CowId: int32(v.Id),
  267. DayAge: v.DayAge,
  268. DailyWeightGain: float32(v.GetDayWeight()),
  269. AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
  270. EarNumber: v.EarNumber,
  271. PenName: penName,
  272. BirthAt: int32(v.BirthAt),
  273. BirthWeight: float32(v.BirthWeight) / 1000,
  274. CurrentWeight: float32(v.CurrentWeight) / 1000,
  275. LastWeightAt: int32(v.LastWeightAt),
  276. }
  277. }
  278. return res
  279. }