book-generator-orgmode/follow_progress.py

196 lines
7.3 KiB
Python
Executable file

# met à jour un fichier de suivi pour chaque livre
# le suivi se fait dans un fichier csv où chaque ligne est un compte rendu de statistiques du livre
# colonnes du csv: date; mots; intrigues; personnages; personnages_mots;
import csv
from datetime import date, timedelta, datetime
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import make_interp_spline
def mise_a_jour_suivi(fichier_csv, fichier_livre, fichier_personnages):
# Lire le fichier livre.org
with open(fichier_livre, 'r') as f:
contenu_livre = f.read()
mots_livre = len(contenu_livre.split())
chapitres = contenu_livre.count('* ')
sous_chapitres = contenu_livre.count('** ') + contenu_livre.count('*** ') + contenu_livre.count('**** ')
# Lire le fichier personnages.org
with open(fichier_personnages, 'r') as f:
contenu_personnages = f.read()
personnages_mots = len(contenu_personnages.split())
personnages = contenu_personnages.count('* ')
# Récupérer les valeurs pour les autres colonnes
intrigues = 5
# Mettre à jour le fichier de suivi
with open(fichier_csv, 'a', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=';')
now = datetime.now()
ligne = [now.isoformat(), mots_livre, intrigues, personnages, personnages_mots, chapitres, sous_chapitres]
writer.writerow(ligne)
# Exemple d'utilisation
fichier_csv ='suivi_livre.csv'
fichier_livre = 'livre.org'
fichier_personnages = 'personnages.org'
def analyse_csv(fichier_csv):
with open(fichier_csv, 'r') as csvfile:
reader = csv.reader(csvfile, delimiter=';')
donnees = list(reader)
# Récupérer les dates et les nombres de mots
dates_raw = [datetime.fromisoformat(donnee[0]) for donnee in donnees]
mots_raw = [int(donnee[1]) for donnee in donnees]
chapitres_raw = [int(donnee[5]) for donnee in donnees]
# Gérer les entrées dupliquées en gardant la dernière valeur pour chaque date
date_data = {}
for i, dt in enumerate(dates_raw):
date_key = dt.date()
date_data[date_key] = {
'mots': mots_raw[i],
'chapitres': chapitres_raw[i]
}
# Trier les dates et extraire les valeurs uniques
dates = sorted(date_data.keys())
mots = [date_data[d]['mots'] for d in dates]
chapitres = [date_data[d]['chapitres'] for d in dates]
# Créer les graphiques en aire adoucie
create_smooth_area_chart(dates, mots, "Evolution du nombre de mots", "evolution_mots.png")
create_smooth_area_chart(dates, chapitres, "Evolution du nombre de chapitres", "evolution_chapitres.png")
# Récupérer la date du jour
aujourd_hui = date.today()
oldest_count=0
hier = aujourd_hui - timedelta(days=1)
semaine_derniere = aujourd_hui - timedelta(days=7)
mois_dernier = date(aujourd_hui.year, aujourd_hui.month - 1, aujourd_hui.day)
# Récupérer la valeur des mots la plus récente parmi celles de la date du jour
mots_aujourd_hui = 0
mots_aujourd_hui_start = 0
most_recent = 0
# print("suivis: ",len(dates))
most_recent = mots[len(dates)-1]
for i, date_ in enumerate(dates):
# trouver le premier décompte supérieur à 0
if mots[i] > 0 and oldest_count == 0:
oldest_count = mots[i]
# print('oldest: ',oldest_count, " mots")
if date_ == aujourd_hui:
if mots_aujourd_hui_start == 0:
mots_aujourd_hui_start = mots[i]
print('au début du jour:' , mots_aujourd_hui_start)
if date_ == aujourd_hui:
mots_aujourd_hui = mots[i]
# Récupérer la valeur des mots la plus récente du jour précédent
mots_hier = 0
for i, date_ in enumerate(dates):
if date_ == hier:
mots_hier = mots[i]
break
# Récupérer la valeur des mots la plus récente de la semaine dernière
mots_semaine_derniere = 0
for i, date_ in enumerate(dates):
if semaine_derniere <= date_ < aujourd_hui:
mots_semaine_derniere = mots[i]
break
# Compter le nombre de mots changés aujourd'hui
mots_changés_aujourd_hui = most_recent - mots_aujourd_hui_start
# Compter le nombre de mots changés depuis la date la plus récente dans la semaine dernière
mots_changés_semaine_derniere = mots_aujourd_hui_start - mots_semaine_derniere
# Afficher le résultat
print("Nombres de mots changés aujourd'hui : ", mots_changés_aujourd_hui)
print("Nombres de mots changés depuis la date la plus récente dans la semaine dernière : ", mots_changés_semaine_derniere)
print("Total : ", most_recent," mots")
mise_a_jour_suivi(fichier_csv, fichier_livre, fichier_personnages)
def create_smooth_area_chart(dates, values, title, filename):
"""
Crée un graphique en aire adoucie à partir des dates et des valeurs.
Args:
dates: Liste des dates
values: Liste des valeurs correspondantes
title: Titre du graphique
filename: Nom du fichier pour sauvegarder le graphique
"""
# Vérifier qu'il y a assez de données pour créer un graphique
if len(dates) < 2:
print(f"Pas assez de données pour créer le graphique {title}")
return
# Convertir les dates en nombres (jours depuis la première date)
date_nums = [(d - dates[0]).days for d in dates]
# Créer des points x pour l'interpolation (plus de points pour une courbe plus lisse)
if len(date_nums) > 2:
x_smooth = np.linspace(min(date_nums), max(date_nums), 300)
# Créer la spline pour l'interpolation
spl = make_interp_spline(date_nums, values, k=min(3, len(dates)-1))
y_smooth = spl(x_smooth)
else:
# Si seulement 2 points, utiliser une interpolation linéaire
x_smooth = np.linspace(min(date_nums), max(date_nums), 300)
y_smooth = np.interp(x_smooth, date_nums, values)
# Créer la figure
plt.figure(figsize=(10, 6))
# Tracer l'aire sous la courbe
plt.fill_between(x_smooth, y_smooth, alpha=0.5, color='skyblue')
# Tracer la ligne
plt.plot(x_smooth, y_smooth, color='blue', linewidth=2)
# Ajouter les points de données réels
plt.scatter(date_nums, values, color='darkblue', s=30)
# Configurer les étiquettes de l'axe x (dates)
if len(dates) > 1:
# Sélectionner quelques dates pour l'affichage
num_ticks = min(10, len(dates))
tick_indices = np.linspace(0, len(dates)-1, num_ticks, dtype=int)
tick_positions = [date_nums[i] for i in tick_indices]
tick_labels = [dates[i].strftime('%Y-%m-%d') for i in tick_indices]
plt.xticks(tick_positions, tick_labels, rotation=45)
# Ajouter les titres et les étiquettes
plt.title(title, fontsize=16)
plt.xlabel('Date', fontsize=12)
plt.ylabel('Valeur', fontsize=12)
# Ajouter une grille
plt.grid(True, linestyle='--', alpha=0.7)
# Ajuster la mise en page
plt.tight_layout()
# Sauvegarder le graphique
plt.savefig(filename, dpi=150, bbox_inches='tight')
plt.savefig(filename.replace('.png', '.svg'), format='svg', bbox_inches='tight')
# Fermer la figure pour libérer la mémoire
plt.close()
print(f"Graphique '{title}' sauvegardé sous {filename} et {filename.replace('.png', '.svg')}")
analyse_csv(fichier_csv)