package models

import (
	"errors"
	"eta/eta_index_lib/utils"
	"fmt"
	"github.com/shopspring/decimal"
	"sort"
	"strconv"
	"strings"
	"time"
)

// EdbInfoData
// @Description: 指标数据
type EdbInfoData struct {
	EdbDataId int       `description:"数据ID"`
	DataTime  time.Time `description:"数据日期"`
	Value     float64   `description:"数据"`
}

// BaseCalculateBySearchData
// @Description: 基础的计算公式
type BaseCalculateBySearchData struct {
	DataList      []*EdbInfoSearchData
	Frequency     string `description:"需要转换的频度"`
	Formula       interface{}
	Calendar      string `description:"公历/农历"`
	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
	MoveFrequency string `description:"移动频度"`
	FromFrequency string `description:"来源的频度"`
	Source        int    `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
}

// BaseCalculate
// @Description: 基础的计算公式
type BaseCalculate struct {
	DataList      []*EdbInfoData
	Frequency     string `description:"需要转换的频度"`
	Formula       interface{}
	Calendar      string `description:"公历/农历"`
	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
	MoveFrequency string `description:"移动频度"`
	FromFrequency string `description:"来源的频度"`
	Source        int    `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
}

type BaseCalculateResp struct {
	DataMap  map[string]float64
	DateList []string
}

// Ljzzy
// @Description: 累计值转月
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:05:19
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Ljzzy() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)

	dataList := obj.DataList // 升序
	// 数据处理
	yearMap := make(map[int]map[int]*EdbInfoData)
	dataLen := len(dataList)
	for i := 0; i < dataLen; i++ {
		item := dataList[i]
		//日其中获取年
		itemDate := item.DataTime
		year := itemDate.Year()
		month := int(itemDate.Month())
		if monthMap, yok := yearMap[year]; yok {
			monthMap[month] = item
			yearMap[year] = monthMap
		} else {
			monthMap = make(map[int]*EdbInfoData)
			monthMap[month] = item
			yearMap[year] = monthMap
		}
	}

	// 开始计算
	for yk, yv := range yearMap {
		_, oneMonthOk := yv[1]
		_, twoMonthOk := yv[2]
		if !oneMonthOk && !twoMonthOk {
			continue
		}
		for i := 1; i <= 12; i++ {
			//fmt.Println(yk, i, yv[i])
			dataCurrentItem := yv[i]
			if dataCurrentItem == nil {
				continue
			}
			var date time.Time
			var val float64

			// 一二月单独处理
			if i == 1 || i == 2 {
				if _, mok := yv[1]; mok { //1月有值
					if i == 1 {
						date = dataCurrentItem.DataTime
						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
					}
					if i == 2 {
						dataOneItem := yv[1]
						date = dataCurrentItem.DataTime
						twoMonth := decimal.NewFromFloat(dataCurrentItem.Value)
						oneMonth := decimal.NewFromFloat(dataOneItem.Value)
						val, _ = twoMonth.Sub(oneMonth).Float64()
					}
				} else { //1月无值
					dataTwoItem := yv[2]
					if i == 1 {
						dateStr := strconv.Itoa(yk) + "-01-31"
						a := decimal.NewFromFloat(dataTwoItem.Value)
						b := decimal.NewFromFloat(2.0)
						val, _ = a.Div(b).Float64()

						date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
						if err != nil {
							return
						}

					}
					if i == 2 {
						//1月无值:1月=2月/2 (不管怎样,都要给1月赋值)
						{
							dateStr := strconv.Itoa(yk) + "-01-31"
							a := decimal.NewFromFloat(dataTwoItem.Value)
							b := decimal.NewFromFloat(2.0)
							val, _ = a.Div(b).Float64()
							date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
							if err != nil {
								return
							}
							dateDataMap[date] = val
						}
						//end 1月无值

						// 这是正常二月份的值
						date = dataCurrentItem.DataTime
						a := decimal.NewFromFloat(dataTwoItem.Value)
						b := decimal.NewFromFloat(2.0)
						val, _ = a.Div(b).Float64()
					}
				}
			} else {
				dataPreItem := yv[i-1]
				if dataCurrentItem != nil && dataPreItem != nil {
					date = dataCurrentItem.DataTime
					//val =  dataCurrentItem.Value - dataPreItem.Value
					a := decimal.NewFromFloat(dataCurrentItem.Value)
					b := decimal.NewFromFloat(dataPreItem.Value)
					val, _ = a.Sub(b).Float64()
				}
			}

			// 如果没有日期,那么就退出当前循环,进入下一个循环
			if date.IsZero() {
				continue
			}

			dateDataMap[date] = val
		}
	}

	return
}

