edb_info_calculate.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. package data
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_api/models/data_manage"
  6. "eta/eta_api/utils"
  7. "fmt"
  8. "github.com/shopspring/decimal"
  9. "math"
  10. "regexp"
  11. "sort"
  12. "strings"
  13. "time"
  14. )
  15. func CheckFormula(formula string) map[string]string {
  16. mathFormula := []string{"MAX", "MIN", "ABS", "ACOS", "ASIN", "CEIL", "MOD", "POW", "ROUND", "SIGN", "SIN", "TAN", "LOG10", "LOG2", "LOG", "LN", "EXP"}
  17. str := strings.ToUpper(formula)
  18. for _, v := range mathFormula {
  19. str = strings.Replace(str, v, "", -1)
  20. }
  21. str = strings.Replace(str, "(", "", -1)
  22. str = strings.Replace(str, ")", "", -1)
  23. byteMap := make(map[string]string)
  24. for i := 0; i < len(str); i++ {
  25. byteInt := str[i]
  26. if byteInt >= 65 && byteInt <= 90 {
  27. byteStr := string(byteInt)
  28. if _, ok := byteMap[byteStr]; !ok {
  29. byteMap[byteStr] = byteStr
  30. }
  31. }
  32. }
  33. return byteMap
  34. }
  35. type FormulaListItem struct {
  36. Formula string `json:"f"`
  37. Date string `json:"d"`
  38. }
  39. // CheckFormulaJson 检测计算公式json串是否异常
  40. func CheckFormulaJson(formula string) (formulaSlice []string, err error) {
  41. list := make([]FormulaListItem, 0)
  42. err = json.Unmarshal([]byte(formula), &list)
  43. if err != nil {
  44. err = fmt.Errorf("公式串解析失败: json.Unmarshal Err: %v", err)
  45. return
  46. }
  47. formulaSlice = make([]string, 0)
  48. // 日期排序
  49. for _, v := range list {
  50. formulaSlice = append(formulaSlice, v.Formula)
  51. }
  52. return
  53. }
  54. type CalculateItems struct {
  55. EdbInfoId int
  56. DataMap map[string]float64
  57. }
  58. func ReplaceFormula(edbInfoIdArr []*data_manage.EdbInfo, valArr map[int]float64, formulaMap map[string]string, formulaStr string, edbInfoIdBytes []string) string {
  59. // todo 处理min和max
  60. funMap := GetFormulaMap()
  61. for k, v := range funMap {
  62. formulaStr = strings.Replace(formulaStr, k, v, -1)
  63. }
  64. replaceCount := 0
  65. for dk, dv := range edbInfoIdArr {
  66. if dk == 0 {
  67. dKey := edbInfoIdBytes[dk]
  68. if _, ok := formulaMap[dKey]; ok { //公式中存在
  69. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  70. dvStr := fmt.Sprintf("%v", val)
  71. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  72. replaceCount++
  73. } else {
  74. fmt.Println("valArr not found:", valArr, valOk)
  75. }
  76. } else {
  77. fmt.Println("formulaMap not found:", dKey, dk)
  78. }
  79. }
  80. if dk == 1 {
  81. dKey := edbInfoIdBytes[dk]
  82. if _, ok := formulaMap[dKey]; ok { //公式中存在
  83. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  84. dvStr := fmt.Sprintf("%v", val)
  85. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  86. replaceCount++
  87. } else {
  88. fmt.Println("valArr not found:", valArr, valOk)
  89. }
  90. } else {
  91. fmt.Println("formulaMap not found:", dKey, dk)
  92. }
  93. }
  94. if dk == 2 {
  95. dKey := edbInfoIdBytes[dk]
  96. if _, ok := formulaMap[dKey]; ok { //公式中存在
  97. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  98. dvStr := fmt.Sprintf("%v", val)
  99. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  100. replaceCount++
  101. }
  102. }
  103. }
  104. if dk == 3 {
  105. dKey := edbInfoIdBytes[dk]
  106. if _, ok := formulaMap[dKey]; ok { //公式中存在
  107. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  108. dvStr := fmt.Sprintf("%v", val)
  109. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  110. replaceCount++
  111. }
  112. }
  113. }
  114. if dk == 4 {
  115. dKey := edbInfoIdBytes[dk]
  116. if _, ok := formulaMap[dKey]; ok { //公式中存在
  117. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  118. dvStr := fmt.Sprintf("%v", val)
  119. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  120. replaceCount++
  121. }
  122. }
  123. }
  124. if dk == 5 {
  125. dKey := edbInfoIdBytes[dk]
  126. if _, ok := formulaMap[dKey]; ok { //公式中存在
  127. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  128. dvStr := fmt.Sprintf("%v", val)
  129. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  130. replaceCount++
  131. }
  132. }
  133. }
  134. if dk == 6 {
  135. dKey := edbInfoIdBytes[dk]
  136. if _, ok := formulaMap[dKey]; ok { //公式中存在
  137. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  138. dvStr := fmt.Sprintf("%v", val)
  139. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  140. replaceCount++
  141. }
  142. }
  143. }
  144. if dk == 7 {
  145. dKey := edbInfoIdBytes[dk]
  146. if _, ok := formulaMap[dKey]; ok { //公式中存在
  147. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  148. dvStr := fmt.Sprintf("%v", val)
  149. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  150. replaceCount++
  151. }
  152. }
  153. }
  154. if dk == 8 {
  155. dKey := edbInfoIdBytes[dk]
  156. if _, ok := formulaMap[dKey]; ok { //公式中存在
  157. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  158. dvStr := fmt.Sprintf("%v", val)
  159. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  160. replaceCount++
  161. }
  162. }
  163. }
  164. if dk == 9 {
  165. dKey := edbInfoIdBytes[dk]
  166. if _, ok := formulaMap[dKey]; ok { //公式中存在
  167. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  168. dvStr := fmt.Sprintf("%v", val)
  169. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  170. replaceCount++
  171. }
  172. }
  173. }
  174. if dk == 10 {
  175. dKey := edbInfoIdBytes[dk]
  176. if _, ok := formulaMap[dKey]; ok { //公式中存在
  177. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  178. dvStr := fmt.Sprintf("%v", val)
  179. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  180. replaceCount++
  181. }
  182. }
  183. }
  184. if dk == 11 {
  185. dKey := edbInfoIdBytes[dk]
  186. if _, ok := formulaMap[dKey]; ok { //公式中存在
  187. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  188. dvStr := fmt.Sprintf("%v", val)
  189. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  190. replaceCount++
  191. }
  192. }
  193. }
  194. if dk == 12 {
  195. dKey := edbInfoIdBytes[dk]
  196. if _, ok := formulaMap[dKey]; ok { //公式中存在
  197. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  198. dvStr := fmt.Sprintf("%v", val)
  199. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  200. replaceCount++
  201. }
  202. }
  203. }
  204. if dk == 13 {
  205. dKey := edbInfoIdBytes[dk]
  206. if _, ok := formulaMap[dKey]; ok { //公式中存在
  207. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  208. dvStr := fmt.Sprintf("%v", val)
  209. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  210. replaceCount++
  211. }
  212. }
  213. }
  214. if dk == 14 {
  215. dKey := edbInfoIdBytes[dk]
  216. if _, ok := formulaMap[dKey]; ok { //公式中存在
  217. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  218. dvStr := fmt.Sprintf("%v", val)
  219. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  220. replaceCount++
  221. }
  222. }
  223. }
  224. if dk == 15 {
  225. dKey := edbInfoIdBytes[dk]
  226. if _, ok := formulaMap[dKey]; ok { //公式中存在
  227. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  228. dvStr := fmt.Sprintf("%v", val)
  229. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  230. replaceCount++
  231. }
  232. }
  233. }
  234. if dk == 16 {
  235. dKey := edbInfoIdBytes[dk]
  236. if _, ok := formulaMap[dKey]; ok { //公式中存在
  237. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  238. dvStr := fmt.Sprintf("%v", val)
  239. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  240. replaceCount++
  241. }
  242. }
  243. }
  244. if dk == 17 {
  245. dKey := edbInfoIdBytes[dk]
  246. if _, ok := formulaMap[dKey]; ok { //公式中存在
  247. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  248. dvStr := fmt.Sprintf("%v", val)
  249. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  250. replaceCount++
  251. }
  252. }
  253. }
  254. if dk == 18 {
  255. dKey := edbInfoIdBytes[dk]
  256. if _, ok := formulaMap[dKey]; ok { //公式中存在
  257. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  258. dvStr := fmt.Sprintf("%v", val)
  259. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  260. replaceCount++
  261. }
  262. }
  263. }
  264. if dk == 19 {
  265. dKey := edbInfoIdBytes[dk]
  266. if _, ok := formulaMap[dKey]; ok { //公式中存在
  267. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  268. dvStr := fmt.Sprintf("%v", val)
  269. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  270. replaceCount++
  271. }
  272. }
  273. }
  274. if dk == 20 {
  275. dKey := edbInfoIdBytes[dk]
  276. if _, ok := formulaMap[dKey]; ok { //公式中存在
  277. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  278. dvStr := fmt.Sprintf("%v", val)
  279. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  280. replaceCount++
  281. }
  282. }
  283. }
  284. if dk == 21 {
  285. dKey := edbInfoIdBytes[dk]
  286. if _, ok := formulaMap[dKey]; ok { //公式中存在
  287. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  288. dvStr := fmt.Sprintf("%v", val)
  289. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  290. replaceCount++
  291. }
  292. }
  293. }
  294. if dk == 22 {
  295. dKey := edbInfoIdBytes[dk]
  296. if _, ok := formulaMap[dKey]; ok { //公式中存在
  297. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  298. dvStr := fmt.Sprintf("%v", val)
  299. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  300. replaceCount++
  301. }
  302. }
  303. }
  304. if dk == 23 {
  305. dKey := edbInfoIdBytes[dk]
  306. if _, ok := formulaMap[dKey]; ok { //公式中存在
  307. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  308. dvStr := fmt.Sprintf("%v", val)
  309. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  310. replaceCount++
  311. }
  312. }
  313. }
  314. if dk == 24 {
  315. dKey := edbInfoIdBytes[dk]
  316. if _, ok := formulaMap[dKey]; ok { //公式中存在
  317. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  318. dvStr := fmt.Sprintf("%v", val)
  319. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  320. replaceCount++
  321. }
  322. }
  323. }
  324. if dk == 25 {
  325. dKey := edbInfoIdBytes[dk]
  326. if _, ok := formulaMap[dKey]; ok { //公式中存在
  327. if val, valOk := valArr[dv.EdbInfoId]; valOk { //值存在
  328. dvStr := fmt.Sprintf("%v", val)
  329. formulaStr = strings.Replace(formulaStr, dKey, dvStr, -1)
  330. replaceCount++
  331. }
  332. }
  333. }
  334. }
  335. for k, v := range funMap {
  336. formulaStr = strings.Replace(formulaStr, v, k, -1)
  337. }
  338. if replaceCount == len(formulaMap) {
  339. return formulaStr
  340. } else {
  341. return ""
  342. }
  343. }
  344. func GetFormulaMap() map[string]string {
  345. funMap := make(map[string]string)
  346. funMap["MAX"] = "[@@]"
  347. funMap["MIN"] = "[@!]"
  348. funMap["ABS"] = "[@#]"
  349. funMap["CEIL"] = "[@$]"
  350. funMap["COS"] = "[@%]"
  351. funMap["FLOOR"] = "[@^]"
  352. funMap["MOD"] = "[@&]"
  353. funMap["POW"] = "[@*]"
  354. funMap["ROUND"] = "[@(]"
  355. return funMap
  356. }
  357. // 处理整个数据
  358. func handleDateSaveDataMap(dateList []string, realSaveDataMap, saveDataMap map[string]map[int]float64, edbInfoIdArr []*data_manage.EdbInfo, emptyType int) {
  359. var startDate, endDate string
  360. var startDateT, endDateT time.Time
  361. if emptyType == 2 || emptyType == 3 {
  362. for k, _ := range realSaveDataMap {
  363. if k > endDate {
  364. endDate = k
  365. }
  366. if k < startDate || startDate == "" {
  367. startDate = k
  368. }
  369. }
  370. startDateT, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  371. endDateT, _ = time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  372. }
  373. for _, date := range dateList {
  374. tmpDataMap := realSaveDataMap[date]
  375. for _, edbInfo := range edbInfoIdArr {
  376. tmpEdbInfoId := edbInfo.EdbInfoId // 当前指标id
  377. // 如果该日期不存在该指标数据,那么需要找寻前后日期的数据,进行填补
  378. if _, ok := tmpDataMap[tmpEdbInfoId]; !ok {
  379. //day := 0
  380. //switch edbInfo.Frequency {
  381. //case "周度":
  382. // day = 7
  383. //case "旬度":
  384. // day = 15
  385. //case "月度":
  386. // day = 30
  387. //case "季度":
  388. // day = 90
  389. //case "年度":
  390. // day = 365
  391. //}
  392. // 需求池 255 指标运算文案修改,补数据遍历区间修改(2023-3-7 09:37:23修改)
  393. switch emptyType {
  394. case 0:
  395. handleDateDataMap(realSaveDataMap, saveDataMap, date, tmpEdbInfoId, 35)
  396. case 2:
  397. handleDateDataMapBefore(realSaveDataMap, saveDataMap, date, tmpEdbInfoId, startDateT, endDateT)
  398. case 3:
  399. handleDateDataMapAfter(realSaveDataMap, saveDataMap, date, tmpEdbInfoId, startDateT, endDateT)
  400. case 4:
  401. handleDateDataMapZero(saveDataMap, date, tmpEdbInfoId)
  402. }
  403. }
  404. }
  405. }
  406. }
  407. // handleDataMap 处理单个日期的数据
  408. func handleDateDataMap(realSaveDataMap, saveDataMap map[string]map[int]float64, date string, edbInfoId, day int) {
  409. currDate, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
  410. // 后一天
  411. nextDateDayStr := currDate.AddDate(0, 0, 1).Format(utils.FormatDate)
  412. // 前一天
  413. preDateDayStr := currDate.AddDate(0, 0, -1).Format(utils.FormatDate)
  414. for i := 1; i <= day; i++ {
  415. // 下个日期的数据
  416. {
  417. if i >= 1 {
  418. nextDateDayStr = currDate.AddDate(0, 0, i).Format(utils.FormatDate)
  419. }
  420. if findDataMap, hasFindDataMap := realSaveDataMap[nextDateDayStr]; hasFindDataMap { // 下一个日期有数据
  421. if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
  422. saveDataMap[date][edbInfoId] = val
  423. return
  424. }
  425. }
  426. }
  427. // 上个日期的数据
  428. {
  429. if i >= 1 {
  430. preDateDayStr = currDate.AddDate(0, 0, -i).Format(utils.FormatDate)
  431. }
  432. if findDataMap, hasFindDataMap := realSaveDataMap[preDateDayStr]; hasFindDataMap { // 下一个日期有数据
  433. if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
  434. saveDataMap[date][edbInfoId] = val
  435. return
  436. }
  437. }
  438. }
  439. }
  440. }
  441. // handleDataByLinearRegression 插值法补充数据(线性方程式)
  442. func handleDataByLinearRegression(edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (err error) {
  443. if len(edbInfoDataList) < 2 {
  444. return
  445. }
  446. var startEdbInfoData *data_manage.EdbDataList
  447. for _, v := range edbInfoDataList {
  448. handleDataMap[v.DataTime] = v.Value
  449. // 第一个数据就给过滤了,给后面的试用
  450. if startEdbInfoData == nil {
  451. startEdbInfoData = v
  452. continue
  453. }
  454. // 获取两条数据之间相差的天数
  455. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  456. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  457. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  458. betweenDay := betweenHour / 24
  459. // 如果相差一天,那么过滤
  460. if betweenDay <= 1 {
  461. startEdbInfoData = v
  462. continue
  463. }
  464. // 生成线性方程式
  465. var a, b float64
  466. {
  467. coordinateData := make([]utils.Coordinate, 0)
  468. tmpCoordinate1 := utils.Coordinate{
  469. X: 1,
  470. Y: startEdbInfoData.Value,
  471. }
  472. coordinateData = append(coordinateData, tmpCoordinate1)
  473. tmpCoordinate2 := utils.Coordinate{
  474. X: float64(betweenDay) + 1,
  475. Y: v.Value,
  476. }
  477. coordinateData = append(coordinateData, tmpCoordinate2)
  478. a, b = utils.GetLinearResult(coordinateData)
  479. if math.IsNaN(a) || math.IsNaN(b) {
  480. err = errors.New("线性方程公式生成失败")
  481. return
  482. }
  483. }
  484. // 生成对应的值
  485. {
  486. for i := 1; i < betweenDay; i++ {
  487. tmpDataTime := startDataTime.AddDate(0, 0, i)
  488. aDecimal := decimal.NewFromFloat(a)
  489. xDecimal := decimal.NewFromInt(int64(i) + 1)
  490. bDecimal := decimal.NewFromFloat(b)
  491. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  492. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
  493. }
  494. }
  495. startEdbInfoData = v
  496. }
  497. return
  498. }
  499. // HandleDataByLinearRegression 插值法补充数据(线性方程式)
  500. func HandleDataByLinearRegression(edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (err error) {
  501. return handleDataByLinearRegression(edbInfoDataList, handleDataMap)
  502. }
  503. // CallCalculateComputeCorrelation 调用计算拟合残差的相关系数
  504. func CallCalculateComputeCorrelation(data *data_manage.EdbInfoCalculateBatchSaveReqByEdbLib, lang string) (val string, err error, errMsg string) {
  505. errMsg = "计算失败"
  506. // 调用指标库去更新
  507. reqJson, err := json.Marshal(data)
  508. if err != nil {
  509. errMsg = "计算相关系数参数解析异常!"
  510. err = errors.New("参数解析失败,Err:" + err.Error())
  511. return
  512. }
  513. respItem, err := CalculateComputeCorrelation(string(reqJson), lang)
  514. if err != nil {
  515. return
  516. }
  517. if respItem.Ret == 200 {
  518. val = respItem.Data
  519. }
  520. return
  521. }
  522. // handleDateDataMapBefore 前值填充:空值优先以最近的前值填充,没有前值时,用后值填充
  523. func handleDateDataMapBefore(realSaveDataMap, saveDataMap map[string]map[int]float64, date string, edbInfoId int, startDateT, endDateT time.Time) {
  524. currDate, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
  525. // 后一天
  526. nextDateDay := currDate
  527. // 前一天
  528. preDateDay := currDate
  529. for i := 1; preDateDay.After(startDateT) || preDateDay == startDateT; i++ {
  530. // 上个日期的数据
  531. {
  532. preDateDay = currDate.AddDate(0, 0, -i)
  533. preDateDayStr := preDateDay.Format(utils.FormatDate)
  534. if findDataMap, hasFindDataMap := realSaveDataMap[preDateDayStr]; hasFindDataMap { // 下一个日期有数据
  535. if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
  536. fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, preDateDayStr, val))
  537. saveDataMap[date][edbInfoId] = val
  538. return
  539. }
  540. }
  541. }
  542. }
  543. for i := 1; nextDateDay.Before(endDateT) || nextDateDay == endDateT; i++ {
  544. // 下个日期的数据
  545. {
  546. nextDateDay = currDate.AddDate(0, 0, i)
  547. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  548. if findDataMap, hasFindDataMap := realSaveDataMap[nextDateDayStr]; hasFindDataMap { // 下一个日期有数据
  549. if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
  550. fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, nextDateDayStr, val))
  551. saveDataMap[date][edbInfoId] = val
  552. return
  553. }
  554. }
  555. }
  556. }
  557. return
  558. }
  559. // handleDateDataMapAfter 后值填充:空值优先以最近的后值填充,没有后值时,用前值填充
  560. func handleDateDataMapAfter(realSaveDataMap, saveDataMap map[string]map[int]float64, date string, edbInfoId int, startDateT, endDateT time.Time) {
  561. currDate, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
  562. // 后一天
  563. nextDateDay := currDate
  564. // 前一天
  565. preDateDay := currDate
  566. for i := 1; nextDateDay.Before(endDateT) || nextDateDay == endDateT; i++ {
  567. // 下个日期的数据
  568. {
  569. nextDateDay = currDate.AddDate(0, 0, i)
  570. nextDateDayStr := nextDateDay.Format(utils.FormatDate)
  571. if findDataMap, hasFindDataMap := realSaveDataMap[nextDateDayStr]; hasFindDataMap { // 下一个日期有数据
  572. if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
  573. fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, nextDateDayStr, val))
  574. saveDataMap[date][edbInfoId] = val
  575. return
  576. }
  577. }
  578. }
  579. }
  580. for i := 1; preDateDay.After(startDateT) || preDateDay == startDateT; i++ {
  581. // 上个日期的数据
  582. {
  583. preDateDay = currDate.AddDate(0, 0, -i)
  584. preDateDayStr := preDateDay.Format(utils.FormatDate)
  585. if findDataMap, hasFindDataMap := realSaveDataMap[preDateDayStr]; hasFindDataMap { // 下一个日期有数据
  586. if val, hasFindItem := findDataMap[edbInfoId]; hasFindItem {
  587. fmt.Println(fmt.Sprintf("date:%s, 无值,取%s的值%.4f", date, preDateDayStr, val))
  588. saveDataMap[date][edbInfoId] = val
  589. return
  590. }
  591. }
  592. }
  593. }
  594. return
  595. }
  596. // handleDateDataMapZero 等于0
  597. func handleDateDataMapZero(saveDataMap map[string]map[int]float64, date string, edbInfoId int) {
  598. saveDataMap[date][edbInfoId] = 0
  599. return
  600. }
  601. func GetMaxMinEdbInfo(formula string) string {
  602. //formula := "A+min(A,B,max(A,C))"
  603. // todo 无法处理max里嵌套max或者min的情况
  604. // 使用正则表达式匹配MAX和MIN函数及其参数
  605. regex := regexp.MustCompile(`(?i)(MAX|MIN)\((.*?)\)`)
  606. matches := regex.FindAllStringSubmatch(formula, -1)
  607. // 遍历匹配结果,输出MAX和MIN函数及其参数
  608. for _, match := range matches {
  609. if len(match) == 3 {
  610. parameter := strings.ToLower(match[0]) // 参数
  611. formula = strings.ReplaceAll(formula, match[0], parameter)
  612. fmt.Printf("formula: %s\n", formula)
  613. }
  614. }
  615. formula = strings.ReplaceAll(formula, "max", "MAX")
  616. formula = strings.ReplaceAll(formula, "min", "MIN")
  617. return formula
  618. }
  619. // HandleDataByLinearRegressionToList 插值法补充数据(线性方程式)
  620. func HandleDataByLinearRegressionToList (edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (dataTimeList []string,valueList []float64, err error) {
  621. if len(edbInfoDataList) < 2 {
  622. return
  623. }
  624. var startEdbInfoData *data_manage.EdbDataList
  625. for _, v := range edbInfoDataList {
  626. handleDataMap[v.DataTime] = v.Value
  627. dataTimeList = append(dataTimeList, v.DataTime)
  628. // 第一个数据就给过滤了,给后面的试用
  629. if startEdbInfoData == nil {
  630. startEdbInfoData = v
  631. //startEdbInfoData.DataTime = startEdbInfoData.DataTime[:5]+ "01-01"
  632. continue
  633. }
  634. // 获取两条数据之间相差的天数
  635. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  636. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  637. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  638. betweenDay := betweenHour / 24
  639. // 如果相差一天,那么过滤
  640. if betweenDay <= 1 {
  641. startEdbInfoData = v
  642. continue
  643. }
  644. // 生成线性方程式
  645. var a, b float64
  646. {
  647. coordinateData := make([]utils.Coordinate, 0)
  648. tmpCoordinate1 := utils.Coordinate{
  649. X: 1,
  650. Y: startEdbInfoData.Value,
  651. }
  652. coordinateData = append(coordinateData, tmpCoordinate1)
  653. tmpCoordinate2 := utils.Coordinate{
  654. X: float64(betweenDay) + 1,
  655. Y: v.Value,
  656. }
  657. coordinateData = append(coordinateData, tmpCoordinate2)
  658. a, b = utils.GetLinearResult(coordinateData)
  659. if math.IsNaN(a) || math.IsNaN(b) {
  660. err = errors.New("线性方程公式生成失败")
  661. return
  662. }
  663. }
  664. // 生成对应的值
  665. {
  666. for i := 1; i < betweenDay; i++ {
  667. tmpDataTime := startDataTime.AddDate(0, 0, i)
  668. aDecimal := decimal.NewFromFloat(a)
  669. xDecimal := decimal.NewFromInt(int64(i) + 1)
  670. bDecimal := decimal.NewFromFloat(b)
  671. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  672. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
  673. dataTimeList = append(dataTimeList, tmpDataTime.Format(utils.FormatDate))
  674. valueList = append(valueList, val)
  675. }
  676. }
  677. startEdbInfoData = v
  678. }
  679. return
  680. }
  681. // HandleDataByLinearRegressionToList 保证生成365个数据点的线性插值法
  682. func HandleDataByLinearRegressionToListV2(edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (dataTimeList []string, valueList []float64, err error) {
  683. if len(edbInfoDataList) < 2 {
  684. return
  685. }
  686. // 确保至少有两天数据来生成线性方程
  687. if len(edbInfoDataList) < 2 {
  688. err = errors.New("至少需要两天的数据来执行线性插值")
  689. return
  690. }
  691. // 对数据按日期排序,确保顺序正确
  692. sort.Slice(edbInfoDataList, func(i, j int) bool {
  693. t1, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[i].DataTime, time.Local)
  694. t2, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[j].DataTime, time.Local)
  695. return t1.Before(t2)
  696. })
  697. startEdbInfoData := edbInfoDataList[0]
  698. endEdbInfoData := edbInfoDataList[len(edbInfoDataList)-1]
  699. // 计算起始和结束日期间实际的天数
  700. startDate, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  701. endDate, _ := time.ParseInLocation(utils.FormatDate, endEdbInfoData.DataTime, time.Local)
  702. actualDays := endDate.Sub(startDate).Hours() / 24
  703. // 生成365个数据点,首先处理已有数据
  704. for _, v := range edbInfoDataList {
  705. handleDataMap[v.DataTime] = v.Value
  706. dataTimeList = append(dataTimeList, v.DataTime)
  707. valueList = append(valueList, v.Value)
  708. }
  709. // 如果已有数据跨越天数不足365天,则对缺失的日期进行线性插值
  710. if actualDays < 365 {
  711. // 使用已有数据点生成线性方程(这里简化处理,实际可能需更细致处理边界情况)
  712. var a, b float64
  713. coordinateData := []utils.Coordinate{
  714. {X: 1, Y: startEdbInfoData.Value},
  715. {X: float64(len(edbInfoDataList)), Y: endEdbInfoData.Value},
  716. }
  717. a, b = utils.GetLinearResult(coordinateData)
  718. if math.IsNaN(a) || math.IsNaN(b) {
  719. err = errors.New("线性方程公式生成失败")
  720. return
  721. }
  722. // 对剩余日期进行插值
  723. for i := 1; i < 365; i++ {
  724. day := startDate.AddDate(0, 0, i)
  725. if _, exists := handleDataMap[day.Format(utils.FormatDate)]; !exists {
  726. aDecimal := decimal.NewFromFloat(a)
  727. xDecimal := decimal.NewFromInt(int64(i) + 1)
  728. bDecimal := decimal.NewFromFloat(b)
  729. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  730. handleDataMap[day.Format(utils.FormatDate)] = val
  731. dataTimeList = append(dataTimeList, day.Format(utils.FormatDate))
  732. valueList = append(valueList, val)
  733. }
  734. }
  735. }
  736. return
  737. }
  738. // HandleDataByLinearRegressionToListV3 插值法补充数据(线性方程式)-直接补充指标起始日期间的所有数据
  739. func HandleDataByLinearRegressionToListV3 (edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (newEdbInfoDataList []*data_manage.EdbDataList, dataTimeList []string,valueList []float64, err error) {
  740. if len(edbInfoDataList) < 2 {
  741. return
  742. }
  743. var startEdbInfoData *data_manage.EdbDataList
  744. for _, v := range edbInfoDataList {
  745. handleDataMap[v.DataTime] = v.Value
  746. newEdbInfoDataList = append(newEdbInfoDataList, v)
  747. dataTimeList = append(dataTimeList, v.DataTime)
  748. // 第一个数据就给过滤了,给后面的试用
  749. if startEdbInfoData == nil {
  750. startEdbInfoData = v
  751. //startEdbInfoData.DataTime = startEdbInfoData.DataTime[:5]+ "01-01"
  752. continue
  753. }
  754. // 获取两条数据之间相差的天数
  755. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  756. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  757. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  758. betweenDay := betweenHour / 24
  759. // 如果相差一天,那么过滤
  760. if betweenDay <= 1 {
  761. startEdbInfoData = v
  762. continue
  763. }
  764. // 生成线性方程式
  765. var a, b float64
  766. {
  767. coordinateData := make([]utils.Coordinate, 0)
  768. tmpCoordinate1 := utils.Coordinate{
  769. X: 1,
  770. Y: startEdbInfoData.Value,
  771. }
  772. coordinateData = append(coordinateData, tmpCoordinate1)
  773. tmpCoordinate2 := utils.Coordinate{
  774. X: float64(betweenDay) + 1,
  775. Y: v.Value,
  776. }
  777. coordinateData = append(coordinateData, tmpCoordinate2)
  778. a, b = utils.GetLinearResult(coordinateData)
  779. if math.IsNaN(a) || math.IsNaN(b) {
  780. err = errors.New("线性方程公式生成失败")
  781. return
  782. }
  783. }
  784. // 生成对应的值
  785. {
  786. for i := 1; i < betweenDay; i++ {
  787. tmpDataTime := startDataTime.AddDate(0, 0, i)
  788. aDecimal := decimal.NewFromFloat(a)
  789. xDecimal := decimal.NewFromInt(int64(i) + 1)
  790. bDecimal := decimal.NewFromFloat(b)
  791. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  792. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
  793. dataTimeList = append(dataTimeList, tmpDataTime.Format(utils.FormatDate))
  794. valueList = append(valueList, val)
  795. newEdbInfoDataList = append(newEdbInfoDataList, &data_manage.EdbDataList{
  796. EdbDataId: v.EdbDataId,
  797. EdbInfoId: v.EdbInfoId,
  798. DataTime: tmpDataTime.Format(utils.FormatDate),
  799. DataTimestamp: tmpDataTime.UnixNano() / 1e6,
  800. Value: val,
  801. })
  802. }
  803. }
  804. startEdbInfoData = v
  805. }
  806. return
  807. }