From a15d2260d1379e105471e91fcf0f6dcb0643c595 Mon Sep 17 00:00:00 2001 From: Esenjin Date: Sun, 16 Feb 2025 22:34:33 +0100 Subject: [PATCH] =?UTF-8?q?ajout=20de=20stats=20=C3=A0=20la=20page=20"?= =?UTF-8?q?=C3=A0=20propos"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- about.php | 75 ++++++++++++++++++++++++++- assets/css/public.css | 3 ++ assets/css/stats.css | 73 ++++++++++++++++++++++++++ includes/Stats.php | 118 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 assets/css/stats.css create mode 100644 includes/Stats.php diff --git a/about.php b/about.php index 50bf1e0..19c5d95 100644 --- a/about.php +++ b/about.php @@ -1,6 +1,7 @@ '' ]; +// Charger les statistiques +$stats = new Stats(); +$siteStats = $stats->getStats(); + // Fonction pour convertir le contenu Delta en HTML function deltaToHtml($content) { return DeltaConverter::toHtml($content); @@ -38,10 +43,78 @@ function deltaToHtml($content) { -
+
+ +
diff --git a/assets/css/public.css b/assets/css/public.css index 5d528f5..f32a43a 100644 --- a/assets/css/public.css +++ b/assets/css/public.css @@ -1,3 +1,6 @@ +/* Import d'autres fichiers CSS */ +@import 'stats.css'; + /* Import Google Fonts */ @import url('https://fonts.googleapis.com/css2?family=Parisienne&display=swap'); diff --git a/assets/css/stats.css b/assets/css/stats.css new file mode 100644 index 0000000..3d349c3 --- /dev/null +++ b/assets/css/stats.css @@ -0,0 +1,73 @@ +.stats-menu { + background: var(--bg-tertiary); + padding: var(--spacing-lg); + border-radius: var(--radius-md); + border: 1px solid var(--border-color); + position: sticky; + top: var(--spacing-lg); + align-self: start; +} + +.stats-menu h2 { + font-size: 1.5rem; + margin-bottom: var(--spacing-md); + color: var(--text-primary); + padding-bottom: var(--spacing-sm); + border-bottom: 2px solid var(--accent-primary); +} + +.stats-list { + list-style: none; + margin: 0; + padding: 0; +} + +.stats-item { + margin-bottom: var(--spacing-md); + padding-bottom: var(--spacing-md); + border-bottom: 1px solid var(--border-color); +} + +.stats-item:last-child { + border-bottom: none; + margin-bottom: 0; + padding-bottom: 0; +} + +.stats-label { + font-size: 0.9rem; + color: var(--text-secondary); + margin-bottom: var(--spacing-xs); +} + +.stats-value { + font-size: 1.2rem; + color: var(--text-primary); + font-weight: bold; +} + +.stats-detail { + font-size: 0.85rem; + color: var(--accent-primary); + margin-top: var(--spacing-xs); +} + +/* Style pour les liens dans les stats */ +.stats-detail a { + color: var(--accent-primary); + text-decoration: none; + transition: color var(--transition-fast); +} + +.stats-detail a:hover { + color: var(--accent-secondary); + text-decoration: underline; +} + +/* Media queries */ +@media (max-width: 900px) { + .stats-menu { + position: static; + margin-top: var(--spacing-xl); + } +} \ No newline at end of file diff --git a/includes/Stats.php b/includes/Stats.php new file mode 100644 index 0000000..2f4d486 --- /dev/null +++ b/includes/Stats.php @@ -0,0 +1,118 @@ +loadStories(); + $this->calculateStats(); + } + + private function loadStories() { + foreach (glob(self::$storiesDir . '*.json') as $file) { + $this->stories[] = json_decode(file_get_contents($file), true); + } + } + + private function calculateStats() { + $totalChapters = 0; + $totalWords = 0; + $maxChapters = 0; + $storyWithMostChapters = null; + $lastUpdate = null; + $mostRecentStory = null; + $longestChapter = [ + 'words' => 0, + 'story' => null, + 'chapter' => null + ]; + + foreach ($this->stories as $story) { + // Compter les chapitres + $chapterCount = count($story['chapters'] ?? []); + $totalChapters += $chapterCount; + + // Trouver le roman avec le plus de chapitres + if ($chapterCount > $maxChapters) { + $maxChapters = $chapterCount; + $storyWithMostChapters = $story; + } + + // Trouver la dernière mise à jour + $storyUpdate = strtotime($story['updated']); + if (!$lastUpdate || $storyUpdate > $lastUpdate) { + $lastUpdate = $storyUpdate; + $mostRecentStory = $story; + } + + // Compter les mots et trouver le plus long chapitre + foreach ($story['chapters'] ?? [] as $chapter) { + $content = $chapter['content']; + + // Si le contenu est au format JSON (Delta) + if (is_string($content) && $this->isJson($content)) { + $content = json_decode($content, true); + $text = ''; + if (isset($content['ops'])) { + foreach ($content['ops'] as $op) { + if (is_string($op['insert'])) { + $text .= $op['insert']; + } + } + } + } else { + // Si le contenu est en HTML + $text = strip_tags($content); + } + + $wordCount = str_word_count(strip_tags($text)); + $totalWords += $wordCount; + + if ($wordCount > $longestChapter['words']) { + $longestChapter = [ + 'words' => $wordCount, + 'story' => $story, + 'chapter' => $chapter + ]; + } + } + } + + $this->stats = [ + 'total_stories' => count($this->stories), + 'total_chapters' => $totalChapters, + 'total_words' => $totalWords, + 'avg_chapters_per_story' => $this->stories ? round($totalChapters / count($this->stories), 1) : 0, + 'avg_words_per_chapter' => $totalChapters ? round($totalWords / $totalChapters) : 0, + 'most_chapters' => [ + 'story' => $storyWithMostChapters, + 'count' => $maxChapters + ], + 'longest_chapter' => $longestChapter, + 'latest_update' => [ + 'story' => $mostRecentStory, + 'date' => $lastUpdate + ] + ]; + } + + public function getStats() { + return $this->stats; + } + + private function isJson($string) { + json_decode($string); + return json_last_error() === JSON_ERROR_NONE; + } + + // Méthodes utilitaires pour le formatage + public static function formatNumber($number) { + return number_format($number, 0, ',', ' '); + } + + public static function formatDate($timestamp) { + if (!$timestamp) return 'Jamais'; + return date('d/m/Y', $timestamp); + } +} \ No newline at end of file