fix: aligne le référentiel d'émotions sur le sujet et complète le dossier

Référentiel d'émotions (conformité au sujet) :
- 6 émotions de base (suppression d'« Amour ») et 36 sous-émotions
- libellés exacts du sujet (Surprise dédupliquée : Étonnement listé 2x)
- propagation du décompte 6+36 (CLAUDE.md, plan oral, slides, dossier, mobile)

Corrections dossier (grille d'évaluation Bloc INFCDAAL1) :
- ajout d'un sommaire
- contraintes budget 75 000 EUR et délai 12 mois (chiffres du sujet)
- table des parties prenantes et de leur communication (§4.1)
- mockup du module Informations (les 3 modules ont désormais une maquette)
- cardinalités du MCD agrandies et lisibles
- chiffrement reformulé honnêtement (bcrypt aujourd'hui, AES-256 prévu en prod HDS)
- dossier maintenu à 20 pages (limite respectée)

Vérifs : backend 15 tests, mobile tsc 0, seeder 6+36.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Azmog
2026-06-18 20:27:33 +02:00
parent 6f5b8182ca
commit 91df66852e
11 changed files with 178 additions and 72 deletions
Binary file not shown.
+2 -2
View File
@@ -48,8 +48,8 @@ Cesizen/
| Configurer les émotions (2 niveaux) | Admin | ✅ | N/A |
### Hiérarchie des émotions (seed)
7 émotions de base (niveau 1) avec 33 sous-émotions (niveau 2) :
Joie, Tristesse, Colère, Peur, Dégoût, Surprise, Amour.
6 émotions de base (niveau 1) avec 36 sous-émotions (niveau 2), conformes au référentiel du sujet :
Joie, Colère, Peur, Tristesse, Surprise, Dégoût.
## Grille de priorisation des besoins
Critères utilisés : Complexité (0-3), Valeur ajoutée Ministère (0-3), Valeur ajoutée Utilisateur (0-3), Nécessité (0-2), Interdépendance (0-2). Total sur 15.
+2 -2
View File
@@ -16,7 +16,7 @@
| **0:00 – 2:00** (2′) | 1 — 2 | **Introduction** | Se présenter. Annoncer le commanditaire (Ministère) et l'objet : une plateforme grand public de santé mentale. Donner le fil rouge : « je vais dérouler le recueil du besoin, la priorisation, la réponse fonctionnelle, puis la modélisation technique et la conformité RGPD. » Présenter le sommaire (slide 2). |
| **2:00 – 5:00** (3′) | 3 — 4 | **Contexte, enjeux, parties prenantes** | Rappeler l'enjeu sociétal (22 % des Français, SPF 2023) et la stigmatisation. Énoncer les 4 objectifs stratégiques. Présenter les parties prenantes et les 3 acteurs (Visiteur, Utilisateur, Administrateur). Insister : « le besoin a été **reformulé**, pas recopié. » |
| **5:00 – 7:00** (2′) | 5 — 6 | **Besoins & priorisation** | Périmètre : 2 modules obligatoires + Tracker au choix ; modules écartés assumés. Présenter la grille pondérée /15 (5 critères). Conclusion argumentée : « le Tracker cumule 4 fonctionnalités à 9-10/15, c'est le module au choix le plus rentable. » |
| **7:00 – 12:00** (5′) | 7 — 8 — 9 | **Réponse fonctionnelle** | Module Comptes : JWT, RGPD, admin (slide 7 + maquette). Module Informations : feeds, modération, slug auto (slide 8). Module Tracker : wizard 3 étapes, journal, rapports 4 périodes, 7+33 émotions (slide 9 + maquettes). Montrer que chaque écran répond à un besoin précis. |
| **7:00 – 12:00** (5′) | 7 — 8 — 9 | **Réponse fonctionnelle** | Module Comptes : JWT, RGPD, admin (slide 7 + maquette). Module Informations : feeds, modération, slug auto (slide 8). Module Tracker : wizard 3 étapes, journal, rapports 4 périodes, 6+36 émotions (slide 9 + maquettes). Montrer que chaque écran répond à un besoin précis. |
| **12:00 – 16:00** (4′) | 10 — 11 — 12 | **Modélisation** | Cas d'usage UML (slide 10) : couverture par acteur. MCD Merise (slide 11) : 8 entités, cardinalités, hiérarchie d'émotions auto-référencée. Architecture MVC découplée (slide 12) : 1 API REST Laravel → 2 clients ; justifier le pattern (testabilité, évolutivité, non-duplication). |
| **16:00 – 17:30** (1′30) | 13 | **RGPD & données sensibles** | Données de santé = sensibles (art. 9). Consentement, droits CNIL (export/anonymisation), soft delete. Sécurité : chiffrement AES-256/TLS, JWT, HDS, table audits. |
| **17:30 – 19:00** (1′30) | 14 | **Prototype & perspectives** | Prototype fonctionnel (Laravel + Next.js + Expo + Docker). Ouverture : activer les modules écartés sans réécrire le modèle, Open Data, Mon Espace Santé (FHIR), i18n. |
@@ -49,7 +49,7 @@
> Le besoin est un journal personnel unique ; le tracker est créé automatiquement à l'inscription. Le modèle reste extensible (passer en 1-N) si un jour on veut plusieurs journaux thématiques.
**Q7. Comment gérez-vous la hiérarchie d'émotions à 2 niveaux ?**
> Une seule table `emotions` avec auto-référence `parent_id` : niveau 1 = parent_id NULL, niveau 2 = parent_id renseigné. 7 émotions de base + 33 sous-émotions. L'admin la configure via le CRUD émotions.
> Une seule table `emotions` avec auto-référence `parent_id` : niveau 1 = parent_id NULL, niveau 2 = parent_id renseigné. 6 émotions de base + 36 sous-émotions (référentiel du sujet). L'admin la configure via le CRUD émotions.
### Données & sécurité (RGPD)
**Q8. Les données émotionnelles sont sensibles — comment êtes-vous conforme ?**
Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 45 KiB

+42 -42
View File
@@ -12,30 +12,22 @@ class EmotionSeeder extends Seeder
*/
public function run(): void
{
// Référentiel d'émotions conforme au sujet détaillé CESIZen (§7) :
// 6 émotions de base (niveau 1) et leurs sous-émotions (niveau 2).
// La colonne « Surprise » du sujet liste « Étonnement » en double (coquille) :
// l'occurrence est dédupliquée ici. Total : 36 sous-émotions.
$emotions = [
[
'nom' => 'Joie',
'couleur' => '#FFD700',
'icone' => '😊',
'sous_emotions' => [
['nom' => 'Bonheur', 'couleur' => '#FFE44D'],
['nom' => 'Gratitude', 'couleur' => '#FFEB70'],
['nom' => 'Sérénité', 'couleur' => '#FFF0A0'],
['nom' => 'Enthousiasme', 'couleur' => '#FFE333'],
['nom' => 'Fierté', 'couleur' => '#FFED80'],
['nom' => 'Espoir', 'couleur' => '#FFF4B3'],
],
],
[
'nom' => 'Tristesse',
'couleur' => '#4169E1',
'icone' => '😢',
'sous_emotions' => [
['nom' => 'Mélancolie', 'couleur' => '#6A8BE9'],
['nom' => 'Solitude', 'couleur' => '#7D9BED'],
['nom' => 'Déception', 'couleur' => '#90ABF1'],
['nom' => 'Nostalgie', 'couleur' => '#A3BBF5'],
['nom' => 'Chagrin', 'couleur' => '#5A7DE5'],
['nom' => 'Fierté', 'couleur' => '#FFE44D'],
['nom' => 'Contentement', 'couleur' => '#FFEB70'],
['nom' => 'Enchantement', 'couleur' => '#FFF0A0'],
['nom' => 'Excitation', 'couleur' => '#FFE333'],
['nom' => 'Émerveillement', 'couleur' => '#FFED80'],
['nom' => 'Gratitude', 'couleur' => '#FFF4B3'],
],
],
[
@@ -45,9 +37,10 @@ class EmotionSeeder extends Seeder
'sous_emotions' => [
['nom' => 'Frustration', 'couleur' => '#E34363'],
['nom' => 'Irritation', 'couleur' => '#E9637F'],
['nom' => 'Agacement', 'couleur' => '#EF839B'],
['nom' => 'Rage', 'couleur' => '#E23355'],
['nom' => 'Indignation', 'couleur' => '#E85373'],
['nom' => 'Rage', 'couleur' => '#EF839B'],
['nom' => 'Ressentiment', 'couleur' => '#E23355'],
['nom' => 'Agacement', 'couleur' => '#E85373'],
['nom' => 'Hostilité', 'couleur' => '#EE93A7'],
],
],
[
@@ -55,22 +48,25 @@ class EmotionSeeder extends Seeder
'couleur' => '#9932CC',
'icone' => '😰',
'sous_emotions' => [
['nom' => 'Anxiété', 'couleur' => '#AD5BD6'],
['nom' => 'Inquiétude', 'couleur' => '#B96FDC'],
['nom' => 'Panique', 'couleur' => '#C583E2'],
['nom' => 'Stress', 'couleur' => '#D197E8'],
['nom' => 'Appréhension', 'couleur' => '#DDABEE'],
['nom' => 'Inquiétude', 'couleur' => '#AD5BD6'],
['nom' => 'Anxiété', 'couleur' => '#B96FDC'],
['nom' => 'Terreur', 'couleur' => '#C583E2'],
['nom' => 'Appréhension', 'couleur' => '#D197E8'],
['nom' => 'Panique', 'couleur' => '#DDABEE'],
['nom' => 'Crainte', 'couleur' => '#C97FE0'],
],
],
[
'nom' => 'Dégoût',
'couleur' => '#228B22',
'icone' => '🤢',
'nom' => 'Tristesse',
'couleur' => '#4169E1',
'icone' => '😢',
'sous_emotions' => [
['nom' => 'Aversion', 'couleur' => '#4DA64D'],
['nom' => 'Répulsion', 'couleur' => '#66B366'],
['nom' => 'Mépris', 'couleur' => '#80C080'],
['nom' => 'Écœurement', 'couleur' => '#3D9C3D'],
['nom' => 'Chagrin', 'couleur' => '#6A8BE9'],
['nom' => 'Mélancolie', 'couleur' => '#7D9BED'],
['nom' => 'Abattement', 'couleur' => '#90ABF1'],
['nom' => 'Désespoir', 'couleur' => '#A3BBF5'],
['nom' => 'Solitude', 'couleur' => '#5A7DE5'],
['nom' => 'Dépression', 'couleur' => '#87A1EF'],
],
],
[
@@ -80,19 +76,23 @@ class EmotionSeeder extends Seeder
'sous_emotions' => [
['nom' => 'Étonnement', 'couleur' => '#FFA333'],
['nom' => 'Stupéfaction', 'couleur' => '#FFB666'],
['nom' => 'Émerveillement', 'couleur' => '#FFC999'],
['nom' => 'Choc', 'couleur' => '#FF9A1A'],
['nom' => 'Sidération', 'couleur' => '#FFC999'],
['nom' => 'Incrédule', 'couleur' => '#FF9A1A'],
['nom' => 'Émerveillement', 'couleur' => '#FFAD4D'],
['nom' => 'Confusion', 'couleur' => '#FFC080'],
],
],
[
'nom' => 'Amour',
'couleur' => '#FF69B4',
'icone' => '💕',
'nom' => 'Dégoût',
'couleur' => '#228B22',
'icone' => '🤢',
'sous_emotions' => [
['nom' => 'Tendresse', 'couleur' => '#FF87C3'],
['nom' => 'Affection', 'couleur' => '#FFA5D2'],
['nom' => 'Compassion', 'couleur' => '#FFC3E1'],
['nom' => 'Admiration', 'couleur' => '#FF96CA'],
['nom' => 'Répulsion', 'couleur' => '#4DA64D'],
['nom' => 'Déplaisir', 'couleur' => '#66B366'],
['nom' => 'Nausée', 'couleur' => '#80C080'],
['nom' => 'Dédain', 'couleur' => '#3D9C3D'],
['nom' => 'Horreur', 'couleur' => '#5CAC5C'],
['nom' => 'Dégoût profond', 'couleur' => '#73BA73'],
],
],
];
+78 -14
View File
@@ -35,6 +35,10 @@ _UNICODE_FIX = {
'≤': '<=',
'≥': '>=',
'°': 'deg',
'œ': 'oe',
'Œ': 'OE',
'æ': 'ae',
'Æ': 'AE',
}
def _safe(s):
@@ -265,8 +269,38 @@ for lib, val in metadata:
pdf.set_font('Helvetica', '', 10)
pdf.cell(0, 7, val, new_x="LMARGIN", new_y="NEXT")
# ─────────────── 1. Glossaire ───────────────
# ─────────────── Sommaire ───────────────
pdf.add_page()
pdf.set_font('Helvetica', 'B', 16)
pdf.set_text_color(*COULEUR_BLEU)
pdf.set_fill_color(*COULEUR_BLEU_CLAIR)
pdf.cell(0, 11, ' Sommaire', fill=True, new_x="LMARGIN", new_y="NEXT")
pdf.ln(6)
sommaire = [
('1', 'Glossaire'),
('2', 'Recueil du besoin'),
('3', 'Critères de priorisation et pondération'),
('4', 'Cahier des charges - Analyse'),
('5', 'Réponse fonctionnelle - Spécifications par module'),
('6', "Schématisation UML - Cas d'usage"),
('7', 'Modèle Conceptuel de Données (MCD)'),
('8', 'Conception technique - Architecture MVC'),
('9', 'Diagrammes UML - Séquences clés'),
('10', 'Gestion des données personnelles et sensibles (RGPD)'),
('11', 'Analyse des risques et mitigation'),
('12', 'Exigences non-fonctionnelles'),
('13', 'Conclusion'),
]
for num, titre in sommaire:
pdf.set_font('Helvetica', 'B', 11)
pdf.set_text_color(*COULEUR_SECONDAIRE)
pdf.cell(12, 8.5, num)
pdf.set_font('Helvetica', '', 11)
pdf.set_text_color(40, 40, 40)
pdf.cell(0, 8.5, titre, new_x="LMARGIN", new_y="NEXT")
pdf.ln(6)
# ─────────────── 1. Glossaire (même page que le sommaire) ───────────────
pdf.h1(1, 'Glossaire')
glossaire = [
('MVC', "Modèle-Vue-Contrôleur. Patron d'architecture séparant données, présentation et logique applicative."),
@@ -330,7 +364,9 @@ pdf.table(
['Organisationnelle', 'Réalisation individuelle, 3 mois calendaires', 'CRITIQUE'],
['Organisationnelle', "Pas de budget dédié à la création de contenu", 'MOYENNE'],
['Fonctionnelle', '2 modules obligatoires + 1 au choix (Tracker retenu)', 'CRITIQUE'],
['Budgétaire', "Budget global du projet plafonné à 75 000 EUR (sujet)", 'CRITIQUE'],
['Budgétaire', 'Stack open-source uniquement (pas de licence payante)', 'MOYENNE'],
['Temporelle', "Livraison de la version testée sous 12 mois (sujet)", 'FORTE'],
],
col_widths=[35, 130, 25],
)
@@ -455,7 +491,33 @@ pdf.bullet(
# ─────────────── 4. Cahier des charges — Analyse ───────────────
pdf.add_page()
pdf.h1(4, 'Cahier des charges — Analyse')
pdf.h2('4.1 Acteurs identifiés')
pdf.h2('4.1 Parties prenantes et communication')
pdf.paragraph(
"Au-delà des acteurs du système, le projet mobilise plusieurs parties prenantes dont les attentes et "
"les canaux d'échange structurent la conduite du projet. Le commanditaire valide les livrables en comité "
"de pilotage ; l'apprenant (maîtrise d'œuvre) restitue son avancement via le dossier et la soutenance ; "
"les contenus sont produits par des professionnels de santé et hébergés chez un prestataire HDS sous "
"le contrôle de la CNIL."
)
pdf.table(
headers=['Partie prenante', 'Rôle / intérêt', 'Attentes', 'Canal de communication'],
rows=[
['Ministère (commanditaire)', "Finance et valide le projet",
"Conformité santé publique, RGPD, image institutionnelle", "Comités de pilotage, validation des livrables"],
["Apprenant (maîtrise d'œuvre)", "Conçoit et développe la solution",
"Cadrage clair, périmètre stable", "Dossier, revues d'avancement, soutenance"],
['Utilisateurs finaux', "Usage quotidien de la plateforme",
"Simplicité, confidentialité, accessibilité", "Retours in-app, enquêtes de satisfaction"],
['Professionnels de santé', "Rédigent et modèrent les contenus",
"Outils d'administration fiables", "Back-office, charte éditoriale"],
['Hébergeur HDS', "Héberge les données de santé",
"Conformité technique, disponibilité (SLA)", "Contrat de service, supervision"],
['CNIL / DPO', "Contrôlent la conformité RGPD",
"Registre des traitements, sécurité", "Registre, analyses d'impact (AIPD)"],
],
col_widths=[42, 40, 58, 50],
)
pdf.h2('4.2 Acteurs identifiés')
pdf.table(
headers=['Acteur', 'Description', 'Périmètre fonctionnel'],
rows=[
@@ -472,7 +534,7 @@ pdf.table(
col_widths=[35, 60, 90],
)
pdf.h2('4.2 Personas')
pdf.h2('4.3 Personas')
personas = [
("Claire — Utilisatrice (Visiteur → Membre)",
"35 ans, responsable marketing à Lille. Mère célibataire de 2 enfants. Stressée par le travail, "
@@ -493,7 +555,7 @@ for nom, desc in personas:
pdf.multi_cell(0, 5, ' ' + desc)
pdf.ln(1)
pdf.h2('4.3 Opportunités et pérennité')
pdf.h2('4.4 Opportunités et pérennité')
pdf.bullet(
"Évolutivité : architecture découplée (API REST + 2 clients web/mobile) permettant l'ajout futur "
"des modules Diagnostic, Respiration, Activités sans réécriture."
@@ -557,8 +619,7 @@ pdf.ln(2)
pdf.figure(_os.path.join(ASSETS, 'mockup_inscription.png'), 62,
caption="Maquette - écran d'inscription (consentement RGPD obligatoire)")
# ─── Module 2 — Informations
pdf.add_page()
# ─── Module 2 — Informations (enchaîne après le module Comptes)
pdf.h2("5.2 Module 'Informations' (obligatoire)")
pdf.h3("Écrans principaux")
pdf.bullet("Page publique liste : grille de cartes (titre, extrait 120 caractères, image, date).")
@@ -579,24 +640,27 @@ pdf.table(
],
col_widths=[20, 170],
)
pdf.figure(_os.path.join(ASSETS, 'mockup_informations.png'), 88,
caption="Maquette - liste publique des pages d'information + back-office admin")
# ─── Module 3 — Tracker
pdf.h2("5.3 Module 'Tracker d'émotions' (au choix)")
pdf.paragraph(
"Le module Tracker permet à l'utilisateur d'enregistrer son état émotionnel via un wizard en 3 étapes, "
"de consulter son journal, et de visualiser des rapports analytiques sur 4 périodes (semaine, mois, trimestre, année). "
"Les émotions sont structurées en 2 niveaux (7 émotions de base + 33 sous-émotions précises)."
"Les émotions sont structurées en 2 niveaux (6 émotions de base + 36 sous-émotions précises), "
"conformément au référentiel défini dans le sujet."
)
pdf.h3("Wizard d'ajout de saisie (3 étapes)")
pdf.block_callout(
"Étape 1 — Sélection de l'émotion de base (niveau 1)",
"L'utilisateur choisit parmi 7 émotions fondamentales : Joie, Tristesse, Colère, Peur, Dégoût, Surprise, Amour. "
"L'utilisateur choisit parmi 6 émotions fondamentales : Joie, Colère, Peur, Tristesse, Surprise, Dégoût. "
"Chaque émotion est représentée par une couleur et un icône distinctifs.",
color=COULEUR_SECONDAIRE
)
pdf.block_callout(
"Étape 2 — Sous-émotion (niveau 2) + intensité 1-10",
"Selon l'émotion choisie, 4 à 6 sous-émotions plus précises sont proposées (ex: Joie → Sérénité, Enthousiasme, Fierté, Gratitude). "
"Selon l'émotion choisie, 6 sous-émotions plus précises sont proposées (ex: Joie -> Fierté, Contentement, Enchantement, Excitation, Émerveillement, Gratitude). "
"L'intensité est ajustée via un slider de 1 (très faible) à 10 (très forte).",
color=COULEUR_BLEU
)
@@ -644,7 +708,7 @@ pdf.paragraph(
"Le MCD utilise le formalisme Merise (entités, associations, cardinalités). 8 entités principales sont "
"modélisées : Utilisateur, Rôle, Tracker, Émotion, SaisieTracker, Feed, ContactUrgence, Audit."
)
pdf.figure(_os.path.join(ASSETS, 'mcd.png'), 150,
pdf.figure(_os.path.join(ASSETS, 'mcd.png'), 165,
caption="Modèle Conceptuel de Données (Merise) - cardinalités et hiérarchie d'émotions")
pdf.h2("7.1 Cardinalités principales")
@@ -781,7 +845,8 @@ pdf.table(
)
pdf.h2('10.3 Mesures de sécurité techniques')
pdf.bullet("Chiffrement en transit : HTTPS strict (HSTS), TLS 1.3 minimum.")
pdf.bullet("Chiffrement au repos : AES-256 sur le volume PostgreSQL, secrets dans .env hors-versioning.")
pdf.bullet("Chiffrement au repos : chiffrement du volume PostgreSQL (AES-256) prévu en production HDS. "
"À ce stade, les mots de passe sont hachés (bcrypt) et les secrets sont stockés hors-versioning (.env).")
pdf.bullet("Hash mot de passe : bcrypt 12 rounds (configurable selon serveur).")
pdf.bullet("Authentification : JWT signé (HS256), expiration 60min, refresh 14j, throttle login 5/min.")
pdf.bullet("Autorisation : middleware role-based (jwt.auth + role:administrateur), rate limit admin 60/min.")
@@ -796,7 +861,7 @@ pdf.table(
headers=['Risque', 'Impact', 'Probabilité', 'Mitigation'],
rows=[
['Fuite données de santé', 'CRITIQUE', 'Faible',
"Chiffrement AES-256, HDS, audits trimestriels, minimisation données."],
"Hachage bcrypt, chiffrement volume AES-256 prévu en prod HDS, audits trimestriels, minimisation données."],
['Dérive contenus (conseil médical dangereux)', 'FORT', 'Moyen',
"Modération admin obligatoire avant publication. Avertissement légal en pied de page."],
['Perte de données utilisateur', 'FORT', 'Faible',
@@ -827,7 +892,6 @@ pdf.table(
['Sécurité', 'Audit pénétration', 'Annuel (tiers indépendant)'],
['Accessibilité', 'RGAA niveau', 'AA'],
['Ergonomie', 'Dark Mode', "Natif iOS / Android / Web"],
['Internationalisation', 'Langues supportées', 'FR (v1), EN (v2)'],
],
col_widths=[30, 80, 80],
)
@@ -850,7 +914,7 @@ pdf.paragraph(
"et démontre la faisabilité technique des choix présentés."
)
pdf.ln(6)
pdf.ln(1)
pdf.set_font('Helvetica', 'I', 9)
pdf.set_text_color(*COULEUR_GRIS_MOYEN)
pdf.cell(0, 6, 'Sources : consignes CESI INFCDAAL1, Santé Publique France 2023, CNIL — Guide RGPD santé.',
+49 -6
View File
@@ -212,9 +212,9 @@ def diagram_mcd():
ca = (p0[0] + (p1[0] - p0[0]) * 0.16, p0[1] + (p1[1] - p0[1]) * 0.16)
cb = (p0[0] + (p1[0] - p0[0]) * 0.84, p0[1] + (p1[1] - p0[1]) * 0.84)
for (cx, cy), card in ((ca, card_a), (cb, card_b)):
w = c.text_w(card, 10, bold=True) + 8
c.box(cx - w / 2, cy - 9, w, 18, fill=WHITE, outline=GREEN_D, width=1, radius=5)
c.text(cx, cy, card, 10, GREEN_D, bold=True, anchor='mm')
w = c.text_w(card, 13, bold=True) + 12
c.box(cx - w / 2, cy - 12, w, 24, fill=WHITE, outline=GREEN_D, width=2, radius=6)
c.text(cx, cy, card, 13, GREEN_D, bold=True, anchor='mm')
c.pill(mx, my, verb, 11, GREEN)
# liens (cardinalités Merise : (min,max) côté de chaque entité)
@@ -233,8 +233,8 @@ def diagram_mcd():
c.line(ex + ew + 45, ey - 5, ex + ew / 2, ey - 5, GREEN_D, 2)
c.line(ex + ew / 2, ey - 5, ex + ew / 2, ey, GREEN_D, 2)
c.pill(ex + ew + 45, ey + 18, 'hiérarchie', 10, GREEN)
c.text(ex + ew + 50, ey + 40, '0,n', 9, GREEN_D, bold=True, anchor='lm')
c.text(ex + ew / 2 + 8, ey - 12, '0,1', 9, GREEN_D, bold=True, anchor='lm')
c.text(ex + ew + 52, ey + 40, '0,n', 12, GREEN_D, bold=True, anchor='lm')
c.text(ex + ew / 2 + 10, ey - 13, '0,1', 12, GREEN_D, bold=True, anchor='lm')
# dessin des entités (au-dessus des liens)
for name, (x, y, w, attrs) in entities.items():
@@ -538,7 +538,7 @@ def mockup_wizard():
c.ellipse(ix + 28, y + 170, 13, 13, fill=(255, 215, 0), outline=(225, 185, 0), width=2)
c.text(ix + 52, y + 170, "Joie", 14, GREY_D, bold=True, anchor='lm')
# sous-émotions
subs = ['Sérénité', 'Gratitude', 'Fierté', 'Espoir', 'Bonheur', 'Enthousiasme']
subs = ['Fierté', 'Contentement', 'Enchantement', 'Excitation', 'Émerveillement', 'Gratitude']
for i, s in enumerate(subs):
sx = ix + (i % 2) * 140
sy = y + 215 + (i // 2) * 50
@@ -598,6 +598,48 @@ def mockup_rapports():
c.save('mockup_rapports.png')
def mockup_informations():
c = Canvas(620, 760)
title_bar(c, 14, 14, 592, "Maquette - Informations (pages de contenu)", fill=GREEN_D)
x, y, w, h = 40, 80, 540, 650
# fenêtre navigateur
c.box(x, y, w, h, fill=WHITE, outline=GREY_D, width=3, radius=14)
c.box(x, y, w, 40, fill=GREY_L, outline=GREY_L, radius=14)
c.rect(x, y + 22, w, 18, fill=GREY_L)
for i, col in enumerate([(255, 95, 86), (255, 189, 46), (39, 201, 63)]):
c.ellipse(x + 22 + i * 22, y + 20, 7, 7, fill=col, outline=col)
c.text(x + w / 2, y + 20, "cesizen.fr / informations", 10, GREY_D, anchor='mm')
ix = x + 28
c.text(ix, y + 68, "Santé mentale - Ressources", 16, BLUE, bold=True, anchor='lm')
c.text(ix, y + 92, "Articles et conseils validés par nos professionnels", 10, GREY, anchor='lm')
# cartes articles (liste publique)
articles = [
("Comprendre le stress", ["Mécanismes du stress et signaux", "d'alerte à reconnaître au quotidien."]),
("5 exercices anti-anxiété", ["Respiration et ancrage pour apaiser", "une montée d'anxiété."]),
("Bien dormir, mieux vivre", ["L'impact du sommeil sur la santé", "mentale et routines de repos."]),
("Quand consulter ?", ["Repères pour identifier le moment", "d'aller voir un professionnel."]),
]
cy0 = y + 118
for i, (titre, lignes) in enumerate(articles):
cardx = ix + (i % 2) * 258
cardy = cy0 + (i // 2) * 152
c.box(cardx, cardy, 240, 132, fill=GREY_LL, outline=GREY_L, width=1, radius=12)
c.box(cardx, cardy, 240, 40, fill=BLUE_L, outline=BLUE_L, radius=12)
c.rect(cardx, cardy + 22, 240, 18, fill=BLUE_L)
c.text(cardx + 14, cardy + 20, titre, 11, BLUE, bold=True, anchor='lm')
for j, ln in enumerate(lignes):
c.text(cardx + 14, cardy + 62 + j * 19, ln, 9, INK, anchor='lm')
c.text(cardx + 14, cardy + 112, "12 mai 2026 · Lire ->", 8, GREEN_D, bold=True, anchor='lm')
# bandeau back-office admin
ay = cy0 + 320
c.box(ix, ay, w - 56, 40, fill=(255, 248, 200), outline=YELLOW, width=2, radius=10)
c.text(ix + 14, ay + 20, "Back-office admin : créer / modifier / publier · slug auto · "
"modération avant mise en ligne", 9, GREY_D, anchor='lm')
c.text(x + w / 2, y + h - 14, "RG-INF-01 slug auto · RG-INF-02 brouillon/publié · RG-INF-06 modération",
8, GREY, anchor='mm')
c.save('mockup_informations.png')
# ════════════════════════════════════════════════════════════════════
def main():
print("Génération des schémas CESIZen ->", OUT_DIR)
@@ -608,6 +650,7 @@ def main():
diagram_mvc()
mockup_inscription()
mockup_wizard()
mockup_informations()
mockup_rapports()
print("Terminé.")
+3 -3
View File
@@ -229,7 +229,7 @@ cols = [
]),
("1 module AU CHOIX (retenu)", BLUE, [
"Tracker d'émotions : journal, saisies, rapports périodiques.",
"Hiérarchie : 7 émotions de base + 33 sous-émotions.",
"Hiérarchie : 6 émotions de base + 36 sous-émotions (référentiel du sujet).",
]),
("Modules ÉCARTÉS", GREY, [
"Diagnostic de stress.",
@@ -326,7 +326,7 @@ bullets(s, [
"Journal de bord : consultation, modification, suppression des saisies.",
"Rapports analytiques sur 4 périodes : semaine, mois, trimestre, année.",
"Statistiques : intensité moyenne, émotion dominante, répartition, évolution.",
"Hiérarchie configurable par l'admin : 7 émotions + 33 sous-émotions.",
"Hiérarchie configurable par l'admin : 6 émotions + 36 sous-émotions.",
"Web (graphiques Recharts) et mobile (Expo) synchronisés via l'API.",
], Inches(0.7), Inches(1.45), Inches(7.0), Inches(5.3), size=16, gap=10)
image_fit(s, "mockup_wizard.png", Inches(7.9), Inches(1.35), Inches(2.5), Inches(5.3))
@@ -383,7 +383,7 @@ rect(s, Inches(0.8), Inches(4.1), Inches(3.6), Inches(0.55), GREEN_D)
tb, tf = textbox(s, Inches(0.95), Inches(4.13), Inches(3.4), Inches(0.5), MSO_ANCHOR.MIDDLE)
set_par(tf.paragraphs[0], "Mesures de sécurité", 15, WHITE, bold=True, space_after=0)
bullets(s, [
"Chiffrement en transit (HTTPS/TLS 1.3) et au repos (AES-256).",
"Chiffrement en transit (HTTPS/TLS 1.3) ; bcrypt sur les mots de passe, AES-256 au repos prévu en prod HDS.",
"Authentification JWT signée, expiration 60 min, throttle login.",
"Hébergement certifié HDS (Scaleway / OVH Healthcare).",
"Journalisation : table audits trace toute action admin sensible.",
+2 -3
View File
@@ -19,11 +19,10 @@ export const Colors = {
},
emotions: {
joie: '#FFD700',
tristesse: '#4169E1',
colere: '#DC143C',
peur: '#9932CC',
degout: '#228B22',
tristesse: '#4169E1',
surprise: '#FF8C00',
amour: '#FF69B4',
degout: '#228B22',
},
};