// Ljzzj
// @Description: 累计值转季度
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:05:05
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Ljzzj() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList // 升序
	// 数据处理
	yearMap := make(map[int]map[int]*EdbInfoData)
	dataLen := len(dataList)
	for i := 0; i < dataLen; i++ {
		item := dataList[i]
		//日其中获取年
		itemDate := item.DataTime
		year := itemDate.Year()
		quarter := utils.MonthQuarterMap[int(itemDate.Month())]
		if quarterMap, yok := yearMap[year]; yok {
			quarterMap[quarter] = item
			yearMap[year] = quarterMap
		} else {
			quarterMap = make(map[int]*EdbInfoData)
			quarterMap[quarter] = item
			yearMap[year] = quarterMap
		}
	}

	// 开始计算
	for yk, yv := range yearMap {
		_, oneQuarterOk := yv[1]
		_, twoQuarterOk := yv[2]
		if !oneQuarterOk && !twoQuarterOk {
			continue
		}
		for i := 1; i <= 4; i++ {
			//fmt.Println(yk, i, yv[i])
			dataCurrentItem := yv[i]
			if dataCurrentItem == nil {
				continue
			}
			var date time.Time
			var val float64

			// 一二季度单独处理
			if i == 1 || i == 2 {
				if _, mok := yv[1]; mok { //第1个季度有值
					if i == 1 {
						date = dataCurrentItem.DataTime
						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
					}
					if i == 2 {
						dataOneItem := yv[1]
						date = dataCurrentItem.DataTime
						twoQuarter := decimal.NewFromFloat(dataCurrentItem.Value)
						oneQuarter := decimal.NewFromFloat(dataOneItem.Value)
						val, _ = twoQuarter.Sub(oneQuarter).Float64()
					}
				} else { //第1个季度无值
					dataTwoItem := yv[2]
					if i == 1 {
						dateStr := strconv.Itoa(yk) + "-03-31"
						a := decimal.NewFromFloat(dataTwoItem.Value)
						b := decimal.NewFromFloat(2.0)
						val, _ = a.Div(b).Float64()
						date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
						if err != nil {
							return
						}
					}
					if i == 2 {
						//第1个季度无值:第1个季度=第2个季度/2 (不管怎样,都要给1季度赋值)
						{
							dateStr := strconv.Itoa(yk) + "-03-31"
							a := decimal.NewFromFloat(dataTwoItem.Value)
							b := decimal.NewFromFloat(2.0)
							val, _ = a.Div(b).Float64()
							date, err = time.ParseInLocation(utils.FormatDate, dateStr, time.Local)
							if err != nil {
								return
							}

							dateDataMap[date] = val
						}
						//end 第1个季度无值

						date = dataCurrentItem.DataTime
						a := decimal.NewFromFloat(dataTwoItem.Value)
						b := decimal.NewFromFloat(2.0)
						val, _ = a.Div(b).Float64()
					}
				}
			} else {
				dataPreItem := yv[i-1]
				if dataCurrentItem != nil && dataPreItem != nil {
					date = dataCurrentItem.DataTime
					//val =  dataCurrentItem.Value - dataPreItem.Value
					a := decimal.NewFromFloat(dataCurrentItem.Value)
					b := decimal.NewFromFloat(dataPreItem.Value)
					val, _ = a.Sub(b).Float64()
				}
			}

			// 如果没有日期,那么就退出当前循环,进入下一个循环
			if date.IsZero() {
				continue
			}

			dateDataMap[date] = val
		}
	}

	return
}

// Tbz
// @Description: 同比值计算
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:04:59
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Tbz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList
	frequency := obj.FromFrequency

	//数据处理
	// 数据降序
	dataList = reverseSliceByDesc(dataList)

	var dateArr []time.Time
	dataMap := make(map[string]*EdbInfoData) // 避免因为时间戳导致的日期不对,还是用string来表示比较合适
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime.Format(utils.FormatDate)] = v
	}

	// 开始计算
	for _, currentDate := range dateArr {
		//当前日期
		currentDateStr := currentDate.Format(utils.FormatDate)
		currentItem, ok := dataMap[currentDateStr]
		if !ok {
			continue
		}

		// 找到的数据
		var findItem *EdbInfoData

		//上一年的日期
		preDate := currentDate.AddDate(-1, 0, 0)
		preDateStr := preDate.Format(utils.FormatDate)
		if findItem, ok = dataMap[preDateStr]; !ok { //上一年同期没找到
			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 { //上一年同期->下一个月找到
						break
					} else {
						preDateDay := preDate.AddDate(0, 0, -i)
						preDateDayStr := preDateDay.Format(utils.FormatDate)
						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
							break
						}
					}
				}
			} else if frequency == "季度" || frequency == "年度" {
				if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
					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 { //上一年同期->下一个月找到
						break
					} else {
						if i >= 1 {
							preDateDay = preDateDay.AddDate(0, 0, -i)
							preDateDayStr = preDateDay.Format(utils.FormatDate)
						}
						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
							break
						}
					}
				}
			}

		}

		// 如果没找到数据
		if findItem == nil {
			continue
		}

		dateDataMap[currentDate] = tbzDiv(currentItem.Value, findItem.Value)
	}

	return
}

// tbzDiv
// @Description: 同比值计算
// @author: Roc
// @datetime2023-11-02 16:29:14
// @param a float64
// @param b float64
// @return float64
func tbzDiv(a, b float64) float64 {
	var val float64
	if b != 0 {
		af := decimal.NewFromFloat(a)
		bf := decimal.NewFromFloat(b)
		val, _ = af.Div(bf).Sub(decimal.NewFromFloat(1)).RoundCeil(4).Float64()
	}
	return val
}

// Tcz
// @Description: 计算同差值
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:04:51
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Tcz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList // 降序
	frequency := obj.FromFrequency

	// 数据处理
	// 数据降序
	dataList = reverseSliceByDesc(dataList)
	var dateArr []time.Time
	dataMap := make(map[string]*EdbInfoData)
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime.Format(utils.FormatDate)] = v
	}

	// 开始计算
	for _, currentDate := range dateArr {
		//当前日期
		currentItem, ok := dataMap[currentDate.Format(utils.FormatDate)]
		if !ok {
			continue
		}

		// 找到的数据
		var findItem *EdbInfoData

		//上一年的日期
		preDate := currentDate.AddDate(-1, 0, 0)
		preDateStr := preDate.Format(utils.FormatDate)
		if findItem, ok = dataMap[preDateStr]; !ok {
			//上一年同期没找到
			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 { //上一年同期->下一个月找到
						break
					} else {
						preDateDay := preDate.AddDate(0, 0, -i)
						preDateDayStr := preDateDay.Format(utils.FormatDate)
						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
							break
						}
					}
				}
			} else if frequency == "季度" || frequency == "年度" {
				if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
					break
				}
			} else {
				for i := 0; i < 35; i++ {
					nextDateDay := preDate.AddDate(0, 0, i)
					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
						break
					} else {
						preDateDay := preDate.AddDate(0, 0, -i)
						preDateDayStr := preDateDay.Format(utils.FormatDate)
						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
							break
						}
					}
				}
			}
		}

		// 如果没找到数据
		if findItem == nil {
			continue
		}

		dateDataMap[currentDate] = tczSub(currentItem.Value, findItem.Value)
	}

	return
}

// tczSub
// @Description: 计算同差值
// @author: Roc
// @datetime2023-11-02 18:01:46
// @param a float64
// @param b float64
// @return float64
func tczSub(a, b float64) float64 {
	af := decimal.NewFromFloat(a)
	bf := decimal.NewFromFloat(b)
	val, _ := af.Sub(bf).RoundCeil(4).Float64()
	return val
}

