def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        discrimination_reason = project.translate_string(
            'vous nous avez dit que les employeurs ne '
            'vous donnent pas votre chance')
        relevant_frustrations = {
            user_pb2.AGE_DISCRIMINATION:
            discrimination_reason,
            user_pb2.ATYPIC_PROFILE:
            discrimination_reason,
            user_pb2.NO_OFFERS:
            project.translate_string(
                "vous nous avez dit ne pas trouver d'offres correspondant "
                'à vos critères'),
            user_pb2.SEX_DISCRIMINATION:
            discrimination_reason,
        }
        its_easy = project.translate_string(
            "c'est plus facile à faire qu'on peut le croire")

        # TODO(pascal): Make this dynamic if we get data for after Feb 2018.
        if project.now >= datetime.datetime(2018, 2, 7):
            return scoring_base.NULL_EXPLAINED_SCORE
        frustration_reasons = {
            relevant_frustrations[frustration]
            for frustration in project.user_profile.frustrations
            if frustration in relevant_frustrations
        }
        if frustration_reasons or project.get_search_length_now() > 3:
            return scoring_base.ExplainedScore(
                2,
                list(frustration_reasons) or [its_easy])
        return scoring_base.ExplainedScore(1, [its_easy])
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        close_jobs = self.get_close_jobs(project)
        search_since_nb_months = round(project.get_search_length_now())
        score_modifier = 0
        reasons = []
        if len(close_jobs.close_jobs) + len(close_jobs.evolution_jobs) < 2:
            return scoring_base.NULL_EXPLAINED_SCORE
        if project.get_user_age() >= 45:
            return scoring_base.NULL_EXPLAINED_SCORE
        if project.details.passionate_level >= project_pb2.PASSIONATING_JOB:
            score_modifier = -1
        else:
            reasons.append(
                project.translate_string(
                    "vous n'êtes pas trop attaché à votre métier"))
        if project.details.job_search_has_not_started or search_since_nb_months <= 1:
            return scoring_base.ExplainedScore(2 + score_modifier, reasons)
        reasons = [
            project.translate_string('vous cherchez depuis {} mois').format(
                search_since_nb_months)
        ]
        if search_since_nb_months >= 12:
            return scoring_base.ExplainedScore(3, reasons)
        if search_since_nb_months >= 9:
            return scoring_base.ExplainedScore(2, reasons)
        if search_since_nb_months >= 6:
            return scoring_base.ExplainedScore(1, reasons)
        return scoring_base.NULL_EXPLAINED_SCORE
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        first_modes = project.get_fap_modes()
        if job_pb2.SPONTANEOUS_APPLICATION in first_modes:
            return scoring_base.ExplainedScore(3, [
                project.translate_static_string(
                    "c'est le canal de recrutement n°1 pour votre métier")
            ])

        # In the category missing-diploma, we always have the alternance strategy which requires
        # spontaneous application data.
        if project.details.diagnostic.category_id == 'missing-diploma':
            return scoring_base.ExplainedScore(2, [
                project.translate_static_string(
                    "c'est le meilleur moyen de trouver un contrat en alternance"
                )
            ])

        second_modes = project.get_fap_modes(rank='second')
        if job_pb2.SPONTANEOUS_APPLICATION in second_modes:
            return scoring_base.ExplainedScore(2, [
                project.translate_static_string(
                    "c'est un des meilleurs canaux de recrutement pour votre métier"
                )
            ])

        if project.details.diagnostic.category_id == 'bravo' and \
                user_profile_pb2.NO_OFFERS in project.user_profile.frustrations:
            return scoring_base.ExplainedScore(2, [
                project.translate_static_string(
                    "vous nous avez dit ne pas trouver assez d'offres.")
            ])
        return scoring_base.NULL_EXPLAINED_SCORE
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        close_jobs = self.get_close_jobs(project)
        search_since_nb_months = round(project.get_search_length_now())
        score_modifier = 0
        reasons: List[str] = []
        if len(close_jobs.close_jobs) + len(close_jobs.evolution_jobs) < 2:
            return scoring_base.NULL_EXPLAINED_SCORE
        # TODO(cyrille): Make this more robust.
        force_in_stuck_market = None
        # TODO(cyrille): Rather use market_stress to avoid depending on diagnostic to be computed.
        if project.details.diagnostic.category_id == 'stuck-market':
            force_in_stuck_market = scoring_base.ExplainedScore(1, reasons)
        if project.get_user_age() >= 45:
            return force_in_stuck_market or scoring_base.NULL_EXPLAINED_SCORE
        if project.details.passionate_level >= project_pb2.PASSIONATING_JOB:
            score_modifier = -1
        else:
            reasons.append(project.translate_string(
                "vous n'êtes pas trop attaché à votre métier"))
        if project.details.job_search_has_not_started or search_since_nb_months <= 1:
            return scoring_base.ExplainedScore(2 + score_modifier, reasons)
        reasons = [
            project.translate_string('vous cherchez depuis {} mois')
            .format(search_since_nb_months)]
        if search_since_nb_months >= 12:
            return scoring_base.ExplainedScore(3, reasons)
        if search_since_nb_months >= 9:
            return scoring_base.ExplainedScore(2, reasons)
        if search_since_nb_months >= 6:
            return scoring_base.ExplainedScore(1, reasons)
        return force_in_stuck_market or scoring_base.NULL_EXPLAINED_SCORE
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        local_jobbing = self.get_local_jobbing(project)
        if len(local_jobbing.reorient_jobbing_jobs) < 2:
            return scoring_base.NULL_EXPLAINED_SCORE
        score_modifier = 0
        reasons: list[str] = []

        if project.details.passionate_level == project_pb2.LIFE_GOAL_JOB:
            score_modifier = -2
            if project.job_group_info().growth_2012_2022 < .1:
                score_modifier = -1
        if score_modifier >= 0:
            reasons.append(
                project.translate_static_string(
                    'votre métier ne vous tient pas trop à cœur'))

        if project.user_profile.highest_degree <= job_pb2.CAP_BEP:
            return scoring_base.ExplainedScore(3 + score_modifier, reasons)
        if project.user_profile.highest_degree <= job_pb2.BAC_BACPRO:
            return scoring_base.ExplainedScore(max(2 + score_modifier, 1),
                                               reasons)
        if project.user_profile.highest_degree <= job_pb2.BTS_DUT_DEUG:
            return scoring_base.ExplainedScore(1, reasons)
        return scoring_base.NULL_EXPLAINED_SCORE
