mirror of
https://forge.chapril.org/tykayn/wololo
synced 2025-06-20 01:34:42 +02:00
update propose mapping from open data for Rouen métropole trees
This commit is contained in:
parent
f309db257d
commit
d7c622bf71
6 changed files with 276 additions and 33 deletions
195
propose_mapping_from_geojson.ts
Normal file
195
propose_mapping_from_geojson.ts
Normal file
|
@ -0,0 +1,195 @@
|
|||
/**
|
||||
* propose_mapping_from_data.ts
|
||||
* Examine un jeu de données GeoJSON et propose des tags à mettre dans une config
|
||||
* comme celle dans mappings/converters/configIRVE.ts
|
||||
*
|
||||
* Exemple de lancement:
|
||||
* npx ts-node propose_mapping_from_data.ts mon_fichier.geojson
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
interface GeoJSONFeature {
|
||||
type: string;
|
||||
geometry: any;
|
||||
properties: Record<string, any>;
|
||||
}
|
||||
|
||||
interface GeoJSONData {
|
||||
type: string;
|
||||
features: GeoJSONFeature[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie les arguments de la ligne de commande
|
||||
*/
|
||||
function checkArguments(): string {
|
||||
if (process.argv.length < 3) {
|
||||
console.error("Usage: npx ts-node propose_mapping_from_data.ts <geojson_file>");
|
||||
process.exit(1);
|
||||
}
|
||||
return process.argv[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge et parse le fichier GeoJSON
|
||||
*/
|
||||
function loadGeoJSONFile(filePath: string): GeoJSONData {
|
||||
try {
|
||||
const fileContent = fs.readFileSync(filePath, 'utf8');
|
||||
const data = JSON.parse(fileContent);
|
||||
|
||||
// Vérifie que le fichier est bien un GeoJSON avec des features
|
||||
if (!data.features || !Array.isArray(data.features)) {
|
||||
console.error("Le fichier ne semble pas être un GeoJSON valide avec des features");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error(`Erreur lors du chargement du fichier: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrait toutes les propriétés uniques des features
|
||||
*/
|
||||
function extractProperties(data: GeoJSONData): Set<string> {
|
||||
const properties: Set<string> = new Set();
|
||||
|
||||
for (const feature of data.features) {
|
||||
if (feature.properties) {
|
||||
Object.keys(feature.properties).forEach(key => properties.add(key));
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compte les occurrences des différentes valeurs pour chaque propriété
|
||||
*/
|
||||
function countPropertyValues(data: GeoJSONData): Record<string, Record<string, number>> {
|
||||
const valuesCounts: Record<string, Record<string, number>> = {};
|
||||
|
||||
// Initialiser le comptage pour chaque propriété
|
||||
for (const feature of data.features) {
|
||||
if (feature.properties) {
|
||||
Object.entries(feature.properties).forEach(([key, value]) => {
|
||||
// Convertir la valeur en chaîne pour pouvoir la compter
|
||||
const stringValue = String(value);
|
||||
|
||||
// Initialiser le compteur pour cette propriété si nécessaire
|
||||
if (!valuesCounts[key]) {
|
||||
valuesCounts[key] = {};
|
||||
}
|
||||
|
||||
// Incrémenter le compteur pour cette valeur
|
||||
valuesCounts[key][stringValue] = (valuesCounts[key][stringValue] || 0) + 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return valuesCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée les mappings suggérés pour les propriétés
|
||||
*/
|
||||
function createMappingSuggestions(properties: Set<string>): Record<string, string> {
|
||||
const defaults: Record<string, string> = {};
|
||||
|
||||
properties.forEach(prop => {
|
||||
// Cherche les propriétés liées au web ou au téléphone
|
||||
if (prop.toLowerCase().includes('web') || prop.toLowerCase().includes('site') || prop.toLowerCase().includes('url')) {
|
||||
defaults[prop] = 'contact:website';
|
||||
}
|
||||
else if (prop.toLowerCase().includes('telephone') || prop.toLowerCase().includes('téléphone') || prop.toLowerCase().includes('phone')) {
|
||||
defaults[prop] = 'contact:phone';
|
||||
}
|
||||
else if (prop.toLowerCase().includes('nom') || prop.toLowerCase().includes('name')) {
|
||||
defaults[prop] = 'name';
|
||||
}
|
||||
else if (prop.toLowerCase().includes('adresse') || prop.toLowerCase().includes('address')) {
|
||||
defaults[prop] = 'addr:full';
|
||||
}
|
||||
else if (prop.toLowerCase().includes('id') || prop.toLowerCase().includes('ref')) {
|
||||
defaults[prop] = 'ref';
|
||||
}
|
||||
else {
|
||||
defaults[prop] = '';
|
||||
}
|
||||
});
|
||||
|
||||
return defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Affiche les statistiques des valeurs pour chaque propriété
|
||||
*/
|
||||
function displayPropertyValueStats(valuesCounts: Record<string, Record<string, number>>): void {
|
||||
console.log('\n=== Statistiques des valeurs par propriété ===');
|
||||
|
||||
Object.entries(valuesCounts).forEach(([prop, values]) => {
|
||||
const totalValues = Object.values(values).reduce((sum, count) => sum + count, 0);
|
||||
const uniqueValues = Object.keys(values).length;
|
||||
|
||||
console.log(`\nPropriété: ${prop}`);
|
||||
console.log(`- Total d'occurrences: ${totalValues}`);
|
||||
console.log(`- Valeurs uniques: ${uniqueValues}`);
|
||||
|
||||
// Si trop de valeurs uniques, n'afficher que les plus fréquentes
|
||||
if (uniqueValues > 10) {
|
||||
console.log('- Top 5 des valeurs les plus fréquentes:');
|
||||
const sortedValues = Object.entries(values)
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.slice(0, 5);
|
||||
|
||||
sortedValues.forEach(([value, count]) => {
|
||||
// Tronquer les valeurs très longues
|
||||
const displayValue = value.length > 50 ? value.substring(0, 47) + '...' : value;
|
||||
console.log(` "${displayValue}": ${count} occurrences (${Math.round(count / totalValues * 100)}%)`);
|
||||
});
|
||||
console.log(` ... et ${uniqueValues - 5} autres valeurs`);
|
||||
} else {
|
||||
console.log('- Toutes les valeurs:');
|
||||
Object.entries(values)
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.forEach(([value, count]) => {
|
||||
// Tronquer les valeurs très longues
|
||||
const displayValue = value.length > 50 ? value.substring(0, 47) + '...' : value;
|
||||
console.log(` "${displayValue}": ${count} occurrences (${Math.round(count / totalValues * 100)}%)`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n=== Fin des statistiques ===\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction principale
|
||||
*/
|
||||
function main(): void {
|
||||
const filePath = checkArguments();
|
||||
const data = loadGeoJSONFile(filePath);
|
||||
|
||||
console.log(`\nFichier GeoJSON chargé: ${filePath}`);
|
||||
console.log(`Nombre de features: ${data.features.length}`);
|
||||
|
||||
const properties = extractProperties(data);
|
||||
|
||||
const valuesCounts = countPropertyValues(data);
|
||||
displayPropertyValueStats(valuesCounts);
|
||||
|
||||
const mappingSuggestions = createMappingSuggestions(properties);
|
||||
|
||||
console.log('Suggestions de mapping OSM:');
|
||||
console.log(JSON.stringify(mappingSuggestions, null, 2));
|
||||
|
||||
console.log(`Nombre de propriétés uniques: ${properties.size}`);
|
||||
}
|
||||
|
||||
// Exécution du programme
|
||||
main();
|
Loading…
Add table
Add a link
Reference in a new issue