Browse Source

feat:新增三类图

Roc 1 year ago
parent
commit
18f5ac022a

+ 86 - 0
controllers/chart_common.go

@@ -9,11 +9,14 @@ import (
 	"hongze/hongze_chart_lib/models/data_manage/future_good/request"
 	"hongze/hongze_chart_lib/models/data_manage/future_good/response"
 	line_equationReq "hongze/hongze_chart_lib/models/data_manage/line_equation/request"
+	line_featureReq "hongze/hongze_chart_lib/models/data_manage/line_feature/request"
 	"hongze/hongze_chart_lib/services/data"
 	correlationServ "hongze/hongze_chart_lib/services/data/correlation"
 	future_goodServ "hongze/hongze_chart_lib/services/data/future_good"
 	"hongze/hongze_chart_lib/services/data/line_equation"
+	lineFeatureServ "hongze/hongze_chart_lib/services/data/line_feature"
 	"hongze/hongze_chart_lib/utils"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -83,6 +86,8 @@ func (this *ChartController) CommonChartInfoDetailFromUniqueCode() {
 		resp, isOk, msg, errMsg = GetCorrelationChartInfoDetailFromUniqueCode(chartInfo, key)
 	case utils.CHART_SOURCE_LINE_EQUATION:
 		resp, isOk, msg, errMsg = GetLineEquationChartInfoDetailFromUniqueCode(chartInfo, key)
+	case utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY:
+		resp, isOk, msg, errMsg = GetLineFeatureChartInfoDetailFromUniqueCode(chartInfo, key)
 	default:
 		br.Msg = "错误的图表"
 		br.ErrMsg = "错误的图表"
@@ -363,6 +368,87 @@ func GetLineEquationChartInfoDetailFromUniqueCode(chartInfo *models.ChartInfo, k
 	return
 }
 
+// GetLineFeatureChartInfoDetailFromUniqueCode 根据编码获取统计特征图表详情
+func GetLineFeatureChartInfoDetailFromUniqueCode(chartInfo *models.ChartInfo, key string) (resp *models.ChartInfoDetailResp, isOk bool, msg, errMsg string) {
+	resp = new(models.ChartInfoDetailResp)
+	// 获取图表关联指标
+	edbMappingList, err := models.GetChartEdbMappingList(chartInfo.ChartInfoId)
+	if err != nil {
+		msg = "获取失败"
+		errMsg = "获取图表关联指标信息失败,Err:" + err.Error()
+		return
+	}
+	if len(edbMappingList) != 1 {
+		msg = "获取失败"
+		errMsg = fmt.Sprint("获取图表关联指标信息异常,数量:", len(edbMappingList))
+		return
+	}
+	edbMapping := edbMappingList[0]
+
+	var edbList []*models.ChartEdbInfoMapping
+	var resultResp interface{}
+
+	switch chartInfo.Source {
+	case utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION:
+		calculateValue, tmpErr := strconv.Atoi(chartInfo.ExtraConfig)
+		if tmpErr != nil {
+			msg = "获取失败"
+			errMsg = "格式化配置项失败,Err:" + tmpErr.Error()
+			return
+		}
+		edbList, err, msg = lineFeatureServ.GetStandardDeviationData(0, edbMapping, calculateValue)
+	case utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE:
+		var percentileConfig line_featureReq.Percentile
+		err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &percentileConfig)
+		if err != nil {
+			msg = "获取失败"
+			errMsg = "格式化配置项失败,Err:" + err.Error()
+			return
+		}
+		edbList, err, msg = lineFeatureServ.GetPercentileData(0, edbMapping, percentileConfig.CalculateValue, percentileConfig.CalculateUnit)
+	case utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY:
+		var frequencyDistributionConfig line_featureReq.FrequencyDistribution
+		err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &frequencyDistributionConfig)
+		if err != nil {
+			msg = "获取失败"
+			errMsg = "格式化配置项失败,Err:" + err.Error()
+			return
+		}
+		// 获取图表中的指标数据
+		edbList, resultResp, err, errMsg = lineFeatureServ.GetFrequencyDistributionData(0, edbMapping, frequencyDistributionConfig.DateType, frequencyDistributionConfig.FrequencyValue, frequencyDistributionConfig.StartDate, frequencyDistributionConfig.EndDate)
+	default:
+		msg = `错误的图表`
+		errMsg = fmt.Sprint("错误的图表来源,source", chartInfo.Source)
+		return
+	}
+	if err != nil {
+		if msg == `` {
+			msg = "获取失败"
+		}
+		errMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	//chartInfo.UnitEn = baseEdbInfo.UnitEn
+	// 图表的指标来源
+	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
+	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+
+	resp.ChartInfo = chartInfo
+	resp.DataResp = resultResp
+	resp.EdbInfoList = edbList
+
+	// 将数据加入缓存
+	if utils.Re == nil {
+		data, _ := json.Marshal(resp)
+		utils.Rc.Put(key, data, 2*time.Hour)
+	}
+	isOk = true
+
+	return
+}
+
 // FutureGoodChartInfoRefresh
 // @Title 商品价格图表刷新接口
 // @Description 商品价格图表刷新接口

+ 8 - 0
models/data_manage/edb_data_base.go

@@ -135,6 +135,14 @@ func GetEdbDataTableName(source int) (tableName string) {
 		tableName = "edb_data_predict_calculate_ljz"
 	case utils.DATA_SOURCE_PREDICT_CALCULATE_LJZNCZJ: //预测指标 - 累计值(年初至今) -> 66
 		tableName = "edb_data_predict_calculate_ljznczj"
+	case utils.DATA_SOURCE_CALCULATE_STANDARD_DEVIATION: //标准差->67
+		tableName = "edb_data_calculate_standard_deviation"
+	case utils.DATA_SOURCE_CALCULATE_PERCENTILE: //百分位->68
+		tableName = "edb_data_calculate_percentile"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_STANDARD_DEVIATION: //预测标准差->69
+		tableName = "edb_data_predict_ccalculate_standard_deviation"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_PERCENTILE: //预测百分位->70
+		tableName = "edb_data_predict_ccalculate_percentile"
 	default:
 		tableName = ""
 	}

+ 107 - 0
models/data_manage/line_feature/request/line_feature.go

@@ -0,0 +1,107 @@
+package request
+
+// SaveMultipleGraphConfigReq 多图配置请求
+type SaveMultipleGraphConfigReq struct {
+	MultipleGraphConfigId int                   `description:"配置id"`
+	EdbInfoId             int                   `description:"指标"`
+	Curve                 CurveConfig           `description:"曲线图配置"`
+	StandardDeviation     StandardDeviation     `description:"标准差配置"`
+	Percentile            Percentile            `description:"百分位配置"`
+	FrequencyDistribution FrequencyDistribution `description:"频率分布配置"`
+}
+
+// ConfigSave 数据库保存
+type ConfigSave struct {
+	Curve                 CurveConfig           `description:"曲线图配置"`
+	StandardDeviation     StandardDeviation     `description:"标准差配置"`
+	Percentile            Percentile            `description:"百分位配置"`
+	FrequencyDistribution FrequencyDistribution `description:"频率分布配置"`
+}
+
+// CurveConfig 曲线图配置
+type CurveConfig struct {
+	DateType  int     `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间"`
+	StartDate string  `description:"自定义开始日期"`
+	EndDate   string  `description:"自定义结束日期"`
+	LeftMin   float64 `description:"图表左侧最小值"`
+	LeftMax   float64 `description:"图表左侧最大值"`
+}
+
+type StandardDeviation struct {
+	CalculateValue int `description:"滚动期数"`
+}
+
+type Percentile struct {
+	CalculateValue int    `description:"时间长度期数"`
+	CalculateUnit  string `description:"时间长度频度"`
+}
+
+type FrequencyDistribution struct {
+	//最近3月 最近6月 最近1年 最近2年 最近3年 最近5年 最近10年
+	DateType       int    `description:"日期类型:1:最近3月;2:最近6月;3:最近1年;4:最近2年;5:最近3年;6:最近5年;7:最近10年,8:自定义时间"`
+	StartDate      string `description:"自定义开始日期"`
+	EndDate        string `description:"自定义结束日期"`
+	FrequencyValue int    `description:"频段数,10/20"`
+}
+
+// LineChartInfoReq 线性拟合图表预览请求数据
+type LineChartInfoReq struct {
+	DateType       int    `description:"日期类型"`
+	StartDate      string `description:"开始日期"`
+	EndDate        string `description:"结束日期"`
+	XEdbInfoIdList []int  `description:"X轴的指标id列表"`
+	YEdbInfoIdList []int  `description:"Y轴的指标id列表"`
+	Source         int    `description:"来源,1:曲线图,8:标准差图表;9:百分位图表;10:频率分布图表;"`
+}
+
+type AddChartInfoReq struct {
+	MultipleGraphConfigId int              `description:"统一配置id,有的话就是编辑,没有则是新增"`
+	BatchAddChart         []AddChart       `description:"批量创建图的信息"`
+	ExtraConfig           LineChartInfoReq `description:"图表额外配置信息"`
+}
+
+type AddChart struct {
+	Source          int    `description:"来源,1:曲线图,8:标准差图表;9:百分位图表;10:频率分布图表;"`
+	ChartClassifyId int    `description:"分类id"`
+	ChartName       string `description:"图表名称"`
+	LeftMin         string `description:"图表左侧最小值"`
+	LeftMax         string `description:"图表左侧最大值"`
+	ChartImage      string `description:"图表截图,复制的时候才用到" json:"-"`
+}
+
+// EditChartEnInfoReq 编辑图表英文信息
+type EditChartEnInfoReq struct {
+	ChartInfoId int    `description:"图表ID"`
+	ChartNameEn string `description:"英文图表名称"`
+}
+
+// SaveMultipleGraphChartReq 多图配置的单图保存请求
+type SaveMultipleGraphChartReq struct {
+	Source                int                   `description:"来源,1:曲线图,8:标准差图表;9:百分位图表;10:频率分布图表;"`
+	ChartName             string                `description:"图表名称"`
+	ClassifyId            int                   `description:"分类id"`
+	MultipleGraphConfigId int                   `description:"配置id"`
+	EdbInfoId             int                   `description:"指标"`
+	Curve                 CurveConfig           `description:"曲线图配置"`
+	StandardDeviation     StandardDeviation     `description:"标准差配置"`
+	Percentile            Percentile            `description:"百分位配置"`
+	FrequencyDistribution FrequencyDistribution `description:"频率分布配置"`
+	IsSaveAs              bool                  `description:"是否另存为,true的话,就是另存为,不会建立与配置的关系"`
+}
+
+// SaveMultipleGraphEdbReq 多图配置的单指标保存请求
+type SaveMultipleGraphEdbReq struct {
+	EdbName    string `description:"指标名称"`
+	Frequency  string `description:"频度"`
+	Unit       string `description:"单位"`
+	ClassifyId int    `description:"分类id"`
+
+	MultipleGraphConfigId int                   `description:"配置id"`
+	Source                int                   `description:"来源,1:曲线图,8:标准差图表;9:百分位图表;10:频率分布图表;"`
+	EdbInfoId             int                   `description:"指标"`
+	Curve                 CurveConfig           `description:"曲线图配置"`
+	StandardDeviation     StandardDeviation     `description:"标准差配置"`
+	Percentile            Percentile            `description:"百分位配置"`
+	FrequencyDistribution FrequencyDistribution `description:"频率分布配置"`
+	IsSaveAs              bool                  `description:"是否另存为,true的话,就是另存为,不会建立与配置的关系"`
+}

+ 27 - 0
models/data_manage/line_feature/response/line_feature.go

@@ -0,0 +1,27 @@
+package response
+
+// FrequencyDistributionResp 频率分布图数据
+type FrequencyDistributionResp struct {
+	LeftMinValue  float64
+	LeftMaxValue  float64
+	RightMinValue float64
+	RightMaxValue float64
+	DataList      []FrequencyDistributionData
+}
+
+// FrequencyDistributionData 频率分布的值
+type FrequencyDistributionData struct {
+	Name   string      `description:"别名"`
+	NameEn string      `description:"英文别名"`
+	Unit   string      `description:"单位"`
+	UnitEn string      `description:"单位别名"`
+	Value  interface{} `description:"每个指标的值"`
+	Color  string      `description:"数据颜色"`
+	IsAxis int         `description:"1:左轴,0:右轴"`
+}
+
+// FrequencyDistributionYData 频率分布的实际数据
+type FrequencyDistributionYData struct {
+	X float64
+	Y float64
+}

+ 8 - 0
models/edb_data_base.go

@@ -134,6 +134,14 @@ func GetEdbDataTableName(source int) (tableName string) {
 		tableName = "edb_data_predict_calculate_ljz"
 	case utils.DATA_SOURCE_PREDICT_CALCULATE_LJZNCZJ: //预测指标 - 累计值(年初至今) -> 66
 		tableName = "edb_data_predict_calculate_ljznczj"
+	case utils.DATA_SOURCE_CALCULATE_STANDARD_DEVIATION: //标准差->67
+		tableName = "edb_data_calculate_standard_deviation"
+	case utils.DATA_SOURCE_CALCULATE_PERCENTILE: //百分位->68
+		tableName = "edb_data_calculate_percentile"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_STANDARD_DEVIATION: //预测标准差->69
+		tableName = "edb_data_predict_ccalculate_standard_deviation"
+	case utils.DATA_SOURCE_PREDICT_CALCULATE_PERCENTILE: //预测百分位->70
+		tableName = "edb_data_predict_ccalculate_percentile"
 	default:
 		tableName = ""
 	}

+ 249 - 0
services/data/line_feature/chart_info.go

@@ -0,0 +1,249 @@
+package line_feature
+
+import (
+	"errors"
+	"github.com/shopspring/decimal"
+	"hongze/hongze_chart_lib/models"
+	"hongze/hongze_chart_lib/models/data_manage/line_feature/response"
+	"hongze/hongze_chart_lib/services/data"
+	"hongze/hongze_chart_lib/utils"
+	"time"
+)
+
+// GetStandardDeviationData 获取标准差图表的指标数据
+func GetStandardDeviationData(chartInfoId int, mappingInfo *models.ChartEdbInfoMapping, calculateValue int) (edbList []*models.ChartEdbInfoMapping, err error, errMsg string) {
+	edbList = make([]*models.ChartEdbInfoMapping, 0)
+
+	// 指标对应的所有数据
+	_, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, ``, ``, []*models.ChartEdbInfoMapping{mappingInfo})
+	if err != nil {
+		return
+	}
+
+	for k, edb := range edbList {
+		dataList := edb.DataList.([]*models.EdbDataList)
+		newDataList := make([]models.EdbDataList, 0)
+		lenData := len(dataList)
+		if lenData >= calculateValue {
+			tmpDataList := make([]float64, 0)
+			for _, tmpData := range dataList {
+				tmpDataList = append(tmpDataList, tmpData.Value)
+			}
+			for i := calculateValue; i <= lenData; i++ {
+				tmpV := utils.CalculateStandardDeviation(tmpDataList[i-calculateValue : i])
+				tmpV, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
+				newDataList = append(newDataList, models.EdbDataList{
+					EdbDataId:     i,
+					EdbInfoId:     edb.EdbInfoId,
+					DataTime:      dataList[i-1].DataTime,
+					DataTimestamp: dataList[i-1].DataTimestamp,
+					Value:         tmpV,
+				})
+			}
+		}
+
+		edb.DataList = newDataList
+		edbList[k] = edb
+	}
+
+	return
+}
+
+// GetPercentileData 获取百分位图表的指标数据
+func GetPercentileData(chartInfoId int, mappingInfo *models.ChartEdbInfoMapping, calculateValue int, calculateUnit string) (edbList []*models.ChartEdbInfoMapping, err error, errMsg string) {
+	edbList = make([]*models.ChartEdbInfoMapping, 0)
+	moveUnitDays, ok := utils.FrequencyDaysMap[calculateUnit]
+	if !ok {
+		errMsg = `错误的周期`
+		err = errors.New(errMsg)
+		return
+	}
+	calculateDay := calculateValue * moveUnitDays
+	// 指标对应的所有数据
+	_, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, ``, ``, []*models.ChartEdbInfoMapping{mappingInfo})
+	if err != nil {
+		return
+	}
+	for k, edb := range edbList {
+		dataList := edb.DataList.([]*models.EdbDataList)
+		newDataList := make([]models.EdbDataList, 0)
+
+		dataMap := make(map[time.Time]float64, 0)
+		for _, tmpData := range dataList {
+			currDateTime, _ := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
+			dataMap[currDateTime] = tmpData.Value
+		}
+
+		//百分位:对所选指标滚动地取对应时间长度的数据值,取最大值Max,最小值Min,计算Max-Min,百分位=(现值-Min)/(Max-Min),Max=Min时不予计算。
+		for i, tmpData := range dataList {
+			currDateTime, _ := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
+			maxVal := tmpData.Value
+			minVal := tmpData.Value
+			for i := 0; i < calculateDay; i++ {
+				preVal, ok := dataMap[currDateTime.AddDate(0, 0, -i)]
+				if ok {
+					if preVal > maxVal {
+						maxVal = preVal
+					}
+					if preVal < minVal {
+						minVal = preVal
+					}
+				}
+			}
+
+			if maxVal == minVal {
+				continue
+			}
+			tmpV := (tmpData.Value) / (maxVal - minVal) * 100
+			tmpV, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
+			//百分位=(现值-Min)/(Max-Min)
+			newDataList = append(newDataList, models.EdbDataList{
+				EdbDataId:     i,
+				EdbInfoId:     edb.EdbInfoId,
+				DataTime:      dataList[i-1].DataTime,
+				DataTimestamp: dataList[i-1].DataTimestamp,
+				Value:         tmpV,
+			})
+		}
+		edb.Unit = "%"
+		edb.UnitEn = "%"
+		edb.DataList = newDataList
+		edbList[k] = edb
+	}
+
+	return
+}
+
+// GetFrequencyDistributionData 获取频率分布的图表数据
+func GetFrequencyDistributionData(chartInfoId int, mappingInfo *models.ChartEdbInfoMapping, dateType, stepVal int, startDate, endDate string) (edbList []*models.ChartEdbInfoMapping, dataResp response.FrequencyDistributionResp, err error, errMsg string) {
+	//日期类型:1:最近3月;2:最近6月;3:最近1年;4:最近2年;5:最近3年;6:最近5年;7:最近10年,8:自定义时间
+	startDate, endDate = utils.GetDateByDateType2(dateType, startDate, endDate)
+	if startDate == `` {
+		errMsg = "错误的日期"
+		err = errors.New(errMsg)
+		return
+	}
+	XDataList := make([]float64, 0)
+	// 频度
+	Y1DataList := make([]response.FrequencyDistributionYData, 0)
+	// 累计频率
+	Y2DataList := make([]response.FrequencyDistributionYData, 0)
+	edbList = make([]*models.ChartEdbInfoMapping, 0)
+
+	// 指标对应的所有数据
+	_, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, startDate, endDate, []*models.ChartEdbInfoMapping{mappingInfo})
+	if err != nil {
+		return
+	}
+	if len(edbList) != 1 {
+		err = errors.New("指标异常")
+		return
+	}
+	startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+	var endDateTime time.Time
+	if endDate != `` {
+		endDateTime, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+	}
+
+	edb := edbList[0]
+	dataList := edb.DataList.([]*models.EdbDataList)
+
+	if len(dataList) <= 0 {
+		return
+	}
+	maxVal := dataList[0].Value
+	minVal := dataList[0].Value
+	dataValMap := make(map[float64]int)
+	total := 0 // 数据总量
+	for _, tmpData := range dataList {
+		currDateTime, _ := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
+		if (currDateTime.Equal(startDateTime) || currDateTime.After(startDateTime)) && (endDateTime.IsZero() || currDateTime.Before(endDateTime)) {
+			if maxVal < tmpData.Value {
+				maxVal = tmpData.Value
+			}
+			if minVal > tmpData.Value {
+				minVal = tmpData.Value
+			}
+
+			num, ok := dataValMap[tmpData.Value]
+			if ok {
+				dataValMap[tmpData.Value] = num + 1
+			} else {
+				dataValMap[tmpData.Value] = 1
+			}
+			total++
+		}
+	}
+
+	if total <= 0 {
+		errMsg = `没有数据`
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 最大最小值 向上/下取整
+	minVal = utils.GetFloorNewNum(minVal, 2)
+	maxVal = utils.GetCeilNewNum(maxVal, 2)
+	//间距
+	spacing, _ := (decimal.NewFromFloat(maxVal).Sub(decimal.NewFromFloat(minVal))).Div(decimal.NewFromInt(int64(stepVal))).Float64()
+
+	distributionDataNumMap := make(map[float64]int)
+	for i := 1; i <= stepVal; i++ {
+		tmpMinVal, _ := decimal.NewFromFloat(minVal).Add((decimal.NewFromFloat(spacing)).Mul(decimal.NewFromInt(int64(i - 1)))).Float64()
+		tmpMaxVal, _ := decimal.NewFromFloat(minVal).Add((decimal.NewFromFloat(spacing)).Mul(decimal.NewFromInt(int64(i)))).Float64()
+		XDataList = append(XDataList, tmpMinVal)
+		distributionDataNumMap[tmpMinVal] = 0
+		for tmpVal, num := range dataValMap {
+			if tmpMinVal <= tmpVal && tmpVal < tmpMaxVal {
+				distributionDataNumMap[tmpMinVal] += num
+			}
+		}
+	}
+
+	tmpNum := 0
+	for _, tmpMinVal := range XDataList {
+		// 频率
+		frequencyYNum := distributionDataNumMap[tmpMinVal]
+		Y1DataList = append(Y1DataList, response.FrequencyDistributionYData{
+			X: tmpMinVal,
+			Y: float64(frequencyYNum),
+		})
+		// 累计数
+		tmpNum += frequencyYNum
+		// 累计频率
+		tmpTotalFrequency, _ := decimal.NewFromInt(int64(tmpNum)).Div(decimal.NewFromInt(int64(total))).Mul(decimal.NewFromInt(100)).Round(4).Float64()
+		Y2DataList = append(Y2DataList, response.FrequencyDistributionYData{
+			X: tmpMinVal,
+			Y: tmpTotalFrequency,
+		})
+	}
+
+	newDataList := []response.FrequencyDistributionData{
+		{
+			Name:   "频率",
+			NameEn: "Frequency",
+			Unit:   "",
+			UnitEn: "",
+			Value:  Y1DataList,
+			Color:  "#00F",
+			IsAxis: 1,
+		}, {
+			Name:   "累计频率",
+			NameEn: "Total Frequency",
+			Unit:   "%",
+			UnitEn: "%",
+			Value:  Y2DataList,
+			Color:  "#F00",
+			IsAxis: 0,
+		},
+	}
+	edbList[0].DataList = nil
+	dataResp = response.FrequencyDistributionResp{
+		LeftMinValue:  minVal,
+		LeftMaxValue:  maxVal,
+		RightMinValue: 0,
+		RightMaxValue: 100,
+		DataList:      newDataList,
+	}
+	return
+}

