2021-04-22 19:29:59 +08:00
using ChartAndGraph ;
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using UnityEngine ;
namespace Assets.Scenes.Ride.Scripts
{
public class ChartDataSourceScript : MonoBehaviour , IComparer < DoubleVector2 >
{
public string Category = "Player 2" ;
2021-04-27 15:15:51 +08:00
public int DownSampleToPoints = 0 ;
public int targetPoints = 500 ;
2021-04-25 19:41:35 +08:00
public List < DoubleVector2 > mData = new List < DoubleVector2 >(); // the data held by the chart
2021-04-22 19:29:59 +08:00
double pageSize = 2f ;
double currentPagePosition = 0.0 ;
double currentZoom = 0f ;
GraphChartBase graph ;
2021-04-25 19:41:35 +08:00
public double mCurrentPageSizeFactor = double . NegativeInfinity ;
2021-04-22 19:29:59 +08:00
private void Start ()
{
graph = GetComponent < GraphChartBase >();
}
2021-04-27 15:15:51 +08:00
public double GetRealTimeStart ()
2021-04-25 13:33:43 +08:00
{
2021-04-27 15:15:51 +08:00
return graph . HorizontalScrolling / mData . Count ();
2021-04-25 13:33:43 +08:00
}
2021-04-27 15:15:51 +08:00
public double GetRealTimeEnd ()
2021-04-25 13:33:43 +08:00
{
2021-04-27 15:15:51 +08:00
return ( graph . HorizontalScrolling + graph . DataSource . HorizontalViewSize ) / mData . Count ();
}
public bool ReachEnd ()
{
return graph . HorizontalScrolling + graph . DataSource . HorizontalViewSize >= mData . Count ;
}
public bool ReachMid ( int index )
{
return index - graph . HorizontalScrolling >= graph . DataSource . HorizontalViewSize / 2 ;
2021-04-25 13:33:43 +08:00
}
2021-05-24 10:16:35 +08:00
public void InitHorizontalScrolling ( int index )
{
var halfView = graph . DataSource . HorizontalViewSize / 2 ;
if ( index >= halfView )
{
if ( index + halfView >= mData . Count )
{
graph . HorizontalScrolling = mData . Count - graph . DataSource . HorizontalViewSize ;
}
else
{
graph . HorizontalScrolling = index - halfView ;
}
}
}
2021-04-22 19:29:59 +08:00
bool VerifySorted ( List < DoubleVector2 > data )
{
if ( data == null )
return true ;
for ( int i = 1 ; i < data . Count ; i ++)
{
if ( data [ i ]. x < data [ i - 1 ]. x )
return false ;
}
return true ;
}
void LoadWithoutDownSampling ( int start , int end )
{
for ( int i = start ; i < end ; i ++) // load the data
{
graph . DataSource . AddPointToCategory ( "Player 2" , mData [ i ]. x , mData [ i ]. y );
}
}
2021-04-23 19:28:35 +08:00
public int total ;
2021-04-22 19:29:59 +08:00
void LoadWithDownSampling ( int start , int end )
{
2021-04-23 19:28:35 +08:00
total = end - start ;
2021-04-22 19:29:59 +08:00
if ( DownSampleToPoints >= total )
{
graph . DataSource . HorizontalViewSize = total ;
LoadWithoutDownSampling ( start , end );
return ;
}
double sampleCount = (( double ) total ) / ( double ) DownSampleToPoints ;
// graph.DataSource.AddPointToCategory(Category, mData[start].x, mData[start].y);
2021-04-27 15:15:51 +08:00
pointMap . Clear ();
2021-04-22 19:29:59 +08:00
for ( int i = 0 ; i < DownSampleToPoints ; i ++)
{
int fractionStart = start + ( int )( i * sampleCount ); // the first point with a fraction
int fractionEnd = start + ( int )(( i + 1 ) * sampleCount ); // the first point with a fraction
fractionEnd = Math . Min ( fractionEnd , mData . Count - 1 );
double x = 0 , y = 0 ;
double divide = 0.0 ;
2021-04-27 15:15:51 +08:00
List < int > l = new List < int >();
2021-04-22 19:29:59 +08:00
for ( int j = fractionStart ; j < fractionEnd ; j ++) // avarge the poins
{
x += mData [ j ]. x ;
y += mData [ j ]. y ;
2021-04-27 15:15:51 +08:00
l . Add ( j );
2021-04-22 19:29:59 +08:00
divide ++;
}
if ( divide > 0.0 )
{
x /= divide ;
y /= divide ;
2021-04-27 15:15:51 +08:00
pointMap . Add ( l , i );
2021-04-22 19:29:59 +08:00
graph . DataSource . AddPointToCategory ( "Player 2" , x , y );
}
else
Debug . Log ( "error" );
}
// graph.DataSource.AddPointToCategory(Category, mData[last].x, mData[last].y);
}
2021-04-27 15:15:51 +08:00
public int GetViewIndex ( int index )
{
foreach ( var item in pointMap )
{
if ( item . Key . Contains ( index ))
{
return item . Value ;
}
}
return index ;
}
2021-04-22 19:29:59 +08:00
2021-04-27 15:15:51 +08:00
private IDictionary < IList < int >, int > pointMap = new Dictionary < IList < int >, int >();
public int FindClosestIndex ( double position ) // if you want to know what is index is currently displayed . use binary search to find it
2021-04-22 19:29:59 +08:00
{
//NOTE :: this method assumes your data is sorted !!!
int res = mData . BinarySearch ( new DoubleVector2 ( position , 0.0 ), this );
if ( res >= 0 )
return res ;
return ~ res ;
}
double PageSizeFactor
{
get
{
return pageSize * graph . DataSource . HorizontalViewSize ;
}
}
void findPointsForPage ( double position , out int start , out int end ) // given a page position , find the right most and left most indices in the data for that page.
{
int index = FindClosestIndex ( position ); // use binary search to find the closest position to the current scroll point
double endPosition = position + PageSizeFactor ;
double startPosition = position - PageSizeFactor ;
//starting from the current index , we find the page boundries
for ( start = index ; start > 0 ; start --)
{
if ( mData [ start ]. x < startPosition ) // take the first point that is out of the page. so the graph doesn't break at the edge
break ;
}
for ( end = index ; end < mData . Count ; end ++)
{
if ( mData [ end ]. x > endPosition ) // take the first point that is out of the page
break ;
}
}
2021-04-25 13:33:43 +08:00
public int start , end ;
2021-04-27 15:15:51 +08:00
public void LoadPage ( double pagePosition )
2021-04-22 19:29:59 +08:00
{
if ( graph != null )
{
graph . DataSource . StartBatch (); // call start batch
graph . DataSource . HorizontalViewOrigin = 0 ;
2021-04-25 13:33:43 +08:00
2021-04-22 19:29:59 +08:00
findPointsForPage ( pagePosition , out start , out end ); // get the page edges
graph . DataSource . ClearCategory ( "Player 2" ); // clear the cateogry
2021-04-27 15:15:51 +08:00
graph . DataSource . HorizontalViewSize = targetPoints > mData . Count ? mData . Count : targetPoints ;
2021-04-22 19:29:59 +08:00
if ( DownSampleToPoints <= 0 )
LoadWithoutDownSampling ( start , end );
else
LoadWithDownSampling ( start , end );
graph . DataSource . EndBatch ();
graph . HorizontalScrolling = pagePosition ;
}
currentPagePosition = pagePosition ;
}
public void SetData ( List < DoubleVector2 > data )
{
if ( data == null )
data = new List < DoubleVector2 >(); // set up an empty list instead of null
if ( VerifySorted ( data ) == false )
{
Debug . LogWarning ( "The data used with large data feed must be sorted acoording to the x value, aborting operation" );
return ;
}
mData = data ;
LoadPage ( currentPagePosition ); // load the page at position 0
}
public void SetDataSource ( double [] data )
{
graph = GetComponent < GraphChartBase >();
List < DoubleVector2 > source = new List < DoubleVector2 >();
for ( int i = 0 ; i < data . Length ; i ++) // initialize with random data
{
source . Add ( new DoubleVector2 ( i , data [ i ]));
}
SetData ( source );
}
public int Compare ( DoubleVector2 x , DoubleVector2 y )
{
if ( x . x < y . x )
return - 1 ;
if ( x . x > y . x )
return 1 ;
return 0 ;
}
2021-04-25 13:33:43 +08:00
public double pageStartThreshold ;
public double pageEndThreshold ;
2021-04-22 19:29:59 +08:00
public void Update ()
{
if ( graph != null )
{
//check the scrolling position of the graph. if we are past the view size , load a new page
2021-04-25 13:33:43 +08:00
pageStartThreshold = currentPagePosition - mCurrentPageSizeFactor ;
pageEndThreshold = currentPagePosition + mCurrentPageSizeFactor - graph . DataSource . HorizontalViewSize ;
2021-04-22 19:29:59 +08:00
if ( graph . HorizontalScrolling < pageStartThreshold || graph . HorizontalScrolling > pageEndThreshold || currentZoom >= graph . DataSource . HorizontalViewSize * 2f )
{
currentZoom = graph . DataSource . HorizontalViewSize ;
mCurrentPageSizeFactor = PageSizeFactor * 0.9f ;
LoadPage ( graph . HorizontalScrolling );
}
}
}
}
}