|
@@ -45,6 +45,8 @@ type CoordinatePoint struct {
|
|
|
YEdbInfoId int
|
|
|
XDate string
|
|
|
YDate string
|
|
|
+ DateType int `description:"日期类型:1-最新日期;2-N天前;3-固定日期"`
|
|
|
+ DaysAgo int `description:"N天前的N值"`
|
|
|
}
|
|
|
|
|
|
// GetChartData
|
|
@@ -140,7 +142,12 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*mo
|
|
|
|
|
|
dataMap := make(map[string]float64)
|
|
|
dateMap := make(map[string]string)
|
|
|
+ dateTypeMap := make(map[int]int) // 日期配置key对应的日期类型
|
|
|
+ daysAgoMap := make(map[int]int) // 日期配置key对应的N天前的N值
|
|
|
+
|
|
|
for dateIndex, dateConfig := range config.DateConfigList {
|
|
|
+ dateTypeMap[dateIndex] = dateConfig.DateType
|
|
|
+ daysAgoMap[dateIndex] = dateConfig.Num
|
|
|
for _, edbInfoMapping := range mappingList {
|
|
|
// 数据会是正序的
|
|
|
dataList, ok := edbDataListMap[edbInfoMapping.EdbInfoId]
|
|
@@ -162,19 +169,18 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*mo
|
|
|
err = tmpErr
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
// 数据开始日期
|
|
|
endDateStr := ``
|
|
|
var endDate time.Time
|
|
|
- var currVal float64
|
|
|
|
|
|
+ var currVal float64
|
|
|
switch dateConfig.DateType {
|
|
|
case 1: // 1:最新日期;
|
|
|
endDateStr = dataEndDateStr
|
|
|
endDate = dataEndDate
|
|
|
currVal = dataList[k].Value
|
|
|
- case 2: // 2:N天前
|
|
|
- tmpEndDate := currDay.AddDate(0, 0, -dateConfig.Num)
|
|
|
+ case 2: // 2:N天前(原为指标最新日期的N天前, 现为系统日期的N天)
|
|
|
+ tmpEndDate := time.Now().AddDate(0, 0, -dateConfig.Num)
|
|
|
tmpEndDateStr := tmpEndDate.Format(utils.FormatDate)
|
|
|
|
|
|
for i := k; i >= 0; i-- {
|
|
@@ -202,6 +208,45 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*mo
|
|
|
currVal = dataList[i].Value
|
|
|
break
|
|
|
}
|
|
|
+ case 3: // 固定日期
|
|
|
+ if dateConfig.FixDate == "" {
|
|
|
+ errMsg = "固定日期不可为空"
|
|
|
+ err = fmt.Errorf("固定日期为空")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ strFixDate := dateConfig.FixDate
|
|
|
+ fixDate, e := time.ParseInLocation(utils.FormatDate, strFixDate, time.Local)
|
|
|
+ if e != nil {
|
|
|
+ errMsg = "固定日期格式有误"
|
|
|
+ err = fmt.Errorf("固定日期有误, FixDate: %s", dateConfig.FixDate)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for i := k; i >= 0; i-- {
|
|
|
+ strThisDate := dataList[i].DataTime
|
|
|
+ // 如果正好是这一天,那么就直接break了
|
|
|
+ if strFixDate == strThisDate {
|
|
|
+ k = i
|
|
|
+ endDateStr = strThisDate
|
|
|
+ endDate = fixDate
|
|
|
+ currVal = dataList[i].Value
|
|
|
+ break
|
|
|
+ }
|
|
|
+ // 若固定日期无值, 则取固定日期之前, 能找到的第一个值(同上N天前的逻辑)
|
|
|
+ thisDate, e := time.ParseInLocation(utils.FormatDate, strThisDate, time.Local)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("数据日期格式有误: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if thisDate.After(fixDate) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ k = i
|
|
|
+ endDateStr = strThisDate
|
|
|
+ endDate = thisDate
|
|
|
+ currVal = dataList[i].Value
|
|
|
+ break
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 没有找到日期,那么就不处理
|
|
@@ -213,51 +258,85 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*mo
|
|
|
earliestDate := endDate.AddDate(0, 0, -config.CalculateValue*moveUnitDays)
|
|
|
earliestDateStr := earliestDate.Format(utils.FormatDate)
|
|
|
|
|
|
- var minVal, maxVal float64
|
|
|
- var isNotFirst bool // 是否是第一条数据
|
|
|
- for i := k; i >= 0; i-- {
|
|
|
- tmpData := dataList[i]
|
|
|
- if !isNotFirst {
|
|
|
- maxVal = tmpData.Value
|
|
|
- minVal = tmpData.Value
|
|
|
- isNotFirst = true
|
|
|
- continue
|
|
|
- }
|
|
|
+ var percentVal float64 // 百分位计算值
|
|
|
+ // 百分位数据区间算法
|
|
|
+ if config.PercentType == utils.PercentCalculateTypeRange {
|
|
|
+ var minVal, maxVal float64
|
|
|
+ var isNotFirst bool // 是否是第一条数据
|
|
|
+ for i := k; i >= 0; i-- {
|
|
|
+ tmpData := dataList[i]
|
|
|
+ if !isNotFirst {
|
|
|
+ maxVal = tmpData.Value
|
|
|
+ minVal = tmpData.Value
|
|
|
+ isNotFirst = true
|
|
|
+ continue
|
|
|
+ }
|
|
|
|
|
|
- tmpDateStr := dataList[i].DataTime
|
|
|
- // 如果正好是这一天,那么就直接break了
|
|
|
- if earliestDateStr == tmpDateStr {
|
|
|
- break
|
|
|
- }
|
|
|
- tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
|
|
|
- if tmpErr != nil {
|
|
|
- err = tmpErr
|
|
|
- return
|
|
|
+ tmpDateStr := dataList[i].DataTime
|
|
|
+ // 如果正好是这一天,那么就直接break了
|
|
|
+ if earliestDateStr == tmpDateStr {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 如果这期的日期早于选择的日期,那么继续停止遍历
|
|
|
+ if tmpDate.Before(earliestDate) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if tmpData.Value > maxVal {
|
|
|
+ maxVal = tmpData.Value
|
|
|
+ }
|
|
|
+ if tmpData.Value < minVal {
|
|
|
+ minVal = tmpData.Value
|
|
|
+ }
|
|
|
}
|
|
|
- // 如果这期的日期早于选择的日期,那么继续停止遍历
|
|
|
- if tmpDate.Before(earliestDate) {
|
|
|
+
|
|
|
+ // 最大值等于最小值,说明计算结果无效
|
|
|
+ if maxVal == minVal {
|
|
|
continue
|
|
|
}
|
|
|
+ // 数据区间百分位=(现值-Min)/(Max-Min)
|
|
|
+ tmpV := (currVal - minVal) / (maxVal - minVal) * 100
|
|
|
+ percentVal, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
|
|
|
+ }
|
|
|
|
|
|
- if tmpData.Value > maxVal {
|
|
|
- maxVal = tmpData.Value
|
|
|
+ // 百分位数据个数算法
|
|
|
+ // 数据区间第一个和最后一个数据点的时间和数据分别为(T1,S1)(T2,S2); N=T1到T2指标数据个数, n=小于等于S2的数据个数
|
|
|
+ // 个数百分位=(n-1)/(N-1)
|
|
|
+ if config.PercentType == utils.PercentCalculateTypeNum {
|
|
|
+ // T1为earliestDate, T2为endDate, S2为currVal
|
|
|
+ var tinyN, bigN int
|
|
|
+ lastVal := decimal.NewFromFloat(currVal)
|
|
|
+ for i := k; i >= 0; i-- {
|
|
|
+ date, e := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("数据日期格式有误: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if !date.Before(earliestDate) && !date.After(endDate) {
|
|
|
+ bigN += 1
|
|
|
+ }
|
|
|
+ dateVal := decimal.NewFromFloat(dataList[i].Value)
|
|
|
+ if dateVal.LessThanOrEqual(lastVal) {
|
|
|
+ tinyN += 1
|
|
|
+ }
|
|
|
}
|
|
|
- if tmpData.Value < minVal {
|
|
|
- minVal = tmpData.Value
|
|
|
+ // N=1时说明计算无效
|
|
|
+ if bigN == 1 {
|
|
|
+ continue
|
|
|
}
|
|
|
+ numerator := decimal.NewFromInt(int64(tinyN - 1))
|
|
|
+ denominator := decimal.NewFromInt(int64(bigN - 1))
|
|
|
+ percentVal, _ = numerator.Div(denominator).Round(4).Float64()
|
|
|
}
|
|
|
|
|
|
- // 最大值等于最小值,说明计算结果无效
|
|
|
- if maxVal == minVal {
|
|
|
- continue
|
|
|
- }
|
|
|
- //百分位=(现值-Min)/(Max-Min)
|
|
|
- tmpV := (currVal - minVal) / (maxVal - minVal) * 100
|
|
|
- tmpV, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
|
|
|
-
|
|
|
// key的生成(日期配置下标+指标id)
|
|
|
key := fmt.Sprint(dateIndex, "_", edbInfoMapping.EdbInfoId)
|
|
|
- dataMap[key] = tmpV
|
|
|
+ dataMap[key] = percentVal
|
|
|
dateMap[key] = endDateStr
|
|
|
}
|
|
|
}
|
|
@@ -283,7 +362,7 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*mo
|
|
|
|
|
|
coordinatePointList := make([]CoordinatePoint, 0)
|
|
|
|
|
|
- for dateIndex := range config.DateConfigList {
|
|
|
+ for dateIndex, _ := range config.DateConfigList {
|
|
|
key1 := fmt.Sprint(dateIndex, "_", xEdbInfoId)
|
|
|
xVal, ok1 := dataMap[key1]
|
|
|
if !ok1 {
|
|
@@ -321,6 +400,8 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*mo
|
|
|
YEdbInfoId: yEdbInfoId,
|
|
|
XDate: dateMap[key1],
|
|
|
YDate: dateMap[key2],
|
|
|
+ DateType: dateTypeMap[dateIndex], // 日期类型
|
|
|
+ DaysAgo: daysAgoMap[dateIndex], // N天前的N值
|
|
|
})
|
|
|
}
|
|
|
|
|
@@ -356,7 +437,7 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*mo
|
|
|
}
|
|
|
|
|
|
// 去除返回指标中的数据信息,避免没必要的数据传输
|
|
|
- for k := range edbList {
|
|
|
+ for k, _ := range edbList {
|
|
|
edbList[k].DataList = nil
|
|
|
}
|
|
|
|