示例#6
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        associations = self.list_associations(project)
        search_length_reason = project.translate_static_string(
            "vous nous avez dit que vous êtes en recherche d'emploi "
            'depuis %jobSearchLengthAtCreation')
        if not associations:
            return scoring_base.NULL_EXPLAINED_SCORE
        if user_profile_pb2.MOTIVATION in project.user_profile.frustrations:
            return scoring_base.ExplainedScore(3, [
                project.translate_static_string(
                    'vous nous avez dit avoir du mal à garder votre ' +
                    'motivation au top')
            ])
        if len(associations) >= 3 and project.get_search_length_at_creation(
        ) >= 6:
            return scoring_base.ExplainedScore(3, [search_length_reason])
        if project.get_search_length_at_creation() >= 12:
            return scoring_base.ExplainedScore(3, [search_length_reason])
        return scoring_base.ExplainedScore(2, [
            project.translate_static_string(
                "l'accompagnement humain peut beaucoup vous apporter")
        ])
示例#7
0
 def score_and_explain(self, project: scoring_base.ScoringProject) \
         -> scoring_base.ExplainedScore:
     if project.details.diagnostic.category_id == 'enhance-methods-to-interview':
         return scoring_base.ExplainedScore(3, [])
     reasons = [
         project.translate_static_string(
             "vous nous avez dit avoir passé beaucoup d'entretiens sans succès"
         )
     ]
     if project.details.total_interview_count < 0:
         num_interviews = 0
     elif project.details.total_interview_count > 0:
         num_interviews = project.details.total_interview_count
     else:
         num_interviews = _NUM_INTERVIEWS.get(
             project.details.total_interviews_estimate, 0)
     job_search_length_months = project.get_search_length_at_creation()
     if job_search_length_months < 1:
         job_search_length_months = 1
     num_monthly_interviews = num_interviews / job_search_length_months
     if num_monthly_interviews > _max_monthly_interviews(project):
         return scoring_base.ExplainedScore(3, reasons)
     # Whatever the number of month of search, trigger 3 if the user did more than 5 interviews:
     if num_interviews >= _NUM_INTERVIEWS[project_pb2.DECENT_AMOUNT]:
         return scoring_base.ExplainedScore(3, reasons)
     if project.details.diagnostic.category_id == 'bravo':
         return scoring_base.ExplainedScore(1, [])
     return scoring_base.NULL_EXPLAINED_SCORE
