cow.go 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. package model
  2. import (
  3. "fmt"
  4. "math"
  5. "time"
  6. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  7. )
  8. type Cow struct {
  9. Id int64 `json:"id"`
  10. PastureId int64 `json:"pastureId"` // 牧场id
  11. Sex pasturePb.Genders_Kind `json:"sex"` // 性别
  12. NeckRingNumber string `json:"neckRingNumber"` // 脖环号
  13. EarNumber string `json:"earNumber"` // 耳标号
  14. EleEarNumber string `json:"eleEarNumber"` // 电子耳标号
  15. EarOldNumber string `json:"earOldNumber"` // 旧耳标号
  16. PenId int32 `json:"penId"` // 栏舍id
  17. PenName string `json:"penName"` // 栏舍名称
  18. Lact int32 `json:"lact"` // 胎次
  19. DayAge int32 `json:"dayAge"` // 日龄
  20. CalvingAge int32 `json:"calvingAge"` // 产后天使
  21. PregnancyAge int32 `json:"pregnancyAge"` // 怀孕天数 孕检结果有阳性更新,产犊后至0
  22. MatingAge int32 `json:"matingAge"` // 配种天数
  23. AdmissionAge int32 `json:"admissionAge"` // 入场日龄
  24. AbortionAge int32 `json:"abortionAge"` // 流产天数
  25. LactationAge int32 `json:"lactationAge"` // 泌乳天数
  26. DryMilkAge int32 `json:"dryMilkAge"` // 干奶天数
  27. CowType pasturePb.CowType_Kind `json:"cowType"` // 牛只类型
  28. MilkKind pasturePb.CowMilk_Kind `json:"milkKind"` // 牛只奶属性
  29. BreedStatus pasturePb.BreedStatus_Kind `json:"breedStatus"` // 繁殖状态
  30. CowKind pasturePb.CowKind_Kind `json:"cowKind"` // 牛只品种
  31. BirthWeight int64 `json:"birthWeight"` // 出生体重
  32. CurrentWeight int64 `json:"currentWeight"` // 当前体重
  33. CurrentHeight int64 `json:"currentHeight"` // 当前身高
  34. AdmissionWeight int64 `json:"admissionWeight"` // 入场体重
  35. AdmissionPrice float32 `json:"admissionPrice"` // 入场价格
  36. SourceKind pasturePb.CowSource_Kind `json:"sourceKind"` // 来源哪里
  37. PurposeKind pasturePb.Purpose_Kind `json:"purposeKind"` // 用途
  38. FatherNumber string `json:"fatherNumber"` // 父号
  39. MotherNumber string `json:"motherNumber"` // 母号
  40. AdmissionStatus pasturePb.AdmissionStatus_Kind `json:"admissionStatus"` // 在场状态
  41. IsPregnant pasturePb.IsShow_Kind `json:"isPregnant"` // 是否怀孕
  42. IsForbiddenMating pasturePb.IsShow_Kind `json:"isForbiddenMating"` // 是否禁配 1 是 2 否
  43. HealthStatus pasturePb.HealthStatus_Kind `json:"healthStatus"` // 健康状态
  44. WeaningAt int64 `json:"weaningAt"` // 断奶时间
  45. BirthAt int64 `json:"birthAt"` // 出生时间
  46. AdmissionAt int64 `json:"admissionAt"` // 入场时间
  47. DepartureAt int64 `json:"departureAt"` // 离场时间
  48. WeaningWeight int64 `json:"weaningWeight"` // 断奶体重
  49. DeparturePrice float32 `json:"departurePrice"` // 离场价格
  50. DepartureAvgWeight int32 `json:"departureAvgWeight"` // 离场平均体重
  51. FirstMatingAt int64 `json:"firstMatingAt"` // 首次配种时间
  52. AllMatingTimes int32 `json:"allMatingTimes"` // 总配次
  53. AllAbortionTimes int32 `json:"allAbortionTimes"` // 总流产次数
  54. MatingTimes int32 `json:"matingTimes"` // 配种次数
  55. AbortionTimes int32 `json:"abortionTimes"` // 流产次数
  56. PregnancyCheckName string `json:"pregnancyCheckName"` // 孕检名称
  57. WeeklyActive int32 `json:"weeklyActive"` // 每周活跃度
  58. LastEstrusAt int64 `json:"lastEstrusAt"` // 最后一次发情时间
  59. LastCalvingAt int64 `json:"lastCalvingAt"` // 最后一次产犊时间
  60. LastMatingAt int64 `json:"lastMatingAt"` // 最后一次配种时间
  61. LastBullNumber string `json:"lastBullNumber"` // 最后一次配种牛号
  62. LastPregnantCheckAt int64 `json:"lastPregnantCheckAt"` // 最后一次孕检时间
  63. LastDryMilkAt int64 `json:"lastDryMilkAt"` // 最近一次干奶日期
  64. LastForbiddenMatingAt int64 `json:"lastForbiddenMatingAt"` // 最近一次禁配时间
  65. LastSecondWeight int64 `json:"lastSecondWeight"` // 最后第二次称重
  66. LastSecondWeightAt int64 `json:"lastSecondWeightAt"` // 最后第二次称重时间
  67. LastAbortionAt int64 `json:"lastAbortionAt"` // 最近一次流产时间
  68. LastWeightAt int64 `json:"lastWeightAt"` // 最近一次称重时间
  69. BatchNumber string `json:"batchNumber"` // 批次号
  70. CreatedAt int64 `json:"createdAt"`
  71. UpdatedAt int64 `json:"updatedAt"`
  72. }
  73. func (c *Cow) TableName() string {
  74. return "cow"
  75. }
  76. // EventUpdate 牛只基本信息维护
  77. func (c *Cow) EventUpdate(weeklyActive int32) {
  78. c.DayAge = c.GetDayAge() // 日龄
  79. c.CalvingAge = c.GetCalvingAge() // 产后天数
  80. c.PregnancyAge = c.GetDaysPregnant() // 怀孕天数
  81. c.AdmissionAge = c.GetAdmissionAge() // 入场天数
  82. c.AbortionAge = c.GetAbortionAge() // 流产天数
  83. c.WeeklyActive = weeklyActive // 周活动量
  84. c.LactationAge = c.GetLactationAge() // 泌乳天数
  85. c.DryMilkAge = c.GetDryMilkAge() // 干奶天数
  86. c.MatingAge = c.GetMatingAge() // 配后天数
  87. if c.DayAge == 60 {
  88. c.CowType = pasturePb.CowType_Weaned_Calf
  89. }
  90. }
  91. // EventCalvingUpdate 产犊更新
  92. func (c *Cow) EventCalvingUpdate(calvingAt int64) {
  93. c.Lact += 1
  94. c.MatingTimes = 0
  95. c.PregnancyAge = 0
  96. c.AbortionTimes = 0
  97. c.BreedStatus = pasturePb.BreedStatus_Calving
  98. c.IsPregnant = pasturePb.IsShow_No
  99. c.LastCalvingAt = calvingAt
  100. c.CalvingAge = c.GetCalvingAge()
  101. c.CowType = pasturePb.CowType_Breeding_Calf
  102. c.MilkKind = pasturePb.CowMilk_Lactation
  103. }
  104. // EventWeaningUpdate 断奶更新
  105. func (c *Cow) EventWeaningUpdate(weaningAt int64, penId int32, currentWeight int64) {
  106. c.PenId = penId
  107. c.WeaningAt = weaningAt
  108. c.CurrentWeight = currentWeight
  109. c.LastWeightAt = weaningAt
  110. c.WeaningWeight = currentWeight
  111. }
  112. // EventPregnantCheckUpdate 孕检更新
  113. func (c *Cow) EventPregnantCheckUpdate(breedStatus pasturePb.BreedStatus_Kind, pregnantCheckAt int64,
  114. isPregnant pasturePb.IsShow_Kind, pregnancyCheckName string) {
  115. c.BreedStatus = breedStatus
  116. c.LastPregnantCheckAt = pregnantCheckAt
  117. c.IsPregnant = isPregnant
  118. c.PregnancyCheckName = pregnancyCheckName
  119. }
  120. // EventAbortionUpdate 流产更新
  121. func (c *Cow) EventAbortionUpdate(abortionAt int64, isLact pasturePb.IsShow_Kind) {
  122. c.IsPregnant = pasturePb.IsShow_No
  123. c.LastAbortionAt = abortionAt
  124. c.BreedStatus = pasturePb.BreedStatus_Abort
  125. c.AbortionTimes += 1
  126. c.AllAbortionTimes += 1
  127. c.PregnancyAge = 0
  128. if isLact == pasturePb.IsShow_Ok {
  129. c.Lact += 1
  130. }
  131. }
  132. // EventWeightUpdate 称重更新
  133. func (c *Cow) EventWeightUpdate(weight, height, weightAt int64) {
  134. c.LastSecondWeight = c.CurrentWeight
  135. c.LastSecondWeightAt = c.LastWeightAt
  136. c.LastWeightAt = weightAt
  137. c.CurrentWeight = weight
  138. c.CurrentHeight = height
  139. }
  140. // EventHealthStatusUpdate 健康状态更新
  141. func (c *Cow) EventHealthStatusUpdate(healthStatus pasturePb.HealthStatus_Kind) {
  142. c.HealthStatus = healthStatus
  143. }
  144. // EventPenUpdate 更新栏舍
  145. func (c *Cow) EventPenUpdate(pen *Pen) {
  146. c.PenId = pen.Id
  147. c.PenName = pen.Name
  148. }
  149. // EventEarNumberUpdate 更新耳标号
  150. func (c *Cow) EventEarNumberUpdate(newEarNumber string) {
  151. c.EarOldNumber = c.EarNumber
  152. c.EarNumber = newEarNumber
  153. }
  154. // EventDeathUpdate 更新牛只死亡信息
  155. func (c *Cow) EventDeathUpdate(eventAt int64) {
  156. c.AdmissionStatus = pasturePb.AdmissionStatus_Die
  157. c.HealthStatus = pasturePb.HealthStatus_Dead
  158. c.DepartureAt = eventAt
  159. c.NeckRingNumber = ""
  160. }
  161. // EventSaleUpdate 更新牛只销售信息
  162. func (c *Cow) EventSaleUpdate(eventSale *EventSale) {
  163. c.DepartureAt = eventSale.SaleAt
  164. c.NeckRingNumber = ""
  165. c.DeparturePrice = float32(eventSale.SalePrice)
  166. if eventSale.SaleKind == pasturePb.SalesType_Out {
  167. c.HealthStatus = pasturePb.HealthStatus_Out
  168. c.AdmissionStatus = pasturePb.AdmissionStatus_Out
  169. }
  170. if eventSale.SaleKind == pasturePb.SalesType_Sales {
  171. c.AdmissionStatus = pasturePb.AdmissionStatus_Sale
  172. }
  173. if eventSale.SaleCowCount > 0 {
  174. c.DepartureAvgWeight = eventSale.SaleAllWeight / eventSale.SaleCowCount
  175. }
  176. }
  177. // EventMatingUpdate 配种更新
  178. func (c *Cow) EventMatingUpdate(matingAt int64, bullNumber string, isReMating bool) {
  179. c.LastMatingAt = matingAt
  180. c.LastBullNumber = bullNumber
  181. c.IsPregnant = pasturePb.IsShow_No
  182. c.BreedStatus = pasturePb.BreedStatus_Breeding
  183. if c.FirstMatingAt <= 0 {
  184. c.FirstMatingAt = matingAt
  185. }
  186. if !isReMating {
  187. c.MatingTimes += 1
  188. c.AllMatingTimes += 1
  189. }
  190. if c.Lact == 0 {
  191. c.CowType = pasturePb.CowType_Reserve_Calf
  192. }
  193. }
  194. // EstrusUpdate 发情更新
  195. func (c *Cow) EstrusUpdate(estrusAt int64) {
  196. c.LastEstrusAt = estrusAt
  197. }
  198. // EventDryMilkUpdate 干奶更新
  199. func (c *Cow) EventDryMilkUpdate(dryMilkAt int64, pen *Pen) {
  200. c.LastDryMilkAt = dryMilkAt
  201. c.MilkKind = pasturePb.CowMilk_Dry_Milk
  202. c.PenId = pen.Id
  203. c.PenName = pen.Name
  204. }
  205. // ForbiddenMatingUpdate 禁配更新
  206. func (c *Cow) ForbiddenMatingUpdate(forbiddenMatingAt int64) {
  207. c.IsForbiddenMating = pasturePb.IsShow_Ok
  208. c.LastForbiddenMatingAt = forbiddenMatingAt
  209. c.BreedStatus = pasturePb.BreedStatus_No_Mating
  210. }
  211. // UnForbiddenMatingUpdate 解禁配更新
  212. func (c *Cow) UnForbiddenMatingUpdate() {
  213. c.IsForbiddenMating = pasturePb.IsShow_No
  214. c.LastForbiddenMatingAt = 0
  215. c.BreedStatus = pasturePb.BreedStatus_UnBreed
  216. }
  217. // GetAvgDailyWeight 牛只平均日增重
  218. func (c *Cow) GetAvgDailyWeight() float32 {
  219. if c.AdmissionAge <= 0 {
  220. c.AdmissionAge = c.GetAdmissionAge()
  221. }
  222. if c.AdmissionAge <= 0 {
  223. return 0
  224. }
  225. return float32(c.CurrentWeight-c.AdmissionWeight) / 1000 / float32(c.AdmissionAge)
  226. }
  227. // GetDayAge 日龄
  228. func (c *Cow) GetDayAge() int32 {
  229. if c.BirthAt <= 0 {
  230. return 0
  231. }
  232. return int32(math.Floor(float64(time.Now().Local().Unix()-c.BirthAt) / 86400))
  233. }
  234. // GetEventDayAge 获取事件发生的日龄
  235. func (c *Cow) GetEventDayAge(eventAt int64) int32 {
  236. if c.BirthAt <= 0 {
  237. return 0
  238. }
  239. return int32(math.Floor(float64(eventAt-c.BirthAt) / 86400))
  240. }
  241. // GetCalvingAge 产后天数
  242. func (c *Cow) GetCalvingAge() int32 {
  243. if c.LastCalvingAt <= 0 {
  244. return 0
  245. }
  246. return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastCalvingAt) / 86400))
  247. }
  248. // GetDaysPregnant 怀孕天数
  249. func (c *Cow) GetDaysPregnant() int32 {
  250. if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
  251. c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
  252. c.IsPregnant == pasturePb.IsShow_Ok {
  253. return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastMatingAt) / 86400))
  254. }
  255. return 0
  256. }
  257. // GetDaysPregnancy 牛只预产日期
  258. func (c *Cow) GetDaysPregnancy(pregnancyAgeValue int32) int32 {
  259. if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
  260. c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
  261. c.IsPregnant == pasturePb.IsShow_Ok {
  262. return int32(math.Floor(float64(c.LastMatingAt + int64(pregnancyAgeValue)*86400)))
  263. }
  264. return 0
  265. }
  266. // GetLactationDays 泌乳天数
  267. func (c *Cow) GetLactationDays() int32 {
  268. if c.BreedStatus == pasturePb.BreedStatus_Calving && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  269. return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastCalvingAt) / 86400))
  270. }
  271. return 0
  272. }
  273. // GetAdmissionAge 入场天数
  274. func (c *Cow) GetAdmissionAge() int32 {
  275. if c.AdmissionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  276. return int32(math.Floor(float64(time.Now().Local().Unix()-c.AdmissionAt) / 86400))
  277. }
  278. return 0
  279. }
  280. func (c *Cow) GetEventAdmissionAge(eventAt int64) int32 {
  281. if eventAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  282. return int32(math.Floor(float64(eventAt-c.AdmissionAt) / 86400))
  283. }
  284. return 0
  285. }
  286. // GetAverageDailyWeight 平均日增重(最后一次称重 - 入场体重)÷在群天数
  287. func (c *Cow) GetAverageDailyWeight() float64 {
  288. if c.AdmissionAge <= 0 {
  289. c.AdmissionAge = c.GetAdmissionAge()
  290. }
  291. if c.AdmissionAge <= 0 {
  292. return 0
  293. }
  294. if c.CurrentWeight-c.AdmissionWeight <= 0 {
  295. return 0
  296. }
  297. return float64(c.CurrentWeight-c.AdmissionWeight) / 1000 / float64(c.AdmissionAge)
  298. }
  299. // GetPreviousStageDailyWeight 上一个阶段日增重
  300. func (c *Cow) GetPreviousStageDailyWeight() float64 {
  301. if c.CurrentWeight-c.LastSecondWeight > 0 && c.LastWeightAt-c.LastSecondWeightAt > 0 {
  302. days := int32(math.Floor(float64(c.LastWeightAt-c.LastSecondWeightAt) / 86400))
  303. if days <= 0 {
  304. return float64(c.CurrentWeight - c.LastSecondWeight)
  305. }
  306. dayWeight := math.Round(1.0 * float64(c.CurrentWeight-c.LastSecondWeight) / float64(days))
  307. return dayWeight / 1000
  308. }
  309. return 0
  310. }
  311. // GetAbortionAge 流产天数
  312. func (c *Cow) GetAbortionAge() int32 {
  313. if c.LastAbortionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
  314. return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastAbortionAt) / 86400))
  315. }
  316. return 0
  317. }
  318. // GetLactationAge 泌乳天数
  319. func (c *Cow) GetLactationAge() int32 {
  320. if c.LastCalvingAt <= 0 {
  321. return 0
  322. }
  323. if c.MilkKind == pasturePb.CowMilk_Lactation ||
  324. c.BreedStatus == pasturePb.BreedStatus_Calving ||
  325. c.BreedStatus == pasturePb.BreedStatus_Abort {
  326. return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastCalvingAt) / 86400))
  327. }
  328. return c.LactationAge
  329. }
  330. // GetDryMilkAge 干奶天数
  331. func (c *Cow) GetDryMilkAge() int32 {
  332. if c.MilkKind == pasturePb.CowMilk_Dry_Milk {
  333. return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastDryMilkAt) / 86400))
  334. }
  335. return c.DryMilkAge
  336. }
  337. func (c *Cow) GetMatingAge() int32 {
  338. if c.LastMatingAt <= 0 {
  339. return 0
  340. }
  341. return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastMatingAt) / 86400))
  342. }
  343. type CowSlice []*Cow
  344. func (c CowSlice) ToPB(
  345. cowTypeMap map[pasturePb.CowType_Kind]string,
  346. breedStatusMap map[pasturePb.BreedStatus_Kind]string,
  347. cowKindMap map[pasturePb.CowKind_Kind]string,
  348. cowSourceMap map[pasturePb.CowSource_Kind]string,
  349. admissionStatusMap map[pasturePb.AdmissionStatus_Kind]string,
  350. healthStatusMap map[pasturePb.HealthStatus_Kind]string,
  351. purposeMap map[pasturePb.Purpose_Kind]string,
  352. pregnancyAge int32,
  353. ) []*pasturePb.CowDetails {
  354. res := make([]*pasturePb.CowDetails, len(c))
  355. for i, v := range c {
  356. sex := "公"
  357. if v.Sex == pasturePb.Genders_Female {
  358. sex = "母"
  359. }
  360. lastWeightAtFormat := ""
  361. if v.LastWeightAt > 0 {
  362. lastWeightAtFormat = time.Unix(v.LastWeightAt, 0).Local().Format(LayoutDate2)
  363. }
  364. isPregnantName := ""
  365. if v.IsPregnant == pasturePb.IsShow_Ok {
  366. isPregnantName = "已孕"
  367. } else {
  368. isPregnantName = "未孕"
  369. }
  370. admissionAtFormat := ""
  371. if v.AdmissionAt > 0 {
  372. admissionAtFormat = time.Unix(v.AdmissionAt, 0).Local().Format(LayoutDate2)
  373. }
  374. birthAtFormat := ""
  375. if v.BirthAt > 0 {
  376. birthAtFormat = time.Unix(v.BirthAt, 0).Local().Format(LayoutDate2)
  377. }
  378. weaningAtFormat := ""
  379. if v.WeaningAt > 0 {
  380. weaningAtFormat = time.Unix(v.WeaningAt, 0).Local().Format(LayoutDate2)
  381. }
  382. firstMatingAtFormat := ""
  383. if v.FirstMatingAt > 0 {
  384. firstMatingAtFormat = time.Unix(v.FirstMatingAt, 0).Local().Format(LayoutDate2)
  385. }
  386. lastMatingAtFormat := ""
  387. if v.LastMatingAt > 0 {
  388. lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Local().Format(LayoutDate2)
  389. }
  390. lastPregnantCheckAtFormat := ""
  391. if v.LastPregnantCheckAt > 0 {
  392. lastPregnantCheckAtFormat = time.Unix(v.LastPregnantCheckAt, 0).Local().Format(LayoutDate2)
  393. }
  394. lastCalvingAtFormat := ""
  395. if v.LastCalvingAt > 0 {
  396. lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Local().Format(LayoutDate2)
  397. }
  398. lastAbortionAtFormat := ""
  399. if v.LastAbortionAt > 0 {
  400. lastAbortionAtFormat = time.Unix(v.LastAbortionAt, 0).Local().Format(LayoutDate2)
  401. }
  402. lastSecondWeightAtFormat := ""
  403. if v.LastSecondWeightAt > 0 {
  404. lastSecondWeightAtFormat = time.Unix(v.LastSecondWeightAt, 0).Local().Format(LayoutDate2)
  405. }
  406. departureAtFormat := ""
  407. if v.DepartureAt > 0 {
  408. departureAtFormat = time.Unix(v.DepartureAt, 0).Local().Format(LayoutDate2)
  409. }
  410. lastForbiddenMatingAtFormat := ""
  411. if v.LastForbiddenMatingAt > 0 {
  412. lastForbiddenMatingAtFormat = time.Unix(v.LastForbiddenMatingAt, 0).Local().Format(LayoutDate2)
  413. }
  414. lastEstrusAtFormat := ""
  415. if v.LastEstrusAt > 0 {
  416. lastEstrusAtFormat = time.Unix(v.LastEstrusAt, 0).Local().Format(LayoutDate2)
  417. }
  418. cowTypeName := ""
  419. if cn, ok := cowTypeMap[v.CowType]; ok {
  420. cowTypeName = cn
  421. }
  422. breedStatusName := ""
  423. if bs, ok := breedStatusMap[v.BreedStatus]; ok {
  424. breedStatusName = bs
  425. }
  426. cowKindName := ""
  427. if ck, ok := cowKindMap[v.CowKind]; ok {
  428. cowKindName = ck
  429. }
  430. sourceName := ""
  431. if sn, ok := cowSourceMap[v.SourceKind]; ok {
  432. sourceName = sn
  433. }
  434. admissionStatusName := ""
  435. if as, ok := admissionStatusMap[v.AdmissionStatus]; ok {
  436. admissionStatusName = as
  437. }
  438. healthStatusName := ""
  439. if hs, ok := healthStatusMap[v.HealthStatus]; ok {
  440. healthStatusName = hs
  441. }
  442. pregnancyDate := ""
  443. if pregnancyAgeAt := v.GetDaysPregnancy(pregnancyAge); pregnancyAgeAt > 0 {
  444. pregnancyDate = time.Unix(int64(pregnancyAge), 0).Local().Format(LayoutDate2)
  445. }
  446. purposeName := ""
  447. if pn, ok := purposeMap[v.PurposeKind]; ok {
  448. purposeName = pn
  449. }
  450. pregnancyCheckTimes := "初检"
  451. if v.PregnancyCheckName == PregnantCheckForSecond {
  452. pregnancyCheckTimes = "复检"
  453. }
  454. res[i] = &pasturePb.CowDetails{
  455. CowId: int32(v.Id),
  456. Sex: sex,
  457. NeckRingNumber: v.NeckRingNumber,
  458. PenName: v.PenName,
  459. Lact: v.Lact,
  460. CowTypeName: cowTypeName,
  461. CowType: v.CowType,
  462. BreedStatusName: breedStatusName,
  463. BreedStatus: v.BreedStatus,
  464. CowKindName: cowKindName,
  465. EarNumber: v.EarNumber,
  466. BirthWeight: float32(v.BirthWeight) / 1000,
  467. CurrentWeight: float32(v.CurrentWeight) / 1000,
  468. CurrentHeight: int32(v.CurrentHeight),
  469. DayAge: v.DayAge,
  470. AdmissionAge: v.AdmissionAge,
  471. SourceName: sourceName,
  472. MotherNumber: v.MotherNumber,
  473. FatherNumber: v.FatherNumber,
  474. AdmissionStatusName: admissionStatusName,
  475. HealthStatusName: healthStatusName,
  476. IsPregnantName: isPregnantName,
  477. AdmissionAtFormat: admissionAtFormat,
  478. BirthAtFormat: birthAtFormat,
  479. WeaningAtFormat: weaningAtFormat,
  480. CalvingAge: v.GetCalvingAge(),
  481. AbortionAge: v.AbortionAge,
  482. MatingTimes: v.MatingTimes,
  483. AbortionTimes: v.AbortionTimes,
  484. FirstMatingAtFormat: firstMatingAtFormat,
  485. LastMatingAtFormat: lastMatingAtFormat,
  486. LastBullNumber: v.LastBullNumber,
  487. LastPregnantCheckAtFormat: lastPregnantCheckAtFormat,
  488. LastWeightAtFormat: lastWeightAtFormat,
  489. LastCalvingAtFormat: lastCalvingAtFormat,
  490. LastAbortionAtFormat: lastAbortionAtFormat,
  491. LastSecondWeight: float32(v.LastSecondWeight) / 1000,
  492. LastSecondWeightAtFormat: lastSecondWeightAtFormat,
  493. DepartureAtFormat: departureAtFormat,
  494. DeparturePrice: v.DeparturePrice,
  495. DepartureWeight: float32(v.DepartureAvgWeight / 1000),
  496. LastForbiddenMatingAtFormat: lastForbiddenMatingAtFormat,
  497. LastEstrusAtFormat: lastEstrusAtFormat,
  498. PregnancyDate: pregnancyDate,
  499. PregnancyCheckTimes: pregnancyCheckTimes,
  500. AvgDailyWeight: float32(v.GetAverageDailyWeight()),
  501. EleEarNumber: v.EleEarNumber,
  502. AdmissionPrice: v.AdmissionPrice,
  503. PurposeName: purposeName,
  504. BatchNumber: v.BatchNumber,
  505. AdmissionWeight: float32(v.AdmissionWeight / 1000),
  506. DepartureAvgWeight: float32(v.DepartureAvgWeight / 1000),
  507. WeaningWeight: float32(v.WeaningWeight / 1000),
  508. }
  509. }
  510. return res
  511. }
  512. func (c CowSlice) ToPB2(penWeightSlice PenWeightSlice) []*pasturePb.CowList {
  513. res := make([]*pasturePb.CowList, len(c))
  514. for i, v := range c {
  515. penWeight := penWeightSlice.GetPenWeight(v.PenId)
  516. penAvgWeight := float32(0)
  517. cowPenAvgWeightDiffValue := float32(0)
  518. if penWeight != nil {
  519. penAvgWeight = float32(penWeight.AvgWeight) / 1000
  520. cowPenAvgWeightDiffValue = float32(v.CurrentWeight-int64(penWeight.AvgWeight)) / 1000
  521. }
  522. res[i] = &pasturePb.CowList{
  523. CowId: int32(v.Id),
  524. DayAge: v.DayAge,
  525. AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
  526. EarNumber: v.EarNumber,
  527. PenName: v.PenName,
  528. BirthAt: int32(v.BirthAt),
  529. BirthWeight: float32(v.BirthWeight) / 1000,
  530. CurrentWeight: float32(v.CurrentWeight) / 1000,
  531. LastWeightAt: int32(v.LastWeightAt),
  532. AdmissionAge: v.AdmissionAge,
  533. AdmissionWeight: float32(v.AbortionAge) / 1000,
  534. PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
  535. PenAvgWeight: penAvgWeight,
  536. CowPenAvgWeightDiffValue: cowPenAvgWeightDiffValue,
  537. }
  538. }
  539. return res
  540. }
  541. // NewEnterCow 入场新增牛只
  542. func NewEnterCow(pastureId int64, req *pasturePb.EventEnterRequest, penMap map[int32]*Pen) *Cow {
  543. var isPregnant = pasturePb.IsShow_No
  544. if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
  545. isPregnant = pasturePb.IsShow_Ok
  546. }
  547. admissionAt := int64(0)
  548. switch req.CowSource {
  549. case pasturePb.CowSource_Calving:
  550. admissionAt = int64(req.BirthAt)
  551. case pasturePb.CowSource_Transfer_In:
  552. admissionAt = int64(req.EnterAt)
  553. case pasturePb.CowSource_Buy:
  554. admissionAt = int64(req.EnterAt)
  555. }
  556. breedStatus := pasturePb.BreedStatus_Invalid
  557. isForbiddenMating := pasturePb.IsShow_No
  558. cowType := pasturePb.CowType_Invalid
  559. if req.Sex == pasturePb.Genders_Female {
  560. if req.Lact == 0 && req.MatingAt <= 0 {
  561. breedStatus = pasturePb.BreedStatus_UnBreed
  562. cowType = pasturePb.CowType_Reserve_Calf
  563. }
  564. if req.MatingAt > 0 && (req.PregnantCheckResult != pasturePb.PregnantCheckResult_Pregnant &&
  565. req.PregnantCheckResult != pasturePb.PregnantCheckResult_UnPregnant) &&
  566. req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
  567. breedStatus = pasturePb.BreedStatus_Breeding
  568. if req.Lact == 0 {
  569. cowType = pasturePb.CowType_Reserve_Calf
  570. } else {
  571. cowType = pasturePb.CowType_Breeding_Calf
  572. }
  573. }
  574. if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant &&
  575. req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
  576. breedStatus = pasturePb.BreedStatus_Pregnant
  577. if req.Lact == 0 {
  578. cowType = pasturePb.CowType_Reserve_Calf
  579. } else {
  580. cowType = pasturePb.CowType_Breeding_Calf
  581. }
  582. }
  583. if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant &&
  584. req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
  585. breedStatus = pasturePb.BreedStatus_Empty
  586. if req.Lact == 0 {
  587. cowType = pasturePb.CowType_Reserve_Calf
  588. } else {
  589. cowType = pasturePb.CowType_Breeding_Calf
  590. }
  591. }
  592. if req.CalvingAt > 0 && req.CalvingAt >= req.MatingAt && req.CalvingAt >= req.AbortionAt {
  593. breedStatus = pasturePb.BreedStatus_Calving
  594. cowType = pasturePb.CowType_Breeding_Calf
  595. }
  596. if req.AbortionAt > 0 && req.AbortionAt >= req.CalvingAt && req.AbortionAt >= req.MatingAt {
  597. breedStatus = pasturePb.BreedStatus_Abort
  598. cowType = pasturePb.CowType_Breeding_Calf
  599. }
  600. }
  601. if breedStatus == pasturePb.BreedStatus_No_Mating {
  602. isForbiddenMating = pasturePb.IsShow_Ok
  603. }
  604. cow := &Cow{
  605. PastureId: pastureId,
  606. Sex: req.Sex,
  607. EarNumber: req.EarNumber,
  608. PenId: req.PenId,
  609. PenName: penMap[req.PenId].Name,
  610. Lact: req.Lact,
  611. CowType: cowType,
  612. BreedStatus: breedStatus,
  613. CowKind: req.CowKind,
  614. SourceKind: req.CowSource,
  615. FatherNumber: req.FatherNumber,
  616. MotherNumber: req.MotherNumber,
  617. AdmissionStatus: pasturePb.AdmissionStatus_Admission,
  618. HealthStatus: pasturePb.HealthStatus_Health,
  619. PurposeKind: req.PurposeKind,
  620. EleEarNumber: req.EleEarNumber,
  621. IsPregnant: isPregnant,
  622. IsForbiddenMating: isForbiddenMating,
  623. WeaningAt: int64(req.WeaningAt),
  624. BirthAt: int64(req.BirthAt),
  625. AdmissionWeight: int64(req.Weight * 1000),
  626. FirstMatingAt: int64(req.MatingAt),
  627. LastMatingAt: int64(req.MatingAt),
  628. LastPregnantCheckAt: int64(req.PregnancyCheckAt),
  629. AdmissionAt: admissionAt,
  630. BirthWeight: int64(req.Weight * 1000),
  631. LastWeightAt: int64(req.EstrusAt),
  632. CurrentWeight: int64(req.Weight * 1000),
  633. LastDryMilkAt: int64(req.DryMilkAt),
  634. MatingTimes: req.MatingTimes,
  635. LastCalvingAt: int64(req.CalvingAt),
  636. LastBullNumber: req.BullNumber,
  637. LastAbortionAt: int64(req.AbortionAt),
  638. AdmissionPrice: req.Price,
  639. BatchNumber: req.BatchNumber,
  640. NeckRingNumber: req.NeckRingNumber,
  641. }
  642. cow.AdmissionAge = cow.GetAdmissionAge()
  643. cow.DayAge = cow.GetDayAge()
  644. return cow
  645. }
  646. // NewCalfCow 产犊新增
  647. func NewCalfCow(matherInfo *Cow, calf *CalvingCalf) *Cow {
  648. return &Cow{
  649. PastureId: calf.PastureId,
  650. Sex: calf.Sex,
  651. EarNumber: calf.EarNumber,
  652. PenId: calf.PenId,
  653. PenName: calf.PenName,
  654. CowType: pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
  655. BreedStatus: pasturePb.BreedStatus_UnBreed, // 未配
  656. CowKind: matherInfo.CowKind, // 牛只品种
  657. BirthWeight: calf.BirthWeight,
  658. BirthAt: calf.BirthAt,
  659. SourceKind: pasturePb.CowSource_Calving, // 产犊方式
  660. FatherNumber: matherInfo.LastBullNumber,
  661. MotherNumber: matherInfo.EarNumber,
  662. AdmissionStatus: pasturePb.AdmissionStatus_Admission,
  663. IsPregnant: pasturePb.IsShow_No,
  664. AdmissionAt: calf.BirthAt,
  665. }
  666. }
  667. type BarCowStruct struct {
  668. Number int32 `json:"number"`
  669. TypeId pasturePb.CowType_Kind `json:"type_id"`
  670. }
  671. // BarCowStructSlice 首页牛群结构
  672. type BarCowStructSlice []*BarCowStruct
  673. func (b BarCowStructSlice) ToPB(cowTypeMap map[pasturePb.CowType_Kind]string, count int32) []*pasturePb.BarCowStruct {
  674. var pb []*pasturePb.BarCowStruct
  675. for _, v := range b {
  676. name := fmt.Sprintf("%s", cowTypeMap[v.TypeId])
  677. pb = append(pb, &pasturePb.BarCowStruct{Name: name, Value: v.Number})
  678. }
  679. return pb
  680. }
  681. type CowWeightRange struct {
  682. WeightRange string `json:"weight_range"`
  683. Count int32 `json:"count"`
  684. }
  685. func (c CowSlice) WeightRangeToPB(penMap map[int32]*Pen) []*pasturePb.CowList {
  686. res := make([]*pasturePb.CowList, len(c))
  687. for i, v := range c {
  688. penName := ""
  689. if pen, ok := penMap[v.PenId]; ok {
  690. penName = pen.Name
  691. }
  692. res[i] = &pasturePb.CowList{
  693. CowId: int32(v.Id),
  694. DayAge: v.DayAge,
  695. AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
  696. PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
  697. EarNumber: v.EarNumber,
  698. PenName: penName,
  699. BirthAt: int32(v.BirthAt),
  700. BirthWeight: float32(v.BirthWeight) / 1000,
  701. CurrentWeight: float32(v.CurrentWeight) / 1000,
  702. LastWeightAt: int32(v.LastWeightAt),
  703. AdmissionAge: v.AdmissionAge,
  704. }
  705. }
  706. return res
  707. }
  708. func (c CowSlice) LongTermInfertilityToPB(breedStatusMap map[pasturePb.BreedStatus_Kind]string) []*pasturePb.LongTermInfertility {
  709. res := make([]*pasturePb.LongTermInfertility, len(c))
  710. for i, v := range c {
  711. breedStatusName := ""
  712. if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
  713. breedStatusName = breedStatus
  714. }
  715. lastCalvingAtFormat := ""
  716. if v.LastCalvingAt > 0 {
  717. lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Local().Format(LayoutDate2)
  718. }
  719. lastAbortionAtFormat := ""
  720. if v.LastAbortionAt > 0 {
  721. lastAbortionAtFormat = time.Unix(v.LastAbortionAt, 0).Local().Format(LayoutDate2)
  722. }
  723. lastMatingAtFormat := ""
  724. if v.LastMatingAt > 0 {
  725. lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Local().Format(LayoutDate2)
  726. }
  727. res[i] = &pasturePb.LongTermInfertility{
  728. CowId: int32(v.Id),
  729. EarNumber: v.EarNumber,
  730. Lact: v.Lact,
  731. PenId: v.PenId,
  732. CalvingAge: v.CalvingAge,
  733. PenName: v.PenName,
  734. BreedStatusName: breedStatusName,
  735. BreedStatus: v.BreedStatus,
  736. LastCalvingAtFormat: lastCalvingAtFormat,
  737. LastAbortionAtFormat: lastAbortionAtFormat,
  738. LastMatingAtFormat: lastMatingAtFormat,
  739. MatingTimes: v.MatingTimes,
  740. LastBullNumber: v.LastBullNumber,
  741. AbortionTimes: v.AbortionTimes,
  742. }
  743. }
  744. return res
  745. }
  746. func (c CowSlice) CanSaleToPB(cowKindMap map[pasturePb.CowKind_Kind]string) []*pasturePb.CanSalesReport {
  747. res := make([]*pasturePb.CanSalesReport, len(c))
  748. for i, v := range c {
  749. cowKindName, lastWeightAtFormat, admissionAtFormat := "", "", ""
  750. if name, ok := cowKindMap[v.CowKind]; ok {
  751. cowKindName = name
  752. }
  753. if v.LastWeightAt > 0 {
  754. lastWeightAtFormat = time.Unix(v.LastWeightAt, 0).Local().Format(LayoutDate2)
  755. }
  756. if v.AdmissionAt > 0 {
  757. admissionAtFormat = time.Unix(v.AdmissionAt, 0).Local().Format(LayoutDate2)
  758. }
  759. res[i] = &pasturePb.CanSalesReport{
  760. CowId: int32(v.Id),
  761. EarNumber: v.EarNumber,
  762. BatchNumber: v.BatchNumber,
  763. CowKindName: cowKindName,
  764. PenName: v.PenName,
  765. Weight: float32(v.CurrentWeight) / 1000,
  766. AdmissionAge: v.AdmissionAge,
  767. EnterWeight: 0,
  768. EnterPrice: 0,
  769. LastWeightAtFormat: lastWeightAtFormat,
  770. DayAvgFeedCost: 0,
  771. AllFeedCost: 0,
  772. AllMedicalCharge: 0,
  773. OtherCost: 0,
  774. ProfitAndLoss: 0,
  775. AdmissionAtFormat: admissionAtFormat,
  776. DayAvgWeight: 0,
  777. }
  778. }
  779. return res
  780. }
  781. // CowBehaviorCurveResponse 脖环行为数据
  782. type CowBehaviorCurveResponse struct {
  783. Code int32 `json:"code"`
  784. Msg string `json:"msg"`
  785. Data *CowBehaviorCurveData `json:"data"`
  786. }
  787. type CowBehaviorCurveData struct {
  788. OriginalDateList []int32 `json:"originalDateList"` // 原始行为数据
  789. ChangeDateList []int32 `json:"changeDateList"` // 变化数据
  790. SumDateList []int32 `json:"sumDateList"` // 累计24小时数据
  791. SumChewList []int32 `json:"sumChewList"` // 累计24小时咀嚼
  792. DateTimeList []string `json:"dateTimeList"` // 时间数据
  793. EstrusList map[pasturePb.EstrusLevel_Kind][]string `json:"estrusList"` // 发情预警
  794. EventList []*pasturePb.CowEvent `json:"eventList"` // 事件数据
  795. EventMap map[pasturePb.EventType_Kind]string `json:"eventMap"` // 所有事件
  796. RuminaChange []int32 `json:"ruminaChange"` // 反刍变化
  797. LowActivity int32 `json:"lowActivity"` // 低活动量参数
  798. MiddleActivity int32 `json:"middleActivity"` // 中活动量行数
  799. IQR1 []int32 `json:"IQR1"` // 1IQR
  800. IQR3 []int32 `json:"IQR3"` // 3IQR
  801. }