package services import ( "errors" "eta_gn/eta_index_lib/models" "eta_gn/eta_index_lib/utils" "fmt" "github.com/dengsgo/math-engine/engine" "github.com/shopspring/decimal" "strconv" "strings" "time" ) 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 } 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 { sourceDataList, tmpErr := models.GetPredictEdbDataListAll(v, 1) if tmpErr != nil { err = tmpErr return } dataMap := make(map[string]float64) 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 } 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 } } } 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) 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 } } 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 { if svMaxData, ok := realSaveDataMap[date]; ok { svMax = svMaxData } } formulaFormStr := models.ReplaceFormula(edbInfoList, sv, svMax, formulaMap, formulaStr, edbInfoIdBytes, maxDealFlag) if formulaFormStr == `` { continue } fmt.Println(fmt.Sprintf("%s:formulaFormStr:%s", date, formulaFormStr)) calVal, err := engine.ParseAndExec(formulaFormStr) if err != nil { err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr) fmt.Println(err) return nil, err } 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 }