Browse Source

analysis: 生长曲线chart图优化

Yi 9 months ago
parent
commit
11d5a20530
6 changed files with 78 additions and 9 deletions
  1. 1 1
      go.mod
  2. 4 0
      go.sum
  3. 1 1
      http/route/analysis_api.go
  4. 27 0
      model/cow.go
  5. 26 7
      module/backend/analysis.go
  6. 19 0
      module/backend/sql.go

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20240606095857-7c3f8fb582a1
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20240607071100-7ceeb27fa509
 	gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/getsentry/sentry-go v0.23.0

+ 4 - 0
go.sum

@@ -136,6 +136,10 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20240605085152-de3ddf049865 h1:icm4K9AW
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240605085152-de3ddf049865/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240606095857-7c3f8fb582a1 h1:pSTADLNa+ylTtxq+xhOg+4oQmu6YVVjur1q/KvE7Z9Q=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20240606095857-7c3f8fb582a1/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240607064246-3237fc0007bc h1:9bSZpry6TazUt4vYExA70e4ocnvaXxAEGofwgSxokRg=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240607064246-3237fc0007bc/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240607071100-7ceeb27fa509 h1:e7+0jjy1IcTM7CiyxyXREcp75yLF+60Vs3w7sEoTsT0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20240607071100-7ceeb27fa509/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015 h1:dfb5dRd57L2HKjdwLT93UFmPYFPOmEl56gtZmqcNnaE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20231218082641-aac597b8a015/go.mod h1:Fk4GYI/v0IK3XFrm1Gn+VkgCz5Y7mfswD5hsTJYOG6A=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 1 - 1
http/route/analysis_api.go

@@ -13,6 +13,6 @@ func AnalysisAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		}
 		// pasture API 组  牧场管理
 		pastureRoute := authRouteGroup(s, "/api/v1/analysis/")
-		pastureRoute.GET("/growth/curve", analysis.GrowthCurve)
+		pastureRoute.POST("/growth/curve", analysis.GrowthCurve)
 	}
 }

+ 27 - 0
model/cow.go

@@ -35,6 +35,8 @@ type Cow struct {
 	LastBullId          int64                      `json:"last_bull_id"`
 	LastPregnantCheckAt int64                      `json:"last_pregnant_check_at"`
 	LastDryMilkAt       int64                      `json:"last_dry_milk_at"`
+	LastSecondWeight    int64                      `json:"last_second_weight"`
+	LastSecondWeightAt  int64                      `json:"last_second_weight_at"`
 	LastWeightAt        int64                      `json:"last_weight_at"`
 	CreatedAt           int64                      `json:"created_at"`
 	UpdatedAt           int64                      `json:"updated_at"`
@@ -116,3 +118,28 @@ func (c *Cow) GetLactationDays() int32 {
 	}
 	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
+		}
+		return math.Round(1.0 * float64(c.CurrentWeight-c.LastSecondWeight) / float64(days))
+	}
+	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
+	}
+	return 0
+}

+ 26 - 7
module/backend/analysis.go

