import custom_utils from './utils' import MappingConfigType from "./mapping-config.type"; const {debugLog} = custom_utils let listOfBooleanKeys = [ "prise_type_ef", "prise_type_2", "prise_type_combo_ccs", "prise_type_chademo", "gratuit", "paiement_acte", "paiement_cb", "cable_t2_attache" ] export default class { mapping_config: any = {} private jardinage = true; public stats: any; constructor(mappingConfig: MappingConfigType) { this.setConfig(mappingConfig) this.stats = { phones_updated: 0, phones_updated_list: [], phones_not_updated: 0 } } setConfig(mappingConfig: MappingConfigType) { debugLog('load config', mappingConfig.config_name) this.mapping_config = mappingConfig } getConfig() { return this.mapping_config } mapFeaturePoint(featurePointGeoJson: any) { let geoJSONConvertedPoint: any = {} geoJSONConvertedPoint.properties = {...this.mapping_config.default_properties_of_point} geoJSONConvertedPoint.type = featurePointGeoJson.type geoJSONConvertedPoint.geometry = featurePointGeoJson.geometry // let props = featurePointGeoJson.properties // props.forEach((key, value) => { // // }) return geoJSONConvertedPoint } /** * TODO convert to mapping config property to transform_truthy * @param pointKeyName * @returns {boolean} */ isBooleanKey(pointKeyName: string): boolean { return listOfBooleanKeys.indexOf(pointKeyName) !== -1 } truthyValues = [true, 'true', 'True', 'TRUE', '1', 'yes', 1] falsyValues = [false, 'false', 'False', 'FALSE', '0', 'no', 0] /** * reduce number of features * @param offsetCount * @param listOfFeatures */ filterFeaturesByOffset(offsetCount: number, listOfFeatures: any): Array { let filteredList = listOfFeatures // TODO return filteredList } // filterFeaturesByPropertyRegex(bboxConfig:any, listOfFeatures:any) { // debugLog('bboxConfig', bboxConfig) // let filteredList = listOfFeatures // // TODO // return filteredList // } filterFeaturesByPropertyRegex(propertyName: string, criteriaRegex: any, listOfFeatures: any) { let filteredList = listOfFeatures.filter((feature: any) => { return criteriaRegex.test(feature?.properties[propertyName]) }) return filteredList } /** * retuns the converted element from mapping config if present, null otherwise */ mapElementFromConf(featurePoint: any): any { debugLog('mapElementFromConf: mapElementFromConf', featurePoint) if (!this.mapping_config) { throw new Error('no config was loaded in the mapping engine. use setConfig(my_mapping_config) on this instance of mapping engine before using this. Your config should be typed to MappingConfigType Type.') } debugLog('mapElementFromConf: config_name', this.mapping_config.config_name) let mappingKeys = Object.keys(this.mapping_config.tags) let featurePointPropertiesKeys = Object.keys(featurePoint.properties) debugLog('mapElementFromConf: ============= keys mappingKeys:', this.mapping_config.tags.length, mappingKeys.length) debugLog('mapElementFromConf: ============= keys featurePointPropertiesKeys :', featurePoint.properties.length, featurePointPropertiesKeys.length) let newProperties = {...this.mapping_config.default_properties_of_point} // reinit properties of current point let basePoint = Object.create(featurePoint) basePoint.type = featurePoint.type basePoint.geometry = featurePoint.geometry basePoint.properties = {...this.mapping_config.default_properties_of_point} // apply new properties if found in mapping config featurePointPropertiesKeys.forEach(pointKeyName => { debugLog('mapElementFromConf: convert', pointKeyName) debugLog('mapElementFromConf: mapping keys:', mappingKeys) this.convertProperty(pointKeyName, mappingKeys, featurePoint, newProperties) }) basePoint.properties = newProperties // debugLog('mapElementFromConf: basePoint', basePoint) return basePoint } /** * convertit une propriété en une autre selon la config de mapping * @param pointKeyName * @param mappingKeys * @param featurePoint * @param newProperties */ convertProperty(pointKeyName: string, mappingKeys: any, featurePoint: any, newProperties: any) { let originalValue = featurePoint.properties[pointKeyName] let mappingValueObject: any = ''; if (mappingKeys.indexOf(pointKeyName) !== -1) { mappingValueObject = this.mapping_config.tags[pointKeyName] debugLog('convertProperty: mappingValueObject ', mappingValueObject) } debugLog(' ------ convertProperty: pointKeyName', pointKeyName) // debugLog('convertProperty: mappingKeys', mappingKeys) if (this.jardinage) { debugLog(' ------ on fait du jardinage') debugLog(' ------ mode mise en qualité activé') debugLog(' ------ les données en entrée sont des infos geojson extraites depuis overpass turbo.') debugLog(' ------ les clés des objets sont donc déjà dans le format de tag OSM,' + 'ne pas les convertir pour les mettre en qualité selon le modèle de mapping.') } if (this.mapping_config.add_not_mapped_tags_too && (mappingKeys.indexOf(pointKeyName) === -1)) { /** * add all unmapped tags is enabled */ debugLog(' ------ add all unmapped tags is enabled') newProperties[pointKeyName] = originalValue; } else { /** * only use existing keys */ if (mappingKeys.indexOf(pointKeyName) !== -1) { let valueConvertedFromMapping = featurePoint.properties[pointKeyName] let keyConvertedFromMapping = mappingKeys[mappingKeys.indexOf(pointKeyName)] let mappingConfigOfTag = this.mapping_config.tags[pointKeyName] debugLog('========== mappingConfigOfTag', mappingConfigOfTag) debugLog('convertProperty: found element', pointKeyName, '=>', keyConvertedFromMapping, 'value : ', valueConvertedFromMapping) let convertedValue = originalValue let typeOfConfigForKey = typeof mappingConfigOfTag let isStringValue = typeOfConfigForKey === 'string' let isConfigMappingObject = typeOfConfigForKey === 'object' debugLog('convertProperty: - typeofValue', typeOfConfigForKey) debugLog('convertProperty: - pointKeyName', pointKeyName) debugLog('convertProperty: - valueConvertedFromMapping', valueConvertedFromMapping) debugLog('typeof valueConvertedFromMapping === \'string\'', typeOfConfigForKey) debugLog('convertProperty: isStringValue?', valueConvertedFromMapping, isStringValue) debugLog('convertProperty: isStringValue?', valueConvertedFromMapping, isStringValue) debugLog('mappingConfigOfTag', mappingConfigOfTag) debugLog('typeOfConfigForKey', typeOfConfigForKey) /** * conversion si la clé à une config d'une string, on ne change que la clé, pas la valeur */ if (isStringValue) { debugLog('convertProperty: -- string value') debugLog('convertProperty: -- string value') debugLog('convertProperty: -- simple conversion : ', pointKeyName, '=> ', mappingConfigOfTag, '_', originalValue, '=>', valueConvertedFromMapping) debugLog('convertProperty: -- convertedValue', convertedValue) convertedValue = valueConvertedFromMapping if (convertedValue) { newProperties[mappingConfigOfTag] = convertedValue } } else { debugLog('convertProperty: no string value') } if (isConfigMappingObject) { let configObject = mappingConfigOfTag debugLog('convertProperty: is config object', configObject) let newKey: any = '' + pointKeyName let remove_original_key = false; if (configObject.key_converted) { newKey = configObject.key_converted } if (configObject.truthy_value) { // convertir la valeur, si elle est truthy, la transformer en ce que donne la propriété truthy_value // exemple: le jeu de données dit que la colonne cable_t2_attache vaut "True", mais on veut le convertir en "1". // on met donc truthy_value: '1' debugLog('truthy_value', originalValue) if (this.truthyValues.indexOf(originalValue) !== -1) { convertedValue = configObject.truthy_value } } if (configObject.falsy_value) { if (this.falsyValues.indexOf(originalValue) !== -1) { convertedValue = configObject.falsy_value } } /** * conversion booléenne */ if (mappingValueObject.convert_to_boolean_value) { debugLog('convertProperty: is boolean_value_conversion') debugLog('convertProperty: ==========> original value', originalValue) if (this.truthyValues.indexOf(originalValue) !== -1) { convertedValue = 'yes' } else { debugLog('convertProperty: ==========> !!! NOT in truthy values', originalValue) } if (this.falsyValues.indexOf(originalValue) !== -1) { convertedValue = 'no' } else { debugLog('convertProperty: ==========> !!! NOT in falsy values', originalValue) } } else { debugLog('convertProperty: is NOT having boolean_value_conversion', mappingValueObject) } if (configObject.convert_to_phone) { /** * nettoyer les numéros de téléphone en ne gardant que les nombres et le préfixe de pays */ debugLog('originalValue', originalValue.substring(1)) let original_without_spaces = originalValue.replace(/ /g, '') let cleaned_value = `${original_without_spaces}` cleaned_value = cleaned_value .trim() .replace('Stations-e', '') .replace(/[a-zA-Zéèà]/ig, '') .replace(/[\(\)\.\- ]/g, '') let original_array = originalValue.split('') let add_prefix = false; if ( /^\d/.test(cleaned_value) && !/^\+33 /.test(original_without_spaces) ) { add_prefix = true } cleaned_value = cleaned_value.replace('+33', '') if (/^0/.test(cleaned_value)) { cleaned_value = cleaned_value.substring(1) } let array_of_numbers = cleaned_value .split('') let ii = 0; if (cleaned_value.length == 4) { ii = 1 } convertedValue = '' array_of_numbers.forEach((num: string) => { if (ii % 2) { convertedValue += ' '; } convertedValue += num; ii++; }) convertedValue = convertedValue.replace(' ', ' ').trim(); console.log('convertedValue', convertedValue) if ( /^\d/.test(convertedValue) && !/^\+33 /.test(convertedValue) ) { add_prefix = true } if (add_prefix) { convertedValue = `+33 ` + convertedValue } debugLog('phone: ', originalValue, '=>', convertedValue) if (originalValue !== convertedValue) { this.stats.phones_updated++ this.stats.phones_updated_list.push(convertedValue) } else { this.stats.phones_not_updated++ } } if (configObject.remove_original_key) { remove_original_key = true } if (configObject.ignore_if_falsy && this.falsyValues.indexOf(originalValue) !== -1) { remove_original_key = true } if (configObject.ignore_if_truthy && this.truthyValues.indexOf(originalValue) !== -1) { remove_original_key = true } /** * config pour une clé * nous pouvons renseigner une string ou un objet décrivant les transformations à réaliser */ if (!remove_original_key && configObject.conditional_values) { debugLog('convertProperty: conditional_values__________', configObject.conditional_values) let keysConditionnalValues: any = Object.keys(configObject.conditional_values) let isFoundValue = keysConditionnalValues.indexOf(originalValue) debugLog('isFoundValue', isFoundValue, originalValue) debugLog('keysConditionnalValues', keysConditionnalValues) if (isFoundValue > -1) { let conditionnalConfig: any = configObject.conditional_values[keysConditionnalValues[isFoundValue]] /** ---------------------- * gestion des valeurs conditionnelles * ---------------------- */ debugLog('conditionnalConfig', conditionnalConfig) if (conditionnalConfig.ignore_this_data) { debugLog(`on ignore cette clé car sa valeur "${originalValue}" est à exclure: `, pointKeyName, '=>', newKey) remove_original_key = true; } if (conditionnalConfig.tags_to_add) { // on peut définir un ensemble de tags à rajouter let tagKeys = Object.keys(conditionnalConfig.tags_to_add) debugLog('conditionnalConfig.tags_to_add', conditionnalConfig.tags_to_add) conditionnalConfig.tags_to_add.forEach((object: any, pair: any) => { debugLog('object', object) debugLog('pair', pair) let key: any = Object.keys(object) key = key[0] let value = object[key] debugLog('key', key) debugLog('value', value) newProperties[key] = value }) } if (conditionnalConfig.truthy_value) { // convertir la valeur, si elle est truthy, la transformer en ce que donne la propriété truthy_value // exemple: le jeu de données dit que la colonne cable_t2_attache vaut "True", mais on veut le convertir en "1". // on met donc truthy_value: '1' if (this.truthyValues.indexOf(originalValue) !== -1) { convertedValue = conditionnalConfig.truthy_value } } if (conditionnalConfig.falsy_value) { if (this.falsyValues.indexOf(originalValue) !== -1) { convertedValue = conditionnalConfig.falsy_value } } if (conditionnalConfig.transform_function) { // une transformation de la valeur // apply transformation to value convertedValue = conditionnalConfig.transform_function(originalValue) } // use the value converted else if (conditionnalConfig.value_converted) { convertedValue = conditionnalConfig.value_converted } } } debugLog('convertProperty: convertedValue ==========> {', newKey, ':', convertedValue, '}') debugLog(' =============== remove_original_key', newKey, remove_original_key) if (!remove_original_key && newKey && convertedValue && !configObject.ignore_this_data) { debugLog('convertProperty: added', newKey, convertedValue) newProperties[newKey] = (`${convertedValue}`).trim() } } } else { debugLog('!!!!!! property not found in mappingKeys: ', pointKeyName) } } return newProperties; } }