From 7611d330729facf7c6711065cbd3be009988e341 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Sun, 16 Jun 2024 22:27:28 +0200 Subject: [PATCH] =?UTF-8?q?S=C3=A9lection=20du=20type=20d'affichage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nupes-elections-front/src/App.js | 24 +-- nupes-elections-front/src/Elections2024.js | 218 +++++++++++---------- nupes/models/geographie.py | 3 +- nupes/scripts/export_resultats_2024.py | 21 +- 4 files changed, 134 insertions(+), 132 deletions(-) diff --git a/nupes-elections-front/src/App.js b/nupes-elections-front/src/App.js index 461e7db..fbe4eb8 100644 --- a/nupes-elections-front/src/App.js +++ b/nupes-elections-front/src/App.js @@ -10,28 +10,12 @@ function App() { element: , }, { - path: "/elections/europeennes/2024/france/", - element: , + path: "/elections/europeennes/2024/:typeResultats/", + element: , }, { - path: "/elections/europeennes/2024/region/:zoneId/", - element: , - }, - { - path: "/elections/europeennes/2024/circonscription/:zoneId/", - element: , - }, - { - path: "/elections/europeennes/2024/departement/:zoneId/", - element: , - }, - { - path: "/elections/europeennes/2024/commune/:zoneId/", - element: , - }, - { - path: "/elections/europeennes/2024/bureau_vote/:zoneId/", - element: , + path: "/elections/europeennes/2024/:typeResultats/:zoneId/", + element: }, ]) diff --git a/nupes-elections-front/src/Elections2024.js b/nupes-elections-front/src/Elections2024.js index 35d9913..58158be 100644 --- a/nupes-elections-front/src/Elections2024.js +++ b/nupes-elections-front/src/Elections2024.js @@ -16,6 +16,7 @@ import {useEffect, useMemo, useState} from "react" import {GeoJSON, MapContainer, Popup, TileLayer, useMap} from "react-leaflet" import 'leaflet/dist/leaflet.css' +import {MenuItem, Select} from "@mui/material"; highchartsItem(Highcharts) @@ -125,8 +126,22 @@ function ParticipationTable({resultats}) { } -function RegionGeoJSON({resultats_region, listes, blocs, nuances, grouperParBloc = false}) { - const voix_listes = resultats_region?.voix_listes ?? {} +function ZoneGeoJSON({resultatsZone, typeZone, listes, blocs, nuances, grouperParBloc = false}) { + const [idZone, nomZone] = useMemo(() => { + if (!resultatsZone[typeZone]) + return ["", ""] + + if (typeZone === "region" || typeZone === "departement" || typeZone === "commune") + return [resultatsZone[typeZone].code_insee, resultatsZone[typeZone].nom] + else if (typeZone === "circonscription") + return [resultatsZone.circonscription.id, `Circonscription ${resultatsZone.circonscription.id}`] + else if (typeZone === "bureau_vote") + return [resultatsZone.bureau_vote.id, resultatsZone.bureau_vote.libelle] + else + return ["", ""] + }, [typeZone, resultatsZone]) + + const voix_listes = resultatsZone?.voix_listes ?? {} const listes_triees = listes.toSorted((l1, l2) => { return (voix_listes[l2.numero] || 0) - (voix_listes[l1.numero] || 0) }) @@ -141,8 +156,8 @@ function RegionGeoJSON({resultats_region, listes, blocs, nuances, grouperParBloc } for (let liste of listes) { - voixParBloc[liste.bloc] += resultats_region.voix_listes[liste.numero] || 0 - voixParNuance[liste.nuance] += resultats_region.voix_listes[liste.numero] || 0 + voixParBloc[liste.bloc] += resultatsZone.voix_listes[liste.numero] || 0 + voixParNuance[liste.nuance] += resultatsZone.voix_listes[liste.numero] || 0 } let couleur = 'grey' @@ -166,89 +181,43 @@ function RegionGeoJSON({resultats_region, listes, blocs, nuances, grouperParBloc } return + data={{'type': "Feature", 'geometry': resultatsZone.geometry}} + style={{fillColor: couleur, fillOpacity: 0.5, color: 'white', weight: 1}}> - {resultats_region.region.nom} + {nomZone}
    {listes_triees.slice(0, 5).map(liste => -
  • {liste.nom} : {voix_listes[liste.numero]} ({(100 * voix_listes[liste.numero] / resultats_region.exprimes).toFixed(2)} %)
  • )} +
  • {liste.nom} : {voix_listes[liste.numero]} ({(100 * voix_listes[liste.numero] / resultatsZone.exprimes).toFixed(2)} %)
  • )}
} - -function DepartementGeoJSON({resultats_departement, listes, blocs, nuances, grouperParBloc = false}) { - const voix_listes = resultats_departement?.voix_listes ?? {} - const listes_triees = listes.toSorted((l1, l2) => { - return (voix_listes[l2.numero] || 0) - (voix_listes[l1.numero] || 0) - }) - - const voixParBloc = {} - const voixParNuance = {} - for (let bloc of blocs) { - voixParBloc[bloc.nom] = 0 - } - for (let nuance of nuances) { - voixParNuance[nuance.code] = 0 - } - - for (let liste of listes) { - voixParBloc[liste.bloc] += resultats_departement.voix_listes[liste.numero] || 0 - voixParNuance[liste.nuance] += resultats_departement.voix_listes[liste.numero] || 0 - } - - let couleur = 'grey' - if (grouperParBloc) { - let maxVoix = 0 - for (let bloc of blocs) { - if (voixParBloc[bloc.nom] > maxVoix) { - maxVoix = voixParBloc[bloc.nom] - couleur = bloc.couleur - } - } - } - else { - let maxVoix = 0 - for (let nuance of nuances) { - if (voixParNuance[nuance.code] > maxVoix) { - maxVoix = voixParNuance[nuance.code] - couleur = nuance.couleur - } - } - } - - console.log(resultats_departement.departement.code_insee, resultats_departement.geometry) - - return - - {resultats_departement.departement.nom} -
    - {listes_triees.slice(0, 5).map(liste => -
  • {liste.nom} : {voix_listes[liste.numero]} ({(100 * voix_listes[liste.numero] / resultats_departement.exprimes).toFixed(2)} %)
  • )} -
-
-
-} - -function ContenuCarte({typeResultats, resultats, listes, blocs, nuances, grouperParBloc = false}) { +function ContenuCarte({typeResultats, resultats, typeZone, listes, blocs, nuances, grouperParBloc = false}) { const map = useMap() + console.log(typeZone) + const [resultatsZones, setResultatsZones] = useState([]) - const [typeZone, zones] = useMemo(() => { - if (typeResultats === "france") { - return ["regions", resultats?.france?.regions ?? []] - } - else if (typeResultats === "regions") { - return ["departements", resultats?.region?.departements ?? []] - } - }, [typeResultats, resultats]) + const zones = useMemo(() => { + const data = resultats[typeResultats] + if (!data) + return [] + + if (typeZone === "region") + return data?.regions ?? [] + else if (typeZone === "departement") + return data?.departements ?? [] + else if (typeZone === "circonscription") + return data?.circonscriptions ?? [] + else if (typeZone === "commune") + return data?.communes ?? [] + else if (typeZone === "bureau_vote") + return data?.bureaux_vote ?? [] + else + return [] + }, [typeResultats, resultats, typeZone]) useEffect(() => { if (!zones) @@ -262,25 +231,24 @@ function ContenuCarte({typeResultats, resultats, listes, blocs, nuances, grouper }) }, [typeZone, zones, resultats]) - if (typeZone === "regions") { - return <> - {resultatsZones.filter(resultatsZone => resultatsZone.geometry['type']).map(resultatsZone => - )} - - } - else if (typeZone === "departements") { - return <> - {resultatsZones.filter(resultatsZone => resultatsZone.geometry['type']).map(resultatsZone => - )} - + function getZoneIdentifier(typeZone, zone) { + if (typeZone === "region" || typeZone === "departement" || typeZone === "commune") + return zone.code_insee + else if (typeZone === "circonscription" || typeZone === "bureau_vote") + return zone.id + else + return "" } + + return <> + {resultatsZones.filter(resultatsZone => resultatsZone.geometry['type']).map(resultatsZone => + )} + } -function Carte({typeResultats, resultats, listes, blocs, nuances, grouperParBloc = false}) { +function Carte({typeResultats, resultats, typeZone, listes, blocs, nuances, grouperParBloc = false}) { const center = [46.603354, 1.888334] return <> @@ -289,13 +257,50 @@ function Carte({typeResultats, resultats, listes, blocs, nuances, grouperParBloc attribution='© Les contributeur⋅rices OpenStreetMap' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> - + } -export default function Election2024({typeResultats = "france"}) { - const {zoneId} = useParams() +function SelectionAffichage({typeResultats, typeZone, setTypeZone}) { + const items = useMemo(() => { + const items = [] + if (typeResultats === "france") { + setTypeZone("region") + items.push(Région) + } + + if (typeResultats === "france" || typeResultats === "region") { + if (typeResultats !== "france") + setTypeZone("departement") + items.push(Département) + } + + if (typeResultats === "france" || typeResultats === "region" || typeResultats === "departement") { + if (typeResultats !== "france" && typeResultats !== "region") + setTypeZone("circonscription") + items.push(Circonscription) + } + + if (typeResultats === "departement") { + items.push(Communes) + } + + if (typeResultats === "circonscription" || typeResultats === "commune") { + setTypeZone("bureau_vote") + items.push(Bureau de vote) + } + + return items + }, [typeResultats, setTypeZone]) + + return +} + +export default function Election2024() { + const {typeResultats, zoneId} = useParams() const [zoneName, setZoneName] = useState("France") const [grouperParBloc, setGrouperParBloc] = useState(false) @@ -312,6 +317,7 @@ export default function Election2024({typeResultats = "france"}) { const [categoriesVoix, setCategoriesVoix] = useState([]) const [dataVoix, setDataVoix] = useState([]) const [dataSieges, setDataSieges] = useState([]) + const [typeZone, setTypeZone] = useState("region") useEffect(() => { fetch("/data/resultats/europeennes2024/blocs.json").then(response => response.json()) @@ -336,19 +342,22 @@ export default function Election2024({typeResultats = "france"}) { setZoneName("") else if (typeResultats === "france") setZoneName("France") - else if (typeResultats === "regions") + else if (typeResultats === "region") setZoneName(`Région ${resultats.region.nom}`) - else if (typeResultats === "departements") + else if (typeResultats === "departement") setZoneName(`Département ${resultats.departement.nom}`) - else if (typeResultats === "circonscriptions") - setZoneName(`Circonscription ${resultats.circonscription.nom}`) - else if (typeResultats === "communes") + else if (typeResultats === "circonscription") + setZoneName(`Circonscription ${resultats.circonscription.id}`) + else if (typeResultats === "commune") setZoneName(`Commune ${resultats.commune.nom}`) - else if (typeResultats === "bureaux_vote") + else if (typeResultats === "bureau_vote") setZoneName(resultats.bureau_vote.libelle) }, [typeResultats, resultats]) useEffect(() => { + if (!resultats['voix_listes']) + return + const parBloc = {} const parNuance = {} for (let bloc of blocs) { @@ -387,6 +396,9 @@ export default function Election2024({typeResultats = "france"}) { }, [voixParBloc, voixParNuance, grouperParBloc]) useEffect(() => { + if (!resultats['voix_listes']) + return + const MAX_SIEGES = 81 const sieges = {} const listesElues = [] @@ -537,6 +549,10 @@ export default function Election2024({typeResultats = "france"}) { /> - + + } + label="Type d'affichage pour la carte" /> + + } diff --git a/nupes/models/geographie.py b/nupes/models/geographie.py index 9e2b743..a372c38 100644 --- a/nupes/models/geographie.py +++ b/nupes/models/geographie.py @@ -27,6 +27,7 @@ class Departement(Base): geometry: Mapped[dict] = mapped_column(JSON()) region: Mapped[Region] = relationship(Region, back_populates="departements") + circonscriptions: Mapped[List["Circonscription"]] = relationship("Circonscription", back_populates="departement") communes: Mapped[List["Commune"]] = relationship("Commune", back_populates="departement") resultats2024 = relationship("ResultatsDepartement", back_populates="departement") @@ -54,7 +55,7 @@ class Circonscription(Base): numero: Mapped[int] = mapped_column(Integer()) geometry: Mapped[dict] = mapped_column(JSON()) - departement: Mapped[Departement] = relationship(Departement) + departement: Mapped[Departement] = relationship(Departement, back_populates="circonscriptions") bureaux_vote: Mapped[List["BureauVote"]] = relationship("BureauVote", back_populates="circonscription") resultats2024 = relationship("ResultatsCirconscription", back_populates="circonscription") diff --git a/nupes/scripts/export_resultats_2024.py b/nupes/scripts/export_resultats_2024.py index 54fe926..8f91393 100644 --- a/nupes/scripts/export_resultats_2024.py +++ b/nupes/scripts/export_resultats_2024.py @@ -140,7 +140,7 @@ def exporter_resultats_regions(engine: Engine, verbose: bool = False) -> None: for voix_liste in resultats_region.voix_listes: resultats_listes[voix_liste.liste.numero] = voix_liste.voix - file = DATA_DIR / "resultats" / "europeennes2024" / "regions" / f"{region.code_insee}.json" + file = DATA_DIR / "resultats" / "europeennes2024" / "region" / f"{region.code_insee}.json" if not file.parent.is_dir(): file.parent.mkdir(parents=True) @@ -149,7 +149,7 @@ def exporter_resultats_regions(engine: Engine, verbose: bool = False) -> None: session.commit() - regions_file = DATA_DIR / "resultats" / "europeennes2024" / "regions" / "regions.json" + regions_file = DATA_DIR / "resultats" / "europeennes2024" / "region" / "regions.json" if not regions_file.parent.is_dir(): regions_file.parent.mkdir(parents=True) @@ -166,6 +166,7 @@ def exporter_resultats_departements(engine: Engine, verbose: bool = False) -> No for departement in iterator: departement_json = {'code_insee': departement.code_insee, 'nom': departement.libelle, 'region': departement.region_code, + 'circonscriptions': [circo.id for circo in departement.circonscriptions], 'communes': [commune.code_insee for commune in departement.communes]} departements_json.append(departement_json) @@ -194,7 +195,7 @@ def exporter_resultats_departements(engine: Engine, verbose: bool = False) -> No for voix_liste in resultats_departement.voix_listes: resultats_listes[voix_liste.liste.numero] = voix_liste.voix - file = DATA_DIR / "resultats" / "europeennes2024" / "departements" / f"{departement.code_insee}.json" + file = DATA_DIR / "resultats" / "europeennes2024" / "departement" / f"{departement.code_insee}.json" if not file.parent.is_dir(): file.parent.mkdir(parents=True) @@ -203,7 +204,7 @@ def exporter_resultats_departements(engine: Engine, verbose: bool = False) -> No session.commit() - departements_file = DATA_DIR / "resultats" / "europeennes2024" / "departements" / "departements.json" + departements_file = DATA_DIR / "resultats" / "europeennes2024" / "departement" / "departements.json" if not departements_file.parent.is_dir(): departements_file.parent.mkdir(parents=True) @@ -248,7 +249,7 @@ def exporter_resultats_circonscriptions(engine: Engine, verbose: bool = False) - for voix_liste in resultats_circonscription.voix_listes: resultats_listes[voix_liste.liste.numero] = voix_liste.voix - file = DATA_DIR / "resultats" / "europeennes2024" / "circonscriptions" / f"{circonscription.id}.json" + file = DATA_DIR / "resultats" / "europeennes2024" / "circonscription" / f"{circonscription.id}.json" if not file.parent.is_dir(): file.parent.mkdir(parents=True) @@ -257,7 +258,7 @@ def exporter_resultats_circonscriptions(engine: Engine, verbose: bool = False) - session.commit() - circonscriptions_file = DATA_DIR / "resultats" / "europeennes2024" / "circonscriptions" / "circonscriptions.json" + circonscriptions_file = DATA_DIR / "resultats" / "europeennes2024" / "circonscription" / "circonscriptions.json" if not circonscriptions_file.parent.is_dir(): circonscriptions_file.parent.mkdir(parents=True) @@ -302,7 +303,7 @@ def exporter_resultats_communes(engine: Engine, verbose: bool = False) -> None: for voix_liste in resultats_commune.voix_listes: resultats_listes[voix_liste.liste.numero] = voix_liste.voix - file = DATA_DIR / "resultats" / "europeennes2024" / "communes" / f"{commune.code_insee}.json" + file = DATA_DIR / "resultats" / "europeennes2024" / "commune" / f"{commune.code_insee}.json" if not file.parent.is_dir(): file.parent.mkdir(parents=True) @@ -311,7 +312,7 @@ def exporter_resultats_communes(engine: Engine, verbose: bool = False) -> None: session.commit() - communes_file = DATA_DIR / "resultats" / "europeennes2024" / "communes" / "communes.json" + communes_file = DATA_DIR / "resultats" / "europeennes2024" / "commune" / "communes.json" if not communes_file.parent.is_dir(): communes_file.parent.mkdir(parents=True) @@ -357,7 +358,7 @@ def exporter_resultats_bureaux_vote(engine: Engine, verbose: bool = False) -> No for voix_liste in resultats_bureau_vote.voix_listes: resultats_listes[voix_liste.liste.numero] = voix_liste.voix - file = DATA_DIR / "resultats" / "europeennes2024" / "bureaux_vote" / f"{bureau_vote.id}.json" + file = DATA_DIR / "resultats" / "europeennes2024" / "bureau_vote" / f"{bureau_vote.id}.json" if not file.parent.is_dir(): file.parent.mkdir(parents=True) @@ -366,7 +367,7 @@ def exporter_resultats_bureaux_vote(engine: Engine, verbose: bool = False) -> No session.commit() - bureaux_vote_file = DATA_DIR / "resultats" / "europeennes2024" / "bureaux_vote" / "bureaux_vote.json" + bureaux_vote_file = DATA_DIR / "resultats" / "europeennes2024" / "bureau_vote" / "bureaux_vote.json" if not bureaux_vote_file.parent.is_dir(): bureaux_vote_file.parent.mkdir(parents=True)