diff --git a/bin/parse.ts b/bin/parse.ts index 85ea80c9..167b9472 100644 --- a/bin/parse.ts +++ b/bin/parse.ts @@ -7,12 +7,17 @@ import { promisify } from "node:util"; import nodeLefff from "node-lefff"; import { toASCIIString } from "../src/utils/ascii"; import type { - OccurenceItem, SentimentOccurenceItem, - StatItem, StatsSummary, } from "../src/utils/writters"; import type { Author, BaseGroup } from "../src/utils/tribunes"; +import { + createBaseStatsItem, + shrinkStats, + sortByName, + aggregatesStats, + computeStats, +} from "../src/utils/stats"; const exec = promisify(_exec); @@ -95,12 +100,17 @@ async function run() { portrait = "default.svg"; } - authors.push({ + const author = { id, name, mandates, portrait, - }); + totalSignificantWords: 0, + totalWords: 0, + }; + + authors.push(author); + globalStats.authors[author.id] = author; } while (authorParts.length); const content = parts @@ -153,6 +163,7 @@ async function run() { partyAbbr: group.abbr, type: group.type, logo: group.logo, + totalWords: 0, writtings: [], sentences: [], sentiments: [], @@ -183,6 +194,7 @@ async function run() { const writerAggregation = writtersAggregations[ toASCIIString(name) ] || { + totalWords: 0, writtings: [], sentences: [], sentiments: [], @@ -300,8 +312,10 @@ async function run() { words.forEach((word) => { const lemma = nl.lem(word.word); + aggregationsList.forEach((aggregation) => { aggregation.words[lemma] = (aggregation.words[lemma] || 0) + 1; + aggregation.totalWords += word.word.length > 3 ? 1 : 0; }); }); @@ -351,12 +365,17 @@ ${content} caps: computeStats(writtersAggregations[key].caps), sentiments: computeSentimentStats(writtersAggregations[key].sentiments), }; + const allWords = Object.keys(writtersAggregations[key].words).filter( + (word) => word.length > 3 + ); + + globalStats.authors[key].totalWords = writtersAggregations[key].totalWords; + globalStats.authors[key].totalSignificantWords = allWords.length; const finalAggregation = { ...writtersAggregations[key], summary: shrinkSummary(summary), - words: Object.keys(writtersAggregations[key].words) - .filter((word) => word.length > 3) + words: allWords .sort((wordA, wordB) => writtersAggregations[key].words[wordA] < writtersAggregations[key].words[wordB] @@ -432,215 +451,113 @@ ${content} pathJoin("contents", `globalStats.json`), JSON.stringify(shrinkSummary(globalStats), null, 2) ); +} - function buildGroupDetails(fullName): BaseGroup { - const matches = fullName.match(/^(.*) :([^\(]*)(\(.*\)|)$/); - const name = matches[2].trim() || "Non-Affilié·es"; - const type = matches[1].trim(); - let party = matches[3].trim() || "Sans-Étiquette"; - let abbr = "SE"; - let logo = "default.svg"; - - if (party.includes("Europe Écologie les Verts")) { - party = "Europe Écologie-Les Verts"; - abbr = "EELV"; - logo = "eelv-douaisis.svg"; - } - if (party.includes("Vivre Douai")) { - party = "Citoyen·nes de Vivre Douai"; - abbr = "SE"; - logo = "douai-au-coeur.svg"; - } - if (party.includes("Parti Socialiste")) { - party = "Parti Socialiste"; - abbr = "PS"; - logo = "ps.png"; - } - if ( - party.includes("L’humain d’abord pour Douai") || - party.includes("Parti Communiste") - ) { - party = "Parti Communiste Français"; - abbr = "PCF"; - logo = "pcf.svg"; - } - if (party.includes("Rassemblement National")) { - party = "Rassemblement National"; - abbr = "RN"; - } - if (party.includes("UMP")) { - party = "Union pour un Mouvement Populaire"; - abbr = "UMP"; - } - if (fullName.includes("Douai dynamique et durable")) { - party = "Alliance LReM-Modem"; - abbr = "DVD"; - } - if (fullName.includes("Ensemble faisons Douai")) { - party = "Sans-Étiquette"; - abbr = "SE"; - } - - return { - id: toASCIIString(`${name} ${abbr}`), - name, - type, - party, - abbr, - logo, - }; +function buildGroupDetails(fullName): BaseGroup { + const matches = fullName.match(/^(.*) :([^\(]*)(\(.*\)|)$/); + const name = matches[2].trim() || "Non-Affilié·es"; + const type = matches[1].trim(); + let party = matches[3].trim() || "Sans-Étiquette"; + let abbr = "SE"; + let logo = "default.svg"; + + if (party.includes("Europe Écologie les Verts")) { + party = "Europe Écologie-Les Verts"; + abbr = "EELV"; + logo = "eelv-douaisis.svg"; } - - function createBaseStatsItem(): StatItem { - return { - mean: { count: 0, total: 0 }, - min: { value: Infinity, ids: [] }, - max: { value: -Infinity, ids: [] }, - }; + if (party.includes("Vivre Douai")) { + party = "Citoyen·nes de Vivre Douai"; + abbr = "SE"; + logo = "douai-au-coeur.svg"; } - - function createBaseStatsObject(): StatsSummary { - return { - sentences: createBaseStatsItem(), - exclamations: createBaseStatsItem(), - questions: createBaseStatsItem(), - bolds: createBaseStatsItem(), - caps: createBaseStatsItem(), - sentiments: { - positive: createBaseStatsItem(), - neutral: createBaseStatsItem(), - negative: createBaseStatsItem(), - }, - }; + if (party.includes("Parti Socialiste")) { + party = "Parti Socialiste"; + abbr = "PS"; + logo = "ps.png"; } - - function aggregatesStats(statsItem: StatItem, statsObject: StatItem) { - statsObject.mean.total += statsItem.mean.total; - statsObject.mean.count++; - if (statsObject.min.value > statsItem.min.value) { - statsObject.min = statsItem.min; - } - if (statsObject.min.value === statsItem.min.value) { - statsObject.min = { - value: statsItem.min.value, - ids: [...statsObject.min.ids, ...statsItem.min.ids], - }; - } - if (statsObject.max.value < statsItem.max.value) { - statsObject.max = statsItem.max; - } - if (statsObject.max.value === statsItem.max.value) { - statsObject.max = { - value: statsItem.max.value, - ids: [...statsObject.max.ids, ...statsItem.max.ids], - }; - } + if ( + party.includes("L’humain d’abord pour Douai") || + party.includes("Parti Communiste") + ) { + party = "Parti Communiste Français"; + abbr = "PCF"; + logo = "pcf.svg"; } - - function computeStats(occurences: OccurenceItem[]): StatItem { - return { - mean: { - count: occurences.reduce((total, { count }) => total + count, 0), - total: occurences.length, - }, - min: occurences.reduce( - (actualMin, { count: value, id }) => { - if (actualMin.value > value) { - return { - value, - ids: [id], - }; - } - if (actualMin.value === value) { - return { - value, - ids: [...actualMin.ids, id], - }; - } - return actualMin; - }, - { value: Infinity, ids: [] } as StatItem["min"] - ), - max: occurences.reduce( - (actualMax, { count: value, id }) => { - if (actualMax.value < value) { - return { - value, - ids: [id], - }; - } - if (actualMax.value === value) { - return { - value, - ids: [...actualMax.ids, id], - }; - } - return actualMax; - }, - { value: -Infinity, ids: [] } as StatItem["max"] - ), - }; + if (party.includes("Rassemblement National")) { + party = "Rassemblement National"; + abbr = "RN"; + } + if (party.includes("UMP")) { + party = "Union pour un Mouvement Populaire"; + abbr = "UMP"; + } + if (fullName.includes("Douai dynamique et durable")) { + party = "Alliance LReM-Modem"; + abbr = "DVD"; + } + if (fullName.includes("Ensemble faisons Douai")) { + party = "Sans-Étiquette"; + abbr = "SE"; } - function computeSentimentStats( - occurences: SentimentOccurenceItem[] - ): StatsSummary["sentiments"] { - return ["positive", "neutral", "negative"].reduce((stats, sentiment) => { - const reshapedOccurences = occurences.map( - ({ id, date, ...occurence }) => ({ - id, - date, - count: occurence[sentiment], - }) - ); + return { + id: toASCIIString(`${name} ${abbr}`), + name, + type, + party, + abbr, + logo, + }; +} - return { - ...stats, - [sentiment]: computeStats(reshapedOccurences), - }; - }, {} as Partial) as StatsSummary["sentiments"]; - } +function createBaseStatsObject() { + return { + authors: {}, + sentences: createBaseStatsItem(), + exclamations: createBaseStatsItem(), + questions: createBaseStatsItem(), + bolds: createBaseStatsItem(), + caps: createBaseStatsItem(), + sentiments: { + positive: createBaseStatsItem(), + neutral: createBaseStatsItem(), + negative: createBaseStatsItem(), + }, + }; +} - function shrinkStats(statsItem: StatItem): StatItem { - return { - mean: statsItem.mean, - min: { - value: statsItem.min.value, - ids: statsItem.min.ids.slice(0, 5), - restLength: statsItem.min.ids.slice(5).length, - }, - max: { - value: statsItem.max.value, - ids: statsItem.max.ids.slice(0, 5), - restLength: statsItem.max.ids.slice(5).length, - }, - }; - } +function computeSentimentStats( + occurences: SentimentOccurenceItem[] +): StatsSummary["sentiments"] { + return ["positive", "neutral", "negative"].reduce((stats, sentiment) => { + const reshapedOccurences = occurences.map(({ id, date, ...occurence }) => ({ + id, + date, + count: occurence[sentiment], + })); - function shrinkSummary(summary: StatsSummary): StatsSummary { return { - sentences: shrinkStats(summary.sentences), - exclamations: shrinkStats(summary.exclamations), - questions: shrinkStats(summary.questions), - bolds: shrinkStats(summary.bolds), - caps: shrinkStats(summary.caps), - sentiments: { - positive: shrinkStats(summary.sentiments.positive), - neutral: shrinkStats(summary.sentiments.neutral), - negative: shrinkStats(summary.sentiments.negative), - }, + ...stats, + [sentiment]: computeStats(reshapedOccurences), }; - } + }, {} as Partial) as StatsSummary["sentiments"]; +} - function sortByName( - authorA: T, - authorB: T - ): number { - if (authorA.name < authorB.name) { - return -1; - } else if (authorA.name > authorB.name) { - return 1; - } - return 0; - } +function shrinkSummary( + summary: Omit +): Omit { + return { + ...summary, + sentences: shrinkStats(summary.sentences), + exclamations: shrinkStats(summary.exclamations), + questions: shrinkStats(summary.questions), + bolds: shrinkStats(summary.bolds), + caps: shrinkStats(summary.caps), + sentiments: { + positive: shrinkStats(summary.sentiments.positive), + neutral: shrinkStats(summary.sentiments.neutral), + negative: shrinkStats(summary.sentiments.negative), + }, + }; } diff --git a/bin/presence.ts b/bin/presence.ts index 66862c22..f5686779 100644 --- a/bin/presence.ts +++ b/bin/presence.ts @@ -1,8 +1,21 @@ import { join as pathJoin } from "node:path"; import { readFile, writeFile, readdir, access } from "node:fs/promises"; import { toASCIIString } from "../src/utils/ascii"; +import { + OccurenceItem, + aggregatesStats, + computeStats, + createBaseStatsItem, + shrinkStats, + sortByDate, +} from "../src/utils/stats"; import type { Author } from "../src/utils/tribunes"; -import type { PresenceItem } from "../src/utils/writters"; +import type { + PresenceItem, + PresenceStatItem, + PresenceStatsSummary, + StatsSummary, +} from "../src/utils/writters"; run(); @@ -54,6 +67,30 @@ async function run() { } } + const instanceCode = file.replace(/\.csv$/, ""); + const globalStats = JSON.parse( + (await readFile(pathJoin("contents", `globalStats.json`))).toString() + ) as StatsSummary; + const globalOccurences: Record< + keyof PresenceStatsSummary, + OccurenceItem[] + > = { + presenceRatio: [], + arrivedLate: [], + leftBeforeTheEnd: [], + delegation: [], + }; + + globalStats.presences = globalStats.presences || {}; + globalStats.presences[instanceCode] = []; + globalStats.presencesStats = globalStats.presencesStats || {}; + globalStats.presencesStats[instanceCode] = { + presenceRatio: createBaseStatsItem(), + arrivedLate: createBaseStatsItem(), + leftBeforeTheEnd: createBaseStatsItem(), + delegation: createBaseStatsItem(), + }; + for (const personId of Object.keys(persons)) { const presences: PresenceItem[] = persons[personId].presences.map( (presence) => @@ -76,14 +113,16 @@ async function run() { pathJoin("contents", "writters", `${persons[personId].id}.json`) ) ).toString() - ); + ) as { + presences?: Record; + presencesStats?: Record; + }; writterData.presences = writterData.presences || {}; - writterData.presences[file.replace(/\.csv$/, "")] = - presences.sort(sortByDate); + writterData.presences[instanceCode] = presences.sort(sortByDate); writterData.presencesStats = writterData.presencesStats || {}; - writterData.presencesStats[file.replace(/\.csv$/, "")] = presences.reduce( + writterData.presencesStats[instanceCode] = presences.reduce( (stats, presence) => ({ total: stats.total + 1, present: stats.present + (presence.present ? 1 : 0), @@ -105,7 +144,71 @@ async function run() { pathJoin("contents", "writters", `${persons[personId].id}.json`), JSON.stringify(writterData, null, 2) ); + + globalStats.authors[persons[personId].id] = globalStats.authors[ + persons[personId].id + ] || { + id: persons[personId].id, + name: persons[personId].name, + portrait: "default.svg", + mandates: [], + totalSignificantWords: 0, + totalWords: 0, + }; + + globalStats.presences[instanceCode].push({ + id: persons[personId].id, + ...writterData.presencesStats[instanceCode], + }); + + aggregatesStats( + createBaseStatsItem( + (writterData.presencesStats[instanceCode].present / + writterData.presencesStats[instanceCode].total) * + 100, + persons[personId].id + ), + globalStats.presencesStats[instanceCode].presenceRatio + ); + globalStats.presencesStats[instanceCode].presenceRatio = shrinkStats( + globalStats.presencesStats[instanceCode].presenceRatio + ); + aggregatesStats( + createBaseStatsItem( + writterData.presencesStats[instanceCode].arrivedLate, + persons[personId].id + ), + globalStats.presencesStats[instanceCode].arrivedLate + ); + globalStats.presencesStats[instanceCode].arrivedLate = shrinkStats( + globalStats.presencesStats[instanceCode].arrivedLate + ); + aggregatesStats( + createBaseStatsItem( + writterData.presencesStats[instanceCode].leftBeforeTheEnd, + persons[personId].id + ), + globalStats.presencesStats[instanceCode].leftBeforeTheEnd + ); + globalStats.presencesStats[instanceCode].leftBeforeTheEnd = shrinkStats( + globalStats.presencesStats[instanceCode].leftBeforeTheEnd + ); + aggregatesStats( + createBaseStatsItem( + writterData.presencesStats[instanceCode].delegation, + persons[personId].id + ), + globalStats.presencesStats[instanceCode].delegation + ); + globalStats.presencesStats[instanceCode].delegation = shrinkStats( + globalStats.presencesStats[instanceCode].delegation + ); } + + await writeFile( + pathJoin("contents", `globalStats.json`), + JSON.stringify(globalStats, null, 2) + ); } } @@ -131,15 +234,3 @@ function parsePresenceCode(code: string): PartialPresence { : {}), }; } - -function sortByDate( - authorA: T, - authorB: T -): number { - if (Date.parse(authorA.date) < Date.parse(authorB.date)) { - return -1; - } else if (Date.parse(authorA.date) > Date.parse(authorB.date)) { - return 1; - } - return 0; -} diff --git a/contents/globalStats.json b/contents/globalStats.json index 61004eb3..a01fe379 100644 --- a/contents/globalStats.json +++ b/contents/globalStats.json @@ -1,4 +1,575 @@ { + "authors": { + "monique-amghar": { + "id": "monique-amghar", + "name": "Monique AMGHAR", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 122, + "totalWords": 156 + }, + "jacques-vernier": { + "id": "jacques-vernier", + "name": "Jacques VERNIER", + "mandates": [ + "Maire de Douai", + "Conseiller Régional" + ], + "portrait": "default.svg", + "totalSignificantWords": 430, + "totalWords": 736 + }, + "cyril-carbonnel": { + "id": "cyril-carbonnel", + "name": "Cyril CARBONNEL", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 313, + "totalWords": 438 + }, + "rene-lavarde": { + "id": "rene-lavarde", + "name": "René LAVARDE", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 64, + "totalWords": 76 + }, + "jean-pierre-divrechy": { + "id": "jean-pierre-divrechy", + "name": "Jean-Pierre DIVRECHY", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 101, + "totalWords": 116 + }, + "brigitte-bonnaffe-leriche": { + "id": "brigitte-bonnaffe-leriche", + "name": "Brigitte BONNAFFE-LERICHE", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 52, + "totalWords": 52 + }, + "karine-doyen-carbonnel": { + "id": "karine-doyen-carbonnel", + "name": "Karine DOYEN CARBONNEL", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 75, + "totalWords": 85 + }, + "annick-louvion": { + "id": "annick-louvion", + "name": "Annick LOUVION", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 72, + "totalWords": 77 + }, + "odile-hage": { + "id": "odile-hage", + "name": "Odile HAGE", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 60, + "totalWords": 62 + }, + "frederic-chereau": { + "id": "frederic-chereau", + "name": "Frédéric CHÉREAU", + "mandates": [ + "Maire de Douai" + ], + "portrait": "frederic-chereau.jpg", + "totalSignificantWords": 2563, + "totalWords": 10363 + }, + "jackie-avenel": { + "id": "jackie-avenel", + "name": "Jackie AVENEL", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 78, + "totalWords": 93 + }, + "guy-cannie": { + "id": "guy-cannie", + "name": "Guy CANNIE", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "guy-cannie.jpg", + "totalSignificantWords": 1431, + "totalWords": 3172 + }, + "francoise-prouvost": { + "id": "francoise-prouvost", + "name": "Françoise PROUVOST", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 789, + "totalWords": 1352 + }, + "gerard-bailliet": { + "id": "gerard-bailliet", + "name": "Gérard BAILLIET", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 495, + "totalWords": 656 + }, + "marie-helene-quatreboeufs-niklikowski": { + "id": "marie-helene-quatreboeufs-niklikowski", + "name": "Marie-Hélène QUATREBOEUFS-NIKLIKOWSKI", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 192, + "totalWords": 226 + }, + "marie-delecambre": { + "id": "marie-delecambre", + "name": "Marie DELECAMBRE", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 409, + "totalWords": 578 + }, + "chantal-rybak": { + "id": "chantal-rybak", + "name": "Chantal RYBAK", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "chantal-rybak.jpg", + "totalSignificantWords": 552, + "totalWords": 876 + }, + "franz-quatreboeufs": { + "id": "franz-quatreboeufs", + "name": "Franz QUATREBOEUFS", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "franz-quatreboeufs.jpg", + "totalSignificantWords": 422, + "totalWords": 610 + }, + "bruno-bufquin": { + "id": "bruno-bufquin", + "name": "Bruno BUFQUIN", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 280, + "totalWords": 362 + }, + "isabelle-chatelain": { + "id": "isabelle-chatelain", + "name": "Isabelle CHÂTELAIN", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "default.svg", + "totalSignificantWords": 155, + "totalWords": 193 + }, + "coline-craeye": { + "id": "coline-craeye", + "name": "Coline CRAEYE,", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "coline-craeye.jpg", + "totalSignificantWords": 617, + "totalWords": 1087 + }, + "francois-guiffard": { + "id": "francois-guiffard", + "name": "François GUIFFARD", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "francois-guiffard.jpg", + "totalSignificantWords": 901, + "totalWords": 1657 + }, + "thibaut-francois": { + "id": "thibaut-francois", + "name": "Thibaut FRANCOIS,", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "thibaut-francois.jpg", + "totalSignificantWords": 647, + "totalWords": 1274 + }, + "agnes-dupuis": { + "id": "agnes-dupuis", + "name": "Agnès DUPUIS", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "agnes-dupuis.jpg", + "totalSignificantWords": 88, + "totalWords": 104 + }, + "stephanie-stiernon": { + "id": "stephanie-stiernon", + "name": "Stéphanie STIERNON", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "stephanie-stiernon.jpg", + "totalSignificantWords": 332, + "totalWords": 457 + }, + "auriane-ait-lasri": { + "id": "auriane-ait-lasri", + "name": "Auriane AIT LASRI", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "auriane-ait-lasri.jpg", + "totalSignificantWords": 593, + "totalWords": 1011 + }, + "mohamed-kheraki": { + "id": "mohamed-kheraki", + "name": "Mohamed KHERAKI", + "mandates": [ + "Adjoint au Maire" + ], + "portrait": "mohamed-kheraki.jpg", + "totalSignificantWords": 91, + "totalWords": 102 + }, + "katia-bittner": { + "id": "katia-bittner", + "name": "Katia BITTNER", + "mandates": [ + "Conseillère municipale" + ], + "portrait": "katia-bittner.jpg", + "totalSignificantWords": 215, + "totalWords": 316 + }, + "virginie-malolepszy": { + "id": "virginie-malolepszy", + "name": "Virginie MALOLEPSZY", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "default.svg", + "totalSignificantWords": 47, + "totalWords": 48 + }, + "marie-delattre": { + "id": "marie-delattre", + "name": "Marie DELATTRE", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "marie-delattre.jpg", + "totalSignificantWords": 183, + "totalWords": 296 + }, + "nathalie-apers": { + "id": "nathalie-apers", + "name": "Nathalie APERS", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "nathalie-apers.jpg", + "totalSignificantWords": 88, + "totalWords": 95 + }, + "yves-piquot": { + "id": "yves-piquot", + "name": "Yves PIQUOT", + "mandates": [ + "Conseiller municipal" + ], + "portrait": "yves-piquot.jpg", + "totalSignificantWords": 190, + "totalWords": 249 + }, + "jessy-kaboul": { + "id": "jessy-kaboul", + "name": "Jessy KABOUL", + "mandates": [ + "Adjoint au maire" + ], + "portrait": "default.svg", + "totalSignificantWords": 86, + "totalWords": 98 + }, + "hocine-mazy": { + "id": "hocine-mazy", + "name": "Hocine MAZY", + "mandates": [ + "Adjoint au maire" + ], + "portrait": "hocine-mazy.jpg", + "totalSignificantWords": 84, + "totalWords": 103 + }, + "jean-christophe-leclercq": { + "id": "jean-christophe-leclercq", + "name": "Jean-Christophe LECLERCQ", + "mandates": [ + "Adjoint au maire" + ], + "portrait": "jean-christophe-leclercq.jpg", + "totalSignificantWords": 162, + "totalWords": 197 + }, + "jean-michel-leroy": { + "id": "jean-michel-leroy", + "name": "Jean-Michel LEROY", + "mandates": [ + "Adjoint au maire" + ], + "portrait": "jean-michel-leroy.jpg", + "totalSignificantWords": 81, + "totalWords": 96 + }, + "guy-caruyer": { + "id": "guy-caruyer", + "name": "Guy CARUYER", + "mandates": [ + "Conseiller municipal délégué" + ], + "portrait": "guy-caruyer.jpg", + "totalSignificantWords": 120, + "totalWords": 142 + }, + "eric-lemaitre": { + "id": "eric-lemaitre", + "name": "Éric LEMAITRE", + "mandates": [ + "Conseiller municipal" + ], + "portrait": "eric-lemaitre.jpg", + "totalSignificantWords": 45, + "totalWords": 47 + }, + "yvon-sipieter": { + "id": "yvon-sipieter", + "name": "Yvon SIPIETER", + "mandates": [ + "Adjoint au maire" + ], + "portrait": "yvon-sipieter.jpg", + "totalSignificantWords": 76, + "totalWords": 95 + }, + "nora-cherki": { + "id": "nora-cherki", + "name": "Nora CHERKI", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "nora-cherki.jpg", + "totalSignificantWords": 267, + "totalWords": 403 + }, + "xavier-thierry": { + "id": "xavier-thierry", + "name": "Xavier THIERRY", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "xavier-thierry.jpg", + "totalSignificantWords": 132, + "totalWords": 144 + }, + "khadija-ahantat": { + "id": "khadija-ahantat", + "name": "Khadija AHANTAT", + "mandates": [ + "Adjointe au maire" + ], + "portrait": "khadija-ahantat.jpg", + "totalSignificantWords": 91, + "totalWords": 105 + }, + "michael-doziere": { + "id": "michael-doziere", + "name": "Michaël DOZIÈRE", + "mandates": [ + "Adjoint au maire" + ], + "portrait": "michael-doziere.jpg", + "totalSignificantWords": 75, + "totalWords": 86 + }, + "carolle-divrechy": { + "id": "carolle-divrechy", + "name": "Carolle DIVRECHY", + "mandates": [ + "Conseillère municipale" + ], + "portrait": "carolle-divrechy.jpg", + "totalSignificantWords": 81, + "totalWords": 96 + }, + "anne-colin": { + "id": "anne-colin", + "name": "Anne COLIN", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "anne-colin.jpg", + "totalSignificantWords": 129, + "totalWords": 147 + }, + "jean-marie-dupire": { + "id": "jean-marie-dupire", + "name": "Jean-Marie DUPIRE", + "mandates": [ + "Conseiller municipal" + ], + "portrait": "jean-marie-dupire.jpg", + "totalSignificantWords": 45, + "totalWords": 50 + }, + "salima-boukentar": { + "id": "salima-boukentar", + "name": "Salima BOUKENTAR", + "mandates": [ + "Conseillère municipale" + ], + "portrait": "salima-boukentar.jpg", + "totalSignificantWords": 82, + "totalWords": 91 + }, + "anissa-bouchaboun": { + "id": "anissa-bouchaboun", + "name": "Anissa BOUCHABOUN", + "mandates": [ + "Conseillère municipale d’opposition" + ], + "portrait": "anissa-bouchaboun.jpg", + "totalSignificantWords": 40, + "totalWords": 50 + }, + "anne-sophie-audegond": { + "id": "anne-sophie-audegond", + "name": "Anne-Sophie AUDEGOND", + "mandates": [ + "Conseillère municipale" + ], + "portrait": "anne-sophie-audegond.jpg", + "totalSignificantWords": 34, + "totalWords": 41 + }, + "sebastien-lanclu": { + "id": "sebastien-lanclu", + "name": "Sébastien LANCLU", + "mandates": [ + "Conseiller municipal" + ], + "portrait": "sebastien-lanclu.jpg", + "totalSignificantWords": 81, + "totalWords": 98 + }, + "maxime-decupper-laud": { + "id": "maxime-decupper-laud", + "name": "Maxime DECUPPER-LAUD", + "mandates": [ + "Conseiller municipal" + ], + "portrait": "maxime-decupper-laud.jpg", + "totalSignificantWords": 60, + "totalWords": 86 + }, + "mohamed-felouki": { + "id": "mohamed-felouki", + "name": "Mohamed FELOUKI", + "mandates": [ + "Conseiller municipal d’opposition" + ], + "portrait": "mohamed-felouki.jpg", + "totalSignificantWords": 43, + "totalWords": 50 + }, + "avida-oulahcene": { + "id": "avida-oulahcene", + "name": "Avida OULAHCENE", + "mandates": [ + "Conseillère municipale" + ], + "portrait": "avida-oulahcene.jpg", + "totalSignificantWords": 41, + "totalWords": 45 + }, + "jamila-mekki": { + "id": "jamila-mekki", + "name": "Jamila MEKKI", + "mandates": [ + "Conseillère municipale" + ], + "portrait": "jamila-mekki.jpg", + "totalSignificantWords": 74, + "totalWords": 100 + }, + "guy-lagache": { + "id": "guy-lagache", + "name": "Guy LAGACHE", + "mandates": [ + "Conseiller municipal" + ], + "portrait": "guy-lagache.jpg", + "totalSignificantWords": 83, + "totalWords": 96 + }, + "nadia-bony": { + "id": "nadia-bony", + "name": "Nadia BONY,", + "mandates": [ + "Conseillère municipale" + ], + "portrait": "nadia-bony.jpg", + "totalSignificantWords": 47, + "totalWords": 56 + }, + "yvette-wattebled": { + "id": "yvette-wattebled", + "name": "Yvette WATTEBLED", + "portrait": "default.svg", + "mandates": [], + "totalSignificantWords": 0, + "totalWords": 0 + } + }, "sentences": { "mean": { "count": 13, @@ -7,7 +578,6 @@ "min": { "value": 1, "ids": [ - "2023-02-douai-notre-ville-anne-colin", "2023-02-douai-notre-ville-anne-colin" ], "restLength": 0 @@ -15,7 +585,6 @@ "max": { "value": 24, "ids": [ - "2022-04-douai-notre-ville-frederic-chereau", "2022-04-douai-notre-ville-frederic-chereau" ], "restLength": 0 @@ -32,16 +601,14 @@ "2012-02-douai-notre-ville-cyril-carbonnel", "2012-04-douai-notre-ville-jean-pierre-divrechy", "2013-03-douai-notre-ville-jean-pierre-divrechy", - "2012-02-douai-notre-ville-cyril-carbonnel", - "2012-04-douai-notre-ville-jean-pierre-divrechy" + "2012-09-douai-notre-ville-odile-hage", + "2014-05-douai-notre-ville-guy-cannie" ], - "restLength": 184 + "restLength": 181 }, "max": { "value": 8, "ids": [ - "2020-12-douai-notre-ville-thibaut-francois", - "2021-04-douai-notre-ville-thibaut-francois", "2020-12-douai-notre-ville-thibaut-francois", "2021-04-douai-notre-ville-thibaut-francois" ], @@ -62,12 +629,11 @@ "2012-12-douai-notre-ville-monique-amghar", "2013-01-douai-notre-ville-frederic-chereau" ], - "restLength": 369 + "restLength": 362 }, "max": { "value": 7, "ids": [ - "2016-03-douai-notre-ville-guy-cannie", "2016-03-douai-notre-ville-guy-cannie" ], "restLength": 0 @@ -81,18 +647,17 @@ "min": { "value": 0, "ids": [ - "2012-09-douai-notre-ville-odile-hage", "2012-09-douai-notre-ville-odile-hage", "2014-05-douai-notre-ville-guy-cannie", "2014-07-douai-notre-ville-guy-cannie", - "2015-02-douai-notre-ville-guy-cannie" + "2015-02-douai-notre-ville-guy-cannie", + "2015-05-douai-notre-ville-guy-cannie" ], - "restLength": 299 + "restLength": 298 }, "max": { "value": 5, "ids": [ - "2022-10-douai-notre-ville-khadija-ahantat", "2022-10-douai-notre-ville-khadija-ahantat" ], "restLength": 0 @@ -112,12 +677,11 @@ "2012-06-douai-notre-ville-karine-doyen-carbonnel", "2012-07-douai-notre-ville-annick-louvion" ], - "restLength": 406 + "restLength": 397 }, "max": { "value": 7, "ids": [ - "2023-02-douai-notre-ville-salima-boukentar", "2023-02-douai-notre-ville-salima-boukentar" ], "restLength": 0 @@ -135,10 +699,10 @@ "2012-01-douai-notre-ville-monique-amghar", "2012-07-douai-notre-ville-annick-louvion", "2013-01-douai-notre-ville-frederic-chereau", - "2012-01-douai-notre-ville-monique-amghar", - "2012-07-douai-notre-ville-annick-louvion" + "2012-01-douai-notre-ville-jacques-vernier", + "2012-02-douai-notre-ville-jacques-vernier" ], - "restLength": 238 + "restLength": 235 }, "max": { "value": 4, @@ -149,7 +713,7 @@ "2021-07-douai-notre-ville-frederic-chereau", "2023-01-douai-notre-ville-frederic-chereau" ], - "restLength": 5 + "restLength": 0 } }, "neutral": { @@ -160,7 +724,6 @@ "min": { "value": 0, "ids": [ - "2023-02-douai-notre-ville-anne-colin", "2023-02-douai-notre-ville-anne-colin" ], "restLength": 0 @@ -168,7 +731,6 @@ "max": { "value": 20, "ids": [ - "2022-04-douai-notre-ville-frederic-chereau", "2022-04-douai-notre-ville-frederic-chereau" ], "restLength": 0 @@ -182,22 +744,454 @@ "min": { "value": 0, "ids": [ - "2012-01-douai-notre-ville-monique-amghar", "2012-01-douai-notre-ville-monique-amghar", "2012-02-douai-notre-ville-jacques-vernier", "2012-03-douai-notre-ville-jacques-vernier", - "2012-05-douai-notre-ville-jacques-vernier" + "2012-05-douai-notre-ville-jacques-vernier", + "2012-10-douai-notre-ville-jacques-vernier" ], - "restLength": 196 + "restLength": 195 }, "max": { "value": 6, "ids": [ - "2022-03-douai-notre-ville-frederic-chereau", "2022-03-douai-notre-ville-frederic-chereau" ], "restLength": 0 } } + }, + "presences": { + "cm-douai": [ + { + "id": "stephanie-stiernon", + "total": 22, + "present": 22, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "frederic-chereau", + "total": 22, + "present": 22, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "agnes-dupuis", + "total": 22, + "present": 22, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "mohamed-kheraki", + "total": 22, + "present": 18, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 3 + }, + { + "id": "hocine-mazy", + "total": 22, + "present": 19, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 3 + }, + { + "id": "auriane-ait-lasri", + "total": 22, + "present": 18, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 4 + }, + { + "id": "jean-michel-leroy", + "total": 22, + "present": 19, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 3 + }, + { + "id": "jean-christophe-leclercq", + "total": 22, + "present": 21, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 1 + }, + { + "id": "yvon-sipieter", + "total": 22, + "present": 22, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "khadija-ahantat", + "total": 22, + "present": 22, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "michael-doziere", + "total": 22, + "present": 19, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "marie-delattre", + "total": 22, + "present": 20, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "guy-caruyer", + "total": 22, + "present": 22, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "avida-oulahcene", + "total": 22, + "present": 15, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 6 + }, + { + "id": "carolle-divrechy", + "total": 22, + "present": 14, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 8 + }, + { + "id": "katia-bittner", + "total": 22, + "present": 21, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 1 + }, + { + "id": "jamila-mekki", + "total": 22, + "present": 18, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "yves-piquot", + "total": 22, + "present": 20, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "salima-boukentar", + "total": 22, + "present": 19, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 3 + }, + { + "id": "sebastien-lanclu", + "total": 22, + "present": 22, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "nora-cherki", + "total": 22, + "present": 18, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 4 + }, + { + "id": "maxime-decupper-laud", + "total": 22, + "present": 17, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 5 + }, + { + "id": "guy-lagache", + "total": 15, + "present": 13, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "chantal-rybak", + "total": 22, + "present": 19, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 3 + }, + { + "id": "franz-quatreboeufs", + "total": 22, + "present": 22, + "arrivedLate": 2, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "anne-colin", + "total": 22, + "present": 20, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "xavier-thierry", + "total": 22, + "present": 21, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "coline-craeye", + "total": 22, + "present": 22, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "eric-lemaitre", + "total": 22, + "present": 15, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 6 + }, + { + "id": "guy-cannie", + "total": 22, + "present": 18, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 3 + }, + { + "id": "thibaut-francois", + "total": 22, + "present": 17, + "arrivedLate": 0, + "leftBeforeTheEnd": 1, + "delegation": 5 + }, + { + "id": "francois-guiffard", + "total": 22, + "present": 15, + "arrivedLate": 1, + "leftBeforeTheEnd": 0, + "delegation": 1 + }, + { + "id": "nathalie-apers", + "total": 22, + "present": 20, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "nadia-bony", + "total": 12, + "present": 9, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 2 + }, + { + "id": "mohamed-felouki", + "total": 22, + "present": 14, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 8 + }, + { + "id": "anissa-bouchaboun", + "total": 22, + "present": 15, + "arrivedLate": 2, + "leftBeforeTheEnd": 0, + "delegation": 7 + }, + { + "id": "anne-sophie-audegond", + "total": 22, + "present": 14, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 7 + }, + { + "id": "yvette-wattebled", + "total": 22, + "present": 10, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 10 + }, + { + "id": "jean-marie-dupire", + "total": 22, + "present": 12, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 8 + }, + { + "id": "virginie-malolepszy", + "total": 10, + "present": 10, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 0 + }, + { + "id": "jessy-kaboul", + "total": 7, + "present": 6, + "arrivedLate": 0, + "leftBeforeTheEnd": 0, + "delegation": 1 + } + ] + }, + "presencesStats": { + "cm-douai": { + "presenceRatio": { + "mean": { + "count": 41, + "total": 3456.4718614718618 + }, + "min": { + "value": 45.45454545454545, + "ids": [ + "yvette-wattebled" + ], + "restLength": 0 + }, + "max": { + "value": 100, + "ids": [ + "stephanie-stiernon", + "frederic-chereau", + "agnes-dupuis", + "yvon-sipieter", + "khadija-ahantat" + ], + "restLength": 0 + } + }, + "arrivedLate": { + "mean": { + "count": 41, + "total": 12 + }, + "min": { + "value": 0, + "ids": [ + "stephanie-stiernon", + "frederic-chereau", + "agnes-dupuis", + "hocine-mazy", + "jean-michel-leroy" + ], + "restLength": 1 + }, + "max": { + "value": 2, + "ids": [ + "franz-quatreboeufs", + "anissa-bouchaboun" + ], + "restLength": 0 + } + }, + "leftBeforeTheEnd": { + "mean": { + "count": 41, + "total": 1 + }, + "min": { + "value": 0, + "ids": [ + "stephanie-stiernon", + "frederic-chereau", + "agnes-dupuis", + "mohamed-kheraki", + "hocine-mazy" + ], + "restLength": 1 + }, + "max": { + "value": 1, + "ids": [ + "thibaut-francois" + ], + "restLength": 0 + } + }, + "delegation": { + "mean": { + "count": 41, + "total": 118 + }, + "min": { + "value": 0, + "ids": [ + "stephanie-stiernon", + "frederic-chereau", + "agnes-dupuis", + "yvon-sipieter", + "khadija-ahantat" + ], + "restLength": 0 + }, + "max": { + "value": 10, + "ids": [ + "yvette-wattebled" + ], + "restLength": 0 + } + } + } } } \ No newline at end of file diff --git a/contents/groups/douai-au-coeur-eelv.json b/contents/groups/douai-au-coeur-eelv.json index 6ece4a7a..e64b97d4 100644 --- a/contents/groups/douai-au-coeur-eelv.json +++ b/contents/groups/douai-au-coeur-eelv.json @@ -5,6 +5,7 @@ "partyAbbr": "EELV", "type": "Majorité municipale", "logo": "eelv-douaisis.svg", + "totalWords": 1657, "writtings": [ { "date": "2020-09-01T00:00:00Z", @@ -1316,7 +1317,9 @@ "mandates": [ "Conseiller municipal délégué" ], - "portrait": "guy-caruyer.jpg" + "portrait": "guy-caruyer.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "jean-christophe-leclercq", @@ -1324,7 +1327,9 @@ "mandates": [ "Adjoint au maire" ], - "portrait": "jean-christophe-leclercq.jpg" + "portrait": "jean-christophe-leclercq.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "katia-bittner", @@ -1332,7 +1337,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "katia-bittner.jpg" + "portrait": "katia-bittner.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "marie-delattre", @@ -1340,7 +1347,9 @@ "mandates": [ "Adjointe au maire" ], - "portrait": "marie-delattre.jpg" + "portrait": "marie-delattre.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "stephanie-stiernon", @@ -1348,7 +1357,9 @@ "mandates": [ "Adjointe au maire" ], - "portrait": "stephanie-stiernon.jpg" + "portrait": "stephanie-stiernon.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "yves-piquot", @@ -1356,7 +1367,9 @@ "mandates": [ "Conseiller municipal" ], - "portrait": "yves-piquot.jpg" + "portrait": "yves-piquot.jpg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/douai-au-coeur-pcf.json b/contents/groups/douai-au-coeur-pcf.json index b2370743..b8c2eae6 100644 --- a/contents/groups/douai-au-coeur-pcf.json +++ b/contents/groups/douai-au-coeur-pcf.json @@ -5,6 +5,7 @@ "partyAbbr": "PCF", "type": "Majorité municipale", "logo": "pcf.svg", + "totalWords": 1559, "writtings": [ { "date": "2020-09-01T00:00:00Z", @@ -1316,7 +1317,9 @@ "mandates": [ "Adjointe au maire" ], - "portrait": "auriane-ait-lasri.jpg" + "portrait": "auriane-ait-lasri.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "jessy-kaboul", @@ -1324,7 +1327,9 @@ "mandates": [ "Adjoint au maire" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "nora-cherki", @@ -1332,7 +1337,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "nora-cherki.jpg" + "portrait": "nora-cherki.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "eric-lemaitre", @@ -1340,7 +1347,9 @@ "mandates": [ "Conseiller municipal" ], - "portrait": "eric-lemaitre.jpg" + "portrait": "eric-lemaitre.jpg", + "totalSignificantWords": 45, + "totalWords": 47 } ], "locality": "Douai", diff --git a/contents/groups/douai-au-coeur-ps.json b/contents/groups/douai-au-coeur-ps.json index 00dd1692..98cb74ae 100644 --- a/contents/groups/douai-au-coeur-ps.json +++ b/contents/groups/douai-au-coeur-ps.json @@ -5,6 +5,7 @@ "partyAbbr": "PS", "type": "Majorité municipale", "logo": "ps.png", + "totalWords": 10466, "writtings": [ { "date": "2014-05-01T00:00:00Z", @@ -3908,7 +3909,9 @@ "mandates": [ "Adjointe au maire" ], - "portrait": "agnes-dupuis.jpg" + "portrait": "agnes-dupuis.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "carolle-divrechy", @@ -3916,7 +3919,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "carolle-divrechy.jpg" + "portrait": "carolle-divrechy.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "frederic-chereau", @@ -3924,7 +3929,9 @@ "mandates": [ "Maire de Douai" ], - "portrait": "frederic-chereau.jpg" + "portrait": "frederic-chereau.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "jean-marie-dupire", @@ -3932,7 +3939,9 @@ "mandates": [ "Conseiller municipal" ], - "portrait": "jean-marie-dupire.jpg" + "portrait": "jean-marie-dupire.jpg", + "totalSignificantWords": 45, + "totalWords": 50 } ], "locality": "Douai", diff --git a/contents/groups/douai-au-coeur-se.json b/contents/groups/douai-au-coeur-se.json index 20fb3e7d..4556efb5 100644 --- a/contents/groups/douai-au-coeur-se.json +++ b/contents/groups/douai-au-coeur-se.json @@ -5,6 +5,7 @@ "partyAbbr": "SE", "type": "Majorité municipale", "logo": "douai-au-coeur.svg", + "totalWords": 1343, "writtings": [ { "date": "2020-10-01T00:00:00Z", @@ -1136,7 +1137,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "anne-sophie-audegond.jpg" + "portrait": "anne-sophie-audegond.jpg", + "totalSignificantWords": 34, + "totalWords": 41 }, { "id": "avida-oulahcene", @@ -1144,7 +1147,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "avida-oulahcene.jpg" + "portrait": "avida-oulahcene.jpg", + "totalSignificantWords": 41, + "totalWords": 45 }, { "id": "guy-lagache", @@ -1152,7 +1157,9 @@ "mandates": [ "Conseiller municipal" ], - "portrait": "guy-lagache.jpg" + "portrait": "guy-lagache.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "hocine-mazy", @@ -1160,7 +1167,9 @@ "mandates": [ "Adjoint au maire" ], - "portrait": "hocine-mazy.jpg" + "portrait": "hocine-mazy.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "jamila-mekki", @@ -1168,7 +1177,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "jamila-mekki.jpg" + "portrait": "jamila-mekki.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "jean-michel-leroy", @@ -1176,7 +1187,9 @@ "mandates": [ "Adjoint au maire" ], - "portrait": "jean-michel-leroy.jpg" + "portrait": "jean-michel-leroy.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "khadija-ahantat", @@ -1184,7 +1197,9 @@ "mandates": [ "Adjointe au maire" ], - "portrait": "khadija-ahantat.jpg" + "portrait": "khadija-ahantat.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "maxime-decupper-laud", @@ -1192,7 +1207,9 @@ "mandates": [ "Conseiller municipal" ], - "portrait": "maxime-decupper-laud.jpg" + "portrait": "maxime-decupper-laud.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "michael-doziere", @@ -1200,7 +1217,9 @@ "mandates": [ "Adjoint au maire" ], - "portrait": "michael-doziere.jpg" + "portrait": "michael-doziere.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "mohamed-kheraki", @@ -1208,7 +1227,9 @@ "mandates": [ "Adjoint au Maire" ], - "portrait": "mohamed-kheraki.jpg" + "portrait": "mohamed-kheraki.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "nadia-bony", @@ -1216,7 +1237,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "nadia-bony.jpg" + "portrait": "nadia-bony.jpg", + "totalSignificantWords": 47, + "totalWords": 56 }, { "id": "nathalie-apers", @@ -1224,7 +1247,9 @@ "mandates": [ "Adjointe au maire" ], - "portrait": "nathalie-apers.jpg" + "portrait": "nathalie-apers.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "salima-boukentar", @@ -1232,7 +1257,9 @@ "mandates": [ "Conseillère municipale" ], - "portrait": "salima-boukentar.jpg" + "portrait": "salima-boukentar.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "sebastien-lanclu", @@ -1240,7 +1267,9 @@ "mandates": [ "Conseiller municipal" ], - "portrait": "sebastien-lanclu.jpg" + "portrait": "sebastien-lanclu.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "virginie-malolepszy", @@ -1248,7 +1277,9 @@ "mandates": [ "Adjointe au maire" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 47, + "totalWords": 48 }, { "id": "yvon-sipieter", @@ -1256,7 +1287,9 @@ "mandates": [ "Adjoint au maire" ], - "portrait": "yvon-sipieter.jpg" + "portrait": "yvon-sipieter.jpg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/douai-dynamique-et-durable-dvd.json b/contents/groups/douai-dynamique-et-durable-dvd.json index 72eef36f..bc655ea5 100644 --- a/contents/groups/douai-dynamique-et-durable-dvd.json +++ b/contents/groups/douai-dynamique-et-durable-dvd.json @@ -5,6 +5,7 @@ "partyAbbr": "DVD", "type": "Élus d’opposition", "logo": "default.svg", + "totalWords": 1627, "writtings": [ { "date": "2020-09-01T00:00:00Z", @@ -1316,7 +1317,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "anissa-bouchaboun.jpg" + "portrait": "anissa-bouchaboun.jpg", + "totalSignificantWords": 40, + "totalWords": 50 }, { "id": "anne-colin", @@ -1324,7 +1327,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "anne-colin.jpg" + "portrait": "anne-colin.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "chantal-rybak", @@ -1332,7 +1337,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "chantal-rybak.jpg" + "portrait": "chantal-rybak.jpg", + "totalSignificantWords": 552, + "totalWords": 876 }, { "id": "coline-craeye", @@ -1340,7 +1347,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "coline-craeye.jpg" + "portrait": "coline-craeye.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "coline-craeye", @@ -1348,7 +1357,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "coline-craeye.jpg" + "portrait": "coline-craeye.jpg", + "totalSignificantWords": 617, + "totalWords": 1087 }, { "id": "franz-quatreboeufs", @@ -1356,7 +1367,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "franz-quatreboeufs.jpg" + "portrait": "franz-quatreboeufs.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "mohamed-felouki", @@ -1364,7 +1377,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "mohamed-felouki.jpg" + "portrait": "mohamed-felouki.jpg", + "totalSignificantWords": 43, + "totalWords": 50 }, { "id": "xavier-thierry", @@ -1372,7 +1387,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "xavier-thierry.jpg" + "portrait": "xavier-thierry.jpg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/douai-plus-belle-plus-propre-plus-sure-rn.json b/contents/groups/douai-plus-belle-plus-propre-plus-sure-rn.json index 279ee32f..66e0c455 100644 --- a/contents/groups/douai-plus-belle-plus-propre-plus-sure-rn.json +++ b/contents/groups/douai-plus-belle-plus-propre-plus-sure-rn.json @@ -5,6 +5,7 @@ "partyAbbr": "RN", "type": "Élus d’opposition", "logo": "default.svg", + "totalWords": 1446, "writtings": [ { "date": "2020-09-01T00:00:00Z", @@ -1316,7 +1317,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "guy-cannie.jpg" + "portrait": "guy-cannie.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "thibaut-francois", @@ -1324,7 +1327,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "thibaut-francois.jpg" + "portrait": "thibaut-francois.jpg", + "totalSignificantWords": 647, + "totalWords": 1274 }, { "id": "thibaut-francois", @@ -1332,7 +1337,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "thibaut-francois.jpg" + "portrait": "thibaut-francois.jpg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/douaisiens-passionnement-ump.json b/contents/groups/douaisiens-passionnement-ump.json index 9416bef4..c7a6034b 100644 --- a/contents/groups/douaisiens-passionnement-ump.json +++ b/contents/groups/douaisiens-passionnement-ump.json @@ -5,6 +5,7 @@ "partyAbbr": "UMP", "type": "Élus d’opposition", "logo": "default.svg", + "totalWords": 3753, "writtings": [ { "date": "2014-05-01T00:00:00Z", @@ -2540,7 +2541,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "chantal-rybak", @@ -2548,7 +2551,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "chantal-rybak.jpg" + "portrait": "chantal-rybak.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "cyril-carbonnel", @@ -2556,7 +2561,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "franz-quatreboeufs", @@ -2564,7 +2571,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "franz-quatreboeufs.jpg" + "portrait": "franz-quatreboeufs.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "francoise-prouvost", @@ -2572,7 +2581,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "isabelle-chatelain", @@ -2580,7 +2591,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "marie-delecambre", @@ -2588,7 +2601,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "marie-helene-quatreboeufs-niklikowski", @@ -2596,7 +2611,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/ensemble-faisons-douai-se.json b/contents/groups/ensemble-faisons-douai-se.json index ae54baa9..9654b237 100644 --- a/contents/groups/ensemble-faisons-douai-se.json +++ b/contents/groups/ensemble-faisons-douai-se.json @@ -5,6 +5,7 @@ "partyAbbr": "SE", "type": "Élus d’opposition", "logo": "default.svg", + "totalWords": 1657, "writtings": [ { "date": "2020-09-01T00:00:00Z", @@ -1316,7 +1317,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "francois-guiffard.jpg" + "portrait": "francois-guiffard.jpg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/jacques-vernier-ump.json b/contents/groups/jacques-vernier-ump.json index cde41f25..05ac2a30 100644 --- a/contents/groups/jacques-vernier-ump.json +++ b/contents/groups/jacques-vernier-ump.json @@ -5,6 +5,7 @@ "partyAbbr": "UMP", "type": "Majorité municipale", "logo": "default.svg", + "totalWords": 736, "writtings": [ { "date": "2012-01-01T00:00:00Z", @@ -633,7 +634,9 @@ "Maire de Douai", "Conseiller Régional" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/rassemblement-douai-bleu-marine-rn.json b/contents/groups/rassemblement-douai-bleu-marine-rn.json index 16da8421..f5d3e323 100644 --- a/contents/groups/rassemblement-douai-bleu-marine-rn.json +++ b/contents/groups/rassemblement-douai-bleu-marine-rn.json @@ -5,6 +5,7 @@ "partyAbbr": "RN", "type": "Élus d’opposition", "logo": "default.svg", + "totalWords": 3656, "writtings": [ { "date": "2014-05-01T00:00:00Z", @@ -2540,7 +2541,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "guy-cannie.jpg" + "portrait": "guy-cannie.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "gerard-bailliet", @@ -2548,7 +2551,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 } ], "locality": "Douai", diff --git a/contents/groups/vivons-douai-eelv.json b/contents/groups/vivons-douai-eelv.json index 6f659afd..8c76f429 100644 --- a/contents/groups/vivons-douai-eelv.json +++ b/contents/groups/vivons-douai-eelv.json @@ -5,6 +5,7 @@ "partyAbbr": "EELV", "type": "Élus d’opposition", "logo": "eelv-douaisis.svg", + "totalWords": 93, "writtings": [ { "date": "2012-11-01T00:00:00Z", @@ -164,7 +165,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 78, + "totalWords": 93 } ], "locality": "Douai", diff --git a/contents/groups/vivons-douai-pcf.json b/contents/groups/vivons-douai-pcf.json index ef30dd03..446f6038 100644 --- a/contents/groups/vivons-douai-pcf.json +++ b/contents/groups/vivons-douai-pcf.json @@ -5,6 +5,7 @@ "partyAbbr": "PCF", "type": "Élus d’opposition", "logo": "pcf.svg", + "totalWords": 114, "writtings": [ { "date": "2012-05-01T00:00:00Z", @@ -200,7 +201,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 52, + "totalWords": 52 }, { "id": "odile-hage", @@ -208,7 +211,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 60, + "totalWords": 62 } ], "locality": "Douai", diff --git a/contents/groups/vivons-douai-ps.json b/contents/groups/vivons-douai-ps.json index dd6daccc..cf1fa1ad 100644 --- a/contents/groups/vivons-douai-ps.json +++ b/contents/groups/vivons-douai-ps.json @@ -5,6 +5,7 @@ "partyAbbr": "PS", "type": "Élus d’opposition", "logo": "ps.png", + "totalWords": 814, "writtings": [ { "date": "2012-01-01T00:00:00Z", @@ -524,7 +525,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 72, + "totalWords": 77 }, { "id": "cyril-carbonnel", @@ -532,7 +535,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "frederic-chereau", @@ -540,7 +545,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "frederic-chereau.jpg" + "portrait": "frederic-chereau.jpg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "jean-pierre-divrechy", @@ -548,7 +555,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "karine-doyen-carbonnel", @@ -556,7 +565,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 75, + "totalWords": 85 }, { "id": "monique-amghar", @@ -564,7 +575,9 @@ "mandates": [ "Conseillère municipale d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 0, + "totalWords": 0 }, { "id": "rene-lavarde", @@ -572,7 +585,9 @@ "mandates": [ "Conseiller municipal d’opposition" ], - "portrait": "default.svg" + "portrait": "default.svg", + "totalSignificantWords": 64, + "totalWords": 76 } ], "locality": "Douai", diff --git a/contents/pages/index.md b/contents/pages/index.md index 2cf9bfae..3c57ebfc 100644 --- a/contents/pages/index.md +++ b/contents/pages/index.md @@ -1,6 +1,6 @@ --- -title: Que disent les élu·es de Douai ? -description: Un site qui recense toutes les tribunes des élu·es de Douai et les analyse pour en tirer l'essentiel. +title: Les élu·es de Douai passé·es à la moulinette ! +description: Savoir ce que disent et font les élu·es est essentiel pour bien choisir ses représentant·es. date: "2023-05-08T22:15:47.659Z" draft: false illustration: @@ -8,20 +8,11 @@ illustration: alt: "Bannière du site Keskidiz" --- -# Keskidiz ? +## À propos -**Les tribunes des élu·es passées à la moulinette !** - -Les tribunes présentes dans les divers magazines institutionnels ne sont pas toujours lues par les citoyen·nes. - -C'est pourquoi j'ai eu l'envie de les rendre plus attractives grâce à une technique informatique nommée **analyse du langage naturel**. - -Pour le moment, ce site propose, pour chaque élu·e et chaque formation politique, une agrégation comprenant : -- les mots les plus utilisés, -- les sentiments exprimés (positif, négatif, neutre), -- des indicateurs sur le contenu : nombre de tribunes, nombre de caractères, de phrases (questions, exclamations) et même sur la mise en forme (gras, majuscules). - -Pour le moment, seules les tribunes de la ville de Douai sont analysées. +Pour vous aider à y voir plus clair, ce site propose, pour chaque élu·e et chaque formation politique, une agrégation comprenant : +- la présence aux conseils municipaux, +- une analyse des tribunes: les mots les plus utilisés, les sentiments exprimés (positif, négatif, neutre) et des indicateurs sur le contenu : nombre de tribunes, nombre de caractères, de phrases (questions, exclamations) et même sur la mise en forme (gras, majuscules). Bien-sûr, le contenu des tribunes est reporté de la manière la plus fidèle possible et l'information est sourcée via une capture d'écran du site. diff --git a/contents/writters/agnes-dupuis.json b/contents/writters/agnes-dupuis.json index c1698843..f9d506cd 100644 --- a/contents/writters/agnes-dupuis.json +++ b/contents/writters/agnes-dupuis.json @@ -1,4 +1,5 @@ { + "totalWords": 104, "writtings": [ { "date": "2020-09-01T00:00:00Z", diff --git a/contents/writters/anissa-bouchaboun.json b/contents/writters/anissa-bouchaboun.json index 4229f4a0..9ea49b20 100644 --- a/contents/writters/anissa-bouchaboun.json +++ b/contents/writters/anissa-bouchaboun.json @@ -1,4 +1,5 @@ { + "totalWords": 50, "writtings": [ { "date": "2021-10-01T00:00:00Z", diff --git a/contents/writters/anne-colin.json b/contents/writters/anne-colin.json index ada28e52..e161093b 100644 --- a/contents/writters/anne-colin.json +++ b/contents/writters/anne-colin.json @@ -1,4 +1,5 @@ { + "totalWords": 147, "writtings": [ { "date": "2021-07-01T00:00:00Z", diff --git a/contents/writters/anne-sophie-audegond.json b/contents/writters/anne-sophie-audegond.json index fea82305..50a224d4 100644 --- a/contents/writters/anne-sophie-audegond.json +++ b/contents/writters/anne-sophie-audegond.json @@ -1,4 +1,5 @@ { + "totalWords": 41, "writtings": [ { "date": "2021-11-01T00:00:00Z", diff --git a/contents/writters/annick-louvion.json b/contents/writters/annick-louvion.json index 989a59a7..fb8ae278 100644 --- a/contents/writters/annick-louvion.json +++ b/contents/writters/annick-louvion.json @@ -1,4 +1,5 @@ { + "totalWords": 77, "writtings": [ { "date": "2012-07-01T00:00:00Z", diff --git a/contents/writters/auriane-ait-lasri.json b/contents/writters/auriane-ait-lasri.json index fd43613d..3c20733a 100644 --- a/contents/writters/auriane-ait-lasri.json +++ b/contents/writters/auriane-ait-lasri.json @@ -1,4 +1,5 @@ { + "totalWords": 1011, "writtings": [ { "date": "2020-09-01T00:00:00Z", diff --git a/contents/writters/avida-oulahcene.json b/contents/writters/avida-oulahcene.json index 77537a59..052644b1 100644 --- a/contents/writters/avida-oulahcene.json +++ b/contents/writters/avida-oulahcene.json @@ -1,4 +1,5 @@ { + "totalWords": 45, "writtings": [ { "date": "2022-02-01T00:00:00Z", diff --git a/contents/writters/brigitte-bonnaffe-leriche.json b/contents/writters/brigitte-bonnaffe-leriche.json index 85bb1f03..2cfa2a19 100644 --- a/contents/writters/brigitte-bonnaffe-leriche.json +++ b/contents/writters/brigitte-bonnaffe-leriche.json @@ -1,4 +1,5 @@ { + "totalWords": 52, "writtings": [ { "date": "2012-05-01T00:00:00Z", diff --git a/contents/writters/bruno-bufquin.json b/contents/writters/bruno-bufquin.json index 076d344e..055fc53c 100644 --- a/contents/writters/bruno-bufquin.json +++ b/contents/writters/bruno-bufquin.json @@ -1,4 +1,5 @@ { + "totalWords": 362, "writtings": [ { "date": "2017-06-01T00:00:00Z", diff --git a/contents/writters/carolle-divrechy.json b/contents/writters/carolle-divrechy.json index dd62b859..f1b0c219 100644 --- a/contents/writters/carolle-divrechy.json +++ b/contents/writters/carolle-divrechy.json @@ -1,4 +1,5 @@ { + "totalWords": 96, "writtings": [ { "date": "2021-07-01T00:00:00Z", diff --git a/contents/writters/chantal-rybak.json b/contents/writters/chantal-rybak.json index 46dea431..7ce9a5a6 100644 --- a/contents/writters/chantal-rybak.json +++ b/contents/writters/chantal-rybak.json @@ -1,4 +1,5 @@ { + "totalWords": 876, "writtings": [ { "date": "2014-12-01T00:00:00Z", diff --git a/contents/writters/coline-craeye.json b/contents/writters/coline-craeye.json index 7b45dcaf..2ec577d5 100644 --- a/contents/writters/coline-craeye.json +++ b/contents/writters/coline-craeye.json @@ -1,4 +1,5 @@ { + "totalWords": 1087, "writtings": [ { "date": "2020-09-01T00:00:00Z", diff --git a/contents/writters/cyril-carbonnel.json b/contents/writters/cyril-carbonnel.json index 2af57cc7..54d31c3b 100644 --- a/contents/writters/cyril-carbonnel.json +++ b/contents/writters/cyril-carbonnel.json @@ -1,4 +1,5 @@ { + "totalWords": 438, "writtings": [ { "date": "2012-02-01T00:00:00Z", diff --git a/contents/writters/eric-lemaitre.json b/contents/writters/eric-lemaitre.json index 2c62f03e..7b9db5dc 100644 --- a/contents/writters/eric-lemaitre.json +++ b/contents/writters/eric-lemaitre.json @@ -1,4 +1,5 @@ { + "totalWords": 47, "writtings": [ { "date": "2021-02-01T00:00:00Z", diff --git a/contents/writters/francois-guiffard.json b/contents/writters/francois-guiffard.json index 8ddb31b0..3d4de64c 100644 --- a/contents/writters/francois-guiffard.json +++ b/contents/writters/francois-guiffard.json @@ -1,4 +1,5 @@ { + "totalWords": 1657, "writtings": [ { "date": "2020-09-01T00:00:00Z", diff --git a/contents/writters/francoise-prouvost.json b/contents/writters/francoise-prouvost.json index a6ad9fa3..5a5ec814 100644 --- a/contents/writters/francoise-prouvost.json +++ b/contents/writters/francoise-prouvost.json @@ -1,4 +1,5 @@ { + "totalWords": 1352, "writtings": [ { "date": "2014-05-01T00:00:00Z", diff --git a/contents/writters/franz-quatreboeufs.json b/contents/writters/franz-quatreboeufs.json index 57f8c58a..dcd1d085 100644 --- a/contents/writters/franz-quatreboeufs.json +++ b/contents/writters/franz-quatreboeufs.json @@ -1,4 +1,5 @@ { + "totalWords": 610, "writtings": [ { "date": "2015-02-01T00:00:00Z", diff --git a/contents/writters/frederic-chereau.json b/contents/writters/frederic-chereau.json index 67c0499a..c6a22291 100644 --- a/contents/writters/frederic-chereau.json +++ b/contents/writters/frederic-chereau.json @@ -1,4 +1,5 @@ { + "totalWords": 10363, "writtings": [ { "date": "2012-10-01T00:00:00Z", diff --git a/contents/writters/gerard-bailliet.json b/contents/writters/gerard-bailliet.json index 84766773..21d9db54 100644 --- a/contents/writters/gerard-bailliet.json +++ b/contents/writters/gerard-bailliet.json @@ -1,4 +1,5 @@ { + "totalWords": 656, "writtings": [ { "date": "2014-09-01T00:00:00Z", diff --git a/contents/writters/guy-cannie.json b/contents/writters/guy-cannie.json index be3ede7c..4ce09787 100644 --- a/contents/writters/guy-cannie.json +++ b/contents/writters/guy-cannie.json @@ -1,4 +1,5 @@ { + "totalWords": 3172, "writtings": [ { "date": "2014-05-01T00:00:00Z", diff --git a/contents/writters/guy-caruyer.json b/contents/writters/guy-caruyer.json index 418cc308..5ad32572 100644 --- a/contents/writters/guy-caruyer.json +++ b/contents/writters/guy-caruyer.json @@ -1,4 +1,5 @@ { + "totalWords": 142, "writtings": [ { "date": "2021-02-01T00:00:00Z", diff --git a/contents/writters/guy-lagache.json b/contents/writters/guy-lagache.json index ceb7e089..79c0f58a 100644 --- a/contents/writters/guy-lagache.json +++ b/contents/writters/guy-lagache.json @@ -1,4 +1,5 @@ { + "totalWords": 96, "writtings": [ { "date": "2022-05-01T00:00:00Z", diff --git a/contents/writters/hocine-mazy.json b/contents/writters/hocine-mazy.json index 7e49779e..4beca385 100644 --- a/contents/writters/hocine-mazy.json +++ b/contents/writters/hocine-mazy.json @@ -1,4 +1,5 @@ { + "totalWords": 103, "writtings": [ { "date": "2021-01-01T00:00:00Z", diff --git a/contents/writters/isabelle-chatelain.json b/contents/writters/isabelle-chatelain.json index 35f4fad7..8581879d 100644 --- a/contents/writters/isabelle-chatelain.json +++ b/contents/writters/isabelle-chatelain.json @@ -1,4 +1,5 @@ { + "totalWords": 193, "writtings": [ { "date": "2017-10-01T00:00:00Z", diff --git a/contents/writters/jackie-avenel.json b/contents/writters/jackie-avenel.json index 13bcbfb1..b0570da8 100644 --- a/contents/writters/jackie-avenel.json +++ b/contents/writters/jackie-avenel.json @@ -1,4 +1,5 @@ { + "totalWords": 93, "writtings": [ { "date": "2012-11-01T00:00:00Z", diff --git a/contents/writters/jacques-vernier.json b/contents/writters/jacques-vernier.json index 2b4a5a23..f305600a 100644 --- a/contents/writters/jacques-vernier.json +++ b/contents/writters/jacques-vernier.json @@ -1,4 +1,5 @@ { + "totalWords": 736, "writtings": [ { "date": "2012-01-01T00:00:00Z", diff --git a/contents/writters/jamila-mekki.json b/contents/writters/jamila-mekki.json index 585dcf1b..d4102046 100644 --- a/contents/writters/jamila-mekki.json +++ b/contents/writters/jamila-mekki.json @@ -1,4 +1,5 @@ { + "totalWords": 100, "writtings": [ { "date": "2022-03-01T00:00:00Z", diff --git a/contents/writters/jean-christophe-leclercq.json b/contents/writters/jean-christophe-leclercq.json index 015d30d2..cac9c55a 100644 --- a/contents/writters/jean-christophe-leclercq.json +++ b/contents/writters/jean-christophe-leclercq.json @@ -1,4 +1,5 @@ { + "totalWords": 197, "writtings": [ { "date": "2021-01-01T00:00:00Z", diff --git a/contents/writters/jean-marie-dupire.json b/contents/writters/jean-marie-dupire.json index 9bfede8c..f486b8f6 100644 --- a/contents/writters/jean-marie-dupire.json +++ b/contents/writters/jean-marie-dupire.json @@ -1,4 +1,5 @@ { + "totalWords": 50, "writtings": [ { "date": "2021-09-01T00:00:00Z", diff --git a/contents/writters/jean-michel-leroy.json b/contents/writters/jean-michel-leroy.json index b0d9dc7f..92d482ce 100644 --- a/contents/writters/jean-michel-leroy.json +++ b/contents/writters/jean-michel-leroy.json @@ -1,4 +1,5 @@ { + "totalWords": 96, "writtings": [ { "date": "2021-02-01T00:00:00Z", diff --git a/contents/writters/jean-pierre-divrechy.json b/contents/writters/jean-pierre-divrechy.json index fd373f0c..19d41d10 100644 --- a/contents/writters/jean-pierre-divrechy.json +++ b/contents/writters/jean-pierre-divrechy.json @@ -1,4 +1,5 @@ { + "totalWords": 116, "writtings": [ { "date": "2012-04-01T00:00:00Z", diff --git a/contents/writters/jessy-kaboul.json b/contents/writters/jessy-kaboul.json index 23b6d080..ecc78d98 100644 --- a/contents/writters/jessy-kaboul.json +++ b/contents/writters/jessy-kaboul.json @@ -1,4 +1,5 @@ { + "totalWords": 98, "writtings": [ { "date": "2020-12-01T00:00:00Z", diff --git a/contents/writters/karine-doyen-carbonnel.json b/contents/writters/karine-doyen-carbonnel.json index 0b3991e2..f71ba312 100644 --- a/contents/writters/karine-doyen-carbonnel.json +++ b/contents/writters/karine-doyen-carbonnel.json @@ -1,4 +1,5 @@ { + "totalWords": 85, "writtings": [ { "date": "2012-06-01T00:00:00Z", diff --git a/contents/writters/katia-bittner.json b/contents/writters/katia-bittner.json index 81875721..1ae46197 100644 --- a/contents/writters/katia-bittner.json +++ b/contents/writters/katia-bittner.json @@ -1,4 +1,5 @@ { + "totalWords": 316, "writtings": [ { "date": "2020-10-01T00:00:00Z", diff --git a/contents/writters/khadija-ahantat.json b/contents/writters/khadija-ahantat.json index 00c681fe..bff60bc7 100644 --- a/contents/writters/khadija-ahantat.json +++ b/contents/writters/khadija-ahantat.json @@ -1,4 +1,5 @@ { + "totalWords": 105, "writtings": [ { "date": "2021-04-01T00:00:00Z", diff --git a/contents/writters/marie-delattre.json b/contents/writters/marie-delattre.json index 101d0c9b..29dda8c1 100644 --- a/contents/writters/marie-delattre.json +++ b/contents/writters/marie-delattre.json @@ -1,4 +1,5 @@ { + "totalWords": 296, "writtings": [ { "date": "2020-11-01T00:00:00Z", diff --git a/contents/writters/marie-delecambre.json b/contents/writters/marie-delecambre.json index 4852e38b..b90e389b 100644 --- a/contents/writters/marie-delecambre.json +++ b/contents/writters/marie-delecambre.json @@ -1,4 +1,5 @@ { + "totalWords": 578, "writtings": [ { "date": "2014-11-01T00:00:00Z", diff --git a/contents/writters/marie-helene-quatreboeufs-niklikowski.json b/contents/writters/marie-helene-quatreboeufs-niklikowski.json index 04558aa4..2c6002c5 100644 --- a/contents/writters/marie-helene-quatreboeufs-niklikowski.json +++ b/contents/writters/marie-helene-quatreboeufs-niklikowski.json @@ -1,4 +1,5 @@ { + "totalWords": 226, "writtings": [ { "date": "2014-10-01T00:00:00Z", diff --git a/contents/writters/maxime-decupper-laud.json b/contents/writters/maxime-decupper-laud.json index 5cdbb46c..72453016 100644 --- a/contents/writters/maxime-decupper-laud.json +++ b/contents/writters/maxime-decupper-laud.json @@ -1,4 +1,5 @@ { + "totalWords": 86, "writtings": [ { "date": "2022-01-01T00:00:00Z", diff --git a/contents/writters/michael-doziere.json b/contents/writters/michael-doziere.json index 4313906c..8cc614c9 100644 --- a/contents/writters/michael-doziere.json +++ b/contents/writters/michael-doziere.json @@ -1,4 +1,5 @@ { + "totalWords": 86, "writtings": [ { "date": "2021-05-01T00:00:00Z", diff --git a/contents/writters/mohamed-felouki.json b/contents/writters/mohamed-felouki.json index de83455f..49dab5a2 100644 --- a/contents/writters/mohamed-felouki.json +++ b/contents/writters/mohamed-felouki.json @@ -1,4 +1,5 @@ { + "totalWords": 50, "writtings": [ { "date": "2022-01-01T00:00:00Z", diff --git a/contents/writters/mohamed-kheraki.json b/contents/writters/mohamed-kheraki.json index 0a7cc9fd..2d93953c 100644 --- a/contents/writters/mohamed-kheraki.json +++ b/contents/writters/mohamed-kheraki.json @@ -1,4 +1,5 @@ { + "totalWords": 102, "writtings": [ { "date": "2020-10-01T00:00:00Z", diff --git a/contents/writters/monique-amghar.json b/contents/writters/monique-amghar.json index cad3fbb3..4487d1b1 100644 --- a/contents/writters/monique-amghar.json +++ b/contents/writters/monique-amghar.json @@ -1,4 +1,5 @@ { + "totalWords": 156, "writtings": [ { "date": "2012-01-01T00:00:00Z", diff --git a/contents/writters/nadia-bony.json b/contents/writters/nadia-bony.json index 6d5f712d..f9b1e20e 100644 --- a/contents/writters/nadia-bony.json +++ b/contents/writters/nadia-bony.json @@ -1,4 +1,5 @@ { + "totalWords": 56, "writtings": [ { "date": "2023-07-01T00:00:00Z", diff --git a/contents/writters/nathalie-apers.json b/contents/writters/nathalie-apers.json index ea307fe0..735d7ca9 100644 --- a/contents/writters/nathalie-apers.json +++ b/contents/writters/nathalie-apers.json @@ -1,4 +1,5 @@ { + "totalWords": 95, "writtings": [ { "date": "2020-12-01T00:00:00Z", diff --git a/contents/writters/nora-cherki.json b/contents/writters/nora-cherki.json index 0ea4fc62..ef803e81 100644 --- a/contents/writters/nora-cherki.json +++ b/contents/writters/nora-cherki.json @@ -1,4 +1,5 @@ { + "totalWords": 403, "writtings": [ { "date": "2021-03-01T00:00:00Z", diff --git a/contents/writters/odile-hage.json b/contents/writters/odile-hage.json index 2ee476b5..c61f11bb 100644 --- a/contents/writters/odile-hage.json +++ b/contents/writters/odile-hage.json @@ -1,4 +1,5 @@ { + "totalWords": 62, "writtings": [ { "date": "2012-09-01T00:00:00Z", diff --git a/contents/writters/rene-lavarde.json b/contents/writters/rene-lavarde.json index cbb99a71..81dd5eae 100644 --- a/contents/writters/rene-lavarde.json +++ b/contents/writters/rene-lavarde.json @@ -1,4 +1,5 @@ { + "totalWords": 76, "writtings": [ { "date": "2012-03-01T00:00:00Z", diff --git a/contents/writters/salima-boukentar.json b/contents/writters/salima-boukentar.json index 579bfb15..29af1657 100644 --- a/contents/writters/salima-boukentar.json +++ b/contents/writters/salima-boukentar.json @@ -1,4 +1,5 @@ { + "totalWords": 91, "writtings": [ { "date": "2021-10-01T00:00:00Z", diff --git a/contents/writters/sebastien-lanclu.json b/contents/writters/sebastien-lanclu.json index d77e41b9..1b20bfdc 100644 --- a/contents/writters/sebastien-lanclu.json +++ b/contents/writters/sebastien-lanclu.json @@ -1,4 +1,5 @@ { + "totalWords": 98, "writtings": [ { "date": "2021-12-01T00:00:00Z", diff --git a/contents/writters/stephanie-stiernon.json b/contents/writters/stephanie-stiernon.json index d5f10230..6659bab9 100644 --- a/contents/writters/stephanie-stiernon.json +++ b/contents/writters/stephanie-stiernon.json @@ -1,4 +1,5 @@ { + "totalWords": 457, "writtings": [ { "date": "2020-09-01T00:00:00Z", diff --git a/contents/writters/thibaut-francois.json b/contents/writters/thibaut-francois.json index c9cfb2a8..3ce72370 100644 --- a/contents/writters/thibaut-francois.json +++ b/contents/writters/thibaut-francois.json @@ -1,4 +1,5 @@ { + "totalWords": 1274, "writtings": [ { "date": "2020-09-01T00:00:00Z", diff --git a/contents/writters/virginie-malolepszy.json b/contents/writters/virginie-malolepszy.json index 126ebd67..8e5cf456 100644 --- a/contents/writters/virginie-malolepszy.json +++ b/contents/writters/virginie-malolepszy.json @@ -1,4 +1,5 @@ { + "totalWords": 48, "writtings": [ { "date": "2020-11-01T00:00:00Z", diff --git a/contents/writters/xavier-thierry.json b/contents/writters/xavier-thierry.json index 1edcec73..f3688230 100644 --- a/contents/writters/xavier-thierry.json +++ b/contents/writters/xavier-thierry.json @@ -1,4 +1,5 @@ { + "totalWords": 144, "writtings": [ { "date": "2021-03-01T00:00:00Z", diff --git a/contents/writters/yves-piquot.json b/contents/writters/yves-piquot.json index b39bf6e6..d984ef62 100644 --- a/contents/writters/yves-piquot.json +++ b/contents/writters/yves-piquot.json @@ -1,4 +1,5 @@ { + "totalWords": 249, "writtings": [ { "date": "2020-12-01T00:00:00Z", diff --git a/contents/writters/yvon-sipieter.json b/contents/writters/yvon-sipieter.json index fc6cc010..8cb04075 100644 --- a/contents/writters/yvon-sipieter.json +++ b/contents/writters/yvon-sipieter.json @@ -1,4 +1,5 @@ { + "totalWords": 95, "writtings": [ { "date": "2021-03-01T00:00:00Z", diff --git a/src/pages/[[...slug]].tsx b/src/pages/[...slug].tsx similarity index 98% rename from src/pages/[[...slug]].tsx rename to src/pages/[...slug].tsx index f0105dae..ebf5549c 100644 --- a/src/pages/[[...slug]].tsx +++ b/src/pages/[...slug].tsx @@ -24,7 +24,7 @@ type Entry = { } & PageFrontmatterMetadata; type Params = { slug: string[] }; -type Props = { entry: Entry }; +export type Props = { entry: Entry }; const Page = ({ entry }: Props) => { return ( diff --git a/src/pages/elu-es/[id].tsx b/src/pages/elu-es/[id].tsx index fdd5560b..394fc60d 100644 --- a/src/pages/elu-es/[id].tsx +++ b/src/pages/elu-es/[id].tsx @@ -113,7 +113,7 @@ const Entry = ({ entry }: Props) => { {entry.presences[instance].map((presence) => ( - + {new Intl.DateTimeFormat("fr-FR", { year: "numeric", diff --git a/src/pages/index.tsx b/src/pages/index.tsx new file mode 100644 index 00000000..a76d124f --- /dev/null +++ b/src/pages/index.tsx @@ -0,0 +1,172 @@ +import Layout from "../layouts/main"; +import ContentBlock from "../components/contentBlock"; +import { fixText } from "../utils/text"; +import { renderMarkdown } from "../utils/markdown"; +import Heading1 from "../components/h1"; +import Heading2 from "../components/h2"; +import Heading3 from "../components/h3"; +import Paragraph from "../components/p"; +import { readGlobalStats } from "../utils/globalStats"; +import Strong from "../components/strong"; +import { + getStaticProps as baseGetStaticProps, + type Props as BaseProps, +} from "./[...slug]"; +import type { GetStaticProps } from "next"; +import type { StatsSummary } from "../utils/writters"; +import UnorderedList from "../components/ul"; +import ListItem from "../components/li"; +import Anchor from "../components/a"; + +type Props = BaseProps & { + globalStats: StatsSummary; +}; + +const Page = ({ entry, globalStats }: Props) => ( + + + {entry.title} + + {entry.description} + + + 🏆 Les bons élèves +
+
+ ✅ Assiduité + + {(globalStats.presences["cm-douai"] || []) + .sort((presenceA, presenceB) => { + const ratioA = presenceA.present / presenceA.total; + const ratioB = presenceB.present / presenceB.total; + + return ratioA > ratioB ? -1 : ratioA < ratioB ? 1 : 0; + }) + .slice(0, 10) + .map((presence) => ( + + + {globalStats.authors[presence.id].name} + +  : {((presence.present / presence.total) * 100).toFixed(2)}% + + ))} + +
+
+ ✍️ Variété de vocabulaire + + {Object.keys(globalStats.authors) + .sort((authorIdA, authorIdB) => { + const ratioA = + globalStats.authors[authorIdA].totalSignificantWords / + globalStats.authors[authorIdA].totalWords; + const ratioB = + globalStats.authors[authorIdB].totalSignificantWords / + globalStats.authors[authorIdB].totalWords; + + return ratioA > ratioB ? -1 : ratioA < ratioB ? 1 : 0; + }) + .slice(0, 10) + .map((authorId) => ( + + + {globalStats.authors[authorId].name} + +  :{" "} + {( + globalStats.authors[authorId].totalSignificantWords / + globalStats.authors[authorId].totalWords + ).toFixed(2)} + + ))} + +
+
+ 🤔 Les mauvais élèves +
+
+ 🤷 Absentéisme + + {(globalStats.presences["cm-douai"] || []) + .sort((presenceA, presenceB) => { + const absenceA = presenceA.total - presenceA.present; + const absenceB = presenceB.total - presenceB.present; + + return absenceA > absenceB ? -1 : absenceA < absenceB ? 1 : 0; + }) + .slice(0, 10) + .map((presence) => ( + + + {globalStats.authors[presence.id].name} + +  : {((presence.present / presence.total) * 100).toFixed(2)}% + + ))} + +
+
+ 🤦‍♂ Absences sans pouvoir + + {(globalStats.presences["cm-douai"] || []) + .sort((presenceA, presenceB) => { + const absenceA = + presenceA.total - presenceA.present - presenceA.delegation; + const absenceB = + presenceB.total - presenceB.present - presenceB.delegation; + + return absenceA > absenceB ? -1 : absenceA < absenceB ? 1 : 0; + }) + .slice(0, 10) + .map((presence) => ( + + + {globalStats.authors[presence.id].name} + +  : {presence.total - presence.present - presence.delegation} + + ))} + +
+
+ {renderMarkdown({ index: 0 }, entry.content)} +
+
+ +
+); + +export default Page; + +export const getStaticProps: GetStaticProps = async () => { + const baseProps = await baseGetStaticProps({ params: { slug: [] } }); + const globalStats = await readGlobalStats(); + + return { + props: { + ...("props" in baseProps ? baseProps.props : {}), + globalStats, + } as Props, + }; +}; diff --git a/src/utils/stats.ts b/src/utils/stats.ts new file mode 100644 index 00000000..f9727875 --- /dev/null +++ b/src/utils/stats.ts @@ -0,0 +1,141 @@ +export type OccurenceItem = { + id: string; + date: string; + count: number; +}; + +export type StatItem = { + mean: { count: number; total: number }; + min: { value: number; ids: string[]; restLength?: number }; + max: { value: number; ids: string[]; restLength?: number }; +}; + +export function computeStats(occurences: OccurenceItem[]): StatItem { + return { + mean: { + count: occurences.reduce((total, { count }) => total + count, 0), + total: occurences.length, + }, + min: occurences.reduce( + (actualMin, { count: value, id }) => { + if (actualMin.value > value) { + return { + value, + ids: [id], + }; + } + if (actualMin.value === value) { + return { + value, + ids: [...actualMin.ids, id], + }; + } + return actualMin; + }, + { value: Infinity, ids: [] } as StatItem["min"] + ), + max: occurences.reduce( + (actualMax, { count: value, id }) => { + if (actualMax.value < value) { + return { + value, + ids: [id], + }; + } + if (actualMax.value === value) { + return { + value, + ids: [...actualMax.ids, id], + }; + } + return actualMax; + }, + { value: -Infinity, ids: [] } as StatItem["max"] + ), + }; +} + +export function createBaseStatsItem( + firstValue?: number, + id?: string +): StatItem { + if (typeof firstValue === "number") { + if (typeof id !== "string") { + throw new Error("E_BAD_ARGS"); + } + return { + mean: { count: 1, total: firstValue }, + min: { value: firstValue, ids: [id] }, + max: { value: firstValue, ids: [id] }, + }; + } + + return { + mean: { count: 0, total: 0 }, + min: { value: Infinity, ids: [] }, + max: { value: -Infinity, ids: [] }, + }; +} + +export function aggregatesStats(statsItem: StatItem, statsObject: StatItem) { + statsObject.mean.total += statsItem.mean.total; + statsObject.mean.count += 1; + + if (statsObject.min.value > statsItem.min.value) { + statsObject.min = statsItem.min; + } else if (statsObject.min.value === statsItem.min.value) { + statsObject.min = { + value: statsItem.min.value, + ids: [...statsObject.min.ids, ...statsItem.min.ids], + }; + } + + if (statsObject.max.value < statsItem.max.value) { + statsObject.max = statsItem.max; + } else if (statsObject.max.value === statsItem.max.value) { + statsObject.max = { + value: statsItem.max.value, + ids: [...statsObject.max.ids, ...statsItem.max.ids], + }; + } +} + +export function shrinkStats(statsItem: StatItem): StatItem { + return { + mean: statsItem.mean, + min: { + value: statsItem.min.value, + ids: statsItem.min.ids.slice(0, 5), + restLength: statsItem.min.ids.slice(5).length, + }, + max: { + value: statsItem.max.value, + ids: statsItem.max.ids.slice(0, 5), + restLength: statsItem.max.ids.slice(5).length, + }, + }; +} + +export function sortByDate( + authorA: T, + authorB: T +): number { + if (Date.parse(authorA.date) < Date.parse(authorB.date)) { + return -1; + } else if (Date.parse(authorA.date) > Date.parse(authorB.date)) { + return 1; + } + return 0; +} + +export function sortByName( + authorA: T, + authorB: T +): number { + if (authorA.name < authorB.name) { + return -1; + } else if (authorA.name > authorB.name) { + return 1; + } + return 0; +} diff --git a/src/utils/tribunes.ts b/src/utils/tribunes.ts index 87edbf46..54c0a8cb 100644 --- a/src/utils/tribunes.ts +++ b/src/utils/tribunes.ts @@ -6,6 +6,8 @@ export type Author = { name: string; mandates: string[]; portrait: string; + totalSignificantWords: number; + totalWords: number; }; export type BaseGroup = { id: string; diff --git a/src/utils/writters.ts b/src/utils/writters.ts index 67e3db66..db1b2f1b 100644 --- a/src/utils/writters.ts +++ b/src/utils/writters.ts @@ -1,5 +1,6 @@ import { toASCIIString } from "./ascii"; import { pathJoin, readDir, readJSON } from "./files"; +import type { OccurenceItem, StatItem } from "./stats"; import type { Author, BaseGroup } from "./tribunes"; export type PresenceItem = { @@ -16,11 +17,13 @@ export type PresenceStatItem = { leftBeforeTheEnd: number; delegation: number; }; -export type OccurenceItem = { - id: string; - date: string; - count: number; +export type PresenceStatsSummary = { + presenceRatio: StatItem; + arrivedLate: StatItem; + leftBeforeTheEnd: StatItem; + delegation: StatItem; }; + export type SentimentOccurenceItem = { id: string; date: string; @@ -28,11 +31,6 @@ export type SentimentOccurenceItem = { neutral: number; negative: number; }; -export type StatItem = { - mean: { count: number; total: number }; - min: { value: number; ids: string[]; restLength?: number }; - max: { value: number; ids: string[]; restLength?: number }; -}; export type StatsSummary = { sentences: StatItem; @@ -45,6 +43,14 @@ export type StatsSummary = { neutral: StatItem; negative: StatItem; }; + authors: Record; + presences?: Record< + string, + (PresenceStatItem & { + id: string; + })[] + >; + presencesStats?: Record; }; export type StatsData = { writtings: {