Browse Source

指标运算改版

xyxie 1 year ago
parent
commit
36e9f5ddc9

+ 1 - 1
controllers/base_from_calculate.go

@@ -1405,7 +1405,7 @@ func (this *CalculateController) Refresh() {
 			edbInfo, _ := models.GetEdbInfoById(v.FromEdbInfoId)
 			edbInfoList = append(edbInfoList, edbInfo)
 		}
-		err = models.RefreshAllCalculate(edbInfoList, edbInfo.EdbInfoId, source, edbInfo.EdbCode, edbInfo.CalculateFormula, startDate, endDate, edbInfoIdBytes)
+		err = models.RefreshAllCalculate(edbInfoList, edbInfo.EdbInfoId, source, edbInfo.EdbCode, edbInfo.CalculateFormula, startDate, endDate, edbInfoIdBytes, edbInfo.EmptyType)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			errMsg = "RefreshCalculate Err:" + err.Error()
 			break

+ 2 - 1
controllers/base_from_predict_calculate.go

@@ -202,6 +202,7 @@ func addPredictCalculate(br *models.BaseResponse, req models.EdbInfoCalculateSav
 		UniqueCode:       uniqueCode,
 		CalculateFormula: req.CalculateFormula,
 		EdbType:          2,
+		EmptyType:        req.EmptyType,
 	}
 	edbInfoId, err := models.AddEdbInfo(edbInfo)
 	if err != nil {
@@ -952,7 +953,7 @@ func (this *PredictCalculateController) Refresh() {
 			edbInfo, _ := models.GetEdbInfoById(v.FromEdbInfoId)
 			edbInfoList = append(edbInfoList, edbInfo)
 		}
-		latestDateStr, latestValue, err = models.RefreshAllPredictCalculate(edbInfoList, edbInfo.EdbInfoId, source, edbInfo.EdbCode, edbInfo.CalculateFormula, startDate, edbInfoIdBytes)
+		latestDateStr, latestValue, err = models.RefreshAllPredictCalculate(edbInfoList, edbInfo.EdbInfoId, source, edbInfo.EdbCode, edbInfo.CalculateFormula, startDate, edbInfoIdBytes, edbInfo.EmptyType)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			errMsg = "RefreshCalculate Err:" + err.Error()
 			break

+ 1 - 0
logic/predict_edb.go

@@ -842,6 +842,7 @@ func RefreshPredictEdbInfo(edbInfoId int) (edbInfo *models.EdbInfo, err error, e
 				errMsg = "请填写计算规则"
 				return
 			}
+			// todo 动态环差的空值类型处理
 			formula := v.Value
 
 			// 动态环差规则 关系表

+ 182 - 12
models/base_from_calculate.go

@@ -7,6 +7,7 @@ import (
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/shopspring/decimal"
 	"github.com/yidane/formula"
+	"regexp"
 	"strconv"
 	"strings"
 	"time"
@@ -22,6 +23,7 @@ type EdbInfoCalculateSaveReq struct {
 	Unit             string `description:"单位"`
 	ClassifyId       int    `description:"分类id"`
 	CalculateFormula string `description:"计算公式"`
+	EmptyType        int    `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
 	EdbInfoIdArr     []EdbInfoFromTag
 }
 
@@ -172,6 +174,7 @@ func AddCalculateInfo(req EdbInfoCalculateSaveReq, calculateMappingList []*EdbIn
 		LatestDate:       "",
 		LatestValue:      0,
 		ChartImage:       "",
+		EmptyType:        req.EmptyType,
 	}
 	lastId, err := to.Insert(edbInfo)
 	if err != nil {
@@ -194,7 +197,7 @@ func AddCalculateInfo(req EdbInfoCalculateSaveReq, calculateMappingList []*EdbIn
 	}
 
 	//计算数据
-	err = refreshAllCalculate(to, edbInfoList, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.EdbCode, edbInfo.CalculateFormula, "", "", edbInfoIdBytes)
+	err = refreshAllCalculate(to, edbInfoList, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.EdbCode, edbInfo.CalculateFormula, "", "", edbInfoIdBytes, edbInfo.EmptyType)
 
 	return
 }
@@ -223,7 +226,8 @@ func EditCalculateInfo(edbInfo *EdbInfo, req EdbInfoCalculateSaveReq, formulaMap
 	edbInfo.ClassifyId = req.ClassifyId
 	edbInfo.CalculateFormula = req.CalculateFormula
 	edbInfo.ModifyTime = time.Now()
-	_, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime")
+	edbInfo.EmptyType = req.EmptyType
+	_, err = to.Update(edbInfo, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId", "CalculateFormula", "ModifyTime", "EmptyType")
 	if err != nil {
 		return
 	}
@@ -293,7 +297,7 @@ func EditCalculateInfo(edbInfo *EdbInfo, req EdbInfoCalculateSaveReq, formulaMap
 		}
 
 		//计算数据
-		err = refreshAllCalculate(to, edbInfoList, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.EdbCode, edbInfo.CalculateFormula, "", "", edbInfoIdBytes)
+		err = refreshAllCalculate(to, edbInfoList, edbInfo.EdbInfoId, edbInfo.Source, edbInfo.EdbCode, edbInfo.CalculateFormula, "", "", edbInfoIdBytes, edbInfo.EmptyType)
 
 	}
 
@@ -337,7 +341,7 @@ func DeleteCalculateEdbInfo(edbInfoId int) (err error) {
 }
 
 // RefreshAllCalculate 刷新全部数据
-func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string) (err error) {
+func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string, emptyType int) (err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
 	if err != nil {
@@ -354,13 +358,13 @@ func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode
 	fmt.Println(startDate, endDate)
 
 	//计算数据
-	err = refreshAllCalculate(to, edbInfoIdArr, edbInfoId, source, edbCode, formulaStr, startDate, endDate, edbInfoIdBytes)
+	err = refreshAllCalculate(to, edbInfoIdArr, edbInfoId, source, edbCode, formulaStr, startDate, endDate, edbInfoIdBytes, emptyType)
 
 	return
 }
 
 // refreshAllCalculate 刷新全部数据
-func refreshAllCalculate(to orm.TxOrmer, edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string) (err error) {
+func refreshAllCalculate(to orm.TxOrmer, edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string, emptyType int) (err error) {
 	realSaveDataMap := make(map[string]map[int]float64)
 	saveDataMap := make(map[string]map[int]float64)
 
@@ -431,9 +435,12 @@ func refreshAllCalculate(to orm.TxOrmer, edbInfoIdArr []*EdbInfo, edbInfoId, sou
 	}
 
 	//数据处理,将日期内不全的数据做补全
-	handleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, edbInfoIdArr)
+	handleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, edbInfoIdArr, emptyType)
 
-	formulaMap := utils.CheckFormula(formulaStr)
+	formulaDateSlice, formulaDateMap, err := utils.CheckFormulaJson(formulaStr, maxStartDate.Format(utils.FormatDate))
+	if err != nil {
+		return
+	}
 	addSql := ` INSERT INTO edb_data_calculate(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
 	var isAdd bool
 
@@ -456,7 +463,28 @@ func refreshAllCalculate(to orm.TxOrmer, edbInfoIdArr []*EdbInfo, edbInfoId, sou
 	edbInfoIdStr := strconv.Itoa(edbInfoId)
 	existDataMap := make(map[string]string)
 	for sk, sv := range saveDataMap {
+		// 当空值处理类型选择了不计算时,只要有一个指标在某个日期没有值(即空值),则计算指标在该日期没有值
+		if emptyType == 1 {
+			if len(sv) != len(edbInfoIdArr) {
+				continue
+			}
+		}
 		//fmt.Println(sk, sv)
+		// 根据时间范围,选择对应的公式
+		formulaMap := make(map[string]string)
+		formulaStr = ""
+		for _, fv := range formulaDateSlice {
+			if sk >= fv {
+				if f, ok := formulaDateMap[fv]; ok {
+					formulaStr = f
+					formulaMap = utils.CheckFormula(formulaStr)
+				}
+				break
+			}
+		}
+		if formulaStr == "" {
+			continue
+		}
 		formulaStr = strings.ToUpper(formulaStr)
 		formulaFormStr := ReplaceFormula(edbInfoIdArr, sv, formulaMap, formulaStr, edbInfoIdBytes)
 		//计算公式异常,那么就移除该指标
@@ -575,9 +603,13 @@ func ReplaceFormula(edbInfoIdArr []*EdbInfo, valArr map[int]float64, formulaMap
 }
 
 func GetFormulaReplace(index, edbInfoId int, formulaStr string, edbInfoIdBytes []string, formulaMap map[string]string, valArr map[int]float64) (formulaResult string, isReplace bool) {
+	// todo 获取原本的值
+	valArrMax := make(map[int]float64)
+
 	formulaResult = formulaStr
 	dKey := edbInfoIdBytes[index]
 	if _, ok := formulaMap[dKey]; ok { //公式中存在
+		// todo 判断公式中存在max、min,如果存在,则值从valArrMax中获取,其余的值从valArr中获取
 		if val, valOk := valArr[edbInfoId]; valOk { //值存在
 			dvStr := fmt.Sprintf("%v", val)
 			formulaResult = strings.Replace(formulaStr, dKey, dvStr, -1)
@@ -599,6 +631,8 @@ func GetFormulaMap() map[string]string {
 	funMap["MOD"] = "[@&]"
 	funMap["POW"] = "[@*]"
 	funMap["ROUND"] = "[@(]"
+	funMap["LN"] = "[@-]"
+	funMap["EXP"] = "[@+]"
 	return funMap
 }
 
@@ -671,7 +705,22 @@ func CheckFormula2(edbInfoArr []*EdbInfo, formulaMap map[string]string, formulaS
 }
 
 // 处理整个数据
-func handleDateSaveDataMap(dateList []string, maxStartDate, minLatestDate time.Time, realSaveDataMap, saveDataMap map[string]map[int]float64, edbInfoIdArr []*EdbInfo) {
+func handleDateSaveDataMap(dateList []string, maxStartDate, minLatestDate time.Time, realSaveDataMap, saveDataMap map[string]map[int]float64, edbInfoIdArr []*EdbInfo, emptyType int) {
+	var startDate, endDate string
+	var startDateT, endDateT time.Time
+	if emptyType == 2 || emptyType == 3 {
+		for k, _ := range realSaveDataMap {
+			if k > endDate {
+				endDate = k
+			}
+			if k < startDate || startDate == "" {
+				startDate = k
+			}
+		}
+
+		startDateT, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+		endDateT, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+	}
 	for _, date := range dateList {
 		dateTime, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
 		// 如果当前日期早于数据的最大开始日期,那么不处理,进入下一个循环
@@ -688,6 +737,7 @@ func handleDateSaveDataMap(dateList []string, maxStartDate, minLatestDate time.T
 			tmpEdbInfoId := edbInfo.EdbInfoId // 当前指标id
 			// 如果该日期不存在该指标数据,那么需要找寻前后日期的数据,进行填补
 			if _, ok := tmpDataMap[tmpEdbInfoId]; !ok {
+
 				//day := 0
 				//switch edbInfo.Frequency {
 				//case "周度":
@@ -702,14 +752,24 @@ func handleDateSaveDataMap(dateList []string, maxStartDate, minLatestDate time.T
 				//	day = 365
 				//}
 				// 需求池 255 指标运算文案修改,补数据遍历区间修改(2023-3-7 09:37:23修改)
-				day := 35
-				handleDateDataMap(realSaveDataMap, saveDataMap, date, tmpEdbInfoId, day)
+
+				switch emptyType {
+				case 0:
+					handleDateDataMap(realSaveDataMap, saveDataMap, date, tmpEdbInfoId, 35)
+				case 2:
+					handleDateDataMapBefore(realSaveDataMap, saveDataMap, date, tmpEdbInfoId, startDateT, endDateT)
+				case 3:
+					handleDateDataMapAfter(realSaveDataMap, saveDataMap, date, tmpEdbInfoId, startDateT, endDateT)
+				case 4:
+					handleDateDataMapZero(saveDataMap, date, tmpEdbInfoId)
+				}
+
 			}
 		}
 	}
 }
 
-// handleDateDataMap 处理单个日期的数据
+// handleDateDataMap 前后35天 处理单个日期的数据
 func handleDateDataMap(realSaveDataMap, saveDataMap map[string]map[int]float64, date string, edbInfoId, day int) {
 	currDate, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
 
@@ -748,3 +808,113 @@ func handleDateDataMap(realSaveDataMap, saveDataMap map[string]map[int]float64,
 		}
 	}
 }
+
+// handleDateDataMapBefore 前值填充:空值优先以最近的前值填充,没有前值时,用后值填充
+func handleDateDataMapBefore(realSaveDataMap, saveDataMap map[string]map[int]float64, date string, edbInfoId int, startDateT, endDateT time.Time) {
+	currDate, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
+
+	// 后一天
+	nextDateDay := currDate
+
+	// 前一天
+	preDateDay := currDate
+
+	for i := 1; preDateDay.After(startDateT) || preDateDay == startDateT; i++ {
+		// 上个日期的数据
+		{
+			preDateDay = currDate.AddDate(0, 0, -i)
+			preDateDayStr := preDateDay.Format(utils.FormatDate)
+			if findDataMap, hasFindDataMap := realSaveDataMap[preDateDayStr]; hasFindDataMap { // 下一个日期有数据
+				if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
+					fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, preDateDayStr, val))
+					saveDataMap[date][edbInfoId] = val
+					return
+				}
+			}
+		}
+	}
+
+	for i := 1; nextDateDay.Before(endDateT) || nextDateDay == endDateT; i++ {
+		// 下个日期的数据
+		{
+			nextDateDay = currDate.AddDate(0, 0, i)
+			nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+			if findDataMap, hasFindDataMap := realSaveDataMap[nextDateDayStr]; hasFindDataMap { // 下一个日期有数据
+				if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
+					fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, nextDateDayStr, val))
+					saveDataMap[date][edbInfoId] = val
+					return
+				}
+			}
+		}
+	}
+	return
+}
+
+// handleDateDataMapAfter 后值填充:空值优先以最近的后值填充,没有后值时,用前值填充
+func handleDateDataMapAfter(realSaveDataMap, saveDataMap map[string]map[int]float64, date string, edbInfoId int, startDateT, endDateT time.Time) {
+	currDate, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
+
+	// 后一天
+	nextDateDay := currDate
+
+	// 前一天
+	preDateDay := currDate
+
+	for i := 1; nextDateDay.Before(endDateT) || nextDateDay == endDateT; i++ {
+		// 下个日期的数据
+		{
+			nextDateDay = currDate.AddDate(0, 0, i)
+			nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+			if findDataMap, hasFindDataMap := realSaveDataMap[nextDateDayStr]; hasFindDataMap { // 下一个日期有数据
+				if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
+					fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, nextDateDayStr, val))
+					saveDataMap[date][edbInfoId] = val
+					return
+				}
+			}
+		}
+	}
+
+	for i := 1; preDateDay.After(startDateT) || preDateDay == startDateT; i++ {
+		// 上个日期的数据
+		{
+			preDateDay = currDate.AddDate(0, 0, -i)
+			preDateDayStr := preDateDay.Format(utils.FormatDate)
+			if findDataMap, hasFindDataMap := realSaveDataMap[preDateDayStr]; hasFindDataMap { // 下一个日期有数据
+				if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
+					fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, preDateDayStr, val))
+					saveDataMap[date][edbInfoId] = val
+					return
+				}
+			}
+		}
+	}
+	return
+}
+
+// handleDateDataMapZero 等于0
+func handleDateDataMapZero(saveDataMap map[string]map[int]float64, date string, edbInfoId int) {
+	saveDataMap[date][edbInfoId] = 0
+	return
+}
+
+func GetMaxMinEdbInfo(formula string, formulaMap map[string]string) (edbInfoIdBytes []string) {
+	//formula := "A+min(A,B,max(A,C))"
+	// 定义正则表达式匹配max和min函数及其参数
+	regex := regexp.MustCompile(`MIN\((.*?)\)|MAX\((.*?)\)`)
+	matches := regex.FindAllStringSubmatch(formula, -1)
+
+	// 遍历匹配结果,输出max和min函数及其参数
+	for _, match := range matches {
+		if len(match) == 3 {
+			function := match[1] // min或max函数
+			parameter := match[2]
+			// todo 将max和min函数里的入参替换成小写
+			//lowercaseParameter := parameter                                                                         // 参数保持不变
+			//lowercaseFormula = strings.ReplaceAll(lowercaseFormula, match[0], lowercaseFunction+lowercaseParameter) // 替换公式中的MAX/MIN函数及其参数为小写形式
+			fmt.Printf("Function: %s, Parameter: %s\n", function, parameter)
+		}
+	}
+	return
+}

