|
@@ -2,7 +2,6 @@ package model
|
|
|
|
|
|
import (
|
|
import (
|
|
"fmt"
|
|
"fmt"
|
|
- "kpt-pasture/util"
|
|
|
|
"math"
|
|
"math"
|
|
"time"
|
|
"time"
|
|
|
|
|
|
@@ -10,78 +9,396 @@ import (
|
|
)
|
|
)
|
|
|
|
|
|
type Cow struct {
|
|
type Cow struct {
|
|
- Id int64 `json:"id"`
|
|
|
|
- Sex pasturePb.Genders_Kind `json:"sex"`
|
|
|
|
- NeckRingNumber string `json:"neckRingNumber"`
|
|
|
|
- EarNumber string `json:"earNumber"`
|
|
|
|
- EarOldNumber string `json:"earOldNumber"`
|
|
|
|
- PenId int32 `json:"penId"`
|
|
|
|
- Lact int32 `json:"lact"`
|
|
|
|
- DayAge int32 `json:"dayAge"`
|
|
|
|
- CalvingAge int64 `json:"calvingAge"`
|
|
|
|
- PregnancyAge int32 `json:"pregnancyAge"` // 怀孕天数 孕检结果有阳性更新,产犊后至0
|
|
|
|
- AdmissionAge int32 `json:"admissionAge"`
|
|
|
|
- AbortionAge int64 `json:"abortionAge"` // 流产天数
|
|
|
|
- CowType pasturePb.CowType_Kind `json:"cowType"`
|
|
|
|
- BreedStatus pasturePb.BreedStatus_Kind `json:"breedStatus"`
|
|
|
|
- CowKind pasturePb.CowKind_Kind `json:"cowKind"`
|
|
|
|
- BirthWeight int64 `json:"birthWeight"`
|
|
|
|
- CurrentWeight int64 `json:"currentWeight"`
|
|
|
|
- AdmissionWeight int64 `json:"admissionWeight"`
|
|
|
|
- SourceId pasturePb.CowSource_Kind `json:"sourceId"`
|
|
|
|
- FatherNumber string `json:"fatherNumber"`
|
|
|
|
- MotherNumber string `json:"motherNumber"`
|
|
|
|
- AdmissionStatus pasturePb.AdmissionStatus_Kind `json:"admissionStatus"`
|
|
|
|
- IsPregnant pasturePb.IsShow_Kind `json:"isPregnant"`
|
|
|
|
- HealthStatus pasturePb.HealthStatus_Kind `json:"healthStatus"`
|
|
|
|
- WeaningAt int64 `json:"weaningAt"`
|
|
|
|
- BirthAt int64 `json:"birthAt"`
|
|
|
|
- AdmissionAt int64 `json:"admissionAt"`
|
|
|
|
- FirstMatingAt int64 `json:"firstMatingAt"`
|
|
|
|
- MatingTimes int32 `json:"matingTimes"`
|
|
|
|
- LastEstrusAt int64 `json:"lastEstrusAt"`
|
|
|
|
- LastCalvingAt int64 `json:"lastCalvingAt"`
|
|
|
|
- LastMatingAt int64 `json:"lastMatingAt"`
|
|
|
|
- LastBullNumber string `json:"lastBullNumber"`
|
|
|
|
- LastPregnantCheckAt int64 `json:"lastPregnantCheckAt"`
|
|
|
|
- LastDryMilkAt int64 `json:"lastDryMilkAt"`
|
|
|
|
- LastSecondWeight int64 `json:"lastSecondWeight"`
|
|
|
|
- LastSecondWeightAt int64 `json:"lastSecondWeightAt"`
|
|
|
|
- LastAbortionAt int64 `json:"lastAbortionAt"`
|
|
|
|
- LastWeightAt int64 `json:"lastWeightAt"`
|
|
|
|
- CreatedAt int64 `json:"createdAt"`
|
|
|
|
- UpdatedAt int64 `json:"updatedAt"`
|
|
|
|
|
|
+ Id int64 `json:"id"`
|
|
|
|
+ PastureId int64 `json:"pastureId"` // 牧场id
|
|
|
|
+ Sex pasturePb.Genders_Kind `json:"sex"` // 性别
|
|
|
|
+ NeckRingNumber string `json:"neckRingNumber"` // 脖环号
|
|
|
|
+ EarNumber string `json:"earNumber"` // 耳标号
|
|
|
|
+ EleEarNumber string `json:"eleEarNumber"` // 电子耳标号
|
|
|
|
+ EarOldNumber string `json:"earOldNumber"` // 旧耳标号
|
|
|
|
+ PenId int32 `json:"penId"` // 栏舍id
|
|
|
|
+ PenName string `json:"penName"` // 栏舍名称
|
|
|
|
+ Lact int32 `json:"lact"` // 胎次
|
|
|
|
+ DayAge int32 `json:"dayAge"` // 日龄
|
|
|
|
+ CalvingAge int32 `json:"calvingAge"` // 产后天使
|
|
|
|
+ PregnancyAge int32 `json:"pregnancyAge"` // 怀孕天数 孕检结果有阳性更新,产犊后至0
|
|
|
|
+ MatingAge int32 `json:"matingAge"` // 配种天数
|
|
|
|
+ AdmissionAge int32 `json:"admissionAge"` // 入场日龄
|
|
|
|
+ AbortionAge int32 `json:"abortionAge"` // 流产天数
|
|
|
|
+ LactationAge int32 `json:"lactationAge"` // 泌乳天数
|
|
|
|
+ DryMilkAge int32 `json:"dryMilkAge"` // 干奶天数
|
|
|
|
+ CowType pasturePb.CowType_Kind `json:"cowType"` // 牛只类型
|
|
|
|
+ MilkKind pasturePb.CowMilk_Kind `json:"milkKind"` // 牛只奶属性
|
|
|
|
+ BreedStatus pasturePb.BreedStatus_Kind `json:"breedStatus"` // 繁殖状态
|
|
|
|
+ CowKind pasturePb.CowKind_Kind `json:"cowKind"` // 牛只品种
|
|
|
|
+ BirthWeight int64 `json:"birthWeight"` // 出生体重
|
|
|
|
+ CurrentWeight int64 `json:"currentWeight"` // 当前体重
|
|
|
|
+ CurrentHeight int64 `json:"currentHeight"` // 当前身高
|
|
|
|
+ AdmissionWeight int64 `json:"admissionWeight"` // 入场体重
|
|
|
|
+ AdmissionPrice float32 `json:"admissionPrice"` // 入场价格
|
|
|
|
+ SourceKind pasturePb.CowSource_Kind `json:"sourceKind"` // 来源哪里
|
|
|
|
+ PurposeKind pasturePb.Purpose_Kind `json:"purposeKind"` // 用途
|
|
|
|
+ FatherNumber string `json:"fatherNumber"` // 父号
|
|
|
|
+ MotherNumber string `json:"motherNumber"` // 母号
|
|
|
|
+ AdmissionStatus pasturePb.AdmissionStatus_Kind `json:"admissionStatus"` // 在场状态
|
|
|
|
+ IsPregnant pasturePb.IsShow_Kind `json:"isPregnant"` // 是否怀孕
|
|
|
|
+ IsForbiddenMating pasturePb.IsShow_Kind `json:"isForbiddenMating"` // 是否禁配 1 是 2 否
|
|
|
|
+ HealthStatus pasturePb.HealthStatus_Kind `json:"healthStatus"` // 健康状态
|
|
|
|
+ WeaningAt int64 `json:"weaningAt"` // 断奶时间
|
|
|
|
+ BirthAt int64 `json:"birthAt"` // 出生时间
|
|
|
|
+ AdmissionAt int64 `json:"admissionAt"` // 入场时间
|
|
|
|
+ DepartureAt int64 `json:"departureAt"` // 离场时间
|
|
|
|
+ DeparturePrice float32 `json:"departurePrice"` // 离场价格
|
|
|
|
+ DepartureAvgWeight int32 `json:"departureAvgWeight"` // 离场平均体重
|
|
|
|
+ FirstMatingAt int64 `json:"firstMatingAt"` // 首次配种时间
|
|
|
|
+ AllMatingTimes int32 `json:"allMatingTimes"` // 总配次
|
|
|
|
+ AllAbortionTimes int32 `json:"allAbortionTimes"` // 总流产次数
|
|
|
|
+ MatingTimes int32 `json:"matingTimes"` // 配种次数
|
|
|
|
+ AbortionTimes int32 `json:"abortionTimes"` // 流产次数
|
|
|
|
+ PregnancyCheckName string `json:"pregnancyCheckName"` // 孕检名称
|
|
|
|
+ WeeklyActive int32 `json:"weeklyActive"` // 每周活跃度
|
|
|
|
+ LastEstrusAt int64 `json:"lastEstrusAt"` // 最后一次发情时间
|
|
|
|
+ LastCalvingAt int64 `json:"lastCalvingAt"` // 最后一次产犊时间
|
|
|
|
+ LastMatingAt int64 `json:"lastMatingAt"` // 最后一次配种时间
|
|
|
|
+ LastBullNumber string `json:"lastBullNumber"` // 最后一次配种牛号
|
|
|
|
+ LastPregnantCheckAt int64 `json:"lastPregnantCheckAt"` // 最后一次孕检时间
|
|
|
|
+ LastDryMilkAt int64 `json:"lastDryMilkAt"` // 最近一次干奶日期
|
|
|
|
+ LastForbiddenMatingAt int64 `json:"lastForbiddenMatingAt"` // 最近一次禁配时间
|
|
|
|
+ LastSecondWeight int64 `json:"lastSecondWeight"` // 最后第二次称重
|
|
|
|
+ LastSecondWeightAt int64 `json:"lastSecondWeightAt"` // 最后第二次称重时间
|
|
|
|
+ LastAbortionAt int64 `json:"lastAbortionAt"` // 最近一次流产时间
|
|
|
|
+ LastWeightAt int64 `json:"lastWeightAt"` // 最近一次称重时间
|
|
|
|
+ BatchNumber string `json:"batchNumber"` // 批次号
|
|
|
|
+ CreatedAt int64 `json:"createdAt"`
|
|
|
|
+ UpdatedAt int64 `json:"updatedAt"`
|
|
}
|
|
}
|
|
|
|
|
|
func (c *Cow) TableName() string {
|
|
func (c *Cow) TableName() string {
|
|
return "cow"
|
|
return "cow"
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// EventUpdate 牛只基本信息维护
|
|
|
|
+func (c *Cow) EventUpdate(weeklyActive int32) {
|
|
|
|
+ c.DayAge = c.GetDayAge() // 日龄
|
|
|
|
+ c.CalvingAge = c.GetCalvingAge() // 产后天数
|
|
|
|
+ c.PregnancyAge = c.GetDaysPregnant() // 怀孕天数
|
|
|
|
+ c.AdmissionAge = c.GetAdmissionAge() // 入场天数
|
|
|
|
+ c.AbortionAge = c.GetAbortionAge() // 流产天数
|
|
|
|
+ c.WeeklyActive = weeklyActive // 周活动量
|
|
|
|
+ c.LactationAge = c.GetLactationAge() // 泌乳天数
|
|
|
|
+ c.DryMilkAge = c.GetDryMilkAge() // 干奶天数
|
|
|
|
+ c.MatingAge = c.GetMatingAge() // 配后天数
|
|
|
|
+ if c.DayAge == 60 {
|
|
|
|
+ c.CowType = pasturePb.CowType_Weaned_Calf
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventCalvingUpdate 产犊更新
|
|
|
|
+func (c *Cow) EventCalvingUpdate(calvingAt int64) {
|
|
|
|
+ c.Lact += 1
|
|
|
|
+ c.MatingTimes = 0
|
|
|
|
+ c.PregnancyAge = 0
|
|
|
|
+ c.AbortionTimes = 0
|
|
|
|
+ c.BreedStatus = pasturePb.BreedStatus_Calving
|
|
|
|
+ c.IsPregnant = pasturePb.IsShow_No
|
|
|
|
+ c.LastCalvingAt = calvingAt
|
|
|
|
+ c.CalvingAge = c.GetCalvingAge()
|
|
|
|
+ c.CowType = pasturePb.CowType_Breeding_Calf
|
|
|
|
+ c.MilkKind = pasturePb.CowMilk_Lactation
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventWeaningUpdate 断奶更新
|
|
|
|
+func (c *Cow) EventWeaningUpdate(weaningAt int64, penId int32, currentWeight int64) {
|
|
|
|
+ c.PenId = penId
|
|
|
|
+ c.WeaningAt = weaningAt
|
|
|
|
+ c.CurrentWeight = currentWeight
|
|
|
|
+ c.LastWeightAt = weaningAt
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventPregnantCheckUpdate 孕检更新
|
|
|
|
+func (c *Cow) EventPregnantCheckUpdate(breedStatus pasturePb.BreedStatus_Kind, pregnantCheckAt int64,
|
|
|
|
+ isPregnant pasturePb.IsShow_Kind, pregnancyCheckName string) {
|
|
|
|
+ c.BreedStatus = breedStatus
|
|
|
|
+ c.LastPregnantCheckAt = pregnantCheckAt
|
|
|
|
+ c.IsPregnant = isPregnant
|
|
|
|
+ c.PregnancyCheckName = pregnancyCheckName
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventAbortionUpdate 流产更新
|
|
|
|
+func (c *Cow) EventAbortionUpdate(abortionAt int64, isLact pasturePb.IsShow_Kind) {
|
|
|
|
+ c.IsPregnant = pasturePb.IsShow_No
|
|
|
|
+ c.LastAbortionAt = abortionAt
|
|
|
|
+ c.BreedStatus = pasturePb.BreedStatus_Abort
|
|
|
|
+ c.AbortionTimes += 1
|
|
|
|
+ c.AllAbortionTimes += 1
|
|
|
|
+ c.PregnancyAge = 0
|
|
|
|
+ if isLact == pasturePb.IsShow_Ok {
|
|
|
|
+ c.Lact += 1
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventWeightUpdate 称重更新
|
|
|
|
+func (c *Cow) EventWeightUpdate(weight, height, weightAt int64) {
|
|
|
|
+ c.LastSecondWeight = c.CurrentWeight
|
|
|
|
+ c.LastSecondWeightAt = c.LastWeightAt
|
|
|
|
+ c.LastWeightAt = weightAt
|
|
|
|
+ c.CurrentWeight = weight
|
|
|
|
+ c.CurrentHeight = height
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventHealthStatusUpdate 健康状态更新
|
|
|
|
+func (c *Cow) EventHealthStatusUpdate(healthStatus pasturePb.HealthStatus_Kind) {
|
|
|
|
+ c.HealthStatus = healthStatus
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventPenUpdate 更新栏舍
|
|
|
|
+func (c *Cow) EventPenUpdate(pen *Pen) {
|
|
|
|
+ c.PenId = pen.Id
|
|
|
|
+ c.PenName = pen.Name
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventEarNumberUpdate 更新耳标号
|
|
|
|
+func (c *Cow) EventEarNumberUpdate(newEarNumber string) {
|
|
|
|
+ c.EarOldNumber = c.EarNumber
|
|
|
|
+ c.EarNumber = newEarNumber
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventDeathUpdate 更新牛只死亡信息
|
|
|
|
+func (c *Cow) EventDeathUpdate(eventAt int64) {
|
|
|
|
+ c.AdmissionStatus = pasturePb.AdmissionStatus_Die
|
|
|
|
+ c.HealthStatus = pasturePb.HealthStatus_Dead
|
|
|
|
+ c.DepartureAt = eventAt
|
|
|
|
+ c.NeckRingNumber = ""
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventSaleUpdate 更新牛只销售信息
|
|
|
|
+func (c *Cow) EventSaleUpdate(eventSale *EventSale) {
|
|
|
|
+ c.DepartureAt = eventSale.SaleAt
|
|
|
|
+ c.NeckRingNumber = ""
|
|
|
|
+ c.DeparturePrice = float32(eventSale.SalePrice)
|
|
|
|
+ if eventSale.SaleKind == pasturePb.SalesType_Out {
|
|
|
|
+ c.HealthStatus = pasturePb.HealthStatus_Out
|
|
|
|
+ c.AdmissionStatus = pasturePb.AdmissionStatus_Out
|
|
|
|
+ }
|
|
|
|
+ if eventSale.SaleKind == pasturePb.SalesType_Sales {
|
|
|
|
+ c.AdmissionStatus = pasturePb.AdmissionStatus_Sale
|
|
|
|
+ }
|
|
|
|
+ if eventSale.SaleCowCount > 0 {
|
|
|
|
+ c.DepartureAvgWeight = eventSale.SaleAllWeight / eventSale.SaleCowCount
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventMatingUpdate 配种更新
|
|
|
|
+func (c *Cow) EventMatingUpdate(matingAt int64, bullNumber string, isReMating bool) {
|
|
|
|
+ c.LastMatingAt = matingAt
|
|
|
|
+ c.LastBullNumber = bullNumber
|
|
|
|
+ c.IsPregnant = pasturePb.IsShow_No
|
|
|
|
+ c.BreedStatus = pasturePb.BreedStatus_Breeding
|
|
|
|
+ if c.FirstMatingAt <= 0 {
|
|
|
|
+ c.FirstMatingAt = matingAt
|
|
|
|
+ }
|
|
|
|
+ if !isReMating {
|
|
|
|
+ c.MatingTimes += 1
|
|
|
|
+ c.AllMatingTimes += 1
|
|
|
|
+ }
|
|
|
|
+ if c.Lact == 0 {
|
|
|
|
+ c.CowType = pasturePb.CowType_Reserve_Calf
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EstrusUpdate 发情更新
|
|
|
|
+func (c *Cow) EstrusUpdate(estrusAt int64) {
|
|
|
|
+ c.LastEstrusAt = estrusAt
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EventDryMilkUpdate 干奶更新
|
|
|
|
+func (c *Cow) EventDryMilkUpdate(dryMilkAt int64, pen *Pen) {
|
|
|
|
+ c.LastDryMilkAt = dryMilkAt
|
|
|
|
+ c.MilkKind = pasturePb.CowMilk_Dry_Milk
|
|
|
|
+ c.PenId = pen.Id
|
|
|
|
+ c.PenName = pen.Name
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ForbiddenMatingUpdate 禁配更新
|
|
|
|
+func (c *Cow) ForbiddenMatingUpdate(forbiddenMatingAt int64) {
|
|
|
|
+ c.IsForbiddenMating = pasturePb.IsShow_Ok
|
|
|
|
+ c.LastForbiddenMatingAt = forbiddenMatingAt
|
|
|
|
+ c.BreedStatus = pasturePb.BreedStatus_No_Mating
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// UnForbiddenMatingUpdate 解禁配更新
|
|
|
|
+func (c *Cow) UnForbiddenMatingUpdate() {
|
|
|
|
+ c.IsForbiddenMating = pasturePb.IsShow_No
|
|
|
|
+ c.LastForbiddenMatingAt = 0
|
|
|
|
+ c.BreedStatus = pasturePb.BreedStatus_UnBreed
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetAvgDailyWeight 牛只平均日增重
|
|
|
|
+func (c *Cow) GetAvgDailyWeight() float32 {
|
|
|
|
+ if c.AdmissionAge <= 0 {
|
|
|
|
+ c.AdmissionAge = c.GetAdmissionAge()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if c.AdmissionAge <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+ return float32(c.CurrentWeight-c.AdmissionWeight) / 1000 / float32(c.AdmissionAge)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetDayAge 日龄
|
|
|
|
+func (c *Cow) GetDayAge() int32 {
|
|
|
|
+ if c.BirthAt <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.BirthAt) / 86400))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetEventDayAge 获取事件发生的日龄
|
|
|
|
+func (c *Cow) GetEventDayAge(eventAt int64) int32 {
|
|
|
|
+ if c.BirthAt <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+ return int32(math.Floor(float64(eventAt-c.BirthAt) / 86400))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetCalvingAge 产后天数
|
|
|
|
+func (c *Cow) GetCalvingAge() int32 {
|
|
|
|
+ if c.LastCalvingAt <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastCalvingAt) / 86400))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetDaysPregnant 怀孕天数
|
|
|
|
+func (c *Cow) GetDaysPregnant() int32 {
|
|
|
|
+ if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
|
|
|
|
+ c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
|
|
|
|
+ c.IsPregnant == pasturePb.IsShow_Ok {
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastMatingAt) / 86400))
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetDaysPregnancy 牛只预产日期
|
|
|
|
+func (c *Cow) GetDaysPregnancy(pregnancyAgeValue int32) int32 {
|
|
|
|
+ if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
|
|
|
|
+ c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
|
|
|
|
+ c.IsPregnant == pasturePb.IsShow_Ok {
|
|
|
|
+ return int32(math.Floor(float64(c.LastMatingAt + int64(pregnancyAgeValue)*86400)))
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetLactationDays 泌乳天数
|
|
|
|
+func (c *Cow) GetLactationDays() int32 {
|
|
|
|
+ if c.BreedStatus == pasturePb.BreedStatus_Calving && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastCalvingAt) / 86400))
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetAdmissionAge 入场天数
|
|
|
|
+func (c *Cow) GetAdmissionAge() int32 {
|
|
|
|
+ if c.AdmissionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.AdmissionAt) / 86400))
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (c *Cow) GetEventAdmissionAge(eventAt int64) int32 {
|
|
|
|
+ if eventAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
|
|
|
|
+ return int32(math.Floor(float64(eventAt-c.AdmissionAt) / 86400))
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetAverageDailyWeight 平均日增重(最后一次称重 - 入场体重)÷在群天数
|
|
|
|
+func (c *Cow) GetAverageDailyWeight() float64 {
|
|
|
|
+ if c.AdmissionAge <= 0 {
|
|
|
|
+ c.AdmissionAge = c.GetAdmissionAge()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if c.AdmissionAge <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if c.CurrentWeight-c.AdmissionWeight <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+ return float64(c.CurrentWeight-c.AdmissionWeight) / 1000 / float64(c.AdmissionAge)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetPreviousStageDailyWeight 上一个阶段日增重
|
|
|
|
+func (c *Cow) GetPreviousStageDailyWeight() float64 {
|
|
|
|
+ if c.CurrentWeight-c.LastSecondWeight > 0 && c.LastWeightAt-c.LastSecondWeightAt > 0 {
|
|
|
|
+ days := int32(math.Floor(float64(c.LastWeightAt-c.LastSecondWeightAt) / 86400))
|
|
|
|
+ if days <= 0 {
|
|
|
|
+ return float64(c.CurrentWeight - c.LastSecondWeight)
|
|
|
|
+ }
|
|
|
|
+ dayWeight := math.Round(1.0 * float64(c.CurrentWeight-c.LastSecondWeight) / float64(days))
|
|
|
|
+ return dayWeight / 1000
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetAbortionAge 流产天数
|
|
|
|
+func (c *Cow) GetAbortionAge() int32 {
|
|
|
|
+ if c.LastAbortionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastAbortionAt) / 86400))
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetLactationAge 泌乳天数
|
|
|
|
+func (c *Cow) GetLactationAge() int32 {
|
|
|
|
+ if c.LastCalvingAt <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if c.MilkKind == pasturePb.CowMilk_Lactation ||
|
|
|
|
+ c.BreedStatus == pasturePb.BreedStatus_Calving ||
|
|
|
|
+ c.BreedStatus == pasturePb.BreedStatus_Abort {
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastCalvingAt) / 86400))
|
|
|
|
+ }
|
|
|
|
+ return c.LactationAge
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetDryMilkAge 干奶天数
|
|
|
|
+func (c *Cow) GetDryMilkAge() int32 {
|
|
|
|
+ if c.MilkKind == pasturePb.CowMilk_Dry_Milk {
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastDryMilkAt) / 86400))
|
|
|
|
+ }
|
|
|
|
+ return c.DryMilkAge
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (c *Cow) GetMatingAge() int32 {
|
|
|
|
+ if c.LastMatingAt <= 0 {
|
|
|
|
+ return 0
|
|
|
|
+ }
|
|
|
|
+ return int32(math.Floor(float64(time.Now().Local().Unix()-c.LastMatingAt) / 86400))
|
|
|
|
+}
|
|
|
|
+
|
|
type CowSlice []*Cow
|
|
type CowSlice []*Cow
|
|
|
|
|
|
func (c CowSlice) ToPB(
|
|
func (c CowSlice) ToPB(
|
|
- penMap map[int32]*Pen,
|
|
|
|
cowTypeMap map[pasturePb.CowType_Kind]string,
|
|
cowTypeMap map[pasturePb.CowType_Kind]string,
|
|
breedStatusMap map[pasturePb.BreedStatus_Kind]string,
|
|
breedStatusMap map[pasturePb.BreedStatus_Kind]string,
|
|
cowKindMap map[pasturePb.CowKind_Kind]string,
|
|
cowKindMap map[pasturePb.CowKind_Kind]string,
|
|
cowSourceMap map[pasturePb.CowSource_Kind]string,
|
|
cowSourceMap map[pasturePb.CowSource_Kind]string,
|
|
admissionStatusMap map[pasturePb.AdmissionStatus_Kind]string,
|
|
admissionStatusMap map[pasturePb.AdmissionStatus_Kind]string,
|
|
healthStatusMap map[pasturePb.HealthStatus_Kind]string,
|
|
healthStatusMap map[pasturePb.HealthStatus_Kind]string,
|
|
|
|
+ purposeMap map[pasturePb.Purpose_Kind]string,
|
|
|
|
+ pregnancyAge int32,
|
|
) []*pasturePb.CowDetails {
|
|
) []*pasturePb.CowDetails {
|
|
res := make([]*pasturePb.CowDetails, len(c))
|
|
res := make([]*pasturePb.CowDetails, len(c))
|
|
for i, v := range c {
|
|
for i, v := range c {
|
|
- penName := ""
|
|
|
|
- if pen, ok := penMap[v.PenId]; ok {
|
|
|
|
- penName = pen.Name
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
sex := "公"
|
|
sex := "公"
|
|
if v.Sex == pasturePb.Genders_Female {
|
|
if v.Sex == pasturePb.Genders_Female {
|
|
sex = "母"
|
|
sex = "母"
|
|
}
|
|
}
|
|
lastWeightAtFormat := ""
|
|
lastWeightAtFormat := ""
|
|
if v.LastWeightAt > 0 {
|
|
if v.LastWeightAt > 0 {
|
|
- lastWeightAtFormat = time.Unix(v.LastWeightAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ lastWeightAtFormat = time.Unix(v.LastWeightAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
|
|
isPregnantName := ""
|
|
isPregnantName := ""
|
|
@@ -93,111 +410,191 @@ func (c CowSlice) ToPB(
|
|
|
|
|
|
admissionAtFormat := ""
|
|
admissionAtFormat := ""
|
|
if v.AdmissionAt > 0 {
|
|
if v.AdmissionAt > 0 {
|
|
- admissionAtFormat = time.Unix(v.AdmissionAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ admissionAtFormat = time.Unix(v.AdmissionAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
|
|
birthAtFormat := ""
|
|
birthAtFormat := ""
|
|
if v.BirthAt > 0 {
|
|
if v.BirthAt > 0 {
|
|
- birthAtFormat = time.Unix(v.BirthAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ birthAtFormat = time.Unix(v.BirthAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
|
|
weaningAtFormat := ""
|
|
weaningAtFormat := ""
|
|
if v.WeaningAt > 0 {
|
|
if v.WeaningAt > 0 {
|
|
- weaningAtFormat = time.Unix(v.WeaningAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ weaningAtFormat = time.Unix(v.WeaningAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
|
|
firstMatingAtFormat := ""
|
|
firstMatingAtFormat := ""
|
|
if v.FirstMatingAt > 0 {
|
|
if v.FirstMatingAt > 0 {
|
|
- firstMatingAtFormat = time.Unix(v.FirstMatingAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ firstMatingAtFormat = time.Unix(v.FirstMatingAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
|
|
lastMatingAtFormat := ""
|
|
lastMatingAtFormat := ""
|
|
if v.LastMatingAt > 0 {
|
|
if v.LastMatingAt > 0 {
|
|
- lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
|
|
lastPregnantCheckAtFormat := ""
|
|
lastPregnantCheckAtFormat := ""
|
|
if v.LastPregnantCheckAt > 0 {
|
|
if v.LastPregnantCheckAt > 0 {
|
|
- lastPregnantCheckAtFormat = time.Unix(v.LastPregnantCheckAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ lastPregnantCheckAtFormat = time.Unix(v.LastPregnantCheckAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
|
|
lastCalvingAtFormat := ""
|
|
lastCalvingAtFormat := ""
|
|
if v.LastCalvingAt > 0 {
|
|
if v.LastCalvingAt > 0 {
|
|
- lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Format(LayoutDate2)
|
|
|
|
|
|
+ lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lastAbortionAtFormat := ""
|
|
|
|
+ if v.LastAbortionAt > 0 {
|
|
|
|
+ lastAbortionAtFormat = time.Unix(v.LastAbortionAt, 0).Local().Format(LayoutDate2)
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ lastSecondWeightAtFormat := ""
|
|
|
|
+ if v.LastSecondWeightAt > 0 {
|
|
|
|
+ lastSecondWeightAtFormat = time.Unix(v.LastSecondWeightAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ departureAtFormat := ""
|
|
|
|
+ if v.DepartureAt > 0 {
|
|
|
|
+ departureAtFormat = time.Unix(v.DepartureAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lastForbiddenMatingAtFormat := ""
|
|
|
|
+ if v.LastForbiddenMatingAt > 0 {
|
|
|
|
+ lastForbiddenMatingAtFormat = time.Unix(v.LastForbiddenMatingAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lastEstrusAtFormat := ""
|
|
|
|
+ if v.LastEstrusAt > 0 {
|
|
|
|
+ lastEstrusAtFormat = time.Unix(v.LastEstrusAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cowTypeName := ""
|
|
|
|
+ if cn, ok := cowTypeMap[v.CowType]; ok {
|
|
|
|
+ cowTypeName = cn
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ breedStatusName := ""
|
|
|
|
+ if bs, ok := breedStatusMap[v.BreedStatus]; ok {
|
|
|
|
+ breedStatusName = bs
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cowKindName := ""
|
|
|
|
+ if ck, ok := cowKindMap[v.CowKind]; ok {
|
|
|
|
+ cowKindName = ck
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sourceName := ""
|
|
|
|
+ if sn, ok := cowSourceMap[v.SourceKind]; ok {
|
|
|
|
+ sourceName = sn
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ admissionStatusName := ""
|
|
|
|
+ if as, ok := admissionStatusMap[v.AdmissionStatus]; ok {
|
|
|
|
+ admissionStatusName = as
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ healthStatusName := ""
|
|
|
|
+ if hs, ok := healthStatusMap[v.HealthStatus]; ok {
|
|
|
|
+ healthStatusName = hs
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pregnancyDate := ""
|
|
|
|
+ if pregnancyAgeAt := v.GetDaysPregnancy(pregnancyAge); pregnancyAgeAt > 0 {
|
|
|
|
+ pregnancyDate = time.Unix(int64(pregnancyAge), 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ purposeName := ""
|
|
|
|
+ if pn, ok := purposeMap[v.PurposeKind]; ok {
|
|
|
|
+ purposeName = pn
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pregnancyCheckTimes := "初检"
|
|
|
|
+ if v.PregnancyCheckName == PregnantCheckForSecond {
|
|
|
|
+ pregnancyCheckTimes = "复检"
|
|
|
|
+ }
|
|
|
|
+
|
|
res[i] = &pasturePb.CowDetails{
|
|
res[i] = &pasturePb.CowDetails{
|
|
- CowId: int32(v.Id),
|
|
|
|
- Sex: sex,
|
|
|
|
- NeckRingNumber: v.NeckRingNumber,
|
|
|
|
- PenName: penName,
|
|
|
|
- Lact: v.Lact,
|
|
|
|
- CowTypeName: cowTypeMap[v.CowType],
|
|
|
|
- BreedStatusName: breedStatusMap[v.BreedStatus],
|
|
|
|
- CowKindName: cowKindMap[v.CowKind],
|
|
|
|
- EarNumber: v.EarNumber,
|
|
|
|
- BirthWeight: float32(v.BirthWeight) / 1000,
|
|
|
|
- CurrentWeight: float32(v.CurrentWeight) / 1000,
|
|
|
|
- DayAge: v.DayAge,
|
|
|
|
- SourceName: cowSourceMap[v.SourceId],
|
|
|
|
- MontherNumber: v.MotherNumber,
|
|
|
|
- FatherNumber: v.FatherNumber,
|
|
|
|
- AdmissionStatusName: admissionStatusMap[v.AdmissionStatus],
|
|
|
|
- HealthStatusName: healthStatusMap[v.HealthStatus],
|
|
|
|
- IsPregnantName: isPregnantName,
|
|
|
|
- AdmissionAtFormat: admissionAtFormat,
|
|
|
|
- BirthAtFormat: birthAtFormat,
|
|
|
|
- WeaningAtFormat: weaningAtFormat,
|
|
|
|
- CalvingAge: int32(v.GetCalvingAge()),
|
|
|
|
- AbortionAge: int32(v.AbortionAge),
|
|
|
|
- MatingTimes: v.MatingTimes,
|
|
|
|
- FirstMatingAtFormat: firstMatingAtFormat,
|
|
|
|
- LastMatingAtFormat: lastMatingAtFormat,
|
|
|
|
- LastBullNumber: v.LastBullNumber,
|
|
|
|
- LastPregnantCheckAtFormat: lastPregnantCheckAtFormat,
|
|
|
|
- LastWeightAtFormat: lastWeightAtFormat,
|
|
|
|
- LastCalvingAtFormat: lastCalvingAtFormat,
|
|
|
|
- //PregnancyAge: v.PregnancyAge,
|
|
|
|
|
|
+ CowId: int32(v.Id),
|
|
|
|
+ Sex: sex,
|
|
|
|
+ NeckRingNumber: v.NeckRingNumber,
|
|
|
|
+ PenName: v.PenName,
|
|
|
|
+ Lact: v.Lact,
|
|
|
|
+ CowTypeName: cowTypeName,
|
|
|
|
+ CowType: v.CowType,
|
|
|
|
+ BreedStatusName: breedStatusName,
|
|
|
|
+ BreedStatus: v.BreedStatus,
|
|
|
|
+ CowKindName: cowKindName,
|
|
|
|
+ EarNumber: v.EarNumber,
|
|
|
|
+ BirthWeight: float32(v.BirthWeight) / 1000,
|
|
|
|
+ CurrentWeight: float32(v.CurrentWeight) / 1000,
|
|
|
|
+ CurrentHeight: int32(v.CurrentHeight),
|
|
|
|
+ DayAge: v.DayAge,
|
|
|
|
+ AdmissionAge: v.AdmissionAge,
|
|
|
|
+ SourceName: sourceName,
|
|
|
|
+ MotherNumber: v.MotherNumber,
|
|
|
|
+ FatherNumber: v.FatherNumber,
|
|
|
|
+ AdmissionStatusName: admissionStatusName,
|
|
|
|
+ HealthStatusName: healthStatusName,
|
|
|
|
+ IsPregnantName: isPregnantName,
|
|
|
|
+ AdmissionAtFormat: admissionAtFormat,
|
|
|
|
+ BirthAtFormat: birthAtFormat,
|
|
|
|
+ WeaningAtFormat: weaningAtFormat,
|
|
|
|
+ CalvingAge: v.GetCalvingAge(),
|
|
|
|
+ AbortionAge: v.AbortionAge,
|
|
|
|
+ MatingTimes: v.MatingTimes,
|
|
|
|
+ AbortionTimes: v.AbortionTimes,
|
|
|
|
+ FirstMatingAtFormat: firstMatingAtFormat,
|
|
|
|
+ LastMatingAtFormat: lastMatingAtFormat,
|
|
|
|
+ LastBullNumber: v.LastBullNumber,
|
|
|
|
+ LastPregnantCheckAtFormat: lastPregnantCheckAtFormat,
|
|
|
|
+ LastWeightAtFormat: lastWeightAtFormat,
|
|
|
|
+ LastCalvingAtFormat: lastCalvingAtFormat,
|
|
|
|
+ LastAbortionAtFormat: lastAbortionAtFormat,
|
|
|
|
+ LastSecondWeight: float32(v.LastSecondWeight) / 1000,
|
|
|
|
+ LastSecondWeightAtFormat: lastSecondWeightAtFormat,
|
|
|
|
+ DepartureAtFormat: departureAtFormat,
|
|
|
|
+ DeparturePrice: v.DeparturePrice,
|
|
|
|
+ DepartureWeight: float32(v.DepartureAvgWeight / 1000),
|
|
|
|
+ LastForbiddenMatingAtFormat: lastForbiddenMatingAtFormat,
|
|
|
|
+ LastEstrusAtFormat: lastEstrusAtFormat,
|
|
|
|
+ PregnancyDate: pregnancyDate,
|
|
|
|
+ PregnancyCheckTimes: pregnancyCheckTimes,
|
|
|
|
+ AvgDailyWeight: float32(v.GetAverageDailyWeight()),
|
|
|
|
+ EleEarNumber: v.EleEarNumber,
|
|
|
|
+ AdmissionPrice: v.AdmissionPrice,
|
|
|
|
+ PurposeName: purposeName,
|
|
|
|
+ BatchNumber: v.BatchNumber,
|
|
|
|
+ AdmissionWeight: float32(v.AdmissionWeight / 1000),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res
|
|
return res
|
|
}
|
|
}
|
|
|
|
|
|
-func (c CowSlice) ToPB2(penMap map[int32]*Pen, penWeightSlice PenWeightSlice) []*pasturePb.CowList {
|
|
|
|
|
|
+func (c CowSlice) ToPB2(penWeightSlice PenWeightSlice) []*pasturePb.CowList {
|
|
res := make([]*pasturePb.CowList, len(c))
|
|
res := make([]*pasturePb.CowList, len(c))
|
|
for i, v := range c {
|
|
for i, v := range c {
|
|
- penName := ""
|
|
|
|
- if pen, ok := penMap[v.PenId]; ok {
|
|
|
|
- penName = pen.Name
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
penWeight := penWeightSlice.GetPenWeight(v.PenId)
|
|
penWeight := penWeightSlice.GetPenWeight(v.PenId)
|
|
- lastWeightDay := util.Ceil(float64(v.LastWeightAt-v.LastSecondWeightAt) / 86400)
|
|
|
|
penAvgWeight := float32(0)
|
|
penAvgWeight := float32(0)
|
|
- previousStageDailyWeight := float32(0)
|
|
|
|
cowPenAvgWeightDiffValue := float32(0)
|
|
cowPenAvgWeightDiffValue := float32(0)
|
|
|
|
|
|
if penWeight != nil {
|
|
if penWeight != nil {
|
|
penAvgWeight = float32(penWeight.AvgWeight) / 1000
|
|
penAvgWeight = float32(penWeight.AvgWeight) / 1000
|
|
cowPenAvgWeightDiffValue = float32(v.CurrentWeight-int64(penWeight.AvgWeight)) / 1000
|
|
cowPenAvgWeightDiffValue = float32(v.CurrentWeight-int64(penWeight.AvgWeight)) / 1000
|
|
- if lastWeightDay > 0 {
|
|
|
|
- previousStageDailyWeight = float32(v.CurrentWeight-v.LastSecondWeight) / 1000 / float32(lastWeightDay)
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
res[i] = &pasturePb.CowList{
|
|
res[i] = &pasturePb.CowList{
|
|
CowId: int32(v.Id),
|
|
CowId: int32(v.Id),
|
|
DayAge: v.DayAge,
|
|
DayAge: v.DayAge,
|
|
- DailyWeightGain: float32(v.GetDayWeight()),
|
|
|
|
AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
|
|
AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
|
|
EarNumber: v.EarNumber,
|
|
EarNumber: v.EarNumber,
|
|
- PenName: penName,
|
|
|
|
|
|
+ PenName: v.PenName,
|
|
BirthAt: int32(v.BirthAt),
|
|
BirthAt: int32(v.BirthAt),
|
|
BirthWeight: float32(v.BirthWeight) / 1000,
|
|
BirthWeight: float32(v.BirthWeight) / 1000,
|
|
CurrentWeight: float32(v.CurrentWeight) / 1000,
|
|
CurrentWeight: float32(v.CurrentWeight) / 1000,
|
|
LastWeightAt: int32(v.LastWeightAt),
|
|
LastWeightAt: int32(v.LastWeightAt),
|
|
- AdmissionAge: int32(v.AdmissionAge),
|
|
|
|
|
|
+ AdmissionAge: v.AdmissionAge,
|
|
AdmissionWeight: float32(v.AbortionAge) / 1000,
|
|
AdmissionWeight: float32(v.AbortionAge) / 1000,
|
|
- PreviousStageDailyWeight: previousStageDailyWeight,
|
|
|
|
|
|
+ PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
|
|
PenAvgWeight: penAvgWeight,
|
|
PenAvgWeight: penAvgWeight,
|
|
CowPenAvgWeightDiffValue: cowPenAvgWeightDiffValue,
|
|
CowPenAvgWeightDiffValue: cowPenAvgWeightDiffValue,
|
|
}
|
|
}
|
|
@@ -205,48 +602,137 @@ func (c CowSlice) ToPB2(penMap map[int32]*Pen, penWeightSlice PenWeightSlice) []
|
|
return res
|
|
return res
|
|
}
|
|
}
|
|
|
|
|
|
-func NewCow(req *pasturePb.EventEnterRequest) *Cow {
|
|
|
|
|
|
+// NewEnterCow 入场新增牛只
|
|
|
|
+func NewEnterCow(pastureId int64, req *pasturePb.EventEnterRequest, penMap map[int32]*Pen) *Cow {
|
|
var isPregnant = pasturePb.IsShow_No
|
|
var isPregnant = pasturePb.IsShow_No
|
|
if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
|
|
if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
|
|
isPregnant = pasturePb.IsShow_Ok
|
|
isPregnant = pasturePb.IsShow_Ok
|
|
}
|
|
}
|
|
- return &Cow{
|
|
|
|
|
|
+
|
|
|
|
+ admissionAt := int64(0)
|
|
|
|
+ switch req.CowSource {
|
|
|
|
+ case pasturePb.CowSource_Calving:
|
|
|
|
+ admissionAt = int64(req.BirthAt)
|
|
|
|
+ case pasturePb.CowSource_Transfer_In:
|
|
|
|
+ admissionAt = int64(req.EnterAt)
|
|
|
|
+ case pasturePb.CowSource_Buy:
|
|
|
|
+ admissionAt = int64(req.EnterAt)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ breedStatus := pasturePb.BreedStatus_Invalid
|
|
|
|
+ isForbiddenMating := pasturePb.IsShow_No
|
|
|
|
+ cowType := pasturePb.CowType_Invalid
|
|
|
|
+ if req.Sex == pasturePb.Genders_Female {
|
|
|
|
+
|
|
|
|
+ if req.Lact == 0 && req.MatingAt <= 0 {
|
|
|
|
+ breedStatus = pasturePb.BreedStatus_UnBreed
|
|
|
|
+ cowType = pasturePb.CowType_Reserve_Calf
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if req.MatingAt > 0 && (req.PregnantCheckResult != pasturePb.PregnantCheckResult_Pregnant &&
|
|
|
|
+ req.PregnantCheckResult != pasturePb.PregnantCheckResult_UnPregnant) &&
|
|
|
|
+ req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
|
|
|
|
+ breedStatus = pasturePb.BreedStatus_Breeding
|
|
|
|
+ if req.Lact == 0 {
|
|
|
|
+ cowType = pasturePb.CowType_Reserve_Calf
|
|
|
|
+ } else {
|
|
|
|
+ cowType = pasturePb.CowType_Breeding_Calf
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant &&
|
|
|
|
+ req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
|
|
|
|
+ breedStatus = pasturePb.BreedStatus_Pregnant
|
|
|
|
+ if req.Lact == 0 {
|
|
|
|
+ cowType = pasturePb.CowType_Reserve_Calf
|
|
|
|
+ } else {
|
|
|
|
+ cowType = pasturePb.CowType_Breeding_Calf
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant &&
|
|
|
|
+ req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
|
|
|
|
+ breedStatus = pasturePb.BreedStatus_Empty
|
|
|
|
+ if req.Lact == 0 {
|
|
|
|
+ cowType = pasturePb.CowType_Reserve_Calf
|
|
|
|
+ } else {
|
|
|
|
+ cowType = pasturePb.CowType_Breeding_Calf
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if req.CalvingAt > 0 && req.CalvingAt >= req.MatingAt && req.CalvingAt >= req.AbortionAt {
|
|
|
|
+ breedStatus = pasturePb.BreedStatus_Calving
|
|
|
|
+ cowType = pasturePb.CowType_Breeding_Calf
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if req.AbortionAt > 0 && req.AbortionAt >= req.CalvingAt && req.AbortionAt >= req.MatingAt {
|
|
|
|
+ breedStatus = pasturePb.BreedStatus_Abort
|
|
|
|
+ cowType = pasturePb.CowType_Breeding_Calf
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if breedStatus == pasturePb.BreedStatus_No_Mating {
|
|
|
|
+ isForbiddenMating = pasturePb.IsShow_Ok
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cow := &Cow{
|
|
|
|
+ PastureId: pastureId,
|
|
Sex: req.Sex,
|
|
Sex: req.Sex,
|
|
EarNumber: req.EarNumber,
|
|
EarNumber: req.EarNumber,
|
|
PenId: req.PenId,
|
|
PenId: req.PenId,
|
|
|
|
+ PenName: penMap[req.PenId].Name,
|
|
Lact: req.Lact,
|
|
Lact: req.Lact,
|
|
- CowType: req.CowType,
|
|
|
|
- BreedStatus: req.BreedStatus,
|
|
|
|
|
|
+ CowType: cowType,
|
|
|
|
+ BreedStatus: breedStatus,
|
|
CowKind: req.CowKind,
|
|
CowKind: req.CowKind,
|
|
- SourceId: req.CowSource,
|
|
|
|
|
|
+ SourceKind: req.CowSource,
|
|
FatherNumber: req.FatherNumber,
|
|
FatherNumber: req.FatherNumber,
|
|
MotherNumber: req.MotherNumber,
|
|
MotherNumber: req.MotherNumber,
|
|
AdmissionStatus: pasturePb.AdmissionStatus_Admission,
|
|
AdmissionStatus: pasturePb.AdmissionStatus_Admission,
|
|
HealthStatus: pasturePb.HealthStatus_Health,
|
|
HealthStatus: pasturePb.HealthStatus_Health,
|
|
|
|
+ PurposeKind: req.PurposeKind,
|
|
|
|
+ EleEarNumber: req.EleEarNumber,
|
|
IsPregnant: isPregnant,
|
|
IsPregnant: isPregnant,
|
|
|
|
+ IsForbiddenMating: isForbiddenMating,
|
|
WeaningAt: int64(req.WeaningAt),
|
|
WeaningAt: int64(req.WeaningAt),
|
|
BirthAt: int64(req.BirthAt),
|
|
BirthAt: int64(req.BirthAt),
|
|
AdmissionWeight: int64(req.Weight * 1000),
|
|
AdmissionWeight: int64(req.Weight * 1000),
|
|
FirstMatingAt: int64(req.MatingAt),
|
|
FirstMatingAt: int64(req.MatingAt),
|
|
LastMatingAt: int64(req.MatingAt),
|
|
LastMatingAt: int64(req.MatingAt),
|
|
LastPregnantCheckAt: int64(req.PregnancyCheckAt),
|
|
LastPregnantCheckAt: int64(req.PregnancyCheckAt),
|
|
- AdmissionAt: time.Now().Unix(),
|
|
|
|
|
|
+ AdmissionAt: admissionAt,
|
|
|
|
+ BirthWeight: int64(req.Weight * 1000),
|
|
|
|
+ LastWeightAt: int64(req.EstrusAt),
|
|
|
|
+ CurrentWeight: int64(req.Weight * 1000),
|
|
|
|
+ LastDryMilkAt: int64(req.DryMilkAt),
|
|
|
|
+ MatingTimes: req.MatingTimes,
|
|
|
|
+ LastCalvingAt: int64(req.CalvingAt),
|
|
|
|
+ LastBullNumber: req.BullNumber,
|
|
|
|
+ LastAbortionAt: int64(req.AbortionAt),
|
|
|
|
+ AdmissionPrice: req.Price,
|
|
|
|
+ BatchNumber: req.BatchNumber,
|
|
}
|
|
}
|
|
|
|
+ cow.AdmissionAge = cow.GetAdmissionAge()
|
|
|
|
+ cow.DayAge = cow.GetDayAge()
|
|
|
|
+ return cow
|
|
}
|
|
}
|
|
|
|
|
|
-func NewCalfCow(motherId int64, fatherNumber string, calf *CalvingCalf) *Cow {
|
|
|
|
|
|
+// NewCalfCow 产犊新增
|
|
|
|
+func NewCalfCow(matherInfo *Cow, calf *CalvingCalf) *Cow {
|
|
return &Cow{
|
|
return &Cow{
|
|
|
|
+ PastureId: calf.PastureId,
|
|
Sex: calf.Sex,
|
|
Sex: calf.Sex,
|
|
EarNumber: calf.EarNumber,
|
|
EarNumber: calf.EarNumber,
|
|
PenId: calf.PenId,
|
|
PenId: calf.PenId,
|
|
|
|
+ PenName: calf.PenName,
|
|
CowType: pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
|
|
CowType: pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
|
|
BreedStatus: pasturePb.BreedStatus_UnBreed, // 未配
|
|
BreedStatus: pasturePb.BreedStatus_UnBreed, // 未配
|
|
- CowKind: calf.CowKind, // 牛只品种
|
|
|
|
|
|
+ CowKind: matherInfo.CowKind, // 牛只品种
|
|
BirthWeight: calf.BirthWeight,
|
|
BirthWeight: calf.BirthWeight,
|
|
BirthAt: calf.BirthAt,
|
|
BirthAt: calf.BirthAt,
|
|
- SourceId: pasturePb.CowSource_Calving, // 产犊方式
|
|
|
|
- FatherNumber: fatherNumber,
|
|
|
|
- MotherNumber: fmt.Sprintf("%d", motherId),
|
|
|
|
|
|
+ SourceKind: pasturePb.CowSource_Calving, // 产犊方式
|
|
|
|
+ FatherNumber: matherInfo.LastBullNumber,
|
|
|
|
+ MotherNumber: matherInfo.EarNumber,
|
|
AdmissionStatus: pasturePb.AdmissionStatus_Admission,
|
|
AdmissionStatus: pasturePb.AdmissionStatus_Admission,
|
|
IsPregnant: pasturePb.IsShow_No,
|
|
IsPregnant: pasturePb.IsShow_No,
|
|
AdmissionAt: calf.BirthAt,
|
|
AdmissionAt: calf.BirthAt,
|
|
@@ -270,82 +756,6 @@ func (b BarCowStructSlice) ToPB(cowTypeMap map[pasturePb.CowType_Kind]string, co
|
|
return pb
|
|
return pb
|
|
}
|
|
}
|
|
|
|
|
|
-// GetDayAge 日龄
|
|
|
|
-func (c *Cow) GetDayAge() int32 {
|
|
|
|
- if c.BirthAt <= 0 {
|
|
|
|
- return 0
|
|
|
|
- }
|
|
|
|
- return int32(math.Floor(float64(time.Now().Unix()-c.BirthAt) / 86400))
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// GetCalvingAge 产后天数
|
|
|
|
-func (c *Cow) GetCalvingAge() int64 {
|
|
|
|
- if c.LastMatingAt <= 0 {
|
|
|
|
- return 0
|
|
|
|
- }
|
|
|
|
- return int64(math.Floor(float64(time.Now().Unix()-c.LastMatingAt) / 86400))
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// GetDaysPregnant 怀孕天数
|
|
|
|
-func (c *Cow) GetDaysPregnant() int32 {
|
|
|
|
- if c.BreedStatus == pasturePb.BreedStatus_Pregnant &&
|
|
|
|
- c.AdmissionStatus == pasturePb.AdmissionStatus_Admission &&
|
|
|
|
- c.IsPregnant == pasturePb.IsShow_Ok {
|
|
|
|
- return int32(math.Floor(float64(time.Now().Unix()-c.LastMatingAt) / 86400))
|
|
|
|
- }
|
|
|
|
- return 0
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// GetLactationDays 泌乳天数
|
|
|
|
-func (c *Cow) GetLactationDays() int32 {
|
|
|
|
- if c.BreedStatus == pasturePb.BreedStatus_Calving && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
|
|
|
|
- return int32(math.Floor(float64(time.Now().Unix()-c.LastCalvingAt) / 86400))
|
|
|
|
- }
|
|
|
|
- return 0
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// GetAdmissionAge 入场天数
|
|
|
|
-func (c *Cow) GetAdmissionAge() int32 {
|
|
|
|
- if c.AdmissionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
|
|
|
|
- return int32(math.Floor(float64(time.Now().Unix()-c.AdmissionAt) / 86400))
|
|
|
|
- }
|
|
|
|
- return 0
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// GetDayWeight 日增重
|
|
|
|
-func (c *Cow) GetDayWeight() float64 {
|
|
|
|
- if c.CurrentWeight-c.LastSecondWeight > 0 && c.LastWeightAt > c.LastSecondWeightAt {
|
|
|
|
- days := int32(math.Floor(float64(c.LastWeightAt-c.LastSecondWeightAt) / 86400))
|
|
|
|
- if days <= 0 {
|
|
|
|
- return 0
|
|
|
|
- }
|
|
|
|
- dayWeight := math.Round(1.0 * float64(c.CurrentWeight-c.LastSecondWeight) / float64(days))
|
|
|
|
- return dayWeight / 1000
|
|
|
|
- }
|
|
|
|
- return 0
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// GetAverageDailyWeight 平均日增重
|
|
|
|
-func (c *Cow) GetAverageDailyWeight() float64 {
|
|
|
|
- if c.CurrentWeight-c.BirthWeight > 0 && c.LastWeightAt > c.BirthAt {
|
|
|
|
- days := int32(math.Floor(float64(c.LastWeightAt-c.BirthAt) / 86400))
|
|
|
|
- if days <= 0 {
|
|
|
|
- return 0
|
|
|
|
- }
|
|
|
|
- dailyWeight := math.Round(1.0 * float64(c.CurrentWeight-c.BirthWeight) / float64(days))
|
|
|
|
- return dailyWeight / 1000
|
|
|
|
- }
|
|
|
|
- return 0
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (c *Cow) GetAbortionAge() int32 {
|
|
|
|
- if c.LastAbortionAt > 0 && c.AdmissionStatus == pasturePb.AdmissionStatus_Admission {
|
|
|
|
- return int32(math.Floor(float64(time.Now().Unix()-c.LastAbortionAt) / 86400))
|
|
|
|
- }
|
|
|
|
- return 0
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
type CowWeightRange struct {
|
|
type CowWeightRange struct {
|
|
WeightRange string `json:"weight_range"`
|
|
WeightRange string `json:"weight_range"`
|
|
Count int32 `json:"count"`
|
|
Count int32 `json:"count"`
|
|
@@ -359,17 +769,80 @@ func (c CowSlice) WeightRangeToPB(penMap map[int32]*Pen) []*pasturePb.CowList {
|
|
penName = pen.Name
|
|
penName = pen.Name
|
|
}
|
|
}
|
|
res[i] = &pasturePb.CowList{
|
|
res[i] = &pasturePb.CowList{
|
|
- CowId: int32(v.Id),
|
|
|
|
- DayAge: v.DayAge,
|
|
|
|
- DailyWeightGain: float32(v.GetDayWeight()),
|
|
|
|
- AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
|
|
|
|
- EarNumber: v.EarNumber,
|
|
|
|
- PenName: penName,
|
|
|
|
- BirthAt: int32(v.BirthAt),
|
|
|
|
- BirthWeight: float32(v.BirthWeight) / 1000,
|
|
|
|
- CurrentWeight: float32(v.CurrentWeight) / 1000,
|
|
|
|
- LastWeightAt: int32(v.LastWeightAt),
|
|
|
|
|
|
+ CowId: int32(v.Id),
|
|
|
|
+ DayAge: v.DayAge,
|
|
|
|
+ AverageDailyWeightGain: float32(v.GetAverageDailyWeight()),
|
|
|
|
+ PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
|
|
|
|
+ EarNumber: v.EarNumber,
|
|
|
|
+ PenName: penName,
|
|
|
|
+ BirthAt: int32(v.BirthAt),
|
|
|
|
+ BirthWeight: float32(v.BirthWeight) / 1000,
|
|
|
|
+ CurrentWeight: float32(v.CurrentWeight) / 1000,
|
|
|
|
+ LastWeightAt: int32(v.LastWeightAt),
|
|
|
|
+ AdmissionAge: v.AdmissionAge,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res
|
|
return res
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func (c CowSlice) LongTermInfertilityToPB(breedStatusMap map[pasturePb.BreedStatus_Kind]string) []*pasturePb.LongTermInfertility {
|
|
|
|
+ res := make([]*pasturePb.LongTermInfertility, len(c))
|
|
|
|
+ for i, v := range c {
|
|
|
|
+ breedStatusName := ""
|
|
|
|
+ if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
|
|
|
|
+ breedStatusName = breedStatus
|
|
|
|
+ }
|
|
|
|
+ lastCalvingAtFormat := ""
|
|
|
|
+ if v.LastCalvingAt > 0 {
|
|
|
|
+ lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+ lastAbortionAtFormat := ""
|
|
|
|
+ if v.LastAbortionAt > 0 {
|
|
|
|
+ lastAbortionAtFormat = time.Unix(v.LastAbortionAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+ lastMatingAtFormat := ""
|
|
|
|
+ if v.LastMatingAt > 0 {
|
|
|
|
+ lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Local().Format(LayoutDate2)
|
|
|
|
+ }
|
|
|
|
+ res[i] = &pasturePb.LongTermInfertility{
|
|
|
|
+ CowId: int32(v.Id),
|
|
|
|
+ EarNumber: v.EarNumber,
|
|
|
|
+ Lact: v.Lact,
|
|
|
|
+ PenId: v.PenId,
|
|
|
|
+ CalvingAge: v.CalvingAge,
|
|
|
|
+ PenName: v.PenName,
|
|
|
|
+ BreedStatusName: breedStatusName,
|
|
|
|
+ BreedStatus: v.BreedStatus,
|
|
|
|
+ LastCalvingAtFormat: lastCalvingAtFormat,
|
|
|
|
+ LastAbortionAtFormat: lastAbortionAtFormat,
|
|
|
|
+ LastMatingAtFormat: lastMatingAtFormat,
|
|
|
|
+ MatingTimes: v.MatingTimes,
|
|
|
|
+ LastBullNumber: v.LastBullNumber,
|
|
|
|
+ AbortionTimes: v.AbortionTimes,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return res
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// CowBehaviorCurveResponse 脖环行为数据
|
|
|
|
+type CowBehaviorCurveResponse struct {
|
|
|
|
+ Code int32 `json:"code"`
|
|
|
|
+ Msg string `json:"msg"`
|
|
|
|
+ Data *CowBehaviorCurveData `json:"data"`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type CowBehaviorCurveData struct {
|
|
|
|
+ OriginalDateList []int32 `json:"originalDateList"` // 原始行为数据
|
|
|
|
+ ChangeDateList []int32 `json:"changeDateList"` // 变化数据
|
|
|
|
+ SumDateList []int32 `json:"sumDateList"` // 累计24小时数据
|
|
|
|
+ SumChewList []int32 `json:"sumChewList"` // 累计24小时咀嚼
|
|
|
|
+ DateTimeList []string `json:"dateTimeList"` // 时间数据
|
|
|
|
+ EstrusList map[pasturePb.EstrusLevel_Kind][]string `json:"estrusList"` // 发情预警
|
|
|
|
+ EventList []*pasturePb.CowEvent `json:"eventList"` // 事件数据
|
|
|
|
+ EventMap map[pasturePb.EventType_Kind]string `json:"eventMap"` // 所有事件
|
|
|
|
+ RuminaChange []int32 `json:"ruminaChange"` // 反刍变化
|
|
|
|
+ LowActivity int32 `json:"lowActivity"` // 低活动量参数
|
|
|
|
+ MiddleActivity int32 `json:"middleActivity"` // 中活动量行数
|
|
|
|
+ IQR1 []int32 `json:"IQR1"`
|
|
|
|
+ IQR3 []int32 `json:"IQR3"`
|
|
|
|
+}
|