// Nszydpjjs
// @Description: N数值移动平均数计算
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:17:38
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Nszydpjjs() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	fromDataList := obj.DataList
	nVal := fmt.Sprint(obj.Formula)
	formulaInt, err := strconv.Atoi(nVal)
	if err != nil {
		return
	}

	// 数据处理

	// 数据降序
	fromDataList = reverseSliceByDesc(fromDataList)

	var fromDateArr []time.Time
	fromDataMap := make(map[time.Time]*EdbInfoData)
	for _, v := range fromDataList {
		fromDateArr = append(fromDateArr, v.DataTime)
		fromDataMap[v.DataTime] = v
	}

	arrLen := len(fromDateArr)
	for ak, currentDate := range fromDateArr {
		//处理第一个值
		var valArr []float64
		if findItem, ok := fromDataMap[currentDate]; ok {
			valArr = append(valArr, findItem.Value)
		} else {
			continue
		}
		if ak+1 != arrLen {
			//处理除第一个值之外的N-1个值
			for i := 1; i < formulaInt; i++ {
				arrIndex := ak + i
				if arrIndex >= arrLen {
					break
				}
				arrVal := fromDateArr[arrIndex]
				if findItem, ok := fromDataMap[arrVal]; ok {
					valArr = append(valArr, findItem.Value)
				} else {
					continue
				}
			}
		}
		valArrLen := len(valArr)
		//var totalVal float64
		totalVal := decimal.NewFromFloat(0.00)
		for _, v := range valArr {
			newDecimal := decimal.NewFromFloat(v)
			totalVal = totalVal.Add(newDecimal)
		}
		af := totalVal //decimal.NewFromFloat(totalVal)
		bf := decimal.NewFromFloat(float64(valArrLen))
		val, _ := af.Div(bf).RoundCeil(4).Float64()

		dateDataMap[currentDate] = val
	}

	return
}

// Hbz
// @Description: 环比值计算
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:28:24
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Hbz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList
	nVal := fmt.Sprint(obj.Formula)
	formulaInt, err := strconv.Atoi(nVal)
	if err != nil {
		return
	}

	// 数据处理
	// 数据降序
	dataList = reverseSliceByDesc(dataList)

	var dateArr []time.Time
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
	}

	// 数据计算
	dataLen := len(dataList)
	//fmt.Println("dataLen:", dataLen)
	for i := 0; i < dataLen; i++ {
		j := i + formulaInt
		if j < dataLen {
			//当期
			currentItem := dataList[i]
			preItem := dataList[j]

			// 当期和上期没有数据
			if currentItem == nil || preItem == nil {
				continue
			}

			// 开始计算
			val, ok := hbzDiv(currentItem.Value, preItem.Value)
			// 计算失败
			if !ok {
				continue
			}

			dateDataMap[currentItem.DataTime] = val
		}
	}

	return
}

// hbzDiv
// @Description: 环比值计算,current:当期,pre:上期 公式: (当期-上期)/上期
// @author: Roc
// @datetime2023-11-02 18:20:11
// @param current float64
// @param pre float64
// @return val float64
// @return ok bool
func hbzDiv(current, pre float64) (val float64, ok bool) {
	if pre == 0 {
		return
	}
	currentVal := decimal.NewFromFloat(current)
	preVal := decimal.NewFromFloat(pre)
	val, _ = currentVal.Sub(preVal).Div(preVal).RoundCeil(4).Float64()
	//valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)
	ok = true

	return
}

// Hcz
// @Description: 计算环差值数据
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:33:20
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Hcz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList
	nVal := fmt.Sprint(obj.Formula)
	formulaInt, err := strconv.Atoi(nVal)
	if err != nil {
		return
	}

	// 数据处理
	// 数据降序
	dataList = reverseSliceByDesc(dataList)

	var dateArr []time.Time
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
	}

	dataLen := len(dataList)
	fmt.Println("dataLen:", dataLen)
	for i := 0; i < dataLen; i++ {
		j := i + formulaInt
		if j < dataLen {
			//当期
			currentItem := dataList[i]
			preItem := dataList[j]

			// 当期和上期没有数据
			if currentItem == nil || preItem == nil {
				continue
			}

			// 开始计算
			val := hczDiv(currentItem.Value, preItem.Value)

			dateDataMap[currentItem.DataTime] = val
		}
	}

	return
}

// hczDiv
// @Description: 环差值计算,current:当期,pre:上期 公式:当期-上期
// @author: Roc
// @datetime2023-11-02 18:33:07
// @param current float64
// @param pre float64
// @return float64
func hczDiv(current, pre float64) float64 {
	currentVal := decimal.NewFromFloat(current)
	preVal := decimal.NewFromFloat(pre)
	val, _ := currentVal.Sub(preVal).RoundCeil(4).Float64()
	//valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)

	return val
}

// UpFrequency
// @Description: 升频计算
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:43:03
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) UpFrequency() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList

	// 数据处理
	var dateArr []time.Time
	dataMap := make(map[time.Time]*EdbInfoData)
	fromDataMap := make(map[time.Time]float64)
	//来源指指标数据
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime] = v
		fromDataMap[v.DataTime] = v.Value
	}

	if obj.FromFrequency == `日度` {
		errMsg = `不能选择日度指标`
		err = errors.New(errMsg)
		return
	}

	// 数据计算
	dataLen := len(dataList)
	for i := 0; i < dataLen; i++ {
		//当期
		currentItem := dataList[i]
		currentDate := currentItem.DataTime
		var day int
		var preItem *EdbInfoData
		var preDate time.Time
		if i == 0 {
			day = int(time.Now().Sub(currentDate).Hours() / float64(24))
			preDate = time.Now()
		} else {
			j := i - 1
			if j < dataLen {
				preItem = dataList[j]
				day = int(preItem.DataTime.Sub(currentDate).Hours() / float64(24))
				utils.FileLog.Info("preItem.DataTime:" + preItem.DataTime.Format(utils.FormatDate) + ";currentItem.DataTime" + currentItem.DataTime.Format(utils.FormatDate))
			}
		}
		for k := 0; k <= day; k++ {
			needDay := preDate.AddDate(0, 0, -k)
			dateDataMap[needDay] = currentItem.Value
		}
		dateDataMap[currentItem.DataTime] = currentItem.Value
	}

	return
}

