add overpass query and josm

This commit is contained in:
Tykayn 2025-06-29 17:23:54 +02:00 committed by tykayn
parent 0cdb2f9ae9
commit afc120ef2a
4 changed files with 108 additions and 2 deletions

View file

@ -85,6 +85,14 @@ class FollowUpController extends AbstractController
'label' => 'Sous-stations électriques',
'objects' => array_filter($elements, fn($el) => ($el['tags']['power'] ?? null) === 'substation')
],
'laboratory' => [
'label' => 'Laboratoires d\'analyse',
'objects' => array_filter($elements, fn($el) => ($el['tags']['healthcare'] ?? null) === 'laboratory')
],
'school' => [
'label' => 'Écoles',
'objects' => array_filter($elements, fn($el) => ($el['tags']['amenity'] ?? null) === 'school')
],
];
$now = new \DateTime();
foreach ($types as $type => $data) {
@ -130,6 +138,14 @@ class FollowUpController extends AbstractController
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['substation'] ?? null);
});
} elseif ($type === 'laboratory') {
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['website'] ?? null) || !empty($el['tags']['contact:website'] ?? null);
});
} elseif ($type === 'school') {
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['ref:UAI'] ?? null) && !empty($el['tags']['isced:level'] ?? null) && !empty($el['tags']['school:FR'] ?? null);
});
}
$completion = count($data['objects']) > 0 ? round(count($completed) / count($data['objects']) * 100) : 0;
$followupCompletion = new CityFollowUp();
@ -195,6 +211,14 @@ class FollowUpController extends AbstractController
'label' => 'Sous-stations électriques',
'objects' => array_filter($elements, fn($el) => ($el['tags']['power'] ?? null) === 'substation')
],
'laboratory' => [
'label' => 'Laboratoires d\'analyse',
'objects' => array_filter($elements, fn($el) => ($el['tags']['healthcare'] ?? null) === 'laboratory')
],
'school' => [
'label' => 'Écoles',
'objects' => array_filter($elements, fn($el) => ($el['tags']['amenity'] ?? null) === 'school')
],
];
$now = new \DateTime();
foreach ($types as $type => $data) {
@ -238,6 +262,14 @@ class FollowUpController extends AbstractController
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['substation'] ?? null);
});
} elseif ($type === 'laboratory') {
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['website'] ?? null) || !empty($el['tags']['contact:website'] ?? null);
});
} elseif ($type === 'school') {
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['ref:UAI'] ?? null) && !empty($el['tags']['isced:level'] ?? null) && !empty($el['tags']['school:FR'] ?? null);
});
}
$completion = count($data['objects']) > 0 ? round(count($completed) / count($data['objects']) * 100) : 0;
$followupCompletion = new CityFollowUp();
@ -316,6 +348,14 @@ class FollowUpController extends AbstractController
'label' => 'Sous-stations électriques',
'objects' => array_filter($elements, fn($el) => ($el['tags']['power'] ?? null) === 'substation')
],
'laboratory' => [
'label' => 'Laboratoires d\'analyse',
'objects' => array_filter($elements, fn($el) => ($el['tags']['healthcare'] ?? null) === 'laboratory')
],
'school' => [
'label' => 'Écoles',
'objects' => array_filter($elements, fn($el) => ($el['tags']['amenity'] ?? null) === 'school')
],
];
foreach ($types as $type => $data) {
// Suivi du nombre
@ -358,6 +398,14 @@ class FollowUpController extends AbstractController
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['substation'] ?? null);
});
} elseif ($type === 'laboratory') {
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['website'] ?? null) || !empty($el['tags']['contact:website'] ?? null);
});
} elseif ($type === 'school') {
$completed = array_filter($data['objects'], function($el) {
return !empty($el['tags']['ref:UAI'] ?? null) && !empty($el['tags']['isced:level'] ?? null) && !empty($el['tags']['school:FR'] ?? null);
});
}
$completion = count($data['objects']) > 0 ? round(count($completed) / count($data['objects']) * 100) : 0;
$followupCompletion = new CityFollowUp();

View file

