package backend import ( "context" "encoding/json" "fmt" "kpt-tmr-group/model" "kpt-tmr-group/pkg/logger/zaplog" "kpt-tmr-group/pkg/tool" "kpt-tmr-group/pkg/xerr" operationPb "kpt-tmr-group/proto/go/backend/operation" "net/http" "sort" "sync" "go.uber.org/multierr" "go.uber.org/zap" ) func (s *StoreEntry) PasturePrefAnalysisData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[int64]*model.PastureAnalysisAccuracyData, error) { groupPastureList, err := s.FindGroupPastureListByIds(ctx, req.PastureIds) if err != nil { return nil, xerr.WithStack(err) } res := make(map[int64]*model.PastureAnalysisAccuracyData, 0) wg := sync.WaitGroup{} wg.Add(len(groupPastureList)) var muError error for _, pasture := range groupPastureList { go func(p *model.GroupPasture) { response := &model.PastureAnalysisAccuracyResponse{} body := &model.DashboardAccuracyRequest{ PastureId: int32(p.Id), FeedFormulaId: req.FeedFormulaId, CattleParentCategoryId: int32(req.CattleParentCategoryId), StartDate: req.StartDate, EndDate: req.EndDate, } if err = s.PastureHttpClient(ctx, DashboardAccuracyUrl, p.Id, body, response); err != nil { muError = multierr.Append(muError, err) zaplog.Error("DistributeFeedFormula", zap.String("url", DashboardAccuracyUrl), zap.Any("pasture", p), zap.Any("body", body), zap.Any("err", err), zap.Any("response", response)) b, _ := json.Marshal(body) resB, _ := json.Marshal(response) pastureDataLog := model.NewPastureDataLog(p.Id, PastureDataLogType["FeedFormula_Distribute"], FeedFormulaDistributeUrl, string(b), string(resB)) s.DB.Create(pastureDataLog) } if response.Code != http.StatusOK { muError = multierr.Append(muError, xerr.Custom(response.Msg)) } res[p.Id] = response.Data wg.Done() }(pasture) } wg.Wait() return res, nil } func (s *StoreEntry) PasturePrefExecTimeData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[string]*model.ExecTimeData, error) { groupPastureList, err := s.FindGroupPastureListByIds(ctx, req.PastureIds) if err != nil { return nil, xerr.WithStack(err) } res := make(map[string]*model.ExecTimeData, 0) wg := sync.WaitGroup{} wg.Add(len(groupPastureList)) var muError error for _, pasture := range groupPastureList { go func(p *model.GroupPasture) { response := &model.PastureExecTimeData{} body := &model.DashboardAccuracyRequest{ PastureId: int32(p.Id), FeedFormulaId: req.FeedFormulaId, CattleParentCategoryId: int32(req.CattleParentCategoryId), StartDate: req.StartDate, EndDate: req.EndDate, } if err = s.PastureHttpClient(ctx, DashboardExecTimeUrl, p.Id, body, response); err != nil { muError = multierr.Append(muError, err) zaplog.Error("PasturePrefExecTimeData", zap.String("url", DashboardExecTimeUrl), zap.Any("pasture", p), zap.Any("body", body), zap.Any("err", err), zap.Any("response", response)) b, _ := json.Marshal(body) resB, _ := json.Marshal(response) pastureDataLog := model.NewPastureDataLog(p.Id, PastureDataLogType["PasturePrefExecTimeData"], DashboardExecTimeUrl, string(b), string(resB)) s.DB.Create(pastureDataLog) } if response.Code != http.StatusOK { muError = multierr.Append(muError, xerr.Custom(response.Msg)) } res[p.Name] = response.Data wg.Done() }(pasture) } wg.Wait() return res, nil } func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) { res := &model.SearchAnalysisAccuracyResponse{ Code: http.StatusOK, Msg: "ok", Data: &model.AnalysisAccuracyData{ Chart: &model.Chart{}, Table: &model.Table{ TitleList: make([]*model.TableList, 0), DataList: &model.DataList{}, }, }, } res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{ Name: "title", Value: "牧场", }) pastureAnalysisAccuracy, err := s.PasturePrefAnalysisData(ctx, req) if err != nil { return nil, xerr.WithStack(err) } mixedFodderAccurateRatio, mixedFodderCorrectRatio, sprinkleFodderAccurateRatio, sprinkleFodderCorrectRatio := &model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{} maTitleValueList, mcTitleValueList, saTitleValueList, scTitleValueList := make([]float64, 0), make([]float64, 0), make([]float64, 0), make([]float64, 0) mTopOneName := "" for pastureId, data := range pastureAnalysisAccuracy { groupPasture, err := s.GetGroupPastureListById(ctx, pastureId) if err != nil { zaplog.Error("SearchAnalysisAccuracy GetGroupPastureListById", zap.Any("pastureId", pastureId), zap.Any("error", err)) continue } if data == nil { continue } mixedFodderAccurateRatioDataList := make([]string, 0) for _, v := range data.MixedFodderAccurateRatio { mixedFodderAccurateRatioDataList = append(mixedFodderAccurateRatioDataList, fmt.Sprintf("%.2f", v.Ratio)) mixedFodderAccurateRatio.DateDay = append(mixedFodderAccurateRatio.DateDay, v.DayTime) maTitleValueList = append(maTitleValueList, v.Ratio) } mixedFodderAccurateRatio.DataList = append(mixedFodderAccurateRatio.DataList, mixedFodderAccurateRatioDataList) mixedFodderAccurateRatio.PastureIds = append(mixedFodderAccurateRatio.PastureIds, int32(pastureId)) mixedFodderAccurateRatio.PastureName = append(mixedFodderAccurateRatio.PastureName, groupPasture.Name) mixedFodderCorrectRatioDataList := make([]string, 0) for _, v := range data.MixedFodderCorrectRatio { mixedFodderCorrectRatioDataList = append(mixedFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio)) mixedFodderCorrectRatio.DateDay = append(mixedFodderCorrectRatio.DateDay, v.DayTime) mcTitleValueList = append(mcTitleValueList, v.Ratio) } mixedFodderCorrectRatio.DataList = append(mixedFodderCorrectRatio.DataList, mixedFodderCorrectRatioDataList) mixedFodderCorrectRatio.PastureIds = append(mixedFodderCorrectRatio.PastureIds, int32(pastureId)) mixedFodderCorrectRatio.PastureName = append(mixedFodderCorrectRatio.PastureName, groupPasture.Name) sprinkleFodderRatioDataList := make([]string, 0) for _, v := range data.SprinkleFodderAccurateRatio { sprinkleFodderRatioDataList = append(sprinkleFodderRatioDataList, fmt.Sprintf("%.2f", v.Ratio)) sprinkleFodderAccurateRatio.DateDay = append(sprinkleFodderAccurateRatio.DateDay, v.DayTime) saTitleValueList = append(saTitleValueList, v.Ratio) } sprinkleFodderAccurateRatio.DataList = append(sprinkleFodderAccurateRatio.DataList, sprinkleFodderRatioDataList) sprinkleFodderAccurateRatio.PastureIds = append(sprinkleFodderAccurateRatio.PastureIds, int32(pastureId)) sprinkleFodderAccurateRatio.PastureName = append(sprinkleFodderAccurateRatio.PastureName, groupPasture.Name) sprinkleFodderCorrectRatioDataList := make([]string, 0) for _, v := range data.SprinkleFodderCorrectRatio { sprinkleFodderCorrectRatioDataList = append(sprinkleFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio)) sprinkleFodderCorrectRatio.DateDay = append(sprinkleFodderCorrectRatio.DateDay, v.DayTime) scTitleValueList = append(scTitleValueList, v.Ratio) } sprinkleFodderCorrectRatio.DataList = append(sprinkleFodderCorrectRatio.DataList, sprinkleFodderCorrectRatioDataList) sprinkleFodderCorrectRatio.PastureIds = append(sprinkleFodderCorrectRatio.PastureIds, int32(pastureId)) sprinkleFodderCorrectRatio.PastureName = append(sprinkleFodderCorrectRatio.PastureName, groupPasture.Name) } sort.Float64s(maTitleValueList) mixedFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", maTitleValueList[len(maTitleValueList)-1]) mixedFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", maTitleValueList[0]) mixedFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(maTitleValueList)) mixedFodderAccurateRatio.TopOneName = mTopOneName sort.Float64s(mcTitleValueList) mixedFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", mcTitleValueList[len(mcTitleValueList)-1]) mixedFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", mcTitleValueList[0]) mixedFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(mcTitleValueList)) mixedFodderCorrectRatio.TopOneName = mTopOneName sort.Float64s(saTitleValueList) sprinkleFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", saTitleValueList[len(saTitleValueList)-1]) sprinkleFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", saTitleValueList[0]) sprinkleFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(saTitleValueList)) sprinkleFodderAccurateRatio.TopOneName = mTopOneName sort.Float64s(scTitleValueList) sprinkleFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", scTitleValueList[len(scTitleValueList)-1]) sprinkleFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", scTitleValueList[0]) sprinkleFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(scTitleValueList)) sprinkleFodderCorrectRatio.TopOneName = mTopOneName chart := &model.Chart{ MixedFodderAccurateRatio: mixedFodderAccurateRatio, MixedFodderCorrectRatio: mixedFodderCorrectRatio, SprinkleFodderAccurateRatio: sprinkleFodderAccurateRatio, SprinkleFodderCorrectRatio: sprinkleFodderCorrectRatio, } res.Data.Chart = chart res.Data.Table = s.TitleList(ctx, pastureAnalysisAccuracy) 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: &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, xerr.WithStack(err) } mixedFodderAccurateRatio := make([]*model.PastureTopData, 0) mixedFodderCorrectRatio := make([]*model.PastureTopData, 0) sprinkleFodderAccurateRatio := make([]*model.PastureTopData, 0) sprinkleFodderCorrectRatio := make([]*model.PastureTopData, 0) 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 } mixedFodderAccurateRatio = append(mixedFodderAccurateRatio, &model.PastureTopData{ PastureName: groupPasture.Name, Ratio: allMaRatio / float64(len(data.MixedFodderAccurateRatio)), }) for _, v := range data.MixedFodderCorrectRatio { allMcRatio += v.Ratio } mixedFodderCorrectRatio = append(mixedFodderCorrectRatio, &model.PastureTopData{ PastureName: groupPasture.Name, Ratio: allMaRatio / float64(len(data.MixedFodderCorrectRatio)), }) for _, v := range data.SprinkleFodderAccurateRatio { allSaRatio += v.Ratio } sprinkleFodderAccurateRatio = append(sprinkleFodderAccurateRatio, &model.PastureTopData{ PastureName: groupPasture.Name, Ratio: allSaRatio / float64(len(data.SprinkleFodderAccurateRatio)), }) for _, v := range data.SprinkleFodderCorrectRatio { allScRatio += v.Ratio } sprinkleFodderCorrectRatio = append(sprinkleFodderCorrectRatio, &model.PastureTopData{ PastureName: groupPasture.Name, Ratio: allScRatio / float64(len(data.SprinkleFodderCorrectRatio)), }) } sort.Slice(mixedFodderAccurateRatio, func(i, j int) bool { return mixedFodderAccurateRatio[i].Ratio > mixedFodderAccurateRatio[j].Ratio }) sort.Slice(mixedFodderCorrectRatio, func(i, j int) bool { return mixedFodderCorrectRatio[i].Ratio > mixedFodderCorrectRatio[j].Ratio }) sort.Slice(sprinkleFodderAccurateRatio, func(i, j int) bool { return sprinkleFodderAccurateRatio[i].Ratio > sprinkleFodderAccurateRatio[j].Ratio }) sort.Slice(sprinkleFodderCorrectRatio, func(i, j int) bool { return sprinkleFodderCorrectRatio[i].Ratio > sprinkleFodderCorrectRatio[j].Ratio }) res.Data.MixedFodderAccurateRatio = mixedFodderAccurateRatio res.Data.MixedFodderCorrectRatio = mixedFodderCorrectRatio res.Data.SprinkleFodderAccurateRatio = sprinkleFodderAccurateRatio res.Data.SprinkleFodderCorrectRatio = sprinkleFodderCorrectRatio return res, 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: make(map[string]*model.ExecTimeData, 0), } pastureExecTime, err := s.PasturePrefExecTimeData(ctx, req) if err != nil { return nil, xerr.WithStack(err) } for pastureName, execTime := range pastureExecTime { if execTime == nil { continue } res.Data = map[string]*model.ExecTimeData{ pastureName: { AddFeedTime: execTime.AddFeedTime, SprinkleTime: execTime.SprinkleTime, StirTime: execTime.StirTime, }, } } return res, nil }