// DownFrequency
// @Description: 降频计算
// @author: Roc
// @receiver obj
// @datetime2023-11-02 18:51:26
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) DownFrequency() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList
	edbFrequency := obj.Frequency
	formula := obj.Formula.(string)

	if !CheckFrequency(obj.FromFrequency, obj.Frequency) {
		errMsg = "频度异常,不允许低频降频到高频"
		err = errors.New(errMsg)
		return
	}

	// 数据处理
	var dateArr []time.Time
	dataMap := make(map[time.Time]*EdbInfoData)
	fromDataMap := make(map[time.Time]float64)
	//来源指指标数据
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime] = v
		fromDataMap[v.DataTime] = v.Value
	}

	// 数据计算
	dataLen := len(dataList)
	if dataLen <= 0 {
		return
	}
	startDataTime := dataList[0].DataTime
	endDataTime := dataList[dataLen-1].DataTime

	var lastValue float64     // 最近的值
	var nextEndDate time.Time // 下一个节点的日期
	weekDayDataList := make([]float64, 0)
	for tmpStartDataTime := startDataTime; !tmpStartDataTime.After(endDataTime); tmpStartDataTime = tmpStartDataTime.AddDate(0, 0, 1) {
		// 将当前数据加入到 weekDayDataList
		if tmpData, ok := dataMap[tmpStartDataTime]; ok {
			tmpValue := decimal.NewFromFloat(tmpData.Value)
			tmpValueFloat, _ := tmpValue.Round(4).Float64()
			weekDayDataList = append(weekDayDataList, tmpValueFloat)
		}
		// 如果下个节点的日期不存在,那么就先给赋值(兼容时间区间内只有一组数据的情况)
		if nextEndDate.IsZero() {
			nextEndDate = utils.GetFrequencyEndDay(tmpStartDataTime, edbFrequency)
		}

		// 日期处理过滤
		switch edbFrequency {
		case "周度":
			if tmpStartDataTime.Weekday() != 0 {
				//不是周日,代表需要进入下一个循环获取数据并计算
				continue
			} else {
				//记录下一个结束节点的日期
				nextEndDate = tmpStartDataTime.AddDate(0, 0, 7)
			}
		case "旬度":
			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
			if nextDay.Day() != 1 && nextDay.Day() != 11 && nextDay.Day() != 21 {
				//不是每月10、20、最后一天,代表需要进入下一个循环获取数据并计算
				continue
			} else {
				//记录下一个结束节点的日期
				if nextDay.Day() == 1 || nextDay.Day() == 11 {
					//月初或者月末的时候,加10天就好了
					nextEndDate = nextDay.AddDate(0, 0, 9)
				} else {
					tmpNextMonth := nextDay.AddDate(0, 1, 0)
					nextEndDate = time.Date(tmpNextMonth.Year(), tmpNextMonth.Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
				}
			}
		case "月度":
			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
			if nextDay.Day() != 1 {
				//不是每月最后一天,代表需要进入下一个循环获取数据并计算
				continue
			} else {
				//记录下一个结束节点的日期
				nextEndDate = nextDay.AddDate(0, 1, -1)
			}
		case "季度":
			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
			if (nextDay.Month() == 1 || nextDay.Month() == 4 || nextDay.Month() == 7 || nextDay.Month() == 10) && nextDay.Day() == 1 {
				//记录下一个结束节点的日期
				nextEndDate = nextDay.AddDate(0, 3, -1)
			} else {
				//不是3,6,9,12 月份的最后一天,代表需要进入下一个循环获取数据并计算
				continue
			}
		case "年度":
			if tmpStartDataTime.Month() == 12 && tmpStartDataTime.Day() == 31 {
				//记录下一个结束节点的日期
				nextEndDate = tmpStartDataTime.AddDate(1, 0, 0)
			} else {
				//不是每年的12-31日,代表需要进入下一个循环获取数据并计算
				continue
			}
		default:
			err = errors.New("错误的频度:" + edbFrequency)
			return
		}

		// 当前时间段内的数据计算,得出实际值
		var currVal float64
		lenWeekDayDataList := len(weekDayDataList)
		// 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
		if len(weekDayDataList) <= 0 {
			currVal = lastValue
		} else {
			if formula == "期末值" {
				currVal = weekDayDataList[lenWeekDayDataList-1]
			} else {
				// 平均值
				sumValDeci := decimal.NewFromFloat(0)
				for _, v := range weekDayDataList {
					tmpValDeci := decimal.NewFromFloat(v)
					sumValDeci = sumValDeci.Add(tmpValDeci)
				}
				lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
				currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
			}
		}

		// 赋值
		dateDataMap[tmpStartDataTime] = currVal

		// 一轮结束后,数据清空
		weekDayDataList = make([]float64, 0)
	}

	// 最后已有的日期处理完成后,需要对剩余不在时间段内的数据做处理
	if len(weekDayDataList) > 0 {
		// 当前时间段内的数据计算,得出实际值
		var currVal float64
		lenWeekDayDataList := len(weekDayDataList)
		// 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
		if len(weekDayDataList) < 0 {
			currVal = lastValue
		} else {
			if formula == "期末值" {
				currVal = weekDayDataList[lenWeekDayDataList-1]
			} else {
				// 平均值
				sumValDeci := decimal.NewFromFloat(0)
				for _, v := range weekDayDataList {
					tmpValDeci := decimal.NewFromFloat(v)
					sumValDeci = sumValDeci.Add(tmpValDeci)
				}
				lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
				currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
			}
		}

		// 赋值
		dateDataMap[nextEndDate] = currVal
	}

	return
}

