|
@@ -11,12 +11,15 @@ import (
|
|
|
"eta/eta_api/services"
|
|
|
"eta/eta_api/services/alarm_msg"
|
|
|
"eta/eta_api/services/data"
|
|
|
+ "eta/eta_api/services/data/area_graph"
|
|
|
"eta/eta_api/services/data/data_manage_permission"
|
|
|
"eta/eta_api/services/data/excel"
|
|
|
"eta/eta_api/services/eta_forum"
|
|
|
etaTrialService "eta/eta_api/services/eta_trial"
|
|
|
"eta/eta_api/utils"
|
|
|
"fmt"
|
|
|
+ "github.com/shopspring/decimal"
|
|
|
+ "math"
|
|
|
"os"
|
|
|
"os/exec"
|
|
|
"sort"
|
|
@@ -1514,13 +1517,10 @@ func fillAreaGraphData(extraConfigStr string, edbDataList []*data_manage.ChartEd
|
|
|
}
|
|
|
if tmpConfig.IsHeap == 1 {
|
|
|
standardIndexMap := make(map[string]*data_manage.EdbDataList)
|
|
|
- var standardIndexStartDate, standardIndexEndDate string
|
|
|
for _, v := range edbDataList {
|
|
|
// 判断是否为基准指标
|
|
|
if v.EdbInfoId == tmpConfig.StandardEdbInfoId {
|
|
|
if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
|
|
|
- standardIndexStartDate = dataList[0].DataTime
|
|
|
- standardIndexEndDate = dataList[len(dataList)-1].DataTime
|
|
|
for _, dataObject := range dataList {
|
|
|
standardIndexMap[dataObject.DataTime] = dataObject
|
|
|
}
|
|
@@ -1528,41 +1528,328 @@ func fillAreaGraphData(extraConfigStr string, edbDataList []*data_manage.ChartEd
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
- switch tmpConfig.NullDealWay {
|
|
|
+ strategy, err := area_graph.CreateStrategy(tmpConfig.NullDealWay)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err, "创建空值处理器失败"
|
|
|
+ }
|
|
|
+ err = strategy.Deal(tmpConfig, edbDataList, standardIndexMap)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err, err.Error()
|
|
|
+ }
|
|
|
+
|
|
|
+ /*switch tmpConfig.NullDealWay {
|
|
|
case 1:
|
|
|
// 插值填充
|
|
|
- //interpolate()
|
|
|
-
|
|
|
+ err := interpolate(tmpConfig, edbDataList, standardIndexMap)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err, "插值填充失败"
|
|
|
+ }
|
|
|
case 2:
|
|
|
// 前值填充
|
|
|
- //fillWithPrevious()
|
|
|
- // 按自然日补充,再根据基准指标取对应数据
|
|
|
- for _, v := range edbDataList {
|
|
|
- if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
- if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
|
|
|
- for i := 0; i < len(dataList); i++ {
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ fillWithPrevious(tmpConfig, edbDataList, standardIndexMap)
|
|
|
case 3:
|
|
|
// 后值填充
|
|
|
- fillWithNext()
|
|
|
+ fillWithNext(tmpConfig, edbDataList, standardIndexMap)
|
|
|
case 4:
|
|
|
// 等于0
|
|
|
- setToZero()
|
|
|
+ setToZero(tmpConfig, edbDataList, standardIndexMap)
|
|
|
case 5:
|
|
|
// 删除日期
|
|
|
- deleteDate()
|
|
|
+ deleteDate(edbDataList)
|
|
|
default:
|
|
|
fmt.Println("Unknown NullDealWay:", tmpConfig.NullDealWay)
|
|
|
+ }*/
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil, nil, ""
|
|
|
+}
|
|
|
+
|
|
|
+// 空值填充:插值填充
|
|
|
+func interpolate(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) (err error) {
|
|
|
+ for _, v := range edbDataList {
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
+ if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
|
|
|
+ // 插值法补充数据
|
|
|
+ var startEdbInfoData *data_manage.EdbDataList
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
+
|
|
|
+ if startEdbInfoData == nil {
|
|
|
+ startEdbInfoData = beforeIndexData
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取两条数据之间相差的天数
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
|
|
|
+ currDataTime, _ := time.ParseInLocation(utils.FormatDate, afterIndexData.DataTime, time.Local)
|
|
|
+ betweenHour := int(currDataTime.Sub(startDataTime).Hours())
|
|
|
+ betweenDay := betweenHour / 24
|
|
|
+
|
|
|
+ // 如果相差一天,那么过滤
|
|
|
+ if betweenDay <= 1 {
|
|
|
+ startEdbInfoData = afterIndexData
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成线性方程式
|
|
|
+ var a, b float64
|
|
|
+ {
|
|
|
+ coordinateData := make([]utils.Coordinate, 0)
|
|
|
+ tmpCoordinate1 := utils.Coordinate{
|
|
|
+ X: 1,
|
|
|
+ Y: startEdbInfoData.Value,
|
|
|
+ }
|
|
|
+ coordinateData = append(coordinateData, tmpCoordinate1)
|
|
|
+ tmpCoordinate2 := utils.Coordinate{
|
|
|
+ X: float64(betweenDay) + 1,
|
|
|
+ Y: afterIndexData.Value,
|
|
|
+ }
|
|
|
+ coordinateData = append(coordinateData, tmpCoordinate2)
|
|
|
+
|
|
|
+ a, b = utils.GetLinearResult(coordinateData)
|
|
|
+ if math.IsNaN(a) || math.IsNaN(b) {
|
|
|
+ err = errors.New("线性方程公式生成失败")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插值补充数据
|
|
|
+ for i := 1; i < betweenDay; i++ {
|
|
|
+ tmpDataTime := startDataTime.AddDate(0, 0, i)
|
|
|
+ aDecimal := decimal.NewFromFloat(a)
|
|
|
+ xDecimal := decimal.NewFromInt(int64(i) + 1)
|
|
|
+ bDecimal := decimal.NewFromFloat(b)
|
|
|
+
|
|
|
+ val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
|
|
|
+ nextDay := tmpDataTime.Format(utils.FormatDate)
|
|
|
+
|
|
|
+ replenishIndexData := data_manage.EdbDataList{
|
|
|
+ EdbDataId: afterIndexData.EdbDataId,
|
|
|
+ DataTime: nextDay,
|
|
|
+ DataTimestamp: tmpDataTime.UnixMilli(),
|
|
|
+ Value: val,
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
+ dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
|
|
|
+ }
|
|
|
+ startEdbInfoData = afterIndexData
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
+ var resultDataList []*data_manage.EdbDataList
|
|
|
+ for _, dataObject := range dataList {
|
|
|
+ if _, ok := standardIndexMap[dataObject.DataTime]; ok {
|
|
|
+ // 存在才保留
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
+ })
|
|
|
+
|
|
|
+ v.DataList = resultDataList
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
|
|
|
+// 空值填充:删除日期
|
|
|
+func deleteDate(edbDataList []*data_manage.ChartEdbInfoMapping) {
|
|
|
+ // 取所有指标的时间交集
|
|
|
+ for _, v := range edbDataList {
|
|
|
+ if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
|
|
|
+ // 创建一个 map 来保存每个时间点的出现次数
|
|
|
+ timeMap := make(map[string]int)
|
|
|
+
|
|
|
+ // 遍历所有的 dataList,为每个 DataTime 增加一个计数
|
|
|
+ for _, dataObject := range dataList {
|
|
|
+ timeMap[dataObject.DataTime]++
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历所有的 dataList,保留所有时间点在所有指标中都存在的数据
|
|
|
+ var resultDataList []*data_manage.EdbDataList
|
|
|
+ for _, dataObject := range dataList {
|
|
|
+ if timeMap[dataObject.DataTime] == len(edbDataList) {
|
|
|
+ // 如果该时间点在所有指标中都存在,加入到结果列表
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将符合条件的数据重新赋值回 v.DataList
|
|
|
+ v.DataList = resultDataList
|
|
|
+ }
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- return nil, nil, ""
|
|
|
+// 空值填充:等于0
|
|
|
+func setToZero(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) {
|
|
|
+ // 按自然日补充,再根据基准指标取对应数据
|
|
|
+ for _, v := range edbDataList {
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
+ if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
+
|
|
|
+ for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
|
|
|
+ // 创建补充数据
|
|
|
+ nextDay := utils.GetNextDay(beforeIndexData.DataTime)
|
|
|
+ toTime := utils.StringToTime(nextDay)
|
|
|
+ replenishIndexData := data_manage.EdbDataList{
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ DataTime: nextDay,
|
|
|
+ DataTimestamp: toTime.UnixMilli(),
|
|
|
+ Value: 0,
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
+ dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
|
|
|
+
|
|
|
+ // 更新 beforeIndexData 为新创建的补充数据
|
|
|
+ beforeIndexData = &replenishIndexData
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
+ var resultDataList []*data_manage.EdbDataList
|
|
|
+ for _, dataObject := range dataList {
|
|
|
+ _, ok = standardIndexMap[dataObject.DataTime]
|
|
|
+ if ok {
|
|
|
+ // 存在才保留
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
+ })
|
|
|
+
|
|
|
+ v.DataList = resultDataList
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 空值填充:后值填充
|
|
|
+func fillWithNext(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) {
|
|
|
+ // 按自然日补充,再根据基准指标取对应数据
|
|
|
+ for _, v := range edbDataList {
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
+ if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
|
|
|
+ // 将切片数据倒序
|
|
|
+ reverseSlice(dataList)
|
|
|
+
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
+
|
|
|
+ for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
|
|
|
+ // 创建补充数据
|
|
|
+ nextDay := utils.GetNextDay(beforeIndexData.DataTime)
|
|
|
+ toTime := utils.StringToTime(nextDay)
|
|
|
+ replenishIndexData := data_manage.EdbDataList{
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ DataTime: nextDay,
|
|
|
+ DataTimestamp: toTime.UnixMilli(),
|
|
|
+ Value: beforeIndexData.Value,
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
+ dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
|
|
|
+
|
|
|
+ // 更新 beforeIndexData 为新创建的补充数据
|
|
|
+ beforeIndexData = &replenishIndexData
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
+ var resultDataList []*data_manage.EdbDataList
|
|
|
+ for _, dataObject := range dataList {
|
|
|
+ _, ok = standardIndexMap[dataObject.DataTime]
|
|
|
+ if ok {
|
|
|
+ // 存在才保留
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
+ })
|
|
|
+
|
|
|
+ v.DataList = resultDataList
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 将列表颠倒
|
|
|
+func reverseSlice(dataList []*data_manage.EdbDataList) {
|
|
|
+ // 使用双指针法,前后两个指针向中间逼近
|
|
|
+ for i, j := 0, len(dataList)-1; i < j; i, j = i+1, j-1 {
|
|
|
+ // 交换位置
|
|
|
+ dataList[i], dataList[j] = dataList[j], dataList[i]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 空值填充:前值填充
|
|
|
+func fillWithPrevious(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList) {
|
|
|
+ // 按自然日补充,再根据基准指标取对应数据
|
|
|
+ for _, v := range edbDataList {
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
+ if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
+
|
|
|
+ for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
|
|
|
+ // 创建补充数据
|
|
|
+ nextDay := utils.GetNextDay(beforeIndexData.DataTime)
|
|
|
+ toTime := utils.StringToTime(nextDay)
|
|
|
+ replenishIndexData := data_manage.EdbDataList{
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ DataTime: nextDay,
|
|
|
+ DataTimestamp: toTime.UnixMilli(),
|
|
|
+ Value: beforeIndexData.Value,
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
+ dataList = append(dataList[:index+1], append([]*data_manage.EdbDataList{&replenishIndexData}, dataList[index+1:]...)...)
|
|
|
+
|
|
|
+ // 更新 beforeIndexData 为新创建的补充数据
|
|
|
+ beforeIndexData = &replenishIndexData
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
+ var resultDataList []*data_manage.EdbDataList
|
|
|
+ for _, dataObject := range dataList {
|
|
|
+ _, ok = standardIndexMap[dataObject.DataTime]
|
|
|
+ if ok {
|
|
|
+ // 存在才保留
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
+ })
|
|
|
+
|
|
|
+ v.DataList = resultDataList
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// ChartInfoDetailV2
|