From d76e23bb65212e7895d8c16733c0fe3c56e342fd Mon Sep 17 00:00:00 2001 From: Tykayn Date: Wed, 25 Sep 2024 17:43:49 +0200 Subject: [PATCH] :zap: ajout de suivi de progression csv et doc de cronjob --- README.md | 16 +++++-- config/books_path.txt | 1 + follow_progress.py | 102 +++++++++++++++++++++++++++++++++++++++++ generate_book.sh | 19 ++++++++ git_save.sh | 5 +- structure_generator.py | 16 ++++++- 6 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 config/books_path.txt create mode 100755 follow_progress.py diff --git a/README.md b/README.md index 1fe0ca6..0b1ed8e 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Le dossier "inspirations" est destiné à avoir des images, des médias, des doc Les intrigues sont des arcs narratifs qui peuvent se superposer dans votre histoire. Pour avoir cette vision des superpositions, le script `make_intrigues_to_csv.py` liste les entêtes et recherche si elles contiennent deux nombres séparés par un tiret. Par exemple : -** l'intrigue bidule chose 4-9 +`** l'intrigue bidule chose 4-9` Indique que l'on souhaite que cette intrigue débute dans la partie 4 et se termine dans la partie 9. Sans information de numérotation, on part du principe qu'une intrigue dure 1 partie de l'histoire, dans l'ordre des intrigues. @@ -52,7 +52,8 @@ Permettent de transformer votre livre en produit distribuable: ebook, html, pdf, ### Génération de plan de livre `python structure_generator.py` Génère un plan de chapitres selon les nombres de chapitres, de sous parties, et d'objectif de mots par section donnés. -Il ne reste plus qu'à copier le texte donné dans livre.org +Il ne reste plus qu'à copier le texte donné dans livre.org ou a utliser la sortie du script pour écrire dans un fichier. + ### Conversion du livre Conversion en epub, html, et pdf grâce à pandoc. @@ -77,14 +78,21 @@ Vous pouvez modifier cet objectif dans `stats_chapitres.py` puis lancer la mise Un tag ajouté aux entêtes de chapitre permet de définir des objectifs de mots. :target_500: définit une cible à 500 mots, :target_1200: défniit la cible à 1200. Cela permettra au générateur de statistiques d'affiner son avancée plus finement. Ce sont des indicateurs, dans la réalité les auteurs écrivent leurs chapitres avec des volumes très variables. -## Suivi de progression de la rédaction +## Suivi de progression de la rédaction Il est envisagé que chaque génération de mise à jour des statistiques remplisse un fichier csv de suivi daté afin de pouvoir voir sa progression quotidienne. La génération de données statistiques peut être incluse dans une tâche cron pour ne pas avoir à faire de lancement de commande tous les jours. +Exemple de cronjob pour lancer le suivi toutes les heures, adaptez le chemin du script dans le dossier du livre concerné: +`0 * * * * /usr/bin/python3 /home/user/book_generator/mon_livre_exemple/follow_progress.py` + +Ceci alimente un fichier csv de suivi des évolutions et présente les changements de mots du jour, ainsi que depuis la semaine dernière. + +Le CSV contient les décomptes de mots pour livre.org, personnages.org, le nombre de personnages, de chapitres, et de sous chapitres. + # Licence AGPLv3+ # Contacts: contact+book_generator@cipherbliss.com -@tykayn@mastodon.cipherbliss.com \ No newline at end of file +@tykayn@mastodon.cipherbliss.com diff --git a/config/books_path.txt b/config/books_path.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/config/books_path.txt @@ -0,0 +1 @@ + diff --git a/follow_progress.py b/follow_progress.py new file mode 100755 index 0000000..50f2bd9 --- /dev/null +++ b/follow_progress.py @@ -0,0 +1,102 @@ +# 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 + +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 = [datetime.fromisoformat(donnee[0]).date() for donnee in donnees] + mots = [int(donnee[1]) for donnee in donnees] + + + # 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) + +analyse_csv(fichier_csv) diff --git a/generate_book.sh b/generate_book.sh index b71a8b3..da1ad01 100755 --- a/generate_book.sh +++ b/generate_book.sh @@ -10,6 +10,22 @@ extension="org" # ou md fi + add_path_to_config() { + local path=$1 + local config_file="config/books_path.txt" + + if [ -f "$config_file" ]; then + if grep -q "^${path}$" "$config_file"; then + echo "Le chemin '${path}' existe déjà dans le fichier de configuration." + else + echo "$(pwd)/$path" >> "$config_file" + echo "Le chemin '${path}' a été ajouté au fichier de configuration." + fi + else + echo "Le fichier de configuration '${config_file}' n'existe pas." + touch $config_file + fi + } function generate_uuid() { uuid=$(cat /proc/sys/kernel/random/uuid) echo "$uuid"; @@ -56,5 +72,8 @@ echo $nom_du_livre | xargs -I{} sed -i 's|BOOK_TITLE|{}|g' $nom_du_livre/taches_$nom_du_livre.org exa -l $nom_du_livre + add_path_to_config $nom_du_livre + echo "fichiers du livre $nom_du_livre créé" + exit 0 diff --git a/git_save.sh b/git_save.sh index e7f71f3..921bd10 100755 --- a/git_save.sh +++ b/git_save.sh @@ -1,4 +1,5 @@ #!/bin/bash -# sauvegarde de tous les changements dans le dossier actuel +# ajout du décompte des informations pour chaque livre +#sauvegarde de tous les changements dans le dossier actuel git add . -git commit -m ":zap: - sauvegarde automatique de l'avancement du livre" \ No newline at end of file +git commit -m ":zap: - sauvegarde automatique de l'avancement du livre" diff --git a/structure_generator.py b/structure_generator.py index 54be5fb..7702e63 100644 --- a/structure_generator.py +++ b/structure_generator.py @@ -1,5 +1,17 @@ -# python script.py --number_chapters 7 --number_parts 2 --objective_words 600 --objective_chapter 1800 - +##################### +# génère une structure à copier dans un nouveau fichier livre.org +# ce script ne remplit pas directement un fichier pour éviter les écrasements trop soudains. +# Exemple d'exécution: +# +# python structure_generator.py --number_chapters 7 --number_parts 2 --objective_words 600 --objective_chapter 1800 +# +##################### +# +# Si vous voulez créer directement un fichier livre sans le reste de ce que fabriquerait generate_book.sh: +# +# python structure_generator.py > mon_livre_généré.org +# +##################### import argparse parser = argparse.ArgumentParser()