chart_info.go 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574
  1. package range_analysis
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_api/models/data_manage"
  6. "eta/eta_api/models/system"
  7. "eta/eta_api/services/alarm_msg"
  8. "eta/eta_api/services/data"
  9. "eta/eta_api/utils"
  10. "fmt"
  11. "github.com/shopspring/decimal"
  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. // GetChartDataByEdbInfo 相关性图表-根据指标信息获取x轴和y轴
  182. func GetChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req data_manage.ChartRangeAnalysisExtraConf) (xEdbIdValue []int, dataResp data_manage.ChartRangeAnalysisDataResp, err error) {
  183. // 指标的开始日期和结束日期
  184. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  185. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  186. // 根据时间区间类型来获取数据的计算窗口,然后再拼接成整段数据
  187. // 智能划分得到一个开始日期,和结束日期
  188. // 手工划分得到多个开始日期和结束日期(已排序)
  189. // 跨年划分得到多个开始日期和结束日期
  190. //// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
  191. //baseEdbInfo := edbInfoMappingB
  192. //changeEdbInfo := edbInfoMappingA
  193. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  194. baseEdbInfo := edbInfoMapping
  195. changeEdbInfo := edbInfoMappingB
  196. // 获取时间基准指标在时间区间内的值
  197. aDataList := make([]*data_manage.EdbDataList, 0)
  198. switch baseEdbInfo.EdbInfoCategoryType {
  199. case 0:
  200. aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  201. case 1:
  202. _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
  203. default:
  204. err = errors.New("指标base类型异常")
  205. return
  206. }
  207. // 获取变频指标所有日期的值, 插值法完善数据
  208. bDataList := make([]*data_manage.EdbDataList, 0)
  209. switch changeEdbInfo.EdbInfoCategoryType {
  210. case 0:
  211. bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  212. case 1:
  213. _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  214. default:
  215. err = errors.New("指标change类型异常")
  216. return
  217. }
  218. //changeDataMap := make(map[string]float64)
  219. //newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  220. //if e != nil {
  221. // err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  222. // return
  223. //}
  224. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  225. baseDataList := make([]*data_manage.EdbDataList, 0)
  226. baseDataMap := make(map[string]float64)
  227. changeDataList := make([]*data_manage.EdbDataList, 0)
  228. changeDataMap := make(map[string]float64)
  229. // 先把低频指标升频为高频
  230. {
  231. frequencyIntMap := map[string]int{
  232. "日度": 1,
  233. "周度": 2,
  234. "旬度": 3,
  235. "月度": 4,
  236. "季度": 5,
  237. "年度": 6,
  238. }
  239. // 如果A指标是高频,那么就需要对B指标进行升频
  240. if frequencyIntMap[edbInfoMappingA.Frequency] < frequencyIntMap[edbInfoMappingB.Frequency] {
  241. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  242. if e != nil {
  243. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  244. return
  245. }
  246. changeDataList = tmpNewChangeDataList
  247. baseDataList = aDataList
  248. for _, v := range baseDataList {
  249. baseDataMap[v.DataTime] = v.Value
  250. }
  251. } else if frequencyIntMap[edbInfoMappingA.Frequency] > frequencyIntMap[edbInfoMappingB.Frequency] {
  252. // 如果B指标是高频,那么就需要对A指标进行升频
  253. tmpNewChangeDataList, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  254. if e != nil {
  255. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  256. return
  257. }
  258. baseDataList = tmpNewChangeDataList
  259. changeDataList = bDataList
  260. for _, v := range changeDataList {
  261. changeDataMap[v.DataTime] = v.Value
  262. }
  263. } else {
  264. baseDataList = aDataList
  265. for _, v := range baseDataList {
  266. baseDataMap[v.DataTime] = v.Value
  267. }
  268. changeDataList = bDataList
  269. for _, v := range changeDataList {
  270. changeDataMap[v.DataTime] = v.Value
  271. }
  272. }
  273. }
  274. // 计算不领先也不滞后时的相关系数
  275. baseCalculateData := make([]float64, 0)
  276. baseDataTimeArr := make([]string, 0)
  277. for i := range baseDataList {
  278. baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
  279. baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
  280. }
  281. //zeroBaseData := make([]float64, 0)
  282. //zeroCalculateData := make([]float64, 0)
  283. //for i := range baseDataTimeArr {
  284. // tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
  285. // tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
  286. // if ok1 && ok2 {
  287. // zeroBaseData = append(zeroBaseData, tmpBaseVal)
  288. // zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
  289. // }
  290. //}
  291. //if len(zeroBaseData) != len(zeroCalculateData) {
  292. // err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
  293. // return
  294. //}
  295. //zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
  296. //if leadValue == 0 {
  297. // yData = append(yData, zeroRatio)
  298. //}
  299. // 计算领先/滞后N期
  300. if leadValue > 0 {
  301. // 平移变频指标领先/滞后的日期(单位天)
  302. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  303. for i := range xData {
  304. //if xData[i] == 0 {
  305. // yData = append(yData, zeroRatio)
  306. // continue
  307. //}
  308. xCalculateData := make([]float64, 0)
  309. yCalculateData := make([]float64, 0)
  310. // 平移指定天数
  311. mDays := int(moveUnitDays) * xData[i]
  312. _, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
  313. // 取出对应的基准日期的值
  314. for i2 := range baseDataTimeArr {
  315. tmpDate := baseDataTimeArr[i2]
  316. if yVal, ok := dMap[tmpDate]; ok {
  317. xCalculateData = append(xCalculateData, baseCalculateData[i2])
  318. yCalculateData = append(yCalculateData, yVal)
  319. }
  320. }
  321. if len(yCalculateData) <= 0 {
  322. //err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
  323. //return
  324. // 领先滞后后,没有可以计算的数据了
  325. continue
  326. }
  327. // 公式计算出领先/滞后频度对应点的相关性系数
  328. ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
  329. yData = append(yData, ratio)
  330. }
  331. }
  332. // 图例
  333. var extra data_manage.CorrelationChartInfoExtraConfig
  334. legend := new(data_manage.CorrelationChartLegend)
  335. if extraConfig != "" {
  336. if e := json.Unmarshal([]byte(extraConfig), &extra); e != nil {
  337. err = fmt.Errorf("图例解析异常, err: %v", e)
  338. return
  339. }
  340. if len(extra.LegendConfig) > 0 {
  341. legend = extra.LegendConfig[0]
  342. }
  343. }
  344. xEdbIdValue = xData
  345. yDataList = make([]data_manage.YData, 0)
  346. yDate := "0000-00-00"
  347. var y data_manage.YData
  348. y.Date = yDate
  349. y.Value = yData
  350. if legend != nil {
  351. y.Name = legend.LegendName
  352. y.Color = legend.Color
  353. }
  354. yDataList = append(yDataList, y)
  355. return
  356. }
  357. // RollingCorrelationChartDataResp 滚动相关性图表数据
  358. type RollingCorrelationChartDataResp struct {
  359. MaxData float64
  360. MinData float64
  361. LatestDate string `description:"真实数据的最后日期"`
  362. EdbInfoCategoryType int
  363. ChartColor string
  364. ChartStyle string
  365. PredictChartColor string
  366. ChartType int
  367. ChartWidth int
  368. EdbName string
  369. EdbNameEn string
  370. Unit string
  371. UnitEn string
  372. IsAxis int
  373. DataList []data_manage.EdbDataList
  374. }
  375. // GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
  376. func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate, chartName, chartNameEn string) (dataResp RollingCorrelationChartDataResp, err error) {
  377. dataResp = RollingCorrelationChartDataResp{
  378. DataList: make([]data_manage.EdbDataList, 0),
  379. MaxData: 0,
  380. MinData: 0,
  381. ChartColor: "#00f",
  382. ChartStyle: `spline`,
  383. PredictChartColor: `#00f`,
  384. ChartType: 0,
  385. ChartWidth: 3,
  386. EdbName: chartName,
  387. EdbNameEn: chartNameEn,
  388. IsAxis: 1,
  389. }
  390. dataList := make([]data_manage.EdbDataList, 0)
  391. // 计算窗口,不包含第一天
  392. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  393. startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  394. baseEdbInfo := edbInfoMappingA
  395. changeEdbInfo := edbInfoMappingB
  396. // 获取时间基准指标在时间区间内的值
  397. aDataList := make([]*data_manage.EdbDataList, 0)
  398. switch baseEdbInfo.EdbInfoCategoryType {
  399. case 0:
  400. aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  401. case 1:
  402. _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, true)
  403. default:
  404. err = errors.New("指标base类型异常")
  405. return
  406. }
  407. // 获取变频指标所有日期的值, 插值法完善数据
  408. bDataList := make([]*data_manage.EdbDataList, 0)
  409. switch changeEdbInfo.EdbInfoCategoryType {
  410. case 0:
  411. bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  412. case 1:
  413. _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  414. default:
  415. err = errors.New("指标change类型异常")
  416. return
  417. }
  418. // 数据平移变频指标领先/滞后的日期(单位天)
  419. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  420. //baseDataList := make([]*data_manage.EdbDataList, 0)
  421. baseDataMap := make(map[string]float64)
  422. changeDataList := make([]*data_manage.EdbDataList, 0)
  423. changeDataMap := make(map[string]float64)
  424. // A指标不管三七二十一,先变个频再说
  425. {
  426. _, e := HandleDataByLinearRegression(aDataList, baseDataMap)
  427. if e != nil {
  428. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  429. return
  430. }
  431. //baseDataList = tmpNewChangeDataList
  432. }
  433. // B指标不管三七二十一,先变个频再说
  434. {
  435. tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  436. if e != nil {
  437. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  438. return
  439. }
  440. changeDataList = tmpNewChangeDataList
  441. // 平移下日期
  442. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  443. _, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
  444. }
  445. // 计算计算时,需要多少个日期内数据
  446. calculateDay := utils.FrequencyDaysMap[calculateUnit] * calculateValue
  447. // 计算 每个日期的相关性值
  448. {
  449. startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  450. if endDate == `` {
  451. endDate = baseEdbInfo.EndDate
  452. }
  453. endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  454. endDateTime = endDateTime.AddDate(0, 0, -(calculateDay - 1))
  455. // 是否开始第一条数据
  456. var isStart, isNotFirst bool
  457. for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
  458. yCalculateData := make([]float64, 0)
  459. baseCalculateData := make([]float64, 0)
  460. // 取出对应的基准日期的值
  461. for i := 0; i < calculateDay; i++ {
  462. iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
  463. tmpBaseValue, ok1 := baseDataMap[iDay]
  464. tmpChangeValue, ok2 := changeDataMap[iDay]
  465. if ok1 && ok2 {
  466. baseCalculateData = append(baseCalculateData, tmpBaseValue)
  467. yCalculateData = append(yCalculateData, tmpChangeValue)
  468. } else {
  469. continue
  470. }
  471. }
  472. // 公式计算出领先/滞后频度对应点的相关性系数
  473. var ratio float64
  474. if len(baseCalculateData) > 0 {
  475. ratio = utils.CalculateCorrelationByIntArr(baseCalculateData, yCalculateData)
  476. } else {
  477. // 没有数据的话,那就不返回
  478. continue
  479. }
  480. // 过滤前面都是0的数据
  481. {
  482. if ratio != 0 {
  483. isStart = true
  484. }
  485. if !isStart {
  486. continue
  487. }
  488. }
  489. dataTime := currDay.AddDate(0, 0, calculateDay-1)
  490. dataList = append(dataList, data_manage.EdbDataList{
  491. //EdbDataId: 0,
  492. EdbInfoId: 0,
  493. DataTime: dataTime.Format(utils.FormatDate),
  494. DataTimestamp: dataTime.UnixNano() / 1e6,
  495. Value: ratio,
  496. })
  497. if !isNotFirst {
  498. dataResp.MinData = ratio
  499. dataResp.MaxData = ratio
  500. isNotFirst = true
  501. }
  502. if dataResp.MinData > ratio {
  503. dataResp.MinData = ratio
  504. }
  505. if dataResp.MaxData < ratio {
  506. dataResp.MaxData = ratio
  507. }
  508. }
  509. dataResp.DataList = dataList
  510. }
  511. return
  512. }
  513. // ChartInfoRefresh 图表刷新
  514. func ChartInfoRefresh(chartInfoId int, uniqueCode string) (isAsync bool, err error) {
  515. var errMsg string
  516. defer func() {
  517. if err != nil {
  518. tips := fmt.Sprintf("CorrelationChartInfoRefresh: %s", errMsg)
  519. utils.FileLog.Info(tips)
  520. go alarm_msg.SendAlarmMsg(tips, 3)
  521. }
  522. }()
  523. correlationChart := new(data_manage.ChartInfoCorrelation)
  524. if err = correlationChart.GetItemById(chartInfoId); err != nil {
  525. errMsg = "获取相关性图表失败, Err: " + err.Error()
  526. return
  527. }
  528. // 多因子刷新-异步
  529. if correlationChart.AnalysisMode == 1 {
  530. isAsync = true
  531. go func() {
  532. // 1.刷新图表关联的指标
  533. mappings, e := data_manage.GetChartEdbMappingList(chartInfoId)
  534. if e != nil {
  535. utils.FileLog.Info(fmt.Sprintf("获取图表关联指标失败, err: %v", e))
  536. return
  537. }
  538. if len(mappings) == 0 {
  539. utils.FileLog.Info("图表无关联指标")
  540. return
  541. }
  542. var edbIds []int
  543. for _, v := range mappings {
  544. edbIds = append(edbIds, v.EdbInfoId)
  545. }
  546. if e, _ = data.EdbInfoRefreshAllFromBaseV3(edbIds, false, true, false); e != nil {
  547. utils.FileLog.Info(fmt.Sprintf("批量刷新指标失败, err: %v", e))
  548. return
  549. }
  550. // 2.刷新指标系列计算数据
  551. for _, v := range mappings {
  552. _, e = data.PostRefreshFactorEdbRecalculate(v.EdbInfoId, v.EdbCode)
  553. if e != nil {
  554. utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbRecalculate err: %v", e))
  555. continue
  556. }
  557. }
  558. // 3.刷新图表矩阵
  559. _, e = data.PostRefreshFactorEdbChartRecalculate(chartInfoId)
  560. if e != nil {
  561. utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbRecalculate err: %v", e))
  562. return
  563. }
  564. // 4.清除图表缓存
  565. key := utils.HZ_CHART_LIB_DETAIL + uniqueCode
  566. _ = utils.Rc.Delete(key)
  567. }()
  568. return
  569. }
  570. // 批量刷新ETA指标
  571. err, _ = data.EdbInfoRefreshAllFromBaseV3([]int{correlationChart.EdbInfoIdFirst, correlationChart.EdbInfoIdSecond}, false, true, false)
  572. if err != nil {
  573. return
  574. }
  575. // 重新生成数据并更新
  576. edbInfoMappingA, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
  577. if err != nil {
  578. errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + err.Error()
  579. return
  580. }
  581. edbInfoMappingB, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
  582. if err != nil {
  583. errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + err.Error()
  584. return
  585. }
  586. periodData, correlationData, err := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate), "")
  587. if err != nil {
  588. errMsg = "获取相关性图表, 图表计算值失败, Err:" + err.Error()
  589. return
  590. }
  591. periodDataByte, err := json.Marshal(periodData)
  592. if err != nil {
  593. errMsg = "相关性图表, X轴信息有误, Err:" + err.Error()
  594. return
  595. }
  596. correlationDataByte, err := json.Marshal(correlationData[0].Value)
  597. if err != nil {
  598. errMsg = "相关性图表, Y轴信息有误, Err:" + err.Error()
  599. return
  600. }
  601. correlationChart.PeriodData = string(periodDataByte)
  602. correlationChart.CorrelationData = string(correlationDataByte)
  603. correlationChart.ModifyTime = time.Now().Local()
  604. correlationUpdateCols := []string{"PeriodData", "CorrelationData", "ModifyTime"}
  605. if err = correlationChart.Update(correlationUpdateCols); err != nil {
  606. errMsg = "更新相关性图表失败, Err:" + err.Error()
  607. return
  608. }
  609. return
  610. }
  611. // GetChartAndCorrelationInfo 获取图表信息和相关信息信息
  612. func GetChartAndCorrelationInfo(chartInfoId int) (chartInfo *data_manage.ChartInfo, correlationInfo *data_manage.ChartInfoCorrelation, tips string, err error) {
  613. item, e := data_manage.GetChartInfoById(chartInfoId)
  614. if e != nil {
  615. if e.Error() == utils.ErrNoRow() {
  616. tips = "图表已被删除, 请刷新页面"
  617. err = fmt.Errorf("图表已被删除, 请刷新页面")
  618. return
  619. }
  620. err = fmt.Errorf("获取图表信息失败, Err: %s", e.Error())
  621. return
  622. }
  623. if item.Source != utils.CHART_SOURCE_CORRELATION {
  624. tips = "该图不是相关性图表"
  625. err = fmt.Errorf("该图不是相关性图表")
  626. return
  627. }
  628. chartInfo = item
  629. correlationInfo = new(data_manage.ChartInfoCorrelation)
  630. if e = correlationInfo.GetItemById(chartInfo.ChartInfoId); e != nil {
  631. err = fmt.Errorf("获取图表相关性信息失败, Err: %s", e.Error())
  632. return
  633. }
  634. return
  635. }
  636. // AddChartInfo 添加图表
  637. func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.Admin, lang string) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  638. isSendEmail = true
  639. req.ChartName = strings.Trim(req.ChartName, " ")
  640. if req.ChartName == "" {
  641. errMsg = "请填写图表名称!"
  642. err = errors.New(errMsg)
  643. isSendEmail = false
  644. return
  645. }
  646. if req.ChartClassifyId <= 0 {
  647. errMsg = "分类参数错误!"
  648. err = errors.New(errMsg)
  649. isSendEmail = false
  650. return
  651. }
  652. // 相关性图表配置
  653. if req.CorrelationChartInfo.LeadValue == 0 && source == utils.CHART_SOURCE_CORRELATION {
  654. errMsg = "请输入领先期数"
  655. err = errors.New(errMsg)
  656. isSendEmail = false
  657. return
  658. }
  659. if req.CorrelationChartInfo.LeadUnit == "" {
  660. errMsg = "请填写领先单位"
  661. err = errors.New(errMsg)
  662. isSendEmail = false
  663. return
  664. }
  665. //if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
  666. // errMsg = "请填写开始结束日期"
  667. // err = errors.New(errMsg)
  668. // isSendEmail = false
  669. // return
  670. //}
  671. //startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
  672. //if e != nil {
  673. // errMsg = "开始日期格式有误"
  674. // err = errors.New(errMsg)
  675. // isSendEmail = false
  676. // return
  677. //}
  678. //endDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
  679. //if e != nil {
  680. // errMsg = "结束日期格式有误"
  681. // err = errors.New(errMsg)
  682. // isSendEmail = false
  683. // return
  684. //}
  685. if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
  686. errMsg = "请选择AB指标"
  687. err = errors.New(errMsg)
  688. isSendEmail = false
  689. return
  690. }
  691. chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
  692. if err != nil {
  693. if err.Error() == utils.ErrNoRow() {
  694. errMsg = "分类不存在"
  695. err = errors.New(errMsg)
  696. isSendEmail = false
  697. return
  698. }
  699. errMsg = "获取分类信息失败"
  700. err = errors.New("获取分类信息失败,Err:" + err.Error())
  701. return
  702. }
  703. if chartClassify == nil {
  704. errMsg = "分类不存在"
  705. err = errors.New(errMsg)
  706. isSendEmail = false
  707. return
  708. }
  709. var edbInfoIdArr []int
  710. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  711. edbInfoId := v.EdbInfoId
  712. edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
  713. if tmpErr != nil {
  714. if tmpErr.Error() == utils.ErrNoRow() {
  715. errMsg = "指标不存在!"
  716. err = errors.New("指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId))
  717. return
  718. } else {
  719. errMsg = "获取指标信息失败!"
  720. err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
  721. return
  722. }
  723. }
  724. if edbInfo == nil {
  725. errMsg = "指标已被删除,请重新选择!"
  726. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  727. return
  728. } else {
  729. if edbInfo.EdbInfoId <= 0 {
  730. errMsg = "指标已被删除,请重新选择!"
  731. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  732. return
  733. }
  734. }
  735. edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
  736. edbInfo.EdbNameSource = edbInfo.EdbName
  737. }
  738. sort.Ints(edbInfoIdArr)
  739. var edbInfoIdArrStr []string
  740. for _, v := range edbInfoIdArr {
  741. edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
  742. }
  743. edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
  744. var chartInfoId int
  745. // 判断图表是否存在
  746. {
  747. var condition string
  748. var pars []interface{}
  749. switch lang {
  750. case utils.EnLangVersion:
  751. condition += " AND chart_name_en = ? AND source = ? "
  752. default:
  753. condition += " AND chart_name=? AND source = ? "
  754. }
  755. pars = append(pars, req.ChartName, source)
  756. count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
  757. if tmpErr != nil {
  758. errMsg = "判断图表名称是否存在失败"
  759. err = errors.New("判断图表名称是否存在失败,Err:" + tmpErr.Error())
  760. return
  761. }
  762. if count > 0 {
  763. errMsg = "图表已存在,请重新填写"
  764. err = errors.New(errMsg)
  765. isSendEmail = false
  766. return
  767. }
  768. }
  769. disableVal := data.CheckIsDisableChart(edbInfoIdArr)
  770. chartInfo = new(data_manage.ChartInfo)
  771. chartInfo.ChartName = req.ChartName
  772. chartInfo.ChartNameEn = req.ChartName
  773. chartInfo.EdbInfoIds = edbInfoIdStr
  774. chartInfo.ChartClassifyId = req.ChartClassifyId
  775. chartInfo.SysUserId = sysUser.AdminId
  776. chartInfo.SysUserRealName = sysUser.RealName
  777. chartInfo.CreateTime = time.Now()
  778. chartInfo.ModifyTime = time.Now()
  779. chartInfo.IsSetName = 0
  780. timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  781. chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
  782. chartInfo.ChartType = 9 // 相关性图
  783. chartInfo.Calendar = "公历"
  784. chartInfo.DateType = 6
  785. chartInfo.StartDate = req.StartDate
  786. chartInfo.EndDate = req.EndDate
  787. chartInfo.SeasonStartDate = req.StartDate
  788. chartInfo.SeasonEndDate = req.EndDate
  789. chartInfo.LeftMin = req.LeftMin
  790. chartInfo.LeftMax = req.LeftMax
  791. chartInfo.RightMin = req.RightMin
  792. chartInfo.RightMax = req.RightMax
  793. chartInfo.Disabled = disableVal
  794. chartInfo.Source = source
  795. chartInfo.ChartThemeId = req.ChartThemeId
  796. chartInfo.SourcesFrom = req.SourcesFrom
  797. chartInfo.Instructions = req.Instructions
  798. chartInfo.MarkersLines = req.MarkersLines
  799. chartInfo.MarkersAreas = req.MarkersAreas
  800. if req.ExtraConfig != "" {
  801. chartInfo.ExtraConfig = req.ExtraConfig
  802. }
  803. // 指标信息
  804. mapList := make([]*data_manage.ChartEdbMapping, 0)
  805. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  806. mapItem := new(data_manage.ChartEdbMapping)
  807. mapItem.EdbInfoId = v.EdbInfoId
  808. mapItem.CreateTime = time.Now()
  809. mapItem.ModifyTime = time.Now()
  810. edbTimestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  811. mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + edbTimestamp + "_" + strconv.Itoa(v.EdbInfoId))
  812. mapItem.IsOrder = true
  813. mapItem.IsAxis = 1
  814. mapItem.EdbInfoType = 1
  815. mapItem.Source = utils.CHART_SOURCE_CORRELATION
  816. mapList = append(mapList, mapItem)
  817. }
  818. // 相关性图表扩展信息
  819. correlationChart := new(data_manage.ChartInfoCorrelation)
  820. correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
  821. correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
  822. correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
  823. correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
  824. correlationChart.BaseCalculateValue = req.CorrelationChartInfo.BaseCalculateValue
  825. correlationChart.BaseCalculateUnit = req.CorrelationChartInfo.BaseCalculateUnit
  826. // 滚动相关性会有日期等信息
  827. if source == utils.CHART_SOURCE_ROLLING_CORRELATION {
  828. correlationChart.DateType = req.CorrelationChartInfo.DateType
  829. if req.CorrelationChartInfo.StartDate != `` {
  830. startDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, req.CorrelationChartInfo.StartDate, time.Local)
  831. if tmpErr != nil {
  832. err = tmpErr
  833. return
  834. }
  835. correlationChart.StartDate = startDateTime
  836. }
  837. if req.CorrelationChartInfo.EndDate != `` {
  838. endDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, req.CorrelationChartInfo.EndDate, time.Local)
  839. if tmpErr != nil {
  840. err = tmpErr
  841. return
  842. }
  843. correlationChart.EndDate = endDateTime
  844. }
  845. }
  846. correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
  847. correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
  848. correlationChart.CreateTime = time.Now().Local()
  849. correlationChart.ModifyTime = time.Now().Local()
  850. //// 生成图表x轴y轴数据
  851. //edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
  852. //if e != nil {
  853. // errMsg = "获取失败"
  854. // err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
  855. // return
  856. //}
  857. //edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
  858. //if e != nil {
  859. // errMsg = "获取失败"
  860. // err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
  861. // return
  862. //}
  863. //periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
  864. //if e != nil {
  865. // errMsg = "获取失败"
  866. // err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
  867. // return
  868. //}
  869. //periodDataByte, e := json.Marshal(periodData)
  870. //if e != nil {
  871. // errMsg = "获取失败"
  872. // err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
  873. // return
  874. //}
  875. //correlationDataByte, e := json.Marshal(correlationData[0].Value)
  876. //if e != nil {
  877. // errMsg = "获取失败"
  878. // err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
  879. // return
  880. //}
  881. //correlationChart.PeriodData = string(periodDataByte)
  882. //correlationChart.CorrelationData = string(correlationDataByte)
  883. // 新增图表和指标mapping
  884. chartInfoId, e := data_manage.CreateCorrelationChartAndEdb(chartInfo, mapList, correlationChart)
  885. if e != nil {
  886. errMsg = "操作失败"
  887. err = errors.New("新增相关性图表失败, Err: " + e.Error())
  888. return
  889. }
  890. // 添加指标引用记录
  891. _ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartInfo)
  892. //添加es数据
  893. go data.EsAddOrEditChartInfo(chartInfoId)
  894. return
  895. }
  896. // EditChartInfo 编辑图表
  897. func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang string) (chartItem *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  898. isSendEmail = true
  899. chartItem, err = data_manage.GetChartInfoById(req.ChartInfoId)
  900. if err != nil {
  901. if err.Error() == utils.ErrNoRow() {
  902. errMsg = "图表已被删除,请刷新页面"
  903. err = errors.New(errMsg)
  904. isSendEmail = false
  905. return
  906. }
  907. errMsg = "获取图表信息失败"
  908. err = errors.New("获取图表信息失败,Err:" + err.Error())
  909. return
  910. }
  911. if chartItem.Source != utils.CHART_SOURCE_CORRELATION && chartItem.Source != utils.CHART_SOURCE_ROLLING_CORRELATION {
  912. errMsg = "该图不是相关性图表!"
  913. err = errors.New(errMsg)
  914. isSendEmail = false
  915. return
  916. }
  917. req.ChartName = strings.Trim(req.ChartName, " ")
  918. if req.ChartClassifyId <= 0 {
  919. errMsg = "分类参数错误!"
  920. err = errors.New(errMsg)
  921. isSendEmail = false
  922. return
  923. }
  924. // 相关性图表配置
  925. if req.CorrelationChartInfo.LeadValue == 0 && chartItem.Source == utils.CHART_SOURCE_CORRELATION {
  926. errMsg = "请输入领先期数"
  927. err = errors.New(errMsg)
  928. isSendEmail = false
  929. return
  930. }
  931. if req.CorrelationChartInfo.LeadUnit == "" {
  932. errMsg = "请填写领先单位"
  933. err = errors.New(errMsg)
  934. isSendEmail = false
  935. return
  936. }
  937. //if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
  938. // errMsg = "请填写开始结束日期"
  939. // err = errors.New(errMsg)
  940. // isSendEmail = false
  941. // return
  942. //}
  943. startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
  944. if e != nil {
  945. errMsg = "开始日期格式有误"
  946. err = errors.New(errMsg)
  947. isSendEmail = false
  948. return
  949. }
  950. var endDate time.Time
  951. if req.CorrelationChartInfo.EndDate != `` {
  952. endDate, e = time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
  953. if e != nil {
  954. errMsg = "结束日期格式有误"
  955. err = errors.New(errMsg)
  956. isSendEmail = false
  957. return
  958. }
  959. }
  960. if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
  961. errMsg = "请选择AB指标"
  962. err = errors.New(errMsg)
  963. isSendEmail = false
  964. return
  965. }
  966. chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
  967. if err != nil {
  968. if err.Error() == utils.ErrNoRow() {
  969. errMsg = "分类不存在"
  970. err = errors.New(errMsg)
  971. isSendEmail = false
  972. return
  973. }
  974. errMsg = "获取分类信息失败"
  975. err = errors.New("获取分类信息失败,Err:" + err.Error())
  976. return
  977. }
  978. if chartClassify == nil {
  979. errMsg = "分类不存在"
  980. err = errors.New(errMsg)
  981. isSendEmail = false
  982. return
  983. }
  984. // 图表操作权限
  985. ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId, true)
  986. if !ok {
  987. errMsg = "没有该图表的操作权限"
  988. err = errors.New(errMsg)
  989. isSendEmail = false
  990. return
  991. }
  992. var edbInfoIdArr []int
  993. for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
  994. edbInfoId := v.EdbInfoId
  995. edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
  996. if tmpErr != nil {
  997. if tmpErr.Error() == utils.ErrNoRow() {
  998. errMsg = "图表不存在!"
  999. err = errors.New("图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  1000. return
  1001. } else {
  1002. errMsg = "获取图表信息失败!"
  1003. err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
  1004. return
  1005. }
  1006. }
  1007. if edbInfo == nil {
  1008. errMsg = "指标不存在!"
  1009. err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
  1010. return
  1011. }
  1012. edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
  1013. }
  1014. sort.Ints(edbInfoIdArr)
  1015. var edbInfoIdArrStr []string
  1016. for _, v := range edbInfoIdArr {
  1017. edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
  1018. }
  1019. edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
  1020. //判断图表是否存在
  1021. {
  1022. var condition string
  1023. var pars []interface{}
  1024. condition += " AND chart_info_id <> ? "
  1025. pars = append(pars, req.ChartInfoId)
  1026. switch lang {
  1027. case utils.EnLangVersion:
  1028. condition += " AND chart_name_en = ? AND source = ? "
  1029. default:
  1030. condition += " AND chart_name=? AND source = ? "
  1031. }
  1032. pars = append(pars, req.ChartName, chartItem.Source)
  1033. count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
  1034. if tmpErr != nil {
  1035. errMsg = "判断图表名称是否存在失败"
  1036. err = errors.New("判断图表名称是否存在失败,Err:" + tmpErr.Error())
  1037. return
  1038. }
  1039. if count > 0 {
  1040. errMsg = "图表已存在,请重新填写"
  1041. err = errors.New(errMsg)
  1042. isSendEmail = false
  1043. return
  1044. }
  1045. }
  1046. correlationChart := new(data_manage.ChartInfoCorrelation)
  1047. if e := correlationChart.GetItemById(chartItem.ChartInfoId); e != nil {
  1048. errMsg = "操作失败"
  1049. err = errors.New("图表相关性信息不存在, Err: " + e.Error())
  1050. return
  1051. }
  1052. // 图表启用与否
  1053. disableVal := data.CheckIsDisableChart(edbInfoIdArr)
  1054. // 重新生成图表值, 并修改相关性图表扩展信息
  1055. //edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
  1056. //if e != nil {
  1057. // errMsg = "获取失败"
  1058. // err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
  1059. // return
  1060. //}
  1061. //edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
  1062. //if e != nil {
  1063. // errMsg = "获取失败"
  1064. // err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
  1065. // return
  1066. //}
  1067. //periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
  1068. //if e != nil {
  1069. // errMsg = "获取失败"
  1070. // err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
  1071. // return
  1072. //}
  1073. //periodDataByte, e := json.Marshal(periodData)
  1074. //if e != nil {
  1075. // errMsg = "获取失败"
  1076. // err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
  1077. // return
  1078. //}
  1079. //correlationDataByte, e := json.Marshal(correlationData[0].Value)
  1080. //if e != nil {
  1081. // errMsg = "获取失败"
  1082. // err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
  1083. // return
  1084. //}
  1085. correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
  1086. correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
  1087. correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
  1088. correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
  1089. correlationChart.StartDate = startDate
  1090. correlationChart.EndDate = endDate
  1091. correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
  1092. correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
  1093. // 滚动相关性会有日期等信息
  1094. if chartItem.Source == utils.CHART_SOURCE_ROLLING_CORRELATION {
  1095. correlationChart.DateType = req.CorrelationChartInfo.DateType
  1096. }
  1097. //correlationChart.PeriodData = string(periodDataByte)
  1098. //correlationChart.CorrelationData = string(correlationDataByte)
  1099. correlationChart.ModifyTime = time.Now().Local()
  1100. //correlationUpdateCols := []string{"LeadValue", "LeadUnit", "StartDate", "EndDate", "EdbInfoIdFirst", "EdbInfoIdSecond", "PeriodData","CorrelationData", "ModifyTime"}
  1101. correlationUpdateCols := []string{"LeadValue", "LeadUnit", "CalculateValue", "CalculateUnit", "DateType", "StartDate", "EndDate", "EdbInfoIdFirst", "EdbInfoIdSecond", "ModifyTime"}
  1102. // 修改图表与指标mapping
  1103. req.ChartType = 9
  1104. err = data_manage.EditCorrelationChartInfoAndMapping(&req, edbInfoIdStr, "公历", 6, disableVal, ``,
  1105. correlationChart, correlationUpdateCols)
  1106. if err != nil {
  1107. errMsg = "保存失败"
  1108. err = errors.New("保存失败,Err:" + err.Error())
  1109. return
  1110. }
  1111. resp := new(data_manage.AddChartInfoResp)
  1112. resp.ChartInfoId = chartItem.ChartInfoId
  1113. resp.UniqueCode = chartItem.UniqueCode
  1114. resp.ChartType = req.ChartType
  1115. // 添加指标引用记录
  1116. _ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartItem)
  1117. //添加es数据
  1118. go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
  1119. //修改my eta es数据
  1120. go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
  1121. return
  1122. }
  1123. // CopyChartInfo 复制图表
  1124. func CopyChartInfo(configId, classifyId int, chartName string, correlationChartInfoReq data_manage.CorrelationChartInfoReq, oldChartInfo *data_manage.ChartInfo, sysUser *system.Admin, lang string) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  1125. configSource := 2
  1126. isSendEmail = true
  1127. // 获取相关性图的配置
  1128. multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(configId, configSource)
  1129. if err != nil {
  1130. return
  1131. }
  1132. multipleGraphConfig, err := data_manage.GetMultipleGraphConfigById(configId)
  1133. if err != nil {
  1134. return
  1135. }
  1136. multipleGraphConfig.MultipleGraphConfigId = 0
  1137. err = data_manage.AddMultipleGraphConfig(multipleGraphConfig)
  1138. if err != nil {
  1139. return
  1140. }
  1141. // 添加图
  1142. addChartReq := data_manage.AddChartInfoReq{
  1143. ChartClassifyId: classifyId,
  1144. ChartName: chartName,
  1145. ChartType: utils.CHART_TYPE_CURVE,
  1146. Calendar: "公历",
  1147. CorrelationChartInfo: correlationChartInfoReq,
  1148. ChartThemeId: oldChartInfo.ChartThemeId,
  1149. SourcesFrom: oldChartInfo.SourcesFrom,
  1150. Instructions: oldChartInfo.Instructions,
  1151. MarkersLines: oldChartInfo.MarkersLines,
  1152. MarkersAreas: oldChartInfo.MarkersAreas,
  1153. }
  1154. chartSource := utils.CHART_SOURCE_CORRELATION // 默认是相关性图
  1155. chartInfo, err, errMsg, isSendEmail = AddChartInfo(addChartReq, chartSource, sysUser, lang)
  1156. if err != nil {
  1157. return
  1158. }
  1159. // 添加关系
  1160. multipleGraphConfigChartMapping = &data_manage.MultipleGraphConfigChartMapping{
  1161. //Id: 0,
  1162. MultipleGraphConfigId: multipleGraphConfig.MultipleGraphConfigId,
  1163. ChartInfoId: chartInfo.ChartInfoId,
  1164. Source: configSource,
  1165. ModifyTime: time.Now(),
  1166. CreateTime: time.Now(),
  1167. }
  1168. err = data_manage.AddMultipleGraphConfigChartMapping(multipleGraphConfigChartMapping)
  1169. if err != nil {
  1170. return
  1171. }
  1172. //添加es数据
  1173. go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)
  1174. return
  1175. }
  1176. // CalculateCorrelation 计算相关性-获取x轴和y轴
  1177. func CalculateCorrelation(leadValue int, leadUnit, frequencyA, frequencyB string, dataListA, dataListB []*data_manage.EdbDataList) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
  1178. xData := make([]int, 0)
  1179. yData := make([]float64, 0)
  1180. if leadValue == 0 {
  1181. xData = append(xData, 0)
  1182. }
  1183. if leadValue > 0 {
  1184. leadMin := 0 - leadValue
  1185. xLen := 2*leadValue + 1
  1186. for i := 0; i < xLen; i++ {
  1187. n := leadMin + i
  1188. xData = append(xData, n)
  1189. }
  1190. }
  1191. // 计算窗口,不包含第一天
  1192. //startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  1193. //startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  1194. //// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
  1195. //baseEdbInfo := edbInfoMappingB
  1196. //changeEdbInfo := edbInfoMappingA
  1197. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  1198. //baseEdbInfo := edbInfoMappingA
  1199. //changeEdbInfo := edbInfoMappingB
  1200. // 获取时间基准指标在时间区间内的值
  1201. //aDataList := make([]*data_manage.EdbDataList, 0)
  1202. //switch baseEdbInfo.EdbInfoCategoryType {
  1203. //case 0:
  1204. // aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
  1205. //case 1:
  1206. // _, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
  1207. //default:
  1208. // err = errors.New("指标base类型异常")
  1209. // return
  1210. //}
  1211. //
  1212. //// 获取变频指标所有日期的值, 插值法完善数据
  1213. //bDataList := make([]*data_manage.EdbDataList, 0)
  1214. //switch changeEdbInfo.EdbInfoCategoryType {
  1215. //case 0:
  1216. // bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
  1217. //case 1:
  1218. // _, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
  1219. //default:
  1220. // err = errors.New("指标change类型异常")
  1221. // return
  1222. //}
  1223. //changeDataMap := make(map[string]float64)
  1224. //newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
  1225. //if e != nil {
  1226. // err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  1227. // return
  1228. //}
  1229. // 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
  1230. baseDataList := make([]*data_manage.EdbDataList, 0)
  1231. baseDataMap := make(map[string]float64)
  1232. changeDataList := make([]*data_manage.EdbDataList, 0)
  1233. changeDataMap := make(map[string]float64)
  1234. // 先把低频指标升频为高频
  1235. {
  1236. frequencyIntMap := map[string]int{
  1237. "日度": 1,
  1238. "周度": 2,
  1239. "旬度": 3,
  1240. "月度": 4,
  1241. "季度": 5,
  1242. "年度": 6,
  1243. }
  1244. // 如果A指标是高频,那么就需要对B指标进行升频
  1245. if frequencyIntMap[frequencyA] < frequencyIntMap[frequencyB] {
  1246. tmpNewChangeDataList, e := HandleDataByLinearRegression(dataListB, changeDataMap)
  1247. if e != nil {
  1248. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  1249. return
  1250. }
  1251. changeDataList = tmpNewChangeDataList
  1252. baseDataList = dataListA
  1253. for _, v := range baseDataList {
  1254. baseDataMap[v.DataTime] = v.Value
  1255. }
  1256. } else if frequencyIntMap[frequencyA] > frequencyIntMap[frequencyB] {
  1257. // 如果B指标是高频,那么就需要对A指标进行升频
  1258. tmpNewChangeDataList, e := HandleDataByLinearRegression(dataListA, baseDataMap)
  1259. if e != nil {
  1260. err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
  1261. return
  1262. }
  1263. baseDataList = tmpNewChangeDataList
  1264. changeDataList = dataListB
  1265. for _, v := range changeDataList {
  1266. changeDataMap[v.DataTime] = v.Value
  1267. }
  1268. } else {
  1269. baseDataList = dataListA
  1270. for _, v := range baseDataList {
  1271. baseDataMap[v.DataTime] = v.Value
  1272. }
  1273. changeDataList = dataListB
  1274. for _, v := range changeDataList {
  1275. changeDataMap[v.DataTime] = v.Value
  1276. }
  1277. }
  1278. }
  1279. // 计算不领先也不滞后时的相关系数
  1280. baseCalculateData := make([]float64, 0)
  1281. baseDataTimeArr := make([]string, 0)
  1282. for i := range baseDataList {
  1283. baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
  1284. baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
  1285. }
  1286. //zeroBaseData := make([]float64, 0)
  1287. //zeroCalculateData := make([]float64, 0)
  1288. //for i := range baseDataTimeArr {
  1289. // tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
  1290. // tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
  1291. // if ok1 && ok2 {
  1292. // zeroBaseData = append(zeroBaseData, tmpBaseVal)
  1293. // zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
  1294. // }
  1295. //}
  1296. //if len(zeroBaseData) != len(zeroCalculateData) {
  1297. // err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
  1298. // return
  1299. //}
  1300. //zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
  1301. //if leadValue == 0 {
  1302. // yData = append(yData, zeroRatio)
  1303. //}
  1304. // 计算领先/滞后N期
  1305. if leadValue > 0 {
  1306. // 平移变频指标领先/滞后的日期(单位天)
  1307. moveUnitDays := utils.FrequencyDaysMap[leadUnit]
  1308. for i := range xData {
  1309. //if xData[i] == 0 {
  1310. // yData = append(yData, zeroRatio)
  1311. // continue
  1312. //}
  1313. xCalculateData := make([]float64, 0)
  1314. yCalculateData := make([]float64, 0)
  1315. // 平移指定天数
  1316. mDays := int(moveUnitDays) * xData[i]
  1317. _, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
  1318. // 取出对应的基准日期的值
  1319. for i2 := range baseDataTimeArr {
  1320. tmpDate := baseDataTimeArr[i2]
  1321. if yVal, ok := dMap[tmpDate]; ok {
  1322. xCalculateData = append(xCalculateData, baseCalculateData[i2])
  1323. yCalculateData = append(yCalculateData, yVal)
  1324. }
  1325. }
  1326. if len(yCalculateData) <= 0 {
  1327. //err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
  1328. //return
  1329. // 领先滞后后,没有可以计算的数据了
  1330. continue
  1331. }
  1332. // 公式计算出领先/滞后频度对应点的相关性系数
  1333. ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
  1334. yData = append(yData, ratio)
  1335. }
  1336. }
  1337. xEdbIdValue = xData
  1338. yDataList = make([]data_manage.YData, 0)
  1339. yDate := "0000-00-00"
  1340. yDataList = append(yDataList, data_manage.YData{
  1341. Date: yDate,
  1342. Value: yData,
  1343. })
  1344. return
  1345. }
  1346. // GetFactorChartDataByChartId 获取多因子相关性图表数据
  1347. func GetFactorChartDataByChartId(chartInfoId int, extraConfig string) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
  1348. if chartInfoId <= 0 {
  1349. return
  1350. }
  1351. // 指标对应的图例
  1352. extra := new(data_manage.CorrelationChartInfoExtraConfig)
  1353. if extraConfig != "" {
  1354. if e := json.Unmarshal([]byte(extraConfig), extra); e != nil {
  1355. err = fmt.Errorf("解析图表额外配置失败, err: %v", e)
  1356. return
  1357. }
  1358. }
  1359. legends := make(map[string]*data_manage.CorrelationChartLegend)
  1360. if extra != nil {
  1361. for _, v := range extra.LegendConfig {
  1362. s := fmt.Sprintf("%d-%d", v.SeriesId, v.EdbInfoId)
  1363. legends[s] = v
  1364. }
  1365. }
  1366. // 获取图表引用到的系列指标
  1367. chartMappingOb := new(data_manage.FactorEdbSeriesChartMapping)
  1368. cond := fmt.Sprintf(" AND %s = ? AND %s = 1", chartMappingOb.Cols().ChartInfoId, chartMappingOb.Cols().EdbUsed)
  1369. pars := make([]interface{}, 0)
  1370. pars = append(pars, chartInfoId)
  1371. chartMappings, e := chartMappingOb.GetItemsByCondition(cond, pars, []string{}, "")
  1372. if e != nil {
  1373. err = fmt.Errorf("获取图表引用系列指标失败")
  1374. return
  1375. }
  1376. // 取出计算结果
  1377. yDataList = make([]data_manage.YData, 0)
  1378. yDate := "0000-00-00"
  1379. for k, m := range chartMappings {
  1380. var values []data_manage.FactorEdbSeriesCorrelationMatrixValues
  1381. if m.CalculateData != "" {
  1382. e = json.Unmarshal([]byte(m.CalculateData), &values)
  1383. if e != nil {
  1384. err = fmt.Errorf("系列指标计算数据有误, err: %v", e)
  1385. return
  1386. }
  1387. }
  1388. var y []float64
  1389. for _, v := range values {
  1390. if k == 0 {
  1391. xEdbIdValue = append(xEdbIdValue, v.XData)
  1392. }
  1393. y = append(y, v.YData)
  1394. }
  1395. var yData data_manage.YData
  1396. yData.Date = yDate
  1397. yData.Value = y
  1398. yData.SeriesEdb.SeriesId = m.FactorEdbSeriesId
  1399. yData.SeriesEdb.EdbInfoId = m.EdbInfoId
  1400. // 图例
  1401. s := fmt.Sprintf("%d-%d", m.FactorEdbSeriesId, m.EdbInfoId)
  1402. legend := legends[s]
  1403. if legend != nil {
  1404. yData.Name = legend.LegendName
  1405. yData.Color = legend.Color
  1406. }
  1407. yDataList = append(yDataList, yData)
  1408. }
  1409. return
  1410. }
  1411. // FormatChartEdbInfoMappings 补充指标信息
  1412. func FormatChartEdbInfoMappings(chartInfoId int, mappings []*data_manage.ChartEdbInfoMapping) (edbList []*data_manage.ChartEdbInfoMapping, err error) {
  1413. edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
  1414. if len(mappings) == 0 {
  1415. return
  1416. }
  1417. for _, v := range mappings {
  1418. if chartInfoId <= 0 {
  1419. v.IsAxis = 1
  1420. v.LeadValue = 0
  1421. v.LeadUnit = ""
  1422. v.ChartEdbMappingId = 0
  1423. v.ChartInfoId = 0
  1424. v.IsOrder = false
  1425. v.EdbInfoType = 1
  1426. v.ChartStyle = ""
  1427. v.ChartColor = ""
  1428. v.ChartWidth = 0
  1429. } else {
  1430. v.LeadUnitEn = data.GetLeadUnitEn(v.LeadUnit)
  1431. v.LeadUnitEn = data.GetLeadUnitEn(v.LeadUnit)
  1432. }
  1433. v.FrequencyEn = data.GetFrequencyEn(v.Frequency)
  1434. if v.Unit == `无` {
  1435. v.Unit = ``
  1436. }
  1437. edbList = append(edbList, v)
  1438. }
  1439. return
  1440. }