chart_info.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  1. package correlation
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/shopspring/decimal"
  7. "eta/eta_mobile/models/data_manage"
  8. "eta/eta_mobile/models/system"
  9. "eta/eta_mobile/services/alarm_msg"
  10. "eta/eta_mobile/services/data"
  11. "eta/eta_mobile/utils"
  12. "math"
  13. "sort"
  14. "strconv"
  15. "strings"
  16. "time"
  17. )
  18. // HandleDataByLinearRegression 线性方程插值法补全数据
  19. func HandleDataByLinearRegression(originList []*data_manage.EdbDataList, handleDataMap map[string]float64) (newList []*data_manage.EdbDataList, err error) {
  20. if len(originList) < 2 {
  21. return
  22. }
  23. var startEdbInfoData *data_manage.EdbDataList
  24. for _, v := range originList {
  25. handleDataMap[v.DataTime] = v.Value
  26. // 第一个数据就给过滤了,给后面的试用
  27. if startEdbInfoData == nil {
  28. startEdbInfoData = v
  29. newList = append(newList, &data_manage.EdbDataList{
  30. DataTime: v.DataTime,
  31. Value: v.Value,
  32. })
  33. continue
  34. }
  35. // 获取两条数据之间相差的天数
  36. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  37. currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  38. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  39. betweenDay := betweenHour / 24
  40. // 如果相差一天,那么过滤
  41. if betweenDay <= 1 {
  42. startEdbInfoData = v
  43. newList = append(newList, &data_manage.EdbDataList{
  44. DataTime: v.DataTime,
  45. Value: v.Value,
  46. })
  47. continue
  48. }
  49. // 生成线性方程式
  50. var a, b float64
  51. {
  52. coordinateData := make([]utils.Coordinate, 0)
  53. tmpCoordinate1 := utils.Coordinate{
  54. X: 1,
  55. Y: startEdbInfoData.Value,
  56. }
  57. coordinateData = append(coordinateData, tmpCoordinate1)
  58. tmpCoordinate2 := utils.Coordinate{
  59. X: float64(betweenDay) + 1,
  60. Y: v.Value,
  61. }
  62. coordinateData = append(coordinateData, tmpCoordinate2)
  63. a, b = utils.GetLinearResult(coordinateData)
  64. if math.IsNaN(a) || math.IsNaN(b) {
  65. err = fmt.Errorf("线性方程公式生成失败")
  66. return
  67. }
  68. }
  69. // 生成对应的值
  70. {
  71. for i := 1; i < betweenDay; i++ {
  72. tmpDataTime := startDataTime.AddDate(0, 0, i)
  73. aDecimal := decimal.NewFromFloat(a)
  74. xDecimal := decimal.NewFromInt(int64(i) + 1)
  75. bDecimal := decimal.NewFromFloat(b)
  76. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  77. handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
  78. newList = append(newList, &data_manage.EdbDataList{
  79. DataTime: tmpDataTime.Format(utils.FormatDate),
  80. Value: val,
  81. })
  82. }
  83. }
  84. // 最后将自己赋值
  85. newList = append(newList, &data_manage.EdbDataList{
  86. EdbDataId: v.EdbDataId,
  87. DataTime: v.DataTime,
  88. Value: v.Value,
  89. })
  90. startEdbInfoData = v
  91. }
  92. return
  93. }
  94. // MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
  95. func MoveDataDaysToNewDataList(dataList []*data_manage.EdbDataList, moveDay int) (newDataList []data_manage.EdbDataList, dateDataMap map[string]float64) {
  96. dateMap := make(map[time.Time]float64)
  97. var minDate, maxDate time.Time
  98. dateDataMap = make(map[string]float64)
  99. for _, v := range dataList {
  100. currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
  101. if minDate.IsZero() || currDate.Before(minDate) {
  102. minDate = currDate
  103. }
  104. if maxDate.IsZero() || currDate.After(maxDate) {
  105. maxDate = currDate
  106. }
  107. dateMap[currDate] = v.Value
  108. }
  109. // 处理领先、滞后数据
  110. newDateMap := make(map[time.Time]float64)
  111. for currDate, value := range dateMap {
  112. newDate := currDate.AddDate(0, 0, moveDay)
  113. newDateMap[newDate] = value
  114. }
  115. minDate = minDate.AddDate(0, 0, moveDay)
  116. maxDate = maxDate.AddDate(0, 0, moveDay)
  117. // 获取日期相差日
  118. dayNum := utils.GetTimeSubDay(minDate, maxDate)
  119. for i := 0; i <= dayNum; i++ {
  120. currDate := minDate.AddDate(0, 0, i)
  121. tmpValue, ok := newDateMap[currDate]
  122. if !ok {
  123. //找不到数据,那么就用前面的数据吧
  124. if len(newDataList)-1 < 0 {
  125. tmpValue = 0
  126. } else {
  127. tmpValue = newDataList[len(newDataList)-1].Value
  128. }
  129. }
  130. tmpData := data_manage.EdbDataList{
  131. DataTime: currDate.Format(utils.FormatDate),
  132. Value: tmpValue,
  133. }
  134. dateDataMap[tmpData.DataTime] = tmpData.Value
  135. newDataList = append(newDataList, tmpData)
  136. }
  137. return
  138. }
  139. // GetChartEdbInfoFormat 相关性图表-获取指标信息
  140. func GetChartEdbInfoFormat(chartInfoId int, edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping) (edbList []*data_manage.ChartEdbInfoMapping, err error) {
  141. edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
  142. if edbInfoMappingA == nil || edbInfoMappingB == nil {
  143. err = fmt.Errorf("指标信息有误")
  144. return
  145. }
  146. edbInfoMappingA.FrequencyEn = data.GetFrequencyEn(edbInfoMappingA.Frequency)
  147. if edbInfoMappingA.Unit == `无` {
  148. edbInfoMappingA.Unit = ``
  149. }
  150. if edbInfoMappingB.Unit == `无` {
  151. edbInfoMappingB.Unit = ``
  152. }
  153. if chartInfoId <= 0 {
  154. edbInfoMappingA.IsAxis = 1
  155. edbInfoMappingA.LeadValue = 0
  156. edbInfoMappingA.LeadUnit = ""
  157. edbInfoMappingA.ChartEdbMappingId = 0
  158. edbInfoMappingA.ChartInfoId = 0
  159. edbInfoMappingA.IsOrder = false
  160. edbInfoMappingA.EdbInfoType = 1
  161. edbInfoMappingA.ChartStyle = ""
  162. edbInfoMappingA.ChartColor = ""
  163. edbInfoMappingA.ChartWidth = 0
  164. edbInfoMappingB.IsAxis = 1
  165. edbInfoMappingB.LeadValue = 0
  166. edbInfoMappingB.LeadUnit = ""
  167. edbInfoMappingB.ChartEdbMappingId = 0
  168. edbInfoMappingB.ChartInfoId = 0
  169. edbInfoMappingB.IsOrder = false
  170. edbInfoMappingB.EdbInfoType = 1
  171. edbInfoMappingB.ChartStyle = ""
  172. edbInfoMappingB.ChartColor = ""
  173. edbInfoMappingB.ChartWidth = 0
  174. } else {
  175. edbInfoMappingA.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingA.LeadUnit)
  176. edbInfoMappingB.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingB.LeadUnit)
  177. }
  178. edbList = append(edbList, edbInfoMappingA, edbInfoMappingB)
  179. return
  180. }
  181. // GetChartAndCorrelationInfo 获取图表信息和相关信息信息
  182. func GetChartAndCorrelationInfo(chartInfoId int) (chartInfo *data_manage.ChartInfo, correlationInfo *data_manage.ChartInfoCorrelation, tips string, err error) {
  183. item, e := data_manage.GetChartInfoById(chartInfoId)
  184. if e != nil {
  185. if e.Error() == utils.ErrNoRow() {
  186. tips = "图表已被删除, 请刷新页面"
  187. err = fmt.Errorf("图表已被删除, 请刷新页面")
  188. return
  189. }
  190. err = fmt.Errorf("获取图表信息失败, Err: %s", e.Error())
  191. return
  192. }
  193. if item.Source != utils.CHART_SOURCE_CORRELATION {
  194. tips = "该图不是相关性图表"
  195. err = fmt.Errorf("该图不是相关性图表")
  196. return
  197. }
  198. chartInfo = item
  199. correlationInfo = new(data_manage.ChartInfoCorrelation)
  200. if e = correlationInfo.GetItemById(chartInfo.ChartInfoId); e != nil {
  201. err = fmt.Errorf("获取图表相关性信息失败, Err: %s", e.Error())
  202. return
  203. }
  204. return
  205. }
  206. // GetChartDataByEdbInfo 相关性图表-根据指标信息获取x轴和y轴
  207. func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit, startDate, endDate string) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
  208. xData := make([]int, 0)
  209. yData := make([]float64, 0)
  210. if leadValue == 0 {
  211. xData = append(xData, 0)
  212. }
  213. if leadValue > 0 {
  214. leadMin := 0 - leadValue
  215. xLen := 2*leadValue + 1
  216. for i := 0; i < xLen; i++ {
  217. n := leadMin + i
  218. xData = append(xData, n)
  219. }
  220. }
  221. // 计算窗口,不包含第一天
  222. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  223. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  224. //// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
  225. //baseEdbInfo := edbInfoMappingB
  226. //changeEdbInfo := edbInfoMappingA
  227. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  228. baseEdbInfo := edbInfoMappingA
  229. changeEdbInfo := edbInfoMappingB
  230. // 获取时间基准指标在时间区间内的值
  231. aDataList := make([]*data_manage.EdbDataList, 0)
  232. switch baseEdbInfo.EdbInfoCategoryType {
  233. case 0:
  234. aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
  235. case 1:
  236. _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
  237. default:
  238. err = errors.New("指标base类型异常")
  239. return
  240. }
  241. // 获取变频指标所有日期的值, 插值法完善数据
  242. bDataList := make([]*data_manage.EdbDataList, 0)
  243. switch changeEdbInfo.EdbInfoCategoryType {
  244. case 0:
  245. bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
  246. case 1:
  247. _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  248. default:
  249. err = errors.New("指标change类型异常")
  250. return
  251. }
  252. //changeDataMap := make(map[string]float64)
  253. //newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  254. //if e != nil {
  255. // err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  256. // return
  257. //}
  258. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  259. baseDataList := make([]*data_manage.EdbDataList, 0)
  260. baseDataMap := make(map[string]float64)
  261. changeDataList := make([]*data_manage.EdbDataList, 0)
  262. changeDataMap := make(map[string]float64)
  263. // 先把低频指标升频为高频
  264. {
  265. frequencyIntMap := map[string]int{
  266. "日度": 1,
  267. "周度": 2,
  268. "旬度": 3,
  269. "月度": 4,
  270. "季度": 5,
  271. "年度": 6,
  272. }
  273. // 如果A指标是高频,那么就需要对B指标进行升频
  274. if frequencyIntMap[edbInfoMappingA.Frequency] < frequencyIntMap[edbInfoMappingB.Frequency] {
  275. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  276. if e != nil {
  277. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  278. return
  279. }
  280. changeDataList = tmpNewChangeDataList
  281. baseDataList = aDataList
  282. for _, v := range baseDataList {
  283. baseDataMap[v.DataTime] = v.Value
  284. }
  285. } else if frequencyIntMap[edbInfoMappingA.Frequency] > frequencyIntMap[edbInfoMappingB.Frequency] {
  286. // 如果B指标是高频,那么就需要对A指标进行升频
  287. tmpNewChangeDataList, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  288. if e != nil {
  289. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  290. return
  291. }
  292. baseDataList = tmpNewChangeDataList
  293. changeDataList = bDataList
  294. for _, v := range changeDataList {
  295. changeDataMap[v.DataTime] = v.Value
  296. }
  297. } else {
  298. baseDataList = aDataList
  299. for _, v := range baseDataList {
  300. baseDataMap[v.DataTime] = v.Value
  301. }
  302. changeDataList = bDataList
  303. for _, v := range changeDataList {
  304. changeDataMap[v.DataTime] = v.Value
  305. }
  306. }
  307. }
  308. // 计算不领先也不滞后时的相关系数
  309. baseCalculateData := make([]float64, 0)
  310. baseDataTimeArr := make([]string, 0)
  311. for i := range baseDataList {
  312. baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
  313. baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
  314. }
  315. zeroBaseData := make([]float64, 0)
  316. zeroCalculateData := make([]float64, 0)
  317. for i := range baseDataTimeArr {
  318. tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
  319. tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
  320. if ok1 && ok2 {
  321. zeroBaseData = append(zeroBaseData, tmpBaseVal)
  322. zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
  323. }
  324. }
  325. if len(zeroBaseData) != len(zeroCalculateData) {
  326. err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
  327. return
  328. }
  329. zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
  330. if leadValue == 0 {
  331. yData = append(yData, zeroRatio)
  332. }
  333. // 计算领先/滞后N期
  334. if leadValue > 0 {
  335. // 平移变频指标领先/滞后的日期(单位天)
  336. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  337. for i := range xData {
  338. if xData[i] == 0 {
  339. yData = append(yData, zeroRatio)
  340. continue
  341. }
  342. xCalculateData := make([]float64, 0)
  343. yCalculateData := make([]float64, 0)
  344. // 平移指定天数
  345. mDays := int(moveUnitDays) * xData[i]
  346. _, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
  347. // 取出对应的基准日期的值
  348. for i2 := range baseDataTimeArr {
  349. if yVal, ok := dMap[baseDataTimeArr[i2]]; ok {
  350. xCalculateData = append(xCalculateData, baseCalculateData[i2])
  351. yCalculateData = append(yCalculateData, yVal)
  352. }
  353. }
  354. if len(yCalculateData) <= 0 {
  355. //err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
  356. //return
  357. // 领先滞后后,没有可以计算的数据了
  358. continue
  359. }
  360. // 公式计算出领先/滞后频度对应点的相关性系数
  361. ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
  362. yData = append(yData, ratio)
  363. }
  364. }
  365. xEdbIdValue = xData
  366. yDataList = make([]data_manage.YData, 0)
  367. yDate := "0000-00-00"
  368. yDataList = append(yDataList, data_manage.YData{
  369. Date: yDate,
  370. Value: yData,
  371. })
  372. return
  373. }
  374. // RollingCorrelationChartDataResp 滚动相关性图表数据
  375. type RollingCorrelationChartDataResp struct {
  376. MaxData float64
  377. MinData float64
  378. LatestDate string `description:"真实数据的最后日期"`
  379. EdbInfoCategoryType int
  380. ChartColor string
  381. ChartStyle string
  382. PredictChartColor string
  383. ChartType int
  384. ChartWidth int
  385. EdbName string
  386. EdbNameEn string
  387. Unit string
  388. UnitEn string
  389. IsAxis int
  390. DataList []data_manage.EdbDataList
  391. }
  392. // GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
  393. func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate, chartName, chartNameEn string) (dataResp RollingCorrelationChartDataResp, err error) {
  394. dataResp = RollingCorrelationChartDataResp{
  395. DataList: make([]data_manage.EdbDataList, 0),
  396. MaxData: 0,
  397. MinData: 0,
  398. ChartColor: "#00f",
  399. ChartStyle: `spline`,
  400. PredictChartColor: `#00f`,
  401. ChartType: 0,
  402. ChartWidth: 3,
  403. EdbName: chartName,
  404. EdbNameEn: chartNameEn,
  405. IsAxis: 1,
  406. }
  407. dataList := make([]data_manage.EdbDataList, 0)
  408. // 计算窗口,不包含第一天
  409. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  410. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  411. baseEdbInfo := edbInfoMappingA
  412. changeEdbInfo := edbInfoMappingB
  413. // 获取时间基准指标在时间区间内的值
  414. aDataList := make([]*data_manage.EdbDataList, 0)
  415. switch baseEdbInfo.EdbInfoCategoryType {
  416. case 0:
  417. aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
  418. case 1:
  419. _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, true)
  420. default:
  421. err = errors.New("指标base类型异常")
  422. return
  423. }
  424. // 获取变频指标所有日期的值, 插值法完善数据
  425. bDataList := make([]*data_manage.EdbDataList, 0)
  426. switch changeEdbInfo.EdbInfoCategoryType {
  427. case 0:
  428. bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
  429. case 1:
  430. _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  431. default:
  432. err = errors.New("指标change类型异常")
  433. return
  434. }
  435. // 数据平移变频指标领先/滞后的日期(单位天)
  436. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  437. //baseDataList := make([]*data_manage.EdbDataList, 0)
  438. baseDataMap := make(map[string]float64)
  439. changeDataList := make([]*data_manage.EdbDataList, 0)
  440. changeDataMap := make(map[string]float64)
  441. // A指标不管三七二十一,先变个频再说
  442. {
  443. _, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  444. if e != nil {
  445. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  446. return
  447. }
  448. //baseDataList = tmpNewChangeDataList
  449. }
  450. // B指标不管三七二十一,先变个频再说
  451. {
  452. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  453. if e != nil {
  454. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  455. return
  456. }
  457. changeDataList = tmpNewChangeDataList
  458. // 平移下日期
  459. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  460. _, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
  461. }
  462. // 计算计算时,需要多少个日期内数据
  463. calculateDay := utils.FrequencyDaysMap[calculateUnit] * calculateValue
  464. // 计算 每个日期的相关性值
  465. {
  466. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  467. if endDate == `` {
  468. endDate = baseEdbInfo.EndDate
  469. }
  470. endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  471. endDateTime = endDateTime.AddDate(0, 0, -(calculateDay - 1))
  472. // 是否开始第一条数据
  473. var isStart, isNotFirst bool
  474. for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
  475. yCalculateData := make([]float64, 0)
  476. baseCalculateData := make([]float64, 0)
  477. // 取出对应的基准日期的值
  478. for i := 0; i < calculateDay; i++ {
  479. iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
  480. tmpBaseValue, ok1 := baseDataMap[iDay]
  481. tmpChangeValue, ok2 := changeDataMap[iDay]
  482. if ok1 && ok2 {
  483. baseCalculateData = append(baseCalculateData, tmpBaseValue)
  484. yCalculateData = append(yCalculateData, tmpChangeValue)
  485. } else {
  486. continue
  487. }
  488. }
  489. // 公式计算出领先/滞后频度对应点的相关性系数
  490. var ratio float64
  491. if len(baseCalculateData) > 0 {
  492. ratio = utils.CalculateCorrelationByIntArr(baseCalculateData, yCalculateData)
  493. } else {
  494. // 没有数据的话,那就不返回
  495. continue
  496. }
  497. // 过滤前面都是0的数据
  498. {
  499. if ratio != 0 {
  500. isStart = true
  501. }
  502. if !isStart {
  503. continue
  504. }
  505. }
  506. dataTime := currDay.AddDate(0, 0, calculateDay-1)
  507. dataList = append(dataList, data_manage.EdbDataList{
  508. //EdbDataId: 0,
  509. EdbInfoId: 0,
  510. DataTime: dataTime.Format(utils.FormatDate),
  511. DataTimestamp: dataTime.UnixNano() / 1e6,
  512. Value: ratio,
  513. })
  514. if !isNotFirst {
  515. dataResp.MinData = ratio
  516. dataResp.MaxData = ratio
  517. isNotFirst = true
  518. }
  519. if dataResp.MinData > ratio {
  520. dataResp.MinData = ratio
  521. }
  522. if dataResp.MaxData < ratio {
  523. dataResp.MaxData = ratio
  524. }
  525. }
  526. dataResp.DataList = dataList
  527. }
  528. return
  529. }
  530. // ChartInfoRefresh 图表刷新
  531. func ChartInfoRefresh(chartInfoId int) (err error) {
  532. var errMsg string
  533. defer func() {
  534. if err != nil {
  535. go alarm_msg.SendAlarmMsg("CorrelationChartInfoRefresh: "+errMsg, 3)
  536. }
  537. }()
  538. correlationChart := new(data_manage.ChartInfoCorrelation)
  539. if err = correlationChart.GetItemById(chartInfoId); err != nil {
  540. errMsg = "获取相关性图表失败, Err: " + err.Error()
  541. return
  542. }
  543. // 批量刷新ETA指标
  544. err = data.EdbInfoRefreshAllFromBaseV3([]int{correlationChart.EdbInfoIdFirst, correlationChart.EdbInfoIdSecond}, false)
  545. if err != nil {
  546. return
  547. }
  548. // 重新生成数据并更新
  549. edbInfoMappingA, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
  550. if err != nil {
  551. errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + err.Error()
  552. return
  553. }
  554. edbInfoMappingB, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
  555. if err != nil {
  556. errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + err.Error()
  557. return
  558. }
  559. periodData, correlationData, err := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate))
  560. if err != nil {
  561. errMsg = "获取相关性图表, 图表计算值失败, Err:" + err.Error()
  562. return
  563. }
  564. periodDataByte, err := json.Marshal(periodData)
  565. if err != nil {
  566. errMsg = "相关性图表, X轴信息有误, Err:" + err.Error()
  567. return
  568. }
  569. correlationDataByte, err := json.Marshal(correlationData[0].Value)
  570. if err != nil {
  571. errMsg = "相关性图表, Y轴信息有误, Err:" + err.Error()
  572. return
  573. }
  574. correlationChart.PeriodData = string(periodDataByte)
  575. correlationChart.CorrelationData = string(correlationDataByte)
  576. correlationChart.ModifyTime = time.Now().Local()
  577. correlationUpdateCols := []string{"PeriodData", "CorrelationData", "ModifyTime"}
  578. if err = correlationChart.Update(correlationUpdateCols); err != nil {
  579. errMsg = "更新相关性图表失败, Err:" + err.Error()
  580. return
  581. }
  582. return
  583. }
  584. // AddChartInfo 添加图表
  585. func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.Admin) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  586. isSendEmail = true
  587. req.ChartName = strings.Trim(req.ChartName, " ")
  588. if req.ChartName == "" {
  589. errMsg = "请填写图表名称!"
  590. err = errors.New(errMsg)
  591. isSendEmail = false
  592. return
  593. }
  594. if req.ChartClassifyId <= 0 {
  595. errMsg = "分类参数错误!"
  596. err = errors.New(errMsg)
  597. isSendEmail = false
  598. return
  599. }
  600. // 相关性图表配置
  601. if req.CorrelationChartInfo.LeadValue == 0 {
  602. errMsg = "请输入领先期数"
  603. err = errors.New(errMsg)
  604. isSendEmail = false
  605. return
  606. }
  607. if req.CorrelationChartInfo.LeadUnit == "" {
  608. errMsg = "请填写领先单位"
  609. err = errors.New(errMsg)
  610. isSendEmail = false
  611. return
  612. }
  613. //if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
  614. // errMsg = "请填写开始结束日期"
  615. // err = errors.New(errMsg)
  616. // isSendEmail = false
  617. // return
  618. //}
  619. //startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
  620. //if e != nil {
  621. // errMsg = "开始日期格式有误"
  622. // err = errors.New(errMsg)
  623. // isSendEmail = false
  624. // return
  625. //}
  626. //endDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
  627. //if e != nil {
  628. // errMsg = "结束日期格式有误"
  629. // err = errors.New(errMsg)
  630. // isSendEmail = false
  631. // return
  632. //}
  633. if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
  634. errMsg = "请选择AB指标"
  635. err = errors.New(errMsg)
  636. isSendEmail = false
  637. return
  638. }
  639. chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
  640. if err != nil {
  641. if err.Error() == utils.ErrNoRow() {
  642. errMsg = "分类不存在"
  643. err = errors.New(errMsg)
  644. isSendEmail = false
  645. return
  646. }
  647. errMsg = "获取分类信息失败"
  648. err = errors.New("获取分类信息失败,Err:" + err.Error())
  649. return
  650. }
  651. if chartClassify == nil {
  652. errMsg = "分类不存在"
  653. err = errors.New(errMsg)
  654. isSendEmail = false
  655. return
  656. }
  657. var edbInfoIdArr []int
  658. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  659. edbInfoId := v.EdbInfoId
  660. edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
  661. if tmpErr != nil {
  662. if tmpErr.Error() == utils.ErrNoRow() {
  663. errMsg = "指标不存在!"
  664. err = errors.New("指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId))
  665. return
  666. } else {
  667. errMsg = "获取指标信息失败!"
  668. err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
  669. return
  670. }
  671. }
  672. if edbInfo == nil {
  673. errMsg = "指标已被删除,请重新选择!"
  674. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  675. return
  676. } else {
  677. if edbInfo.EdbInfoId <= 0 {
  678. errMsg = "指标已被删除,请重新选择!"
  679. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  680. return
  681. }
  682. }
  683. edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
  684. edbInfo.EdbNameSource = edbInfo.EdbName
  685. }
  686. sort.Ints(edbInfoIdArr)
  687. var edbInfoIdArrStr []string
  688. for _, v := range edbInfoIdArr {
  689. edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
  690. }
  691. edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
  692. var chartInfoId int
  693. // 判断图表是否存在
  694. var condition string
  695. var pars []interface{}
  696. condition += " AND chart_name=? AND source = ? "
  697. pars = append(pars, req.ChartName, source)
  698. count, err := data_manage.GetChartInfoCountByCondition(condition, pars)
  699. if err != nil {
  700. errMsg = "判断图表名称是否存在失败"
  701. err = errors.New("判断图表名称是否存在失败,Err:" + err.Error())
  702. return
  703. }
  704. if count > 0 {
  705. errMsg = "图表已存在,请重新填写"
  706. err = errors.New(errMsg)
  707. isSendEmail = false
  708. return
  709. }
  710. disableVal := data.CheckIsDisableChart(edbInfoIdArr)
  711. chartInfo = new(data_manage.ChartInfo)
  712. chartInfo.ChartName = req.ChartName
  713. chartInfo.EdbInfoIds = edbInfoIdStr
  714. chartInfo.ChartClassifyId = req.ChartClassifyId
  715. chartInfo.SysUserId = sysUser.AdminId
  716. chartInfo.SysUserRealName = sysUser.RealName
  717. chartInfo.CreateTime = time.Now()
  718. chartInfo.ModifyTime = time.Now()
  719. chartInfo.IsSetName = 0
  720. timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  721. chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
  722. chartInfo.ChartType = 9 // 相关性图
  723. chartInfo.Calendar = "公历"
  724. chartInfo.DateType = 6
  725. chartInfo.StartDate = req.StartDate
  726. chartInfo.EndDate = req.EndDate
  727. chartInfo.SeasonStartDate = req.SeasonStartDate
  728. chartInfo.SeasonEndDate = req.SeasonEndDate
  729. chartInfo.LeftMin = req.LeftMin
  730. chartInfo.LeftMax = req.LeftMax
  731. chartInfo.RightMin = req.RightMin
  732. chartInfo.RightMax = req.RightMax
  733. chartInfo.Disabled = disableVal
  734. chartInfo.Source = source
  735. // 指标信息
  736. mapList := make([]*data_manage.ChartEdbMapping, 0)
  737. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  738. mapItem := new(data_manage.ChartEdbMapping)
  739. mapItem.EdbInfoId = v.EdbInfoId
  740. mapItem.CreateTime = time.Now()
  741. mapItem.ModifyTime = time.Now()
  742. timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  743. mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp + "_" + strconv.Itoa(v.EdbInfoId))
  744. mapItem.IsOrder = true
  745. mapItem.IsAxis = 1
  746. mapItem.EdbInfoType = 1
  747. mapItem.Source = utils.CHART_SOURCE_CORRELATION
  748. mapList = append(mapList, mapItem)
  749. }
  750. // 相关性图表扩展信息
  751. correlationChart := new(data_manage.ChartInfoCorrelation)
  752. correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
  753. correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
  754. correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
  755. correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
  756. correlationChart.BaseCalculateValue = req.CorrelationChartInfo.BaseCalculateValue
  757. correlationChart.BaseCalculateUnit = req.CorrelationChartInfo.BaseCalculateUnit
  758. correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
  759. correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
  760. correlationChart.CreateTime = time.Now().Local()
  761. correlationChart.ModifyTime = time.Now().Local()
  762. //// 生成图表x轴y轴数据
  763. //edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
  764. //if e != nil {
  765. // errMsg = "获取失败"
  766. // err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
  767. // return
  768. //}
  769. //edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
  770. //if e != nil {
  771. // errMsg = "获取失败"
  772. // err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
  773. // return
  774. //}
  775. //periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
  776. //if e != nil {
  777. // errMsg = "获取失败"
  778. // err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
  779. // return
  780. //}
  781. //periodDataByte, e := json.Marshal(periodData)
  782. //if e != nil {
  783. // errMsg = "获取失败"
  784. // err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
  785. // return
  786. //}
  787. //correlationDataByte, e := json.Marshal(correlationData[0].Value)
  788. //if e != nil {
  789. // errMsg = "获取失败"
  790. // err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
  791. // return
  792. //}
  793. //correlationChart.PeriodData = string(periodDataByte)
  794. //correlationChart.CorrelationData = string(correlationDataByte)
  795. // 新增图表和指标mapping
  796. chartInfoId, e := data_manage.CreateCorrelationChartAndEdb(chartInfo, mapList, correlationChart)
  797. if e != nil {
  798. errMsg = "操作失败"
  799. err = errors.New("新增相关性图表失败, Err: " + e.Error())
  800. return
  801. }
  802. //添加es数据
  803. go data.EsAddOrEditChartInfo(chartInfoId)
  804. return
  805. }
  806. // CopyChartInfo 复制图表
  807. func CopyChartInfo(configId, classifyId int, chartName string, correlationChartInfoReq data_manage.CorrelationChartInfoReq, sysUser *system.Admin) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  808. configSource := 2
  809. isSendEmail = true
  810. // 获取相关性图的配置
  811. multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(configId, configSource)
  812. if err != nil {
  813. return
  814. }
  815. multipleGraphConfig, err := data_manage.GetMultipleGraphConfigById(configId)
  816. if err != nil {
  817. return
  818. }
  819. multipleGraphConfig.MultipleGraphConfigId = 0
  820. err = data_manage.AddMultipleGraphConfig(multipleGraphConfig)
  821. if err != nil {
  822. return
  823. }
  824. // 添加图
  825. addChartReq := data_manage.AddChartInfoReq{
  826. ChartClassifyId: classifyId,
  827. ChartName: chartName,
  828. ChartType: utils.CHART_TYPE_CURVE,
  829. Calendar: "公历",
  830. CorrelationChartInfo: correlationChartInfoReq,
  831. }
  832. chartSource := utils.CHART_SOURCE_CORRELATION // 默认是相关性图
  833. chartInfo, err, errMsg, isSendEmail = AddChartInfo(addChartReq, chartSource, sysUser)
  834. if err != nil {
  835. return
  836. }
  837. // 添加关系
  838. multipleGraphConfigChartMapping = &data_manage.MultipleGraphConfigChartMapping{
  839. //Id: 0,
  840. MultipleGraphConfigId: multipleGraphConfig.MultipleGraphConfigId,
  841. ChartInfoId: chartInfo.ChartInfoId,
  842. Source: configSource,
  843. ModifyTime: time.Now(),
  844. CreateTime: time.Now(),
  845. }
  846. err = data_manage.AddMultipleGraphConfigChartMapping(multipleGraphConfigChartMapping)
  847. if err != nil {
  848. return
  849. }
  850. //添加es数据
  851. go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)
  852. return
  853. }