chart_info.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. package line_equation
  2. import (
  3. "errors"
  4. "hongze/hongze_chart_lib/models"
  5. "hongze/hongze_chart_lib/models/data_manage/line_equation/request"
  6. "hongze/hongze_chart_lib/services/data"
  7. "hongze/hongze_chart_lib/utils"
  8. "math"
  9. "time"
  10. )
  11. type LineEquationResp struct {
  12. AData LineEquationDataResp
  13. BData LineEquationDataResp
  14. R2Data LineEquationDataResp
  15. }
  16. type LineEquationDataResp struct {
  17. MaxData float64
  18. MinData float64
  19. LatestDate string `description:"真实数据的最后日期"`
  20. EdbInfoCategoryType int
  21. ChartColor string
  22. ChartStyle string
  23. PredictChartColor string
  24. ChartType int
  25. ChartWidth int
  26. EdbName string
  27. EdbNameEn string
  28. IsAxis int
  29. DataList []models.EdbDataList
  30. }
  31. // GetChartEdbData 获取图表数据
  32. func GetChartEdbData(chartInfoId int, lineChartInfoConfig request.LineChartInfoReq, getAData, getBData, getR2Data bool) (edbList []*models.ChartEdbInfoMapping, dataResp LineEquationResp, err error, errMsg string) {
  33. // 获取基本信息
  34. mappingList, startDate, endDate, err, errMsg := getConfigData(lineChartInfoConfig)
  35. if err != nil {
  36. return
  37. }
  38. xEdbInfoIdList := lineChartInfoConfig.XEdbInfoIdList
  39. yEdbInfoIdList := lineChartInfoConfig.YEdbInfoIdList
  40. aLineEquationDataResp := LineEquationDataResp{
  41. DataList: make([]models.EdbDataList, 0),
  42. MaxData: 0,
  43. MinData: 0,
  44. ChartColor: "#00f",
  45. ChartStyle: `spline`,
  46. PredictChartColor: `#00f`,
  47. ChartType: 0,
  48. ChartWidth: 3,
  49. EdbName: `弹性系数`,
  50. EdbNameEn: `elastic coefficient`,
  51. IsAxis: 1,
  52. }
  53. bLineEquationDataResp := LineEquationDataResp{
  54. DataList: make([]models.EdbDataList, 0),
  55. MaxData: 0,
  56. MinData: 0,
  57. ChartColor: "#00f",
  58. ChartStyle: `spline`,
  59. PredictChartColor: `#00f`,
  60. ChartType: 0,
  61. ChartWidth: 3,
  62. EdbName: `截距`,
  63. EdbNameEn: `intercept`,
  64. IsAxis: 1,
  65. }
  66. r2LineEquationDataResp := LineEquationDataResp{
  67. DataList: make([]models.EdbDataList, 0),
  68. MaxData: 0,
  69. MinData: 0,
  70. ChartColor: "#00f",
  71. ChartStyle: `spline`,
  72. PredictChartColor: `#00f`,
  73. ChartType: 0,
  74. ChartWidth: 3,
  75. EdbName: `相关系数`,
  76. EdbNameEn: `coefficient of association`,
  77. IsAxis: 1,
  78. }
  79. edbList = make([]*models.ChartEdbInfoMapping, 0)
  80. dataResp = LineEquationResp{
  81. AData: aLineEquationDataResp,
  82. BData: bLineEquationDataResp,
  83. R2Data: r2LineEquationDataResp,
  84. }
  85. var baseEdbInfo *models.ChartEdbInfoMapping
  86. // 获取确定以哪个指标的日期作为基准日期
  87. {
  88. var xEdbInfo, yEdbInfo *models.ChartEdbInfoMapping
  89. for _, v := range mappingList {
  90. if v.EdbInfoId == xEdbInfoIdList[0] {
  91. xEdbInfo = v
  92. } else if v.EdbInfoId == yEdbInfoIdList[0] {
  93. yEdbInfo = v
  94. }
  95. }
  96. if xEdbInfo == nil {
  97. errMsg = `X轴第一个指标异常`
  98. err = errors.New(errMsg)
  99. return
  100. }
  101. if yEdbInfo == nil {
  102. errMsg = `Y轴第一个指标异常`
  103. err = errors.New(errMsg)
  104. return
  105. }
  106. // 时间截面规则:按照什么频率来取不同的截面的问题。原则是:按照X轴和Y轴所选择的第一个指标(X和Y分别有一个第一个指标),两个指标中,以低频的那个作为基准。如果X轴和Y轴是同频的,那以Y轴第一个指标的为准。
  107. frequencyIntMap := map[string]int{
  108. "日度": 1,
  109. "周度": 2,
  110. "旬度": 3,
  111. "月度": 4,
  112. "季度": 5,
  113. "年度": 6,
  114. }
  115. // 如果x是高频 或者 x与y是同频的,那么就是Y轴的第一个指标为主
  116. if frequencyIntMap[xEdbInfo.Frequency] <= frequencyIntMap[yEdbInfo.Frequency] {
  117. baseEdbInfo = yEdbInfo
  118. } else {
  119. // 否则是X轴的第一个指标是低频
  120. baseEdbInfo = xEdbInfo
  121. }
  122. }
  123. // 指标对应的所有数据
  124. chartType := 1 //1:普通图,2:季节性图
  125. calendar := "农历"
  126. edbDataListMap, edbList, err := data.GetEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList)
  127. if err != nil {
  128. return
  129. }
  130. // 获取所有的日期
  131. dateList := make([]string, 0)
  132. for _, v := range edbDataListMap[baseEdbInfo.EdbInfoId] {
  133. dateList = append(dateList, v.DataTime)
  134. }
  135. // 数据整理
  136. // [日期][A指标id:值,B指标id:值]
  137. dateEdbMap, err := handleData(baseEdbInfo.EdbInfoId, edbDataListMap)
  138. if err != nil {
  139. return
  140. }
  141. lenX := len(xEdbInfoIdList)
  142. for i, date := range dateList {
  143. coordinateData := make([]utils.Coordinate, 0)
  144. for k := 0; k < lenX; k++ {
  145. xVal, ok1 := dateEdbMap[date][xEdbInfoIdList[k]]
  146. yVal, ok2 := dateEdbMap[date][yEdbInfoIdList[k]]
  147. if !ok1 || !ok2 {
  148. continue
  149. }
  150. tmpCoordinate1 := utils.Coordinate{
  151. X: xVal,
  152. Y: yVal,
  153. }
  154. coordinateData = append(coordinateData, tmpCoordinate1)
  155. }
  156. dataTime, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
  157. timestamp := dataTime.UnixNano() / 1e6
  158. // 只有存在两个坐标点的时候,才能去计算线性方程和R平方
  159. if len(coordinateData) >= 2 {
  160. a, b := utils.GetLinearResult(coordinateData)
  161. if !math.IsNaN(a) && !math.IsNaN(b) && !math.IsInf(a, 0) && !math.IsInf(b, 0) {
  162. if getAData {
  163. dataResp.AData.DataList = append(dataResp.AData.DataList, models.EdbDataList{
  164. EdbDataId: i,
  165. EdbInfoId: 0,
  166. DataTime: date,
  167. DataTimestamp: timestamp,
  168. Value: a,
  169. })
  170. if dataResp.AData.MinData > a {
  171. dataResp.AData.MinData = a
  172. }
  173. if dataResp.AData.MaxData < a {
  174. dataResp.AData.MaxData = a
  175. }
  176. }
  177. if getBData {
  178. dataResp.BData.DataList = append(dataResp.BData.DataList, models.EdbDataList{
  179. EdbDataId: i,
  180. EdbInfoId: 0,
  181. DataTime: date,
  182. DataTimestamp: timestamp,
  183. Value: b,
  184. })
  185. if dataResp.BData.MinData > a {
  186. dataResp.BData.MinData = a
  187. }
  188. if dataResp.BData.MaxData < a {
  189. dataResp.BData.MaxData = a
  190. }
  191. }
  192. }
  193. // 计算R平方
  194. if getR2Data {
  195. tmpVal := utils.CalculationDecisive(coordinateData)
  196. if math.IsNaN(tmpVal) || math.IsInf(tmpVal, 0) {
  197. continue
  198. }
  199. dataResp.R2Data.DataList = append(dataResp.R2Data.DataList, models.EdbDataList{
  200. EdbDataId: i,
  201. EdbInfoId: 0,
  202. DataTime: date,
  203. DataTimestamp: timestamp,
  204. Value: tmpVal,
  205. })
  206. if dataResp.R2Data.MinData > tmpVal {
  207. dataResp.R2Data.MinData = tmpVal
  208. }
  209. if dataResp.R2Data.MaxData < tmpVal {
  210. dataResp.R2Data.MaxData = tmpVal
  211. }
  212. }
  213. }
  214. }
  215. dataResp.AData.LatestDate = baseEdbInfo.LatestDate
  216. dataResp.AData.EdbInfoCategoryType = baseEdbInfo.EdbInfoCategoryType
  217. dataResp.BData.LatestDate = baseEdbInfo.LatestDate
  218. dataResp.BData.EdbInfoCategoryType = baseEdbInfo.EdbInfoCategoryType
  219. dataResp.R2Data.LatestDate = baseEdbInfo.LatestDate
  220. dataResp.R2Data.EdbInfoCategoryType = baseEdbInfo.EdbInfoCategoryType
  221. return
  222. }
  223. // getConfigData 获取配置数据
  224. func getConfigData(lineChartInfoConfig request.LineChartInfoReq) (mappingList []*models.ChartEdbInfoMapping, startDate, endDate string, err error, errMsg string) {
  225. dateType := lineChartInfoConfig.DateType
  226. switch dateType {
  227. case 1:
  228. startDate = "2000-01-01"
  229. case 2:
  230. startDate = "2010-01-01"
  231. case 3:
  232. startDate = "2015-01-01"
  233. case 4:
  234. //startDate = strconv.Itoa(time.Now().Year()) + "-01-01"
  235. startDate = "2021-01-01"
  236. case 5:
  237. startDate = lineChartInfoConfig.StartDate + "-01"
  238. endDate = lineChartInfoConfig.EndDate + "-01"
  239. case 6:
  240. startDate = lineChartInfoConfig.StartDate + "-01"
  241. case 7:
  242. startDate = "2018-01-01"
  243. case 8:
  244. startDate = "2019-01-01"
  245. case 9:
  246. startDate = "2020-01-01"
  247. case 11:
  248. startDate = "2022-01-01"
  249. }
  250. //指标数据
  251. edbInfoIdList := make([]int, 0)
  252. {
  253. edbInfoIdMap := make(map[int]int, 0)
  254. for _, edbInfoId := range lineChartInfoConfig.XEdbInfoIdList {
  255. edbInfoIdMap[edbInfoId] = edbInfoId
  256. }
  257. for _, edbInfoId := range lineChartInfoConfig.YEdbInfoIdList {
  258. edbInfoIdMap[edbInfoId] = edbInfoId
  259. }
  260. for _, edbInfoId := range edbInfoIdMap {
  261. edbInfoIdList = append(edbInfoIdList, edbInfoId)
  262. }
  263. }
  264. mappingList, err = models.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdList)
  265. if err != nil {
  266. errMsg = `获取失败`
  267. err = errors.New("获取图表,指标信息失败,Err:" + err.Error())
  268. return
  269. }
  270. return
  271. }
  272. // handleData 数据处理
  273. func handleData(baseEdbInfoId int, edbDataListMap map[int][]*models.EdbDataList) (dateEdbMap map[string]map[int]float64, err error) {
  274. dateEdbMap = make(map[string]map[int]float64) // [日期][A指标id:值,B指标id:值]
  275. for edbInfoId, edbDataList := range edbDataListMap {
  276. if edbInfoId != baseEdbInfoId {
  277. // 用上期的数据补充当期的数据处理
  278. handleDataMap := make(map[string]float64)
  279. err = models.HandleDataByPreviousData(edbDataList, handleDataMap)
  280. if err != nil {
  281. return
  282. }
  283. for date, val := range handleDataMap {
  284. item, ok := dateEdbMap[date]
  285. if ok {
  286. item[edbInfoId] = val
  287. } else {
  288. item = map[int]float64{
  289. edbInfoId: val,
  290. }
  291. }
  292. dateEdbMap[date] = item
  293. }
  294. } else {
  295. for _, edbData := range edbDataList {
  296. item, ok := dateEdbMap[edbData.DataTime]
  297. if ok {
  298. item[edbInfoId] = edbData.Value
  299. } else {
  300. item = map[int]float64{
  301. edbInfoId: edbData.Value,
  302. }
  303. }
  304. dateEdbMap[edbData.DataTime] = item
  305. }
  306. }
  307. }
  308. return
  309. }