// TimeShift
// @Description: 时间移位计算
// @author: Roc
// @receiver obj
// @datetime2023-11-03 13:19:07
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) TimeShift() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList

	nVal := fmt.Sprint(obj.Formula)
	formulaInt, err := strconv.Atoi(nVal)
	if err != nil {
		return
	}

	moveType := obj.MoveType
	moveFrequency := obj.MoveFrequency

	// 数据处理
	var dateArr []time.Time
	dataMap := make(map[time.Time]*EdbInfoData)
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime] = v
	}

	var shiftDay int
	switch moveFrequency {
	case "天":
		shiftDay = formulaInt
	case "周":
		shiftDay = formulaInt * 7
	case "月":
		shiftDay = formulaInt * 30
	case "季":
		shiftDay = formulaInt * 90
	case "年":
		shiftDay = formulaInt * 365
	default:
		shiftDay = formulaInt
	}

	if moveType == 2 {
		shiftDay = -shiftDay
	}

	dataLen := len(dataList)
	for i := 0; i < dataLen; i++ {
		//当期
		currentItem := dataList[i]
		currentDate := currentItem.DataTime

		newDate := currentDate.AddDate(0, 0, shiftDay)

		val, _ := decimal.NewFromFloat(currentItem.Value).RoundCeil(4).Float64()

		dateDataMap[newDate] = val
	}

	return
}

// Cjjx
// @Description: 超季节性计算
// @author: Roc
// @receiver obj
// @datetime2023-11-03 13:28:23
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Cjjx() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList

	nVal := fmt.Sprint(obj.Formula)
	formulaInt, err := strconv.Atoi(nVal)
	if err != nil {
		return
	}

	calendar := obj.Calendar

	// 数据处理
	var dateArr []time.Time
	dataMap := make(map[time.Time]*EdbInfoData)
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime] = v
	}

	// 通过插值法补全所有数据(包含周末)
	handleDataMap := make(map[time.Time]float64)
	_, err = HandleDataByLinearRegressionByTime(dataList, handleDataMap)
	if err != nil {
		return
	}

	// 每个年份的日期数据需要平移的天数
	moveDayMap := make(map[int]int, 0) // 每个年份的春节公历
	var lastDataDay time.Time
	if len(dataList) > 0 {
		lastDataDay = dataList[0].DataTime
	}

	// 数据计算
	for _, currentDate := range dateArr {
		// 如果遇到闰二月,如2.29,去掉该天数据
		if strings.Contains(currentDate.Format(utils.FormatDate), "02-29") {
			continue
		}

		//农历的超季节性运算,只计算11月--次年5月,分段计算,与数据区间和N数值有关
		if calendar == "农历" && currentDate.Month() > 5 && currentDate.Month() < 11 {
			continue
		}

		currentItem, ok := dataMap[currentDate]
		// 找不到数据就退出当前循环,进入下一循环
		if !ok {
			continue
		}

		pastValueList := make([]float64, 0)                      // 过去几期的数据
		pastValueList = append(pastValueList, currentItem.Value) //当前日期

		for i := 1; i < formulaInt; i++ {
			//前几年当天公历的日期
			historyPreDate := currentDate.AddDate(-i, 0, 0)
			moveDay := 0
			if calendar == "农历" {
				if tmpMoveDay, ok := moveDayMap[historyPreDate.Year()]; !ok {
					moveDay, err = getMoveDay(lastDataDay, historyPreDate)
					if err != nil {
						return
					}
				} else {
					moveDay = tmpMoveDay
				}

				// 移动天数到对应农历 的 公历 日期
				historyPreDate = historyPreDate.AddDate(0, 0, moveDay)
			}

			if tmpValue, ok := handleDataMap[historyPreDate]; ok { //上一年同期找到
				pastValueList = append(pastValueList, tmpValue)
			}
		}

		if len(pastValueList) == formulaInt {
			val, ok := cjjxSub(currentItem.Value, pastValueList)
			if !ok {
				continue
			}
			dateDataMap[currentDate] = val
		}
	}

	return
}

// cjjxSub
// @Description: 超季节性计算
// @author: Roc
// @datetime2023-11-03 13:25:49
// @param currValue float64
// @param pastValue []float64
// @return value float64
// @return ok bool
func cjjxSub(currValue float64, pastValue []float64) (value float64, ok bool) {
	num := len(pastValue)
	if num == 0 {
		return
	}
	numDecimal := decimal.NewFromInt(int64(num))

	af := decimal.NewFromFloat(currValue)
	bf := decimal.NewFromFloat(pastValue[0])

	for k := 1; k < num; k++ {
		tmpVal := decimal.NewFromFloat(pastValue[k])
		bf = bf.Add(tmpVal)
	}
	value, _ = af.Sub(bf.Div(numDecimal)).RoundCeil(4).Float64()
	ok = true

	return
}

// Annualized
// @Description: 年化计算
// @author: Roc
// @receiver obj
// @datetime2023-11-03 13:34:32
// @param to orm.TxOrmer
// @param edbInfoId int
// @param source int
// @param fromEdbInfo *EdbInfo
// @param edbCode string
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Annualized() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	fromDataList := obj.DataList
	lenFromDataList := len(fromDataList)
	// 如果来源指标没有数据,那么就直接返回得了
	if lenFromDataList <= 0 {
		return
	}

	// 数据处理
	// 插值法数据处理
	handleDataMap := make(map[time.Time]float64)
	_, err = HandleDataByLinearRegressionByTime(fromDataList, handleDataMap)
	if err != nil {
		return
	}

	// 每年的最后一天的数据值
	yearLastValMap := make(map[int]float64)
	startDataTime := fromDataList[0].DataTime
	endDataTime := fromDataList[lenFromDataList-1].DataTime
	for i := startDataTime.Year(); i <= endDataTime.Year(); i++ {
		tmpDate := time.Date(i, 12, 31, startDataTime.Hour(), startDataTime.Minute(), startDataTime.Second(), startDataTime.Nanosecond(), time.Local)
		if tmpVal, ok := handleDataMap[tmpDate]; ok {
			yearLastValMap[i] = tmpVal
		}
	}

	// 数据计算
	// 遍历来源指标数据
	for _, v := range fromDataList {
		currDate := v.DataTime

		perValMap := make(map[time.Time]float64)
		//前3年当日的数据
		for i := 1; i <= 3; i++ {
			tmpDateTime := currDate.AddDate(-i, 0, 0)
			if tmpVal, ok := handleDataMap[tmpDateTime]; ok {
				perValMap[tmpDateTime] = tmpVal
			}
		}
		lenPerValMap := len(perValMap)
		// 如果数据少于2年,那么就不参与计算,结束当前循环,进入下一个循环
		if lenPerValMap < 2 {
			continue
		}

		// N年 当前值占全年比重 的值列表
		divValList := make([]decimal.Decimal, 0)
		for tmpDateTime, tmpVal := range perValMap {
			yearLastVal, ok2 := yearLastValMap[tmpDateTime.Year()]
			// 如果当年最后一天没有数据
			if !ok2 {
				continue
			}

			// 当前值占全年比重
			tmpYearLastVal := decimal.NewFromFloat(yearLastVal)
			if tmpYearLastVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
				continue
			}
			divVal := decimal.NewFromFloat(tmpVal).Div(tmpYearLastVal)
			divValList = append(divValList, divVal)
		}

		lenDivValList := len(divValList)
		// 如果 N年 当前值占全年比重 的值 小于 2个,那么就不参与计算,结束当前循环,进入下一个循环
		if lenDivValList < 2 {
			continue
		}

		divValSum := decimal.NewFromFloat(0)
		for _, divVal := range divValList {
			divValSum = divValSum.Add(divVal)
		}

		// 当前计算出来的结果
		tmpDivVal := divValSum.Div(decimal.NewFromInt(int64(lenDivValList)))
		if tmpDivVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
			continue
		}
		currVal, _ := decimal.NewFromFloat(v.Value).Div(tmpDivVal).Round(4).Float64()

		dateDataMap[currDate] = currVal
	}

	return
}