@ -573,6 +573,8 @@ area["ref:INSEE"="$zone"]->.searchArea;
nwr["man_made"="surveillance"](area.searchArea);
nwr["amenity"="recycling"](area.searchArea);
nwr["power"="substation"](area.searchArea);
nwr["healthcare"="laboratory"](area.searchArea);
nwr["amenity"="school"](area.searchArea);
);
out body;
>;

View file

@ -19,11 +19,34 @@
'defibrillator': 'Défibrillateurs',
'camera': 'Caméras de surveillance',
'recycling': 'Points de recyclage',
'substation': 'Sous-stations électriques'
'substation': 'Sous-stations électriques',
'laboratory': "Laboratoires d'analyse",
'school': 'Écoles'
} %}
{% for type in type_labels|keys %}
<h2 id="title-{{ type }}">{{ type_labels[type] }}</h2>
<canvas id="{{ type }}Chart" width="600" height="300"></canvas>
<div class="mb-3">
{% set overpass_queries = {
'fire_hydrant': 'nwr["emergency"="fire_hydrant"](area.searchArea);',
'charging_station': 'nwr["amenity"="charging_station"](area.searchArea);',
'toilets': 'nwr["amenity"="toilets"](area.searchArea);',
'bus_stop': 'nwr["highway"="bus_stop"](area.searchArea);',
'defibrillator': 'nwr["emergency"="defibrillator"](area.searchArea);',
'camera': 'nwr["man_made"="surveillance"](area.searchArea);',
'recycling': 'nwr["amenity"="recycling"](area.searchArea);',
'substation': 'nwr["power"="substation"](area.searchArea);',
'laboratory': 'nwr["healthcare"="laboratory"](area.searchArea);',
'school': 'nwr["amenity"="school"](area.searchArea);'
} %}
{% set overpass_query = '[out:json][timeout:60];\narea["ref:INSEE"="' ~ stats.zone ~ '"]->.searchArea;\n(' ~ overpass_queries[type]|default('') ~ ');\n\n(._;>;);\n\nout meta;\n>;' %}
<a href="https://overpass-turbo.eu/?Q={{ overpass_query|url_encode }}" target="_blank" class="btn btn-sm btn-outline-primary me-2">
<i class="bi bi-geo"></i> Voir sur Overpass Turbo
</a>
<a href="http://127.0.0.1:8111/import?url=https://overpass-api.de/api/interpreter?data={{ overpass_query|url_encode }}" target="_blank" class="btn btn-sm btn-outline-success">
<i class="bi bi-box-arrow-in-up-right"></i> Ouvrir dans JOSM
</a>
</div>
{% endfor %}
<h2 class="mt-4">Données brutes</h2>
<table class="table table-bordered table-striped">
@ -66,7 +89,9 @@
defibrillator: 'Défibrillateurs',
camera: 'Caméras de surveillance',
recycling: 'Points de recyclage',
substation: 'Sous-stations électriques'
substation: 'Sous-stations électriques',
laboratory: "Laboratoires d'analyse",
school: 'Écoles'
};
function formatDelta(val) {
if (val === null) return '-';

View file

@ -329,6 +329,37 @@
<!-- Bouton caché pour JOSM -->
<a id="josmButton" style="display: none;"></a>
{% set followup_icons = {
'fire_hydrant': 'bi-droplet',
'charging_station': 'bi-lightning-charge',
'toilets': 'bi-toilet',
'bus_stop': 'bi-bus-front',
'defibrillator': 'bi-heart-pulse',
'camera': 'bi-camera-video',
'recycling': 'bi-recycle',
'substation': 'bi-plug',
'laboratory': 'bi-beaker',
'school': 'bi-mortarboard',
'places': 'bi-geo-alt'
} %}
<div class="row mb-4">
{% for type, data in latestFollowups %}
{% if data.count or data.completion %}
<div class="col-auto mb-2">
<div class="card shadow-sm text-center" style="min-width: 140px;">
<div class="card-body p-2">
<i class="bi {{ followup_icons[type]|default('bi-question-circle') }} fs-2 mb-1"></i><br>
<span class="fw-bold">{{ type_labels[type]|default(type|capitalize) }}</span><br>
<span title="Nombre">N = {{ data.count ? data.count.getMeasure() : '?' }}</span><br>
<span title="Complétion">Compl. = {{ data.completion ? data.completion.getMeasure() : '?' }}%</span>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
{% endblock %}
{% block javascripts %}