示例#8
0
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        missions = self.volunteering_missions(project).missions
        if not missions:
            return scoring_base.NULL_EXPLAINED_SCORE
        if project.get_search_length_at_creation() < 9:
            return scoring_base.ExplainedScore(1, [])
        return scoring_base.ExplainedScore(2, [
            'ça fait du bien de garder une activité sociale dans une recherche longue'
        ])
示例#9
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        frustration_reasons = list(self._get_frustrations_reasons(project))
        its_easy = project.translate_static_string(
            "c'est plus facile à faire qu'on peut le croire")

        if frustration_reasons or project.get_search_length_now() > 3:
            return scoring_base.ExplainedScore(
                2, frustration_reasons or [its_easy])
        return scoring_base.ExplainedScore(1, [its_easy])
示例#10
0
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        application_modes = project.job_group_info().application_modes.values()
        first_modes = set(fap_modes.modes[0].mode for fap_modes in application_modes)
        first_modes.discard(job_pb2.UNDEFINED_APPLICATION_MODE)
        if first_modes == {job_pb2.PERSONAL_OR_PROFESSIONAL_CONTACTS}:
            return scoring_base.ExplainedScore(2, [project.translate_string(
                'les embauches se font surtout par les contacts personnels ou professionnels dans'
                ' votre métier')])

        return scoring_base.ExplainedScore(1, [project.translate_string(
            "c'est un bon moyen d'étendre votre réseau")])
示例#11
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        if (self._num_interviews_increase(project) >= 2 and
                project.details.job_search_length_months <= 6):
            return scoring_base.ExplainedScore(3, [project.translate_string(
                "nous pensons qu'avec votre profil vous pourriez "
                "décrocher plus d'entretiens")])
        if project.details.diagnostic.category_id == 'bravo' and \
                user_pb2.RESUME in project.user_profile.frustrations:
            return scoring_base.ExplainedScore(1, [project.translate_string(
                'vous nous avez dit avoir du mal à rédiger votre CV')])
        return scoring_base.NULL_EXPLAINED_SCORE
示例#12
0
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        nearby_cities = self.list_nearby_cities(project)
        if not nearby_cities:
            return scoring_base.NULL_EXPLAINED_SCORE

        if project.details.mobility.area_type > geo_pb2.CITY and \
                any(c.relative_offers_per_inhabitant >= 2 for c in nearby_cities):
            return scoring_base.ExplainedScore(
                3, ["il y a beaucoup plus d'offres par habitants dans d'autres villes"])

        return scoring_base.ExplainedScore(
            2, ["il est toujours bon d'avoir une idée des offres dans les autres villes"])
示例#13
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        if project.details.network_estimate != self._network_level:
            return scoring_base.NULL_EXPLAINED_SCORE

        first_modes = project.get_fap_modes()
        first_modes.discard(job_pb2.UNDEFINED_APPLICATION_MODE)
        if first_modes == {job_pb2.PERSONAL_OR_PROFESSIONAL_CONTACTS}:
            return scoring_base.ExplainedScore(3, [
                'le réseau est le canal n°1 pour trouver un métier %inDomain'
            ])
        return scoring_base.ExplainedScore(2, [])
示例#14
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        if project.details.weekly_applications_estimate <= project_pb2.LESS_THAN_2 or \
                project.details.job_search_length_months < 2:
            return scoring_base.ExplainedScore(3, [project.translate_string(
                'vous nous avez dit que vous en êtes au début de '
                'vos candidatures')])
        if project.details.diagnostic.category_id == 'bravo' and \
                user_pb2.RESUME in project.user_profile.frustrations:
            return scoring_base.ExplainedScore(1, [project.translate_string(
                'vous nous avez dit avoir du mal à rédiger votre CV')])

        return scoring_base.NULL_EXPLAINED_SCORE
示例#15
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        for opened_strategy in project.details.opened_strategies:
            if opened_strategy.strategy_id in self._strategies:
                return scoring_base.ExplainedScore(
                    3, ['vous avez démarré une stratégie qui correspond'])

        for strategy in project.details.strategies:
            if strategy.strategy_id in self._strategies:
                return scoring_base.ExplainedScore(2, [
                    "c'est une stratégie qui pourrait marcher dans votre cas"
                ])

        return scoring_base.ExplainedScore(1, [])