// Ljz
// @Description: 累计值
// @author: Roc
// @receiver obj
// @datetime2023-11-03 13:49:17
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Ljz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList
	frequency := obj.Frequency         //需要变更的频度
	fromFrequency := obj.FromFrequency //来源的频度
	// 数据处理
	var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
	// 周度数据需要先变成日度的
	if fromFrequency == `周度` {
		isWeekData = true
	}

	fromEdbDataMap := make(map[time.Time]float64)
	if isWeekData {
		dataList, err = HandleDataByLinearRegressionByTime(dataList, fromEdbDataMap)
		if err != nil {
			return
		}
	}

	//日度转周度:日期选周五,计算上周六到本周五的日度值的加总,最新日期为最新值对应的周五。
	//日度转月度:日期选每个月最后一天,计算当月所有日度值的加总,最新日期为最新值对应当月最后一天。
	//日度转季度、年度:方法类似转月度。
	//周度转月度/季度/年度:将周度值转成日度,空值用插值法插值,计算当月/当季/当年所有值的加总,然后除以7。
	//月度转季度/年度: 当季/当年月度值相加。

	dateList := make([]time.Time, 0)
	valueMap := make(map[time.Time]float64)
	switch frequency {
	case "年度":
		yearMap := make(map[int]float64)
		yearList := make([]int, 0)
		for _, item := range dataList {
			year := item.DataTime.Year()
			yearVal, ok := yearMap[year]
			if ok {
				yearMap[year] = item.Value + yearVal
			} else {
				yearList = append(yearList, year)
				yearMap[year] = item.Value
			}
		}
		for _, v := range yearList {
			currTime := time.Date(v, 12, 31, 0, 0, 0, 0, time.Local)
			dateList = append(dateList, currTime)
			valueMap[currTime] = yearMap[v]
		}
	case "半年度":
		yearMonthMap := make(map[string]float64)
		yearMonthList := make([]string, 0)
		for _, item := range dataList {
			itemDate := item.DataTime
			year := itemDate.Year()
			var tmpK string
			if itemDate.Month() <= 6 {
				tmpK = fmt.Sprint(year, "06")
			} else {
				tmpK = fmt.Sprint(year, "12")
			}

			yearVal, ok := yearMonthMap[tmpK]
			if ok {
				yearMonthMap[tmpK] = item.Value + yearVal
			} else {
				yearMonthList = append(yearMonthList, tmpK)
				yearMonthMap[tmpK] = item.Value
			}
		}
		for _, v := range yearMonthList {
			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
			if tmpErr != nil {
				err = tmpErr
				return
			}
			currTime = currTime.AddDate(0, 1, -1)
			dateList = append(dateList, currTime)
			valueMap[currTime] = yearMonthMap[v]
		}
	case "季度":
		yearMonthMap := make(map[string]float64)
		yearMonthList := make([]string, 0)
		for _, item := range dataList {
			itemDate := item.DataTime
			year := itemDate.Year()
			var tmpK string
			if itemDate.Month() <= 3 {
				tmpK = fmt.Sprint(year, "03")
			} else if itemDate.Month() <= 6 {
				tmpK = fmt.Sprint(year, "06")
			} else if itemDate.Month() <= 9 {
				tmpK = fmt.Sprint(year, "09")
			} else {
				tmpK = fmt.Sprint(year, "12")
			}

			yearVal, ok := yearMonthMap[tmpK]
			if ok {
				yearMonthMap[tmpK] = item.Value + yearVal
			} else {
				yearMonthList = append(yearMonthList, tmpK)
				yearMonthMap[tmpK] = item.Value
			}
		}
		for _, v := range yearMonthList {
			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
			if tmpErr != nil {
				err = tmpErr
				return
			}
			currTime = currTime.AddDate(0, 1, -1)
			dateList = append(dateList, currTime)
			valueMap[currTime] = yearMonthMap[v]
		}
	case "月度":
		yearMonthMap := make(map[string]float64)
		yearMonthList := make([]string, 0)
		for _, item := range dataList {
			itemDate := item.DataTime
			year := itemDate.Year()
			var tmpK string
			tmpK = fmt.Sprint(year*100 + int(itemDate.Month()))

			yearVal, ok := yearMonthMap[tmpK]
			if ok {
				yearMonthMap[tmpK] = item.Value + yearVal
			} else {
				yearMonthList = append(yearMonthList, tmpK)
				yearMonthMap[tmpK] = item.Value
			}
		}
		for _, v := range yearMonthList {
			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
			if tmpErr != nil {
				err = tmpErr
				return
			}
			currTime = currTime.AddDate(0, 1, -1)
			dateList = append(dateList, currTime)
			valueMap[currTime] = yearMonthMap[v]
		}
	case "旬度":
		tmpDateDataMap := make(map[time.Time]float64)
		tmpDateList := make([]time.Time, 0)
		for _, item := range dataList {
			itemDate := item.DataTime
			dayInt := itemDate.Year()*100 + int(itemDate.Month())
			var currTime time.Time
			if itemDate.Month() <= 10 {
				tmpK := fmt.Sprint(dayInt*100, "10")
				currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
				if err != nil {
					return
				}

			} else if itemDate.Month() <= 20 {
				tmpK := fmt.Sprint(dayInt*100, "20")
				currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
				if err != nil {
					return
				}
			} else {
				currTime, err = time.ParseInLocation(utils.FormatYearMonthUnSpace, fmt.Sprint(dayInt), time.Local)
				if err != nil {
					return
				}
				currTime = currTime.AddDate(0, 1, -1)
			}

			yearVal, ok := tmpDateDataMap[currTime]
			if ok {
				tmpDateDataMap[currTime] = item.Value + yearVal
			} else {
				tmpDateList = append(tmpDateList, currTime)
				tmpDateDataMap[currTime] = item.Value
			}
		}
		for _, currTime := range tmpDateList {
			dateList = append(dateList, currTime)
			valueMap[currTime] = tmpDateDataMap[currTime]
		}
	case "周度":
		tmpDateDataMap := make(map[time.Time]float64)
		tmpDateList := make([]time.Time, 0)
		for _, item := range dataList {
			itemDate := item.DataTime
			var currTime time.Time
			// 周六周日,这是下一个周五的数据
			if itemDate.Weekday() == 0 {
				currTime = itemDate.AddDate(0, 0, 5)
			} else if itemDate.Weekday() == 6 {
				currTime = itemDate.AddDate(0, 0, 6)
			} else {
				currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
			}

			yearVal, ok := tmpDateDataMap[currTime]
			if ok {
				tmpDateDataMap[currTime] = item.Value + yearVal
			} else {
				tmpDateList = append(tmpDateList, currTime)
				tmpDateDataMap[currTime] = item.Value
			}
		}
		for _, currTime := range tmpDateList {
			dateList = append(dateList, currTime)
			valueMap[currTime] = tmpDateDataMap[currTime]
		}
	default:
		err = errors.New("错误的频度")
		return

	}

	// 数据计算
	for _, currTime := range dateList {
		tmpVal, ok2 := valueMap[currTime]
		if !ok2 {
			err = errors.New("数据异常,date:" + currTime.Format(utils.FormatDate))
			return
		}
		var saveValue float64
		if isWeekData { //周度指标转的话,最后结果要除以7
			saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
		} else {
			saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
		}

		dateDataMap[currTime] = saveValue
	}

	return
}

