Skip to content

Commit a5b4e41

Browse files
authored
Merge branch 'main' into wsun/eas-updates
2 parents fd434f5 + 955cd1e commit a5b4e41

File tree

8 files changed

+1152
-12
lines changed

8 files changed

+1152
-12
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { distributeDataPoints } from './utils';
2+
3+
describe('distributeDataPoints', () => {
4+
it('returns all data points when there are exactly 100 points', () => {
5+
const dataPoints = createDataPoints(100);
6+
7+
const result = distributeDataPoints(dataPoints);
8+
9+
expect(result).toEqual(dataPoints);
10+
expect(result.length).toBe(100);
11+
});
12+
13+
it('returns all data points when there are fewer than 100 points', () => {
14+
const dataPoints = createDataPoints(50);
15+
16+
const result = distributeDataPoints(dataPoints);
17+
18+
expect(result).toEqual(dataPoints);
19+
expect(result.length).toBe(50);
20+
});
21+
22+
it('returns exactly 100 points when there are more than 100 points', () => {
23+
const dataPoints = createDataPoints(200);
24+
25+
const result = distributeDataPoints(dataPoints);
26+
27+
expect(result.length).toBe(100);
28+
});
29+
30+
it('includes the first and last data points', () => {
31+
const dataPoints = createDataPoints(200);
32+
33+
const result = distributeDataPoints(dataPoints);
34+
35+
expect(result[0]).toEqual(dataPoints[0]);
36+
expect(result[99]).toEqual(dataPoints[199]);
37+
});
38+
39+
it('maintains chronological order of data points', () => {
40+
const dataPoints = createDataPoints(500);
41+
42+
const result = distributeDataPoints(dataPoints);
43+
44+
for (let i = 1; i < result.length; i++) {
45+
const prevTimestamp = parseInt(result[i - 1][0], 10);
46+
const currTimestamp = parseInt(result[i][0], 10);
47+
expect(currTimestamp).toBeGreaterThanOrEqual(prevTimestamp);
48+
}
49+
});
50+
51+
it('distributes points evenly across the dataset', () => {
52+
const dataPoints = createDataPoints(200, Date.now(), 0);
53+
54+
const result = distributeDataPoints(dataPoints);
55+
56+
// Expected interval: (200 - 1) / 99 ≈ 2.01
57+
// So we should get indices approximately: 0, 2, 4, 6, ..., 197, 199
58+
expect(result[0][1]).toBe(0);
59+
expect(result[1][1]).toBe(2);
60+
expect(result[2][1]).toBe(4);
61+
expect(result[98][1]).toBe(197);
62+
expect(result[99][1]).toBe(199);
63+
});
64+
65+
it('does not duplicate points', () => {
66+
const dataPoints = createDataPoints(300, Date.now(), 0);
67+
68+
const result = distributeDataPoints(dataPoints);
69+
70+
// Check for duplicates by comparing timestamps
71+
const timestamps = result.map((point) => point[0]);
72+
const uniqueTimestamps = new Set(timestamps);
73+
expect(uniqueTimestamps.size).toBe(result.length);
74+
});
75+
76+
it('handles empty array', () => {
77+
const dataPoints: [string, number][] = [];
78+
79+
const result = distributeDataPoints(dataPoints);
80+
81+
expect(result).toEqual([]);
82+
expect(result.length).toBe(0);
83+
});
84+
85+
it('ensures gaps between points are relatively uniform', () => {
86+
const dataPoints = createDataPoints(500, Date.now(), 0);
87+
88+
const result = distributeDataPoints(dataPoints);
89+
90+
// Calculate the value differences between consecutive points
91+
const gaps: number[] = [];
92+
for (let i = 1; i < result.length; i++) {
93+
gaps.push(result[i][1] - result[i - 1][1]);
94+
}
95+
96+
// Expected interval: (500 - 1) / 99 ≈ 5.04
97+
// All gaps should be either 5 or 6 due to rounding
98+
const minGap = Math.min(...gaps);
99+
const maxGap = Math.max(...gaps);
100+
expect(maxGap - minGap).toBeLessThanOrEqual(1);
101+
});
102+
});
103+
104+
function createDataPoints(
105+
length: number,
106+
baseTime: number = Date.now(),
107+
basePrice: number = 3000,
108+
): [string, number][] {
109+
return Array.from({ length }, (_, i) => [
110+
createTimestamp(baseTime, i),
111+
basePrice + i,
112+
]);
113+
}
114+
115+
function createTimestamp(baseTime: number, offsetMinutes: number): string {
116+
return (baseTime + offsetMinutes * 60 * 1000).toString();
117+
}

app/components/UI/AssetOverview/PriceChart/utils.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,30 @@ import { TokenPrice } from 'app/components/hooks/useTokenHistoricalPrices';
33
// this function is used to sample the data points to be displayed on the chart
44
// it will return a maximum of 100 data points
55
// if there are less than 100 data points, it will return all of them
6-
// if there are more than 100 data points, it will return 100 data points
6+
// if there are more than 100 data points, it will return 100 evenly distributed data points
77
// the first and last data points will always be included
8-
// the data points in between will be sampled at an interval of (numDataPoints / 98)
8+
// the data points are distributed evenly across the dataset to ensure similar gaps between points
99

1010
// this is to ensure that the chart does not become unresponsive when there are too many data points
1111
export function distributeDataPoints(dataPoints: TokenPrice[]): TokenPrice[] {
1212
const numDataPoints = dataPoints.length;
13-
const interval = Math.max(1, Math.floor(numDataPoints / 98));
14-
const sampledDataPoints: [string, number][] = [];
15-
sampledDataPoints.push(dataPoints[0]);
16-
for (let i = interval; i < numDataPoints - 1; i += interval) {
17-
if (sampledDataPoints.length === 98) break;
18-
sampledDataPoints.push(dataPoints[i]);
13+
14+
if (numDataPoints <= 100) {
15+
return dataPoints;
1916
}
20-
sampledDataPoints.push(dataPoints[numDataPoints - 1]);
21-
if (sampledDataPoints.length === 99) {
22-
sampledDataPoints.push(dataPoints[numDataPoints - 2]);
17+
18+
// Calculate the exact interval to evenly distribute 100 points across the dataset
19+
// We want indices: 0, interval, 2*interval, ..., numDataPoints-1
20+
// So we need 99 intervals to get 100 points
21+
const interval = (numDataPoints - 1) / 99;
22+
23+
const sampledDataPoints: [string, number][] = [];
24+
25+
for (let i = 0; i < 100; i++) {
26+
const index = Math.round(i * interval);
27+
sampledDataPoints.push(dataPoints[index]);
2328
}
29+
2430
return sampledDataPoints;
2531
}
2632

0 commit comments

Comments
 (0)