示例#16
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute the score for a given project and explains it.

        Requirements are:
        - being between 16 and 30 y.o if having a handicap or between 16 and 25 otherwise
        - having low or no experience (intern maximum)
        """

        age = project.get_user_age()
        seniority = project.details.seniority
        reasons: list[str] = []
        if age < 16 or seniority > project_pb2.INTERN:
            return scoring_base.NULL_EXPLAINED_SCORE
        if project.user_profile.has_handicap and age <= 30:
            reasons = [
                project.translate_static_string('vous avez entre 16 et 30 ans')
            ]
        if age <= 25:
            reasons = [
                project.translate_static_string('vous avez entre 16 et 25 ans')
            ]
        if not reasons:
            return scoring_base.NULL_EXPLAINED_SCORE
        return scoring_base.ExplainedScore(2, reasons)
示例#17
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        reasons: List[str] = []

        # For now we just match for people willing to move to the whole country.
        # There might be cases where we should be able to recommend to people who want to move to
        # their own region, but it would add complexity to find them.
        is_not_ready_to_move = project.details.area_type < geo_pb2.COUNTRY

        is_not_single = project.user_profile.family_situation != user_pb2.SINGLE
        has_advanced_degree = project.user_profile.highest_degree >= job_pb2.LICENCE_MAITRISE
        is_not_young = project.get_user_age() > 30
        looks_only_for_cdi = project.details.employment_types == [job_pb2.CDI]

        if (is_not_ready_to_move or is_not_young or is_not_single
                or has_advanced_degree or looks_only_for_cdi):
            return scoring_base.NULL_EXPLAINED_SCORE
        reasons.append(
            project.translate_string(
                'vous nous avez dit être prêt%eFeminine à déménager'))
        reasons.append(
            project.translate_string('vous êtes disponible familialement'))

        if len(self._get_seasonal_departements(project).departement_stats) > 1:
            reasons.append(
                project.translate_string(
                    "il y a plus d'offres saisonnières par habitants dans d'autres villes"
                ))
            return scoring_base.ExplainedScore(2, reasons)
        return scoring_base.NULL_EXPLAINED_SCORE
示例#18
0
def _score_and_explain_after_filters(project):
    """A helper function to give a score and an explanation for all advices in the module,
    once some prerequisite filters have been met.
    """

    if project.user_profile.has_car_driving_license != user_pb2.FALSE:
        return scoring_base.NULL_EXPLAINED_SCORE
    reasons = []
    license_required = next(
        (license.percent_required
         for license in project.job_group_info().requirements.driving_licenses
         if license.driving_license == job_pb2.CAR), 0)
    if license_required:
        reasons.append(
            project.translate_string(
                'le permis est important dans votre métier'))
    score_modifier = 0
    if _license_helps_mobility(project.details.mobility):
        reasons.append(
            project.translate_string('le permis augmenterait votre mobilité'))
        score_modifier = 1
    if not reasons:
        return scoring_base.NULL_EXPLAINED_SCORE
    score = min(
        3, score_modifier +
        (3 if license_required > 30 else
         2 if license_required > 10 else 1 if license_required else 0))
    return scoring_base.ExplainedScore(score, reasons)
示例#19
0
def _score_and_explain_after_filters(project: scoring_base.ScoringProject) \
        -> scoring_base.ExplainedScore:
    """A helper function to give a score and an explanation for all advices in the module,
    once some prerequisite filters have been met.
    """

    if project.user_profile.has_car_driving_license != boolean_pb2.FALSE:
        return scoring_base.NULL_EXPLAINED_SCORE
    reasons = []
    license_required = next(
        (license.percent_required
         for license in project.job_group_info().requirements.driving_licenses
         if license.driving_license == job_pb2.CAR), 0)
    if license_required:
        reasons.append(
            project.translate_static_string(
                'le permis est important dans votre métier'))
    score_modifier = 0
    if _license_helps_mobility(project.details):
        reasons.append(
            project.translate_static_string(
                'le permis augmenterait votre mobilité'))
        score_modifier = 1
    if not reasons:
        return scoring_base.NULL_EXPLAINED_SCORE
    score = min(
        3,
        score_modifier + (
            # Example at 80% is civil engineer F1106.
            3 if license_required > 80 else
            # Example at 67% is translator E1108.
            2 if license_required > 67 else
            # Example at 50% is chiropractor J1408.
            1 if license_required > 50 else 0))
    return scoring_base.ExplainedScore(score, reasons)
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        # This job group has jobs that are too different to consider them as a
        # small change.
        # TODO(pascal): Check for other such job groups and move the config to
        # a class property.
        if project.details.target_job.job_group.rome_id == 'K2401':
            return scoring_base.NULL_EXPLAINED_SCORE

        specific_jobs = project.requirements().specific_jobs
        if not specific_jobs or specific_jobs[
                0].code_ogr == project.details.target_job.code_ogr:
            return scoring_base.NULL_EXPLAINED_SCORE

        try:
            target_job_percentage = next(
                j.percent_suggested for j in specific_jobs
                if j.code_ogr == project.details.target_job.code_ogr)
        except StopIteration:
            target_job_percentage = 0

        has_way_better_job = target_job_percentage + 30 < specific_jobs[
            0].percent_suggested
        has_better_job = target_job_percentage + 5 < specific_jobs[
            0].percent_suggested
        is_looking_for_new_job = project.details.kind == project_pb2.REORIENTATION

        reasons = []
        if has_way_better_job:
            reasons.append(
                project.translate_string(
                    "il y a beaucoup plus d'offres dans des métiers proches"))
        elif (project.get_search_length_at_creation() > 6 and has_better_job):
            reasons.append(
                project.translate_string(
                    "il y a plus d'offres dans des métiers proches"))
        if is_looking_for_new_job:
            reasons.append(
                project.translate_string(
                    'vous nous avezdit vouloir vous reconvertir'))
        if reasons:
            return scoring_base.ExplainedScore(3, reasons)
        return scoring_base.ExplainedScore(2, [
            project.translate_string(
                "il y a un bon nombre d'offres dans des métiers proches")
        ])
示例#21
0
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        application_modes = project.job_group_info().application_modes.values()
        first_modes = set(
            fap_modes.modes[0].mode for fap_modes in application_modes
            if len(fap_modes.modes))
        if job_pb2.SPONTANEOUS_APPLICATION in first_modes:
            return scoring_base.ExplainedScore(3, [project.translate_string(
                "c'est le canal de recrutement n°1 pour votre métier")])

        second_modes = set(
            fap_modes.modes[1].mode for fap_modes in application_modes
            if len(fap_modes.modes) > 1)
        if job_pb2.SPONTANEOUS_APPLICATION in second_modes:
            return scoring_base.ExplainedScore(2, [project.translate_string(
                "c'est un des meilleurs canaux de recrutement pour votre métier")])

        return scoring_base.NULL_EXPLAINED_SCORE
示例#22
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute the score for a given project and explains it."""

        skills = self._get_skills(project)

        if not skills.skills:
            return scoring_base.NULL_EXPLAINED_SCORE

        return scoring_base.ExplainedScore(2, [])
