package line_feature import ( "errors" "github.com/shopspring/decimal" "hongze/hongze_ETA_mobile_api/models/data_manage" "hongze/hongze_ETA_mobile_api/models/data_manage/line_feature/response" "hongze/hongze_ETA_mobile_api/services/data" "hongze/hongze_ETA_mobile_api/utils" "time" ) // GetStandardDeviationData 获取标准差图表的指标数据 func GetStandardDeviationData(chartInfoId int, mappingInfo *data_manage.ChartEdbInfoMapping, calculateValue int) (edbList []*data_manage.ChartEdbInfoMapping, dataResp response.LineFeatureDataResp, err error, errMsg string) { edbList = make([]*data_manage.ChartEdbInfoMapping, 0) // 指标对应的所有数据 _, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, ``, ``, []*data_manage.ChartEdbInfoMapping{mappingInfo}) if err != nil { return } if len(edbList) != 1 { errMsg = `指标异常` err = errors.New(errMsg) return } edb := edbList[0] dataList := edb.DataList.([]*data_manage.EdbDataList) newDataList := make([]data_manage.EdbDataList, 0) lenData := len(dataList) var minVal, maxVal float64 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, data_manage.EdbDataList{ EdbDataId: i, EdbInfoId: edb.EdbInfoId, DataTime: dataList[i-1].DataTime, DataTimestamp: dataList[i-1].DataTimestamp, Value: tmpV, }) if tmpV > maxVal { maxVal = tmpV } if tmpV < minVal { minVal = tmpV } } } dataResp = response.LineFeatureDataResp{ MaxData: maxVal, MinData: minVal, LatestDate: edb.LatestDate, EdbInfoCategoryType: edb.EdbInfoCategoryType, ChartColor: `#00F`, ChartStyle: `spline`, PredictChartColor: `#00F`, ChartType: 0, ChartWidth: 3, EdbName: "标准差", EdbNameEn: "standard deviation", Unit: edb.Unit, UnitEn: edb.UnitEn, IsAxis: 1, DataList: newDataList, } return } // GetPercentileData 获取百分位图表的指标数据 func GetPercentileData(chartInfoId int, mappingInfo *data_manage.ChartEdbInfoMapping, calculateValue int, calculateUnit string) (edbList []*data_manage.ChartEdbInfoMapping, dataResp response.LineFeatureDataResp, err error, errMsg string) { edbList = make([]*data_manage.ChartEdbInfoMapping, 0) moveUnitDays, ok := utils.FrequencyDaysMap[calculateUnit] if !ok { errMsg = `错误的周期` err = errors.New(errMsg) return } calculateDay := calculateValue * moveUnitDays // 指标对应的所有数据 _, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, ``, ``, []*data_manage.ChartEdbInfoMapping{mappingInfo}) if err != nil { return } if len(edbList) != 1 { errMsg = `指标异常` err = errors.New(errMsg) return } edb := edbList[0] dataList := edb.DataList.([]*data_manage.EdbDataList) newDataList := make([]data_manage.EdbDataList, 0) var edbMinVal, edbMaxVal float64 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, data_manage.EdbDataList{ EdbDataId: i, EdbInfoId: edb.EdbInfoId, DataTime: dataList[i-1].DataTime, DataTimestamp: dataList[i-1].DataTimestamp, Value: tmpV, }) if tmpV < edbMinVal { edbMinVal = tmpV } if tmpV > edbMaxVal { edbMaxVal = tmpV } } dataResp = response.LineFeatureDataResp{ MaxData: edbMaxVal, MinData: edbMinVal, LatestDate: edb.LatestDate, EdbInfoCategoryType: edb.EdbInfoCategoryType, ChartColor: `#00F`, ChartStyle: `spline`, PredictChartColor: `#00F`, ChartType: 0, ChartWidth: 3, EdbName: "百分位", EdbNameEn: "percentile", Unit: "%", UnitEn: "%", IsAxis: 1, DataList: newDataList, } return } // GetFrequencyDistributionData 获取频率分布的图表数据 func GetFrequencyDistributionData(chartInfoId int, mappingInfo *data_manage.ChartEdbInfoMapping, dateType, stepVal int, startDate, endDate string) (edbList []*data_manage.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([]*data_manage.ChartEdbInfoMapping, 0) // 指标对应的所有数据 _, edbList, err = data.GetEdbDataMapList(chartInfoId, 1, `公历`, startDate, endDate, []*data_manage.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.([]*data_manage.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 }