|
@@ -7,12 +7,18 @@ import {HsLayerManagerMetadataService} from 'hslayers-ng/components/layermanager
|
|
|
import {HsLayerManagerService} from 'hslayers-ng/components/layermanager';
|
|
import {HsLayerManagerService} from 'hslayers-ng/components/layermanager';
|
|
|
import {HsUtilsService} from 'hslayers-ng/components/utils/utils.service';
|
|
import {HsUtilsService} from 'hslayers-ng/components/utils/utils.service';
|
|
|
|
|
|
|
|
|
|
+import attractivenessConfig from '../attractiveness.config.json';
|
|
|
import clusteringMethods from '../data/clustering_methods.json';
|
|
import clusteringMethods from '../data/clustering_methods.json';
|
|
|
import {AdjusterEventService} from './adjuster-event.service';
|
|
import {AdjusterEventService} from './adjuster-event.service';
|
|
|
import {obce, obceIndexLayer, osmLayer} from '../app.config';
|
|
import {obce, obceIndexLayer, osmLayer} from '../app.config';
|
|
|
|
|
|
|
|
@Injectable({providedIn: 'root'})
|
|
@Injectable({providedIn: 'root'})
|
|
|
export class AdjusterService {
|
|
export class AdjusterService {
|
|
|
|
|
+ /** To be read from a config file */
|
|
|
|
|
+ allowedClusteringMethods: Array<string>;
|
|
|
|
|
+ /** To be read from a config file */
|
|
|
|
|
+ initialWeights;
|
|
|
|
|
+ /** To be read from a config file */
|
|
|
serviceBaseUrl: string;
|
|
serviceBaseUrl: string;
|
|
|
factors = [];
|
|
factors = [];
|
|
|
//clusters = [];
|
|
//clusters = [];
|
|
@@ -36,14 +42,18 @@ export class AdjusterService {
|
|
|
public hsUtilsService: HsUtilsService,
|
|
public hsUtilsService: HsUtilsService,
|
|
|
public $http: HttpClient
|
|
public $http: HttpClient
|
|
|
) {
|
|
) {
|
|
|
|
|
+ // First safely set configurable properties
|
|
|
|
|
+ this.allowedClusteringMethods =
|
|
|
|
|
+ attractivenessConfig?.allowedClusteringMethods ?? [];
|
|
|
|
|
+ this.initialWeights = attractivenessConfig?.initialWeights ?? {};
|
|
|
this.serviceBaseUrl =
|
|
this.serviceBaseUrl =
|
|
|
- window.location.hostname === 'localhost'
|
|
|
|
|
- ? 'https://jmacura.ml/ws/' // 'http://localhost:3000/'
|
|
|
|
|
- : 'https://publish.lesprojekt.cz/nodejs/';
|
|
|
|
|
- this.methods = clusteringMethods.filter(
|
|
|
|
|
- (m) => m.codename == 'haclustwd2' || m.codename == 'km50l.cluster'
|
|
|
|
|
|
|
+ attractivenessConfig?.serviceBaseUrl ??
|
|
|
|
|
+ 'https://publish.lesprojekt.cz/nodejs/';
|
|
|
|
|
+ // 'https://jmacura.ml/ws/' // 'http://localhost:3000/'
|
|
|
|
|
+
|
|
|
|
|
+ this.methods = clusteringMethods.filter((m) =>
|
|
|
|
|
+ this.allowedClusteringMethods.includes(m.codename)
|
|
|
);
|
|
);
|
|
|
- //this.method = 'haclustwd2';
|
|
|
|
|
this.numberOfClusters = 9;
|
|
this.numberOfClusters = 9;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -57,7 +67,6 @@ export class AdjusterService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
calculateIndex(): void {
|
|
calculateIndex(): void {
|
|
|
- //const f = () => {
|
|
|
|
|
this._raiInProcess = true;
|
|
this._raiInProcess = true;
|
|
|
this.$http
|
|
this.$http
|
|
|
.post(this.serviceBaseUrl + 'scores/cz', {
|
|
.post(this.serviceBaseUrl + 'scores/cz', {
|
|
@@ -74,13 +83,6 @@ export class AdjusterService {
|
|
|
.toPromise()
|
|
.toPromise()
|
|
|
.then((attractivenessData: any[]) => {
|
|
.then((attractivenessData: any[]) => {
|
|
|
console.log(attractivenessData);
|
|
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
|
|
// Spread the 'aggregate' value between 0 and 1
|
|
|
const min = attractivenessData.reduce((a, b) =>
|
|
const min = attractivenessData.reduce((a, b) =>
|
|
|
a.aggregate < b.aggregate ? a : b
|
|
a.aggregate < b.aggregate ? a : b
|
|
@@ -94,22 +96,18 @@ export class AdjusterService {
|
|
|
a.aggregate *= coefficient;
|
|
a.aggregate *= coefficient;
|
|
|
a.aggregate += constant;
|
|
a.aggregate += constant;
|
|
|
});
|
|
});
|
|
|
- console.log(attractivenessData);
|
|
|
|
|
// Store relation between region and its data in a hash-table-like structure
|
|
// Store relation between region and its data in a hash-table-like structure
|
|
|
|
|
+ // more memory consuming, but faster then find()
|
|
|
const codeRecordRelations = {};
|
|
const codeRecordRelations = {};
|
|
|
attractivenessData.forEach((a) => {
|
|
attractivenessData.forEach((a) => {
|
|
|
codeRecordRelations[a.code] = a;
|
|
codeRecordRelations[a.code] = a;
|
|
|
});
|
|
});
|
|
|
let errs = 0;
|
|
let errs = 0;
|
|
|
- let logs = 0;
|
|
|
|
|
- console.time('forEachObce');
|
|
|
|
|
|
|
+ //let logs = 0;
|
|
|
|
|
+ console.time('forEach-Index');
|
|
|
obce.forEachFeature((feature) => {
|
|
obce.forEachFeature((feature) => {
|
|
|
// Pair each feature with its attractivity data
|
|
// Pair each feature with its attractivity data
|
|
|
const featureData = codeRecordRelations[feature.get('nationalCode')];
|
|
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 (!featureData) {
|
|
|
if (errs < 20) {
|
|
if (errs < 20) {
|
|
|
errs++;
|
|
errs++;
|
|
@@ -120,41 +118,19 @@ export class AdjusterService {
|
|
|
}
|
|
}
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- logs++;
|
|
|
|
|
|
|
+ /*logs++;
|
|
|
if (logs % 100 == 0) {
|
|
if (logs % 100 == 0) {
|
|
|
console.log(`processed ${logs} items`);
|
|
console.log(`processed ${logs} items`);
|
|
|
- }
|
|
|
|
|
|
|
+ }*/
|
|
|
Object.keys(featureData).forEach((key, index) => {
|
|
Object.keys(featureData).forEach((key, index) => {
|
|
|
if (key !== 'lau2') {
|
|
if (key !== 'lau2') {
|
|
|
- feature.set(key, featureData[key], true); //true stands for "silent" - important!
|
|
|
|
|
|
|
+ feature.set(key, featureData[key], true); //true stands for "silent" - important for performance!
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
- /*feature.set(
|
|
|
|
|
- 'total',
|
|
|
|
|
- this.nutsCodeRecordRelations[feature.get('nationalCode')]
|
|
|
|
|
- .aggregate
|
|
|
|
|
- );*/
|
|
|
|
|
- /*feature.set(
|
|
|
|
|
- 'totalForHumans',
|
|
|
|
|
- (
|
|
|
|
|
- this.nutsCodeRecordRelations[feature.get('nationalCode')]
|
|
|
|
|
- .aggregate * 100
|
|
|
|
|
- ).toFixed(2)
|
|
|
|
|
- );*/
|
|
|
|
|
- /*this.factors.forEach((factor) => {
|
|
|
|
|
- feature.set(
|
|
|
|
|
- factor.name,
|
|
|
|
|
- (
|
|
|
|
|
- this.nutsCodeRecordRelations[feature.get('nationalCode')][
|
|
|
|
|
- factor.name
|
|
|
|
|
- ] * 100
|
|
|
|
|
- ).toFixed(2)
|
|
|
|
|
- );
|
|
|
|
|
- });*/
|
|
|
|
|
});
|
|
});
|
|
|
// Since we are updating the features silently, we now have to refresh manually
|
|
// Since we are updating the features silently, we now have to refresh manually
|
|
|
obce.getFeatures()[0].dispatchEvent('change');
|
|
obce.getFeatures()[0].dispatchEvent('change');
|
|
|
- console.timeEnd('forEachObce');
|
|
|
|
|
|
|
+ console.timeEnd('forEach-Index');
|
|
|
this._raiInProcess = false;
|
|
this._raiInProcess = false;
|
|
|
this.adjusterEventService.loaded.next({
|
|
this.adjusterEventService.loaded.next({
|
|
|
success: true,
|
|
success: true,
|
|
@@ -171,12 +147,9 @@ export class AdjusterService {
|
|
|
err: error,
|
|
err: error,
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
- //};
|
|
|
|
|
- //this.hsUtilsService.debounce(f, 300, false, this)();
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
calculateClusters(): void {
|
|
calculateClusters(): void {
|
|
|
- //const f = () => {
|
|
|
|
|
this._clusteringInProcess = true;
|
|
this._clusteringInProcess = true;
|
|
|
this.$http
|
|
this.$http
|
|
|
.post(this.serviceBaseUrl + 'clusters/cz', {
|
|
.post(this.serviceBaseUrl + 'clusters/cz', {
|
|
@@ -220,7 +193,7 @@ export class AdjusterService {
|
|
|
sublyr.Name = `c${i + 1}`;
|
|
sublyr.Name = `c${i + 1}`;
|
|
|
i++;
|
|
i++;
|
|
|
}*/
|
|
}*/
|
|
|
- console.time('forEachObceCluster');
|
|
|
|
|
|
|
+ console.time('forEach-Cluster');
|
|
|
obce.forEachFeature((feature) => {
|
|
obce.forEachFeature((feature) => {
|
|
|
// Pair each feature with its clustering data
|
|
// Pair each feature with its clustering data
|
|
|
const featureData = clusterData.find(
|
|
const featureData = clusterData.find(
|
|
@@ -282,8 +255,7 @@ export class AdjusterService {
|
|
|
//obceLayer.set('Layer', sublayers);
|
|
//obceLayer.set('Layer', sublayers);
|
|
|
//this.hsLayerMetadataService.fillMetadata(obceLayer);
|
|
//this.hsLayerMetadataService.fillMetadata(obceLayer);
|
|
|
//console.log(sublayers[0].getSource().getFeatures());
|
|
//console.log(sublayers[0].getSource().getFeatures());
|
|
|
- console.log(obceIndexLayer);
|
|
|
|
|
- console.timeEnd('forEachObceCluster');
|
|
|
|
|
|
|
+ console.timeEnd('forEach-Cluster');
|
|
|
console.log('clustering done!');
|
|
console.log('clustering done!');
|
|
|
//this.clusters = clusters;
|
|
//this.clusters = clusters;
|
|
|
this._clusteringInProcess = false;
|
|
this._clusteringInProcess = false;
|
|
@@ -302,8 +274,6 @@ export class AdjusterService {
|
|
|
err: error,
|
|
err: error,
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
- //};
|
|
|
|
|
- //this.hsUtilsService.debounce(f, 300, false, this)();
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
init(): void {
|
|
init(): void {
|
|
@@ -315,7 +285,7 @@ export class AdjusterService {
|
|
|
this.factors = data.map((dataset) => {
|
|
this.factors = data.map((dataset) => {
|
|
|
return {
|
|
return {
|
|
|
name: dataset.Factor,
|
|
name: dataset.Factor,
|
|
|
- weight: dataset.Factor == 'Udržitelná města a obce' ? 1 : 0,
|
|
|
|
|
|
|
+ weight: this.initialWeights[dataset.Factor] ?? 1,
|
|
|
datasets: [],
|
|
datasets: [],
|
|
|
};
|
|
};
|
|
|
});
|
|
});
|