示例#23
0
    def score_and_explain(self, project):
        """Compute the score for a given project and explains it."""

        age = project.get_user_age()
        if age < 16:
            return scoring_base.NULL_EXPLAINED_SCORE
        score, reasons = _score_and_explain_after_filters(project)
        if not score:
            return scoring_base.NULL_EXPLAINED_SCORE
        return scoring_base.ExplainedScore(max(1, score - 1), reasons)
示例#24
0
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        if (self._num_interviews_increase(project) >= 2
                and project.details.job_search_length_months <= 6):
            return scoring_base.ExplainedScore(3, [
                project.translate_string(
                    "nous pensons qu'avec votre profil vous pourriez "
                    "décrocher plus d'entretiens")
            ])
        return scoring_base.NULL_EXPLAINED_SCORE
示例#25
0
    def score_and_explain(self, project):  # pylint: disable=no-self-use
        """Compute a score for the given ScoringProject."""

        if project.details.weekly_applications_estimate <= project_pb2.LESS_THAN_2 or \
                project.details.job_search_length_months < 2:
            return scoring_base.ExplainedScore(3, [
                project.translate_string(
                    'vous nous avez dit que vous en êtes au début de '
                    'vos candidatures')
            ])
        return scoring_base.NULL_EXPLAINED_SCORE
