using ChartAndGraph; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.EventSystems; using WI; using TMPro; using static ChartAndGraph.GraphChartBase; public class UI_GraphChart : UIBase, IPointerClickHandler { public GraphChart Graph; private UI_DateTime prf_dateTime; private RectTransform Content_DateTime; public UI_GraphChartData chartDetailData; private TextMeshProUGUI GraphName; public string graphName; public int targetCount; public int startIndex; public float offsetY; public bool isMainChart; public Action onClickChart; private List graphChartData = new List(); private List graphDateTimeData = new List(); private Dictionary labelPos = new(); private TextMeshProUGUI MinValue; private TextMeshProUGUI MaxValue; private TextMeshProUGUI AveValue; private float min; private float max; private float ave; public override void AfterAwake() { Graph = GetComponentInChildren(); prf_dateTime = Resources.Load("Prefabs/UI/PRF_UI_DateTime"); chartDetailData = GetComponentInChildren(true); } public void Update() { if (!isMainChart) return; if (Input.GetMouseButtonDown(0)) { if (RectTransformUtility.RectangleContainsScreenPoint(chartDetailData.rectTransform, Input.mousePosition)) { return; } chartDetailData.SetActive(false); } } public void OnPointerClick(PointerEventData eventData) { if (!isMainChart) { onClickChart?.Invoke(graphName); } } public void OnClickItem(GraphEventArgs args) { chartDetailData.SetData(graphName, graphChartData[args.Index], graphDateTimeData[args.Index], args.Position); } public void SetChartData(string graphName, GraphChartData graphData) { this.graphName = graphName; SetDataValue(graphData); graphChartData.Clear(); graphDateTimeData.Clear(); Graph.DataSource.VerticalViewSize = max * 2f; Graph.DataSource.ClearCategory("WorkConditionsData"); Graph.DataSource.StartBatch(); for (int i = 0; i < graphData.chartData.Count; i++) { Graph.DataSource.AddPointToCategory("WorkConditionsData", i, graphData.chartData[i]); graphChartData.Add(graphData.chartData[i]); graphDateTimeData.Add(graphData.timeData[i]); } Graph.DataSource.EndBatch(); if (isMainChart) { Graph.OnRedraw.AddListener(SetChartLabels); } } private void SetDataValue(GraphChartData graphData) { min = graphData.chartData.Min(); max = graphData.chartData.Max(); ave = graphData.chartData.Average(); AveValue.SetText(DecimalPointCalculate(ave)); if (isMainChart) { MinValue.SetText(DecimalPointCalculate(min)); MaxValue.SetText(DecimalPointCalculate(max)); } else { GraphName.SetText(this.graphName); } } private void SetChartLabels() { ClearLabels(); this.labelPos.Clear(); for (int i = 0; i < graphChartData.Count; i++) { Graph.PointToWorldSpace(out var worldSpace, i, graphChartData[i], "WorkConditionsData"); this.labelPos.Add(i, worldSpace); } var labelPos = DownSampleToFixedCount(this.labelPos, targetCount, startIndex); foreach(var index in labelPos.Keys) { var date = Instantiate(prf_dateTime, Content_DateTime); date.transform.position = new Vector3(labelPos[index].x, offsetY, 0); date.SetDateTime(graphDateTimeData[index]); } } private void ClearLabels() { if (Content_DateTime.childCount <= 0) return; for (int i = 0; i < Content_DateTime.childCount; i++) { Destroy(Content_DateTime.transform.GetChild(i).gameObject); } } private Dictionary DownSampleToFixedCount(Dictionary labelPos, int targetCount, int startIndex) { Dictionary sampledData = new Dictionary(); if (labelPos.Count <= targetCount || targetCount <= 0) return new Dictionary(labelPos); if (startIndex < 0) startIndex = 0; List keys = labelPos.Keys.OrderBy(k => k).ToList(); int totalCount = keys.Count; if (startIndex >= totalCount) startIndex = totalCount - 1; int availableCount = totalCount - startIndex; double interval = (double)(availableCount - 1) / (targetCount - 1); for (int i = 0; i < targetCount; i++) { int indexInKeys = (int)Math.Round(startIndex + i * interval); if (i == targetCount - 1) indexInKeys = totalCount - 1; if (indexInKeys >= totalCount) indexInKeys = totalCount - 1; int key = keys[indexInKeys]; if (!sampledData.ContainsKey(key)) sampledData.Add(key, labelPos[key]); } return sampledData; } private string DecimalPointCalculate(float value) { var floatValue = Mathf.Round(value * 10f) / 10f; return floatValue.ToString(); } }