|
@@ -652,6 +652,19 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
|
|
|
}
|
|
|
}
|
|
|
dataResp = chart_info.ChartTimeCombineDataResp{IsHeap: timeConf.IsHeap}
|
|
|
+ case 2: // 季节性图
|
|
|
+ if seasonExtraConfig != "" {
|
|
|
+ // 季节性图计算不管图上数据时间,拿所有数据
|
|
|
+ _, tempEdbList, e := getEdbDataMapListForSeason(chartInfoId, chartType, calendar, "1990-01-01", "", mappingList, seasonExtraConfig)
|
|
|
+ if e != nil {
|
|
|
+ err = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ dataResp, err = SeasonChartData(tempEdbList, seasonExtraConfig)
|
|
|
+ } else {
|
|
|
+ // 兼容无配置的老图
|
|
|
+ dataResp = new(edbDataModel.SeasonChartResp)
|
|
|
+ }
|
|
|
case 7: // 柱形图
|
|
|
barChartConf := extraConfig.(request.BarChartInfoReq)
|
|
|
xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
|
|
@@ -699,6 +712,800 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+// getEdbDataMapListForSeason 获取指标最后的基础数据-插值补充好数据-季节性图用
|
|
|
+func getEdbDataMapListForSeason(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*chartEdbMappingModel.ChartEdbInfoMapping, seasonExtraConfig string) (edbDataListMap map[int][]*edbDataModel.EdbDataList, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, err error) {
|
|
|
+ // 指标对应的所有数据
|
|
|
+ edbDataListMap = make(map[int][]*edbDataModel.EdbDataList)
|
|
|
+ seasonXStartDateWithYear := ""
|
|
|
+ seasonXEndDateWithYear := ""
|
|
|
+ if chartType == 2 {
|
|
|
+ sort.Slice(mappingList, func(i, j int) bool {
|
|
|
+ return mappingList[i].IsAxis > mappingList[j].IsAxis
|
|
|
+ })
|
|
|
+ }
|
|
|
+ for _, v := range mappingList {
|
|
|
+ //fmt.Println("v:", v.EdbInfoId)
|
|
|
+ item := new(chartEdbMappingModel.ChartEdbInfoMappingList)
|
|
|
+ item.EdbInfoId = v.EdbInfoId
|
|
|
+ item.SourceName = v.SourceName
|
|
|
+ item.Source = v.Source
|
|
|
+ item.EdbCode = v.EdbCode
|
|
|
+ item.EdbName = v.EdbName
|
|
|
+ item.EdbNameEn = v.EdbNameEn
|
|
|
+ item.Frequency = v.Frequency
|
|
|
+ item.EdbType = v.EdbType
|
|
|
+ item.FrequencyEn = GetFrequencyEn(v.Frequency)
|
|
|
+ if v.Unit != `无` {
|
|
|
+ item.Unit = v.Unit
|
|
|
+ }
|
|
|
+ item.UnitEn = v.UnitEn
|
|
|
+ item.StartDate = v.StartDate
|
|
|
+ item.EndDate = v.EndDate
|
|
|
+ item.ModifyTime = v.ModifyTime
|
|
|
+ item.EdbInfoCategoryType = v.EdbInfoCategoryType
|
|
|
+ item.PredictChartColor = v.PredictChartColor
|
|
|
+ item.ClassifyId = v.ClassifyId
|
|
|
+ if chartInfoId <= 0 {
|
|
|
+ item.IsAxis = 1
|
|
|
+ item.LeadValue = 0
|
|
|
+ item.LeadUnit = ""
|
|
|
+ item.ChartEdbMappingId = 0
|
|
|
+ item.ChartInfoId = 0
|
|
|
+ item.IsOrder = false
|
|
|
+ item.EdbInfoType = 1
|
|
|
+ item.ChartStyle = ""
|
|
|
+ item.ChartColor = ""
|
|
|
+ item.ChartWidth = 0
|
|
|
+ item.MaxData = v.MaxValue
|
|
|
+ item.MinData = v.MinValue
|
|
|
+ } else {
|
|
|
+ item.IsAxis = v.IsAxis
|
|
|
+ item.EdbInfoType = v.EdbInfoType
|
|
|
+ item.LeadValue = v.LeadValue
|
|
|
+ item.LeadUnit = v.LeadUnit
|
|
|
+ item.LeadUnitEn = GetLeadUnitEn(v.LeadUnit)
|
|
|
+ item.ChartEdbMappingId = v.ChartEdbMappingId
|
|
|
+ item.ChartInfoId = v.ChartInfoId
|
|
|
+ item.ChartStyle = v.ChartStyle
|
|
|
+ item.ChartColor = v.ChartColor
|
|
|
+ item.ChartWidth = v.ChartWidth
|
|
|
+ item.IsOrder = v.IsOrder
|
|
|
+ item.MaxData = v.MaxData
|
|
|
+ item.MinData = v.MinData
|
|
|
+ }
|
|
|
+ item.LatestValue = v.LatestValue
|
|
|
+ item.LatestDate = v.LatestDate
|
|
|
+ item.UniqueCode = v.UniqueCode
|
|
|
+ item.MoveLatestDate = v.LatestDate
|
|
|
+ item.EdbAliasName = v.EdbAliasName
|
|
|
+ item.IsConvert = v.IsConvert
|
|
|
+ item.ConvertType = v.ConvertType
|
|
|
+ item.ConvertValue = v.ConvertValue
|
|
|
+ item.ConvertUnit = v.ConvertUnit
|
|
|
+ item.ConvertEnUnit = v.ConvertEnUnit
|
|
|
+ item.IsJoinPermission = v.IsJoinPermission
|
|
|
+
|
|
|
+ var startDateReal string
|
|
|
+ var diffSeconds int64
|
|
|
+ if chartType == 2 { //季节性图
|
|
|
+ startDateReal = startDate
|
|
|
+ if len(mappingList) > 1 {
|
|
|
+ item.IsAxis = v.IsAxis
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
|
|
|
+ var startTimeRealTemp time.Time
|
|
|
+ startDateParse, _ := time.Parse(utils.FormatDate, startDate)
|
|
|
+ switch v.LeadUnit {
|
|
|
+ case "天":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, 0, -v.LeadValue)
|
|
|
+ case "月":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, -v.LeadValue, 0)
|
|
|
+ case "季":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, -3*v.LeadValue, 0)
|
|
|
+ case "周":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, 0, -7*v.LeadValue)
|
|
|
+ case "年":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(-v.LeadValue, 0, 0)
|
|
|
+ }
|
|
|
+ if startTimeRealTemp.Before(startDateParse) {
|
|
|
+ startDateReal = startTimeRealTemp.Format(utils.FormatDate)
|
|
|
+ diffSeconds = (int64(startTimeRealTemp.UnixNano()) - int64(startDateParse.UnixNano())) / 1e6
|
|
|
+ } else {
|
|
|
+ startDateReal = startDate
|
|
|
+ diffSeconds = 0
|
|
|
+ }
|
|
|
+
|
|
|
+ // 预测指标的开始日期也要偏移
|
|
|
+ {
|
|
|
+ day, tmpErr := utils.GetDaysBetween2Date(utils.FormatDate, startDate, startDateReal)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ moveLatestDateTime := item.MoveLatestDate.Local()
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item.MoveLatestDate = moveLatestDateTime.AddDate(0, 0, day)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ startDateReal = startDate
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //fmt.Println("line 1011 chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
|
|
|
+ calendarPreYear := 0
|
|
|
+ if calendar == "农历" {
|
|
|
+ newStartDateReal, err := time.Parse(utils.FormatDate, startDateReal)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("time.Parse:" + err.Error())
|
|
|
+ }
|
|
|
+ calendarPreYear = newStartDateReal.Year() - 1
|
|
|
+ newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
|
|
|
+ startDateReal = newStartDateReal.Format(utils.FormatDate)
|
|
|
+ }
|
|
|
+ dataList := make([]*edbDataModel.EdbDataList, 0)
|
|
|
+ //fmt.Println("chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
|
|
|
+ //fmt.Println("calendarPreYear:", calendarPreYear)
|
|
|
+ //var newEdbInfo *data_manage.EdbInfo
|
|
|
+ switch v.EdbInfoCategoryType {
|
|
|
+ case 0:
|
|
|
+ dataList, err = edbDataModel.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, startDateReal, endDate)
|
|
|
+ case 1:
|
|
|
+ _, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, startDateReal, endDate, true)
|
|
|
+ default:
|
|
|
+ err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.EdbInfoCategoryType))
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ handleDataMap := make(map[string]float64)
|
|
|
+ newDataList, _, _, e := HandleDataByLinearRegressionToListV3(dataList, handleDataMap)
|
|
|
+ if e != nil {
|
|
|
+ err = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if v.IsConvert == 1 {
|
|
|
+ switch v.ConvertType {
|
|
|
+ case 1:
|
|
|
+ for i, data := range newDataList {
|
|
|
+ newDataList[i].Value = data.Value * v.ConvertValue
|
|
|
+ }
|
|
|
+ //item.MaxData = item.MaxData * v.ConvertValue
|
|
|
+ //item.MinData = item.MinData * v.ConvertValue
|
|
|
+ case 2:
|
|
|
+ for i, data := range newDataList {
|
|
|
+ newDataList[i].Value = data.Value / v.ConvertValue
|
|
|
+ }
|
|
|
+ //item.MaxData = item.MaxData / v.ConvertValue
|
|
|
+ //item.MinData = item.MinData / v.ConvertValue
|
|
|
+ case 3:
|
|
|
+ for i, data := range newDataList {
|
|
|
+ if data.Value <= 0 {
|
|
|
+ err = errors.New("数据中含有负数或0,无法对数运算")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ newDataList[i].Value = math.Log(data.Value) / math.Log(v.ConvertValue)
|
|
|
+ }
|
|
|
+ //item.MaxData = math.Log(item.MaxData) / math.Log(v.ConvertValue)
|
|
|
+ //item.MinData = math.Log(item.MinData) / math.Log(v.ConvertValue)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ edbDataListMap[v.EdbInfoId] = newDataList
|
|
|
+
|
|
|
+ if diffSeconds != 0 && v.EdbInfoType == 0 {
|
|
|
+ newDataListLen := len(newDataList)
|
|
|
+ for i := 0; i < newDataListLen; i++ {
|
|
|
+ newDataList[i].DataTimestamp = newDataList[i].DataTimestamp - diffSeconds
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if chartType == 2 && item.IsAxis == 1 {
|
|
|
+ latestDate := v.LatestDate
|
|
|
+ if latestDate.IsZero() {
|
|
|
+ //item.DataList = newDataList
|
|
|
+ item.IsNullData = true
|
|
|
+ edbList = append(edbList, item)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if calendar == "农历" {
|
|
|
+ if len(newDataList) <= 0 {
|
|
|
+ result := new(edbDataModel.EdbDataResult)
|
|
|
+ item.DataList = result
|
|
|
+ } else {
|
|
|
+ result, tmpErr := edbDataService.AddCalculateQuarterV6(newDataList)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ quarterDataList, seasonXStartDateWithYearTmp, seasonXEndDateWithYearTmp, tErr := GetSeasonEdbInfoDataListByXDateNong(result, latestDate, seasonExtraConfig, calendarPreYear)
|
|
|
+ if tErr != nil {
|
|
|
+ err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item.DataList = quarterDataList
|
|
|
+ seasonXStartDateWithYear = seasonXStartDateWithYearTmp
|
|
|
+ seasonXEndDateWithYear = seasonXEndDateWithYearTmp
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ quarterDataList, seasonXStartDateWithYearTmp, seasonXEndDateWithYearTmp, tErr := GetSeasonEdbInfoDataListByXDate(newDataList, latestDate, seasonExtraConfig)
|
|
|
+ if tErr != nil {
|
|
|
+ err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item.DataList = quarterDataList
|
|
|
+ seasonXStartDateWithYear = seasonXStartDateWithYearTmp
|
|
|
+ seasonXEndDateWithYear = seasonXEndDateWithYearTmp
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if chartType == 2 && item.IsAxis == 0 {
|
|
|
+ newDataList := make([]*edbDataModel.EdbDataList, 0)
|
|
|
+ for _, v := range dataList {
|
|
|
+ dataTime, e := time.Parse(utils.FormatDate, v.DataTime)
|
|
|
+ if e != nil {
|
|
|
+ err = errors.New("季节性图处理右轴指标数据转换日期失败,Err:" + e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ seasonXStartDateWithYearT, _ := time.Parse(utils.FormatDate, seasonXStartDateWithYear)
|
|
|
+ seasonXEndDateWithYearT, _ := time.Parse(utils.FormatDate, seasonXEndDateWithYear)
|
|
|
+ if dataTime.Equal(seasonXStartDateWithYearT) || (dataTime.After(seasonXStartDateWithYearT) && dataTime.Before(seasonXEndDateWithYearT)) || dataTime.Equal(seasonXEndDateWithYearT) {
|
|
|
+ newDataList = append(newDataList, v)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ item.DataList = newDataList
|
|
|
+ } else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
|
|
|
+ //item.DataList = newDataList
|
|
|
+ } else {
|
|
|
+ item.DataList = newDataList
|
|
|
+ }
|
|
|
+ edbList = append(edbList, item)
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// SeasonChartData 季节性图的数据处理
|
|
|
+func SeasonChartData(dataList []*chartEdbMappingModel.ChartEdbInfoMappingList, seasonExtraConfig string) (dataResp edbDataModel.SeasonChartResp, err error) {
|
|
|
+ var seasonConfig edbDataModel.SeasonExtraItem
|
|
|
+ err = json.Unmarshal([]byte(seasonExtraConfig), &seasonConfig)
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("季节性图配置异常, Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, mappingItem := range dataList {
|
|
|
+ if mappingItem.IsAxis == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ quarterDataList, ok := mappingItem.DataList.(edbDataModel.QuarterDataList)
|
|
|
+ if !ok {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 上下限区间
|
|
|
+ if seasonConfig.MaxMinLimits.Year > 0 {
|
|
|
+ startYear := time.Now().AddDate(-seasonConfig.MaxMinLimits.Year, 0, 0).Year()
|
|
|
+ dataResp.MaxMinLimits.List = make([]*edbDataModel.MaxMinLimitsData, 0)
|
|
|
+ dataTimeMap := make(map[time.Time]time.Time)
|
|
|
+ dataTimeList := make([]string, 0)
|
|
|
+ maxValueMap := make(map[time.Time]float64)
|
|
|
+ minValueMap := make(map[time.Time]float64)
|
|
|
+
|
|
|
+ maxMinDataList := make([]*edbDataModel.MaxMinLimitsData, 0)
|
|
|
+ var startDateStr string
|
|
|
+ var endDateStr string
|
|
|
+ var newDate time.Time
|
|
|
+
|
|
|
+ startDateStr = fmt.Sprintf("%d-%s", time.Now().Year(), seasonConfig.XStartDate)
|
|
|
+ endDateStr = fmt.Sprintf("%d-%s", time.Now().Year(), seasonConfig.XEndDate)
|
|
|
+ startDate, e := time.Parse(utils.FormatDate, startDateStr)
|
|
|
+ if e != nil {
|
|
|
+ err = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ endDate, e := time.Parse(utils.FormatDate, endDateStr)
|
|
|
+ if e != nil {
|
|
|
+ err = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 日度 周度插值
|
|
|
+ for _, v := range quarterDataList {
|
|
|
+ if mappingItem.Frequency == "日度" || mappingItem.Frequency == "周度" {
|
|
|
+ handleDataMap := make(map[string]float64)
|
|
|
+ dataTimeList, _, err = HandleDataByLinearRegressionToList(v.DataList, handleDataMap)
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("插值处理数据异常, Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 不包含当年
|
|
|
+ if v.ChartLegend == strconv.Itoa(time.Now().Year()) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
|
|
|
+ chartLegend, _ := strconv.Atoi(v.ChartLegend)
|
|
|
+ if chartLegend < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ for _, date := range dataTimeList {
|
|
|
+ dateTime, e := time.Parse(utils.FormatDate, date)
|
|
|
+ if e != nil {
|
|
|
+ err = errors.New("时间格式化异常, Err:" + e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if dateTime.Year() < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 不包含2月29号
|
|
|
+ if dateTime.Month() == 2 && dateTime.Day() == 29 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ newDate = dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
|
|
|
+ if seasonConfig.JumpYear == 1 {
|
|
|
+ if startDate.After(endDate) {
|
|
|
+ // 如果跨年且不到一年
|
|
|
+ // 全年截取一部分
|
|
|
+ if newDate.Before(startDate.AddDate(0, 0, 1)) && newDate.After(endDate) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if newDate.After(startDate.AddDate(0, 0, -1)) {
|
|
|
+ // 减一年
|
|
|
+ newDate = dateTime.AddDate(time.Now().Year()-dateTime.Year()-1, 0, 0)
|
|
|
+ }
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < handleDataMap[date] {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > handleDataMap[date] {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ } else {
|
|
|
+ // 如果跨年且大于等于一年
|
|
|
+ // double后截取
|
|
|
+ if newDate.After(startDate) {
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < handleDataMap[date] {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > handleDataMap[date] {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ }
|
|
|
+
|
|
|
+ newDate = dateTime.AddDate(time.Now().Year()-dateTime.Year()+1, 0, 0)
|
|
|
+ newEndDate := endDate.AddDate(1, 0, 0)
|
|
|
+ if newDate.Before(newEndDate) {
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < handleDataMap[date] {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > handleDataMap[date] {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果不跨年 正常获取
|
|
|
+ // 获取当前日期所在区间
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < handleDataMap[date] {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > handleDataMap[date] {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 旬度、月度、季度、半年度 不插值,需要先把日期列表和数据map取出来
|
|
|
+ for _, vv := range v.DataList {
|
|
|
+ dateTime, e := time.Parse(utils.FormatDate, vv.DataTime)
|
|
|
+ if e != nil {
|
|
|
+ err = errors.New("时间格式化异常, Err:" + e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 不包含当年
|
|
|
+ if v.ChartLegend == strconv.Itoa(time.Now().Year()) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if dateTime.Year() < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
|
|
|
+ chartLegend, _ := strconv.Atoi(v.ChartLegend)
|
|
|
+ if chartLegend < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 月度的2月29号日期改为2月28日
|
|
|
+ if dateTime.Month() == 2 && dateTime.Day() == 29 {
|
|
|
+ dateTime = dateTime.AddDate(0, 0, -1)
|
|
|
+ }
|
|
|
+ newDate = dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
|
|
|
+ if seasonConfig.JumpYear == 1 {
|
|
|
+ if startDate.After(endDate) {
|
|
|
+ // 如果跨年且不到一年
|
|
|
+ // 全年截取一部分
|
|
|
+ if newDate.Before(startDate.AddDate(0, 0, 1)) && newDate.After(endDate) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if newDate.After(startDate.AddDate(0, 0, -1)) {
|
|
|
+ // 减一年
|
|
|
+ newDate = dateTime.AddDate(time.Now().Year()-dateTime.Year()-1, 0, 0)
|
|
|
+ }
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < vv.Value {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > vv.Value {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ } else {
|
|
|
+ // 如果跨年且大于等于一年
|
|
|
+ // double后截取
|
|
|
+ if newDate.After(startDate) {
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < vv.Value {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > vv.Value {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ }
|
|
|
+
|
|
|
+ newDate = dateTime.AddDate(time.Now().Year()-dateTime.Year()+1, 0, 0)
|
|
|
+ newEndDate := endDate.AddDate(1, 0, 0)
|
|
|
+ if newDate.Before(newEndDate) {
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < vv.Value {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > vv.Value {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果不跨年 正常获取
|
|
|
+ // 获取当前日期所在区间
|
|
|
+ // 处理上下限列表
|
|
|
+ if value, ok := maxValueMap[newDate]; ok {
|
|
|
+ if value < vv.Value {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ maxValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ if value, ok := minValueMap[newDate]; ok {
|
|
|
+ if value > vv.Value {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ minValueMap[newDate] = vv.Value
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range dataTimeMap {
|
|
|
+ maxMinItem := &edbDataModel.MaxMinLimitsData{}
|
|
|
+ if maxValue, ok := maxValueMap[v]; ok {
|
|
|
+ maxMinItem.MaxValue = maxValue
|
|
|
+ } else {
|
|
|
+ maxMinItem.MaxValue = minValueMap[v]
|
|
|
+ }
|
|
|
+
|
|
|
+ if minValue, ok := minValueMap[v]; ok {
|
|
|
+ maxMinItem.MinValue = minValue
|
|
|
+ } else {
|
|
|
+ maxMinItem.MinValue = maxValueMap[v]
|
|
|
+ }
|
|
|
+
|
|
|
+ maxMinItem.DataTime = v.Format(utils.FormatDate)
|
|
|
+ maxMinItem.DataTimestamp = v.UnixNano() / 1e6
|
|
|
+
|
|
|
+ maxMinDataList = append(maxMinDataList, maxMinItem)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ sort.Slice(maxMinDataList, func(i, j int) bool {
|
|
|
+ return maxMinDataList[i].DataTime < maxMinDataList[j].DataTime
|
|
|
+ })
|
|
|
+
|
|
|
+ dataResp.MaxMinLimits.List = maxMinDataList
|
|
|
+ dataResp.MaxMinLimits.Color = seasonConfig.MaxMinLimits.Color
|
|
|
+ dataResp.MaxMinLimits.Legend = seasonConfig.MaxMinLimits.Legend
|
|
|
+ dataResp.MaxMinLimits.IsShow = seasonConfig.MaxMinLimits.IsShow
|
|
|
+ dataResp.MaxMinLimits.IsAdd = seasonConfig.MaxMinLimits.IsAdd
|
|
|
+ dataResp.MaxMinLimits.Year = seasonConfig.MaxMinLimits.Year
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自定义同期均线
|
|
|
+ if seasonConfig.SamePeriodAverage.Year > 0 {
|
|
|
+ handleDataMap := make(map[string]float64)
|
|
|
+ dataTimeMap := make(map[time.Time]time.Time)
|
|
|
+ dataTimeList := make([]string, 0)
|
|
|
+ valueMap := make(map[time.Time]float64)
|
|
|
+ averageDataList := make([]*edbDataModel.SamePeriodAverageData, 0)
|
|
|
+ dateNumMap := make(map[time.Time]float64)
|
|
|
+ for i := len(quarterDataList) - 1; i >= 0; i-- {
|
|
|
+ // 插值成日度
|
|
|
+ dataTimeList, _, err = HandleDataByLinearRegressionToList(quarterDataList[i].DataList, handleDataMap)
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("插值处理数据异常, Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, date := range dataTimeList {
|
|
|
+ dateTime, e := time.Parse(utils.FormatDate, date)
|
|
|
+ if e != nil {
|
|
|
+ err = errors.New("时间格式化异常, Err:" + e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ startYear := time.Now().AddDate(-seasonConfig.SamePeriodAverage.Year, 0, 0).Year()
|
|
|
+ if dateTime.Year() < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
|
|
|
+ chartLegend, _ := strconv.Atoi(quarterDataList[i].ChartLegend)
|
|
|
+ if chartLegend < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 不包含2月29号
|
|
|
+ if dateTime.Month() == 2 && dateTime.Day() == 29 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 不包含当年
|
|
|
+ if quarterDataList[i].ChartLegend == strconv.Itoa(time.Now().Year()) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ newDate := dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
|
|
|
+ // 处理均值
|
|
|
+ if value, ok := valueMap[newDate]; ok {
|
|
|
+ valueMap[newDate] = handleDataMap[date] + value
|
|
|
+ } else {
|
|
|
+ valueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+ dateNumMap[newDate] += 1
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //year := float64(seasonConfig.SamePeriodAverage.Year)
|
|
|
+ for _, v := range dataTimeMap {
|
|
|
+ averageItem := &edbDataModel.SamePeriodAverageData{}
|
|
|
+ year := dateNumMap[v]
|
|
|
+ if value, ok := valueMap[v]; ok {
|
|
|
+ if year > 0 {
|
|
|
+ averageItem.Value = value / year
|
|
|
+ } else {
|
|
|
+ averageItem.Value = value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ averageItem.DataTime = v.Format(utils.FormatDate)
|
|
|
+ averageItem.DataTimestamp = v.UnixNano() / 1e6
|
|
|
+
|
|
|
+ averageDataList = append(averageDataList, averageItem)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ sort.Slice(averageDataList, func(i, j int) bool {
|
|
|
+ return averageDataList[i].DataTime < averageDataList[j].DataTime
|
|
|
+ })
|
|
|
+
|
|
|
+ dataResp.SamePeriodAverage.List = averageDataList
|
|
|
+ dataResp.SamePeriodAverage.Year = seasonConfig.SamePeriodAverage.Year
|
|
|
+ dataResp.SamePeriodAverage.Color = seasonConfig.SamePeriodAverage.Color
|
|
|
+ dataResp.SamePeriodAverage.Legend = seasonConfig.SamePeriodAverage.Legend
|
|
|
+ dataResp.SamePeriodAverage.IsShow = seasonConfig.SamePeriodAverage.IsShow
|
|
|
+ dataResp.SamePeriodAverage.LineType = seasonConfig.SamePeriodAverage.LineType
|
|
|
+ dataResp.SamePeriodAverage.LineWidth = seasonConfig.SamePeriodAverage.LineWidth
|
|
|
+ dataResp.SamePeriodAverage.IsAdd = seasonConfig.SamePeriodAverage.IsAdd
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自定义同期标准差
|
|
|
+ if seasonConfig.SamePeriodStandardDeviation.Year > 1 && seasonConfig.SamePeriodStandardDeviation.Multiple > 0 {
|
|
|
+ startYear := time.Now().AddDate(-seasonConfig.SamePeriodStandardDeviation.Year, 0, 0).Year()
|
|
|
+
|
|
|
+ // 先算均值,再算标准差
|
|
|
+ handleDataMap := make(map[string]float64)
|
|
|
+ dataTimeMap := make(map[time.Time]time.Time)
|
|
|
+ dataTimeValueMap := make(map[time.Time][]float64)
|
|
|
+ dataTimeList := make([]string, 0)
|
|
|
+ valueMap := make(map[time.Time]float64)
|
|
|
+
|
|
|
+ samePeriodStandardDeviationList := make([]*edbDataModel.MaxMinLimitsData, 0)
|
|
|
+ for i := len(quarterDataList) - 1; i > len(quarterDataList)-seasonConfig.SamePeriodAverage.Year-1 && i > 0; i-- {
|
|
|
+ // 插值成日度
|
|
|
+ dataTimeList, _, err = HandleDataByLinearRegressionToListV2(quarterDataList[i].DataList, handleDataMap)
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("插值处理数据异常, Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, date := range dataTimeList {
|
|
|
+ dateTime, e := time.Parse(utils.FormatDate, date)
|
|
|
+ if e != nil {
|
|
|
+ err = errors.New("时间格式化异常, Err:" + e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if dateTime.Year() < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
|
|
|
+ chartLegend, _ := strconv.Atoi(quarterDataList[i].ChartLegend)
|
|
|
+ if chartLegend < startYear {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 不包含2月29号
|
|
|
+ if dateTime.Month() == 2 && dateTime.Day() == 29 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ newDate := dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
|
|
|
+ // 处理均值
|
|
|
+ if value, ok := valueMap[newDate]; ok {
|
|
|
+ valueMap[newDate] = (handleDataMap[date] + value) / 2
|
|
|
+ } else {
|
|
|
+ valueMap[newDate] = handleDataMap[date]
|
|
|
+ }
|
|
|
+
|
|
|
+ dataTimeMap[newDate] = newDate
|
|
|
+ valueList := dataTimeValueMap[newDate]
|
|
|
+ valueList = append(valueList, handleDataMap[date])
|
|
|
+ dataTimeValueMap[newDate] = valueList
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range dataTimeMap {
|
|
|
+ valueList := dataTimeValueMap[v]
|
|
|
+ stdev := utils.CalculateStandardDeviation(valueList)
|
|
|
+ stdev, _ = decimal.NewFromFloat(stdev).Round(4).Float64()
|
|
|
+
|
|
|
+ maxMinItem := &edbDataModel.MaxMinLimitsData{}
|
|
|
+
|
|
|
+ if value, ok := valueMap[v]; ok {
|
|
|
+ maxMinItem.MaxValue = value + stdev*seasonConfig.SamePeriodStandardDeviation.Multiple
|
|
|
+ maxMinItem.MinValue = value - stdev*seasonConfig.SamePeriodStandardDeviation.Multiple
|
|
|
+ }
|
|
|
+
|
|
|
+ maxMinItem.DataTime = v.Format(utils.FormatDate)
|
|
|
+ maxMinItem.DataTimestamp = v.UnixNano() / 1e6
|
|
|
+
|
|
|
+ samePeriodStandardDeviationList = append(samePeriodStandardDeviationList, maxMinItem)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ sort.Slice(samePeriodStandardDeviationList, func(i, j int) bool {
|
|
|
+ return samePeriodStandardDeviationList[i].DataTime < samePeriodStandardDeviationList[j].DataTime
|
|
|
+ })
|
|
|
+
|
|
|
+ dataResp.SamePeriodStandardDeviation.List = samePeriodStandardDeviationList
|
|
|
+ dataResp.SamePeriodStandardDeviation.Color = seasonConfig.SamePeriodStandardDeviation.Color
|
|
|
+ dataResp.SamePeriodStandardDeviation.Legend = seasonConfig.SamePeriodStandardDeviation.Legend
|
|
|
+ dataResp.SamePeriodStandardDeviation.IsShow = seasonConfig.SamePeriodStandardDeviation.IsShow
|
|
|
+ dataResp.SamePeriodStandardDeviation.Multiple = seasonConfig.SamePeriodStandardDeviation.Multiple
|
|
|
+ dataResp.SamePeriodStandardDeviation.Year = seasonConfig.SamePeriodStandardDeviation.Year
|
|
|
+ dataResp.SamePeriodStandardDeviation.IsAdd = seasonConfig.SamePeriodStandardDeviation.IsAdd
|
|
|
+ }
|
|
|
+
|
|
|
+ // 自定义右轴
|
|
|
+ if seasonConfig.RightAxis.IndicatorType != 0 {
|
|
|
+ if seasonConfig.RightAxis.IndicatorType == 1 {
|
|
|
+ startTime, _ := time.Parse(utils.FormatDate, mappingItem.StartDate)
|
|
|
+ for i := len(quarterDataList) - 1; i > len(quarterDataList)-2 && i > 0; i-- {
|
|
|
+ var rightMappingItem chartEdbMappingModel.ChartEdbInfoMappingList
|
|
|
+ rightMappingItem = *mappingItem
|
|
|
+ // 计算同比值
|
|
|
+ tbzDataList, minValue, maxValue, e := GetEdbDataTbzForSeason(mappingItem.Frequency, quarterDataList[i].DataList, startTime)
|
|
|
+ if e != nil {
|
|
|
+ err = errors.New("计算同比值失败, Err:" + e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ rightMappingItem.DataList = tbzDataList
|
|
|
+ rightMappingItem.MaxData = maxValue
|
|
|
+ rightMappingItem.MinData = minValue
|
|
|
+ dataResp.RightAxis.EdbInfoList = append(dataResp.RightAxis.EdbInfoList, &rightMappingItem)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dataResp.RightAxis.SeasonRightAxis = seasonConfig.RightAxis
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
// GetEdbDataMapList 获取指标最后的基础数据
|
|
|
func GetEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*chartEdbMappingModel.ChartEdbInfoMapping, seasonExtraConfig string) (edbDataListMap map[int][]*edbDataModel.EdbDataList, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, sourceArr []string, err error) {
|
|
|
edbDataListMap, edbList, sourceArr, err = getEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtraConfig)
|
|
@@ -711,6 +1518,14 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
|
|
|
sourceArr = make([]string, 0)
|
|
|
// 指标对应的所有数据
|
|
|
edbDataListMap = make(map[int][]*edbDataModel.EdbDataList)
|
|
|
+ seasonXStartDateWithYear := ""
|
|
|
+ seasonXEndDateWithYear := ""
|
|
|
+ if chartType == 2 {
|
|
|
+ sort.Slice(mappingList, func(i, j int) bool {
|
|
|
+ return mappingList[i].IsAxis > mappingList[j].IsAxis
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
for _, v := range mappingList {
|
|
|
//fmt.Println("v:", v.EdbInfoId)
|
|
|
item := new(chartEdbMappingModel.ChartEdbInfoMappingList)
|
|
@@ -884,7 +1699,7 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if chartType == 2 {
|
|
|
+ if chartType == 2 && v.IsAxis == 1 {
|
|
|
//latestDateStr := v.LatestDate.Format(utils.FormatDate) //实际数据的截止日期
|
|
|
latestDate := v.LatestDate
|
|
|
|
|
@@ -898,22 +1713,41 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
|
|
|
err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
|
|
|
return
|
|
|
}
|
|
|
- quarterDataList, tErr := GetSeasonEdbInfoDataListByXDateNong(result, latestDate, seasonExtraConfig, calendarPreYear)
|
|
|
+ quarterDataList, seasonXStartDateWithYearTmp, seasonXEndDateWithYearTmp, tErr := GetSeasonEdbInfoDataListByXDateNong(result, latestDate, seasonExtraConfig, calendarPreYear)
|
|
|
if tErr != nil {
|
|
|
err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
|
|
|
return
|
|
|
}
|
|
|
item.DataList = quarterDataList
|
|
|
+ seasonXStartDateWithYear = seasonXStartDateWithYearTmp
|
|
|
+ seasonXEndDateWithYear = seasonXEndDateWithYearTmp
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
- quarterDataList, tErr := GetSeasonEdbInfoDataListByXDate(dataList, latestDate, seasonExtraConfig)
|
|
|
+ quarterDataList, seasonXStartDateWithYearTmp, seasonXEndDateWithYearTmp, tErr := GetSeasonEdbInfoDataListByXDate(dataList, latestDate, seasonExtraConfig)
|
|
|
if tErr != nil {
|
|
|
err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
|
|
|
return
|
|
|
}
|
|
|
item.DataList = quarterDataList
|
|
|
+ seasonXStartDateWithYear = seasonXStartDateWithYearTmp
|
|
|
+ seasonXEndDateWithYear = seasonXEndDateWithYearTmp
|
|
|
}
|
|
|
+ } else if chartType == 2 && v.IsAxis == 0 { //季节性图的非横轴指标
|
|
|
+ newDataList := make([]*edbDataModel.EdbDataList, 0)
|
|
|
+ for _, v := range dataList {
|
|
|
+ dataTime, e := time.Parse(utils.FormatDate, v.DataTime)
|
|
|
+ if e != nil {
|
|
|
+ err = errors.New("季节性图处理右轴指标数据转换日期失败,Err:" + e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ seasonXStartDateWithYearT, _ := time.Parse(utils.FormatDate, seasonXStartDateWithYear)
|
|
|
+ seasonXEndDateWithYearT, _ := time.Parse(utils.FormatDate, seasonXEndDateWithYear)
|
|
|
+ if dataTime.Equal(seasonXStartDateWithYearT) || (dataTime.After(seasonXStartDateWithYearT) && dataTime.Before(seasonXEndDateWithYearT)) || dataTime.Equal(seasonXEndDateWithYearT) {
|
|
|
+ newDataList = append(newDataList, v)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ item.DataList = newDataList
|
|
|
} else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
|
|
|
//item.DataList = dataList
|
|
|
} else {
|
|
@@ -926,7 +1760,7 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
|
|
|
}
|
|
|
|
|
|
// GetSeasonEdbInfoDataListByXDate 季节性图的指标数据根据横轴展示
|
|
|
-func GetSeasonEdbInfoDataListByXDate(dataList []*edbDataModel.EdbDataList, latestDate time.Time, seasonExtraConfig string) (quarterDataListSort edbDataModel.QuarterDataList, err error) {
|
|
|
+func GetSeasonEdbInfoDataListByXDate(dataList []*edbDataModel.EdbDataList, latestDate time.Time, seasonExtraConfig string) (quarterDataListSort edbDataModel.QuarterDataList, xStartDateWithYear string, xEndDateWithYear string, err error) {
|
|
|
xStartDate := "01-01"
|
|
|
xEndDate := "12-31"
|
|
|
jumpYear := 0
|
|
@@ -976,7 +1810,7 @@ func GetSeasonEdbInfoDataListByXDate(dataList []*edbDataModel.EdbDataList, lates
|
|
|
return
|
|
|
}
|
|
|
endYear := lastDateT.Year()
|
|
|
- nowYear := time.Now().Year()
|
|
|
+ nowYear := endYear
|
|
|
chartLegendMaxYear := 0
|
|
|
dataMap := make(map[string]edbDataModel.QuarterXDateItem, 0)
|
|
|
|
|
@@ -1026,6 +1860,8 @@ func GetSeasonEdbInfoDataListByXDate(dataList []*edbDataModel.EdbDataList, lates
|
|
|
dataMap[name] = item
|
|
|
chartLegendMap[name] = idx
|
|
|
idx++
|
|
|
+ xStartDateWithYear = startStr
|
|
|
+ xEndDateWithYear = endStr
|
|
|
if lastDateT.Before(endT) {
|
|
|
//如果最新的日期在起始日之前,则跳出循环
|
|
|
break
|
|
@@ -1119,7 +1955,7 @@ func GetSeasonEdbInfoDataListByXDate(dataList []*edbDataModel.EdbDataList, lates
|
|
|
}
|
|
|
|
|
|
// GetSeasonEdbInfoDataListByXDateNong 季节性图的指标数据根据横轴选择农历时展示
|
|
|
-func GetSeasonEdbInfoDataListByXDateNong(result *edbDataModel.EdbDataResult, latestDate time.Time, seasonExtraConfig string, calendarPreYear int) (quarterDataListSort edbDataModel.QuarterDataList, err error) {
|
|
|
+func GetSeasonEdbInfoDataListByXDateNong(result *edbDataModel.EdbDataResult, latestDate time.Time, seasonExtraConfig string, calendarPreYear int) (quarterDataListSort edbDataModel.QuarterDataList, xStartDateWithYear string, xEndDateWithYear string, err error) {
|
|
|
xStartDate := "01-01"
|
|
|
xEndDate := "12-31"
|
|
|
jumpYear := 0
|
|
@@ -1171,7 +2007,7 @@ func GetSeasonEdbInfoDataListByXDateNong(result *edbDataModel.EdbDataResult, lat
|
|
|
return
|
|
|
}
|
|
|
endYear := lastDateT.Year()
|
|
|
- nowYear := time.Now().Year()
|
|
|
+ nowYear := endYear
|
|
|
chartLegendMaxYear := 0
|
|
|
dataMap := make(map[string]edbDataModel.QuarterXDateItem, 0)
|
|
|
|
|
@@ -1224,6 +2060,8 @@ func GetSeasonEdbInfoDataListByXDateNong(result *edbDataModel.EdbDataResult, lat
|
|
|
endTmpT = endT
|
|
|
chartLegendMap[showName] = idx
|
|
|
idx++
|
|
|
+ xStartDateWithYear = startStr
|
|
|
+ xEndDateWithYear = endStr
|
|
|
if lastDateT.Before(endT) {
|
|
|
//如果最新的日期在起始日之前,则跳出循环
|
|
|
break
|
|
@@ -2073,3 +2911,327 @@ func RadarChartData(mappingList []*chartEdbMappingModel.ChartEdbInfoMapping, edb
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
+// HandleDataByLinearRegressionToList 插值法补充数据(线性方程式)
|
|
|
+func HandleDataByLinearRegressionToList(edbInfoDataList []*edbDataModel.EdbDataList, handleDataMap map[string]float64) (dataTimeList []string, valueList []float64, err error) {
|
|
|
+ if len(edbInfoDataList) < 2 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ var startEdbInfoData *edbDataModel.EdbDataList
|
|
|
+ for _, v := range edbInfoDataList {
|
|
|
+ handleDataMap[v.DataTime] = v.Value
|
|
|
+ dataTimeList = append(dataTimeList, v.DataTime)
|
|
|
+ // 第一个数据就给过滤了,给后面的试用
|
|
|
+ if startEdbInfoData == nil {
|
|
|
+ startEdbInfoData = v
|
|
|
+ //startEdbInfoData.DataTime = startEdbInfoData.DataTime[:5]+ "01-01"
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取两条数据之间相差的天数
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
|
|
|
+ currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
|
|
|
+ betweenHour := int(currDataTime.Sub(startDataTime).Hours())
|
|
|
+ betweenDay := betweenHour / 24
|
|
|
+
|
|
|
+ // 如果相差一天,那么过滤
|
|
|
+ if betweenDay <= 1 {
|
|
|
+ startEdbInfoData = v
|
|
|
+ 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: v.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()
|
|
|
+ handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
|
|
|
+ dataTimeList = append(dataTimeList, tmpDataTime.Format(utils.FormatDate))
|
|
|
+ valueList = append(valueList, val)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ startEdbInfoData = v
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// HandleDataByLinearRegressionToList 保证生成365个数据点的线性插值法
|
|
|
+func HandleDataByLinearRegressionToListV2(edbInfoDataList []*edbDataModel.EdbDataList, handleDataMap map[string]float64) (dataTimeList []string, valueList []float64, err error) {
|
|
|
+ if len(edbInfoDataList) < 2 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保至少有两天数据来生成线性方程
|
|
|
+ if len(edbInfoDataList) < 2 {
|
|
|
+ err = errors.New("至少需要两天的数据来执行线性插值")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对数据按日期排序,确保顺序正确
|
|
|
+ sort.Slice(edbInfoDataList, func(i, j int) bool {
|
|
|
+ t1, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[i].DataTime, time.Local)
|
|
|
+ t2, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[j].DataTime, time.Local)
|
|
|
+ return t1.Before(t2)
|
|
|
+ })
|
|
|
+
|
|
|
+ startEdbInfoData := edbInfoDataList[0]
|
|
|
+ endEdbInfoData := edbInfoDataList[len(edbInfoDataList)-1]
|
|
|
+
|
|
|
+ // 计算起始和结束日期间实际的天数
|
|
|
+ startDate, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
|
|
|
+ endDate, _ := time.ParseInLocation(utils.FormatDate, endEdbInfoData.DataTime, time.Local)
|
|
|
+ actualDays := endDate.Sub(startDate).Hours() / 24
|
|
|
+
|
|
|
+ // 生成365个数据点,首先处理已有数据
|
|
|
+ for _, v := range edbInfoDataList {
|
|
|
+ handleDataMap[v.DataTime] = v.Value
|
|
|
+ dataTimeList = append(dataTimeList, v.DataTime)
|
|
|
+ valueList = append(valueList, v.Value)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果已有数据跨越天数不足365天,则对缺失的日期进行线性插值
|
|
|
+ if actualDays < 365 {
|
|
|
+ // 使用已有数据点生成线性方程(这里简化处理,实际可能需更细致处理边界情况)
|
|
|
+ var a, b float64
|
|
|
+ coordinateData := []utils.Coordinate{
|
|
|
+ {X: 1, Y: startEdbInfoData.Value},
|
|
|
+ {X: float64(len(edbInfoDataList)), Y: endEdbInfoData.Value},
|
|
|
+ }
|
|
|
+ a, b = utils.GetLinearResult(coordinateData)
|
|
|
+ if math.IsNaN(a) || math.IsNaN(b) {
|
|
|
+ err = errors.New("线性方程公式生成失败")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对剩余日期进行插值
|
|
|
+ for i := 1; i < 365; i++ {
|
|
|
+ day := startDate.AddDate(0, 0, i)
|
|
|
+ if _, exists := handleDataMap[day.Format(utils.FormatDate)]; !exists {
|
|
|
+ aDecimal := decimal.NewFromFloat(a)
|
|
|
+ xDecimal := decimal.NewFromInt(int64(i) + 1)
|
|
|
+ bDecimal := decimal.NewFromFloat(b)
|
|
|
+
|
|
|
+ val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
|
|
|
+ handleDataMap[day.Format(utils.FormatDate)] = val
|
|
|
+ dataTimeList = append(dataTimeList, day.Format(utils.FormatDate))
|
|
|
+ valueList = append(valueList, val)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// HandleDataByLinearRegressionToListV3 插值法补充数据(线性方程式)-直接补充指标起始日期间的所有数据
|
|
|
+func HandleDataByLinearRegressionToListV3(edbInfoDataList []*edbDataModel.EdbDataList, handleDataMap map[string]float64) (newEdbInfoDataList []*edbDataModel.EdbDataList, dataTimeList []string, valueList []float64, err error) {
|
|
|
+ if len(edbInfoDataList) < 2 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ var startEdbInfoData *edbDataModel.EdbDataList
|
|
|
+ for _, v := range edbInfoDataList {
|
|
|
+ handleDataMap[v.DataTime] = v.Value
|
|
|
+ newEdbInfoDataList = append(newEdbInfoDataList, v)
|
|
|
+ dataTimeList = append(dataTimeList, v.DataTime)
|
|
|
+ // 第一个数据就给过滤了,给后面的试用
|
|
|
+ if startEdbInfoData == nil {
|
|
|
+ startEdbInfoData = v
|
|
|
+ //startEdbInfoData.DataTime = startEdbInfoData.DataTime[:5]+ "01-01"
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取两条数据之间相差的天数
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
|
|
|
+ currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
|
|
|
+ betweenHour := int(currDataTime.Sub(startDataTime).Hours())
|
|
|
+ betweenDay := betweenHour / 24
|
|
|
+
|
|
|
+ // 如果相差一天,那么过滤
|
|
|
+ if betweenDay <= 1 {
|
|
|
+ startEdbInfoData = v
|
|
|
+ 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: v.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()
|
|
|
+ handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
|
|
|
+ dataTimeList = append(dataTimeList, tmpDataTime.Format(utils.FormatDate))
|
|
|
+ valueList = append(valueList, val)
|
|
|
+ newEdbInfoDataList = append(newEdbInfoDataList, &edbDataModel.EdbDataList{
|
|
|
+ EdbDataId: v.EdbDataId,
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ DataTime: tmpDataTime.Format(utils.FormatDate),
|
|
|
+ DataTimestamp: tmpDataTime.UnixNano() / 1e6,
|
|
|
+ Value: val,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ startEdbInfoData = v
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetEdbDataTbzForSeason 获取指标的同比值数据
|
|
|
+func GetEdbDataTbzForSeason(frequency string, tmpDataList []*edbDataModel.EdbDataList, startDateTime time.Time) (dataList []*edbDataModel.EdbDataList, minValue, maxValue float64, err error) {
|
|
|
+ dataList = make([]*edbDataModel.EdbDataList, 0)
|
|
|
+
|
|
|
+ // 数据处理
|
|
|
+ var dateArr []string
|
|
|
+ dataMap := make(map[string]*edbDataModel.EdbDataList)
|
|
|
+ for _, v := range tmpDataList {
|
|
|
+ dateArr = append(dateArr, v.DataTime)
|
|
|
+ dataMap[v.DataTime] = v
|
|
|
+ }
|
|
|
+ for _, av := range dateArr {
|
|
|
+ currentItem, ok := dataMap[av]
|
|
|
+ // 如果找不到当前日期的数据,那么终止当前循环,进入下一循环
|
|
|
+ if !ok {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ tmpItem := *currentItem
|
|
|
+ var isOk bool //是否计算出来结果
|
|
|
+
|
|
|
+ //当前日期
|
|
|
+ currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 如果存在开始日期,同时,当前日期早于开始日期,那么终止当前循环,进入下一循环
|
|
|
+ if !startDateTime.IsZero() && currentDate.Before(startDateTime) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ //上一年的日期
|
|
|
+ preDate := currentDate.AddDate(-1, 0, 0)
|
|
|
+ preDateStr := preDate.Format(utils.FormatDate)
|
|
|
+ if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
|
|
|
+ tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
|
|
|
+ isOk = true
|
|
|
+ } else {
|
|
|
+ if frequency == "月度" { //向上和向下,各找一个月
|
|
|
+ for i := 0; i <= 35; i++ {
|
|
|
+ nextDateDay := preDate.AddDate(0, 0, i)
|
|
|
+ nextDateDayStr := nextDateDay.Format(utils.FormatDate)
|
|
|
+ if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
|
|
|
+ tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
|
|
|
+ isOk = true
|
|
|
+ break
|
|
|
+ } else {
|
|
|
+ preDateDay := preDate.AddDate(0, 0, -i)
|
|
|
+ preDateDayStr := preDateDay.Format(utils.FormatDate)
|
|
|
+ if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
|
|
|
+ tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
|
|
|
+ isOk = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if frequency == "季度" || frequency == "年度" {
|
|
|
+ if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
|
|
|
+ tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
|
|
|
+ isOk = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ nextDateDay := preDate.AddDate(0, 0, 1)
|
|
|
+ nextDateDayStr := nextDateDay.Format(utils.FormatDate)
|
|
|
+
|
|
|
+ preDateDay := preDate.AddDate(0, 0, -1)
|
|
|
+ preDateDayStr := preDateDay.Format(utils.FormatDate)
|
|
|
+
|
|
|
+ for i := 0; i < 35; i++ {
|
|
|
+ if i >= 1 {
|
|
|
+ nextDateDay = nextDateDay.AddDate(0, 0, i)
|
|
|
+ nextDateDayStr = nextDateDay.Format(utils.FormatDate)
|
|
|
+ }
|
|
|
+ if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
|
|
|
+ tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
|
|
|
+ isOk = true
|
|
|
+ break
|
|
|
+ } else {
|
|
|
+ if i >= 1 {
|
|
|
+ preDateDay = preDate.AddDate(0, 0, -i)
|
|
|
+ preDateDayStr = nextDateDay.Format(utils.FormatDate)
|
|
|
+ }
|
|
|
+ if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
|
|
|
+ tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
|
|
|
+ isOk = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if isOk {
|
|
|
+ if tmpItem.Value > maxValue {
|
|
|
+ maxValue = tmpItem.Value
|
|
|
+ }
|
|
|
+ if tmpItem.Value < minValue {
|
|
|
+ minValue = tmpItem.Value
|
|
|
+ }
|
|
|
+ dataList = append(dataList, &tmpItem)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|