123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- package services
- import (
- "errors"
- "eta/eta_index_lib/models"
- "eta/eta_index_lib/utils"
- "fmt"
- "github.com/dengsgo/math-engine/engine"
- "github.com/shopspring/decimal"
- "strconv"
- "strings"
- "time"
- )
- // GetCalculateByRuleByNineParams 获取预测规则9的计算参数
- func GetCalculateByRuleByNineParams(req models.RuleConfig) (formula string, edbInfoList []*models.EdbInfo, edbInfoIdBytes []string, err error, errMsg string) {
- formula = req.Value
- formula = strings.Replace(formula, "(", "(", -1)
- formula = strings.Replace(formula, ")", ")", -1)
- formula = strings.Replace(formula, ",", ",", -1)
- formula = strings.Replace(formula, "。", ".", -1)
- formula = strings.Replace(formula, "%", "*0.01", -1)
- //检验公式
- var checkFormulaStr string
- for _, tmpEdbInfoId := range req.EdbInfoIdArr {
- checkFormulaStr += tmpEdbInfoId.FromTag + ","
- edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
- }
- formulaSlice, err := utils.CheckFormulaJson(formula)
- if err != nil {
- errMsg = "公式格式错误,请重新填写"
- err = errors.New(errMsg)
- return
- }
- for _, f := range formulaSlice {
- formulaMap, e := utils.CheckFormula(f)
- if e != nil {
- err = fmt.Errorf("公式错误,请重新填写")
- return
- }
- for _, v := range formulaMap {
- if !strings.Contains(checkFormulaStr, v) {
- errMsg = "公式错误,请重新填写"
- err = errors.New(errMsg)
- return
- }
- }
- }
- //关联的指标信息
- edbInfoList = make([]*models.EdbInfo, 0)
- for _, tmpEdbInfoId := range req.EdbInfoIdArr {
- fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
- if tmpErr != nil {
- if tmpErr.Error() == utils.ErrNoRow() {
- err = errors.New("指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在")
- } else {
- err = errors.New("获取指标失败:Err:" + tmpErr.Error())
- }
- errMsg = "数据计算失败"
- return
- }
- edbInfoList = append(edbInfoList, fromEdbInfo)
- }
- for _, v := range formulaSlice {
- formulaMap, e := utils.CheckFormula(v)
- if e != nil {
- err = fmt.Errorf("公式错误,请重新填写")
- return
- }
- //预先计算,判断公式是否正常
- ok, _ := models.CheckFormula2(edbInfoList, formulaMap, v, edbInfoIdBytes)
- if !ok {
- errMsg = "生成计算指标失败,请使用正确的计算公式"
- err = errors.New(errMsg)
- return
- }
- }
- return
- }
- // CalculateByRuleByNine 动态环差规则计算入库
- func CalculateByRuleByNine(formulaStr string, edbInfoList []*models.EdbInfo, edbInfoIdBytes []string, emptyType, maxEmptyType int) (dataList []*models.EdbDataList, err error) {
- realSaveDataMap := make(map[string]map[int]float64)
- saveDataMap := make(map[string]map[int]float64)
- dateList := make([]string, 0) //日期
- // 最小的结束日期 , 最晚的数据开始日期
- var minLatestDate, maxStartDate time.Time
- formulaStr = strings.ToUpper(formulaStr)
- // 获取关联指标数据
- for edbInfoIndex, v := range edbInfoList {
- // todo eta_api和eta_index_lib两个函数的逻辑不一致
- sourceDataList, tmpErr := models.GetPredictEdbDataListAll(v, 1)
- if tmpErr != nil {
- err = tmpErr
- return
- }
- dataMap := make(map[string]float64)
- //lenData := len(sourceDataList)
- for _, dv := range sourceDataList {
- // 实际数据
- if val, ok := realSaveDataMap[dv.DataTime]; ok {
- if _, ok1 := val[v.EdbInfoId]; !ok1 {
- val[v.EdbInfoId] = dv.Value
- }
- } else {
- temp := make(map[int]float64)
- temp[v.EdbInfoId] = dv.Value
- realSaveDataMap[dv.DataTime] = temp
- }
- // saveDataMap 待计算的数据
- if val, ok := saveDataMap[dv.DataTime]; ok {
- if _, ok1 := val[v.EdbInfoId]; !ok1 {
- val[v.EdbInfoId] = dv.Value
- }
- } else {
- temp2 := make(map[int]float64)
- temp2[v.EdbInfoId] = dv.Value
- saveDataMap[dv.DataTime] = temp2
- }
- // 以第一个指标的日期作为基准日期
- if edbInfoIndex == 0 {
- dateList = append(dateList, dv.DataTime)
- tmpDate, _ := time.ParseInLocation(utils.FormatDate, dv.DataTime, time.Local)
- if minLatestDate.IsZero() || tmpDate.After(minLatestDate) {
- minLatestDate = tmpDate
- }
- if maxStartDate.IsZero() || tmpDate.Before(maxStartDate) {
- maxStartDate = tmpDate
- }
- }
- /* if lenData > 0 {
- tmpLatestDate, _ := time.ParseInLocation(utils.FormatDate, sourceDataList[lenData-1].DataTime, time.Local)
- if minLatestDate.IsZero() || minLatestDate.After(tmpLatestDate) {
- minLatestDate = tmpLatestDate
- }
- tmpStartDate, _ := time.ParseInLocation(utils.FormatDate, sourceDataList[0].DataTime, time.Local)
- if maxStartDate.IsZero() || maxStartDate.Before(tmpStartDate) {
- maxStartDate = tmpStartDate
- }
- }*/
- }
- item := new(models.CalculateItems)
- item.EdbInfoId = v.EdbInfoId
- item.DataMap = dataMap
- }
- models.HandleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, edbInfoList, emptyType)
- // 添加数据
- dataList = make([]*models.EdbDataList, 0)
- // 计算规则
- formulaDateSlice, formulaDateMap, err := utils.HandleFormulaJson(formulaStr, minLatestDate)
- if err != nil {
- return
- }
- existDataMap := make(map[string]string)
- // 判断是否特殊处理max和min函数
- maxDealFlag := false
- if emptyType == 4 && maxEmptyType == 2 {
- maxDealFlag = true
- }
- for k, date := range dateList {
- sv := saveDataMap[date]
- // 当空值处理类型选择了不计算时,只要有一个指标在某个日期没有值(即空值),则计算指标在该日期没有值
- if emptyType == 1 {
- if len(sv) != len(edbInfoList) {
- continue
- }
- }
- //fmt.Println(sk, sv)
- // 根据时间范围,选择对应的公式
- formulaMap := make(map[string]string)
- formulaStr = ""
- for _, fv := range formulaDateSlice {
- if date < fv {
- if f, ok := formulaDateMap[fv]; ok {
- formulaStr = f
- formulaMap, err = utils.CheckFormula(formulaStr)
- if err != nil {
- err = fmt.Errorf("公式错误,请重新填写")
- return
- }
- }
- break
- }
- }
- if formulaStr == "" {
- continue
- }
- svMax := make(map[int]float64)
- if maxDealFlag {
- // 特殊处理max和min函数,如果原本的值为空,则选择空值参与运算
- if svMaxData, ok := realSaveDataMap[date]; ok {
- svMax = svMaxData
- }
- }
- //fmt.Println(date, sv)
- formulaFormStr := models.ReplaceFormula(edbInfoList, sv, svMax, formulaMap, formulaStr, edbInfoIdBytes, maxDealFlag)
- if formulaFormStr == `` {
- //计算公式异常,那么就移除该指标
- continue
- }
- //fmt.Println(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
- fmt.Println(fmt.Sprintf("%s:formulaFormStr:%s", date, formulaFormStr))
- //expression := formula.NewExpression(formulaFormStr)
- //calResult, tmpErr := expression.Evaluate()
- //if tmpErr != nil {
- // // 分母为0的报错
- // if strings.Contains(tmpErr.Error(), "divide by zero") {
- // continue
- // }
- // err = errors.New("计算失败:Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
- // return
- //}
- calVal, err := engine.ParseAndExec(formulaFormStr)
- //calVal, err := calResult.Float64()
- if err != nil {
- err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
- fmt.Println(err)
- return nil, err
- }
- //nanCheck := fmt.Sprintf("%0.f", calVal)
- //calVal, tmpErr := calResult.Float64()
- //if tmpErr != nil {
- // err = errors.New("计算失败:获取计算值失败 Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
- // fmt.Println(err)
- // return
- //}
- saveValue, _ := decimal.NewFromFloat(calVal).Round(4).Float64() //utils.SubFloatToString(calVal, 4)
- dataTime, _ := time.Parse(utils.FormatDate, date)
- timestamp := dataTime.UnixNano() / 1e6
- if _, existOk := existDataMap[date]; !existOk {
- tmpPredictEdbRuleData := &models.EdbDataList{
- EdbDataId: k,
- EdbInfoId: 0,
- DataTime: date,
- DataTimestamp: timestamp,
- Value: saveValue,
- }
- dataList = append(dataList, tmpPredictEdbRuleData)
- }
- existDataMap[date] = date
- }
- return
- }
|