mirror of
https://forge.chapril.org/tykayn/osm-commerces
synced 2025-10-04 17:04:53 +02:00
up score complétion normalisé dans le podium
This commit is contained in:
parent
c3a9bc52b2
commit
59398d14ba
8 changed files with 116 additions and 36 deletions
|
@ -37,7 +37,8 @@ import {
|
|||
updateMapHeightForLargeScreens
|
||||
} from './utils.js';
|
||||
// import Tablesort from 'tablesort';
|
||||
// import TableSort from 'table-sort-js/table-sort.js';
|
||||
import TableSort from 'table-sort-js/table-sort.js';
|
||||
console.log('TableSort', TableSort)
|
||||
|
||||
// Charger table-sortable (version non minifiée locale)
|
||||
// import '../assets/js/table-sortable.js';
|
||||
|
@ -61,7 +62,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
|
||||
if(updateMapHeightForLargeScreens){
|
||||
|
||||
updateMapHeightForLargeScreens();
|
||||
|
||||
window.addEventListener('resize', updateMapHeightForLargeScreens);
|
||||
}
|
||||
|
||||
|
@ -195,13 +196,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
});
|
||||
}
|
||||
|
||||
enableLabourageForm();
|
||||
if(enableLabourageForm){
|
||||
|
||||
enableLabourageForm();
|
||||
}
|
||||
adjustListGroupFontSize('.list-group-item');
|
||||
|
||||
// Activer le tri naturel sur tous les tableaux avec la classe table-sort
|
||||
// document.querySelectorAll('table.table-sort').forEach(table => {
|
||||
// new TableSort(table);
|
||||
// });
|
||||
if(TableSort){
|
||||
|
||||
document.querySelectorAll('table.table-sort')?.forEach(table => {
|
||||
new TableSort(table);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialisation du tri et filtrage sur les tableaux du dashboard et de la page stats
|
||||
// if (document.querySelector('#dashboard-table')) {
|
||||
|
@ -244,4 +251,25 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Ajouter un écouteur pour l'événement 'load' de MapLibre afin d'ajuster la hauteur de la carte
|
||||
if (window.maplibregl && document.getElementById('map')) {
|
||||
// On suppose que la carte est initialisée ailleurs et accessible via window.mapInstance
|
||||
// Sinon, on peut essayer de détecter l'instance automatiquement
|
||||
let mapInstance = window.mapInstance;
|
||||
if (!mapInstance && window.maplibreMap) {
|
||||
mapInstance = window.maplibreMap;
|
||||
}
|
||||
// Si l'instance n'est pas trouvée, essayer de la récupérer via une variable globale courante
|
||||
if (!mapInstance && window.map) {
|
||||
mapInstance = window.map;
|
||||
}
|
||||
if (mapInstance && typeof mapInstance.on === 'function') {
|
||||
mapInstance.on('load', function() {
|
||||
updateMapHeightForLargeScreens();
|
||||
});
|
||||
}
|
||||
}
|
||||
//updateMapHeightForLargeScreens();
|
||||
|
||||
});
|
||||
|
|
|
@ -140,6 +140,11 @@ img {
|
|||
max-height: 400px;
|
||||
}
|
||||
|
||||
|
||||
#completionHistoryChart{
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.form-label {
|
||||
margin-bottom: 0.5rem;
|
||||
|
|
|
@ -99,8 +99,10 @@ async function searchInseeCode(query) {
|
|||
|
||||
export function updateMapHeightForLargeScreens() {
|
||||
const mapFound = document.querySelector('#map');
|
||||
const canvasFound = document.querySelector('#map canvas');
|
||||
const newHeight = window.innerHeight * 0.5 + 'px'
|
||||
if (mapFound && window.innerHeight > 800 && window.innerWidth > 800) {
|
||||
mapFound.style.height = window.innerWidth * 0.8 + 'px';
|
||||
mapFound.style.height = newHeight;
|
||||
} else {
|
||||
console.log('window.innerHeight', window.innerHeight);
|
||||
}
|
||||
|
@ -188,8 +190,12 @@ export function enableLabourageForm() {
|
|||
// Soumettre le formulaire
|
||||
form.submit();
|
||||
}
|
||||
}else{
|
||||
console.warn('pas de form pour labourage trouvé')
|
||||
}
|
||||
});
|
||||
}else{
|
||||
console.warn('pas de labourage citySearchInput citySuggestionsList trouvé', citySearchInput,citySuggestionsList )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1119,37 +1119,52 @@ public function podiumContributeursOsm(): Response
|
|||
// On suppose que le champ "osmUser" existe sur l'entité Place
|
||||
$placeRepo = $this->entityManager->getRepository(\App\Entity\Place::class);
|
||||
|
||||
// Récupérer les 10 contributeurs OSM les plus actifs (par nombre de lieux)
|
||||
// Nouvelle requête groupée pour tout calculer d'un coup
|
||||
$qb = $placeRepo->createQueryBuilder('p')
|
||||
->select('p.osm_user, COUNT(p.id) as nb')
|
||||
->select(
|
||||
'p.osm_user',
|
||||
'COUNT(p.id) as nb',
|
||||
'AVG((CASE WHEN p.has_opening_hours = true THEN 1 ELSE 0 END) +'
|
||||
. ' (CASE WHEN p.has_address = true THEN 1 ELSE 0 END) +'
|
||||
. ' (CASE WHEN p.has_website = true THEN 1 ELSE 0 END) +'
|
||||
. ' (CASE WHEN p.has_wheelchair = true THEN 1 ELSE 0 END) +'
|
||||
. ' (CASE WHEN p.has_note = true THEN 1 ELSE 0 END)) / 5 * 100 as completion_moyen'
|
||||
)
|
||||
->where('p.osm_user IS NOT NULL')
|
||||
->andWhere("p.osm_user != ''")
|
||||
->groupBy('p.osm_user')
|
||||
->orderBy('nb', 'DESC')
|
||||
->setMaxResults(300);
|
||||
->setMaxResults(100);
|
||||
|
||||
$podium = $qb->getQuery()->getResult();
|
||||
|
||||
// Pour chaque utilisateur, calculer le score de complétion moyen
|
||||
// Calcul du score pondéré et normalisation
|
||||
$maxPondere = 0;
|
||||
foreach ($podium as &$row) {
|
||||
$osmUser = $row['osm_user'];
|
||||
// Récupérer toutes les places de cet utilisateur
|
||||
$places = $placeRepo->createQueryBuilder('p')
|
||||
->where('p.osm_user = :osm_user')
|
||||
->setParameter('osm_user', $osmUser)
|
||||
->getQuery()->getResult();
|
||||
$total = 0;
|
||||
$sum = 0;
|
||||
foreach ($places as $place) {
|
||||
$score = $place->getCompletionPercentage();
|
||||
if ($score !== null) {
|
||||
$sum += $score;
|
||||
$total++;
|
||||
}
|
||||
$row['completion_moyen'] = $row['completion_moyen'] !== null ? round($row['completion_moyen'], 1) : null;
|
||||
$row['completion_pondere'] = ($row['completion_moyen'] !== null && $row['nb'] > 0)
|
||||
? round($row['completion_moyen'] * $row['nb'], 1)
|
||||
: null;
|
||||
if ($row['completion_pondere'] !== null && $row['completion_pondere'] > $maxPondere) {
|
||||
$maxPondere = $row['completion_pondere'];
|
||||
}
|
||||
$row['completion_moyen'] = $total > 0 ? round($sum / $total, 1) : null;
|
||||
}
|
||||
unset($row);
|
||||
// Normalisation des scores pondérés entre 0 et 100
|
||||
if ($maxPondere > 0) {
|
||||
foreach ($podium as &$row) {
|
||||
if ($row['completion_pondere'] !== null) {
|
||||
$row['completion_pondere_normalisee'] = round($row['completion_pondere'] / $maxPondere * 100, 1);
|
||||
} else {
|
||||
$row['completion_pondere_normalisee'] = null;
|
||||
}
|
||||
}
|
||||
unset($row);
|
||||
}
|
||||
// Tri décroissant sur le score normalisé
|
||||
usort($podium, function($a, $b) {
|
||||
return ($b['completion_pondere_normalisee'] ?? 0) <=> ($a['completion_pondere_normalisee'] ?? 0);
|
||||
});
|
||||
|
||||
return $this->render('admin/podium_contributeurs_osm.html.twig', [
|
||||
'podium' => $podium
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{% block body %}
|
||||
<div class="container mt-4">
|
||||
<h1>Podium des contributeurs OSM</h1>
|
||||
<p>Voici les 10 contributeurs OpenStreetMap ayant ajouté ou modifié le plus de lieux dans la base :</p>
|
||||
<p>Voici les 10 contributeurs OpenStreetMap ayant ajouté ou modifié le plus de lieux dans la base, pondérés de la complétion moyenne des lieux :</p>
|
||||
<p>Le <strong>score de complétion moyen</strong> correspond à la moyenne du taux de complétion des lieux ajoutés ou modifiés par chaque contributeur.</p>
|
||||
<table class="table table-striped table-bordered mt-4" style="max-width:800px">
|
||||
<thead class="table-dark">
|
||||
|
@ -14,6 +14,8 @@
|
|||
<th scope="col">Utilisateur OSM</th>
|
||||
<th scope="col">Nombre de lieux</th>
|
||||
<th scope="col">Score de complétion moyen</th>
|
||||
<th scope="col">Score de complétion pondéré</th>
|
||||
<th scope="col">Score pondéré normalisé (0-100)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -33,9 +35,23 @@
|
|||
<span class="text-muted">N/A</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if row.completion_pondere is not null %}
|
||||
{{ row.completion_pondere }}
|
||||
{% else %}
|
||||
<span class="text-muted">N/A</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if row.completion_pondere_normalisee is not null %}
|
||||
{{ row.completion_pondere_normalisee }}
|
||||
{% else %}
|
||||
<span class="text-muted">N/A</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="4">Aucun contributeur trouvé.</td></tr>
|
||||
<tr><td colspan="6">Aucun contributeur trouvé.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -232,7 +232,15 @@
|
|||
</div>
|
||||
</div>
|
||||
<div id="map" style="height: 400px; width: 100%; margin-bottom: 1rem;"></div>
|
||||
|
||||
<div class="row ">
|
||||
|
||||
<div class="col-md-6 col-12 ">
|
||||
<canvas id="repartition_tags" width="600" height="300" style="max-width:100%; margin: 20px 0;"></canvas>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-12 ">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<i class="bi bi-calendar-event"></i> Fréquence des mises à jour par trimestre pour {{stats.name}}
|
||||
|
@ -241,6 +249,9 @@
|
|||
<canvas id="modificationsByQuarterChart" style="min-height: 250px; width: 100%;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="attribution">
|
||||
<a href="https://www.openstreetmap.org/copyright">Données OpenStreetMap</a>
|
||||
|
@ -263,7 +274,7 @@
|
|||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" id="stats-table-search" class="form-control mb-2" placeholder="Filtrer les lieux...">
|
||||
{# <input type="text" id="stats-table-search" class="form-control mb-2" placeholder="Filtrer les lieux..."> #}
|
||||
<table id="stats-table" class="table table-bordered table-striped table-hover table-responsive table-sort">
|
||||
{% include 'admin/stats/table-head.html.twig' %}
|
||||
<tbody>
|
||||
|
|
|
@ -130,10 +130,10 @@
|
|||
{{ parent() }}
|
||||
{# <script src='{{ asset('js/utils.js') }}'></script> #}
|
||||
<script type="module">
|
||||
import { adjustListGroupFontSize } from '{{ asset('js/utils.js') }}';
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
adjustListGroupFontSize('.list-group-item');
|
||||
});
|
||||
// import { adjustListGroupFontSize } from '{{ asset('js/utils.js') }}';
|
||||
// document.addEventListener('DOMContentLoaded', function() {
|
||||
// adjustListGroupFontSize('.list-group-item');
|
||||
// });
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
@ -236,8 +236,7 @@
|
|||
});
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
enableLabourageForm();
|
||||
});
|
||||
|
||||
function displayStatsBubble(){
|
||||
const statsBubble = document.querySelector('#stats_bubble');
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<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
|
||||
Fraîcheur de ladonnée
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue