2021-03-24 01:25:57 +01:00
import SimpleMetaTagger from "./SimpleMetaTagger" ;
2021-03-25 15:19:44 +01:00
import { ExtraFunction } from "./ExtraFunction" ;
2021-04-22 13:30:00 +02:00
import { Relation } from "./Osm/ExtractRelations" ;
2021-06-21 03:25:54 +02:00
import { UIEventSource } from "./UIEventSource" ;
2021-08-07 23:11:34 +02:00
import LayerConfig from "../Models/ThemeConfig/LayerConfig" ;
2021-04-22 13:30:00 +02:00
interface Params {
featuresPerLayer : Map < string , any [ ] > ,
memberships : Map < string , { role : string , relation : Relation } [ ] >
}
2020-10-19 12:08:42 +02:00
/ * *
* Metatagging adds various tags to the elements , e . g . lat , lon , surface area , . . .
*
* All metatags start with an underscore
* /
export default class MetaTagging {
2021-09-09 00:05:51 +02:00
private static errorPrintCount = 0 ;
private static readonly stopErrorOutputAt = 10 ;
2021-03-24 01:25:57 +01:00
/ * *
* An actor which adds metatags on every feature in the given object
* The features are a list of geojson - features , with a "properties" - field and geometry
* /
2021-04-22 13:30:00 +02:00
static addMetatags ( features : { feature : any ; freshness : Date } [ ] ,
2021-06-21 03:25:54 +02:00
allKnownFeatures : UIEventSource < { feature : any ; freshness : Date } [ ] > ,
2021-05-13 12:40:19 +02:00
relations : Map < string , { role : string , relation : Relation } [ ] > ,
2021-04-25 13:25:03 +02:00
layers : LayerConfig [ ] ,
includeDates = true ) {
2021-07-26 20:21:05 +02:00
if ( features === undefined || features . length === 0 ) {
2021-06-21 03:13:49 +02:00
return ;
}
2020-10-30 00:56:46 +01:00
2021-03-24 01:25:57 +01:00
for ( const metatag of SimpleMetaTagger . metatags ) {
2021-05-13 12:40:19 +02:00
if ( metatag . includesDates && ! includeDates ) {
2021-04-25 13:25:03 +02:00
// We do not add dated entries
continue ;
}
2021-03-24 01:25:57 +01:00
try {
metatag . addMetaTags ( features ) ;
} catch ( e ) {
console . error ( "Could not calculate metatag for " , metatag . keys . join ( "," ) , ":" , e )
2020-10-30 00:56:46 +01:00
}
2021-03-24 01:25:57 +01:00
}
2020-10-30 00:56:46 +01:00
2021-03-24 01:25:57 +01:00
// The functions - per layer - which add the new keys
2021-04-22 13:30:00 +02:00
const layerFuncs = new Map < string , ( ( params : Params , feature : any ) = > void ) > ( ) ;
2021-03-24 01:25:57 +01:00
for ( const layer of layers ) {
layerFuncs . set ( layer . id , this . createRetaggingFunc ( layer ) ) ;
}
2020-10-30 00:56:46 +01:00
2021-06-30 18:47:48 +02:00
allKnownFeatures . addCallbackAndRunD ( newFeatures = > {
2021-03-26 03:24:58 +01:00
2021-06-20 03:09:26 +02:00
const featuresPerLayer = new Map < string , any [ ] > ( ) ;
2021-06-21 03:13:49 +02:00
const allFeatures = Array . from ( new Set ( features . concat ( newFeatures ) ) )
for ( const feature of allFeatures ) {
2021-06-20 03:09:26 +02:00
const key = feature . feature . _matching_layer_id ;
if ( ! featuresPerLayer . has ( key ) ) {
featuresPerLayer . set ( key , [ ] )
}
featuresPerLayer . get ( key ) . push ( feature . feature )
2021-05-10 23:51:03 +02:00
}
2021-05-13 12:40:19 +02:00
2021-06-20 03:09:26 +02:00
for ( const feature of features ) {
// @ts-ignore
const key = feature . feature . _matching_layer_id ;
const f = layerFuncs . get ( key ) ;
if ( f === undefined ) {
continue ;
}
2020-10-30 00:56:46 +01:00
2021-06-20 03:09:26 +02:00
try {
f ( { featuresPerLayer : featuresPerLayer , memberships : relations } , feature . feature )
} catch ( e ) {
console . error ( e )
}
}
2021-07-26 20:21:05 +02:00
2021-06-20 03:09:26 +02:00
} )
2021-07-26 20:21:05 +02:00
2021-05-20 12:27:33 +02:00
2021-03-24 01:25:57 +01:00
}
2020-10-30 00:56:46 +01:00
2021-04-22 13:30:00 +02:00
private static createRetaggingFunc ( layer : LayerConfig ) :
( ( params : Params , feature : any ) = > void ) {
2021-03-24 01:25:57 +01:00
const calculatedTags : [ string , string ] [ ] = layer . calculatedTags ;
if ( calculatedTags === undefined ) {
return undefined ;
2020-10-30 00:56:46 +01:00
}
2021-03-22 02:45:22 +01:00
2021-04-22 13:30:00 +02:00
const functions : ( ( params : Params , feature : any ) = > void ) [ ] = [ ] ;
2021-03-24 01:25:57 +01:00
for ( const entry of calculatedTags ) {
const key = entry [ 0 ]
const code = entry [ 1 ] ;
if ( code === undefined ) {
continue ;
2021-03-22 01:04:25 +01:00
}
2021-03-24 01:25:57 +01:00
const func = new Function ( "feat" , "return " + code + ";" ) ;
2021-03-22 01:04:25 +01:00
2021-05-13 12:40:19 +02:00
try {
const f = ( featuresPerLayer , feature : any ) = > {
try {
2021-05-14 02:25:30 +02:00
let result = func ( feature ) ;
2021-09-09 00:05:51 +02:00
if ( result instanceof UIEventSource ) {
2021-07-26 20:21:05 +02:00
result . addCallbackAndRunD ( d = > {
if ( typeof d !== "string" ) {
// Make sure it is a string!
d = JSON . stringify ( d ) ;
}
feature . properties [ key ] = d ;
} )
result = result . data
}
2021-09-09 00:05:51 +02:00
2021-05-20 12:27:33 +02:00
if ( result === undefined || result === "" ) {
2021-05-14 02:25:30 +02:00
return ;
}
2021-05-20 12:27:33 +02:00
if ( typeof result !== "string" ) {
2021-05-14 02:25:30 +02:00
// Make sure it is a string!
2021-06-20 03:09:26 +02:00
result = JSON . stringify ( result ) ;
2021-05-14 02:25:30 +02:00
}
2021-05-20 12:27:33 +02:00
feature . properties [ key ] = result ;
2021-05-13 12:40:19 +02:00
} catch ( e ) {
2021-07-26 20:21:05 +02:00
if ( MetaTagging . errorPrintCount < MetaTagging . stopErrorOutputAt ) {
2021-06-24 02:31:02 +02:00
console . warn ( "Could not calculate a calculated tag defined by " + code + " due to " + e + ". This is code defined in the theme. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features" , e )
2021-07-26 20:21:05 +02:00
MetaTagging . errorPrintCount ++ ;
if ( MetaTagging . errorPrintCount == MetaTagging . stopErrorOutputAt ) {
console . error ( "Got " , MetaTagging . stopErrorOutputAt , " errors calculating this metatagging - stopping output now" )
2021-06-21 03:13:49 +02:00
}
}
2021-05-13 12:40:19 +02:00
}
2021-05-10 23:51:03 +02:00
}
2021-05-13 12:40:19 +02:00
functions . push ( f )
} catch ( e ) {
2021-05-10 23:51:03 +02:00
console . error ( "Could not create a dynamic function: " , e )
}
2021-02-20 03:29:55 +01:00
}
2021-04-22 13:30:00 +02:00
return ( params : Params , feature ) = > {
2021-03-24 01:25:57 +01:00
const tags = feature . properties
if ( tags === undefined ) {
return ;
2020-11-11 16:23:49 +01:00
}
2021-03-22 02:45:22 +01:00
2021-05-13 13:04:17 +02:00
const relations = params . memberships ? . get ( feature . properties . id ) ? ? [ ]
2021-04-22 13:30:00 +02:00
ExtraFunction . FullPatchFeature ( params . featuresPerLayer , relations , feature ) ;
2021-03-26 03:24:58 +01:00
try {
for ( const f of functions ) {
2021-04-22 13:30:00 +02:00
f ( params , feature ) ;
2021-03-24 01:25:57 +01:00
}
2021-03-26 03:24:58 +01:00
} catch ( e ) {
console . error ( "While calculating a tag value: " , e )
2021-03-24 01:25:57 +01:00
}
2021-03-22 01:04:25 +01:00
}
}
2021-03-25 15:19:44 +01:00
2020-10-19 12:08:42 +02:00
}