base_from_predict.go 7.3 KB

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