cow.go 28 KB

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