analysis_breed.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package backend
  2. import (
  3. "context"
  4. "kpt-pasture/model"
  5. "kpt-pasture/util"
  6. "net/http"
  7. "gitee.com/xuyiping_admin/pkg/xerr"
  8. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  9. )
  10. // SingleFactorInfantSurvivalRateAnalysis 单因素受胎率分析
  11. func (s *StoreEntry) SingleFactorInfantSurvivalRateAnalysis(ctx context.Context, req *pasturePb.SingleFactorPregnancyRateRequest) (*pasturePb.SingleFactorPregnancyRateResponse, error) {
  12. startTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  13. endTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  14. if startTimeUnix == 0 || endTimeUnix == 0 || endTimeUnix <= startTimeUnix {
  15. return nil, xerr.Custom("开始时间不能大于结束时间")
  16. }
  17. var err error
  18. list := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  19. chart := &pasturePb.SingleFactorPregnancyRateChart{
  20. Headers: make([]string, 0),
  21. PregnantRate: make([]float32, 0),
  22. MaxValue: make([]int32, 0),
  23. MinValue: make([]int32, 0),
  24. AveragePregnantRate: 0,
  25. }
  26. switch req.AnalysisMethod {
  27. case pasturePb.SingleFactorAnalysisMethod_Cycle:
  28. list, err = s.SingleFactorAnalysisMethodCycle(ctx, req)
  29. case pasturePb.SingleFactorAnalysisMethod_Months:
  30. list, err = s.SingleFactorAnalysisMethodMonths(ctx, req)
  31. case pasturePb.SingleFactorAnalysisMethod_Mating_Times:
  32. case pasturePb.SingleFactorAnalysisMethod_Breeding_Method:
  33. case pasturePb.SingleFactorAnalysisMethod_Breeding_Company:
  34. case pasturePb.SingleFactorAnalysisMethod_Operation:
  35. case pasturePb.SingleFactorAnalysisMethod_Mating_Interval:
  36. case pasturePb.SingleFactorAnalysisMethod_Bull:
  37. case pasturePb.SingleFactorAnalysisMethod_Breeding_Cycle:
  38. case pasturePb.SingleFactorAnalysisMethod_Week:
  39. case pasturePb.SingleFactorAnalysisMethod_Lact:
  40. default:
  41. return nil, xerr.Custom("错误的统计方式")
  42. }
  43. if err != nil {
  44. return nil, xerr.WithStack(err)
  45. }
  46. totalCountMap := make(map[int]int32, len(list))
  47. allTotalCount := int32(0) // 总头数
  48. allPregnantRate := float64(0) // 总受胎率
  49. for i, v := range list {
  50. chart.Headers = append(chart.Headers, v.StatisticMethod)
  51. pregnantRate := float64(0)
  52. if v.EmptyPregnantCount+v.PregnantCount > 0 {
  53. pregnantRate = float64(v.PregnantCount) / float64(v.EmptyPregnantCount+v.PregnantCount)
  54. }
  55. chart.PregnantRate = append(chart.PregnantRate, float32(util.RoundToTwoDecimals(pregnantRate*100)))
  56. v.TotalCount = v.PregnantCount + v.EmptyPregnantCount + v.OtherCount
  57. v.PregnantRate = float32(util.RoundToTwoDecimals(pregnantRate * 100))
  58. spcRate := float32(0)
  59. if v.PregnantRate > 0 {
  60. spcRate = float32(util.RoundToTwoDecimals((float64(v.PregnantCount) / float64(v.TotalCount)) * 100))
  61. }
  62. v.SpceRate = spcRate
  63. totalCountMap[i] = v.TotalCount
  64. allTotalCount += v.TotalCount
  65. allPregnantRate += pregnantRate
  66. }
  67. for i, v := range totalCountMap {
  68. if allTotalCount <= 0 || list[i].TotalCount <= 0 {
  69. continue
  70. }
  71. list[i].TotalRate = float32(util.RoundToTwoDecimals(float64(v) / float64(allTotalCount) * 100))
  72. }
  73. chart.AveragePregnantRate = float32(util.RoundToTwoDecimals(allPregnantRate/float64(len(list))) * 100)
  74. return &pasturePb.SingleFactorPregnancyRateResponse{
  75. Code: http.StatusOK,
  76. Message: "ok",
  77. Data: &pasturePb.SingleFactorPregnancyRateData{
  78. Total: int32(len(list)),
  79. List: list,
  80. Chart: chart,
  81. },
  82. }, nil
  83. }
  84. func (s *StoreEntry) SingleFactorAnalysisMethodCycle(ctx context.Context, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  85. /*dateTimeRange, err := util.GetRangeDayByDays(req.StartDayTime, req.EndDayTime, req.Value)
  86. if err != nil {
  87. return nil, xerr.WithStack(err)
  88. }*/
  89. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  90. return res, nil
  91. }
  92. func (s *StoreEntry) SingleFactorAnalysisMethodMonths(ctx context.Context, req *pasturePb.SingleFactorPregnancyRateRequest) ([]*pasturePb.SingleFactorPregnancyRateList, error) {
  93. startDayTimeUnix := util.TimeParseLocalUnix(req.StartDayTime)
  94. endDayTimeUnix := util.TimeParseLocalEndUnix(req.EndDayTime)
  95. if startDayTimeUnix == 0 || endDayTimeUnix == 0 || endDayTimeUnix <= startDayTimeUnix {
  96. return nil, xerr.Custom("开始时间不能大于结束时间")
  97. }
  98. res := make([]*pasturePb.SingleFactorPregnancyRateList, 0)
  99. pref := s.DB.Model(new(model.EventMating)).
  100. Select(`
  101. DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m') AS months,
  102. DATE_FORMAT(FROM_UNIXTIME(reality_day), '%Y-%m') AS statistic_method,
  103. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS pregnant_count, -- 怀孕头数
  104. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS empty_pregnant_count, -- 空怀头数
  105. COUNT(DISTINCT CASE WHEN mating_result = ? AND mating_result_at > 0 THEN cow_id END) AS abortion_count, -- 流产头数
  106. COUNT(DISTINCT CASE WHEN mating_result IN (?, ?) THEN cow_id END) AS other_count, -- 其他数
  107. (
  108. COUNT(DISTINCT CASE WHEN mating_result = 3 AND mating_result_at > 0 THEN cow_id END) +
  109. COUNT(DISTINCT CASE WHEN mating_result = 4 AND mating_result_at > 0 THEN cow_id END) +
  110. COUNT(DISTINCT CASE WHEN mating_result IN (1, 2) THEN cow_id END)
  111. ) AS total_count -- 总数
  112. `, pasturePb.MatingResult_Pregnant, pasturePb.MatingResult_Empty, pasturePb.MatingResult_Abort,
  113. pasturePb.MatingResult_Unknown, pasturePb.MatingResult_ReMatch).
  114. Where("status = ?", pasturePb.IsShow_Ok).
  115. Where("reality_day BETWEEN ? AND ?", startDayTimeUnix, endDayTimeUnix).
  116. Where("reality_day > 0")
  117. if req.CowType > 0 {
  118. pref.Where("cow_type = ?", req.CowType)
  119. }
  120. if req.CowKind > 0 {
  121. pref.Where("cow_kind = ?", req.CowKind)
  122. }
  123. if req.LactInterval > 0 {
  124. switch req.LactInterval {
  125. case pasturePb.LactIntervalSymbol_Less_Than:
  126. pref.Where("lact < ?", req.LactIntervalStartValue)
  127. case pasturePb.LactIntervalSymbol_Less_Than_Or_Equal_To:
  128. pref.Where("lact <= ?", req.LactIntervalStartValue)
  129. case pasturePb.LactIntervalSymbol_Greater_Than:
  130. pref.Where("lact > ?", req.LactIntervalStartValue)
  131. case pasturePb.LactIntervalSymbol_Greater_Than_Or_Equal_To:
  132. pref.Where("lact >= ?", req.LactIntervalStartValue)
  133. case pasturePb.LactIntervalSymbol_Equal_To:
  134. pref.Where("lact = ?", req.LactIntervalStartValue)
  135. case pasturePb.LactIntervalSymbol_Not_Equal_To:
  136. pref.Where("lact != ?", req.LactIntervalStartValue)
  137. case pasturePb.LactIntervalSymbol_Between:
  138. pref.Where("lact BETWEEN ? AND ? ", req.LactIntervalStartValue, req.LactIntervalEndValue)
  139. default:
  140. return nil, xerr.Custom("错误的胎次区间符号")
  141. }
  142. }
  143. if err := pref.Group("months").Order("months").Find(&res).Error; err != nil {
  144. return nil, xerr.WithStack(err)
  145. }
  146. return res, nil
  147. }