package backend import ( "context" "encoding/json" "fmt" "kpt-tmr-group/model" "net/http" "sort" "sync" "time" operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation" "gitee.com/xuyiping_admin/pkg/logger/zaplog" "gitee.com/xuyiping_admin/pkg/tool" "gitee.com/xuyiping_admin/pkg/xerr" "go.uber.org/multierr" "go.uber.org/zap" ) const ( compareTime = 10 * 60 ) // PasturePrefAnalysisData PasturePrefExecTimeData PastureSprinkleFeedTime TODO 后期三个函数封装一下 func (s *StoreEntry) PasturePrefAnalysisData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[int64]*model.PastureAnalysisAccuracyData, error) { res := make(map[int64]*model.PastureAnalysisAccuracyData, 0) wg := sync.WaitGroup{} wg.Add(len(req.PastureIds)) for _, pastureId := range req.PastureIds { go func(pId int32) { defer wg.Done() response := &model.PastureAnalysisAccuracyResponse{} groupPasture, err := s.GetGroupPastureListById(ctx, int64(pId)) if err != nil { zaplog.Error("PasturePrefAnalysisData", zap.Any("GetGroupPastureListById", err), zap.Any("pId", pId)) return } body := &model.DashboardAccuracyRequest{ PastureId: int32(groupPasture.PastureId), FeedFormulaId: req.FeedFormulaId, CattleParentCategoryId: int32(req.CattleParentCategoryId), StartDate: req.StartDate, EndDate: req.EndDate, } if err = s.PastureHttpClient(ctx, model.DashboardAccuracyUrl, int64(pId), body, response); err != nil { zaplog.Error("PasturePrefAnalysisData", zap.String("url", model.DashboardAccuracyUrl), zap.Any("pasture", groupPasture), zap.Any("body", body), zap.Any("err", err), zap.Any("response", response)) b, _ := json.Marshal(body) resB, _ := json.Marshal(response) pastureDataLog := model.NewPastureDataLog(groupPasture.Id, PastureDataLogType["FeedFormula_Distribute"], model.DashboardAccuracyUrl, string(b), string(resB)) s.DB.Create(pastureDataLog) return } if response.Code != http.StatusOK { zaplog.Error("PasturePrefAnalysisData-response", zap.String("url", model.DashboardAccuracyUrl), zap.Any("pasture", groupPasture), zap.Any("body", body), zap.Any("response", response), zap.Any("response", response)) return } res[groupPasture.Id] = response.Data }(pastureId) } wg.Wait() return res, nil } func (s *StoreEntry) PasturePrefExecTimeData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[string]*model.ExecTimeData, error) { res := make(map[string]*model.ExecTimeData, 0) wg := sync.WaitGroup{} wg.Add(len(req.PastureIds)) for _, pastureId := range req.PastureIds { go func(pId int32) { defer wg.Done() groupPasture, err := s.GetGroupPastureListById(ctx, int64(pId)) if err != nil { return } response := &model.PastureExecTimeData{} body := &model.DashboardAccuracyRequest{ PastureId: int32(groupPasture.PastureId), FeedFormulaId: req.FeedFormulaId, CattleParentCategoryId: int32(req.CattleParentCategoryId), StartDate: req.StartDate, EndDate: req.EndDate, } if err = s.PastureHttpClient(ctx, model.DashboardExecTimeUrl, int64(pId), body, response); err != nil { zaplog.Error("PasturePrefExecTimeData", zap.String("url", model.DashboardExecTimeUrl), zap.Any("pasture", groupPasture), zap.Any("body", body), zap.Any("err", err), zap.Any("response", response)) b, _ := json.Marshal(body) resB, _ := json.Marshal(response) pastureDataLog := model.NewPastureDataLog(groupPasture.Id, PastureDataLogType["PasturePrefExecTimeData"], model.DashboardExecTimeUrl, string(b), string(resB)) s.DB.Create(pastureDataLog) return } if response.Code != http.StatusOK { zaplog.Error("PasturePrefExecTimeData-response", zap.String("url", model.DashboardExecTimeUrl), zap.Any("pasture", groupPasture), zap.Any("body", body), zap.Any("err", err), zap.Any("response", response)) return } res[groupPasture.Name] = response.Data }(pastureId) } wg.Wait() return res, nil } func (s *StoreEntry) PastureSprinkleFeedTime(ctx context.Context, req *operationPb.SprinkleFeedTimeRequest) (map[int64][]*model.SprinkleStatisticsDataList, map[int64]*model.GroupPasture, error) { res, pastureList := make(map[int64][]*model.SprinkleStatisticsDataList), make(map[int64]*model.GroupPasture, 0) wg := sync.WaitGroup{} wg.Add(len(req.PastureIds)) var muError error for _, pasture := range req.PastureIds { go func(pId int32) { defer wg.Done() groupPasture, err := s.GetGroupPastureListById(ctx, int64(pId)) if err != nil { zaplog.Error("PastureSprinkleFeedTime", zap.Any("GetGroupPastureListById", err)) return } response := &model.PastureSprinkleStatisticsDataList{} body := &model.DashboardAccuracyRequest{ PastureId: int32(groupPasture.PastureId), FeedFormulaId: req.FeedFormulaId, StartDate: req.StartDate, EndDate: req.EndDate, } if err = s.PastureHttpClient(ctx, model.DashboardSprinkleFeedTimeUrl, int64(pId), body, response); err != nil { muError = multierr.Append(muError, err) zaplog.Error("PastureSprinkleFeedTime", zap.String("url", model.DashboardSprinkleFeedTimeUrl), zap.Any("pasture", groupPasture), zap.Any("body", body), zap.Any("err", err), zap.Any("response", response)) b, _ := json.Marshal(body) resB, _ := json.Marshal(response) pastureDataLog := model.NewPastureDataLog(groupPasture.Id, PastureDataLogType["PasturePrefExecTimeData"], model.DashboardSprinkleFeedTimeUrl, string(b), string(resB)) s.DB.Create(pastureDataLog) } if response.Code != http.StatusOK { muError = multierr.Append(muError, xerr.Custom(response.Msg)) } res[groupPasture.Id] = response.Data pastureList[groupPasture.Id] = groupPasture }(pasture) } wg.Wait() return res, pastureList, nil } // SearchAnalysisAccuracy 准确性分析 func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse1, error) { res := &model.SearchAnalysisAccuracyResponse1{ Code: http.StatusOK, Msg: "ok", Data: &model.AnalysisAccuracyData1{ Table: &model.Table{ TitleList: make([]*model.TableList, 0), DataList: &model.DataList{}, }, Chart: nil, }, } res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{ Name: "title", Value: "牧场", }) dashboardTopData, pastureAnalysisAccuracy, err := s.DashboardTopPasture(ctx, req) if err != nil { return nil, xerr.WithStack(err) } res.Data.Table = s.TitleList(ctx, pastureAnalysisAccuracy) dashboardTopData1 := &model.Chart1{ MixedFodderAccurateRatio: &model.PastureTopData1{ Title: make([]string, 0), Ratio: make([]float64, 0), }, MixedFodderCorrectRatio: &model.PastureTopData1{ Title: make([]string, 0), Ratio: make([]float64, 0), }, SprinkleFodderAccurateRatio: &model.PastureTopData1{ Title: make([]string, 0), Ratio: make([]float64, 0), }, SprinkleFodderCorrectRatio: &model.PastureTopData1{ Title: make([]string, 0), Ratio: make([]float64, 0), }, } pastureDayTimeRatioList := make(map[operationPb.DashboardTopType_Kind][]*model.PastureDayTimeRatio) for _, v := range dashboardTopData.MixedFodderCorrectRatio { pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE] = append(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE], &model.PastureDayTimeRatio{ PastureId: v.PastureId, PastureName: v.PastureName, Ratio: v.Ratio, }) dashboardTopData1.MixedFodderCorrectRatio.Title = append(dashboardTopData1.MixedFodderCorrectRatio.Title, v.PastureName) dashboardTopData1.MixedFodderCorrectRatio.Ratio = append(dashboardTopData1.MixedFodderCorrectRatio.Ratio, v.Ratio) } for _, v := range dashboardTopData.MixedFodderAccurateRatio { pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT] = append(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT], &model.PastureDayTimeRatio{ PastureId: v.PastureId, PastureName: v.PastureName, Ratio: v.Ratio, }) dashboardTopData1.MixedFodderAccurateRatio.Title = append(dashboardTopData1.MixedFodderAccurateRatio.Title, v.PastureName) dashboardTopData1.MixedFodderAccurateRatio.Ratio = append(dashboardTopData1.MixedFodderAccurateRatio.Ratio, v.Ratio) } for _, v := range dashboardTopData.SprinkleFodderAccurateRatio { pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE] = append(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE], &model.PastureDayTimeRatio{ PastureId: v.PastureId, PastureName: v.PastureName, Ratio: v.Ratio, }) dashboardTopData1.SprinkleFodderAccurateRatio.Title = append(dashboardTopData1.SprinkleFodderAccurateRatio.Title, v.PastureName) dashboardTopData1.SprinkleFodderAccurateRatio.Ratio = append(dashboardTopData1.SprinkleFodderAccurateRatio.Ratio, v.Ratio) } for _, v := range dashboardTopData.SprinkleFodderCorrectRatio { pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT] = append(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT], &model.PastureDayTimeRatio{ PastureId: v.PastureId, PastureName: v.PastureName, Ratio: v.Ratio, }) dashboardTopData1.SprinkleFodderCorrectRatio.Title = append(dashboardTopData1.SprinkleFodderCorrectRatio.Title, v.PastureName) dashboardTopData1.SprinkleFodderCorrectRatio.Ratio = append(dashboardTopData1.SprinkleFodderCorrectRatio.Ratio, v.Ratio) } // 排序 最大值。最小值。中位数 sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE], func(i, j int) bool { return pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][j].Ratio }) sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT], func(i, j int) bool { return pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][j].Ratio }) sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE], func(i, j int) bool { return pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][j].Ratio }) sort.Slice(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT], func(i, j int) bool { return pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][i].Ratio < pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][j].Ratio }) // 混料准确率 dashboardTopData1.MixedFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE])-1].Ratio) dashboardTopData1.MixedFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][0].Ratio) dashboardTopData1.MixedFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE])) dashboardTopData1.MixedFodderAccurateRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_ACCURATE])-1].PastureName // 混料正确率 dashboardTopData1.MixedFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT])-1].Ratio) dashboardTopData1.MixedFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][0].Ratio) dashboardTopData1.MixedFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT])) dashboardTopData1.MixedFodderCorrectRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_MIXED_CORRECT])-1].PastureName // 散料准确率 dashboardTopData1.SprinkleFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE])-1].Ratio) dashboardTopData1.SprinkleFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][0].Ratio) dashboardTopData1.SprinkleFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE])) dashboardTopData1.SprinkleFodderAccurateRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE][len(pastureDayTimeRatioList[operationPb.DashboardTopType_SPRINKLE_ACCURATE])-1].PastureName // 散料正确率 dashboardTopData1.SprinkleFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT])-1].Ratio) dashboardTopData1.SprinkleFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][0].Ratio) dashboardTopData1.SprinkleFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", getPastureDayTimeRatioMiddleValue(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT])) dashboardTopData1.SprinkleFodderCorrectRatio.TopOneName = pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT][len(pastureDayTimeRatioList[operationPb.DashboardTopType_Sprinkle_CORRECT])-1].PastureName res.Data.Chart = dashboardTopData1 return res, nil } // TopPasture 牧场排名 func (s *StoreEntry) TopPasture(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error) { res := &model.GetPastureTopResponse{ Code: http.StatusOK, Msg: "ok", Data: nil, } dashboardTopData, _, err := s.DashboardTopPasture(ctx, req) if err != nil { return nil, xerr.WithStack(err) } res.Data = dashboardTopData return res, nil } func (s *StoreEntry) DashboardTopPasture(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.PastureTop, map[int64]*model.PastureAnalysisAccuracyData, error) { dashboardTopData := &model.PastureTop{ MixedFodderAccurateRatio: make([]*model.PastureTopData, 0), MixedFodderCorrectRatio: make([]*model.PastureTopData, 0), SprinkleFodderAccurateRatio: make([]*model.PastureTopData, 0), SprinkleFodderCorrectRatio: make([]*model.PastureTopData, 0), } analysisAccuracy, err := s.PasturePrefAnalysisData(ctx, req) if err != nil { return nil, nil, xerr.WithStack(err) } for pastureId, data := range analysisAccuracy { groupPasture, err := s.GetGroupPastureListById(ctx, pastureId) if err != nil { zaplog.Error("TopPasture", zap.Any("GetGroupPastureListById", pastureId), zap.Any("err", err)) continue } if data == nil { continue } allMaRatio, allMcRatio, allSaRatio, allScRatio := 0.0, 0.0, 0.0, 0.0 for _, v := range data.MixedFodderAccurateRatio { allMaRatio += v.Ratio } dashboardTopData.MixedFodderAccurateRatio = append(dashboardTopData.MixedFodderAccurateRatio, &model.PastureTopData{ PastureId: pastureId, PastureName: groupPasture.Name, Ratio: tool.Decimal(allMaRatio / float64(len(data.MixedFodderAccurateRatio))), }) for _, v := range data.MixedFodderCorrectRatio { allMcRatio += v.Ratio } dashboardTopData.MixedFodderCorrectRatio = append(dashboardTopData.MixedFodderCorrectRatio, &model.PastureTopData{ PastureId: pastureId, PastureName: groupPasture.Name, Ratio: tool.Decimal(allMcRatio / float64(len(data.MixedFodderCorrectRatio))), }) for _, v := range data.SprinkleFodderAccurateRatio { allSaRatio += v.Ratio } dashboardTopData.SprinkleFodderAccurateRatio = append(dashboardTopData.SprinkleFodderAccurateRatio, &model.PastureTopData{ PastureId: pastureId, PastureName: groupPasture.Name, Ratio: tool.Decimal(allSaRatio / float64(len(data.SprinkleFodderAccurateRatio))), }) for _, v := range data.SprinkleFodderCorrectRatio { allScRatio += v.Ratio } dashboardTopData.SprinkleFodderCorrectRatio = append(dashboardTopData.SprinkleFodderCorrectRatio, &model.PastureTopData{ PastureId: pastureId, PastureName: groupPasture.Name, Ratio: tool.Decimal(allScRatio / float64(len(data.SprinkleFodderCorrectRatio))), }) } sort.Slice(dashboardTopData.MixedFodderAccurateRatio, func(i, j int) bool { return dashboardTopData.MixedFodderAccurateRatio[i].Ratio > dashboardTopData.MixedFodderAccurateRatio[j].Ratio }) sort.Slice(dashboardTopData.MixedFodderCorrectRatio, func(i, j int) bool { return dashboardTopData.MixedFodderCorrectRatio[i].Ratio > dashboardTopData.MixedFodderCorrectRatio[j].Ratio }) sort.Slice(dashboardTopData.SprinkleFodderAccurateRatio, func(i, j int) bool { return dashboardTopData.SprinkleFodderAccurateRatio[i].Ratio > dashboardTopData.SprinkleFodderAccurateRatio[j].Ratio }) sort.Slice(dashboardTopData.SprinkleFodderCorrectRatio, func(i, j int) bool { return dashboardTopData.SprinkleFodderCorrectRatio[i].Ratio > dashboardTopData.SprinkleFodderCorrectRatio[j].Ratio }) if req.DashboardTopType > 0 { switch req.DashboardTopType { case operationPb.DashboardTopType_MIXED_ACCURATE: dashboardTopData.MixedFodderAccurateRatio = dashboardTopRand(req, dashboardTopData.MixedFodderAccurateRatio) case operationPb.DashboardTopType_MIXED_CORRECT: dashboardTopData.MixedFodderCorrectRatio = dashboardTopRand(req, dashboardTopData.MixedFodderCorrectRatio) case operationPb.DashboardTopType_SPRINKLE_ACCURATE: dashboardTopData.SprinkleFodderAccurateRatio = dashboardTopRand(req, dashboardTopData.SprinkleFodderAccurateRatio) case operationPb.DashboardTopType_Sprinkle_CORRECT: dashboardTopData.SprinkleFodderCorrectRatio = dashboardTopRand(req, dashboardTopData.SprinkleFodderCorrectRatio) } } return dashboardTopData, analysisAccuracy, nil } func (s *StoreEntry) TitleList(ctx context.Context, pastureAnalysisList map[int64]*model.PastureAnalysisAccuracyData) *model.Table { res := &model.Table{ TitleList: make([]*model.TableList, 0), DataList: &model.DataList{ MixedFodderAccurateRatio: make([]map[string]string, 0), MixedFodderCorrectRatio: make([]map[string]string, 0), SprinkleFodderAccurateRatio: make([]map[string]string, 0), SprinkleFodderCorrectRatio: make([]map[string]string, 0), }, } for pastureId, data := range pastureAnalysisList { groupPasture, err := s.GetGroupPastureListById(ctx, pastureId) if err != nil { zaplog.Info("TitleList", zap.Any("GetGroupPastureListById", pastureId), zap.Any("err", err)) continue } if len(res.TitleList) <= len(data.MixedFodderAccurateRatio) { res.TitleList = append(res.TitleList, &model.TableList{ Name: "title", Value: "牧场", }) } maMap := map[string]string{ "title": groupPasture.Name, } for i, v := range data.MixedFodderCorrectRatio { maMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio) if len(res.TitleList) <= len(data.MixedFodderAccurateRatio) { res.TitleList = append(res.TitleList, &model.TableList{ Name: fmt.Sprintf("data%d", i+1), Value: v.DayTime, }) } } res.DataList.MixedFodderAccurateRatio = append(res.DataList.MixedFodderAccurateRatio, maMap) mcMap := map[string]string{ "title": groupPasture.Name, } for i, v := range data.MixedFodderCorrectRatio { mcMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio) } res.DataList.MixedFodderCorrectRatio = append(res.DataList.MixedFodderCorrectRatio, mcMap) saMap := map[string]string{ "title": groupPasture.Name, } for i, v := range data.SprinkleFodderAccurateRatio { saMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio) } res.DataList.SprinkleFodderAccurateRatio = append(res.DataList.SprinkleFodderAccurateRatio, saMap) scMap := map[string]string{ "title": groupPasture.Name, } for i, v := range data.SprinkleFodderCorrectRatio { scMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio) } res.DataList.SprinkleFodderCorrectRatio = append(res.DataList.SprinkleFodderCorrectRatio, scMap) } return res } func (s *StoreEntry) ExecutionTime(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.ExecTimeResponse, error) { res := &model.ExecTimeResponse{ Code: http.StatusOK, Msg: "ok", Data: &model.ExecTimeDataList{ Chart: &model.ExecTimeDataListChart{ Title: make([]string, 0), AddFeedTime: make([][]string, 0), SprinkleTime: make([][]string, 0), StirTime: make([][]string, 0), }, TableList: make([]map[string]string, 0), }, } pastureExecTime, err := s.PasturePrefExecTimeData(ctx, req) if err != nil { return nil, xerr.WithStack(err) } for pastureName, execTime := range pastureExecTime { res.Data.Chart.Title = append(res.Data.Chart.Title, pastureName) addFeedTimeStr, sprinkleTimeStr, stirTimeStr := make([]string, 0), make([]string, 0), make([]string, 0) if execTime != nil { addFeedTimeStr = append(addFeedTimeStr, execTime.AddFeedTime.MaxValue, execTime.AddFeedTime.UpMiddleValue, execTime.AddFeedTime.MiddleValue, execTime.AddFeedTime.DownMiddleValue, execTime.AddFeedTime.MinValue) sprinkleTimeStr = append(sprinkleTimeStr, execTime.SprinkleTime.MaxValue, execTime.SprinkleTime.UpMiddleValue, execTime.SprinkleTime.MiddleValue, execTime.SprinkleTime.DownMiddleValue, execTime.SprinkleTime.MinValue) stirTimeStr = append(stirTimeStr, execTime.StirTime.MaxValue, execTime.StirTime.UpMiddleValue, execTime.StirTime.MiddleValue, execTime.StirTime.DownMiddleValue, execTime.StirTime.MinValue) } res.Data.Chart.AddFeedTime = append(res.Data.Chart.AddFeedTime, addFeedTimeStr) res.Data.Chart.SprinkleTime = append(res.Data.Chart.SprinkleTime, sprinkleTimeStr) res.Data.Chart.StirTime = append(res.Data.Chart.StirTime, stirTimeStr) if execTime == nil { continue } tableList := map[string]string{ "title": pastureName, "add_feed_time": "加料时间", "add_feed_time_max_value": execTime.AddFeedTime.MaxValue, "add_feed_time_up_middle_value": execTime.AddFeedTime.UpMiddleValue, "add_feed_time_middle_value": execTime.AddFeedTime.MiddleValue, "add_feed_time_down_middle_value": execTime.AddFeedTime.DownMiddleValue, "add_feed_time_min_value": execTime.AddFeedTime.MinValue, "sprinkle_time": "撒料时间", "sprinkle_time_max_value": execTime.SprinkleTime.MaxValue, "sprinkle_time_up_middle_value": execTime.SprinkleTime.UpMiddleValue, "sprinkle_time_middle_value": execTime.SprinkleTime.MiddleValue, "sprinkle_time_down_middle_value": execTime.SprinkleTime.DownMiddleValue, "sprinkle_time_min_value": execTime.SprinkleTime.MinValue, "stir_time": "搅拌延迟时间", "stir_time_max_value": execTime.StirTime.MaxValue, "stir_time_up_middle_value": execTime.StirTime.UpMiddleValue, "stir_time_middle_value": execTime.StirTime.MiddleValue, "stir_time_down_middle_value": execTime.StirTime.DownMiddleValue, "stir_time_min_value": execTime.StirTime.MinValue, } res.Data.TableList = append(res.Data.TableList, tableList) } return res, nil } func (s *StoreEntry) SprinkleFeedTime(ctx context.Context, req *operationPb.SprinkleFeedTimeRequest) (*model.SprinkleFeedTimeResponse, error) { res := &model.SprinkleFeedTimeResponse{ Code: http.StatusOK, Msg: "ok", Data: &model.SprinkleFeedTimeData{ Chart: &model.SprinkleFeedTimeChart{ Title: make([]string, 0), SprinkleNumberList: make([][]int32, 0), }, TableList: make([]*model.SprinkleFeedTimeTable, 0), }, } pastureSprinkleDataList, pastureList, err := s.PastureSprinkleFeedTime(ctx, req) if err != nil { return nil, xerr.WithStack(err) } tableList := make([]*model.SprinkleFeedTimeTable, 0) infoSprinkleNumber, errorSprinkleNumber, pastureIds := make([]int32, 0), make([]int32, 0), make([]int, 0) for pastureId, _ := range pastureSprinkleDataList { pastureIds = append(pastureIds, int(pastureId)) } sort.Ints(pastureIds) pastureInfo := &model.GroupPasture{} for _, pastureId := range pastureIds { if pastureData, ok := pastureList[int64(pastureId)]; ok { pastureInfo = pastureData } if data, ok := pastureSprinkleDataList[int64(pastureId)]; ok { sprinkleFeedTimeList := make(map[int32]map[int32][]int64, 0) for _, v := range data { tableList = append(tableList, &model.SprinkleFeedTimeTable{ PastureName: pastureInfo.Name, BarnName: v.FName, ClassNumber: fmt.Sprintf("%d", v.Times), RealitySprinkleFeedTime: tool.TimeSub(v.InTime, v.ProcessTime), }) realityTime := tool.TimeSub(v.InTime, v.ProcessTime) realityTimeUnix, _ := time.Parse(model.LayoutTime, realityTime) if sprinkleFeedTimeList[v.FBarId] == nil { sprinkleFeedTimeList[v.FBarId] = make(map[int32][]int64, 0) } sprinkleFeedTimeList[v.FBarId][v.Times] = append(sprinkleFeedTimeList[v.FBarId][v.Times], realityTimeUnix.Unix()) } res.Data.Chart.Title = append(res.Data.Chart.Title, pastureInfo.Name) infoNumber, errNumber := sprinkleExecTimeAnalysis(sprinkleFeedTimeList) infoSprinkleNumber = append(infoSprinkleNumber, infoNumber) errorSprinkleNumber = append(errorSprinkleNumber, errNumber) } } res.Data.Chart.SprinkleNumberList = append(res.Data.Chart.SprinkleNumberList, infoSprinkleNumber, errorSprinkleNumber) res.Data.TableList = tableList return res, nil } func (s *StoreEntry) FeedMixedAndTmrName(ctx context.Context, req *operationPb.MixedCategoryTmrName) (*model.PastureCommonResponse, error) { groupPasture, err := s.GetGroupPastureListById(ctx, int64(req.PastureId)) if err != nil { return nil, xerr.WithStack(err) } pastureId := req.PastureId if groupPasture.PastureId > 0 { pastureId = int32(groupPasture.PastureId) } body := &model.PastureCommonRequest{ Name: req.ApiName, ReturnType: "Map", ParamMaps: &model.MixedCategoryTmrNameParams{ PastureId: fmt.Sprintf("%d", pastureId), StartTime: req.StartTime, EndTime: req.EndTime, }, } response := &model.PastureCommonResponse{Data: &model.PastureCommonData{}} if err = s.PastureHttpClient(ctx, model.UrlDataByName, int64(req.PastureId), body, response); err != nil { return nil, xerr.WithStack(err) } return response, nil } func (s *StoreEntry) FeedTemplateHistory(ctx context.Context, req *operationPb.FeedTemplateHistoryRequest) (*model.PastureFeedTemplateHistoryResponse, error) { groupPasture, err := s.GetGroupPastureListById(ctx, int64(req.PastureId)) if err != nil { return nil, xerr.WithStack(err) } pastureId := req.PastureId if groupPasture.PastureId > 0 { pastureId = int32(groupPasture.PastureId) } body := &model.PastureFeedTemplateHistoryRequest{ PastureId: fmt.Sprintf("%d", pastureId), FTid: int64(req.Ftid), StartDate: req.StartTime, EndDate: req.EndTime, } response := &model.PastureFeedTemplateHistoryResponse{} if err = s.PastureHttpClient(ctx, model.UrlFeedTemplateHistory, int64(req.PastureId), body, response); err != nil { return nil, xerr.WithStack(err) } return response, nil } func (s *StoreEntry) BarnHistory(ctx context.Context, req *operationPb.BarnHistoryRequest) (*model.PastureBarnHistoryResponse, error) { _, err := s.GetGroupPastureListById(ctx, int64(req.PastureId)) if err != nil { return nil, xerr.WithStack(err) } body := &model.PastureBarnHistoryRequest{ BarName: req.BarnName, StartDate: req.StartTime, EndDate: req.EndTime, } response := &model.PastureBarnHistoryResponse{} if err = s.PastureHttpClient(ctx, model.UrlBarnHistory, int64(req.PastureId), body, response); err != nil { return nil, xerr.WithStack(err) } return response, nil } func (s *StoreEntry) SpillageAllHistory(ctx context.Context, req *operationPb.BarnHistoryRequest) (*model.PastureBarnHistoryResponse, error) { groupPasture, err := s.GetGroupPastureListById(ctx, int64(req.PastureId)) if err != nil { return nil, xerr.WithStack(err) } pastureId := req.PastureId if groupPasture.PastureId > 0 { pastureId = int32(groupPasture.PastureId) } body := &model.PastureBarnHistoryRequest{ PastureId: fmt.Sprintf("%d", pastureId), BarName: req.BarnName, StartDate: req.StartTime, EndDate: req.EndTime, } response := &model.PastureBarnHistoryResponse{} if err = s.PastureHttpClient(ctx, model.UrlSpillageAllHistory, int64(req.PastureId), body, response); err != nil { return nil, xerr.WithStack(err) } return response, nil } func sprinkleExecTimeAnalysis(sprinkleFeedTimeList map[int32]map[int32][]int64) (int32, int32) { var infoSprinkleNumber, errorSprinkleNumber int32 = 0, 0 if len(sprinkleFeedTimeList) <= 0 { return infoSprinkleNumber, errorSprinkleNumber } else { for _, value := range sprinkleFeedTimeList { for _, execTimeList := range value { middleValue := tool.MedianInt64(execTimeList) for _, v := range execTimeList { if v >= middleValue-int64(compareTime) && v <= middleValue+int64(compareTime) { infoSprinkleNumber += 1 } else { errorSprinkleNumber += 1 } } } } } return infoSprinkleNumber, errorSprinkleNumber } func dashboardTopRand(req *operationPb.SearchAnalysisAccuracyRequest, data []*model.PastureTopData) []*model.PastureTopData { if req.TopRandStart < 0 || req.TopRandEnd < 0 || req.TopRandStart > req.TopRandEnd { return data } res := make([]*model.PastureTopData, 0) for _, v := range data { if v.Ratio >= float64(req.TopRandStart) && v.Ratio <= float64(req.TopRandEnd) { res = append(res, v) } } return res } func getPastureDayTimeRatioMiddleValue(pastureDayTimeRatio []*model.PastureDayTimeRatio) float64 { if len(pastureDayTimeRatio) <= 0 { return 0 } ratioList := make([]float64, 0) for _, v := range pastureDayTimeRatio { ratioList = append(ratioList, v.Ratio) } sort.Float64s(ratioList) return tool.Median(ratioList) }