Merge pull request #2694 from mononaut/ln-channel-distance
calculate & show avg channel distance on node page
This commit is contained in:
		
						commit
						a9760326f2
					
				| @ -52,6 +52,10 @@ | |||||||
|                 <span i18n="unknown">Unknown</span> |                 <span i18n="unknown">Unknown</span> | ||||||
|               </td> |               </td> | ||||||
|             </tr> |             </tr> | ||||||
|  |             <tr *ngIf="(avgChannelDistance$ | async) as avgDistance;"> | ||||||
|  |               <td i18n="lightning.avg-distance" class="text-truncate">Avg channel distance</td> | ||||||
|  |               <td>{{ avgDistance | number : '1.0-0' }} <span class="symbol">km</span> <span class="separator">/</span> {{ kmToMiles(avgDistance) | number : '1.0-0' }} <span class="symbol">mi</span></td> | ||||||
|  |             </tr> | ||||||
|           </tbody> |           </tbody> | ||||||
|         </table> |         </table> | ||||||
|       </div> |       </div> | ||||||
|  | |||||||
| @ -101,3 +101,7 @@ app-fiat { | |||||||
|     font-family: "Courier New", Courier, monospace; |     font-family: "Courier New", Courier, monospace; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .separator { | ||||||
|  |   margin: 0 1em; | ||||||
|  | } | ||||||
|  | |||||||
| @ -3,9 +3,11 @@ import { ActivatedRoute, ParamMap } from '@angular/router'; | |||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { catchError, map, switchMap, tap } from 'rxjs/operators'; | import { catchError, map, switchMap, tap } from 'rxjs/operators'; | ||||||
| import { SeoService } from '../../services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
|  | import { ApiService } from '../../services/api.service'; | ||||||
| import { LightningApiService } from '../lightning-api.service'; | import { LightningApiService } from '../lightning-api.service'; | ||||||
| import { GeolocationData } from '../../shared/components/geolocation/geolocation.component'; | import { GeolocationData } from '../../shared/components/geolocation/geolocation.component'; | ||||||
| import { ILiquidityAd, parseLiquidityAdHex } from './liquidity-ad'; | import { ILiquidityAd, parseLiquidityAdHex } from './liquidity-ad'; | ||||||
|  | import { haversineDistance, kmToMiles } from 'src/app/shared/common.utils'; | ||||||
| 
 | 
 | ||||||
| interface CustomRecord { | interface CustomRecord { | ||||||
|   type: string; |   type: string; | ||||||
| @ -34,8 +36,12 @@ export class NodeComponent implements OnInit { | |||||||
|   showDetails = false; |   showDetails = false; | ||||||
|   liquidityAd: ILiquidityAd; |   liquidityAd: ILiquidityAd; | ||||||
|   tlvRecords: CustomRecord[]; |   tlvRecords: CustomRecord[]; | ||||||
|  |   avgChannelDistance$: Observable<number | null>; | ||||||
|  | 
 | ||||||
|  |   kmToMiles = kmToMiles; | ||||||
| 
 | 
 | ||||||
|   constructor( |   constructor( | ||||||
|  |     private apiService: ApiService, | ||||||
|     private lightningApiService: LightningApiService, |     private lightningApiService: LightningApiService, | ||||||
|     private activatedRoute: ActivatedRoute, |     private activatedRoute: ActivatedRoute, | ||||||
|     private seoService: SeoService, |     private seoService: SeoService, | ||||||
| @ -119,6 +125,26 @@ export class NodeComponent implements OnInit { | |||||||
|           }]; |           }]; | ||||||
|         }) |         }) | ||||||
|       ); |       ); | ||||||
|  | 
 | ||||||
|  |     this.avgChannelDistance$ = this.activatedRoute.paramMap | ||||||
|  |     .pipe( | ||||||
|  |       switchMap((params: ParamMap) => { | ||||||
|  |         return this.apiService.getChannelsGeo$(params.get('public_key'), 'nodepage'); | ||||||
|  |       }), | ||||||
|  |       map((channelsGeo) => { | ||||||
|  |         if (channelsGeo?.length) { | ||||||
|  |           const totalDistance = channelsGeo.reduce((sum, chan) => { | ||||||
|  |             return sum + haversineDistance(chan[3], chan[2], chan[7], chan[6]); | ||||||
|  |           }, 0); | ||||||
|  |           return totalDistance / channelsGeo.length; | ||||||
|  |         } else { | ||||||
|  |           return null; | ||||||
|  |         } | ||||||
|  |       }), | ||||||
|  |       catchError(() => { | ||||||
|  |         return null; | ||||||
|  |       }) | ||||||
|  |     ) as Observable<number | null>; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   toggleShowDetails(): void { |   toggleShowDetails(): void { | ||||||
|  | |||||||
| @ -118,3 +118,21 @@ export function convertRegion(input, to: 'name' | 'abbreviated'): string { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export function haversineDistance(lat1: number, lon1: number, lat2: number, lon2: number): number { | ||||||
|  |   const rlat1 = lat1 * Math.PI / 180; | ||||||
|  |   const rlon1 = lon1 * Math.PI / 180; | ||||||
|  |   const rlat2 = lat2 * Math.PI / 180; | ||||||
|  |   const rlon2 = lon2 * Math.PI / 180; | ||||||
|  | 
 | ||||||
|  |   const dlat = Math.sin((rlat2 - rlat1) / 2); | ||||||
|  |   const dlon = Math.sin((rlon2 - rlon1) / 2); | ||||||
|  |   const a = Math.min(1, Math.max(0, (dlat * dlat) + (Math.cos(rlat1) * Math.cos(rlat2) * dlon * dlon))); | ||||||
|  |   const d = 2 * 6371 * Math.asin(Math.sqrt(a)); | ||||||
|  | 
 | ||||||
|  |   return d; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function kmToMiles(km: number): number { | ||||||
|  |   return km * 0.62137119; | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user