示例#26
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute the score for a given project and explains it."""

        age = project.get_user_age()
        if age < 16:
            return scoring_base.NULL_EXPLAINED_SCORE
        score, reasons = _score_and_explain_after_filters(project)
        if not score:
            return scoring_base.NULL_EXPLAINED_SCORE
        # We bring more value in the driving-license-euro and
        # driving-license-low-income so we show this one after (lower score).
        return scoring_base.ExplainedScore(max(1, score - 1), reasons)
示例#27
0
    def score_and_explain(self, project):
        """Compute a score for the given ScoringProject."""

        reasons = []
        if project.details.mobility.area_type != geo_pb2.COUNTRY and \
                project.details.mobility.area_type != geo_pb2.WORLD:
            return scoring_base.NULL_EXPLAINED_SCORE
        reasons.append(
            project.translate_string(
                'vous nous avez dit être prêt%eFeminine à déménager'))

        if _find_best_departements(None, project):
            reasons.append(
                project.translate_string(
                    "il y a beaucoup plus d'offres par habitants dans d'autres villes"
                ))
            return scoring_base.ExplainedScore(2, reasons)
        return scoring_base.NULL_EXPLAINED_SCORE
示例#28
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        has_any_covid_risk_info = jobs.has_covid_risk_info(project.database)
        has_any_automation_risk_info = jobs.has_automation_risk_info(
            project.database)
        if not has_any_covid_risk_info and not has_any_automation_risk_info:
            raise scoring_base.NotEnoughDataException(
                'No data about jobs being affected by Covid or automation', {
                    'data.job_group_info.covid_risk',
                    'data.job_group_info.automation_risk'
                })

        # Total risk from 0 to 100.
        total_risk = 0

        # Covid risk: 0 if safe or no covid data at all, 25 if unknown, 50 if risky.
        covid_risk = project.job_group_info().covid_risk
        if covid_risk == job_pb2.COVID_RISKY:
            total_risk += 50
        elif not covid_risk and has_any_covid_risk_info:
            total_risk += 25

        # Automation risk: 0 if super safe or no covid data at all, 25 if unknown, 50 if very risky.
        automation_risk = project.job_group_info().automation_risk
        if automation_risk:
            total_risk += automation_risk // 2
        elif has_any_automation_risk_info:
            total_risk += 25

        if total_risk <= 15:
            # This job is as safe as it can be, no need to explore for more.
            return scoring_base.NULL_EXPLAINED_SCORE

        # 81+ => 3
        return scoring_base.ExplainedScore(min((total_risk - 15) / 22, 3), [
            project.translate_static_string(
                "il existe des métiers avec peu de risques d'automatisation",
            ),
        ])
示例#29
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        relevant_salons = self._get_relevant_salons(project)
        if not relevant_salons:
            return scoring_base.NULL_EXPLAINED_SCORE

        reasons = []
        # TODO(cyrille): Refine this depending on salons' locations.
        if project.details.area_type >= geo_pb2.COUNTRY:
            reasons.append(project.translate_static_string('vous êtes mobile partout en France'))
        elif any(salon.HasField('location') for salon in relevant_salons):
            reasons.append(project.translate_static_string(
                'certains salons concernent votre zone géographique'))

        if any(salon.job_group_ids for salon in relevant_salons):
            reasons.append(
                f'des entreprises {project.job_group_info().in_domain} recherchent du monde')

        return scoring_base.ExplainedScore(1, reasons)
示例#30
0
    def score_and_explain(self, project: scoring_base.ScoringProject) \
            -> scoring_base.ExplainedScore:
        """Compute a score for the given ScoringProject."""

        reasons = []
        if project.details.area_type < geo_pb2.COUNTRY:
            return scoring_base.NULL_EXPLAINED_SCORE
        reasons.append(
            project.populate_template(
                project.translate_static_string(
                    'vous nous avez dit être prêt%eFeminine à déménager')))

        local_stats = project.local_diagnosis()
        if local_stats.imt.yearly_avg_offers_per_10_candidates and \
                local_stats.num_less_stressful_departements:
            reasons.append(
                project.translate_static_string(
                    "il y a beaucoup plus d'offres par habitants dans d'autres villes"
                ))
            return scoring_base.ExplainedScore(2, reasons)
        return scoring_base.NULL_EXPLAINED_SCORE