predict_edb.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package models
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/beego/beego/v2/client/orm"
  6. "github.com/shopspring/decimal"
  7. "github.com/yidane/formula"
  8. "hongze/hongze_edb_lib/services"
  9. "hongze/hongze_edb_lib/utils"
  10. "strings"
  11. "time"
  12. )
  13. // CalculateRule 预测指标 规则 计算
  14. type CalculateRule struct {
  15. EdbInfoId int `description:"指标id"`
  16. ConfigId int `description:"配置id"`
  17. TrendsCalculateMappingList []*PredictEdbConfCalculateMapping
  18. EdbInfoList []*EdbInfo
  19. EdbInfoIdBytes []string
  20. Formula string
  21. RuleType int `description:"预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差"`
  22. EndDate string `description:"截止日期"`
  23. EdbInfoIdArr []EdbInfoFromTag `description:"指标信息"`
  24. }
  25. // CalculateByRuleBy9 动态环差规则计算入库
  26. func CalculateByRuleBy9(to orm.TxOrmer, rule CalculateRule) (err error) {
  27. saveDataMap := make(map[string]map[int]float64)
  28. formulaStr := strings.ToUpper(rule.Formula)
  29. // 获取关联指标数据
  30. for _, v := range rule.EdbInfoList {
  31. dataList, tmpErr := GetPredictEdbDataListAll(v, 1)
  32. if tmpErr != nil {
  33. err = tmpErr
  34. return
  35. }
  36. dataMap := make(map[string]float64)
  37. for _, dv := range dataList {
  38. if val, ok := saveDataMap[dv.DataTime]; ok {
  39. if _, ok := val[v.EdbInfoId]; !ok {
  40. val[v.EdbInfoId] = dv.Value
  41. }
  42. } else {
  43. temp := make(map[int]float64)
  44. temp[v.EdbInfoId] = dv.Value
  45. saveDataMap[dv.DataTime] = temp
  46. }
  47. }
  48. item := new(CalculateItems)
  49. item.EdbInfoId = v.EdbInfoId
  50. item.DataMap = dataMap
  51. }
  52. // 添加数据
  53. addDataList := make([]*PredictEdbRuleData, 0)
  54. // 计算规则
  55. formulaMap := services.CheckFormula(formulaStr)
  56. //获取指标所有数据
  57. dataList := make([]*PredictEdbRuleData, 0)
  58. sql := `SELECT * FROM predict_edb_rule_data WHERE config_id = ?`
  59. _, err = to.Raw(sql, rule.ConfigId).QueryRows(&dataList)
  60. if err != nil {
  61. return err
  62. }
  63. dataMap := make(map[string]*PredictEdbRuleData)
  64. for _, v := range dataList {
  65. dataMap[v.DataTime] = v
  66. }
  67. existDataMap := make(map[string]string)
  68. removeDateList := make([]string, 0) //需要移除的日期
  69. for sk, sv := range saveDataMap {
  70. //fmt.Println(sk, sv)
  71. formulaFormStr := ReplaceFormula(rule.EdbInfoList, sv, formulaMap, formulaStr, rule.EdbInfoIdBytes)
  72. if formulaFormStr != "" {
  73. utils.FileLog.Info(fmt.Sprintf("formulaFormStr:%s", formulaFormStr))
  74. expression := formula.NewExpression(formulaFormStr)
  75. calResult, err := expression.Evaluate()
  76. if err != nil {
  77. // 分母为0的报错
  78. if strings.Contains(err.Error(), "divide by zero") {
  79. removeDateList = append(removeDateList, sk)
  80. continue
  81. }
  82. err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  83. fmt.Println(err)
  84. return err
  85. }
  86. calVal, err := calResult.Float64()
  87. if err != nil {
  88. err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  89. fmt.Println(err)
  90. return err
  91. }
  92. saveValue := decimal.NewFromFloat(calVal).RoundCeil(4).String() //utils.SubFloatToString(calVal, 4)
  93. if existPredictEdbRuleData, ok := dataMap[sk]; !ok {
  94. dataTime, _ := time.Parse(utils.FormatDate, sk)
  95. timestamp := dataTime.UnixNano() / 1e6
  96. if _, existOk := existDataMap[sk]; !existOk {
  97. tmpPredictEdbRuleData := &PredictEdbRuleData{
  98. //PredictEdbRuleDataId: 0,
  99. EdbInfoId: rule.EdbInfoId,
  100. ConfigId: rule.ConfigId,
  101. DataTime: sk,
  102. Value: saveValue,
  103. CreateTime: time.Now(),
  104. ModifyTime: time.Now(),
  105. DataTimestamp: timestamp,
  106. }
  107. addDataList = append(addDataList, tmpPredictEdbRuleData)
  108. }
  109. existDataMap[sk] = sk
  110. } else {
  111. existValDecimal, err := decimal.NewFromString(existPredictEdbRuleData.Value)
  112. existStr := existValDecimal.String()
  113. if existStr != saveValue {
  114. existPredictEdbRuleData.Value = saveValue
  115. existPredictEdbRuleData.ModifyTime = time.Now()
  116. _, err = to.Update(existPredictEdbRuleData, "Value", "ModifyTime")
  117. if err != nil {
  118. return err
  119. }
  120. }
  121. }
  122. } else {
  123. //计算公式异常,那么就移除该指标
  124. removeDateList = append(removeDateList, sk)
  125. continue
  126. }
  127. }
  128. // 添加计算出来的值入库
  129. lenAddDataList := len(addDataList)
  130. if lenAddDataList > 0 {
  131. _, err = to.InsertMulti(lenAddDataList, addDataList)
  132. if err != nil {
  133. return
  134. }
  135. }
  136. //删除多余的值
  137. lenRemoveDateList := len(removeDateList)
  138. if lenRemoveDateList > 0 {
  139. removeDateStr := strings.Join(removeDateList, `","`)
  140. removeDateStr = `"` + removeDateStr + `"`
  141. //如果拼接指标变更了,那么需要删除所有的指标数据
  142. sql := ` DELETE FROM predict_edb_rule_data WHERE config_id = ? and data_time in (` + utils.GetOrmInReplace(lenRemoveDateList) + `) `
  143. _, err = to.Raw(sql, rule.ConfigId, removeDateList).Exec()
  144. if err != nil {
  145. err = fmt.Errorf("删除计算失败的预测规则计算指标数据失败,Err:" + err.Error())
  146. return
  147. }
  148. }
  149. return
  150. }