cow.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. PenName string `json:"penName"`
  17. Lact int32 `json:"lact"`
  18. DayAge int32 `json:"dayAge"`
  19. CalvingAge int64 `json:"calvingAge"`
  20. PregnancyAge int32 `json:"pregnancyAge"` // 怀孕天数 孕检结果有阳性更新,产犊后至0
  21. AdmissionAge int32 `json:"admissionAge"`
  22. AbortionAge int64 `json:"abortionAge"` // 流产天数
  23. CowType pasturePb.CowType_Kind `json:"cowType"`
  24. BreedStatus pasturePb.BreedStatus_Kind `json:"breedStatus"`
  25. CowKind pasturePb.CowKind_Kind `json:"cowKind"`
  26. BirthWeight int64 `json:"birthWeight"`
  27. CurrentWeight int64 `json:"currentWeight"`
  28. AdmissionWeight int64 `json:"admissionWeight"`
  29. SourceId pasturePb.CowSource_Kind `json:"sourceId"`
  30. FatherNumber string `json:"fatherNumber"`
  31. MotherNumber string `json:"motherNumber"`
  32. AdmissionStatus pasturePb.AdmissionStatus_Kind `json:"admissionStatus"`
  33. IsPregnant pasturePb.IsShow_Kind `json:"isPregnant"`
  34. HealthStatus pasturePb.HealthStatus_Kind `json:"healthStatus"`
  35. WeaningAt int64 `json:"weaningAt"`
  36. BirthAt int64 `json:"birthAt"`
  37. AdmissionAt int64 `json:"admissionAt"`
  38. FirstMatingAt int64 `json:"firstMatingAt"`
  39. MatingTimes int32 `json:"matingTimes"`
  40. WeeklyActive int32 `json:"weeklyActive"`
  41. LastEstrusAt int64 `json:"lastEstrusAt"`
  42. LastCalvingAt int64 `json:"lastCalvingAt"`
  43. LastMatingAt int64 `json:"lastMatingAt"`
  44. LastBullNumber string `json:"lastBullNumber"`
  45. LastPregnantCheckAt int64 `json:"lastPregnantCheckAt"`
  46. LastDryMilkAt int64 `json:"lastDryMilkAt"`
  47. LastSecondWeight int64 `json:"lastSecondWeight"`
  48. LastSecondWeightAt int64 `json:"lastSecondWeightAt"`
  49. LastAbortionAt int64 `json:"lastAbortionAt"`
  50. LastWeightAt int64 `json:"lastWeightAt"`
  51. CreatedAt int64 `json:"createdAt"`
  52. UpdatedAt int64 `json:"updatedAt"`
  53. }
  54. func (c *Cow) TableName() string {
  55. return "cow"
  56. }
  57. // EventCalvingUpdate 产犊更新
  58. func (c *Cow) EventCalvingUpdate(calvingAt int64) {
  59. c.Lact += 1
  60. c.CalvingAge = int64(time.Now().Sub(time.Unix(calvingAt, 0)).Hours() / 24)
  61. c.MatingTimes = 0
  62. c.PregnancyAge = 0
  63. c.BreedStatus = pasturePb.BreedStatus_Calving
  64. c.IsPregnant = pasturePb.IsShow_No
  65. c.LastCalvingAt = calvingAt
  66. }
  67. // EventWeaningUpdate 断奶更新
  68. func (c *Cow) EventWeaningUpdate(weaningAt int64, penId int32, currentWeight int64) {
  69. c.PenId = penId
  70. c.WeaningAt = weaningAt
  71. c.CurrentWeight = currentWeight
  72. c.LastWeightAt = weaningAt
  73. }
  74. // EventPregnantCheckUpdate 孕检更新
  75. func (c *Cow) EventPregnantCheckUpdate(breedStatus pasturePb.BreedStatus_Kind, pregnantCheckAt int64, isPregnant pasturePb.IsShow_Kind) {
  76. c.BreedStatus = breedStatus
  77. c.LastPregnantCheckAt = pregnantCheckAt
  78. c.IsPregnant = isPregnant
  79. }
  80. // EventAbortionUpdate 流产更新
  81. func (c *Cow) EventAbortionUpdate(abortionAt int64) {
  82. c.IsPregnant = pasturePb.IsShow_No
  83. c.LastAbortionAt = abortionAt
  84. c.BreedStatus = pasturePb.BreedStatus_Abort
  85. }
  86. // EventWeightUpdate 称重更新
  87. func (c *Cow) EventWeightUpdate(weight int64, weightAt int64) {
  88. c.LastSecondWeight = c.CurrentWeight
  89. c.LastSecondWeightAt = c.LastWeightAt
  90. c.LastWeightAt = weightAt
  91. c.CurrentWeight = weight
  92. }
  93. // EventDiseaseUpdate 疾病更新
  94. func (c *Cow) EventDiseaseUpdate(healthStatus pasturePb.HealthStatus_Kind) {
  95. c.HealthStatus = healthStatus
  96. }
  97. type CowSlice []*Cow
  98. func (c CowSlice) ToPB(
  99. penMap map[int32]*Pen,
  100. cowTypeMap map[pasturePb.CowType_Kind]string,
  101. breedStatusMap map[pasturePb.BreedStatus_Kind]string,
  102. cowKindMap map[pasturePb.CowKind_Kind]string,
  103. cowSourceMap map[pasturePb.CowSource_Kind]string,
  104. admissionStatusMap map[pasturePb.AdmissionStatus_Kind]string,
  105. healthStatusMap map[pasturePb.HealthStatus_Kind]string,
  106. ) []*pasturePb.CowDetails {
  107. res := make([]*pasturePb.CowDetails, len(c))
  108. for i, v := range c {
  109. penName := ""
  110. if pen, ok := penMap[v.PenId]; ok {
  111. penName = pen.Name
  112. }
  113. sex := "公"
  114. if v.Sex == pasturePb.Genders_Female {
  115. sex = "母"
  116. }
  117. lastWeightAtFormat := ""
  118. if v.LastWeightAt > 0 {
  119. lastWeightAtFormat = time.Unix(v.LastWeightAt, 0).Format(LayoutDate2)
  120. }
  121. isPregnantName := ""
  122. if v.IsPregnant == pasturePb.IsShow_Ok {
  123. isPregnantName = "已孕"
  124. } else {
  125. isPregnantName = "未孕"
  126. }
  127. admissionAtFormat := ""
  128. if v.AdmissionAt > 0 {
  129. admissionAtFormat = time.Unix(v.AdmissionAt, 0).Format(LayoutDate2)
  130. }
  131. birthAtFormat := ""
  132. if v.BirthAt > 0 {
  133. birthAtFormat = time.Unix(v.BirthAt, 0).Format(LayoutDate2)
  134. }
  135. weaningAtFormat := ""
  136. if v.WeaningAt > 0 {
  137. weaningAtFormat = time.Unix(v.WeaningAt, 0).Format(LayoutDate2)
  138. }
  139. firstMatingAtFormat := ""
  140. if v.FirstMatingAt > 0 {
  141. firstMatingAtFormat = time.Unix(v.FirstMatingAt, 0).Format(LayoutDate2)
  142. }
  143. lastMatingAtFormat := ""
  144. if v.LastMatingAt > 0 {
  145. lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Format(LayoutDate2)
  146. }
  147. lastPregnantCheckAtFormat := ""
  148. if v.LastPregnantCheckAt > 0 {
  149. lastPregnantCheckAtFormat = time.Unix(v.LastPregnantCheckAt, 0).Format(LayoutDate2)
  150. }
  151. lastCalvingAtFormat := ""
  152. if v.LastCalvingAt > 0 {
  153. lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Format(LayoutDate2)
  154. }
  155. res[i] = &pasturePb.CowDetails{
  156. CowId: int32(v.Id),
  157. Sex: sex,
  158. NeckRingNumber: v.NeckRingNumber,
  159. PenName: penName,
  160. Lact: v.Lact,
  161. CowTypeName: cowTypeMap[v.CowType],
  162. BreedStatusName: breedStatusMap[v.BreedStatus],
  163. CowKindName: cowKindMap[v.CowKind],
  164. EarNumber: v.EarNumber,
  165. BirthWeight: float32(v.BirthWeight) / 1000,
  166. CurrentWeight: float32(v.CurrentWeight) / 1000,
  167. DayAge: v.DayAge,
  168. SourceName: cowSourceMap[v.SourceId],
  169. MontherNumber: v.MotherNumber,
  170. FatherNumber: v.FatherNumber,
  171. AdmissionStatusName: admissionStatusMap[v.AdmissionStatus],
  172. HealthStatusName: healthStatusMap[v.HealthStatus],
  173. IsPregnantName: isPregnantName,
  174. AdmissionAtFormat: admissionAtFormat,
  175. BirthAtFormat: birthAtFormat,
  176. WeaningAtFormat: weaningAtFormat,
  177. CalvingAge: int32(v.GetCalvingAge()),
  178. AbortionAge: int32(v.AbortionAge),
  179. MatingTimes: v.MatingTimes,
  180. FirstMatingAtFormat: firstMatingAtFormat,
  181. LastMatingAtFormat: lastMatingAtFormat,
  182. LastBullNumber: v.LastBullNumber,
  183. LastPregnantCheckAtFormat: lastPregnantCheckAtFormat,
  184. LastWeightAtFormat: lastWeightAtFormat,
  185. LastCalvingAtFormat: lastCalvingAtFormat,
  186. //PregnancyAge: v.PregnancyAge,
  187. }
  188. }
  189. return res
  190. }
  191. func (c CowSlice) ToPB2(penMap map[int32]*Pen, penWeightSlice PenWeightSlice) []*pasturePb.CowList {
  192. res := make([]*pasturePb.CowList, len(c))
  193. for i, v := range c {
  194. penName := ""
  195. if pen, ok := penMap[v.PenId]; ok {
  196. penName = pen.Name
  197. }
  198. penWeight := penWeightSlice.GetPenWeight(v.PenId)
  199. lastWeightDay := util.Ceil(float64(v.LastWeightAt-v.LastSecondWeightAt) / 86400)
  200. penAvgWeight := float32(0)
  201. previousStageDailyWeight := float32(0)
  202. cowPenAvgWeightDiffValue := float32(0)
  203. if penWeight != nil {
  204. penAvgWeight = float32(penWeight.AvgWeight) / 1000
  205. cowPenAvgWeightDiffValue = float32(v.CurrentWeight-int64(penWeight.AvgWeight)) / 1000
  206. if lastWeightDay > 0 {
  207. previousStageDailyWeight = float32(v.CurrentWeight-v.LastSecondWeight) / 1000 / float32(lastWeightDay)
  208. }
  209. }
  210. res[i] = &pasturePb.CowList{
  211. CowId: int32(v.Id),
  212. DayAge: v.DayAge,
  213. DailyWeightGain: float32(v.GetDayWeight()),
  214. AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
  215. EarNumber: v.EarNumber,
  216. PenName: penName,
  217. BirthAt: int32(v.BirthAt),
  218. BirthWeight: float32(v.BirthWeight) / 1000,
  219. CurrentWeight: float32(v.CurrentWeight) / 1000,
  220. LastWeightAt: int32(v.LastWeightAt),
  221. AdmissionAge: int32(v.AdmissionAge),
  222. AdmissionWeight: float32(v.AbortionAge) / 1000,
  223. PreviousStageDailyWeight: previousStageDailyWeight,
  224. PenAvgWeight: penAvgWeight,
  225. CowPenAvgWeightDiffValue: cowPenAvgWeightDiffValue,
  226. }
  227. }
  228. return res
  229. }
  230. func NewCow(req *pasturePb.EventEnterRequest) *Cow {
  231. var isPregnant = pasturePb.IsShow_No
  232. if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
  233. isPregnant = pasturePb.IsShow_Ok
  234. }
  235. return &Cow{
  236. Sex: req.Sex,
  237. EarNumber: req.EarNumber,
  238. PenId: req.PenId,
  239. Lact: req.Lact,
  240. CowType: req.CowType,
  241. BreedStatus: req.BreedStatus,
  242. CowKind: req.CowKind,
  243. SourceId: req.CowSource,
  244. FatherNumber: req.FatherNumber,
  245. MotherNumber: req.MotherNumber,
  246. AdmissionStatus: pasturePb.AdmissionStatus_Admission,
  247. HealthStatus: pasturePb.HealthStatus_Health,
  248. IsPregnant: isPregnant,
  249. WeaningAt: int64(req.WeaningAt),
  250. BirthAt: int64(req.BirthAt),
  251. AdmissionWeight: int64(req.Weight * 1000),
  252. FirstMatingAt: int64(req.MatingAt),
  253. LastMatingAt: int64(req.MatingAt),
  254. LastPregnantCheckAt: int64(req.PregnancyCheckAt),
  255. AdmissionAt: time.Now().Unix(),
  256. }
  257. }
  258. func NewCalfCow(motherId int64, fatherNumber string, calf *CalvingCalf) *Cow {
  259. return &Cow{
  260. Sex: calf.Sex,
  261. EarNumber: calf.EarNumber,
  262. PenId: calf.PenId,
  263. CowType: pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
  264. BreedStatus: pasturePb.BreedStatus_UnBreed, // 未配
  265. CowKind: calf.CowKind, // 牛只品种
  266. BirthWeight: calf.BirthWeight,
  267. BirthAt: calf.BirthAt,
  268. SourceId: pasturePb.CowSource_Calving, // 产犊方式
  269. FatherNumber: fatherNumber,
  270. MotherNumber: fmt.Sprintf("%d", motherId),
  271. AdmissionStatus: pasturePb.AdmissionStatus_Admission,
  272. IsPregnant: pasturePb.IsShow_No,
  273. AdmissionAt: calf.BirthAt,
  274. }
  275. }
  276. type BarCowStruct struct {
  277. Number int32 `json:"number"`
  278. TypeId pasturePb.CowType_Kind `json:"type_id"`
  279. }
  280. // BarCowStructSlice 首页牛群结构
  281. type BarCowStructSlice []*BarCowStruct
  282. func (b BarCowStructSlice) ToPB(cowTypeMap map[pasturePb.CowType_Kind]string, count int32) []*pasturePb.BarCowStruct {
  283. var pb []*pasturePb.BarCowStruct
  284. for _, v := range b {
  285. name := fmt.Sprintf("%s", cowTypeMap[v.TypeId])
  286. pb = append(pb, &pasturePb.BarCowStruct{Name: name, Value: v.Number})
  287. }
  288. return pb
  289. }
  290. // GetDayAge 日龄
  291. func (c *Cow) GetDayAge() int32 {
  292. if c.BirthAt <= 0 {
  293. return 0
  294. }
  295. return int32(math.Floor(float64(time.Now().Unix()-c.BirthAt) / 86400))
  296. }
  297. // GetCalvingAge 产后天数
  298. func (c *Cow) GetCalvingAge() int64 {
  299. if c.LastMatingAt <= 0 {
  300. return 0
  301. }
  302. return int64(math.Floor(float64(time.Now().Unix()-c.LastMatingAt) / 86400))
  303. }
  304. // GetDaysPregnant 怀孕天数
  305. func (c *Cow) GetDaysPregnant() int32 {
  306. if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
  307. c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
  308. c.IsPregnant == pasturePb.IsShow_Ok {
  309. return int32(math.Floor(float64(time.Now().Unix()-c.LastMatingAt) / 86400))
  310. }
  311. return 0
  312. }
  313. // GetLactationDays 泌乳天数
  314. func (c *Cow) GetLactationDays() int32 {
  315. if c.BreedStatus == pasturePb.BreedStatus_Calving && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  316. return int32(math.Floor(float64(time.Now().Unix()-c.LastCalvingAt) / 86400))
  317. }
  318. return 0
  319. }
  320. // GetAdmissionAge 入场天数
  321. func (c *Cow) GetAdmissionAge() int32 {
  322. if c.AdmissionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  323. return int32(math.Floor(float64(time.Now().Unix()-c.AdmissionAt) / 86400))
  324. }
  325. return 0
  326. }
  327. // GetDayWeight 日增重
  328. func (c *Cow) GetDayWeight() float64 {
  329. if c.CurrentWeight-c.LastSecondWeight > 0 && c.LastWeightAt > c.LastSecondWeightAt {
  330. days := int32(math.Floor(float64(c.LastWeightAt-c.LastSecondWeightAt) / 86400))
  331. if days <= 0 {
  332. return 0
  333. }
  334. dayWeight := math.Round(1.0 * float64(c.CurrentWeight-c.LastSecondWeight) / float64(days))
  335. return dayWeight / 1000
  336. }
  337. return 0
  338. }
  339. // GetAverageDailyWeight 平均日增重
  340. func (c *Cow) GetAverageDailyWeight() float64 {
  341. if c.CurrentWeight-c.BirthWeight > 0 && c.LastWeightAt > c.BirthAt {
  342. days := int32(math.Floor(float64(c.LastWeightAt-c.BirthAt) / 86400))
  343. if days <= 0 {
  344. return 0
  345. }
  346. dailyWeight := math.Round(1.0 * float64(c.CurrentWeight-c.BirthWeight) / float64(days))
  347. return dailyWeight / 1000
  348. }
  349. return 0
  350. }
  351. func (c *Cow) GetAbortionAge() int32 {
  352. if c.LastAbortionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  353. return int32(math.Floor(float64(time.Now().Unix()-c.LastAbortionAt) / 86400))
  354. }
  355. return 0
  356. }
  357. type CowWeightRange struct {
  358. WeightRange string `json:"weight_range"`
  359. Count int32 `json:"count"`
  360. }
  361. func (c CowSlice) WeightRangeToPB(penMap map[int32]*Pen) []*pasturePb.CowList {
  362. res := make([]*pasturePb.CowList, len(c))
  363. for i, v := range c {
  364. penName := ""
  365. if pen, ok := penMap[v.PenId]; ok {
  366. penName = pen.Name
  367. }
  368. res[i] = &pasturePb.CowList{
  369. CowId: int32(v.Id),
  370. DayAge: v.DayAge,
  371. DailyWeightGain: float32(v.GetDayWeight()),
  372. AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
  373. EarNumber: v.EarNumber,
  374. PenName: penName,
  375. BirthAt: int32(v.BirthAt),
  376. BirthWeight: float32(v.BirthWeight) / 1000,
  377. CurrentWeight: float32(v.CurrentWeight) / 1000,
  378. LastWeightAt: int32(v.LastWeightAt),
  379. }
  380. }
  381. return res
  382. }