Abmacode12 commited on
Commit
33405a0
·
verified ·
1 Parent(s): 499a5a2

class Documentation:

Browse files

def __init__(self):
self.docs = {
"python": "Documentation Python officielle",
"javascript": "Documentation JavaScript MDN",
"api": "Documentation API du projet"
}

def provide_docs(self, topic=""):
if topic in self.docs:
return f"Documentation pour {topic}: {self.docs[topic]}"
return "Documentation générale disponible"

class CodeEditor:
def __init__(self, language="python"):
self.language = language
self.code = ""
self.documentation = Documentation()
self.terminal = Terminal()
self.debugger = Debugger()
self.build_system = BuildSystem(language)
self.version_control = VersionControl()
self.testing_framework = TestingFramework()
self.deployment = Deployment()

def write_code(self, code):
self.code = code
print(f"Code {self.language} écrit:\n{self.code}")
return self.code

def get_suggestions(self):
suggestions = {
"python": ["import ", "def ", "class ", "print(", "if __name__"],
"javascript": ["function ", "const ", "let ", "console.log("]
}
return suggestions.get(self.language, ["// Commencez à coder..."])

def build(self):
print(f"Construction du projet {self.language}...")
return self.build_system.build(self.code)

def debug(self):
print("Débogage en cours...")
return self.debugger.debug(self.code)

def test(self):
print("Exécution des tests...")
return self.testing_framework.run_tests()

def deploy(self, environment="production"):
print(f"Déploiement sur {environment}...")
return self.deployment.deploy(environment)

def commit(self, message="Mise à jour du code"):
print(f"Commit: {message}")
return self.version_control.commit(message)

def run_terminal_command(self, command):
return self.terminal.execute_command(command)

def show_docs(self, topic=""):
return self.documentation.provide_docs(topic)

class Terminal:
def __init__(self):
self.history = []

def execute_command(self, command):
print(f"Terminal: {command}")
self.history.append(command)

commands = {
"ls": "fichier1.py fichier2.js dossier1/",
"pwd": "/home/user/projet",
"python --version": "Python 3.11.0",
"node --version": "v18.12.0"
}

if command in commands:
return commands[command]
return f"Commande exécutée: {command}"

def get_history(self):
return self.history

class Debugger:
def __init__(self):
self.breakpoints = []

def debug(self, code):
issues = self.analyze_code(code)
print(f"{len(issues)} problèmes détectés")
return issues

def analyze_code(self, code):
issues = []

if "print(" in code and "python" in code.lower():
issues.append("Utilisation de print() pour le débogage - considérez un logger")

if "TODO" in code:
issues.append("TODO trouvé dans le code")

if len(code) > 1000:
issues.append("Code très long - considérez la modularisation")

return issues

def add_breakpoint(self, line):
self.breakpoints.append(line)
print(f"Point d'arrêt ajouté à la ligne {line}")

def step_through(self):
print("Exécution pas à pas...")

class BuildSystem:
def __init__(self, language):
self.language = language
self.dependencies = []

def build(self, code):
build_commands = {
"python": "python -m py_compile",
"javascript": "npm run build",
"java": "mvn compile"
}

command = build_commands.get(self.language, "build")
print(f"Exécution: {command}")

if self.language == "python" and "import " in code:
self.dependencies = self.extract_imports(code)
print(f"Dépendances détectées: {self.dependencies}")

return {"status": "succès", "language": self.language}

def extract_imports(self, code):
imports = []
lines = code.split('\n')
for line in lines:
if line.strip().startswith("import "):
imports.append(line.strip())
elif line.strip().startswith("from "):
imports.append(line.strip())
return imports

class VersionControl:
def __init__(self):
self.commits = []
self.branch = "main"

def commit(self, message):
from datetime import datetime
commit = {
"id": len(self.commits) + 1,
"message": message,
"timestamp": datetime.now().isoformat(),
"branch": self.branch
}
self.commits.append(commit)
print(f"Commit #{commit['id']} créé sur la branche {self.branch}")
return commit

def create_branch(self, name):
self.branch = name
print(f"Branche '{name}' créée")
return self.branch

def get_history(self):
return self.commits

class TestingFramework:
def __init__(self):
self.tests = []

def run_tests(self):
print("Exécution des tests automatisés...")

test_results = {
"total": 5,
"passed": 4,
"failed": 1,
"coverage": "85%"
}

print(f"Résultats: {test_results['passed']}/{test_results['total']} tests réussis")
print(f"Couverture de code: {test_results['coverage']}")

return test_results

def add_test(self, test_name, test_function):
self.tests.append({"name": test_name, "function": test_function})
print(f"Test ajouté: {test_name}")

class Deployment:
def __init__(self):
self.environments = ["development", "staging", "production"]

def deploy(self, environment="production"):
if environment not in self.environments:
print(f"Environnement {environment} non reconnu")
return False

print(f"Déploiement sur {environment}...")

deployment_steps = [
"Validation du build",
"Exécution des tests",
"Backup de la version actuelle",
"Déploiement des fichiers",
"Redémarrage des services",
"Vérification de la santé"
]

for step in deployment_steps:
print(f" ✓ {step}")

print("Déploiement terminé avec succès!")
return True

def rollback(self, version):
print(f"Retour à la version {version}...")
return True

# Exemple d'utilisation
if __name__ == "__main__":
print("=== Espace Codage - Environnement de développement intégré ===\n")

# Initialisation de l'éditeur
editeur = CodeEditor(language="python")

# Écriture de code
code_exemple = """
import math

def calculate_circle_area(radius):
\"\"\"Calcule l'aire d'un cercle\"\"\"
return math.pi * radius ** 2

# TODO: Ajouter une fonction pour le périmètre
print("Aire du cercle:", calculate_circle_area(5))
"""

editeur.write_code(code_exemple)

