import {HttpClient} from '@angular/common/http'; import {Injectable} from '@angular/core'; import {HsDialogContainerService} from 'hslayers-ng/components/layout/dialogs/dialog-container.service'; import {HsUtilsService} from 'hslayers-ng/components/utils/utils.service'; // import attractivity from '../Attractivity.json'; import {AdjusterEventService} from './adjuster-event.service'; import {AdjusterLoaderComponent} from './adjuster-loader.component'; import {nuts} from '../nuts'; //import {factors} from './factors.js'; @Injectable({providedIn: 'root'}) export class AdjusterService { serviceBaseUrl: string; factors = []; clusters = []; numberOfClusters = 12; method: string; methods = [ { codename: 'km25.cluster', name: 'k-means (25 random sets, Hartigan-Wong method)', type: 'non-hierarchical', }, { codename: 'km50hw.cluster', name: 'k-means (50 random sets, Hartigan-Wong method)', type: 'non-hierarchical', }, { codename: 'km50l.cluster', name: 'k-means (50 random sets, Lloyd method)', type: 'non-hierarchical', }, { codename: 'km50m.cluster', name: 'k-means (50 random sets, MacQueen method)', type: 'non-hierarchical', }, { codename: 'kme_eu.cluster', name: 'partitioning (Euclidean distance matrix)', type: 'non-hierarchical', }, { codename: 'kme_mn.cluster', name: 'partitioning (Manhattan distance matrix)', type: 'non-hierarchical', }, { codename: 'haclust', name: 'complete linkage (Euclidean distance matrix)', type: 'hierarchical', }, { codename: 'haclustmin', name: 'complete linkage (Minkowski distance matrix)', type: 'hierarchical', }, { codename: 'haclustbin', name: 'complete linkage (asymmetric binary distance matrix)', type: 'hierarchical', }, { codename: 'haclustman', name: 'complete linkage (Manhattan distance matrix)', type: 'hierarchical', }, { codename: 'haclustmax', name: 'complete linkage ("Supremum norm" distance matrix)', type: 'hierarchical', }, { codename: 'haclustcan', name: 'complete linkage (Canberra distance matrix)', type: 'hierarchical', }, /*{ codename: 'haclustcom', name: 'complete linkage (Euclidean distance matrix)', type: 'hierarchical', },*/ {codename: 'haclustwd2', name: 'Ward2', type: 'hierarchical'}, {codename: 'haclustsin', name: 'single linkage', type: 'hierarchical'}, {codename: 'haclustcen', name: 'centroid (UPGMC)', type: 'hierarchical'}, {codename: 'haclustmed', name: 'median (WPGMC)', type: 'hierarchical'}, {codename: 'haclustmcq', name: 'McQuitty (WPGMA)', type: 'hierarchical'}, { codename: 'hdclust', name: 'DIANA (DIvisive ANAlysis)', type: 'hierarchical', }, ]; private _clusteringInProcess: boolean; constructor( public adjusterEventService: AdjusterEventService, public hsDialogContainerService: HsDialogContainerService, public hsUtilsService: HsUtilsService, public httpClient: HttpClient ) { this.serviceBaseUrl = window.location.hostname === 'localhost' ? 'https://jmacura.ml/ws/' // 'http://localhost:3000/' : 'https://publish.lesprojekt.cz/nodejs/'; this.method = 'haclustwd2'; } /** * Sends a request to polirural-attractiveness-service * and applies the returned values */ apply(): void { this.hsDialogContainerService.create(AdjusterLoaderComponent, {}); const f = () => { this._clusteringInProcess = true; this.httpClient .post(this.serviceBaseUrl + 'clusters', { numberOfClusters: this.numberOfClusters, factors: this.factors.map((f) => { return { factor: f.name, weight: f.weight, datasets: f.datasets .filter((ds) => ds.included) .map((ds) => ds.name), }; }), }) .toPromise() .then((data: any) => { const clusterData = data.response; /*let max = 0; this.clusters.forEach((a) => { if (a.aggregate > max) { max = a.aggregate; } }); const normalizer = 1 / max; this.attractivity.forEach((a) => { a.aggregate *= normalizer; }); this.attractivity.forEach((a) => { this.nutsCodeRecordRelations[a.code] = a; });*/ nuts.nuts3Source.forEachFeature((feature) => { // Pair each feature with its clustering data const featureData = clusterData.find( (item) => item['nuts_id'] === feature.get('NUTS_ID') ); if (!featureData) { console.warn(`No data for feature ${feature.get('NUTS_ID')}`); console.log(feature); return; } Object.keys(featureData).forEach(function (key, index) { if (key !== 'nuts_id') { feature.set(key, featureData[key]); } }); }); const clusters = []; for (const region of clusterData) { if (!clusters.includes(region[this.method])) { clusters.push(region[this.method]); } } this.clusters = clusters; this._clusteringInProcess = false; this.adjusterEventService.clustersLoaded.next({success: true}); }) .catch((error) => { console.warn(`Error obtaining data from ${this.serviceBaseUrl}.`); console.log(error); this._clusteringInProcess = false; this.adjusterEventService.clustersLoaded.next({ success: false, err: error, }); }); }; this.hsUtilsService.debounce(f, 300, false, this)(); } init(): void { this._clusteringInProcess = true; this.httpClient .get(this.serviceBaseUrl + 'datasets') .toPromise() .then((data: any) => { this.factors = data.map((dataset) => { return {name: dataset.Factor, weight: 1, datasets: []}; }); this.factors = this.hsUtilsService.removeDuplicates( this.factors, 'name' ); this.factors.forEach((factor) => { factor.datasets = data .filter((ds) => ds.Factor === factor.name) .map((ds) => { return { name: ds.Name, desc: ds.Description, included: true, }; }); }); this.apply(); }) .catch((error) => { console.warn(`Web service at ${this.serviceBaseUrl} unavailable!`); console.log(error); this._clusteringInProcess = false; this.adjusterEventService.clustersLoaded.next({ success: false, err: error, }); }); } /** * @returns {boolean} true if clustering is in process, false otherwise */ isClusteringInProcess(): boolean { return this._clusteringInProcess; } }