base_from_predict.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. package services
  2. import (
  3. "errors"
  4. "eta_gn/eta_index_lib/models"
  5. "eta_gn/eta_index_lib/utils"
  6. "fmt"
  7. "github.com/dengsgo/math-engine/engine"
  8. "github.com/shopspring/decimal"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. // GetCalculateByRuleByNineParams 获取预测规则9的计算参数
  14. func GetCalculateByRuleByNineParams(req models.RuleConfig) (formula string, edbInfoList []*models.EdbInfo, edbInfoIdBytes []string, err error, errMsg string) {
  15. formula = req.Value
  16. formula = strings.Replace(formula, "(", "(", -1)
  17. formula = strings.Replace(formula, ")", ")", -1)
  18. formula = strings.Replace(formula, ",", ",", -1)
  19. formula = strings.Replace(formula, "。", ".", -1)
  20. formula = strings.Replace(formula, "%", "*0.01", -1)
  21. //检验公式
  22. var checkFormulaStr string
  23. for _, tmpEdbInfoId := range req.EdbInfoIdArr {
  24. checkFormulaStr += tmpEdbInfoId.FromTag + ","
  25. edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
  26. }
  27. formulaSlice, err := utils.CheckFormulaJson(formula)
  28. if err != nil {
  29. errMsg = "公式格式错误,请重新填写"
  30. err = errors.New(errMsg)
  31. return
  32. }
  33. for _, f := range formulaSlice {
  34. formulaMap, e := utils.CheckFormula(f)
  35. if e != nil {
  36. err = fmt.Errorf("公式错误,请重新填写")
  37. return
  38. }
  39. for _, v := range formulaMap {
  40. if !strings.Contains(checkFormulaStr, v) {
  41. errMsg = "公式错误,请重新填写"
  42. err = errors.New(errMsg)
  43. return
  44. }
  45. }
  46. }
  47. //关联的指标信息
  48. edbInfoList = make([]*models.EdbInfo, 0)
  49. for _, tmpEdbInfoId := range req.EdbInfoIdArr {
  50. fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
  51. if tmpErr != nil {
  52. if tmpErr.Error() == utils.ErrNoRow() {
  53. err = errors.New("指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在")
  54. } else {
  55. err = errors.New("获取指标失败:Err:" + tmpErr.Error())
  56. }
  57. errMsg = "数据计算失败"
  58. return
  59. }
  60. edbInfoList = append(edbInfoList, fromEdbInfo)
  61. }
  62. for _, v := range formulaSlice {
  63. formulaMap, e := utils.CheckFormula(v)
  64. if e != nil {
  65. err = fmt.Errorf("公式错误,请重新填写")
  66. return
  67. }
  68. //预先计算,判断公式是否正常
  69. ok, _ := models.CheckFormula2(edbInfoList, formulaMap, v, edbInfoIdBytes)
  70. if !ok {
  71. errMsg = "生成计算指标失败,请使用正确的计算公式"
  72. err = errors.New(errMsg)
  73. return
  74. }
  75. }
  76. return
  77. }
  78. // CalculateByRuleByNine 动态环差规则计算入库
  79. func CalculateByRuleByNine(formulaStr string, edbInfoList []*models.EdbInfo, edbInfoIdBytes []string, emptyType, maxEmptyType int) (dataList []*models.EdbDataList, err error) {
  80. realSaveDataMap := make(map[string]map[int]float64)
  81. saveDataMap := make(map[string]map[int]float64)
  82. dateList := make([]string, 0) //日期
  83. // 最小的结束日期 , 最晚的数据开始日期
  84. var minLatestDate, maxStartDate time.Time
  85. formulaStr = strings.ToUpper(formulaStr)
  86. // 获取关联指标数据
  87. for edbInfoIndex, v := range edbInfoList {
  88. // todo eta_api和eta_index_lib两个函数的逻辑不一致
  89. sourceDataList, tmpErr := models.GetPredictEdbDataListAll(v, 1)
  90. if tmpErr != nil {
  91. err = tmpErr
  92. return
  93. }
  94. dataMap := make(map[string]float64)
  95. //lenData := len(sourceDataList)
  96. for _, dv := range sourceDataList {
  97. // 实际数据
  98. if val, ok := realSaveDataMap[dv.DataTime]; ok {
  99. if _, ok1 := val[v.EdbInfoId]; !ok1 {
  100. val[v.EdbInfoId] = dv.Value
  101. }
  102. } else {
  103. temp := make(map[int]float64)
  104. temp[v.EdbInfoId] = dv.Value
  105. realSaveDataMap[dv.DataTime] = temp
  106. }
  107. // saveDataMap 待计算的数据
  108. if val, ok := saveDataMap[dv.DataTime]; ok {
  109. if _, ok1 := val[v.EdbInfoId]; !ok1 {
  110. val[v.EdbInfoId] = dv.Value
  111. }
  112. } else {
  113. temp2 := make(map[int]float64)
  114. temp2[v.EdbInfoId] = dv.Value
  115. saveDataMap[dv.DataTime] = temp2
  116. }
  117. // 以第一个指标的日期作为基准日期
  118. if edbInfoIndex == 0 {
  119. dateList = append(dateList, dv.DataTime)
  120. tmpDate, _ := time.ParseInLocation(utils.FormatDate, dv.DataTime, time.Local)
  121. if minLatestDate.IsZero() || tmpDate.After(minLatestDate) {
  122. minLatestDate = tmpDate
  123. }
  124. if maxStartDate.IsZero() || tmpDate.Before(maxStartDate) {
  125. maxStartDate = tmpDate
  126. }
  127. }
  128. /* if lenData > 0 {
  129. tmpLatestDate, _ := time.ParseInLocation(utils.FormatDate, sourceDataList[lenData-1].DataTime, time.Local)
  130. if minLatestDate.IsZero() || minLatestDate.After(tmpLatestDate) {
  131. minLatestDate = tmpLatestDate
  132. }
  133. tmpStartDate, _ := time.ParseInLocation(utils.FormatDate, sourceDataList[0].DataTime, time.Local)
  134. if maxStartDate.IsZero() || maxStartDate.Before(tmpStartDate) {
  135. maxStartDate = tmpStartDate
  136. }
  137. }*/
  138. }
  139. item := new(models.CalculateItems)
  140. item.EdbInfoId = v.EdbInfoId
  141. item.DataMap = dataMap
  142. }
  143. models.HandleDateSaveDataMap(dateList, maxStartDate, minLatestDate, realSaveDataMap, saveDataMap, edbInfoList, emptyType)
  144. // 添加数据
  145. dataList = make([]*models.EdbDataList, 0)
  146. // 计算规则
  147. formulaDateSlice, formulaDateMap, err := utils.HandleFormulaJson(formulaStr, minLatestDate)
  148. if err != nil {
  149. return
  150. }
  151. existDataMap := make(map[string]string)
  152. // 判断是否特殊处理max和min函数
  153. maxDealFlag := false
  154. if emptyType == 4 && maxEmptyType == 2 {
  155. maxDealFlag = true
  156. }
  157. for k, date := range dateList {
  158. sv := saveDataMap[date]
  159. // 当空值处理类型选择了不计算时,只要有一个指标在某个日期没有值(即空值),则计算指标在该日期没有值
  160. if emptyType == 1 {
  161. if len(sv) != len(edbInfoList) {
  162. continue
  163. }
  164. }
  165. //fmt.Println(sk, sv)
  166. // 根据时间范围,选择对应的公式
  167. formulaMap := make(map[string]string)
  168. formulaStr = ""
  169. for _, fv := range formulaDateSlice {
  170. if date < fv {
  171. if f, ok := formulaDateMap[fv]; ok {
  172. formulaStr = f
  173. formulaMap, err = utils.CheckFormula(formulaStr)
  174. if err != nil {
  175. err = fmt.Errorf("公式错误,请重新填写")
  176. return
  177. }
  178. }
  179. break
  180. }
  181. }
  182. if formulaStr == "" {
  183. continue
  184. }
  185. svMax := make(map[int]float64)
  186. if maxDealFlag {
  187. // 特殊处理max和min函数,如果原本的值为空,则选择空值参与运算
  188. if svMaxData, ok := realSaveDataMap[date]; ok {
  189. svMax = svMaxData
  190. }
  191. }
  192. //fmt.Println(date, sv)
  193. formulaFormStr := models.ReplaceFormula(edbInfoList, sv, svMax, formulaMap, formulaStr, edbInfoIdBytes, maxDealFlag)
  194. if formulaFormStr == `` {
  195. //计算公式异常,那么就移除该指标
  196. continue
  197. }
  198. //fmt.Println(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
  199. fmt.Println(fmt.Sprintf("%s:formulaFormStr:%s", date, formulaFormStr))
  200. //expression := formula.NewExpression(formulaFormStr)
  201. //calResult, tmpErr := expression.Evaluate()
  202. //if tmpErr != nil {
  203. // // 分母为0的报错
  204. // if strings.Contains(tmpErr.Error(), "divide by zero") {
  205. // continue
  206. // }
  207. // err = errors.New("计算失败:Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
  208. // return
  209. //}
  210. calVal, err := engine.ParseAndExec(formulaFormStr)
  211. //calVal, err := calResult.Float64()
  212. if err != nil {
  213. err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  214. fmt.Println(err)
  215. return nil, err
  216. }
  217. //nanCheck := fmt.Sprintf("%0.f", calVal)
  218. //calVal, tmpErr := calResult.Float64()
  219. //if tmpErr != nil {
  220. // err = errors.New("计算失败:获取计算值失败 Err:" + tmpErr.Error() + ";formulaStr:" + formulaFormStr)
  221. // fmt.Println(err)
  222. // return
  223. //}
  224. saveValue, _ := decimal.NewFromFloat(calVal).Round(4).Float64() //utils.SubFloatToString(calVal, 4)
  225. dataTime, _ := time.Parse(utils.FormatDate, date)
  226. timestamp := dataTime.UnixNano() / 1e6
  227. if _, existOk := existDataMap[date]; !existOk {
  228. tmpPredictEdbRuleData := &models.EdbDataList{
  229. EdbDataId: k,
  230. EdbInfoId: 0,
  231. DataTime: date,
  232. DataTimestamp: timestamp,
  233. Value: saveValue,
  234. }
  235. dataList = append(dataList, tmpPredictEdbRuleData)
  236. }
  237. existDataMap[date] = date
  238. }
  239. return
  240. }