# Affichage des suggestions
print("\nSuggestions de code:")
for suggestion in editeur.get_suggestions():
print(f" - {suggestion}")

# Documentation
print(f"\n{editeur.show_docs('python')}")

# Construction
editeur.build()

# Débogage
issues = editeur.debug()
if issues:
print("\nProblèmes détectés:")
for issue in issues:
print(f" ⚠ {issue}")

# Terminal
print("\nTerminal:")
print(editeur.run_terminal_command("pwd"))
print(editeur.run_terminal_command("ls"))

# Tests
editeur.test()

# Version control
editeur.commit("Ajout fonction calcul aire cercle")
editeur.version_control.create_branch("feature/new-geometry")
editeur.commit("Ajout branche pour nouvelles fonctions géométriques")

# Déploiement
print("\n" + "="*50)
editeur.deploy("staging")

# Affichage historique
print("\nHistorique des commits:")
for commit in editeur.version_control.get_history():
print(f" #{commit['id']}: {commit['message']} ({commit['branch']})")

print("\n=== Espace Codage prêt à l'utilisation ===") from abc import ABC, abstractmethod
from datetime import datetime
import json

# Produit complexe : Un projet de développement complet
class ProjetCodage:
def __init__(self, nom="Nouveau Projet"):
self.nom = nom
self.date_creation = datetime.now()
self.fichiers = []
self.configurations = {}
self.dependances = []
self.environnements = {}
self.statistiques = {
"lignes_code": 0,
"tests": 0,
"complexite": "faible"
}

def ajouter_fichier(self, nom_fichier, contenu=""):
fichier = {
"nom": nom_fichier,
"contenu": contenu,
"date_modification": datetime.now(),
"langage": self._detecter_langage(nom_fichier)
}
self.fichiers.append(fichier)
print(f"✓ Fichier '{nom_fichier}' ajouté au projet")

def _detecter_langage(self, nom_fichier):
extensions = {
'.py': 'Python',
'.js': 'JavaScript',
'.java': 'Java',
'.html': 'HTML',
'.css': 'CSS',
'.md': 'Markdown'
}
for ext, lang in extensions.items():
if nom_fichier.endswith(ext):
return lang
return 'Autre'

def configurer(self, cle, valeur):
self.configurations[cle] = valeur
print(f"✓ Configuration '{cle}' = {valeur}")

def ajouter_dependance(self, dependance, version="latest"):
self.dependance

