""" Ce module contient les Utilitaires de matching """ # import des pré requis import time import pandas as pd from matching.games import HospitalResident from .models import Notation, Poste, PreferencesListe, StatutPamChoices, AvisPosteChoices as AvisPoste from .utils.logging import get_logger logger = get_logger(__name__) # Fonction de preprocessing def preprocess_matching(pam_id,sv_id,df_pref): """ Retourne les liste de souhait des militaires et des postes :type sv_id: char :param sv_id: id du sous vivier étudié :return: - **gs_proposants** (*liste*): liste des proposants - **gs_disposants** (*liste*): liste des disposants - **gs_capacite** (*liste*): liste des capacités pour chaque disposants """ logger.debug('preprocessing matching %s', sv_id) statut_adm = [StatutPamChoices.A_MUTER,StatutPamChoices.A_ETUDIER] statut_poste =[AvisPoste.P1,AvisPoste.P2,AvisPoste.P3,AvisPoste.P4] # liste_preference = PreferencesListe.objects.filter(pam_id=pam_id,administre_pam__administre__sous_vivier_id=sv_id).values() notation = Notation.objects.filter(pam_id=pam_id, administre_pam__administre__sous_vivier_id=sv_id, administre_pam__a_statut_pam_annee__in=statut_adm, administre_pam__decision__de_decision__isnull=True, poste_pam__poste__sous_viviers=sv_id, poste_pam__decisions__de_decision__isnull=True, poste_pam__p_avis_pam__in=statut_poste).values() liste_preference_df = df_pref notation_df = pd.DataFrame.from_records(notation) liste_admin_lp = liste_preference_df.drop_duplicates(subset=['administre_id']) gs_proposants = {} gs_disposants = {} gs_capacite = {} l2 = [] if not liste_preference_df.empty: for admin in liste_admin_lp['administre_id']: l = [] new_lp_df = liste_preference_df.loc[liste_preference_df['administre_id'] == admin].drop_duplicates(subset=['poste_id']) new_lp_df = new_lp_df.drop_duplicates(subset=['lp_rang_poste']) new_lp_df = new_lp_df.sort_values( by=['lp_rang_poste']).reset_index() for i in range(len(new_lp_df)): l.append(new_lp_df.at[i, 'poste_id']) l2.append(new_lp_df.at[i, 'poste_id']) gs_proposants[admin] = l l2 = list(set(l2)) notation_df = notation_df[notation_df.administre_id.isin(liste_admin_lp['administre_id'])] for poste in l2: l1 = [] new_no_df = notation_df.loc[notation_df['poste_id'] == poste].sort_values(by=['no_score_administre'], ascending=False).reset_index() for i in range(len(new_no_df)): if poste in gs_proposants[new_no_df.at[i, 'administre_id']]: l1.append(new_no_df.at[i, 'administre_id']) gs_disposants[poste] = l1 gs_capacite[poste] = 1 logger.debug("Administre proposants : %s", gs_proposants) logger.debug("Poste disposants : %s", gs_disposants) logger.debug('end preprocessing matching func') return gs_proposants, gs_disposants, gs_capacite # Fonction de preprocessing def preprocess_matchingSelectif(sv_id, pam_id,l_a_id,l_p_id, df_pref): """ Retourne les liste de souhait des militaires et des postes :type sv_id: char :param sv_id: id du sous vivier étudié :return: - **gs_proposants** (*liste*): liste des proposants - **gs_disposants** (*liste*): liste des disposants - **gs_capacite** (*liste*): liste des capacités pour chaque disposants """ logger.debug('preprocessing matching %s', sv_id) statut_adm = [StatutPamChoices.A_MUTER,StatutPamChoices.A_ETUDIER] statut_poste =[AvisPoste.P1,AvisPoste.P2,AvisPoste.P3,AvisPoste.P4] notation = Notation.objects.filter(pam_id=pam_id, administre_pam__administre__sous_vivier_id=sv_id, administre_pam__a_statut_pam_annee__in=statut_adm, administre_pam__administre_id__in=l_a_id, administre_pam__decision__de_decision__isnull=True, poste_pam__poste__sous_viviers=sv_id, poste_pam__decisions__de_decision__isnull=True, poste_pam__p_avis_pam__in=statut_poste).values() liste_preference_df = df_pref notation_df = pd.DataFrame.from_records(notation) liste_admin_lp = liste_preference_df.drop_duplicates(subset=['administre_id']) gs_proposants = {} gs_disposants = {} gs_capacite = {} l2 = [] if not liste_preference_df.empty: for admin in liste_admin_lp['administre_id']: l = [] new_lp_df = liste_preference_df.loc[liste_preference_df['administre_id'] == admin].drop_duplicates(subset=['poste_id']) new_lp_df = new_lp_df.drop_duplicates(subset=['lp_rang_poste']) new_lp_df = new_lp_df.sort_values( by=['lp_rang_poste']).reset_index() for i in range(len(new_lp_df)): l.append(new_lp_df.at[i, 'poste_id']) l2.append(new_lp_df.at[i, 'poste_id']) gs_proposants[admin] = l l2 = list(set(l2)) notation_df = notation_df[notation_df.administre_id.isin(liste_admin_lp['administre_id'])] for poste in l2: l1 = [] new_no_df = notation_df.loc[notation_df['poste_id'] == poste].sort_values(by=['no_score_administre'], ascending=False).reset_index() for i in range(len(new_no_df)): if poste in gs_proposants[new_no_df.at[i, 'administre_id']]: l1.append(new_no_df.at[i, 'administre_id']) gs_disposants[poste] = l1 gs_capacite[poste] = 1 logger.debug("Administre proposants : %s", gs_proposants) logger.debug("Poste disposants : %s", gs_disposants) logger.debug('end preprocessing matching func') return gs_proposants, gs_disposants, gs_capacite # Fonction de matching def matching_parfait(gs_proposants, gs_disposants, gs_capacite): """ Retourne le dictionnaire python presentant le resultats du matching :type gs_proposants: liste :param gs_proposants: liste des proposants :type gs_disposants: liste :param gs_disposants: liste des disposants :type gs_capacite: liste :param gs_capacite: liste des capacités pour chaque disposants :return: - **matching** (*dictionnaire*): dictionnaire python presentant le resultats du matching """ logger.debug('start matching parfait') # Traitement des entrées game = HospitalResident.create_from_dictionaries( gs_proposants, gs_disposants, gs_capacite ) # Creation du jeu matching = game.solve(optimal='hospital') # Test de validation et de stabilité logger.debug('Validity Check : %s', game.check_validity()) assert game.check_validity() logger.debug('Stability Check : %s', game.check_stability()) assert game.check_stability() # Creation des listes d'affectés et de non afféctes matched_residents = [] for _, residents in matching.items(): for resident in residents: matched_residents.append(resident.name) unmatched_residents = set(gs_proposants.keys()) - set(matched_residents) # KPI matching logger.debug("Nb demandeurs : %s", len(gs_proposants)) logger.debug("Poste demandeurs : %s", gs_proposants) logger.debug("Nb affectés : %s", len(matched_residents)) logger.debug("Administres affectés : %s", matched_residents) logger.debug("Nb non affecte : %s", len(unmatched_residents)) logger.debug("Administres non affecte : %s", unmatched_residents) logger.debug('end matching parfait') return (matching)