mirror of
https://forge.chapril.org/tykayn/orgmode-to-gemini-blog
synced 2025-11-19 23:00:35 +01:00
435 lines
22 KiB
Django/Jinja
435 lines
22 KiB
Django/Jinja
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Statistiques - {{blog_title}}</title>
|
|
<link rel="stylesheet" href="{{css_path}}">
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>📊 Statistiques de production - {{blog_title}}</h1>
|
|
{% if author %}
|
|
<p><strong>Auteur:</strong> {{author}}</p>
|
|
{% endif %}
|
|
|
|
<h2>Vue d'ensemble</h2>
|
|
{% if date_debut_ecriture %}
|
|
<p style="color: #666; margin-bottom: 15px;">
|
|
<strong>Date de début d'écriture:</strong> {{date_debut_ecriture}}
|
|
</p>
|
|
{% endif %}
|
|
<div class="stats-grid">
|
|
<div class="stat-card">
|
|
<h3>Articles publiés</h3>
|
|
<div class="value">{{nb_articles_total|int|format_number}}</div>
|
|
{% if articles_par_jour_moyen is defined %}
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">
|
|
{{articles_par_jour_moyen|round(3)}} /j,
|
|
{{articles_par_mois_moyen|round(2)}} /mois,
|
|
{{articles_par_annee_moyen|round(2)}} /an
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="stat-card blue">
|
|
<h3>Mots totaux</h3>
|
|
<div class="value">{{mots_total|int|format_number}}</div>
|
|
{% if mots_par_jour_moyen is defined %}
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">
|
|
{{mots_par_jour_moyen|int|format_number}} /j,
|
|
{{mots_par_mois_moyen|int|format_number}} /mois,
|
|
{{mots_par_annee_moyen|int|format_number}} /an
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="stat-card green">
|
|
<h3>Signes (espaces inclus)</h3>
|
|
<div class="value">{{signes_total|int|format_number}}</div>
|
|
{% if signes_par_jour_moyen is defined %}
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">
|
|
{{signes_par_jour_moyen|int|format_number}} /j,
|
|
{{signes_par_mois_moyen|int|format_number}} /mois,
|
|
{{signes_par_annee_moyen|int|format_number}} /an
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="stat-card orange">
|
|
<h3>Temps de lecture total</h3>
|
|
<div class="value">{{temps_lecture_total|format_duree}}</div>
|
|
{% if temps_lecture_par_jour_moyen is defined %}
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">
|
|
{{temps_lecture_par_jour_moyen|format_duree}} /j,
|
|
{{temps_lecture_par_mois_moyen|format_duree}} /mois,
|
|
{{temps_lecture_par_annee_moyen|format_duree}} /an
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="stat-card purple">
|
|
<h3>Liens totaux</h3>
|
|
<div class="value">{{liens_total|int|format_number}}</div>
|
|
{% if liens_par_jour_moyen is defined %}
|
|
<div style="font-size: 0.9em; color: #666; margin-top: 5px;">
|
|
{{liens_par_jour_moyen|round(2)}} /j,
|
|
{{liens_par_mois_moyen|round(1)}} /mois,
|
|
{{liens_par_annee_moyen|round(1)}} /an
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<h2>Répartition des liens</h2>
|
|
<div class="stats-grid">
|
|
<div class="stat-card blue">
|
|
<h3>Liens images</h3>
|
|
<div class="value">{{liens_images_total|int|format_number}}</div>
|
|
</div>
|
|
<div class="stat-card green">
|
|
<h3>Autres liens</h3>
|
|
<div class="value">{{liens_autres_total|int|format_number}}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>Moyennes par article</h2>
|
|
<div class="stats-grid">
|
|
<div class="stat-card">
|
|
<h3>Mots par article</h3>
|
|
<div class="value">{{mots_moyen|int|format_number}}</div>
|
|
</div>
|
|
<div class="stat-card blue">
|
|
<h3>Liens par article</h3>
|
|
<div class="value">{{liens_moyen|round(1)}}</div>
|
|
</div>
|
|
<div class="stat-card purple">
|
|
<h3>Liens images par article</h3>
|
|
<div class="value">{{liens_images_moyen|round(1)}}</div>
|
|
</div>
|
|
<div class="stat-card orange">
|
|
<h3>Autres liens par article</h3>
|
|
<div class="value">{{liens_autres_moyen|round(1)}}</div>
|
|
</div>
|
|
<div class="stat-card green">
|
|
<h3>Signes par article</h3>
|
|
<div class="value">{{signes_moyen|int|format_number}}</div>
|
|
</div>
|
|
<div class="stat-card orange">
|
|
<h3>Temps de lecture par article</h3>
|
|
<div class="value">{{temps_lecture_par_article|format_duree}}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>Vitesse et fréquence de rédaction</h2>
|
|
<div class="stats-grid">
|
|
<div class="stat-card">
|
|
<h3>Fréquence moyenne</h3>
|
|
<div class="value">{{frequence|round(2)}}</div>
|
|
<p>articles par mois</p>
|
|
</div>
|
|
<div class="stat-card blue">
|
|
<h3>Vitesse d'écriture</h3>
|
|
<div class="value">{{mots_par_mois_moyen|int|format_number}}</div>
|
|
<p>mots par mois</p>
|
|
</div>
|
|
<div class="stat-card green">
|
|
<h3>Premier article</h3>
|
|
<div class="value" style="font-size: 18px;">{{premiere_date_str}}</div>
|
|
</div>
|
|
<div class="stat-card orange">
|
|
<h3>Dernier article</h3>
|
|
<div class="value" style="font-size: 18px;">{{derniere_date_str}}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if graphiques %}
|
|
<h2>Graphiques</h2>
|
|
{% for graph_file, graph_title in graphiques %}
|
|
<div class="graph-container">
|
|
<div class="graph-title">{{graph_title}}</div>
|
|
<img src="stats_graphs/{{graph_file}}" alt="{{graph_title}}">
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{% if stats_nanowrimo %}
|
|
<h2>Statistiques NaNoWriMo - 12 derniers mois</h2>
|
|
<div class="nanowrimo-section">
|
|
<p><strong>Objectif quotidien:</strong> 1667 signes (espaces compris) par jour</p>
|
|
{% for mois_stats in stats_nanowrimo %}
|
|
<div class="nanowrimo-month">
|
|
<h3>
|
|
{{mois_stats.mois_formate}}
|
|
{% if mois_stats.depassement > 0 %}
|
|
⭐ <span style="color: #FFC107; font-size: 0.9em;">+{{mois_stats.depassement|int|format_number}} signes</span>
|
|
{% endif %}
|
|
</h3>
|
|
|
|
{% if mois_stats.objectif_articles is not none %}
|
|
<div class="progress-info">
|
|
<strong>Objectif d'articles ce mois:</strong> {{mois_stats.objectif_articles}}
|
|
| <strong>Réalisés:</strong> {{mois_stats.articles_realises}}
|
|
{% set pourcentage_articles = (mois_stats.articles_realises / mois_stats.objectif_articles * 100) if mois_stats.objectif_articles > 0 else 0 %}
|
|
| <strong>Progression:</strong> {{pourcentage_articles|round(1)}}%
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="progress-info">
|
|
<strong>Signes réalisés:</strong> {{mois_stats.signes_realises|int|format_number}}
|
|
/ {{mois_stats.objectif_total|int|format_number}}
|
|
({{mois_stats.objectif_quotidien|int|format_number}} par jour)
|
|
{% if mois_stats.est_mois_courant %}
|
|
| <strong>Aujourd'hui:</strong> {{mois_stats.signes_aujourdhui|int|format_number}} signes
|
|
{% endif %}
|
|
{% if mois_stats.reste_a_faire > 0 and not mois_stats.est_mois_futur %}
|
|
| <strong>Reste à faire:</strong> {{mois_stats.reste_a_faire|int|format_number}} signes
|
|
{% endif %}
|
|
{% if mois_stats.signes_par_jour_moyen > 0 %}
|
|
| <strong>Moyenne par jour:</strong> {{mois_stats.signes_par_jour_moyen|int|format_number}} signes/jour
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="progress-container">
|
|
<div class="progress-bar">
|
|
{% set signes_sans_aujourdhui = mois_stats.signes_realises - mois_stats.signes_aujourdhui %}
|
|
{% set objectif_jusqu_aujourdhui = mois_stats.objectif_jusqu_aujourdhui if mois_stats.est_mois_courant else mois_stats.objectif_total %}
|
|
{% set reste_a_faire_calc = objectif_jusqu_aujourdhui - mois_stats.signes_realises %}
|
|
{% set reste_a_faire = reste_a_faire_calc if reste_a_faire_calc > 0 else 0 %}
|
|
|
|
{% set total_pour_barre = mois_stats.objectif_total %}
|
|
{% if mois_stats.depassement > 0 %}
|
|
{% set total_pour_barre = mois_stats.signes_realises %}
|
|
{% endif %}
|
|
|
|
{% set pourcentage_aujourdhui = (mois_stats.signes_aujourdhui / total_pour_barre * 100) if total_pour_barre > 0 and mois_stats.est_mois_courant else 0 %}
|
|
{% set pourcentage_restant = (signes_sans_aujourdhui / total_pour_barre * 100) if total_pour_barre > 0 else 0 %}
|
|
{% set pourcentage_depassement = (mois_stats.depassement / total_pour_barre * 100) if total_pour_barre > 0 and mois_stats.depassement > 0 else 0 %}
|
|
{% set pourcentage_reste = (reste_a_faire / total_pour_barre * 100) if total_pour_barre > 0 and reste_a_faire > 0 else 0 %}
|
|
|
|
{% if mois_stats.signes_aujourdhui > 0 and mois_stats.est_mois_courant %}
|
|
<div class="progress-segment blue" style="width: {{pourcentage_aujourdhui}}%">
|
|
{% if pourcentage_aujourdhui > 3 %}
|
|
Aujourd'hui
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if signes_sans_aujourdhui > 0 %}
|
|
<div class="progress-segment blue-light" style="width: {{pourcentage_restant}}%">
|
|
{% if pourcentage_restant > 3 %}
|
|
{{signes_sans_aujourdhui|int|format_number}}
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if reste_a_faire > 0 and not mois_stats.est_mois_futur %}
|
|
<div class="progress-segment gray" style="width: {{pourcentage_reste}}%">
|
|
{% if pourcentage_reste > 3 %}
|
|
Reste
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if mois_stats.depassement > 0 %}
|
|
<div class="progress-segment yellow" style="width: {{pourcentage_depassement}}%">
|
|
{% if pourcentage_depassement > 3 %}
|
|
+{{mois_stats.depassement|int|format_number}}
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{% if mois_stats.est_mois_courant %}
|
|
<div class="progress-info">
|
|
<strong>Progression:</strong> {{mois_stats.pourcentage_realise|round(1)}}%
|
|
(objectif jusqu'à aujourd'hui: {{mois_stats.objectif_jusqu_aujourdhui|int|format_number}} signes)
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if mois_stats.articles_du_mois %}
|
|
<div style="margin-top: 15px;">
|
|
<strong>Articles du mois ({{mois_stats.articles_du_mois|length}}):</strong>
|
|
<ul style="margin-top: 5px; padding-left: 20px;">
|
|
{% for article in mois_stats.articles_du_mois %}
|
|
<li>
|
|
<strong>{{article.date.strftime('%d/%m/%Y')}}</strong> - {{article.fichier}}
|
|
<span style="color: #666; font-size: 0.9em;">
|
|
({{article.mots|int|format_number}} mots, {{article.signes|int|format_number}} signes)
|
|
</span>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
{% else %}
|
|
<div style="margin-top: 15px; color: #999; font-style: italic;">
|
|
Aucun article ce mois
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if sections_stats %}
|
|
<h2>Analyse des sections</h2>
|
|
{% set niveaux_vus = [] %}
|
|
{% set objectifs_text = [] %}
|
|
{% for section in sections_stats %}
|
|
{% if section.niveau not in niveaux_vus %}
|
|
{% set _ = niveaux_vus.append(section.niveau) %}
|
|
{% set _ = objectifs_text.append("Niveau " + section.niveau|string + " : " + section.objectif|int|string + " mots") %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
<p style="color: #666; margin-bottom: 15px; font-size: 0.95em;">
|
|
<strong>Objectif par section :</strong> {{objectifs_text|join(" | ")}}
|
|
</p>
|
|
<style>
|
|
.tooltip-container {
|
|
position: relative;
|
|
display: inline-block;
|
|
cursor: help;
|
|
}
|
|
.tooltip-text {
|
|
visibility: hidden;
|
|
opacity: 0;
|
|
background-color: #333;
|
|
color: #fff;
|
|
text-align: left;
|
|
padding: 10px;
|
|
border-radius: 6px;
|
|
position: absolute;
|
|
z-index: 1000;
|
|
bottom: 125%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
white-space: normal;
|
|
width: 250px;
|
|
font-size: 0.9em;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
transition: opacity 0.3s, visibility 0.3s;
|
|
}
|
|
.tooltip-container:hover .tooltip-text,
|
|
.tooltip-container:focus .tooltip-text {
|
|
visibility: visible;
|
|
opacity: 1;
|
|
}
|
|
.tooltip-text::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
border: 5px solid;
|
|
border-color: #333 transparent transparent transparent;
|
|
}
|
|
</style>
|
|
<table style="width: 100%; border-collapse: collapse; margin-bottom: 30px;">
|
|
<thead>
|
|
<tr>
|
|
<th style="text-align: left; padding: 10px; border-bottom: 2px solid #ddd;">Niveau</th>
|
|
<th style="text-align: left; padding: 10px; border-bottom: 2px solid #ddd;">Titre</th>
|
|
<th style="text-align: center; padding: 10px; border-bottom: 2px solid #ddd; width: 300px;">Mots</th>
|
|
<th style="text-align: right; padding: 10px; border-bottom: 2px solid #ddd;">Mots</th>
|
|
<th style="text-align: right; padding: 10px; border-bottom: 2px solid #ddd;">Signes</th>
|
|
<th style="text-align: right; padding: 10px; border-bottom: 2px solid #ddd;">Manquants</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for section in sections_stats %}
|
|
{% set max_mots_section = sections_stats|map(attribute='mots')|max %}
|
|
{% set barre_width = (section.mots / max_mots_section * 100) if max_mots_section > 0 else 0 %}
|
|
<tr style="{% if section.depasse %}border-left: 4px solid #4CAF50;{% else %}border-left: 4px solid transparent;{% endif %}">
|
|
<td style="padding: 10px; border-bottom: 1px solid #eee;">{{section.niveau}}</td>
|
|
<td style="padding: 10px; border-bottom: 1px solid #eee;">{{section.titre}}</td>
|
|
<td style="padding: 10px; border-bottom: 1px solid #eee;">
|
|
<div style="background-color: #f0f0f0; height: 20px; border-radius: 3px; position: relative; overflow: hidden;">
|
|
<div style="background-color: {% if section.depasse %}#4CAF50{% else %}#2196F3{% endif %}; height: 100%; width: {{barre_width}}%; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.85em; font-weight: bold;">
|
|
{% if barre_width > 10 %}{{section.mots|int|format_number}}{% endif %}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td style="text-align: right; padding: 10px; border-bottom: 1px solid #eee;">{{section.mots|int|format_number}}</td>
|
|
<td style="text-align: right; padding: 10px; border-bottom: 1px solid #eee;">{{section.signes|int|format_number}}</td>
|
|
<td style="text-align: right; padding: 10px; border-bottom: 1px solid #eee;">
|
|
<span class="tooltip-container" tabindex="0" role="button" aria-label="Détails sur les mots manquants">
|
|
{% if section.manquants > 0 %}
|
|
<span style="color: #f44336;">{{section.manquants|int|format_number}}</span>
|
|
{% else %}
|
|
<span style="color: #4CAF50;">✓</span>
|
|
{% endif %}
|
|
<span class="tooltip-text">
|
|
<strong>Section: {{section.titre}}</strong><br>
|
|
<strong>Objectif (niveau {{section.niveau}}):</strong> {{section.objectif|int|format_number}} mots<br>
|
|
<strong>Réalisé:</strong> {{section.mots|int|format_number}} mots<br>
|
|
<strong>Signes:</strong> {{section.signes|int|format_number}}<br><br>
|
|
<strong>État:</strong><br>
|
|
{% if section.depasse %}
|
|
✓ Objectif atteint ! (+{{(section.mots - section.objectif)|int|format_number}} mots au-delà de l'objectif)
|
|
{% else %}
|
|
En cours ({{section.manquants|int|format_number}} mots manquants pour atteindre l'objectif)
|
|
{% endif %}
|
|
</span>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{% if domaines_liens %}
|
|
<h2>Domaines des sites web liés</h2>
|
|
<table style="width: 100%; border-collapse: collapse; margin-bottom: 30px;">
|
|
<thead>
|
|
<tr>
|
|
<th style="text-align: left; padding: 10px; border-bottom: 2px solid #ddd;">Rang</th>
|
|
<th style="text-align: left; padding: 10px; border-bottom: 2px solid #ddd;">Domaine</th>
|
|
<th style="text-align: right; padding: 10px; border-bottom: 2px solid #ddd;">Occurrences</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for domaine, nombre in domaines_liens %}
|
|
<tr>
|
|
<td style="padding: 10px; border-bottom: 1px solid #eee; color: #666;">{{loop.index}}</td>
|
|
<td style="padding: 10px; border-bottom: 1px solid #eee;"><code style="background-color: #f5f5f5; padding: 2px 6px; border-radius: 3px;">{{domaine}}</code></td>
|
|
<td style="text-align: right; padding: 10px; border-bottom: 1px solid #eee;"><strong>{{nombre|int|format_number}}</strong></td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
<h2>Statistiques détaillées par mois</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Mois</th>
|
|
<th>Articles</th>
|
|
<th>Mots</th>
|
|
<th>Signes</th>
|
|
<th>Liens images</th>
|
|
<th>Autres liens</th>
|
|
<th>Temps de lecture</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for mois_cle, stats in stats_par_mois.items() %}
|
|
<tr>
|
|
<td>{{stats.mois_formate}}</td>
|
|
<td>{{stats.nb_articles}}</td>
|
|
<td>{{stats.mots_total|int|format_number}}</td>
|
|
<td>{{stats.signes_total|int|format_number}}</td>
|
|
<td>{{stats.liens_images_total}}</td>
|
|
<td>{{stats.liens_autres_total}}</td>
|
|
<td>{{stats.temps_lecture_total|format_duree}}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="footer">
|
|
<p>Statistiques générées le {{date_gen}}</p>
|
|
<p>Vitesse de lecture estimée: {{lecture_mots_par_minute}} mots/minute</p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
|