+ 28 - 0
utils/calculate.go

@@ -161,3 +161,31 @@ func CalculationDecisive(sList []Coordinate) (r2 float64) {
 
 	return
 }
+
+// CalculateStandardDeviation 计算标准差
+func CalculateStandardDeviation(data []float64) float64 {
+	// 计算平均值
+	mean := calculateMean(data)
+	// 计算方差
+	variance := calculateVariance(data, mean)
+	return math.Sqrt(variance)
+}
+
+// 计算平均值
+func calculateMean(data []float64) float64 {
+	sum := 0.0
+	for _, value := range data {
+		sum += value
+	}
+	return sum / float64(len(data))
+}
+
+// 计算方差
+func calculateVariance(data []float64, mean float64) float64 {
+	sumSquaredDiff := 0.0
+	for _, value := range data {
+		diff := value - mean
+		sumSquaredDiff += diff * diff
+	}
+	return sumSquaredDiff / float64(len(data))
+}

+ 218 - 0
utils/common.go

@@ -8,6 +8,7 @@ import (
 	"encoding/hex"
 	"encoding/json"
 	"fmt"
+	"github.com/shopspring/decimal"
 	"image"
 	"image/png"
 	"io"
@@ -781,3 +782,220 @@ func GetDateByDateType(dateType int, tmpStartDate, tmpEndDate string) (startDate
 
 	return
 }
+
+// GetDateByDateType2 通过dateType获取需要的开始/结束日期(日期类型:1:最近3月;2:最近6月;3:最近1年;4:最近2年;5:最近3年;6:最近5年;7:最近10年,8:自定义时间)
+func GetDateByDateType2(dateType int, tmpStartDate, tmpEndDate string) (startDate, endDate string) {
+	startDate = tmpStartDate
+	endDate = tmpEndDate
+	currDate := time.Now()
+	switch dateType {
+	case 1:
+		startDate = currDate.AddDate(0, -3, 0).Format(FormatDate)
+		endDate = ""
+	case 2:
+		startDate = currDate.AddDate(0, -6, 0).Format(FormatDate)
+		endDate = ""
+	case 3:
+		startDate = currDate.AddDate(-1, 0, 0).Format(FormatDate)
+		endDate = ""
+	case 4:
+		startDate = currDate.AddDate(-2, 0, 0).Format(FormatDate)
+		endDate = ""
+	case 5:
+		startDate = currDate.AddDate(-3, 0, 0).Format(FormatDate)
+		endDate = ""
+	case 6:
+		startDate = currDate.AddDate(-5, 0, 0).Format(FormatDate)
+		endDate = ""
+	case 7:
+		startDate = currDate.AddDate(-10, 0, 0).Format(FormatDate)
+		endDate = ""
+	}
+
+	return
+}
+
+// GetCeilNewNum 保留n位有效数字的向上取整
+// @params num 实际数据
+// @params baseLen 需要保留的有效位数
+func GetCeilNewNum(num float64, baseLen int) (newNum float64) {
+	if num >= 1 {
+		tmpNum := int(math.Ceil(num)) // 向上取整
+		str := strconv.Itoa(tmpNum)
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+			if newNum < num {
+				newNumInt += 1
+				newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+			}
+		} else {
+			newNum = float64(tmpNum)
+		}
+		return
+	} else if num > 0 {
+		// 这是小数
+		str := strconv.FormatFloat(num, 'f', -1, 64)
+		// 去除小数点和负号
+		str = removeDecimalPoint(str)
+		// 计算字符串长度
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+			if newNum < num {
+				newNumInt += 1
+				newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+			}
+		} else {
+			newNum = num
+		}
+	} else if num > -1 {
+		// 这是小数
+		str := strconv.FormatFloat(num, 'f', -1, 64)
+		// 去除小数点和负号
+		str = removeDecimalPoint(str)
+		// 计算字符串长度
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+			newNum = -newNum
+			if newNum < num {
+				newNumInt -= 1
+				newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+				newNum = -newNum
+			}
+		} else {
+			newNum = num
+		}
+		if newNum == -0 {
+			newNum = 0
+		}
+	} else { // 小于等于-1
+		tmpNumFloat := math.Abs(num)
+		tmpNum := int(math.Floor(tmpNumFloat)) // 向上取整
+		str := strconv.Itoa(tmpNum)
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			//fmt.Println("newNumStr:", newNumStr)
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+			newNum = -newNum
+			if newNum < num {
+				newNumInt -= 1
+				newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+				newNum = -newNum
+			}
+		} else {
+			newNum = float64(-tmpNum)
+		}
+	}
+
+	return
+}
+
+// GetFloorNewNum 保留n位有效数字的向下取整
+// @params num 实际数据
+// @params baseLen 需要保留的有效位数
+func GetFloorNewNum(num float64, baseLen int) (newNum float64) {
+	if num >= 1 {
+		tmpNum := int(math.Floor(num)) // 向上取整
+		str := strconv.Itoa(tmpNum)
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+			if newNum < num {
+				newNumInt -= 1
+				newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+			}
+		} else {
+			newNum = float64(tmpNum)
+		}
+		return
+	} else if num > 0 {
+		// 这是小数
+		str := strconv.FormatFloat(num, 'f', -1, 64)
+		// 去除小数点和负号
+		str = removeDecimalPoint(str)
+		// 计算字符串长度
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+			if newNum > num {
+				newNumInt -= 1
+				newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+			}
+		} else {
+			newNum = num
+		}
+	} else if num > -1 {
+		// 这是小数
+		str := strconv.FormatFloat(num, 'f', -1, 64)
+		// 去除小数点和负号
+		str = removeDecimalPoint(str)
+		// 计算字符串长度
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+			newNum = -newNum
+			if newNum > num {
+				newNumInt += 1
+				newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
+				newNum = -newNum
+			}
+		} else {
+			newNum = num
+		}
+		if newNum == -0 {
+			newNum = 0
+		}
+	} else { // 小于等于-1
+		tmpNumFloat := math.Abs(num)
+		tmpNum := int(math.Ceil(tmpNumFloat)) // 向上取整
+		str := strconv.Itoa(tmpNum)
+		lenStr := len(str)
+
+		if lenStr > baseLen {
+			newNumStr := str[0:baseLen]
+			//fmt.Println("newNumStr:", newNumStr)
+			newNumInt, _ := strconv.Atoi(newNumStr)
+			newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+			newNum = -newNum
+			if newNum > num {
+				newNumInt += 1
+				newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
+				newNum = -newNum
+			}
+		} else {
+			newNum = float64(-tmpNum)
+		}
+	}
+
+	return
+}
+
+// 去除小数点和负号
+func removeDecimalPoint(str string) string {
+	// 去除小数点
+	str = str[strings.Index(str, ".")+1:]
+	return str
+}

