mirror of
https://forge.chapril.org/tykayn/osm-commerces
synced 2025-10-09 17:02:46 +02:00
infos de fraicheur de données
This commit is contained in:
parent
4eb95d5b95
commit
b41bbc9696
6 changed files with 573 additions and 0 deletions
260
templates/admin/fraicheur_histogramme.html.twig
Normal file
260
templates/admin/fraicheur_histogramme.html.twig
Normal file
|
@ -0,0 +1,260 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Histogramme de fraîcheur OSM{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container mt-4">
|
||||
<h1>Histogramme de fraîcheur des données OSM</h1>
|
||||
<h2>Par année</h2>
|
||||
<canvas id="fraicheurHistogrammeAnnee" width="800" height="400" style="max-width:100%; margin: 20px 0;"></canvas>
|
||||
<h2>Par trimestre</h2>
|
||||
<canvas id="fraicheurHistogrammeTrimestre" width="800" height="400" style="max-width:100%; margin: 20px 0;"></canvas>
|
||||
|
||||
<h2>Par mois</h2>
|
||||
<canvas id="fraicheurHistogramme" width="800" height="400" style="max-width:100%; margin: 20px 0;"></canvas>
|
||||
|
||||
<h2>Distribution des villes selon le nombre d'habitants par lieu (par pas de 10)</h2>
|
||||
<canvas id="distributionHabitantsParLieu" width="800" height="400" style="max-width:100%; margin: 20px 0;"></canvas>
|
||||
<div id="fraicheurMeta" class="mb-3"></div>
|
||||
<a href="{{ path('admin_fraicheur_calculate') }}" class="btn btn-primary">Régénérer les statistiques</a>
|
||||
<a href="{{ path('admin_fraicheur_download') }}" class="btn btn-secondary">Télécharger le JSON des lieux</a>
|
||||
<a href="{{ path('admin_distribution_villes_lieux_par_habitant_download') }}" class="btn btn-secondary">Télécharger le JSON villes/lieux/habitant</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
fetch('/admin/fraicheur/download')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if(data.error){
|
||||
document.getElementById('fraicheurMeta').innerHTML = '<div class="alert alert-danger">'+data.error+'</div>';
|
||||
return;
|
||||
}
|
||||
const ctx = document.getElementById('fraicheurHistogramme').getContext('2d');
|
||||
const labels = Object.keys(data.histogram);
|
||||
const values = Object.values(data.histogram);
|
||||
document.getElementById('fraicheurMeta').innerHTML =
|
||||
'<b>Date de génération :</b> ' + data.generated_at + '<br>' +
|
||||
'<b>Total lieux :</b> ' + data.total;
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: 'Nombre de lieux modifiés ce mois',
|
||||
data: values,
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.7)',
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
title: { display: true, text: 'Fraîcheur des données OSM (par mois)' }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: true, title: { display: true, text: 'Nombre de lieux' } },
|
||||
x: { title: { display: true, text: 'Mois' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Agrégation par trimestre
|
||||
const trimestreAgg = {};
|
||||
for(const key in data.histogram){
|
||||
// key = YYYY-MM
|
||||
const [year, month] = key.split('-');
|
||||
const m = parseInt(month, 10);
|
||||
let trimestre = 1;
|
||||
if(m >= 4 && m <= 6) trimestre = 2;
|
||||
else if(m >= 7 && m <= 9) trimestre = 3;
|
||||
else if(m >= 10 && m <= 12) trimestre = 4;
|
||||
const trimestreKey = `${year}-T${trimestre}`;
|
||||
if(!trimestreAgg[trimestreKey]) trimestreAgg[trimestreKey] = 0;
|
||||
trimestreAgg[trimestreKey] += data.histogram[key];
|
||||
}
|
||||
const trimestreLabels = Object.keys(trimestreAgg).sort();
|
||||
const trimestreValues = trimestreLabels.map(k => trimestreAgg[k]);
|
||||
const ctxTrim = document.getElementById('fraicheurHistogrammeTrimestre').getContext('2d');
|
||||
new Chart(ctxTrim, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: trimestreLabels,
|
||||
datasets: [{
|
||||
label: 'Nombre de lieux modifiés ce trimestre',
|
||||
data: trimestreValues,
|
||||
backgroundColor: 'rgba(255, 159, 64, 0.7)',
|
||||
borderColor: 'rgba(255, 159, 64, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
title: { display: true, text: 'Fraîcheur des données OSM (par trimestre)' }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: true, title: { display: true, text: 'Nombre de lieux' } },
|
||||
x: { title: { display: true, text: 'Trimestre' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Agrégation par année
|
||||
const anneeAgg = {};
|
||||
for(const key in data.histogram){
|
||||
// key = YYYY-MM
|
||||
const [year] = key.split('-');
|
||||
if(!anneeAgg[year]) anneeAgg[year] = 0;
|
||||
anneeAgg[year] += data.histogram[key];
|
||||
}
|
||||
const anneeLabels = Object.keys(anneeAgg).sort();
|
||||
const anneeValues = anneeLabels.map(k => anneeAgg[k]);
|
||||
const ctxAnnee = document.getElementById('fraicheurHistogrammeAnnee').getContext('2d');
|
||||
new Chart(ctxAnnee, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: anneeLabels,
|
||||
datasets: [{
|
||||
label: 'Nombre de lieux modifiés cette année',
|
||||
data: anneeValues,
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.7)',
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
title: { display: true, text: 'Fraîcheur des données OSM (par année)' }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: true, title: { display: true, text: 'Nombre de lieux' } },
|
||||
x: { title: { display: true, text: 'Année' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Histogramme distribution villes/lieux/habitant
|
||||
fetch('/admin/distribution_villes_lieux_par_habitant_download')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if(data.error){
|
||||
document.getElementById('distributionVillesLieuxParHabitant').insertAdjacentHTML('afterend', '<div class="alert alert-danger">Erreur de chargement des données : '+data.error+'</div>');
|
||||
return;
|
||||
}
|
||||
// Histogramme habitants par lieu (pas de 10)
|
||||
fetch('/admin/distribution_villes_lieux_par_habitant_villes')
|
||||
.then(r2 => r2.json())
|
||||
.then(villesData => {
|
||||
// Histogramme habitants par lieu
|
||||
if(!data.histogram_10){
|
||||
document.getElementById('distributionHabitantsParLieu').insertAdjacentHTML('afterend', '<div class="alert alert-danger">Erreur : données histogram_10 absentes. Cliquez sur "Régénérer les statistiques".</div>');
|
||||
return;
|
||||
}
|
||||
const ctxHPL = document.getElementById('distributionHabitantsParLieu').getContext('2d');
|
||||
const labelsHPL = Object.keys(data.histogram_10);
|
||||
const valuesHPL = Object.values(data.histogram_10);
|
||||
const villesByBin10 = villesData.villes_by_bin_10 || {};
|
||||
console.log('HPL', labelsHPL, villesByBin10);
|
||||
new Chart(ctxHPL, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labelsHPL,
|
||||
datasets: [{
|
||||
label: "Nombre de villes",
|
||||
data: valuesHPL,
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.7)',
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
title: { display: true, text: "Distribution des villes par habitants/lieu (par pas de 10)" },
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
afterBody: function(context) {
|
||||
const bin = context[0].label;
|
||||
const villes = villesByBin10[bin] || [];
|
||||
if(villes.length > 0){
|
||||
return ['Villes :'].concat(villes.map(v => '• ' + v));
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: true, title: { display: true, text: 'Nombre de villes' } },
|
||||
x: { title: { display: true, text: 'Habitants par lieu (arrondi à 10)' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
// Histogramme lieux/habitant (pas de 0.01)
|
||||
if(!data.histogram_001){
|
||||
document.getElementById('distributionVillesLieuxParHabitant').insertAdjacentHTML('afterend', '<div class="alert alert-danger">Erreur : données histogram_001 absentes. Cliquez sur "Régénérer les statistiques".</div>');
|
||||
return;
|
||||
}
|
||||
const ctx = document.getElementById('distributionVillesLieuxParHabitant').getContext('2d');
|
||||
const labels = Object.keys(data.histogram_001);
|
||||
const values = Object.values(data.histogram_001);
|
||||
const villesByBin001 = villesData.villes_by_bin_001 || {};
|
||||
console.log('LPH', labels, villesByBin001);
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: "Nombre de villes",
|
||||
data: values,
|
||||
backgroundColor: 'rgba(153, 102, 255, 0.7)',
|
||||
borderColor: 'rgba(153, 102, 255, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
title: { display: true, text: "Distribution des villes par lieux/habitant (par pas de 0,01)" },
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
afterBody: function(context) {
|
||||
const bin = context[0].label;
|
||||
const villes = villesByBin001[bin] || [];
|
||||
if(villes.length > 0){
|
||||
return ['Villes :'].concat(villes.map(v => '• ' + v));
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: true, title: { display: true, text: 'Nombre de villes' } },
|
||||
x: { title: { display: true, text: 'Lieux par habitant (arrondi à 0,01)' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -513,6 +513,7 @@
|
|||
x: { title: { display: true, text: 'Trimestre' } }
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
} else if (modifCanvas) {
|
||||
modifCanvas.parentNode.innerHTML = '<div class="alert alert-info">Aucune donnée de modification disponible pour cette ville.</div>';
|
||||
|
|
|
@ -100,6 +100,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="mb-2">
|
||||
<a href="https://osm-commerces.cipherbliss.com/api/v1/stats_geojson" target="_blank">Documentation de l'API (GeoJSON)</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
<i class="bi bi-clock-fill"></i>
|
||||
{{ 'display.latest_changes'|trans }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('admin_fraicheur_histogramme') }}">
|
||||
<i class="bi bi-clock-history"></i>
|
||||
Fraîcheur de la donnée
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue