dashboard_service.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. package backend
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "kpt-tmr-group/model"
  7. "kpt-tmr-group/pkg/logger/zaplog"
  8. "kpt-tmr-group/pkg/tool"
  9. "kpt-tmr-group/pkg/xerr"
  10. operationPb "kpt-tmr-group/proto/go/backend/operation"
  11. "net/http"
  12. "sort"
  13. "sync"
  14. "go.uber.org/multierr"
  15. "go.uber.org/zap"
  16. )
  17. func (s *StoreEntry) PasturePrefAnalysisData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[int64]*model.PastureAnalysisAccuracyData, error) {
  18. groupPastureList, err := s.FindGroupPastureListByIds(ctx, req.PastureIds)
  19. if err != nil {
  20. return nil, xerr.WithStack(err)
  21. }
  22. res := make(map[int64]*model.PastureAnalysisAccuracyData, 0)
  23. wg := sync.WaitGroup{}
  24. wg.Add(len(groupPastureList))
  25. var muError error
  26. for _, pasture := range groupPastureList {
  27. go func(p *model.GroupPasture) {
  28. response := &model.PastureAnalysisAccuracyResponse{}
  29. body := &model.DashboardAccuracyRequest{
  30. PastureId: int32(p.Id),
  31. FeedFormulaId: req.FeedFormulaId,
  32. CattleParentCategoryId: int32(req.CattleParentCategoryId),
  33. StartDate: req.StartDate,
  34. EndDate: req.EndDate,
  35. }
  36. if err = s.PastureHttpClient(ctx, DashboardAccuracyUrl, p.Id, body, response); err != nil {
  37. muError = multierr.Append(muError, err)
  38. zaplog.Error("DistributeFeedFormula",
  39. zap.String("url", DashboardAccuracyUrl),
  40. zap.Any("pasture", p), zap.Any("body", body),
  41. zap.Any("err", err), zap.Any("response", response))
  42. b, _ := json.Marshal(body)
  43. resB, _ := json.Marshal(response)
  44. pastureDataLog := model.NewPastureDataLog(p.Id, PastureDataLogType["FeedFormula_Distribute"], FeedFormulaDistributeUrl, string(b), string(resB))
  45. s.DB.Create(pastureDataLog)
  46. }
  47. if response.Code != http.StatusOK {
  48. muError = multierr.Append(muError, xerr.Custom(response.Msg))
  49. }
  50. res[p.Id] = response.Data
  51. wg.Done()
  52. }(pasture)
  53. }
  54. wg.Wait()
  55. return res, nil
  56. }
  57. func (s *StoreEntry) PasturePrefExecTimeData(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (map[string]*model.ExecTimeData, error) {
  58. groupPastureList, err := s.FindGroupPastureListByIds(ctx, req.PastureIds)
  59. if err != nil {
  60. return nil, xerr.WithStack(err)
  61. }
  62. res := make(map[string]*model.ExecTimeData, 0)
  63. wg := sync.WaitGroup{}
  64. wg.Add(len(groupPastureList))
  65. var muError error
  66. for _, pasture := range groupPastureList {
  67. go func(p *model.GroupPasture) {
  68. response := &model.PastureExecTimeData{}
  69. body := &model.DashboardAccuracyRequest{
  70. PastureId: int32(p.Id),
  71. FeedFormulaId: req.FeedFormulaId,
  72. CattleParentCategoryId: int32(req.CattleParentCategoryId),
  73. StartDate: req.StartDate,
  74. EndDate: req.EndDate,
  75. }
  76. if err = s.PastureHttpClient(ctx, DashboardExecTimeUrl, p.Id, body, response); err != nil {
  77. muError = multierr.Append(muError, err)
  78. zaplog.Error("PasturePrefExecTimeData",
  79. zap.String("url", DashboardExecTimeUrl),
  80. zap.Any("pasture", p), zap.Any("body", body),
  81. zap.Any("err", err), zap.Any("response", response))
  82. b, _ := json.Marshal(body)
  83. resB, _ := json.Marshal(response)
  84. pastureDataLog := model.NewPastureDataLog(p.Id, PastureDataLogType["PasturePrefExecTimeData"], DashboardExecTimeUrl, string(b), string(resB))
  85. s.DB.Create(pastureDataLog)
  86. }
  87. if response.Code != http.StatusOK {
  88. muError = multierr.Append(muError, xerr.Custom(response.Msg))
  89. }
  90. res[p.Name] = response.Data
  91. wg.Done()
  92. }(pasture)
  93. }
  94. wg.Wait()
  95. return res, nil
  96. }
  97. func (s *StoreEntry) SearchAnalysisAccuracy(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.SearchAnalysisAccuracyResponse, error) {
  98. res := &model.SearchAnalysisAccuracyResponse{
  99. Code: http.StatusOK,
  100. Msg: "ok",
  101. Data: &model.AnalysisAccuracyData{
  102. Chart: &model.Chart{},
  103. Table: &model.Table{
  104. TitleList: make([]*model.TableList, 0),
  105. DataList: &model.DataList{},
  106. },
  107. },
  108. }
  109. res.Data.Table.TitleList = append(res.Data.Table.TitleList, &model.TableList{
  110. Name: "title",
  111. Value: "牧场",
  112. })
  113. pastureAnalysisAccuracy, err := s.PasturePrefAnalysisData(ctx, req)
  114. if err != nil {
  115. return nil, xerr.WithStack(err)
  116. }
  117. mixedFodderAccurateRatio, mixedFodderCorrectRatio, sprinkleFodderAccurateRatio, sprinkleFodderCorrectRatio :=
  118. &model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{}, &model.CommonValueRatio{}
  119. maTitleValueList, mcTitleValueList, saTitleValueList, scTitleValueList := make([]float64, 0), make([]float64, 0), make([]float64, 0), make([]float64, 0)
  120. mTopOneName := ""
  121. for pastureId, data := range pastureAnalysisAccuracy {
  122. groupPasture, err := s.GetGroupPastureListById(ctx, pastureId)
  123. if err != nil {
  124. zaplog.Error("SearchAnalysisAccuracy GetGroupPastureListById",
  125. zap.Any("pastureId", pastureId), zap.Any("error", err))
  126. continue
  127. }
  128. if data == nil {
  129. continue
  130. }
  131. mixedFodderAccurateRatioDataList := make([]string, 0)
  132. for _, v := range data.MixedFodderAccurateRatio {
  133. mixedFodderAccurateRatioDataList = append(mixedFodderAccurateRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
  134. mixedFodderAccurateRatio.DateDay = append(mixedFodderAccurateRatio.DateDay, v.DayTime)
  135. maTitleValueList = append(maTitleValueList, v.Ratio)
  136. }
  137. mixedFodderAccurateRatio.DataList = append(mixedFodderAccurateRatio.DataList, mixedFodderAccurateRatioDataList)
  138. mixedFodderAccurateRatio.PastureIds = append(mixedFodderAccurateRatio.PastureIds, int32(pastureId))
  139. mixedFodderAccurateRatio.PastureName = append(mixedFodderAccurateRatio.PastureName, groupPasture.Name)
  140. mixedFodderCorrectRatioDataList := make([]string, 0)
  141. for _, v := range data.MixedFodderCorrectRatio {
  142. mixedFodderCorrectRatioDataList = append(mixedFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
  143. mixedFodderCorrectRatio.DateDay = append(mixedFodderCorrectRatio.DateDay, v.DayTime)
  144. mcTitleValueList = append(mcTitleValueList, v.Ratio)
  145. }
  146. mixedFodderCorrectRatio.DataList = append(mixedFodderCorrectRatio.DataList, mixedFodderCorrectRatioDataList)
  147. mixedFodderCorrectRatio.PastureIds = append(mixedFodderCorrectRatio.PastureIds, int32(pastureId))
  148. mixedFodderCorrectRatio.PastureName = append(mixedFodderCorrectRatio.PastureName, groupPasture.Name)
  149. sprinkleFodderRatioDataList := make([]string, 0)
  150. for _, v := range data.SprinkleFodderAccurateRatio {
  151. sprinkleFodderRatioDataList = append(sprinkleFodderRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
  152. sprinkleFodderAccurateRatio.DateDay = append(sprinkleFodderAccurateRatio.DateDay, v.DayTime)
  153. saTitleValueList = append(saTitleValueList, v.Ratio)
  154. }
  155. sprinkleFodderAccurateRatio.DataList = append(sprinkleFodderAccurateRatio.DataList, sprinkleFodderRatioDataList)
  156. sprinkleFodderAccurateRatio.PastureIds = append(sprinkleFodderAccurateRatio.PastureIds, int32(pastureId))
  157. sprinkleFodderAccurateRatio.PastureName = append(sprinkleFodderAccurateRatio.PastureName, groupPasture.Name)
  158. sprinkleFodderCorrectRatioDataList := make([]string, 0)
  159. for _, v := range data.SprinkleFodderCorrectRatio {
  160. sprinkleFodderCorrectRatioDataList = append(sprinkleFodderCorrectRatioDataList, fmt.Sprintf("%.2f", v.Ratio))
  161. sprinkleFodderCorrectRatio.DateDay = append(sprinkleFodderCorrectRatio.DateDay, v.DayTime)
  162. scTitleValueList = append(scTitleValueList, v.Ratio)
  163. }
  164. sprinkleFodderCorrectRatio.DataList = append(sprinkleFodderCorrectRatio.DataList, sprinkleFodderCorrectRatioDataList)
  165. sprinkleFodderCorrectRatio.PastureIds = append(sprinkleFodderCorrectRatio.PastureIds, int32(pastureId))
  166. sprinkleFodderCorrectRatio.PastureName = append(sprinkleFodderCorrectRatio.PastureName, groupPasture.Name)
  167. }
  168. sort.Float64s(maTitleValueList)
  169. mixedFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", maTitleValueList[len(maTitleValueList)-1])
  170. mixedFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", maTitleValueList[0])
  171. mixedFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(maTitleValueList))
  172. mixedFodderAccurateRatio.TopOneName = mTopOneName
  173. sort.Float64s(mcTitleValueList)
  174. mixedFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", mcTitleValueList[len(mcTitleValueList)-1])
  175. mixedFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", mcTitleValueList[0])
  176. mixedFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(mcTitleValueList))
  177. mixedFodderCorrectRatio.TopOneName = mTopOneName
  178. sort.Float64s(saTitleValueList)
  179. sprinkleFodderAccurateRatio.MaxValue = fmt.Sprintf("%.2f", saTitleValueList[len(saTitleValueList)-1])
  180. sprinkleFodderAccurateRatio.MinValue = fmt.Sprintf("%.2f", saTitleValueList[0])
  181. sprinkleFodderAccurateRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(saTitleValueList))
  182. sprinkleFodderAccurateRatio.TopOneName = mTopOneName
  183. sort.Float64s(scTitleValueList)
  184. sprinkleFodderCorrectRatio.MaxValue = fmt.Sprintf("%.2f", scTitleValueList[len(scTitleValueList)-1])
  185. sprinkleFodderCorrectRatio.MinValue = fmt.Sprintf("%.2f", scTitleValueList[0])
  186. sprinkleFodderCorrectRatio.MiddleValue = fmt.Sprintf("%.2f", tool.Median(scTitleValueList))
  187. sprinkleFodderCorrectRatio.TopOneName = mTopOneName
  188. chart := &model.Chart{
  189. MixedFodderAccurateRatio: mixedFodderAccurateRatio,
  190. MixedFodderCorrectRatio: mixedFodderCorrectRatio,
  191. SprinkleFodderAccurateRatio: sprinkleFodderAccurateRatio,
  192. SprinkleFodderCorrectRatio: sprinkleFodderCorrectRatio,
  193. }
  194. res.Data.Chart = chart
  195. res.Data.Table = s.TitleList(ctx, pastureAnalysisAccuracy)
  196. return res, nil
  197. }
  198. // TopPasture 牧场排名
  199. func (s *StoreEntry) TopPasture(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.GetPastureTopResponse, error) {
  200. res := &model.GetPastureTopResponse{
  201. Code: http.StatusOK,
  202. Msg: "ok",
  203. Data: &model.PastureTop{
  204. MixedFodderAccurateRatio: make([]*model.PastureTopData, 0),
  205. MixedFodderCorrectRatio: make([]*model.PastureTopData, 0),
  206. SprinkleFodderAccurateRatio: make([]*model.PastureTopData, 0),
  207. SprinkleFodderCorrectRatio: make([]*model.PastureTopData, 0),
  208. },
  209. }
  210. analysisAccuracy, err := s.PasturePrefAnalysisData(ctx, req)
  211. if err != nil {
  212. return nil, xerr.WithStack(err)
  213. }
  214. mixedFodderAccurateRatio := make([]*model.PastureTopData, 0)
  215. mixedFodderCorrectRatio := make([]*model.PastureTopData, 0)
  216. sprinkleFodderAccurateRatio := make([]*model.PastureTopData, 0)
  217. sprinkleFodderCorrectRatio := make([]*model.PastureTopData, 0)
  218. for pastureId, data := range analysisAccuracy {
  219. groupPasture, err := s.GetGroupPastureListById(ctx, pastureId)
  220. if err != nil {
  221. zaplog.Error("TopPasture", zap.Any("GetGroupPastureListById", pastureId), zap.Any("err", err))
  222. continue
  223. }
  224. if data == nil {
  225. continue
  226. }
  227. allMaRatio, allMcRatio, allSaRatio, allScRatio := 0.0, 0.0, 0.0, 0.0
  228. for _, v := range data.MixedFodderAccurateRatio {
  229. allMaRatio += v.Ratio
  230. }
  231. mixedFodderAccurateRatio = append(mixedFodderAccurateRatio, &model.PastureTopData{
  232. PastureName: groupPasture.Name,
  233. Ratio: allMaRatio / float64(len(data.MixedFodderAccurateRatio)),
  234. })
  235. for _, v := range data.MixedFodderCorrectRatio {
  236. allMcRatio += v.Ratio
  237. }
  238. mixedFodderCorrectRatio = append(mixedFodderCorrectRatio, &model.PastureTopData{
  239. PastureName: groupPasture.Name,
  240. Ratio: allMaRatio / float64(len(data.MixedFodderCorrectRatio)),
  241. })
  242. for _, v := range data.SprinkleFodderAccurateRatio {
  243. allSaRatio += v.Ratio
  244. }
  245. sprinkleFodderAccurateRatio = append(sprinkleFodderAccurateRatio, &model.PastureTopData{
  246. PastureName: groupPasture.Name,
  247. Ratio: allSaRatio / float64(len(data.SprinkleFodderAccurateRatio)),
  248. })
  249. for _, v := range data.SprinkleFodderCorrectRatio {
  250. allScRatio += v.Ratio
  251. }
  252. sprinkleFodderCorrectRatio = append(sprinkleFodderCorrectRatio, &model.PastureTopData{
  253. PastureName: groupPasture.Name,
  254. Ratio: allScRatio / float64(len(data.SprinkleFodderCorrectRatio)),
  255. })
  256. }
  257. sort.Slice(mixedFodderAccurateRatio, func(i, j int) bool {
  258. return mixedFodderAccurateRatio[i].Ratio > mixedFodderAccurateRatio[j].Ratio
  259. })
  260. sort.Slice(mixedFodderCorrectRatio, func(i, j int) bool {
  261. return mixedFodderCorrectRatio[i].Ratio > mixedFodderCorrectRatio[j].Ratio
  262. })
  263. sort.Slice(sprinkleFodderAccurateRatio, func(i, j int) bool {
  264. return sprinkleFodderAccurateRatio[i].Ratio > sprinkleFodderAccurateRatio[j].Ratio
  265. })
  266. sort.Slice(sprinkleFodderCorrectRatio, func(i, j int) bool {
  267. return sprinkleFodderCorrectRatio[i].Ratio > sprinkleFodderCorrectRatio[j].Ratio
  268. })
  269. res.Data.MixedFodderAccurateRatio = mixedFodderAccurateRatio
  270. res.Data.MixedFodderCorrectRatio = mixedFodderCorrectRatio
  271. res.Data.SprinkleFodderAccurateRatio = sprinkleFodderAccurateRatio
  272. res.Data.SprinkleFodderCorrectRatio = sprinkleFodderCorrectRatio
  273. return res, nil
  274. }
  275. func (s *StoreEntry) TitleList(ctx context.Context, pastureAnalysisList map[int64]*model.PastureAnalysisAccuracyData) *model.Table {
  276. res := &model.Table{
  277. TitleList: make([]*model.TableList, 0),
  278. DataList: &model.DataList{
  279. MixedFodderAccurateRatio: make([]map[string]string, 0),
  280. MixedFodderCorrectRatio: make([]map[string]string, 0),
  281. SprinkleFodderAccurateRatio: make([]map[string]string, 0),
  282. SprinkleFodderCorrectRatio: make([]map[string]string, 0),
  283. },
  284. }
  285. for pastureId, data := range pastureAnalysisList {
  286. groupPasture, err := s.GetGroupPastureListById(ctx, pastureId)
  287. if err != nil {
  288. zaplog.Info("TitleList", zap.Any("GetGroupPastureListById", pastureId), zap.Any("err", err))
  289. continue
  290. }
  291. if len(res.TitleList) <= len(data.MixedFodderAccurateRatio) {
  292. res.TitleList = append(res.TitleList, &model.TableList{
  293. Name: "title",
  294. Value: "牧场",
  295. })
  296. }
  297. maMap := map[string]string{
  298. "title": groupPasture.Name,
  299. }
  300. for i, v := range data.MixedFodderCorrectRatio {
  301. maMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
  302. if len(res.TitleList) <= len(data.MixedFodderAccurateRatio) {
  303. res.TitleList = append(res.TitleList, &model.TableList{
  304. Name: fmt.Sprintf("data%d", i+1),
  305. Value: v.DayTime,
  306. })
  307. }
  308. }
  309. res.DataList.MixedFodderAccurateRatio = append(res.DataList.MixedFodderAccurateRatio, maMap)
  310. mcMap := map[string]string{
  311. "title": groupPasture.Name,
  312. }
  313. for i, v := range data.MixedFodderCorrectRatio {
  314. mcMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
  315. }
  316. res.DataList.MixedFodderCorrectRatio = append(res.DataList.MixedFodderCorrectRatio, mcMap)
  317. saMap := map[string]string{
  318. "title": groupPasture.Name,
  319. }
  320. for i, v := range data.SprinkleFodderAccurateRatio {
  321. saMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
  322. }
  323. res.DataList.SprinkleFodderAccurateRatio = append(res.DataList.SprinkleFodderAccurateRatio, saMap)
  324. scMap := map[string]string{
  325. "title": groupPasture.Name,
  326. }
  327. for i, v := range data.SprinkleFodderCorrectRatio {
  328. scMap[fmt.Sprintf("data%d", i+1)] = fmt.Sprintf("%.2f", v.Ratio)
  329. }
  330. res.DataList.SprinkleFodderCorrectRatio = append(res.DataList.SprinkleFodderCorrectRatio, scMap)
  331. }
  332. return res
  333. }
  334. func (s *StoreEntry) ExecutionTime(ctx context.Context, req *operationPb.SearchAnalysisAccuracyRequest) (*model.ExecTimeResponse, error) {
  335. res := &model.ExecTimeResponse{
  336. Code: http.StatusOK,
  337. Msg: "ok",
  338. Data: make(map[string]*model.ExecTimeData, 0),
  339. }
  340. pastureExecTime, err := s.PasturePrefExecTimeData(ctx, req)
  341. if err != nil {
  342. return nil, xerr.WithStack(err)
  343. }
  344. for pastureName, execTime := range pastureExecTime {
  345. if execTime == nil {
  346. continue
  347. }
  348. res.Data = map[string]*model.ExecTimeData{
  349. pastureName: {
  350. AddFeedTime: execTime.AddFeedTime,
  351. SprinkleTime: execTime.SprinkleTime,
  352. StirTime: execTime.StirTime,
  353. },
  354. }
  355. }
  356. return res, nil
  357. }