mirror of
				https://forge.chapril.org/tykayn/book_generator
				synced 2025-06-20 01:34:43 +02:00 
			
		
		
		
	⚡ ajout de suivi de progression csv et doc de cronjob
This commit is contained in:
		
							parent
							
								
									c7383ed6ef
								
							
						
					
					
						commit
						d76e23bb65
					
				
					 6 changed files with 151 additions and 8 deletions
				
			
		
							
								
								
									
										14
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								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. | 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. | 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 : | 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. | 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. | 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 | ### Génération de plan de livre | ||||||
| `python structure_generator.py` | `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. | 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 du livre | ||||||
| Conversion en epub, html, et pdf grâce à pandoc. | Conversion en epub, html, et pdf grâce à pandoc. | ||||||
|  | @ -77,11 +78,18 @@ 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. | 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. | :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. | 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. | 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 | # Licence | ||||||
| AGPLv3+ | AGPLv3+ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								config/books_path.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								config/books_path.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | 
 | ||||||
							
								
								
									
										102
									
								
								follow_progress.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										102
									
								
								follow_progress.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -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) | ||||||
|  | @ -10,6 +10,22 @@ | ||||||
| 		extension="org" # ou md | 		extension="org" # ou md | ||||||
| 	fi | 	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() { |     function generate_uuid() { | ||||||
| 	    uuid=$(cat /proc/sys/kernel/random/uuid) | 	    uuid=$(cat /proc/sys/kernel/random/uuid) | ||||||
|       echo "$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 | 	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 | 	exa -l $nom_du_livre | ||||||
|  | 	add_path_to_config $nom_du_livre | ||||||
|  | 
 | ||||||
| 	echo "fichiers du livre $nom_du_livre créé" | 	echo "fichiers du livre $nom_du_livre créé" | ||||||
|  | 
 | ||||||
| exit 0 | exit 0 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #!/bin/bash | #!/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 add . | ||||||
| git commit -m ":zap: - sauvegarde automatique de l'avancement du livre" | git commit -m ":zap: - sauvegarde automatique de l'avancement du livre" | ||||||
|  | @ -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 | import argparse | ||||||
| parser = argparse.ArgumentParser() | parser = argparse.ArgumentParser() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tykayn
						Tykayn