Files changed (2) hide show
  1. README.md +8 -5
  2. index.html +692 -19
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Espace Codage Builder Pattern
3
- emoji:
4
- colorFrom: gray
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: Espace Codage - Builder Pattern
3
+ colorFrom: purple
4
+ colorTo: blue
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
index.html CHANGED
@@ -1,19 +1,692 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Espace Codage Modèle Constructeur (Builder Pattern)</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+
8
+ <!-- Tailwind CSS CDN -->
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <script>
11
+ tailwind.config = {
12
+ theme: {
13
+ extend: {
14
+ colors: {
15
+ primary: {
16
+ DEFAULT: '#4f46e5', // indigo-600
17
+ fg: '#ffffff',
18
+ soft: 'rgba(79,70,229,0.2)',
19
+ },
20
+ secondary: {
21
+ DEFAULT: '#64748b', // slate-500
22
+ fg: '#ffffff',
23
+ soft: 'rgba(100,116,139,0.2)',
24
+ },
25
+ accent: {
26
+ DEFAULT: '#22d3ee', // cyan-400
27
+ soft: 'rgba(34,211,238,0.2)',
28
+ },
29
+ success: '#22c55e',
30
+ danger: '#ef4444',
31
+ warning: '#f59e0b',
32
+ surface: {
33
+ DEFAULT: '#0b1020',
34
+ soft: '#0f172a',
35
+ },
36
+ card: {
37
+ DEFAULT: '#0f172a',
38
+ soft: '#111827',
39
+ },
40
+ code: '#0b132b',
41
+ grid: 'rgba(255,255,255,0.06)',
42
+ border: 'rgba(255,255,255,0.12)',
43
+ },
44
+ boxShadow: {
45
+ soft: '0 18px 45px rgba(0,0,0,0.6)',
46
+ },
47
+ borderRadius: {
48
+ xl: '1rem',
49
+ '2xl': '1.25rem',
50
+ },
51
+ fontFamily: {
52
+ mono: ['JetBrains Mono','ui-monospace','SFMono-Regular','Menlo','Monaco','Consolas','Liberation Mono','Courier New','monospace'],
53
+ display: ['Inter','ui-sans-serif','system-ui','-apple-system','BlinkMacSystemFont','Segoe UI','Roboto','Helvetica Neue','Arial','Noto Sans','sans-serif','Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji'],
54
+ },
55
+ },
56
+ },
57
+ darkMode: 'class',
58
+ }
59
+ </script>
60
+
61
+ <!-- Google Fonts -->
62
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
63
+
64
+ <style>
65
+ :root { color-scheme: dark; }
66
+ body { background-color: #050714; }
67
+ /* subtle grid background */
68
+ .grid-bg {
69
+ background-image:
70
+ linear-gradient(to bottom, var(--tw-colors-grid) 1px, transparent 1px),
71
+ linear-gradient(to right, var(--tw-colors-grid) 1px, transparent 1px);
72
+ background-size: 40px 40px, 40px 40px;
73
+ }
74
+ </style>
75
+ </head>
76
+ <body class="bg-surface text-slate-100 font-display antialiased selection:bg-primary/30 selection:text-white">
77
+ <main class="max-w-7xl mx-auto px-5 py-8 md:px-8 md:py-10">
78
+ <!-- Header -->
79
+ <header class="relative overflow-hidden rounded-2xl border border-border bg-gradient-to-br from-card to-surface shadow-soft p-5 md:p-7" data-animate="1">
80
+ <div class="absolute inset-0 pointer-events-none opacity-30">
81
+ <div class="absolute -top-24 -left-20 w-72 h-72 rounded-full bg-primary/20 blur-3xl"></div>
82
+ <div class="absolute -bottom-24 -right-20 w-72 h-72 rounded-full bg-accent/20 blur-3xl"></div>
83
+ </div>
84
+ <div class="relative flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
85
+ <div class="flex items-center gap-3">
86
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-primary to-accent animate-spin-slow"></div>
87
+ <div>
88
+ <div class="text-xs uppercase tracking-[0.2em] text-slate-400">Espace Codage</div>
89
+ <h1 class="text-xl md:text-2xl font-bold tracking-wide">Modèle Constructeur · Builder Pattern</h1>
90
+ </div>
91
+ </div>
92
+ <p class="text-sm text-slate-400 max-w-2xl">
93
+ Visualisation de l'espace de codage et implémentation du pattern
94
+ <span class="text-white font-semibold">Builder</span> pour créer un
95
+ <span class="text-white font-semibold">ProjetEspaceCodage</span> étape par étape.
96
+ </p>
97
+ </div>
98
+ </header>
99
+
100
+ <div class="mt-6 grid grid-cols-1 lg:grid-cols-2 gap-6">
101
+ <!-- Diagramme Espace Codage -->
102
+ <section class="relative rounded-2xl border border-border bg-gradient-to-br from-card to-surface shadow-soft p-5" data-animate="2" aria-label="Schéma Espace Codage">
103
+ <div class="flex items-center justify-between mb-3">
104
+ <div>
105
+ <h2 class="text-sm uppercase tracking-[0.2em] text-accent">Espace Codage</h2>
106
+ <p class="text-xs text-slate-400">Vue conceptuelle des outils : éditeur, terminal, build, tests, déploiement…</p>
107
+ </div>
108
+ <span class="text-[10px] uppercase tracking-[0.25em] text-slate-500">SCHEMA</span>
109
+ </div>
110
+
111
+ <div class="relative grid-bg rounded-xl border border-border p-4 md:p-5 min-h-[420px]">
112
+ <!-- Overlay SVG pour les flèches -->
113
+ <svg class="absolute inset-0 w-full h-full pointer-events-none" id="arrowLayer" style="z-index: 0;"></svg>
114
+
115
+ <div class="relative grid grid-rows-[auto,1fr,auto] gap-4 h-full" id="schemaRoot" style="z-index: 1;">
116
+ <!-- Ligne du haut : Documentation -->
117
+ <div class="flex justify-center">
118
+ <button class="node-btn" data-id="documentation" data-name="Documentation" title="Documentation">
119
+ Documentation
120
+ </button>
121
+ </div>
122
+
123
+ <!-- Ligne centrale -->
124
+ <div class="grid grid-cols-3 gap-3 md:gap-4 items-center">
125
+ <!-- Version Control (gauche) -->
126
+ <div class="flex justify-center">
127
+ <button class="node-btn" data-id="version" data-name="Version Control" title="Version Control">
128
+ Version Control
129
+ </button>
130
+ </div>
131
+
132
+ <!-- Colonne centrale -->
133
+ <div class="flex flex-col items-center gap-3">
134
+ <!-- Code Editor (centre principal) -->
135
+ <button class="node-btn node-main" data-id="editor" data-name="Code Editor" title="Code Editor">
136
+ Code Editor
137
+ </button>
138
+
139
+ <!-- Terminal + Debugger -->
140
+ <div class="flex gap-3">
141
+ <button class="node-btn" data-id="terminal" data-name="Terminal" title="Terminal">
142
+ Terminal
143
+ </button>
144
+ <button class="node-btn" data-id="debugger" data-name="Debugger" title="Debugger">
145
+ Debugger
146
+ </button>
147
+ </div>
148
+
149
+ <!-- Testing Framework -->
150
+ <button class="node-btn" data-id="testing" data-name="Testing Framework" title="Testing Framework">
151
+ Testing Framework
152
+ </button>
153
+ </div>
154
+
155
+ <!-- Build System (droite) -->
156
+ <div class="flex justify-center">
157
+ <button class="node-btn" data-id="build" data-name="Build System" title="Build System">
158
+ Build System
159
+ </button>
160
+ </div>
161
+ </div>
162
+
163
+ <!-- Ligne du bas : Deployment -->
164
+ <div class="flex justify-center">
165
+ <button class="node-btn" data-id="deploy" data-name="Deployment" title="Deployment">
166
+ Deployment
167
+ </button>
168
+ </div>
169
+ </div>
170
+ </div>
171
+
172
+ <div class="mt-4 text-xs text-slate-400">
173
+ Cliquez sur un nœud pour voir une info rapide. Utilisez les boutons de démonstration ci-dessous pour simuler la construction.
174
+ </div>
175
+ </section>
176
+
177
+ <!-- Code + Démonstration Builder -->
178
+ <section class="rounded-2xl border border-border bg-gradient-to-br from-card to-surface shadow-soft p-5" data-animate="3" aria-label="Code Builder Pattern">
179
+ <div class="flex items-start justify-between gap-3">
180
+ <div>
181
+ <h2 class="text-sm uppercase tracking-[0.2em] text-primary">Code · Builder Pattern</h2>
182
+ <p class="text-xs text-slate-400">
183
+ Implémentation en <strong class="text-white">Python</strong> du pattern
184
+ <strong class="text-white">Builder</strong> pour un <em>ProjetEspaceCodage</em> complexe.
185
+ </p>
186
+ <div class="mt-2 flex flex-wrap gap-2">
187
+ <span class="badge">Builder Pattern</span>
188
+ <span class="badge">Objet complexe</span>
189
+ <span class="badge">Python</span>
190
+ <span class="badge">Espace Codage</span>
191
+ </div>
192
+ </div>
193
+ <span class="text-[10px] uppercase tracking-[0.25em] text-slate-500">BUILDER</span>
194
+ </div>
195
+
196
+ <!-- Editeur simulé -->
197
+ <div class="mt-4 rounded-xl border border-border bg-code shadow-soft overflow-hidden">
198
+ <div class="flex items-center justify-between px-3 py-2 border-b border-border bg-slate-900/50">
199
+ <div class="flex items-center gap-1.5">
200
+ <span class="w-2.5 h-2.5 rounded-full bg-danger"></span>
201
+ <span class="w-2.5 h-2.5 rounded-full bg-warning"></span>
202
+ <span class="w-2.5 h-2.5 rounded-full bg-success"></span>
203
+ </div>
204
+ <div class="flex items-center gap-2 text-[10px] uppercase tracking-[0.18em] text-slate-400">
205
+ espace_codage_builder.py · Python
206
+ </div>
207
+ <div></div>
208
+ </div>
209
+ <pre class="font-mono text-[11px] leading-5 p-3 md:p-4 overflow-auto max-h-[420px]"><code><span class="text-slate-400"># === ESPACE CODAGE · MODÈLE CONSTRUCTEUR (BUILDER) ===</span>
210
+ <span class="text-slate-400"># Situation :</span>
211
+ <span class="text-slate-400"># - on veut créer un "objet complexe" ProjetEspaceCodage</span>
212
+ <span class="text-slate-400"># indépendamment de la manière dont chaque partie est construite.</span>
213
+ <span class="text-slate-400"># - différents Builders produisent différentes représentations</span>
214
+ <span class="text-slate-400"># (projet minimal, projet full‑stack, etc.).</span>
215
+
216
+ <span class="text-primary">from</span> abc <span class="text-primary">import</span> ABC, abstractmethod
217
+ <span class="text-primary">from</span> typing <span class="text-primary">import</span> List, Dict
218
+
219
+
220
+ <span class="text-accent">class</span> <span class="text-white">ProjetEspaceCodage</span>:
221
+ <span class="text-slate-400">"""Produit complexe : représente l'espace de codage complet."""</span>
222
+
223
+ <span class="text-primary">def</span> <span class="text-accent">__init__</span>(<span class="text-white">self</span>, <span class="text-white">nom</span>: <span class="text-secondary">str</span> = <span class="text-warning">"Nouveau Projet"</span>) -> <span class="text-primary">None</span>:
224
+ <span class="text-white">self</span>.nom = nom
225
+ <span class="text-white">self</span>.composants: List[str] = []
226
+ <span class="text-white">self</span>.configurations: Dict[str, str] = {}
227
+ <span class="text-white">self</span>.etapes: List[str] = []
228
+
229
+ <span class="text-primary">def</span> <span class="text-accent">ajouter_composant</span>(<span class="text-white">self</span>, <span class="text-white">description</span>: <span class="text-secondary">str</span>) -> <span class="text-primary">None</span>:
230
+ <span class="text-white">self</span>.composants.append(description)
231
+
232
+ <span class="text-primary">def</span> <span class="text-accent">ajouter_configuration</span>(<span class="text-white">self</span>, <span class="text-white">cle</span>: <span class="text-secondary">str</span>, <span class="text-white">valeur</span>: <span class="text-secondary">str</span>) -> <span class="text-primary">None</span>:
233
+ <span class="text-white">self</span>.configurations[cle] = valeur
234
+
235
+ <span class="text-primary">def</span> <span class="text-accent">ajouter_etape</span>(<span class="text-white">self</span>, <span class="text-white">etape</span>: <span class="text-secondary">str</span>) -> <span class="text-primary">None</span>:
236
+ <span class="text-white">self</span>.etapes.append(etape)
237
+
238
+ <span class="text-primary">def</span> <span class="text-accent">decrire</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
239
+ <span class="text-primary">print</span>(<span class="text-warning">f"</span><span class="text-warning">=== ESPACE CODAGE : {</span><span class="text-white">self</span>.nom<span class="text-warning">} ==="</span>)
240
+ <span class="text-primary">print</span>(<span class="text-warning">"Composants :"</span>)
241
+ <span class="text-primary">for</span> i, comp <span class="text-primary">in</span> <span class="text-primary">enumerate</span>(<span class="text-white">self</span>.composants, <span class="text-warning">1</span>):
242
+ <span class="text-primary">print</span>(<span class="text-warning">f"</span><span class="text-warning"> {i}. {comp}"</span>)
243
+
244
+ <span class="text-primary">if</span> <span class="text-white">self</span>.configurations:
245
+ <span class="text-primary">print</span>(<span class="text-warning">"</span><span class="text-warning">Configurations :"</span>)
246
+ <span class="text-primary">for</span> cle, val <span class="text-primary">in</span> <span class="text-white">self</span>.configurations.items():
247
+ <span class="text-primary">print</span>(<span class="text-warning">f"</span><span class="text-warning"> • {cle}: {val}"</span>)
248
+
249
+ <span class="text-primary">if</span> <span class="text-white">self</span>.etapes:
250
+ <span class="text-primary">print</span>(<span class="text-warning">"</span><span class="text-warning">Étapes de construction :"</span>)
251
+ <span class="text-primary">for</span> etape <span class="text-primary">in</span> <span class="text-white">self</span>.etapes:
252
+ <span class="text-primary">print</span>(<span class="text-warning">f"</span><span class="text-warning"> → {etape}"</span>)
253
+
254
+
255
+ <span class="text-accent">class</span> <span class="text-white">ConstructeurEspaceCodage</span>(ABC):
256
+ <span class="text-slate-400">"""Interface d'assemblage & construction."""</span>
257
+
258
+ <span class="text-primary">def</span> <span class="text-accent">__init__</span>(<span class="text-white">self</span>, <span class="text-white">nom_projet</span>: <span class="text-secondary">str</span>) -> <span class="text-primary">None</span>:
259
+ <span class="text-white">self</span>.projet = ProjetEspaceCodage(nom_projet)
260
+
261
+ @abstractmethod
262
+ <span class="text-primary">def</span> <span class="text-accent">configurer_documentation</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>: <span class="text-primary">pass</span>
263
+
264
+ @abstractmethod
265
+ <span class="text-primary">def</span> <span class="text-accent">configurer_editeur</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>: <span class="text-primary">pass</span>
266
+
267
+ @abstractmethod
268
+ <span class="text-primary">def</span> <span class="text-accent">configurer_terminal_debugger</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>: <span class="text-primary">pass</span>
269
+
270
+ @abstractmethod
271
+ <span class="text-primary">def</span> <span class="text-accent">configurer_build_system</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>: <span class="text-primary">pass</span>
272
+
273
+ @abstractmethod
274
+ <span class="text-primary">def</span> <span class="text-accent">configurer_tests</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>: <span class="text-primary">pass</span>
275
+
276
+ @abstractmethod
277
+ <span class="text-primary">def</span> <span class="text-accent">configurer_deploiement</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>: <span class="text-primary">pass</span>
278
+
279
+ <span class="text-primary">def</span> <span class="text-accent">obtenir_projet</span>(<span class="text-white">self</span>) -> ProjetEspaceCodage:
280
+ <span class="text-primary">return</span> <span class="text-white">self</span>.projet
281
+
282
+ <span class="text-primary">def</span> <span class="text-accent">operation_optionnelle</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>: <span class="text-primary">pass</span>
283
+
284
+
285
+ <span class="text-accent">class</span> <span class="text-white">ConstructeurMinimal</span>(ConstructeurEspaceCodage):
286
+
287
+ <span class="text-primary">def</span> <span class="text-accent">configurer_documentation</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
288
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Documentation : README.md simple"</span>)
289
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Documentation minimale configurée"</span>)
290
+
291
+ <span class="text-primary">def</span> <span class="text-accent">configurer_editeur</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
292
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Code Editor : VS Code avec thème par défaut"</span>)
293
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"editor.theme"</span>, <span class="text-warning">"default-dark"</span>)
294
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Éditeur de code configuré"</span>)
295
+
296
+ <span class="text-primary">def</span> <span class="text-accent">configurer_terminal_debugger</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
297
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Terminal intégré + debug minimal (print)"</span>)
298
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Terminal et debugger basique configurés"</span>)
299
+
300
+ <span class="text-primary">def</span> <span class="text-accent">configurer_build_system</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
301
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Build System : exécution directe du script"</span>)
302
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Système de build minimal configuré"</span>)
303
+
304
+ <span class="text-primary">def</span> <span class="text-accent">configurer_tests</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
305
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Tests : quelques tests manuels"</span>)
306
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Tests manuels configurés"</span>)
307
+
308
+ <span class="text-primary">def</span> <span class="text-accent">configurer_deploiement</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
309
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Déploiement : exécution locale seulement"</span>)
310
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"deployment.target"</span>, <span class="text-warning">"local"</span>)
311
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Déploiement local configuré"</span>)
312
+
313
+
314
+ <span class="text-accent">class</span> <span class="text-white">ConstructeurFullStack</span>(ConstructeurEspaceCodage):
315
+
316
+ <span class="text-primary">def</span> <span class="text-accent">configurer_documentation</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
317
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Documentation : wiki, UML, API complète"</span>)
318
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"docs.format"</span>, <span class="text-warning">"OpenAPI + Markdown"</span>)
319
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Documentation complète configurée"</span>)
320
+
321
+ <span class="text-primary">def</span> <span class="text-accent">configurer_editeur</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
322
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Code Editor : IDE complet + plugins"</span>)
323
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"editor.plugins"</span>, <span class="text-warning">"lint, format, refactor, git, ..."</span>)
324
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Éditeur avancé configuré"</span>)
325
+
326
+ <span class="text-primary">def</span> <span class="text-accent">configurer_terminal_debugger</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
327
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Terminal multi‑onglets + debugger graphique"</span>)
328
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"debugger.features"</span>, <span class="text-warning">"breakpoints, watch, stack, step-by-step"</span>)
329
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Terminal et debugger avancés configurés"</span>)
330
+
331
+ <span class="text-primary">def</span> <span class="text-accent">configurer_build_system</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
332
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Build System : pipeline CI/CD automatisé"</span>)
333
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"build.pipeline"</span>, <span class="text-warning">"tests → build → packaging → deployment"</span>)
334
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Système de build avancé configuré"</span>)
335
+
336
+ <span class="text-primary">def</span> <span class="text-accent">configurer_tests</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
337
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Testing Framework : unitaires, intégration, e2e"</span>)
338
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"testing.coverage"</span>, <span class="text-warning">">= 90%"</span>)
339
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Framework de tests complet configuré"</span>)
340
+
341
+ <span class="text-primary">def</span> <span class="text-accent">configurer_deploiement</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
342
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Déploiement : CI/CD vers staging/production (cloud)"</span>)
343
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"deployment.providers"</span>, <span class="text-warning">"AWS, Docker, Kubernetes"</span>)
344
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Déploiement cloud configuré"</span>)
345
+
346
+ <span class="text-primary">def</span> <span class="text-accent">operation_optionnelle</span>(<span class="text-white">self</span>) -> <span class="text-primary">None</span>:
347
+ <span class="text-white">self</span>.projet.ajouter_composant(<span class="text-warning">"Analyse statique + métriques + revues automatisées"</span>)
348
+ <span class="text-white">self</span>.projet.ajouter_configuration(<span class="text-warning">"quality.metrics"</span>, <span class="text-warning">"complexité, dette technique, vulnérabilités"</span>)
349
+ <span class="text-white">self</span>.projet.ajouter_etape(<span class="text-warning">"Analyses avancées configurées (optionnel)"</span>)
350
+
351
+
352
+ <span class="text-accent">class</span> <span class="text-white">DirecteurEspaceCodage</span>:
353
+ <span class="text-slate-400">"""Le Directeur orchestre les étapes de construction."""</span>
354
+
355
+ <span class="text-primary">def</span> <span class="text-accent">__init__</span>(<span class="text-white">self</span>, <span class="text-white">builder</span>: ConstructeurEspaceCodage) -> <span class="text-primary">None</span>:
356
+ <span class="text-white">self</span>._builder = builder
357
+
358
+ <span class="text-primary">def</span> <span class="text-accent">construire_espace_codage</span>(<span class="text-white">self</span>) -> ProjetEspaceCodage:
359
+ <span class="text-white">self</span>._builder.configurer_documentation()
360
+ <span class="text-white">self</span>._builder.configurer_editeur()
361
+ <span class="text-white">self</span>._builder.configurer_terminal_debugger()
362
+ <span class="text-white">self</span>._builder.configurer_build_system()
363
+ <span class="text-white">self</span>._builder.configurer_tests()
364
+ <span class="text-white">self</span>._builder.configurer_deploiement()
365
+ <span class="text-white">self</span>._builder.operation_optionnelle()
366
+ <span class="text-primary">return</span> <span class="text-white">self</span>._builder.obtenir_projet()
367
+
368
+
369
+ <span class="text-primary">if</span> __name__ == <span class="text-warning">"__main__"</span>:
370
+ <span class="text-primary">print</span>(<span class="text-warning">"=== ESPACE CODAGE · PROJET MINIMAL ==="</span>)
371
+ directeur = DirecteurEspaceCodage(ConstructeurMinimal(<span class="text-warning">"Script Python Simple"</span>))
372
+ projet_min = directeur.construire_espace_codage()
373
+ projet_min.decrire()
374
+
375
+ <span class="text-primary">print</span>(<span class="text-warning">"</span><span class="text-warning">=== ESPACE CODAGE · PROJET FULL‑STACK ==="</span>)
376
+ directeur = DirecteurEspaceCodage(ConstructeurFullStack(<span class="text-warning">"Application Web Avancée"</span>))
377
+ projet_full = directeur.construire_espace_codage()
378
+ projet_full.decrire()
379
+ </code></pre>
380
+ </div>
381
+
382
+ <!-- Démonstration Builder -->
383
+ <div class="mt-5 rounded-xl border border-border bg-slate-900/40 p-4">
384
+ <div class="flex items-center justify-between">
385
+ <h3 class="text-xs uppercase tracking-[0.2em] text-accent">Démonstration du Builder Pattern</h3>
386
+ <div class="text-[10px] uppercase tracking-[0.2em] text-slate-500">DEMO</div>
387
+ </div>
388
+ <div class="mt-3 flex flex-wrap gap-2">
389
+ <button class="btn-primary" id="btn-minimal">Construire Projet Minimal</button>
390
+ <button class="btn-secondary" id="btn-fullstack">Construire Projet Full‑Stack</button>
391
+ <button class="btn-ghost" id="btn-reset">Réinitialiser</button>
392
+ </div>
393
+ <div id="demoOutput" class="mt-4 rounded-lg border border-border bg-black/40 p-3 font-mono text-[12px] leading-5 max-h-56 overflow-auto text-accent">
394
+ <div>Prêt à construire un espace de codage…</div>
395
+ </div>
396
+ </div>
397
+
398
+ <div class="mt-4 text-xs text-slate-400">
399
+ <strong class="text-white">Note :</strong> Le <strong>modèle Constructeur</strong> se concentre sur un seul
400
+ <em>objet complexe</em> (ProjetEspaceCodage) construit étape par étape. Une
401
+ <strong>Abstract Factory</strong> fournirait plusieurs familles d’objets (éditeur, terminal, debugger, …)
402
+ sans orchestrer le processus de construction comme le fait le <code>DirecteurEspaceCodage</code>.
403
+ </div>
404
+ </section>
405
+ </div>
406
+ </main>
407
+
408
+ <!-- Tooltip flottant -->
409
+ <div id="nodeTooltip" class="hidden absolute z-50 max-w-[240px] rounded-lg border border-primary/40 bg-slate-900/95 px-3 py-2 text-[11px] leading-5 shadow-xl backdrop-blur">
410
+ <div class="text-primary font-semibold" id="nodeTitle"></div>
411
+ <div class="text-slate-300" id="nodeDesc"></div>
412
+ </div>
413
+
414
+ <script>
415
+ // Animation helpers
416
+ const animateItems = document.querySelectorAll('[data-animate]');
417
+ animateItems.forEach(el => {
418
+ el.style.opacity = '0';
419
+ el.style.transform = 'translateY(10px)';
420
+ setTimeout(() => {
421
+ el.style.transition = 'all .6s cubic-bezier(.2,.7,.2,1)';
422
+ el.style.opacity = '1';
423
+ el.style.transform = 'translateY(0)';
424
+ }, 120);
425
+ });
426
+
427
+ // Node definitions and info
428
+ const nodeInfo = {
429
+ documentation: {
430
+ title: 'Documentation',
431
+ desc: 'Système de documentation intégré avec recherche et exemples (wiki, API, UML).'
432
+ },
433
+ editor: {
434
+ title: 'Code Editor',
435
+ desc: 'Éditeur de code avec coloration syntaxique, auto-complétion, refactorisations.'
436
+ },
437
+ terminal: {
438
+ title: 'Terminal',
439
+ desc: 'Terminal intégré multi‑onglets avec support de plusieurs shells et historique.'
440
+ },
441
+ debugger: {
442
+ title: 'Debugger',
443
+ desc: 'Debugger graphique avec breakpoints, inspection, watch, step‑by‑step.'
444
+ },
445
+ version: {
446
+ title: 'Version Control',
447
+ desc: 'Contrôle de version (Git) avec interface graphique, branches et historial.'
448
+ },
449
+ testing: {
450
+ title: 'Testing Framework',
451
+ desc: 'Tests unitaires, d’intégration et end‑to‑end. Couverture de code et rapports.'
452
+ },
453
+ build: {
454
+ title: 'Build System',
455
+ desc: 'Pipeline de build et CI/CD : compilation, packaging et déploiement automatisés.'
456
+ },
457
+ deploy: {
458
+ title: 'Deployment',
459
+ desc: 'Déploiement vers staging/production (cloud), rollback et monitoring.'
460
+ },
461
+ };
462
+
463
+ // Connections for arrows (visual only)
464
+ const connections = [
465
+ { from: 'documentation', to: 'editor', label: 'docs' },
466
+ { from: 'editor', to: 'terminal', label: 'exec' },
467
+ { from: 'editor', to: 'debugger', label: 'debug' },
468
+ { from: 'editor', to: 'build', label: 'build' },
469
+ { from: 'version', to: 'editor', label: 'vcs' },
470
+ { from: 'terminal', to: 'testing', label: 'test' },
471
+ { from: 'debugger', to: 'testing', label: 'verify' },
472
+ { from: 'testing', to: 'deploy', label: 'deploy' },
473
+ { from: 'build', to: 'deploy', label: 'package' },
474
+ { from: 'deploy', to: 'version', label: 'release' },
475
+ ];
476
+
477
+ // Build arrows
478
+ function drawArrows() {
479
+ const svg = document.getElementById('arrowLayer');
480
+ if (!svg) return;
481
+ svg.innerHTML = '';
482
+
483
+ const root = document.getElementById('schemaRoot');
484
+ const rootRect = root.getBoundingClientRect();
485
+
486
+ function centerOf(id) {
487
+ const el = root.querySelector(`[data-id="${id}"]`);
488
+ if (!el) return { x: 0, y: 0 };
489
+ const r = el.getBoundingClientRect();
490
+ return {
491
+ x: r.left - rootRect.left + r.width / 2,
492
+ y: r.top - rootRect.top + r.height / 2
493
+ };
494
+ }
495
+
496
+ connections.forEach((c, idx) => {
497
+ const from = centerOf(c.from);
498
+ const to = centerOf(c.to);
499
+
500
+ // Curved path
501
+ const dx = to.x - from.x;
502
+ const dy = to.y - from.y;
503
+ const dist = Math.hypot(dx, dy);
504
+ const curve = Math.min(80, Math.max(30, dist * 0.25));
505
+
506
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
507
+ const d = `M ${from.x} ${from.y}
508
+ C ${from.x + curve} ${from.y}
509
+ ${to.x - curve} ${to.y}
510
+ ${to.x} ${to.y}`;
511
+ path.setAttribute('d', d);
512
+ path.setAttribute('fill', 'none');
513
+ path.setAttribute('stroke', 'rgba(148,163,184,0.55)');
514
+ path.setAttribute('stroke-width', '1.25');
515
+ path.setAttribute('marker-end', 'url(#arrowHead)');
516
+ svg.appendChild(path);
517
+ });
518
+
519
+ // Marker
520
+ let defs = svg.querySelector('defs');
521
+ if (!defs) {
522
+ defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
523
+ svg.appendChild(defs);
524
+ }
525
+ let marker = svg.querySelector('#arrowHead');
526
+ if (!marker) {
527
+ marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker');
528
+ marker.setAttribute('id', 'arrowHead');
529
+ marker.setAttribute('viewBox', '0 0 10 10');
530
+ marker.setAttribute('refX', '8');
531
+ marker.setAttribute('refY', '5');
532
+ marker.setAttribute('markerWidth', '6');
533
+ marker.setAttribute('markerHeight', '6');
534
+ marker.setAttribute('orient', 'auto-start-reverse');
535
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
536
+ path.setAttribute('d', 'M 0 0 L 10 5 L 0 10 z');
537
+ path.setAttribute('fill', 'rgba(148,163,184,0.9)');
538
+ marker.appendChild(path);
539
+ defs.appendChild(marker);
540
+ }
541
+ }
542
+
543
+ // Node interactions + tooltip
544
+ function setupNodes() {
545
+ const tooltip = document.getElementById('nodeTooltip');
546
+ const title = document.getElementById('nodeTitle');
547
+ const desc = document.getElementById('nodeDesc');
548
+
549
+ document.querySelectorAll('.node-btn').forEach(btn => {
550
+ btn.addEventListener('click', (e) => {
551
+ const id = btn.dataset.id;
552
+ const info = nodeInfo[id];
553
+ if (!info) return;
554
+
555
+ // Visual pulse
556
+ btn.classList.add('ring-2', 'ring-primary/60');
557
+ setTimeout(() => btn.classList.remove('ring-2', 'ring-primary/60'), 600);
558
+
559
+ // Tooltip content
560
+ title.textContent = info.title;
561
+ desc.textContent = info.desc;
562
+ tooltip.classList.remove('hidden');
563
+
564
+ // Position near button
565
+ const r = btn.getBoundingClientRect();
566
+ tooltip.style.left = `${Math.min(window.innerWidth - 260, r.right + 10)}px`;
567
+ tooltip.style.top = `${r.top + window.scrollY}px`;
568
+
569
+ setTimeout(() => tooltip.classList.add('hidden'), 2800);
570
+ });
571
+ });
572
+
573
+ document.addEventListener('click', (e) => {
574
+ if (!e.target.closest('.node-btn')) {
575
+ tooltip.classList.add('hidden');
576
+ }
577
+ });
578
+ }
579
+
580
+ // Builder demo logic
581
+ function setupBuilderDemo() {
582
+ const output = document.getElementById('demoOutput');
583
+ const btnMinimal = document.getElementById('btn-minimal');
584
+ const btnFullstack = document.getElementById('btn-fullstack');
585
+ const btnReset = document.getElementById('btn-reset');
586
+
587
+ function clearOutput() {
588
+ output.innerHTML = '<div>Prêt à construire un espace de codage…</div>';
589
+ }
590
+ function addLine(text, kind = 'info') {
591
+ const line = document.createElement('div');
592
+ line.className = 'mb-1';
593
+ if (kind === 'ok') line.classList.add('text-success');
594
+ if (kind === 'warn') line.classList.add('text-warning');
595
+ line.textContent = text;
596
+ output.appendChild(line);
597
+ output.scrollTop = output.scrollHeight;
598
+ }
599
+ function highlightNode(id) {
600
+ const node = document.querySelector(`[data-id="${id}"]`);
601
+ if (!node) return;
602
+ node.classList.add('ring-2', 'ring-accent/70');
603
+ setTimeout(() => node.classList.remove('ring-2', 'ring-accent/70'), 900);
604
+ }
605
+
606
+ const minimalSteps = [
607
+ { id: 'documentation', msg: 'Configuration de la documentation simple (README).' },
608
+ { id: 'editor', msg: 'Configuration de l’éditeur VS Code (thème par défaut).' },
609
+ { id: 'terminal', msg: 'Configuration du terminal intégré et du debug minimal.' },
610
+ { id: 'build', msg: 'Configuration du système de build minimal (exécution directe).' },
611
+ { id: 'testing', msg: 'Configuration des tests manuels.' },
612
+ { id: 'deploy', msg: 'Configuration du déploiement local.' },
613
+ ];
614
+
615
+ const fullstackSteps = [
616
+ { id: 'documentation', msg: 'Configuration de la documentation complète (wiki, UML, API).' },
617
+ { id: 'editor', msg: 'Configuration de l’IDE avancé et des plugins.' },
618
+ { id: 'terminal', msg: 'Configuration du terminal multi‑onglets et debugger graphique.' },
619
+ { id: 'build', msg: 'Configuration du pipeline CI/CD automatisé.' },
620
+ { id: 'testing', msg: 'Configuration du framework de tests complet (unitaires, intégration, e2e).' },
621
+ { id: 'deploy', msg: 'Configuration du déploiement cloud (AWS, Docker, Kubernetes).' },
622
+ ];
623
+
624
+ function runDemo(type) {
625
+ clearOutput();
626
+ const steps = type === 'minimal' ? minimalSteps : fullstackSteps;
627
+
628
+ let delay = 0;
629
+ steps.forEach((s, i) => {
630
+ setTimeout(() => {
631
+ addLine(`→ ${s.msg}`);
632
+ highlightNode(s.id);
633
+ }, delay);
634
+ delay += 650;
635
+ });
636
+
637
+ // Completion
638
+ setTimeout(() => {
639
+ addLine('✅ Projet ' + (type === 'minimal' ? 'minimal' : 'full‑stack') + ' construit avec succès.', 'ok');
640
+ }, delay + 200);
641
+ }
642
+
643
+ btnMinimal.addEventListener('click', () => runDemo('minimal'));
644
+ btnFullstack.addEventListener('click', () => runDemo('fullstack'));
645
+ btnReset.addEventListener('click', () => clearOutput());
646
+ }
647
+
648
+ // Initial draw
649
+ window.addEventListener('load', () => {
650
+ drawArrows();
651
+ setupNodes();
652
+ setupBuilderDemo();
653
+ });
654
+ window.addEventListener('resize', () => {
655
+ // Throttle redraw
656
+ clearTimeout(window.__arrowTimer);
657
+ window.__arrowTimer = setTimeout(drawArrows, 120);
658
+ });
659
+ </script>
660
+
661
+ <!-- Tailwind utilities via @apply -->
662
+ <style type="text/tailwindcss">
663
+ @layer utilities {
664
+ .animate-spin-slow {
665
+ animation: spin 8s linear infinite;
666
+ }
667
+ @keyframes spin {
668
+ to { transform: rotate(360deg); }
669
+ }
670
+ .node-btn {
671
+ @apply inline-flex items-center justify-center px-4 py-2 text-[11px] tracking-[0.18em] uppercase rounded-full border border-border bg-slate-900/60 hover:bg-slate-800/70 transition;
672
+ }
673
+ .node-main {
674
+ @apply border-primary/70 bg-gradient-to-br from-primary/15 to-accent/10 text-white;
675
+ }
676
+ .btn-primary {
677
+ @apply inline-flex items-center gap-2 px-4 py-2 rounded-full border border-primary/60 bg-primary/15 hover:bg-primary/25 text-primary transition;
678
+ }
679
+ .btn-secondary {
680
+ @apply inline-flex items-center gap-2 px-4 py-2 rounded-full border border-secondary/60 bg-secondary/15 hover:bg-secondary/25 text-secondary transition;
681
+ }
682
+ .btn-ghost {
683
+ @apply inline-flex items-center gap-2 px-4 py-2 rounded-full border border-border bg-transparent hover:bg-slate-800/50 text-slate-300 transition;
684
+ }
685
+ .badge {
686
+ @apply text-[10px] uppercase tracking-[0.18em] rounded-full border border-border px-2 py-0.5 text-slate-300;
687
+ }
688
+ }
689
+ </style>
690
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
691
+ </body>
692
+ </html>