+ 6 - 5
models/base_predict_from_calculate.go

@@ -238,12 +238,12 @@ func AddPredictCalculateData(edbInfoIdList []*EdbInfo, edbInfo *EdbInfo, edbCode
 		}
 	}()
 
-	latestDateStr, latestValue, err = refreshAllPredictCalculate(to, edbInfoIdList, edbInfo.EdbInfoId, edbInfo.Source, edbCode, formulaStr, "", edbInfoIdBytes)
+	latestDateStr, latestValue, err = refreshAllPredictCalculate(to, edbInfoIdList, edbInfo.EdbInfoId, edbInfo.Source, edbCode, formulaStr, "", edbInfoIdBytes, edbInfo.EmptyType)
 	return
 }
 
 // RefreshAllPredictCalculate 刷新预测计算指标的全部数据
-func RefreshAllPredictCalculate(edbInfoIdList []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate string, edbInfoIdBytes []string) (latestDateStr string, latestValue float64, err error) {
+func RefreshAllPredictCalculate(edbInfoIdList []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate string, edbInfoIdBytes []string, emptyType int) (latestDateStr string, latestValue float64, err error) {
 	o := orm.NewOrm()
 	to, err := o.Begin()
 	if err != nil {
@@ -258,13 +258,13 @@ func RefreshAllPredictCalculate(edbInfoIdList []*EdbInfo, edbInfoId, source int,
 		}
 	}()
 
-	latestDateStr, latestValue, err = refreshAllPredictCalculate(to, edbInfoIdList, edbInfoId, source, edbCode, formulaStr, startDate, edbInfoIdBytes)
+	latestDateStr, latestValue, err = refreshAllPredictCalculate(to, edbInfoIdList, edbInfoId, source, edbCode, formulaStr, startDate, edbInfoIdBytes, emptyType)
 
 	return
 }
 
 // refreshAllPredictCalculate 刷新预测计算指标的全部数据
-func refreshAllPredictCalculate(to orm.TxOrmer, edbInfoIdList []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate string, edbInfoIdBytes []string) (latestDateStr string, latestValue float64, err error) {
+func refreshAllPredictCalculate(to orm.TxOrmer, edbInfoIdList []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate string, edbInfoIdBytes []string, emptyType int) (latestDateStr string, latestValue float64, err error) {
 	fmt.Println("startDate:", startDate)
 
 	// 最小的结束日期 , 最晚的数据开始日期
@@ -275,6 +275,7 @@ func refreshAllPredictCalculate(to orm.TxOrmer, edbInfoIdList []*EdbInfo, edbInf
 	saveDataMap := make(map[string]map[int]float64)
 
 	for edbInfoIndex, v := range edbInfoIdList {
+		// 单独存储max、min函数里的指标的数据
 		tmpLatestDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.LatestDate, time.Local)
 		if tmpErr != nil {
 			err = errors.New(`最近的日期格式化失败;日期:` + v.EndDate + `;err:` + tmpErr.Error())
@@ -327,7 +328,7 @@ func refreshAllPredictCalculate(to orm.TxOrmer, edbInfoIdList []*EdbInfo, edbInf
 	}
 
 	//数据处理,将日期内不全的数据做填补
-	handleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, edbInfoIdList)
+	handleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, edbInfoIdList, emptyType)
 
 	formulaMap := utils.CheckFormula(formulaStr)
 	addSql := ` INSERT INTO edb_data_predict_calculate (edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `

+ 2 - 0
models/edb_info.go

@@ -45,6 +45,8 @@ type EdbInfo struct {
 	ServerUrl        string  `description:"服务器地址"`
 	ChartImage       string  `description:"图表图片"`
 	Calendar         string  `description:"公历/农历" orm:"default(公历);"`
+	EmptyType        int     `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
+	MaxEmptyType     int     `description:"MAX、MIN公式空值处理类型(1、等于0;2、跳过空值)"`
 	DataDateType     string  `orm:"column(data_date_type);size(255);null;default(交易日)"`
 	ManualSave       int     `description:"是否有手动保存过上下限: 0-否; 1-是"`
 }

+ 3 - 2
models/predict_edb.go

@@ -23,6 +23,7 @@ type CalculateRule struct {
 	RuleType                   int              `description:"预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差"`
 	EndDate                    string           `description:"截止日期"`
 	EdbInfoIdArr               []EdbInfoFromTag `description:"指标信息"`
+	EmptyType                  int              `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
 }
 
 // RefreshCalculateByRuleBy9 刷新计算
@@ -106,8 +107,8 @@ func CalculateByRuleBy9(to orm.TxOrmer, rule CalculateRule) (resultDataList []*E
 		}
 	}
 
-	//数据处理,将日期内不全的数据做填补
-	handleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, rule.EdbInfoList)
+	// todo 数据处理,将日期内不全的数据做填补
+	handleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, rule.EdbInfoList, rule.EmptyType)
 
 	// 添加数据
 	addDataList := make([]*PredictEdbRuleData, 0)