@@ -4,6 +4,10 @@ import (
 	"context"
 	"kpt-pasture/model"
 	"net/http"
+	"strings"
+	"time"
+
+	"gitee.com/xuyiping_admin/pkg/xerr"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
@@ -13,18 +17,24 @@ func (s *StoreEntry) GrowthCurve(ctx context.Context, req *pasturePb.SearchGrowt
 	// 查询数据
 	cowList := make([]*model.Cow, 0)
 	pref := s.DB.Model(new(model.Cow)).Where("is_remove = ?", pasturePb.IsShow_Ok)
-
 	if req.GetCowId() != "" {
-		pref.Where("id IN ?", req.GetCowId())
+		pref.Where("id IN ?", strings.Split(req.CowId, ","))
 	}
 
-	if req.BirthStartDate > 0 && req.BirthEndDate > 0 && req.BirthStartDate <= req.BirthEndDate {
-		pref.Where("birth_at BETWEEN ? AND ?", req.GetBirthStartDate(), req.GetBirthEndDate())
+	if len(req.BirthDate) == 2 && req.BirthDate[0] != "" && req.BirthDate[1] != "" {
+		t0, _ := time.Parse(time.RFC3339, req.BirthDate[0])
+		t1, _ := time.Parse(time.RFC3339, req.BirthDate[1])
+
+		pref.Where("birth_at BETWEEN ? AND ?", t0.Unix(), t1.Unix()+86399)
 	}
 
 	if err := pref.Find(&cowList).Error; err != nil {
 		return nil, err
 	}
+	penList, err := s.GetPenList(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	// 计算图表数据
 	chartsList := &pasturePb.Charts{
 		CowId:  make([]int32, 0),
@@ -34,22 +44,31 @@ func (s *StoreEntry) GrowthCurve(ctx context.Context, req *pasturePb.SearchGrowt
 	cowData := make([]*pasturePb.CowList, 0)
 	for _, cow := range cowList {
 		currentWeight := float32(cow.CurrentWeight) / 100
+		penName := ""
+		for _, v := range penList {
+			if cow.PenId != v.Id {
+				continue
+			}
+			penName = v.Name
+		}
 		cowData = append(cowData, &pasturePb.CowList{
 			CowId:                  int32(cow.Id),
 			EarNumber:              cow.EarNumber,
 			DayAge:                 cow.GetDayAge(),
-			PenName:                "",
+			PenName:                penName,
 			CurrentWeight:          currentWeight,
 			BirthAt:                int32(cow.BirthAt),
 			BirthWeight:            float32(cow.BirthWeight) / 100,
 			LastWeightAt:           int32(cow.LastWeightAt),
-			DailyWeightGain:        0,
-			AverageDailyWeightGain: 0,
+			DailyWeightGain:        float32(cow.GetDayWeight() / 100),
+			AverageDailyWeightGain: float32(cow.GetAverageDailyWeight() / 100),
 		})
+
 		chartsList.CowId = append(chartsList.CowId, int32(cow.Id))
 		chartsList.Weight = append(chartsList.Weight, currentWeight)
 		chartsList.DayAge = append(chartsList.DayAge, cow.GetDayAge())
 	}
+
 	// 返回数据
 	return &pasturePb.GrowthCurvesResponse{
 		Code:    http.StatusOK,

+ 19 - 0
module/backend/sql.go

@@ -69,6 +69,14 @@ func (s *StoreEntry) GetPenInfo(ctx context.Context, penId int64) (*model.Pen, e
 	return penData, nil
 }
 
+func (s *StoreEntry) GetPenList(ctx context.Context) ([]*model.Pen, error) {
+	penList := make([]*model.Pen, 0)
+	if err := s.DB.Where("is_delete = ?", pasturePb.IsShow_Ok).Find(&penList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return penList, nil
+}
+
 func (s *StoreEntry) GetCowInfo(ctx context.Context, cowId int64) (*model.Cow, error) {
 	cowData := &model.Cow{Id: cowId}
 	if err := s.DB.First(cowData).Error; err != nil {
@@ -92,3 +100,14 @@ func (s *StoreEntry) GetTransferReasonInfo(ctx context.Context, reasonId int64)
 	}
 	return configTransferPenReasonData, nil
 }
+
+func (s *StoreEntry) GetCowWeightByLastSecond(ctx context.Context, cowId, lastWeightAt int64) (*model.EventWeight, error) {
+	cowWeightData := &model.EventWeight{}
+	if err := s.DB.Where("cow_id = ?", cowId).Where("weight_at < ?", lastWeightAt).First(cowWeightData).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, xerr.Customf("该牛只体重数据不存在: %d", cowId)
+		}
+		return nil, xerr.WithStack(err)
+	}
+	return cowWeightData, nil
+}