@@ -80,7 +80,7 @@ export const HistoryGraph = GObject.registerClass({
8080 if ( data . length === 0 ) return ;
8181
8282 const graphW = GRAPH_WIDTH - 2 * PADDING ;
83- const graphH = GRAPH_HEIGHT - 2 * PADDING ;
83+ const graphH = GRAPH_HEIGHT - PADDING ;
8484 if ( graphW <= 0 || graphH <= 0 ) return ;
8585
8686 const vals = data . map ( d => d . v ) ;
@@ -97,37 +97,72 @@ export const HistoryGraph = GObject.registerClass({
9797 const now = Date . now ( ) / 1000 ;
9898 const tOldest = data [ 0 ] . t ;
9999
100- const gaps = [ ] ;
100+ const rawGaps = [ ] ;
101101 for ( let i = 1 ; i < data . length ; i ++ )
102- gaps . push ( data [ i ] . t - data [ i - 1 ] . t ) ;
103- gaps . sort ( ( a , b ) => a - b ) ;
104- const medianGap = gaps . length > 0
105- ? gaps [ Math . floor ( gaps . length / 2 ) ]
102+ rawGaps . push ( data [ i ] . t - data [ i - 1 ] . t ) ;
103+ rawGaps . sort ( ( a , b ) => a - b ) ;
104+ const rawMedianGap = rawGaps . length > 0
105+ ? rawGaps [ Math . floor ( rawGaps . length / 2 ) ]
106106 : 0 ;
107- const maxBarTime = medianGap > 0 ? medianGap * 2.5 : Infinity ;
108107
109- const tEnd = medianGap > 0
110- ? data [ data . length - 1 ] . t + medianGap
108+ const tEnd = rawMedianGap > 0
109+ ? data [ data . length - 1 ] . t + rawMedianGap
111110 : now ;
112111 this . _tSpan = tEnd - tOldest ;
113112 const tRange = Math . max ( 0.001 , this . _tSpan ) ;
114113
115- const xPixels = data . map ( d =>
114+ const maxBars = Math . floor ( graphW / MIN_BAR_WIDTH ) ;
115+ let displayData ;
116+ if ( data . length <= maxBars ) {
117+ displayData = data ;
118+ } else {
119+ const bucketDuration = tRange / maxBars ;
120+ displayData = [ ] ;
121+ let di = 0 ;
122+ for ( let b = 0 ; b < maxBars ; b ++ ) {
123+ const bEnd = tOldest + ( b + 1 ) * bucketDuration ;
124+ let sum = 0 , count = 0 ;
125+ while ( di < data . length && data [ di ] . t < bEnd ) {
126+ sum += data [ di ] . v ;
127+ count ++ ;
128+ di ++ ;
129+ }
130+ if ( count > 0 ) {
131+ displayData . push ( {
132+ t : tOldest + b * bucketDuration ,
133+ v : sum / count
134+ } ) ;
135+ }
136+ }
137+ }
138+
139+ if ( displayData . length === 0 ) return ;
140+
141+ const gaps = [ ] ;
142+ for ( let i = 1 ; i < displayData . length ; i ++ )
143+ gaps . push ( displayData [ i ] . t - displayData [ i - 1 ] . t ) ;
144+ gaps . sort ( ( a , b ) => a - b ) ;
145+ const medianGap = gaps . length > 0
146+ ? gaps [ Math . floor ( gaps . length / 2 ) ]
147+ : 0 ;
148+ const maxBarTime = medianGap > 0 ? medianGap * 2.5 : Infinity ;
149+
150+ const xPixels = displayData . map ( d =>
116151 Math . round ( ( d . t - tOldest ) / tRange * graphW ) ) ;
117152
118- for ( let i = 0 ; i < data . length ; i ++ ) {
119- const v = data [ i ] . v ;
153+ for ( let i = 0 ; i < displayData . length ; i ++ ) {
154+ const v = displayData [ i ] . v ;
120155 const norm = ( v - vMin ) / vRange ;
121156 const barH = Math . max ( 1 , Math . round ( norm * graphH ) ) ;
122157 const x = xPixels [ i ] ;
123- const nextT = ( i < data . length - 1 ) ? data [ i + 1 ] . t : tEnd ;
124- const gap = nextT - data [ i ] . t ;
158+ const nextT = ( i < displayData . length - 1 ) ? displayData [ i + 1 ] . t : tEnd ;
159+ const gap = nextT - displayData [ i ] . t ;
125160 let rightEdge ;
126161 if ( gap <= maxBarTime ) {
127- rightEdge = ( i < data . length - 1 ) ? xPixels [ i + 1 ] : graphW ;
162+ rightEdge = ( i < displayData . length - 1 ) ? xPixels [ i + 1 ] : graphW ;
128163 } else {
129164 rightEdge = Math . min ( graphW ,
130- Math . round ( ( data [ i ] . t - tOldest + maxBarTime ) / tRange * graphW ) ) ;
165+ Math . round ( ( displayData [ i ] . t - tOldest + maxBarTime ) / tRange * graphW ) ) ;
131166 }
132167 const barW = Math . max ( MIN_BAR_WIDTH , rightEdge - x ) ;
133168 const y = graphH - barH ;
0 commit comments