+ 34 - 1
utils/base_from_calculate.go

@@ -1,12 +1,15 @@
 package utils
 
 import (
+	"encoding/json"
+	"fmt"
+	"sort"
 	"strings"
 )
 
 // CheckFormula 检测计算公式是否异常
 func CheckFormula(formula string) map[string]string {
-	mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN"}
+	mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN", "EXP"}
 
 	str := strings.ToUpper(formula)
 	for _, v := range mathFormula {
@@ -27,3 +30,33 @@ func CheckFormula(formula string) map[string]string {
 	}
 	return byteMap
 }
+
+type FormulaListItem struct {
+	Formula string `json:"f"`
+	Date    string `json:"d"`
+}
+
+// CheckFormulaJson 检测计算公式json串是否异常
+func CheckFormulaJson(formula string, startDate string) (dateSlice []string, formulaMap map[string]string, err error) {
+	list := make([]FormulaListItem, 0)
+	err = json.Unmarshal([]byte(formula), &list)
+	if err != nil {
+		err = fmt.Errorf("公式串解析失败: json.Unmarshal Err: %v", err)
+		return
+	}
+	formulaMap = make(map[string]string)
+	dateSlice = make([]string, 0)
+	// 日期排序
+	for k, v := range list {
+		if k == 0 { // 首个日期均为起始日
+			v.Date = startDate
+		}
+		formulaMap[v.Date] = v.Formula
+		dateSlice = append(dateSlice, v.Date)
+	}
+	sort.Slice(dateSlice, func(i, j int) bool {
+		return dateSlice[i] > dateSlice[j]
+	})
+
+	return
+}