mirror of
https://github.com/mempool/mempool.git
synced 2025-02-24 14:50:52 +01:00
[graph] use echart echart yaxis max
property instead of modifying the data itself
This commit is contained in:
parent
c393483590
commit
2d30c0b588
3 changed files with 27 additions and 35 deletions
|
@ -7,6 +7,8 @@ import { formatNumber } from '@angular/common';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
|
const OUTLIERS_MEDIAN_MULTIPLIER = 4;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-incoming-transactions-graph',
|
selector: 'app-incoming-transactions-graph',
|
||||||
templateUrl: './incoming-transactions-graph.component.html',
|
templateUrl: './incoming-transactions-graph.component.html',
|
||||||
|
@ -29,6 +31,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
|
||||||
@Input() left: number | string = '0';
|
@Input() left: number | string = '0';
|
||||||
@Input() template: ('widget' | 'advanced') = 'widget';
|
@Input() template: ('widget' | 'advanced') = 'widget';
|
||||||
@Input() windowPreferenceOverride: string;
|
@Input() windowPreferenceOverride: string;
|
||||||
|
@Input() outlierCappingEnabled: boolean = false;
|
||||||
|
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
mempoolStatsChartOption: EChartsOption = {};
|
mempoolStatsChartOption: EChartsOption = {};
|
||||||
|
@ -40,6 +43,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
|
||||||
MA: number[][] = [];
|
MA: number[][] = [];
|
||||||
weightMode: boolean = false;
|
weightMode: boolean = false;
|
||||||
rateUnitSub: Subscription;
|
rateUnitSub: Subscription;
|
||||||
|
medianVbytesPerSecond: number | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(LOCALE_ID) private locale: string,
|
@Inject(LOCALE_ID) private locale: string,
|
||||||
|
@ -65,16 +69,35 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
|
||||||
this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference');
|
this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference');
|
||||||
const windowSize = Math.max(10, Math.floor(this.data.series[0].length / 8));
|
const windowSize = Math.max(10, Math.floor(this.data.series[0].length / 8));
|
||||||
this.MA = this.calculateMA(this.data.series[0], windowSize);
|
this.MA = this.calculateMA(this.data.series[0], windowSize);
|
||||||
|
if (this.outlierCappingEnabled === true) {
|
||||||
|
this.computeMedianVbytesPerSecond(this.data.series[0]);
|
||||||
|
}
|
||||||
this.mountChart();
|
this.mountChart();
|
||||||
}
|
}
|
||||||
|
|
||||||
rendered() {
|
rendered() {
|
||||||
if (!this.data) {
|
if (!this.data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the median value of the vbytes per second chart to hide outliers
|
||||||
|
*/
|
||||||
|
computeMedianVbytesPerSecond(data: number[][]): void {
|
||||||
|
const vBytes: number[] = [];
|
||||||
|
for (const value of data) {
|
||||||
|
vBytes.push(value[1]);
|
||||||
|
}
|
||||||
|
const sorted = vBytes.slice().sort((a, b) => a - b);
|
||||||
|
const middle = Math.floor(sorted.length / 2);
|
||||||
|
this.medianVbytesPerSecond = sorted[middle];
|
||||||
|
if (sorted.length % 2 === 0) {
|
||||||
|
this.medianVbytesPerSecond = (sorted[middle - 1] + sorted[middle]) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// calculate the moving average of the provided data based on windowSize
|
/// calculate the moving average of the provided data based on windowSize
|
||||||
calculateMA(data: number[][], windowSize: number = 100): number[][] {
|
calculateMA(data: number[][], windowSize: number = 100): number[][] {
|
||||||
//update const variables that are not changed
|
//update const variables that are not changed
|
||||||
|
@ -232,6 +255,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
yAxis: {
|
yAxis: {
|
||||||
|
max: this.outlierCappingEnabled ? Math.round(this.medianVbytesPerSecond * OUTLIERS_MEDIAN_MULTIPLIER) : undefined,
|
||||||
type: 'value',
|
type: 'value',
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
|
|
|
@ -128,7 +128,7 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="incoming-transactions-graph">
|
<div class="incoming-transactions-graph">
|
||||||
<app-incoming-transactions-graph #incominggraph [height]="500" [left]="65" [template]="'advanced'"
|
<app-incoming-transactions-graph #incominggraph [height]="500" [left]="65" [template]="'advanced'"
|
||||||
[data]="mempoolTransactionsWeightPerSecondData"></app-incoming-transactions-graph>
|
[data]="mempoolTransactionsWeightPerSecondData" [outlierCappingEnabled]="outlierCappingEnabled"></app-incoming-transactions-graph>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -160,10 +160,6 @@ export class StatisticsComponent implements OnInit {
|
||||||
labels: labels,
|
labels: labels,
|
||||||
series: [mempoolStats.map((stats) => [stats.added * 1000, stats.vbytes_per_second])],
|
series: [mempoolStats.map((stats) => [stats.added * 1000, stats.vbytes_per_second])],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.outlierCappingEnabled) {
|
|
||||||
this.capExtremeVbytesValues();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
saveGraphPreference() {
|
saveGraphPreference() {
|
||||||
|
@ -214,36 +210,8 @@ export class StatisticsComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
onOutlierToggleChange(e): void {
|
||||||
* All value higher that "median * capRatio" are capped
|
|
||||||
*/
|
|
||||||
onOutlierToggleChange(e) {
|
|
||||||
this.outlierCappingEnabled = e.target.checked;
|
this.outlierCappingEnabled = e.target.checked;
|
||||||
this.handleNewMempoolData(this.mempoolStats);
|
|
||||||
}
|
|
||||||
capExtremeVbytesValues() {
|
|
||||||
if (this.stateService.network.length !== 0) {
|
|
||||||
return; // Only cap on Bitcoin mainnet
|
|
||||||
}
|
|
||||||
|
|
||||||
let capRatio = 4;
|
|
||||||
|
|
||||||
// Find median value
|
|
||||||
const vBytes: number[] = [];
|
|
||||||
for (const stat of this.mempoolTransactionsWeightPerSecondData.series[0]) {
|
|
||||||
vBytes.push(stat[1]);
|
|
||||||
}
|
|
||||||
const sorted = vBytes.slice().sort((a, b) => a - b);
|
|
||||||
const middle = Math.floor(sorted.length / 2);
|
|
||||||
let median = sorted[middle];
|
|
||||||
if (sorted.length % 2 === 0) {
|
|
||||||
median = (sorted[middle - 1] + sorted[middle]) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cap
|
|
||||||
for (const stat of this.mempoolTransactionsWeightPerSecondData.series[0]) {
|
|
||||||
stat[1] = Math.min(median * capRatio, stat[1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSaveChart(name) {
|
onSaveChart(name) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue