SimonAugus/Planning
0
1import pandas as pd2from datetime import datetime, timedelta3from openpyxl import Workbook4from openpyxl.styles import PatternFill5from openpyxl.worksheet.table import Table, TableStyleInfo6import gradio as gr7from transformers import pipeline8from concurrent.futures import ThreadPoolExecutor9 10# Charger le modèle Hugging Face11generator = pipeline("text-generation", model="gpt2")12 13# Fonction pour générer des suggestions IA14def generer_analyse_ia(tache, projet, statut, duree_restante):15 if statut == "En retard":16 prompt = (17 f"La tâche '{tache}' dans le projet '{projet}' est en retard. "18 f"Proposez des solutions pour optimiser les délais, comme intervertir des tâches, ajouter des ressources "19 f"(et précisez le nombre nécessaire), ou toute autre mesure pour réduire les délais finaux. "20 f"La durée restante est estimée à {duree_restante} heures."21 )22 try:23 suggestion = generator(24 prompt,25 max_length=100, # Longueur totale (entrée + sortie)26 max_new_tokens=50, # Tokens générés27 num_return_sequences=1,28 truncation=True # Tronquer si l'entrée est trop longue29 )30 return suggestion[0]['generated_text']31 except Exception as e:32 return f"Erreur IA : {str(e)}"33 return "RAS"34 35# Fonction pour définir les heures de travail36def heures_ouvrables(jour, personnes):37 heures_par_jour = 8 * personnes38 heures = []39 if jour.weekday() in [0, 1, 2, 3]:40 heures = [f"{hour}:30" for hour in range(7, 16)] * (heures_par_jour // 8)41 elif jour.weekday() == 4:42 heures = [f"{hour}:30" for hour in range(7, 14)] * (heures_par_jour // 8)43 return heures44 45# Fonction principale pour analyser le fichier Excel46def analyser_planning(file, personnes):47 try:48 df = pd.read_excel(file)49 print("Fichier Excel chargé avec succès.")50 except Exception as e:51 return f"Erreur lors de la lecture du fichier Excel : {str(e)}"52 53 # Vérification des colonnes attendues54 colonnes_attendues = ['Code unique', 'Projet', 'Tâche', 'Durée (H)', 'Date Start', 'Date Limite']55 for colonne in colonnes_attendues:56 if colonne not in df.columns:57 return f"Erreur : La colonne '{colonne}' est absente du fichier."58 59 # Conversion des dates60 df['Date Start'] = pd.to_datetime(df['Date Start'], format="%Y-%m-%d", errors='coerce')61 df['Date Limite'] = pd.to_datetime(df['Date Limite'], format="%Y-%m-%d", errors='coerce')62 63 # Vérification des dates et durées64 if df['Date Start'].isnull().any():65 return "Erreur : Certaines dates dans 'Date Start' sont manquantes ou mal formatées."66 if df['Date Limite'].isnull().any():67 return "Erreur : Certaines dates dans 'Date Limite' sont manquantes ou mal formatées."68 if df['Durée (H)'].isnull().any() or not pd.api.types.is_numeric_dtype(df['Durée (H)']):69 return "Erreur : La colonne 'Durée (H)' contient des valeurs manquantes ou non numériques."70 71 # Création de l'agenda vide72 date_fin = datetime.now() + timedelta(days=30)73 all_hours = []74 for single_date in pd.date_range(start=datetime.now(), end=date_fin):75 for hour in range(7, 16):76 hour_str = f"{hour}:30"77 all_hours.append({78 "Date": single_date.strftime("%d/%m/%Y"),79 "Heure": hour_str,80 "Code unique": None,81 "Projet": None,82 "Tâche": None,83 "Date Limite": None,84 "Statut": "Libre",85 "Analyse IA": None86 })87 88 agenda_df = pd.DataFrame(all_hours)89 90 # Fonction pour traiter une ligne avec ThreadPoolExecutor91 def process_row(row):92 code = row['Code unique']93 projet = row['Projet']94 tache = row['Tâche']95 duree = row['Durée (H)'] / personnes96 date_limite = row['Date Limite']97 date_start = row['Date Start']98 date_actuelle = max(datetime.now(), date_start)99 100 while duree > 0:101 if date_actuelle.weekday() >= 5: # Weekends102 date_actuelle += timedelta(days=1)103 continue104 105 daily_slots = agenda_df[106 (agenda_df['Date'] == date_actuelle.strftime("%d/%m/%Y")) & 107 (agenda_df['Statut'] == "Libre")108 ]109 110 for idx, slot in daily_slots.iterrows():111 if duree <= 0:112 break113 114 statut = "À temps" if date_actuelle <= date_limite else "En retard"115 analyse_ia = generer_analyse_ia(tache, projet, statut, duree)116 117 agenda_df.at[idx, 'Code unique'] = code118 agenda_df.at[idx, 'Projet'] = projet119 agenda_df.at[idx, 'Tâche'] = tache120 agenda_df.at[idx, 'Date Limite'] = date_limite.strftime("%d/%m/%Y")121 agenda_df.at[idx, 'Statut'] = statut122 agenda_df.at[idx, 'Analyse IA'] = analyse_ia123 duree -= 1124 125 if duree > 0:126 date_actuelle += timedelta(days=1)127 128 # Utilisation de ThreadPoolExecutor pour paralléliser les appels129 try:130 with ThreadPoolExecutor(max_workers=5) as executor:131 executor.map(process_row, [row for _, row in df.iterrows()])132 except Exception as e:133 return f"Erreur lors de la planification des tâches : {str(e)}"134 135 # Exportation du fichier Excel136 output_file = "retroplanning.xlsx"137 try:138 with pd.ExcelWriter(output_file, engine='openpyxl') as writer:139 agenda_df.to_excel(writer, index=False, sheet_name="Rétroplanning")140 141 workbook = writer.book142 sheet = writer.sheets["Rétroplanning"]143 144 table = Table(displayName="RétroplanningTable", ref=f"A1:{chr(65+len(agenda_df.columns)-1)}{len(agenda_df)+1}")145 style = TableStyleInfo(146 name="TableStyleMedium9",147 showFirstColumn=False,148 showLastColumn=False,149 showRowStripes=True,150 showColumnStripes=True151 )152 table.tableStyleInfo = style153 sheet.add_table(table)154 155 fill = PatternFill(start_color="D9EAD3", end_color="D9EAD3", fill_type="solid")156 for cell in sheet[1]:157 cell.fill = fill158 159 for column_cells in sheet.columns:160 max_length = 0161 col_letter = column_cells[0].column_letter162 for cell in column_cells:163 if cell.value:164 max_length = max(max_length, len(str(cell.value)))165 sheet.column_dimensions[col_letter].width = max_length + 2166 167 print("Fichier Excel exporté avec succès.")168 return output_file169 170 except Exception as e:171 return f"Erreur lors de l'exportation du fichier : {str(e)}"172 173# Interface utilisateur avec Gradio174def interface_planning(file, personnes):175 result = analyser_planning(file, personnes)176 if result.endswith(".xlsx"):177 return result178 return f"Erreur : {result}"179 180interface = gr.Interface(181 fn=interface_planning,182 inputs=[183 gr.File(label="Téléchargez votre planning (format Excel)"),184 gr.Number(value=1, label="Nombre de personnes", precision=0)185 ],186 outputs=gr.File(label="Téléchargez votre rétroplanning généré"),187 title="Analyseur de Planning avec Rétroplanning et IA",188 description="Téléchargez un fichier Excel contenant votre planning brut et indiquez le nombre de personnes disponibles. L'IA analysera et ajoutera des suggestions pour optimiser le planning."189)190 191interface.launch()