+ 70 - 66
utils/constants.go

@@ -32,72 +32,76 @@ const (
 
 // 数据来源渠道
 const (
-	DATA_SOURCE_THS                          = iota + 1 //同花顺
-	DATA_SOURCE_WIND                                    //wind
-	DATA_SOURCE_PB                                      //彭博
-	DATA_SOURCE_CALCULATE                               //指标运算
-	DATA_SOURCE_CALCULATE_LJZZY                         //累计值转月
-	DATA_SOURCE_CALCULATE_TBZ                           //同比值
-	DATA_SOURCE_CALCULATE_TCZ                           //同差值
-	DATA_SOURCE_CALCULATE_NSZYDPJJS                     //N数值移动平均计算
-	DATA_SOURCE_MANUAL                                  //手工指标
-	DATA_SOURCE_LZ                                      //隆众
-	DATA_SOURCE_YS                                      //有色
-	DATA_SOURCE_CALCULATE_HBZ                           //环比值->12
-	DATA_SOURCE_CALCULATE_HCZ                           //环差值->13
-	DATA_SOURCE_CALCULATE_BP                            //变频->14
-	DATA_SOURCE_GL                                      //钢联->15
-	DATA_SOURCE_ZZ                                      //郑商所->16
-	DATA_SOURCE_DL                                      //大商所->17
-	DATA_SOURCE_SH                                      //上期所->18
-	DATA_SOURCE_CFFEX                                   //中金所->19
-	DATA_SOURCE_SHFE                                    //上期能源->20
-	DATA_SOURCE_GIE                                     //欧洲天然气->21
-	DATA_SOURCE_CALCULATE_TIME_SHIFT                    //时间移位->22
-	DATA_SOURCE_CALCULATE_ZJPJ                          //直接拼接->23
-	DATA_SOURCE_CALCULATE_LJZTBPJ                       //累计值同比拼接->24
-	DATA_SOURCE_LT                                      //路透->25
-	DATA_SOURCE_COAL                                    //煤炭网->26
-	DATA_SOURCE_PYTHON                                  //python代码->27
-	DATA_SOURCE_PB_FINANCE                              //彭博财务数据->28
-	DATA_SOURCE_GOOGLE_TRAVEL                           //谷歌出行->29
-	DATA_SOURCE_PREDICT                                 //普通预测指标->30
-	DATA_SOURCE_PREDICT_CALCULATE                       //预测指标运算->31
-	DATA_SOURCE_PREDICT_CALCULATE_TBZ                   //预测指标同比值->32
-	DATA_SOURCE_PREDICT_CALCULATE_TCZ                   //预测指标同差值->33
-	DATA_SOURCE_MYSTEEL_CHEMICAL                        //钢联化工->34
-	DATA_SOURCE_CALCULATE_CJJX                          //超季节性->35
-	DATA_SOURCE_EIA_STEO                                //eia steo报告->36
-	DATA_SOURCE_CALCULATE_NHCC                          //计算指标(拟合残差)->37
-	DATA_SOURCE_COM_TRADE                               //联合国商品贸易数据->38
-	DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS             //预测指标 - N数值移动平均计算 -> 39
-	DATA_SOURCE_CALCULATE_ADJUST                        //数据调整->40
-	DATA_SOURCE_SCI                                     //卓创数据(红桃三) -> 41
-	DATA_SOURCE_PREDICT_CALCULATE_LJZZY                 //预测指标 - 累计值转月->42
-	DATA_SOURCE_PREDICT_CALCULATE_HBZ                   //预测指标 - 环比值->43
-	DATA_SOURCE_PREDICT_CALCULATE_HCZ                   //预测指标 - 环差值->44
-	DATA_SOURCE_PREDICT_CALCULATE_BP                    //预测指标 - 变频->45
-	DATA_SOURCE_PREDICT_CALCULATE_TIME_SHIFT            //预测指标 - 时间移位->46
-	DATA_SOURCE_PREDICT_CALCULATE_ZJPJ                  //预测指标 - 直接拼接->47
-	DATA_SOURCE_PREDICT_CALCULATE_LJZTBPJ               //预测指标 - 累计值同比拼接->48
-	DATA_SOURCE_PREDICT_CALCULATE_CJJX                  //预测指标 - 超季节性->49
-	DATA_SOURCE_PREDICT_CALCULATE_NHCC                  //预测指标 - 计算指标(拟合残差)->50
-	DATA_SOURCE_CALCULATE_JP                            //变频->51
-	DATA_SOURCE_CALCULATE_NH                            //年化->52
-	DATA_SOURCE_CALCULATE_KSZS                          //扩散指数->53
-	DATA_SOURCE_PREDICT_CALCULATE_JP                    //预测指标 - 计算指标(降频)->54
-	DATA_SOURCE_PREDICT_CALCULATE_NH                    //预测指标 - 计算指标(年化)->55
-	DATA_SOURCE_PREDICT_CALCULATE_KSZS                  //预测指标 - 计算指标(扩散指数)->56
-	DATA_SOURCE_BAIINFO                                 //百川盈孚 ->57
-	DATA_SOURCE_STOCK_PLANT                             //存量装置 ->58
-	DATA_SOURCE_CALCULATE_CORRELATION                   //滚动相关性->59
-	DATA_SOURCE_NATIONAL_STATISTICS                     //国家统计局->60
-	DATA_SOURCE_CALCULATE_LJZZJ                         //累计值转季 -> 61
-	DATA_SOURCE_CALCULATE_LJZ                           //累计值 -> 62
-	DATA_SOURCE_CALCULATE_LJZNCZJ                       //累计值(年初至今) -> 63
-	DATA_SOURCE_PREDICT_CALCULATE_LJZZJ                 //预测指标 - 累计值转季->64
-	DATA_SOURCE_PREDICT_CALCULATE_LJZ                   //预测指标 - 累计值 -> 65
-	DATA_SOURCE_PREDICT_CALCULATE_LJZNCZJ               //预测指标 - 累计值(年初至今) -> 66
+	DATA_SOURCE_THS                                  = iota + 1 //同花顺
+	DATA_SOURCE_WIND                                            //wind
+	DATA_SOURCE_PB                                              //彭博
+	DATA_SOURCE_CALCULATE                                       //指标运算
+	DATA_SOURCE_CALCULATE_LJZZY                                 //累计值转月
+	DATA_SOURCE_CALCULATE_TBZ                                   //同比值
+	DATA_SOURCE_CALCULATE_TCZ                                   //同差值
+	DATA_SOURCE_CALCULATE_NSZYDPJJS                             //N数值移动平均计算
+	DATA_SOURCE_MANUAL                                          //手工指标
+	DATA_SOURCE_LZ                                              //隆众
+	DATA_SOURCE_YS                                              //有色
+	DATA_SOURCE_CALCULATE_HBZ                                   //环比值->12
+	DATA_SOURCE_CALCULATE_HCZ                                   //环差值->13
+	DATA_SOURCE_CALCULATE_BP                                    //变频->14
+	DATA_SOURCE_GL                                              //钢联->15
+	DATA_SOURCE_ZZ                                              //郑商所->16
+	DATA_SOURCE_DL                                              //大商所->17
+	DATA_SOURCE_SH                                              //上期所->18
+	DATA_SOURCE_CFFEX                                           //中金所->19
+	DATA_SOURCE_SHFE                                            //上期能源->20
+	DATA_SOURCE_GIE                                             //欧洲天然气->21
+	DATA_SOURCE_CALCULATE_TIME_SHIFT                            //时间移位->22
+	DATA_SOURCE_CALCULATE_ZJPJ                                  //直接拼接->23
+	DATA_SOURCE_CALCULATE_LJZTBPJ                               //累计值同比拼接->24
+	DATA_SOURCE_LT                                              //路透->25
+	DATA_SOURCE_COAL                                            //煤炭网->26
+	DATA_SOURCE_PYTHON                                          //python代码->27
+	DATA_SOURCE_PB_FINANCE                                      //彭博财务数据->28
+	DATA_SOURCE_GOOGLE_TRAVEL                                   //谷歌出行->29
+	DATA_SOURCE_PREDICT                                         //普通预测指标->30
+	DATA_SOURCE_PREDICT_CALCULATE                               //预测指标运算->31
+	DATA_SOURCE_PREDICT_CALCULATE_TBZ                           //预测指标同比值->32
+	DATA_SOURCE_PREDICT_CALCULATE_TCZ                           //预测指标同差值->33
+	DATA_SOURCE_MYSTEEL_CHEMICAL                                //钢联化工->34
+	DATA_SOURCE_CALCULATE_CJJX                                  //超季节性->35
+	DATA_SOURCE_EIA_STEO                                        //eia steo报告->36
+	DATA_SOURCE_CALCULATE_NHCC                                  //计算指标(拟合残差)->37
+	DATA_SOURCE_COM_TRADE                                       //联合国商品贸易数据->38
+	DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS                     //预测指标 - N数值移动平均计算 -> 39
+	DATA_SOURCE_CALCULATE_ADJUST                                //数据调整->40
+	DATA_SOURCE_SCI                                             //卓创数据(红桃三) -> 41
+	DATA_SOURCE_PREDICT_CALCULATE_LJZZY                         //预测指标 - 累计值转月->42
+	DATA_SOURCE_PREDICT_CALCULATE_HBZ                           //预测指标 - 环比值->43
+	DATA_SOURCE_PREDICT_CALCULATE_HCZ                           //预测指标 - 环差值->44
+	DATA_SOURCE_PREDICT_CALCULATE_BP                            //预测指标 - 变频->45
+	DATA_SOURCE_PREDICT_CALCULATE_TIME_SHIFT                    //预测指标 - 时间移位->46
+	DATA_SOURCE_PREDICT_CALCULATE_ZJPJ                          //预测指标 - 直接拼接->47
+	DATA_SOURCE_PREDICT_CALCULATE_LJZTBPJ                       //预测指标 - 累计值同比拼接->48
+	DATA_SOURCE_PREDICT_CALCULATE_CJJX                          //预测指标 - 超季节性->49
+	DATA_SOURCE_PREDICT_CALCULATE_NHCC                          //预测指标 - 计算指标(拟合残差)->50
+	DATA_SOURCE_CALCULATE_JP                                    //变频->51
+	DATA_SOURCE_CALCULATE_NH                                    //年化->52
+	DATA_SOURCE_CALCULATE_KSZS                                  //扩散指数->53
+	DATA_SOURCE_PREDICT_CALCULATE_JP                            //预测指标 - 计算指标(降频)->54
+	DATA_SOURCE_PREDICT_CALCULATE_NH                            //预测指标 - 计算指标(年化)->55
+	DATA_SOURCE_PREDICT_CALCULATE_KSZS                          //预测指标 - 计算指标(扩散指数)->56
+	DATA_SOURCE_BAIINFO                                         //百川盈孚 ->57
+	DATA_SOURCE_STOCK_PLANT                                     //存量装置 ->58
+	DATA_SOURCE_CALCULATE_CORRELATION                           //滚动相关性->59
+	DATA_SOURCE_NATIONAL_STATISTICS                             //国家统计局->60
+	DATA_SOURCE_CALCULATE_LJZZJ                                 //累计值转季 -> 61
+	DATA_SOURCE_CALCULATE_LJZ                                   //累计值 -> 62
+	DATA_SOURCE_CALCULATE_LJZNCZJ                               //累计值(年初至今) -> 63
+	DATA_SOURCE_PREDICT_CALCULATE_LJZZJ                         //预测指标 - 累计值转季->64
+	DATA_SOURCE_PREDICT_CALCULATE_LJZ                           //预测指标 - 累计值 -> 65
+	DATA_SOURCE_PREDICT_CALCULATE_LJZNCZJ                       //预测指标 - 累计值(年初至今) -> 66
+	DATA_SOURCE_CALCULATE_STANDARD_DEVIATION                    //标准差->67
+	DATA_SOURCE_CALCULATE_PERCENTILE                            //百分位->68
+	DATA_SOURCE_PREDICT_CALCULATE_STANDARD_DEVIATION            //预测标准差->69
+	DATA_SOURCE_PREDICT_CALCULATE_PERCENTILE                    //预测百分位->70
 )
 
 // 数据刷新频率