|
|
@@ -1,14 +1,15 @@
|
|
|
import {HttpClient} from '@angular/common/http';
|
|
|
import {Injectable} from '@angular/core';
|
|
|
import {Vector as VectorLayer} from 'ol/layer';
|
|
|
-import {Vector as VectorSource} from 'ol/source';
|
|
|
|
|
|
+import {HsConfig} from 'hslayers-ng/config.service';
|
|
|
import {HsLayerManagerMetadataService} from 'hslayers-ng/components/layermanager/layermanager-metadata.service';
|
|
|
import {HsLayerManagerService} from 'hslayers-ng/components/layermanager';
|
|
|
import {HsUtilsService} from 'hslayers-ng/components/utils/utils.service';
|
|
|
|
|
|
import clusteringMethods from '../data/clustering_methods.json';
|
|
|
-import {obce, obceLayer, osmLayer} from '../app.config';
|
|
|
+import {AdjusterEventService} from './adjuster-event.service';
|
|
|
+import {obce, obceIndexLayer, osmLayer} from '../app.config';
|
|
|
|
|
|
@Injectable({providedIn: 'root'})
|
|
|
export class AdjusterService {
|
|
|
@@ -16,9 +17,10 @@ export class AdjusterService {
|
|
|
factors = [];
|
|
|
//clusters = [];
|
|
|
numberOfClusters;
|
|
|
- method: string;
|
|
|
+ //method: string;
|
|
|
methods: Array<{
|
|
|
codename: string;
|
|
|
+ layer?: VectorLayer;
|
|
|
name: string;
|
|
|
type: string;
|
|
|
}>;
|
|
|
@@ -27,6 +29,8 @@ export class AdjusterService {
|
|
|
private _raiInProcess: boolean;
|
|
|
|
|
|
constructor(
|
|
|
+ public adjusterEventService: AdjusterEventService,
|
|
|
+ public hsConfig: HsConfig,
|
|
|
public hsLayerMetadataService: HsLayerManagerMetadataService,
|
|
|
public hsLayerManagerService: HsLayerManagerService,
|
|
|
public hsUtilsService: HsUtilsService,
|
|
|
@@ -34,12 +38,12 @@ export class AdjusterService {
|
|
|
) {
|
|
|
this.serviceBaseUrl =
|
|
|
window.location.hostname === 'localhost'
|
|
|
- ? 'http://localhost:3000/' // 'https://jmacura.ml/ws/'
|
|
|
+ ? 'https://jmacura.ml/ws/' // 'http://localhost:3000/'
|
|
|
: 'https://publish.lesprojekt.cz/nodejs/';
|
|
|
this.methods = clusteringMethods.filter(
|
|
|
(m) => m.codename == 'haclustwd2' || m.codename == 'km50l.cluster'
|
|
|
);
|
|
|
- this.method = 'haclustwd2';
|
|
|
+ //this.method = 'haclustwd2';
|
|
|
this.numberOfClusters = 9;
|
|
|
}
|
|
|
|
|
|
@@ -49,96 +53,95 @@ export class AdjusterService {
|
|
|
*/
|
|
|
apply(): void {
|
|
|
this.calculateIndex();
|
|
|
- //this.calculateClusters();
|
|
|
+ this.calculateClusters();
|
|
|
}
|
|
|
|
|
|
calculateIndex(): void {
|
|
|
- const f = () => {
|
|
|
- this._raiInProcess = true;
|
|
|
- this.$http
|
|
|
- .post(this.serviceBaseUrl + 'scores/cz', {
|
|
|
- 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((attractivenessData: any[]) => {
|
|
|
- console.log(attractivenessData);
|
|
|
- //this.attractivity = attractivenessData;
|
|
|
- /*let max = 0;
|
|
|
+ //const f = () => {
|
|
|
+ this._raiInProcess = true;
|
|
|
+ this.$http
|
|
|
+ .post(this.serviceBaseUrl + 'scores/cz', {
|
|
|
+ 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((attractivenessData: any[]) => {
|
|
|
+ console.log(attractivenessData);
|
|
|
+ //this.attractivity = attractivenessData;
|
|
|
+ /*let max = 0;
|
|
|
attractivenessData.forEach((a) => {
|
|
|
if (a.aggregate > max) {
|
|
|
max = a.aggregate;
|
|
|
}
|
|
|
});*/
|
|
|
- // Spread the 'aggregate' value between 0 and 1
|
|
|
- const min = attractivenessData.reduce((a, b) =>
|
|
|
- a.aggregate < b.aggregate ? a : b
|
|
|
- ).aggregate;
|
|
|
- const max = attractivenessData.reduce((a, b) =>
|
|
|
- a.aggregate > b.aggregate ? a : b
|
|
|
- ).aggregate;
|
|
|
- const coefficient = 1 / (max - min);
|
|
|
- const constant = -min * coefficient;
|
|
|
- attractivenessData.forEach((a) => {
|
|
|
- a.aggregate *= coefficient;
|
|
|
- a.aggregate += constant;
|
|
|
- });
|
|
|
- console.log(attractivenessData);
|
|
|
- // Store relation between region and its data in a hash-table-like structure
|
|
|
- const codeRecordRelations = {};
|
|
|
- attractivenessData.forEach((a) => {
|
|
|
- codeRecordRelations[a.code] = a;
|
|
|
- });
|
|
|
- let errs = 0;
|
|
|
- let logs = 0;
|
|
|
- console.time('forEachObce');
|
|
|
- obce.forEachFeature((feature) => {
|
|
|
- // Pair each feature with its attractivity data
|
|
|
- const featureData =
|
|
|
- codeRecordRelations[feature.get('nationalCode')];
|
|
|
- /*const featureData = attractivenessData.find(
|
|
|
+ // Spread the 'aggregate' value between 0 and 1
|
|
|
+ const min = attractivenessData.reduce((a, b) =>
|
|
|
+ a.aggregate < b.aggregate ? a : b
|
|
|
+ ).aggregate;
|
|
|
+ const max = attractivenessData.reduce((a, b) =>
|
|
|
+ a.aggregate > b.aggregate ? a : b
|
|
|
+ ).aggregate;
|
|
|
+ const coefficient = 1 / (max - min);
|
|
|
+ const constant = -min * coefficient;
|
|
|
+ attractivenessData.forEach((a) => {
|
|
|
+ a.aggregate *= coefficient;
|
|
|
+ a.aggregate += constant;
|
|
|
+ });
|
|
|
+ console.log(attractivenessData);
|
|
|
+ // Store relation between region and its data in a hash-table-like structure
|
|
|
+ const codeRecordRelations = {};
|
|
|
+ attractivenessData.forEach((a) => {
|
|
|
+ codeRecordRelations[a.code] = a;
|
|
|
+ });
|
|
|
+ let errs = 0;
|
|
|
+ let logs = 0;
|
|
|
+ console.time('forEachObce');
|
|
|
+ obce.forEachFeature((feature) => {
|
|
|
+ // Pair each feature with its attractivity data
|
|
|
+ const featureData = codeRecordRelations[feature.get('nationalCode')];
|
|
|
+ /*const featureData = attractivenessData.find(
|
|
|
// NOTE: Do NOT add triple equal sign!
|
|
|
(item) => item['code'] == feature.get('nationalCode')
|
|
|
);*/
|
|
|
- if (!featureData) {
|
|
|
- if (errs < 20) {
|
|
|
- errs++;
|
|
|
- console.warn(
|
|
|
- `No data for feature ${feature.get('nationalCode')}`
|
|
|
- );
|
|
|
- console.log(feature);
|
|
|
- }
|
|
|
- return;
|
|
|
+ if (!featureData) {
|
|
|
+ if (errs < 20) {
|
|
|
+ errs++;
|
|
|
+ console.warn(
|
|
|
+ `No data for feature ${feature.get('nationalCode')}`
|
|
|
+ );
|
|
|
+ console.log(feature);
|
|
|
}
|
|
|
- logs++;
|
|
|
- if (logs % 100 == 0) {
|
|
|
- console.log(`processed ${logs} items`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ logs++;
|
|
|
+ if (logs % 100 == 0) {
|
|
|
+ console.log(`processed ${logs} items`);
|
|
|
+ }
|
|
|
+ Object.keys(featureData).forEach((key, index) => {
|
|
|
+ if (key !== 'lau2') {
|
|
|
+ feature.set(key, featureData[key], true); //true stands for "silent" - important!
|
|
|
}
|
|
|
- Object.keys(featureData).forEach((key, index) => {
|
|
|
- if (key !== 'lau2') {
|
|
|
- feature.set(key, featureData[key], true); //true stands for "silent" - important!
|
|
|
- }
|
|
|
- });
|
|
|
- /*feature.set(
|
|
|
+ });
|
|
|
+ /*feature.set(
|
|
|
'total',
|
|
|
this.nutsCodeRecordRelations[feature.get('nationalCode')]
|
|
|
.aggregate
|
|
|
);*/
|
|
|
- /*feature.set(
|
|
|
+ /*feature.set(
|
|
|
'totalForHumans',
|
|
|
(
|
|
|
this.nutsCodeRecordRelations[feature.get('nationalCode')]
|
|
|
.aggregate * 100
|
|
|
).toFixed(2)
|
|
|
);*/
|
|
|
- /*this.factors.forEach((factor) => {
|
|
|
+ /*this.factors.forEach((factor) => {
|
|
|
feature.set(
|
|
|
factor.name,
|
|
|
(
|
|
|
@@ -148,45 +151,54 @@ export class AdjusterService {
|
|
|
).toFixed(2)
|
|
|
);
|
|
|
});*/
|
|
|
- });
|
|
|
- // Since we are updating the features silently, we now have to refresh manually
|
|
|
- obce.getFeatures()[0].dispatchEvent('change');
|
|
|
- console.timeEnd('forEachObce');
|
|
|
- this._raiInProcess = false;
|
|
|
- })
|
|
|
- .catch((error) => {
|
|
|
- console.warn(`Error obtaining data from ${this.serviceBaseUrl}.`);
|
|
|
- console.log(error);
|
|
|
- this._raiInProcess = false;
|
|
|
});
|
|
|
- };
|
|
|
- this.hsUtilsService.debounce(f, 300, false, this)();
|
|
|
+ // Since we are updating the features silently, we now have to refresh manually
|
|
|
+ obce.getFeatures()[0].dispatchEvent('change');
|
|
|
+ console.timeEnd('forEachObce');
|
|
|
+ this._raiInProcess = false;
|
|
|
+ this.adjusterEventService.loaded.next({
|
|
|
+ success: true,
|
|
|
+ type: 'index',
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.warn(`Error obtaining data from ${this.serviceBaseUrl}.`);
|
|
|
+ console.log(error);
|
|
|
+ this._raiInProcess = false;
|
|
|
+ this.adjusterEventService.loaded.next({
|
|
|
+ success: true,
|
|
|
+ type: 'index',
|
|
|
+ err: error,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ //};
|
|
|
+ //this.hsUtilsService.debounce(f, 300, false, this)();
|
|
|
}
|
|
|
|
|
|
calculateClusters(): void {
|
|
|
- const f = () => {
|
|
|
- this._clusteringInProcess = true;
|
|
|
- this.$http
|
|
|
- .post(this.serviceBaseUrl + 'clusters/cz', {
|
|
|
- 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) => {
|
|
|
- console.log('data received', data);
|
|
|
- let logs = 0;
|
|
|
- let errs = 0;
|
|
|
- const clusterData = data.response;
|
|
|
- console.log(obceLayer);
|
|
|
- /*let sublayers = [];
|
|
|
+ //const f = () => {
|
|
|
+ this._clusteringInProcess = true;
|
|
|
+ this.$http
|
|
|
+ .post(this.serviceBaseUrl + 'clusters/cz', {
|
|
|
+ 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) => {
|
|
|
+ console.log('data received', data);
|
|
|
+ let logs = 0;
|
|
|
+ let errs = 0;
|
|
|
+ const clusterData = data.response;
|
|
|
+ console.log(obceIndexLayer);
|
|
|
+ /*let sublayers = [];
|
|
|
const oldSublayers = obceLayer.get('Layer');
|
|
|
if (oldSublayers !== undefined && Array.isArray(oldSublayers)) {
|
|
|
for (const sublyr of oldSublayers) {
|
|
|
@@ -208,36 +220,36 @@ export class AdjusterService {
|
|
|
sublyr.Name = `c${i + 1}`;
|
|
|
i++;
|
|
|
}*/
|
|
|
- console.time('forEachObceCluster');
|
|
|
- obce.forEachFeature((feature) => {
|
|
|
- // Pair each feature with its clustering data
|
|
|
- const featureData = clusterData.find(
|
|
|
- // NOTE: Do NOT add triple equal sign!
|
|
|
- (item) => item['lau2'] == feature.get('nationalCode')
|
|
|
- );
|
|
|
- if (!featureData) {
|
|
|
- if (errs < 20) {
|
|
|
- errs++;
|
|
|
- console.warn(
|
|
|
- `No data for feature ${feature.get('nationalCode')}`
|
|
|
- );
|
|
|
- console.log(feature);
|
|
|
- }
|
|
|
- return;
|
|
|
+ console.time('forEachObceCluster');
|
|
|
+ obce.forEachFeature((feature) => {
|
|
|
+ // Pair each feature with its clustering data
|
|
|
+ const featureData = clusterData.find(
|
|
|
+ // NOTE: Do NOT add triple equal sign!
|
|
|
+ (item) => item['lau2'] == feature.get('nationalCode')
|
|
|
+ );
|
|
|
+ if (!featureData) {
|
|
|
+ if (errs < 20) {
|
|
|
+ errs++;
|
|
|
+ console.warn(
|
|
|
+ `No data for feature ${feature.get('nationalCode')}`
|
|
|
+ );
|
|
|
+ console.log(feature);
|
|
|
}
|
|
|
- logs++;
|
|
|
- if (logs % 100 == 0) {
|
|
|
- console.log(`processed ${logs} items`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ logs++;
|
|
|
+ if (logs % 100 == 0) {
|
|
|
+ console.log(`processed ${logs} items`);
|
|
|
+ }
|
|
|
+ Object.keys(featureData).forEach(function (key, index) {
|
|
|
+ if (key !== 'lau2') {
|
|
|
+ feature.set(key, featureData[key], true);
|
|
|
}
|
|
|
- Object.keys(featureData).forEach(function (key, index) {
|
|
|
- if (key !== 'lau2') {
|
|
|
- feature.set(key, featureData[key], true);
|
|
|
- }
|
|
|
- });
|
|
|
});
|
|
|
- //const clusters = [];
|
|
|
- //const obceFeatures: Array<any> = obce.getFeatures();
|
|
|
- /*for (const region of clusterData) {
|
|
|
+ });
|
|
|
+ //const clusters = [];
|
|
|
+ //const obceFeatures: Array<any> = obce.getFeatures();
|
|
|
+ /*for (const region of clusterData) {
|
|
|
if (!clusters.includes(region[this.method])) {
|
|
|
clusters.push(region[this.method]);
|
|
|
}
|
|
|
@@ -267,27 +279,31 @@ export class AdjusterService {
|
|
|
}
|
|
|
//sublayers[region[this.method] - 1].getSource().addFeature(feature);
|
|
|
}*/
|
|
|
- //obceLayer.set('Layer', sublayers);
|
|
|
- //this.hsLayerMetadataService.fillMetadata(obceLayer);
|
|
|
- //console.log(sublayers[0].getSource().getFeatures());
|
|
|
- console.log(obceLayer);
|
|
|
- console.timeEnd('forEachObceCluster');
|
|
|
- console.log('clustering done!');
|
|
|
- //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,
|
|
|
- });*/
|
|
|
+ //obceLayer.set('Layer', sublayers);
|
|
|
+ //this.hsLayerMetadataService.fillMetadata(obceLayer);
|
|
|
+ //console.log(sublayers[0].getSource().getFeatures());
|
|
|
+ console.log(obceIndexLayer);
|
|
|
+ console.timeEnd('forEachObceCluster');
|
|
|
+ console.log('clustering done!');
|
|
|
+ //this.clusters = clusters;
|
|
|
+ this._clusteringInProcess = false;
|
|
|
+ this.adjusterEventService.loaded.next({
|
|
|
+ success: true,
|
|
|
+ type: 'clusters',
|
|
|
});
|
|
|
- };
|
|
|
- this.hsUtilsService.debounce(f, 300, false, this)();
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.warn(`Error obtaining data from ${this.serviceBaseUrl}.`);
|
|
|
+ console.log(error);
|
|
|
+ this._clusteringInProcess = false;
|
|
|
+ this.adjusterEventService.loaded.next({
|
|
|
+ success: false,
|
|
|
+ type: 'clusters',
|
|
|
+ err: error,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ //};
|
|
|
+ //this.hsUtilsService.debounce(f, 300, false, this)();
|
|
|
}
|
|
|
|
|
|
init(): void {
|