185 lines
6.9 KiB
PHP
Executable File
185 lines
6.9 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* WEVIA OPUS — Output Formatting Engine
|
|
*
|
|
* Formate les réponses de WEVIA dans le format optimal:
|
|
* - Markdown structuré
|
|
* - Code blocks avec syntax highlighting
|
|
* - Tableaux pour les comparaisons
|
|
* - Mermaid pour les diagrammes
|
|
* - JSON pour les données structurées
|
|
* - HTML pour les emails/rapports
|
|
*/
|
|
|
|
class OutputFormatter {
|
|
|
|
/**
|
|
* Formate une réponse en fonction du type détecté
|
|
*/
|
|
public function format(string $content, string $type = 'auto'): string {
|
|
if ($type === 'auto') {
|
|
$type = $this->detectType($content);
|
|
}
|
|
|
|
switch ($type) {
|
|
case 'code': return $this->formatCode($content);
|
|
case 'table': return $this->formatTable($content);
|
|
case 'list': return $this->formatList($content);
|
|
case 'steps': return $this->formatSteps($content);
|
|
case 'comparison': return $this->formatComparison($content);
|
|
case 'diagram': return $this->formatDiagram($content);
|
|
default: return $this->formatProse($content);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Détecte le type de contenu optimal
|
|
*/
|
|
private function detectType(string $content): string {
|
|
if (preg_match('/```|function |class |SELECT |def |import |<\?php/', $content)) return 'code';
|
|
if (preg_match('/\|.*\|.*\|/', $content)) return 'table';
|
|
if (preg_match('/^\s*[-*]\s/m', $content) && substr_count($content, "\n-") > 3) return 'list';
|
|
if (preg_match('/étape\s+\d|step\s+\d|1\.\s+.*\n2\.\s+/i', $content)) return 'steps';
|
|
if (preg_match('/vs\.?\s|versus|comparaison|comparer/i', $content)) return 'comparison';
|
|
if (preg_match('/flowchart|graph|sequenceDiagram|classDiagram/', $content)) return 'diagram';
|
|
return 'prose';
|
|
}
|
|
|
|
/**
|
|
* Formate du code avec metadata
|
|
*/
|
|
private function formatCode(string $content): string {
|
|
// Détecter le langage si pas spécifié
|
|
if (!preg_match('/```(\w+)/', $content)) {
|
|
$lang = $this->detectCodeLanguage($content);
|
|
$content = preg_replace('/```\n/', "```$lang\n", $content, 1);
|
|
}
|
|
return $content;
|
|
}
|
|
|
|
private function detectCodeLanguage(string $code): string {
|
|
if (preg_match('/<\?php|function\s+\w+\s*\(.*\)\s*{|\$this->/', $code)) return 'php';
|
|
if (preg_match('/def\s+\w+|import\s+\w+|from\s+\w+\s+import/', $code)) return 'python';
|
|
if (preg_match('/const\s+\w+\s*=|let\s+\w+|=>\s*{|require\(/', $code)) return 'javascript';
|
|
if (preg_match('/SELECT\s+|INSERT\s+|CREATE\s+TABLE/i', $code)) return 'sql';
|
|
if (preg_match('/#!/', $code)) return 'bash';
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Génère un tableau Markdown depuis des données
|
|
*/
|
|
public function generateTable(array $headers, array $rows): string {
|
|
$table = '| ' . implode(' | ', $headers) . " |\n";
|
|
$table .= '| ' . implode(' | ', array_fill(0, count($headers), '---')) . " |\n";
|
|
foreach ($rows as $row) {
|
|
$table .= '| ' . implode(' | ', array_map('strval', $row)) . " |\n";
|
|
}
|
|
return $table;
|
|
}
|
|
|
|
/**
|
|
* Génère un diagramme Mermaid
|
|
*/
|
|
public function generateFlowchart(array $steps, string $direction = 'TD'): string {
|
|
$mermaid = "```mermaid\nflowchart $direction\n";
|
|
foreach ($steps as $i => $step) {
|
|
$id = 'S' . ($i + 1);
|
|
$mermaid .= " {$id}[\"" . addslashes($step['label']) . "\"]\n";
|
|
if (isset($step['next'])) {
|
|
foreach ((array)$step['next'] as $next) {
|
|
$nextId = 'S' . $next;
|
|
$label = $step['edge_label'] ?? '';
|
|
$mermaid .= $label ?
|
|
" $id -->|\"$label\"| $nextId\n" :
|
|
" $id --> $nextId\n";
|
|
}
|
|
}
|
|
// Styling
|
|
if (isset($step['style'])) {
|
|
$mermaid .= " style $id {$step['style']}\n";
|
|
}
|
|
}
|
|
$mermaid .= "```\n";
|
|
return $mermaid;
|
|
}
|
|
|
|
/**
|
|
* Génère un diagramme de séquence Mermaid
|
|
*/
|
|
public function generateSequenceDiagram(array $interactions): string {
|
|
$mermaid = "```mermaid\nsequenceDiagram\n";
|
|
foreach ($interactions as $interaction) {
|
|
$from = $interaction['from'];
|
|
$to = $interaction['to'];
|
|
$message = addslashes($interaction['message']);
|
|
$type = $interaction['type'] ?? '->>'; // ->> solid, -->> dashed
|
|
$mermaid .= " $from$type$to: $message\n";
|
|
if (isset($interaction['note'])) {
|
|
$mermaid .= " Note over $from,$to: {$interaction['note']}\n";
|
|
}
|
|
}
|
|
$mermaid .= "```\n";
|
|
return $mermaid;
|
|
}
|
|
|
|
/**
|
|
* Formate des étapes numérotées avec statut
|
|
*/
|
|
public function formatStepsWithStatus(array $steps): string {
|
|
$output = '';
|
|
foreach ($steps as $i => $step) {
|
|
$num = $i + 1;
|
|
$status = $step['status'] ?? 'pending';
|
|
$emoji = match($status) {
|
|
'done' => '✅',
|
|
'in_progress' => '🔄',
|
|
'failed' => '❌',
|
|
'skipped' => '⏭️',
|
|
default => '⬜'
|
|
};
|
|
$output .= "$emoji **Étape $num**: {$step['description']}\n";
|
|
if (isset($step['detail'])) {
|
|
$output .= " _{$step['detail']}_\n";
|
|
}
|
|
if (isset($step['command'])) {
|
|
$output .= " ```bash\n {$step['command']}\n ```\n";
|
|
}
|
|
$output .= "\n";
|
|
}
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Génère un résumé exécutif structuré
|
|
*/
|
|
public function executiveSummary(string $title, array $sections): string {
|
|
$md = "# $title\n\n";
|
|
$md .= "**Date**: " . date('d/m/Y H:i') . "\n\n";
|
|
$md .= "---\n\n";
|
|
|
|
foreach ($sections as $section) {
|
|
$md .= "## {$section['title']}\n\n";
|
|
$md .= "{$section['content']}\n\n";
|
|
|
|
if (isset($section['metrics'])) {
|
|
$md .= $this->generateTable(
|
|
['Métrique', 'Valeur', 'Status'],
|
|
array_map(fn($k, $v) => [$k, $v['value'], $v['status'] ?? ''],
|
|
array_keys($section['metrics']), array_values($section['metrics']))
|
|
);
|
|
$md .= "\n";
|
|
}
|
|
}
|
|
|
|
return $md;
|
|
}
|
|
|
|
private function formatProse(string $content): string { return $content; }
|
|
private function formatTable(string $content): string { return $content; }
|
|
private function formatList(string $content): string { return $content; }
|
|
private function formatSteps(string $content): string { return $content; }
|
|
private function formatComparison(string $content): string { return $content; }
|
|
private function formatDiagram(string $content): string { return $content; }
|
|
}
|