Block prediction -> Block health - Fix wrong chart download name

This commit is contained in:
nymkappa 2023-03-16 17:03:32 +09:00 committed by softsimon
parent 7b127ebe8b
commit 720c2b8807
No known key found for this signature in database
GPG key ID: 488D7DCFB5A430D7
13 changed files with 45 additions and 79 deletions

View file

@ -26,7 +26,7 @@ class MiningRoutes {
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/fee-rates/:interval', this.$getHistoricalBlockFeeRates)
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/sizes-weights/:interval', this.$getHistoricalBlockSizeAndWeight)
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/difficulty-adjustments/:interval', this.$getDifficultyAdjustments)
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/predictions/:interval', this.$getHistoricalBlockPrediction)
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/predictions/:interval', this.$getHistoricalBlocksHealth)
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/audit/scores', this.$getBlockAuditScores)
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/audit/scores/:height', this.$getBlockAuditScores)
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/audit/score/:hash', this.$getBlockAuditScore)
@ -244,15 +244,15 @@ class MiningRoutes {
}
}
private async $getHistoricalBlockPrediction(req: Request, res: Response) {
private async $getHistoricalBlocksHealth(req: Request, res: Response) {
try {
const blockPredictions = await mining.$getBlockPredictionsHistory(req.params.interval);
const blockCount = await BlocksAuditsRepository.$getPredictionsCount();
const blocksHealth = await mining.$getBlocksHealthHistory(req.params.interval);
const blockCount = await BlocksAuditsRepository.$getBlocksHealthCount();
res.header('Pragma', 'public');
res.header('Cache-control', 'public');
res.header('X-total-count', blockCount.toString());
res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString());
res.json(blockPredictions.map(prediction => [prediction.time, prediction.height, prediction.match_rate]));
res.json(blocksHealth.map(health => [health.time, health.height, health.match_rate]));
} catch (e) {
res.status(500).send(e instanceof Error ? e.message : e);
}

View file

@ -13,7 +13,6 @@ import BlocksAuditsRepository from '../../repositories/BlocksAuditsRepository';
import PricesRepository from '../../repositories/PricesRepository';
import { bitcoinCoreApi } from '../bitcoin/bitcoin-api-factory';
import { IEsploraApi } from '../bitcoin/esplora-api.interface';
import database from '../../database';
class Mining {
private blocksPriceIndexingRunning = false;
@ -21,10 +20,10 @@ class Mining {
public lastWeeklyHashrateIndexingDate: number | null = null;
/**
* Get historical block predictions match rate
* Get historical blocks health
*/
public async $getBlockPredictionsHistory(interval: string | null = null): Promise<any> {
return await BlocksAuditsRepository.$getBlockPredictionsHistory(
public async $getBlocksHealthHistory(interval: string | null = null): Promise<any> {
return await BlocksAuditsRepository.$getBlocksHealthHistory(
this.getTimeRange(interval),
Common.getSqlInterval(interval)
);

View file

@ -19,7 +19,7 @@ class BlocksAuditRepositories {
}
}
public async $getBlockPredictionsHistory(div: number, interval: string | null): Promise<any> {
public async $getBlocksHealthHistory(div: number, interval: string | null): Promise<any> {
try {
let query = `SELECT UNIX_TIMESTAMP(time) as time, height, match_rate FROM blocks_audits`;
@ -32,17 +32,17 @@ class BlocksAuditRepositories {
const [rows] = await DB.query(query);
return rows;
} catch (e: any) {
logger.err(`Cannot fetch block prediction history. Reason: ` + (e instanceof Error ? e.message : e));
logger.err(`Cannot fetch blocks health history. Reason: ` + (e instanceof Error ? e.message : e));
throw e;
}
}
public async $getPredictionsCount(): Promise<number> {
public async $getBlocksHealthCount(): Promise<number> {
try {
const [rows] = await DB.query(`SELECT count(hash) as count FROM blocks_audits`);
return rows[0].count;
} catch (e: any) {
logger.err(`Cannot fetch block prediction history. Reason: ` + (e instanceof Error ? e.message : e));
logger.err(`Cannot fetch blocks health count. Reason: ` + (e instanceof Error ? e.message : e));
throw e;
}
}

View file

@ -3,7 +3,7 @@
<div class="full-container">
<div class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.block-prediction-accuracy">Block Prediction Accuracy</span>
<span i18n="mining.blocks-health">Block Health</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
@ -12,34 +12,34 @@
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic" [class]="{'disabled': isLoading}">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 144" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 24h
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 24h
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 432" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 3D
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 3D
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 1008" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 1W
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 1W
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 1M
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 3M
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 6M
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 1Y
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 2Y
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> 3Y
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 3Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount > 157680" [class.active]="radioGroupForm.get('dateSpan').value === 'all'">
<input type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" formControlName="dateSpan"> ALL
<input type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> ALL
</label>
</div>
</form>

View file

@ -13,9 +13,9 @@ import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pi
import { StateService } from '../../services/state.service';
@Component({
selector: 'app-block-prediction-graph',
templateUrl: './block-prediction-graph.component.html',
styleUrls: ['./block-prediction-graph.component.scss'],
selector: 'app-block-health-graph',
templateUrl: './block-health-graph.component.html',
styleUrls: ['./block-health-graph.component.scss'],
styles: [`
.loadingGraphs {
position: absolute;
@ -26,7 +26,7 @@ import { StateService } from '../../services/state.service';
`],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BlockPredictionGraphComponent implements OnInit {
export class BlockHealthGraphComponent implements OnInit {
@Input() right: number | string = 45;
@Input() left: number | string = 75;
@ -60,7 +60,7 @@ export class BlockPredictionGraphComponent implements OnInit {
}
ngOnInit(): void {
this.seoService.setTitle($localize`:@@d7d5fcf50179ad70c938491c517efb82de2c8146:Block Prediction Accuracy`);
this.seoService.setTitle($localize`:@@d7d5fcf50179ad70c938491c517efb82de2c8146:Block Health`);
this.miningWindowPreference = '24h';//this.miningService.getDefaultTimespan('24h');
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
@ -80,7 +80,7 @@ export class BlockPredictionGraphComponent implements OnInit {
this.storageService.setValue('miningWindowPreference', timespan);
this.timespan = timespan;
this.isLoading = true;
return this.apiService.getHistoricalBlockPrediction$(timespan)
return this.apiService.getHistoricalBlocksHealth$(timespan)
.pipe(
tap((response) => {
this.prepareChartOptions(response.body);
@ -163,7 +163,7 @@ export class BlockPredictionGraphComponent implements OnInit {
hideOverlap: true,
padding: [0, 5],
},
data: data.map(prediction => prediction[0])
data: data.map(health => health[0])
},
yAxis: data.length === 0 ? undefined : [
{
@ -186,12 +186,12 @@ export class BlockPredictionGraphComponent implements OnInit {
series: data.length === 0 ? undefined : [
{
zlevel: 0,
name: $localize`Match rate`,
data: data.map(prediction => ({
value: prediction[2],
block: prediction[1],
name: $localize`Health`,
data: data.map(health => ({
value: health[2],
block: health[1],
itemStyle: {
color: this.getPredictionColor(prediction[2])
color: this.getHealthColor(health[2])
}
})),
type: 'bar',
@ -257,7 +257,7 @@ export class BlockPredictionGraphComponent implements OnInit {
return 'rgb(' + gradient.red + ',' + gradient.green + ',' + gradient.blue + ')';
}
getPredictionColor(matchRate) {
getHealthColor(matchRate) {
return this.colorGradient(
Math.pow((100 - matchRate) / 100, 0.5),
{red: 67, green: 171, blue: 71},
@ -294,7 +294,7 @@ export class BlockPredictionGraphComponent implements OnInit {
download(this.chartInstance.getDataURL({
pixelRatio: 2,
excludeComponents: ['dataZoom'],
}), `block-fees-${this.timespan}-${Math.round(now.getTime() / 1000)}.svg`);
}), `block-health-${this.timespan}-${Math.round(now.getTime() / 1000)}.svg`);
// @ts-ignore
this.chartOptions.grid.bottom = prevBottom;
this.chartOptions.backgroundColor = 'none';

View file

@ -22,7 +22,7 @@
<a class="dropdown-item" routerLinkActive="active"
[routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" i18n="mining.block-sizes-weights">Block Sizes and Weights</a>
<a *ngIf="stateService.env.AUDIT" class="dropdown-item" routerLinkActive="active"
[routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" i18n="mining.block-prediction-accuracy">Block Prediction Accuracy</a>
[routerLink]="['/graphs/mining/block-health' | relativeUrl]" i18n="mining.blocks-health">Blocks Health</a>
</div>
</div>

View file

@ -21,7 +21,7 @@ import { DashboardComponent } from '../dashboard/dashboard.component';
import { MiningDashboardComponent } from '../components/mining-dashboard/mining-dashboard.component';
import { HashrateChartComponent } from '../components/hashrate-chart/hashrate-chart.component';
import { HashrateChartPoolsComponent } from '../components/hashrates-chart-pools/hashrate-chart-pools.component';
import { BlockPredictionGraphComponent } from '../components/block-prediction-graph/block-prediction-graph.component';
import { BlockHealthGraphComponent } from '../components/block-health-graph/block-health-graph.component';
import { CommonModule } from '@angular/common';
@NgModule({
@ -46,7 +46,7 @@ import { CommonModule } from '@angular/common';
LbtcPegsGraphComponent,
HashrateChartComponent,
HashrateChartPoolsComponent,
BlockPredictionGraphComponent,
BlockHealthGraphComponent,
],
imports: [
CommonModule,

View file

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { BlockPredictionGraphComponent } from '../components/block-prediction-graph/block-prediction-graph.component';
import { BlockHealthGraphComponent } from '../components/block-health-graph/block-health-graph.component';
import { BlockFeeRatesGraphComponent } from '../components/block-fee-rates-graph/block-fee-rates-graph.component';
import { BlockFeesGraphComponent } from '../components/block-fees-graph/block-fees-graph.component';
import { BlockRewardsGraphComponent } from '../components/block-rewards-graph/block-rewards-graph.component';
@ -143,9 +143,9 @@ const routes: Routes = [
redirectTo: 'mempool',
},
{
path: 'mining/block-prediction',
path: 'mining/block-health',
data: { networks: ['bitcoin'] },
component: BlockPredictionGraphComponent,
component: BlockHealthGraphComponent,
},
]
},

View file

@ -253,20 +253,4 @@ export class NodeFeeChartComponent implements OnInit {
isMobile() {
return (window.innerWidth <= 767.98);
}
onSaveChart() {
// @ts-ignore
const prevBottom = this.chartOptions.grid.bottom;
// @ts-ignore
this.chartOptions.grid.bottom = 40;
this.chartOptions.backgroundColor = '#11131f';
this.chartInstance.setOption(this.chartOptions);
download(this.chartInstance.getDataURL({
pixelRatio: 2,
}), `node-fee-chart.svg`);
// @ts-ignore
this.chartOptions.grid.bottom = prevBottom;
this.chartOptions.backgroundColor = 'none';
this.chartInstance.setOption(this.chartOptions);
}
}

View file

@ -252,21 +252,4 @@ export class NodeStatisticsChartComponent implements OnInit {
isMobile() {
return (window.innerWidth <= 767.98);
}
onSaveChart() {
// @ts-ignore
const prevBottom = this.chartOptions.grid.bottom;
const now = new Date();
// @ts-ignore
this.chartOptions.grid.bottom = 40;
this.chartOptions.backgroundColor = '#11131f';
this.chartInstance.setOption(this.chartOptions);
download(this.chartInstance.getDataURL({
pixelRatio: 2,
}), `block-sizes-weights-${this.timespan}-${Math.round(now.getTime() / 1000)}.svg`);
// @ts-ignore
this.chartOptions.grid.bottom = prevBottom;
this.chartOptions.backgroundColor = 'none';
this.chartInstance.setOption(this.chartOptions);
}
}

View file

@ -442,7 +442,7 @@ export class NodesNetworksChartComponent implements OnInit {
download(this.chartInstance.getDataURL({
pixelRatio: 2,
excludeComponents: ['dataZoom'],
}), `block-sizes-weights-${this.timespan}-${Math.round(now.getTime() / 1000)}.svg`);
}), `lightning-nodes-per-network-${Math.round(now.getTime() / 1000)}.svg`);
// @ts-ignore
this.chartOptions.grid.bottom = prevBottom;
this.chartOptions.backgroundColor = 'none';

View file

@ -238,7 +238,7 @@ export class ApiService {
);
}
getHistoricalBlockPrediction$(interval: string | undefined) : Observable<any> {
getHistoricalBlocksHealth$(interval: string | undefined) : Observable<any> {
return this.httpClient.get<any[]>(
this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/blocks/predictions` +
(interval !== undefined ? `/${interval}` : ''), { observe: 'response' }