// LjzNczj
// @Description:年初至今累计值计算
// @author: Roc
// @receiver obj
// @datetime2023-11-03 13:55:44
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) LjzNczj() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList
	frequency := obj.Frequency         //需要变更的频度
	fromFrequency := obj.FromFrequency //来源的频度

	// 数据处理
	var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
	// 周度数据需要先变成日度的
	if fromFrequency == `周度` {
		isWeekData = true
	}

	fromEdbDataMap := make(map[time.Time]float64)
	if isWeekData {
		dataList, err = HandleDataByLinearRegressionByTime(dataList, fromEdbDataMap)
		if err != nil {
			return
		}
	}

	//日度数据年初至今:日期同原日度数据。将每年1月1日(含)到日度数据所在日期含间的日度值,进行加总。
	//周度数据年初至今:日期同原周度数据。将周度值转成日度频率,空值用插值法插值,然后算法同日度年度至今,再除以7
	//月度/季度数据年初至今:日期同原月度/季度数据,将每年1月1日(含)到月度数据所在日期(含)之间的月度/季度值,进行加总
	//以此类推

	dateList := make([]time.Time, 0)
	valueMap := make(map[time.Time]float64)
	yearMap := make(map[int]float64)
	switch frequency {
	case "周度":
		tmpDateDataMap := make(map[time.Time]float64)
		tmpDateList := make([]time.Time, 0)
		for _, item := range dataList {
			itemDate := item.DataTime
			var currTime time.Time
			// 周六周日,这是下一个周五的数据
			if itemDate.Weekday() == 0 {
				currTime = itemDate.AddDate(0, 0, 5)
			} else if itemDate.Weekday() == 6 {
				currTime = itemDate.AddDate(0, 0, 6)
			} else {
				currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
			}

			year := itemDate.Year()
			yearVal, ok := yearMap[year]
			if ok {
				yearMap[year] = item.Value + yearVal
			} else {
				yearMap[year] = item.Value
			}

			if itemDate.Equal(currTime) {
				tmpDateDataMap[itemDate] = yearMap[year]
				tmpDateList = append(tmpDateList, itemDate)
			}
		}
		for _, currTime := range tmpDateList {
			dateList = append(dateList, currTime)
			valueMap[currTime] = tmpDateDataMap[currTime]
		}
	default:
		for _, item := range dataList {
			itemDate := item.DataTime
			year := itemDate.Year()
			yearVal, ok := yearMap[year]
			if ok {
				yearMap[year] = item.Value + yearVal
			} else {
				yearMap[year] = item.Value
			}
			valueMap[itemDate] = yearMap[year]
			dateList = append(dateList, itemDate)
		}

	}

	// 数据计算
	for _, currTime := range dateList {
		tmpVal, ok2 := valueMap[currTime]
		if !ok2 {
			err = errors.New("数据异常,date:" + currTime.Format(utils.FormatDate))
			return
		}
		var saveValue float64
		if isWeekData { //周度指标转的话,最后结果要除以7
			saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
		} else {
			saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
		}

		dateDataMap[currTime] = saveValue
	}

	return
}

// ExponentialSmoothing
// @Description: 指数修匀计算
// @author: Roc
// @receiver obj
// @datetime2023-11-03 14:07:47
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) ExponentialSmoothing() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList
	formula := obj.Formula.(string) // alpha值

	alpha, _ := strconv.ParseFloat(formula, 64)
	if alpha <= 0 || alpha >= 1 {
		err = fmt.Errorf("alpha值有误: %v", alpha)
		return
	}

	// 获取标准差图表的指标数据
	fromDataList, err := calculateExponentialSmoothingData(dataList, alpha)
	if err != nil {
		return
	}

	// 数据计算
	for _, tmpData := range fromDataList {
		if tmpData.DataTime.IsZero() {
			continue
		}
		// 当前的实际值
		saveValue, _ := decimal.NewFromFloat(tmpData.Value).Round(4).Float64()

		dateDataMap[tmpData.DataTime] = saveValue
	}

	return
}

