chart_info.go 9.3 KB

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