processor_business_logic.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. package area_graph
  2. import (
  3. "errors"
  4. "eta/eta_api/models/data_manage"
  5. "eta/eta_api/utils"
  6. "github.com/shopspring/decimal"
  7. "math"
  8. "sort"
  9. "time"
  10. )
  11. type InterpolateStrategy struct{}
  12. func (i *InterpolateStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) (err error) {
  13. for _, v := range edbDataList {
  14. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  15. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  16. // 插值法补充数据
  17. var startEdbInfoData *data_manage.EdbDataList
  18. for index := 0; index < len(dataList)-1; index++ {
  19. // 获取当前数据和下一个数据
  20. beforeIndexData := dataList[index]
  21. afterIndexData := dataList[index+1]
  22. if startEdbInfoData == nil {
  23. startEdbInfoData = beforeIndexData
  24. continue
  25. }
  26. // 获取两条数据之间相差的天数
  27. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  28. currDataTime, _ := time.ParseInLocation(utils.FormatDate, afterIndexData.DataTime, time.Local)
  29. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  30. betweenDay := betweenHour / 24
  31. // 如果相差一天,那么过滤
  32. if betweenDay <= 1 {
  33. startEdbInfoData = afterIndexData
  34. continue
  35. }
  36. // 生成线性方程式
  37. var a, b float64
  38. {
  39. coordinateData := make([]utils.Coordinate, 0)
  40. tmpCoordinate1 := utils.Coordinate{
  41. X: 1,
  42. Y: startEdbInfoData.Value,
  43. }
  44. coordinateData = append(coordinateData, tmpCoordinate1)
  45. tmpCoordinate2 := utils.Coordinate{
  46. X: float64(betweenDay) + 1,
  47. Y: afterIndexData.Value,
  48. }
  49. coordinateData = append(coordinateData, tmpCoordinate2)
  50. a, b = utils.GetLinearResult(coordinateData)
  51. if math.IsNaN(a) || math.IsNaN(b) {
  52. err = errors.New("线性方程公式生成失败")
  53. return
  54. }
  55. }
  56. // 插值补充数据
  57. for i := 1; i < betweenDay; i++ {
  58. tmpDataTime := startDataTime.AddDate(0, 0, i)
  59. aDecimal := decimal.NewFromFloat(a)
  60. xDecimal := decimal.NewFromInt(int64(i) + 1)
  61. bDecimal := decimal.NewFromFloat(b)
  62. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  63. nextDay := tmpDataTime.Format(utils.FormatDate)
  64. replenishIndexData := data_manage.EdbDataList{
  65. EdbDataId: afterIndexData.EdbDataId,
  66. DataTime: nextDay,
  67. DataTimestamp: tmpDataTime.UnixMilli(),
  68. Value: val,
  69. }
  70. // 将补充数据加入补充数据列表
  71. dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
  72. }
  73. startEdbInfoData = afterIndexData
  74. }
  75. // 根据基准指标筛选出符合数据
  76. var resultDataList []*data_manage.EdbDataList
  77. for _, dataObject := range dataList {
  78. if _, ok := standardIndexMap[dataObject.DataTime]; ok {
  79. // 存在才保留
  80. resultDataList = append(resultDataList, dataObject)
  81. }
  82. }
  83. // 排序
  84. sort.Slice(resultDataList, func(i, j int) bool {
  85. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  86. })
  87. v.DataList = resultDataList
  88. }
  89. }
  90. }
  91. return nil
  92. }
  93. type FillWithPreviousStrategy struct{}
  94. func (f *FillWithPreviousStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) (err error) {
  95. // 按自然日补充,再根据基准指标取对应数据
  96. for _, v := range edbDataList {
  97. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  98. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  99. for index := 0; index < len(dataList)-1; index++ {
  100. // 获取当前数据和下一个数据
  101. beforeIndexData := dataList[index]
  102. afterIndexData := dataList[index+1]
  103. for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
  104. // 创建补充数据
  105. nextDay := utils.GetNextDay(beforeIndexData.DataTime)
  106. toTime := utils.StringToTime(nextDay)
  107. replenishIndexData := data_manage.EdbDataList{
  108. EdbInfoId: v.EdbInfoId,
  109. DataTime: nextDay,
  110. DataTimestamp: toTime.UnixMilli(),
  111. Value: beforeIndexData.Value,
  112. }
  113. // 将补充数据加入补充数据列表
  114. dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
  115. // 更新 beforeIndexData 为新创建的补充数据
  116. beforeIndexData = &replenishIndexData
  117. }
  118. }
  119. // 根据基准指标筛选出符合数据
  120. var resultDataList []*data_manage.EdbDataList
  121. for _, dataObject := range dataList {
  122. _, ok = standardIndexMap[dataObject.DataTime]
  123. if ok {
  124. // 存在才保留
  125. resultDataList = append(resultDataList, dataObject)
  126. }
  127. }
  128. // 排序
  129. sort.Slice(resultDataList, func(i, j int) bool {
  130. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  131. })
  132. v.DataList = resultDataList
  133. }
  134. }
  135. }
  136. return nil
  137. }
  138. type FillWithNextStrategy struct{}
  139. func (f *FillWithNextStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) (err error) {
  140. // 按自然日补充,再根据基准指标取对应数据
  141. for _, v := range edbDataList {
  142. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  143. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  144. // 将切片数据倒序
  145. reverseSlice(dataList)
  146. for index := 0; index < len(dataList)-1; index++ {
  147. // 获取当前数据和下一个数据
  148. beforeIndexData := dataList[index]
  149. afterIndexData := dataList[index+1]
  150. for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
  151. // 创建补充数据
  152. nextDay := utils.GetNextDay(beforeIndexData.DataTime)
  153. toTime := utils.StringToTime(nextDay)
  154. replenishIndexData := data_manage.EdbDataList{
  155. EdbInfoId: v.EdbInfoId,
  156. DataTime: nextDay,
  157. DataTimestamp: toTime.UnixMilli(),
  158. Value: beforeIndexData.Value,
  159. }
  160. // 将补充数据加入补充数据列表
  161. dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
  162. // 更新 beforeIndexData 为新创建的补充数据
  163. beforeIndexData = &replenishIndexData
  164. }
  165. }
  166. // 根据基准指标筛选出符合数据
  167. var resultDataList []*data_manage.EdbDataList
  168. for _, dataObject := range dataList {
  169. _, ok = standardIndexMap[dataObject.DataTime]
  170. if ok {
  171. // 存在才保留
  172. resultDataList = append(resultDataList, dataObject)
  173. }
  174. }
  175. // 排序
  176. sort.Slice(resultDataList, func(i, j int) bool {
  177. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  178. })
  179. v.DataList = resultDataList
  180. }
  181. }
  182. }
  183. return nil
  184. }
  185. type SetToZeroStrategy struct{}
  186. func (s *SetToZeroStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) (err error) {
  187. // 按自然日补充,再根据基准指标取对应数据
  188. for _, v := range edbDataList {
  189. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  190. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  191. for index := 0; index < len(dataList)-1; index++ {
  192. // 获取当前数据和下一个数据
  193. beforeIndexData := dataList[index]
  194. afterIndexData := dataList[index+1]
  195. for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
  196. // 创建补充数据
  197. nextDay := utils.GetNextDay(beforeIndexData.DataTime)
  198. toTime := utils.StringToTime(nextDay)
  199. replenishIndexData := data_manage.EdbDataList{
  200. EdbInfoId: v.EdbInfoId,
  201. DataTime: nextDay,
  202. DataTimestamp: toTime.UnixMilli(),
  203. Value: 0,
  204. }
  205. // 将补充数据加入补充数据列表
  206. dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
  207. // 更新 beforeIndexData 为新创建的补充数据
  208. beforeIndexData = &replenishIndexData
  209. }
  210. }
  211. // 根据基准指标筛选出符合数据
  212. var resultDataList []*data_manage.EdbDataList
  213. for _, dataObject := range dataList {
  214. _, ok = standardIndexMap[dataObject.DataTime]
  215. if ok {
  216. // 存在才保留
  217. resultDataList = append(resultDataList, dataObject)
  218. }
  219. }
  220. // 排序
  221. sort.Slice(resultDataList, func(i, j int) bool {
  222. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  223. })
  224. v.DataList = resultDataList
  225. }
  226. }
  227. }
  228. return nil
  229. }
  230. type DeleteDateStrategy struct{}
  231. func (d *DeleteDateStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) error {
  232. // 取所有指标的时间交集
  233. for _, v := range edbDataList {
  234. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  235. // 创建一个 map 来保存每个时间点的出现次数
  236. timeMap := make(map[string]int)
  237. // 遍历所有的 dataList,为每个 DataTime 增加一个计数
  238. for _, dataObject := range dataList {
  239. timeMap[dataObject.DataTime]++
  240. }
  241. // 遍历所有的 dataList,保留所有时间点在所有指标中都存在的数据
  242. var resultDataList []*data_manage.EdbDataList
  243. for _, dataObject := range dataList {
  244. if timeMap[dataObject.DataTime] == len(edbDataList) {
  245. // 如果该时间点在所有指标中都存在,加入到结果列表
  246. resultDataList = append(resultDataList, dataObject)
  247. }
  248. }
  249. // 将符合条件的数据重新赋值回 v.DataList
  250. v.DataList = resultDataList
  251. }
  252. }
  253. return nil
  254. }
  255. // 将列表颠倒
  256. func reverseSlice(dataList []*data_manage.EdbDataList) {
  257. // 使用双指针法,前后两个指针向中间逼近
  258. for i, j := 0, len(dataList)-1; i < j; i, j = i+1, j-1 {
  259. // 交换位置
  260. dataList[i], dataList[j] = dataList[j], dataList[i]
  261. }
  262. }