predict_edb.go 5.5 KB

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