// calculateExponentialSmoothingData
// @Description: 计算指数修匀
// @author: Roc
// @datetime2023-11-03 14:05:41
// @param dataList []*EdbInfoData 时间基准指标在时间区间内的值
// @param strAlpha float64
// @return newDataList []EdbInfoData
// @return err error
func calculateExponentialSmoothingData(dataList []*EdbInfoData, alpha float64) (newDataList []EdbInfoData, err error) {
	if alpha <= 0 || alpha >= 1 {
		err = fmt.Errorf("alpha值有误: %v", alpha)
		return
	}

	var preVal float64
	alphaDecimal := decimal.NewFromFloat(alpha)
	subAlpha := decimal.NewFromFloat(1).Sub(alphaDecimal)
	for k, d := range dataList {
		// 首期的值以原始值作为指数修匀的计算值
		if k == 0 {
			newDataList = append(newDataList, EdbInfoData{
				EdbDataId: k,
				DataTime:  dataList[k].DataTime,
				Value:     d.Value,
			})
			preVal = d.Value
			continue
		}

		// 上一期的值参与计算
		preDecimal := decimal.NewFromFloat(preVal)
		valDecimal := decimal.NewFromFloat(d.Value)

		partA := alphaDecimal.Mul(valDecimal)
		partB := subAlpha.Mul(preDecimal)
		res, _ := (partA.Add(partB)).Float64()
		preVal = res
		newDataList = append(newDataList, EdbInfoData{
			EdbDataId: k,
			DataTime:  dataList[k].DataTime,
			Value:     res,
		})
	}
	return
}

// Rjz
// @Description: 日均值计算
// @author: Roc
// @receiver obj
// @datetime2023-11-03 14:47:47
// @return dateDataMap map[time.Time]float64
// @return err error
func (obj BaseCalculate) Rjz() (dateDataMap map[time.Time]float64, err error, errMsg string) {
	dateDataMap = make(map[time.Time]float64)
	dataList := obj.DataList

	fromFrequency := obj.FromFrequency
	if fromFrequency == `` {
		errMsg = "原指标的频度不能为空"
		err = errors.New(errMsg)
		return
	}

	if obj.FromFrequency == "日度" {
		errMsg = "日度指标无需进行日均值计算"
		err = errors.New(errMsg)
		return
	}

	// 数据处理

	// 数据降序
	dataList = reverseSliceByDesc(dataList)

	var dateArr []time.Time
	dataMap := make(map[time.Time]*EdbInfoData)
	for _, v := range dataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime] = v
	}

	// 数据计算
	for _, currentDate := range dateArr {
		//当前日期
		currentItem, ok := dataMap[currentDate]
		if !ok {
			continue
		}

		//根据频度计算需要均分的天数
		days := GetRjzFrequencyDays(currentDate, fromFrequency)
		val, ok := rjzDivV2(currentItem.Value, days)
		if !ok {
			continue
		}

		dateDataMap[currentDate] = val
	}

	return
}

// rjzDivV2
// @Description: 日均值计算
// @author: Roc
// @datetime2023-11-03 14:47:36
// @param a float64
// @param b int
// @return val float64
// @return ok bool
func rjzDivV2(a float64, b int) (val float64, ok bool) {
	if b == 0 {
		return
	}

	af := decimal.NewFromFloat(a)
	bf := decimal.NewFromFloat(float64(b))
	val, _ = af.Div(bf).Round(4).Float64()
	ok = true

	return
}

// reverseSliceByDesc
// @Description: 倒转切片
// @author: Roc
// @datetime2023-11-06 14:08:25
// @param slice []*EdbInfoData
// @return []*EdbInfoData
func reverseSliceByDesc(slice []*EdbInfoData) (newSlice []*EdbInfoData) {
	// 只有一个数据的话,那么就直接返回
	if len(slice) <= 1 {
		newSlice = slice
		return
	}

	if !slice[1].DataTime.After(slice[0].DataTime) {
		newSlice = slice
		return
	}

	newSlice = make([]*EdbInfoData, len(slice))
	for i, j := 0, len(slice)-1; i < len(slice); i, j = i+1, j-1 {
		newSlice[i] = slice[j]
	}

	return
}

// EdbInfoSearchDataToData
// @Description: 将EdbInfoSearchData转成EdbInfoData
// @author: Roc
// @datetime2023-11-09 11:11:31
// @param dataList []*EdbInfoSearchData
// @return newDateDataList []*EdbInfoData
// @return err error
func EdbInfoSearchDataToData(dataList []*EdbInfoSearchData) (newDateDataList []*EdbInfoData, err error) {
	newDateDataList = make([]*EdbInfoData, 0)

	for _, data := range dataList {
		dateTime, tmpErr := time.ParseInLocation(utils.FormatDate, data.DataTime, time.Local)
		if tmpErr != nil {
			err = tmpErr
			return
		}

		newDateDataList = append(newDateDataList, &EdbInfoData{
			EdbDataId: data.EdbDataId,
			DataTime:  dateTime,
			Value:     data.Value,
		})
	}

	return
}

// GetDateDataAndDateList
// @Description: 通过时间数据map 获取 时间字符串数据map和日期字符串切片
// @author: Roc
// @datetime2023-11-09 13:10:38
// @param dateDataMap map[time.Time]float64
// @return dateStrDataMap map[string]float64
// @return dateStrList []string
func GetDateDataAndDateList(dateDataMap map[time.Time]float64) (dateStrDataMap map[string]float64, dateStrList []string) {
	dateStrDataMap = make(map[string]float64)
	dateStrList = make([]string, 0)
	dateList := make([]time.Time, 0)
	for date, val := range dateDataMap {
		dateStr := date.Format(utils.FormatDate)
		dateStrDataMap[dateStr] = val
		dateList = append(dateList, date)
	}

	// 使用 sort.Slice 对日期切片进行排序
	sort.Slice(dateList, func(i, j int) bool {
		return dateList[i].Before(dateList[j])
	})

	// 将日期排序后返回日期字符串切片
	for _, v := range dateList {
		dateStrList = append(dateStrList, v.Format(utils.FormatDate))
	}

	return
}