import {trierCandidats, regrouperVoix} from "../utils" import TableContainer from "@mui/material/TableContainer" import Paper from "@mui/material/Paper" import Table from "@mui/material/Table" import TableHead from "@mui/material/TableHead" import TableRow from "@mui/material/TableRow" import TableCell from "@mui/material/TableCell" import TableBody from "@mui/material/TableBody" import {useEffect, useMemo, useState} from "react" import {GeoJSON, MapContainer, Popup, TileLayer, useMap} from "react-leaflet" import bbox from "geojson-bbox" import {FormControl, InputLabel, MenuItem, Select} from "@mui/material" import * as Highcharts from "highcharts"; import HighchartsReact from "highcharts-react-official"; import Switch from "@mui/material/Switch"; import FormControlLabel from "@mui/material/FormControlLabel"; export function HistogrammeVoix({titre, nomCategories, valeurParCategorie, totalExprimes, couleurParCategorie}) { const [categoriesVoix, dataVoix] = useMemo(() => { const categories = [] const data = [] for (let categorie of Object.keys(nomCategories)) { if (valeurParCategorie[categorie] !== 0) { categories.push(nomCategories[categorie]) data.push([nomCategories[categorie], valeurParCategorie[categorie], couleurParCategorie[categorie], nomCategories[categorie]]) } } return [categories, data] }, [nomCategories, valeurParCategorie, couleurParCategorie]) const scoreOptions = { chart: { type: 'column' }, title: { text: titre, }, tooltip: { formatter: function () { return `${this.x} : ${this.y} voix (${(100 * this.y / totalExprimes).toFixed(2)} %)
` } }, xAxis: { categories: categoriesVoix, }, series: [{ name: "Nombre de voix", keys: ['name', 'y', 'color', 'label'], data: dataVoix, }] } return } export function CompositionHemicycle({titre, blocs, nuances, siegesParBloc, siegesParNuance, grouperParBloc}) { const dataSieges = useMemo(() => { const data = [] if (grouperParBloc) { for (let bloc of blocs) { data.push([bloc.nom, siegesParBloc[bloc.nom], bloc.couleur, bloc.nom]) } } else { for (let nuance of nuances) { data.push([nuance.nom, siegesParNuance[nuance.code], nuance.couleur, nuance.nom]) } } return data }, [blocs, nuances, siegesParBloc, siegesParNuance, grouperParBloc]) const compositonOptions = { chart: { type: 'item' }, title: { text: titre, }, legend: { labelFormat: '{name} {y}' }, series: [{ name: 'Nombre de sièges', keys: ['name', 'y', 'color', 'label'], data: dataSieges, dataLabels: { enabled: false, format: '{point.label}' }, // Circular options center: ['50%', '88%'], size: '170%', startAngle: -100, endAngle: 100 }] } return } /** * Tableau de participation de l'élection dans la zone concernée * @param donnees_t1 * @param donnees_t2 * @return {JSX.Element} * @constructor */ export function TableauParticipation({donnees_t1, donnees_t2 = null}) { const headerRow = useMemo(() => { if (donnees_t2 && donnees_t2.inscrits) { return Nombre tour 1 % Inscrit⋅es tour 1 % Votant⋅es tour 1 Nombre tour 2 % Inscrit⋅es tour 2 % Votant⋅es tour 2 } else { return Nombre % Inscrit⋅es % Votant⋅es } }, [donnees_t2]) const bodyRows = useMemo(() => { if (donnees_t2 && donnees_t2.inscrits) { return <> Inscrit⋅es {donnees_t1.inscrits} {donnees_t2.inscrits} Abstention {donnees_t1.abstentions} {(100 * donnees_t1.abstentions / donnees_t1.inscrits).toFixed(2)} % {donnees_t2.abstentions} {(100 * donnees_t2.abstentions / donnees_t2.inscrits).toFixed(2)} % Votant⋅es {donnees_t1.votants} {(100 * donnees_t1.votants / donnees_t1.inscrits).toFixed(2)} % {donnees_t2.votants} {(100 * donnees_t2.votants / donnees_t2.inscrits).toFixed(2)} % Blancs {donnees_t1.blancs} {(100 * donnees_t1.blancs / donnees_t1.inscrits).toFixed(2)} % {(100 * donnees_t1.blancs / donnees_t1.votants).toFixed(2)} % {donnees_t2.blancs} {(100 * donnees_t2.blancs / donnees_t2.inscrits).toFixed(2)} % {(100 * donnees_t2.blancs / donnees_t2.votants).toFixed(2)} % Nuls {donnees_t1.nuls} {(100 * donnees_t1.nuls / donnees_t1.inscrits).toFixed(2)} % {(100 * donnees_t1.nuls / donnees_t1.votants).toFixed(2)} % {donnees_t2.nuls} {(100 * donnees_t2.nuls / donnees_t2.inscrits).toFixed(2)} % {(100 * donnees_t2.nuls / donnees_t2.votants).toFixed(2)} % Exprimés {donnees_t1.exprimes} {(100 * donnees_t1.exprimes / donnees_t1.inscrits).toFixed(2)} % {(100 * donnees_t1.exprimes / donnees_t1.votants).toFixed(2)} % {donnees_t2.exprimes} {(100 * donnees_t2.exprimes / donnees_t2.inscrits).toFixed(2)} % {(100 * donnees_t2.exprimes / donnees_t2.votants).toFixed(2)} % } else { return <> Inscrit⋅es {donnees_t1.inscrits} Abstention {donnees_t1.abstentions} {(100 * donnees_t1.abstentions / donnees_t1.inscrits).toFixed(2)} % Votant⋅es {donnees_t1.votants} {(100 * donnees_t1.votants / donnees_t1.inscrits).toFixed(2)} % Blancs {donnees_t1.blancs} {(100 * donnees_t1.blancs / donnees_t1.inscrits).toFixed(2)} % {(100 * donnees_t1.blancs / donnees_t1.votants).toFixed(2)} % Nuls {donnees_t1.nuls} {(100 * donnees_t1.nuls / donnees_t1.inscrits).toFixed(2)} % {(100 * donnees_t1.nuls / donnees_t1.votants).toFixed(2)} % Exprimés {donnees_t1.exprimes} {(100 * donnees_t1.exprimes / donnees_t1.inscrits).toFixed(2)} % {(100 * donnees_t1.exprimes / donnees_t1.votants).toFixed(2)} % } }, [donnees_t1, donnees_t2]) return <> {headerRow} {bodyRows}
} export function GroupementParBloc({grouperParBloc, setGrouperParBloc}) { return setGrouperParBloc(event.target.checked)} inputProps={{ 'aria-label': 'controlled' }} />} label="Grouper par bloc plutôt que nuance politique" /> } export function RetirerSeuil({retirerSeuil, setRetirerSeuil}) { return setRetirerSeuil(event.target.checked)} inputProps={{ 'aria-label': 'controlled' }} />} label="Retirer le seuil des 5 %" /> } export function SelectionTour({tour, setTour}) { return Zone à afficher } export function SelectionAffichage({typeResultats, typeSousZone, setTypeSousZone}) { const items = useMemo(() => { const items = [] if (typeResultats === "france") { setTypeSousZone("region") items.push(Région) } if (typeResultats === "france" || typeResultats === "region") { if (typeResultats !== "france") setTypeSousZone("departement") items.push(Département) } if (typeResultats === "france" || typeResultats === "region" || typeResultats === "departement") { if (typeResultats !== "france" && typeResultats !== "region") setTypeSousZone("circonscription") items.push(Circonscription) } if (typeResultats === "departement") { items.push(Communes) } if (typeResultats === "circonscription" || typeResultats === "commune" || typeResultats === "bureau_vote") { setTypeSousZone("bureau_vote") items.push(Bureau de vote) } return items }, [typeResultats, setTypeSousZone]) return Zone à afficher } function ZoneGeoJSON({typeElection, anneeElection, resultatsZone, typeSousZone, candidats, blocs, nuances, tour, grouperParBloc = false, candidatKey = "numero"}) { const sousZoneInfo = resultatsZone.zone const donnees = useMemo(() => { return resultatsZone ? (tour === 1 ? resultatsZone.tour1 : resultatsZone.tour2) : {} }, [resultatsZone, tour]) const [idZone, nomZone] = useMemo(() => { if (!sousZoneInfo) return ["", ""] if (typeSousZone === "region" || typeSousZone === "departement" || typeSousZone === "commune") return [sousZoneInfo.code_insee, sousZoneInfo.nom] else if (typeSousZone === "circonscription") return [sousZoneInfo.id, `Circonscription ${sousZoneInfo.id}`] else if (typeSousZone === "bureau_vote") return [sousZoneInfo.id, sousZoneInfo.libelle] else return ["", ""] }, [typeSousZone, sousZoneInfo]) const [candidatsZone, setCandidatsZone] = useState(candidats) useEffect(() => { if (typeElection === "legislatives" && (typeSousZone === "circonscription" || typeSousZone === "bureau_vote") && sousZoneInfo.id) { const circo_id = typeSousZone === "circonscription" ? sousZoneInfo.id : sousZoneInfo.circonscription fetch(`/data/resultats/${typeElection}/${anneeElection}/candidats/${circo_id}.json`) .then(response => response.json()) .then(data => setCandidatsZone(data)) } }, [typeElection, anneeElection, typeSousZone, sousZoneInfo]) const voixCandidats = useMemo(() => donnees?.voix ?? {}, [donnees]) const candidatsTries = trierCandidats(candidatsZone, voixCandidats, candidatKey) const dejaGroupesParNuance = typeElection === "legislatives" && (typeSousZone !== "circonscription" && typeSousZone !== "bureau_vote") const [voixParBloc, voixParNuance] = regrouperVoix(voixCandidats, candidatsZone, blocs, nuances, dejaGroupesParNuance) 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 } } } return {nomZone}
    {candidatsTries.slice(0, 5).map(candidat =>
  • {candidat.nom} : {voixCandidats[candidat[candidatKey]]} ({(100 * voixCandidats[candidat[candidatKey]] / donnees.exprimes).toFixed(2)} %)
  • )}
} function ContenuCarte({typeElection, anneeElection, zoneInfo, typeSousZone, candidats, blocs, nuances, tour, grouperParBloc = false, candidatKey = "numero"}) { const map = useMap() const [resultatsZones, setResultatsZones] = useState([]) const zones = useMemo(() => { if (!zoneInfo) return [] if (typeSousZone === "region") return zoneInfo?.regions ?? [] else if (typeSousZone === "departement") return zoneInfo?.departements ?? [] else if (typeSousZone === "circonscription") return zoneInfo?.circonscriptions ?? [] else if (typeSousZone === "commune") return zoneInfo?.communes ?? [] else if (typeSousZone === "bureau_vote") { if (zoneInfo.type === "bureau_vote") return zoneInfo ? [zoneInfo.id] : [] else return zoneInfo?.bureaux_vote ?? [] } else return [] }, [zoneInfo, typeSousZone]) useEffect(() => { if (zoneInfo.type === "france") return const geometry = zoneInfo.geometry if (geometry) { // On centre la carte sur la zone const geometry_bbox = bbox(geometry) map.fitBounds([[geometry_bbox[1], geometry_bbox[0]], [geometry_bbox[3], geometry_bbox[2]]]) } }, [zoneInfo, map]) useEffect(() => { if (!zones) return setResultatsZones(resultatsZones => []) zones.forEach(zoneId => { fetch(`/data/resultats/${typeElection}/${anneeElection}/${typeSousZone}/${zoneId}.json`) .then(response => response.json()) .then(resultatsZone => setResultatsZones(resultatsZones => [...resultatsZones, resultatsZone])) }) }, [typeElection, anneeElection, typeSousZone, zones]) function getZoneIdentifier(typeSousZone, zone) { if (typeSousZone === "region" || typeSousZone === "departement" || typeSousZone === "commune") return zone.code_insee else if (typeSousZone === "circonscription" || typeSousZone === "bureau_vote") return zone.id else return "" } return <> {resultatsZones.filter(resultatsZone => resultatsZone.zone.geometry['type']) .map(resultatsZone => )} } export function CarteResultats({typeElection, anneeElection, typeResultats, zoneInfo, typeSousZone, candidats, blocs, nuances, tour, grouperParBloc = false, candidatKey = "numero"}) { const center = typeResultats === "france" ? [46.603354, 1.888334] : [0, 0] return <> }