예제 #1
0
            project.details.job_search_length_months or 1)
        if num_monthly_interviews > self._max_monthly_interviews(project):
            return 3
        # Whatever the number of month of search, trigger 3 if the user did more than 5 interviews:
        if num_interviews >= self._NUM_INTERVIEWS[project_pb2.A_LOT] and \
                project.details.job_search_length_months <= 6:
            return 3
        return 0

    def get_expanded_card_data(self, project):
        """Retrieve data for the expanded card."""
        interview_tips = project.list_application_tips()
        sorted_tips = sorted(interview_tips,
                             key=lambda t: (-len(t.filters), random.random()))
        tips_proto = application_pb2.InterviewTips(
            qualities=[
                t for t in sorted_tips if t.type == application_pb2.QUALITY
            ],
            preparations=[
                t for t in sorted_tips
                if t.type == application_pb2.INTERVIEW_PREPARATION
            ])
        for tip in itertools.chain(tips_proto.qualities,
                                   tips_proto.preparations):
            tip.ClearField('type')
        return tips_proto


scoring.register_model('advice-improve-interview', _AdviceImproveInterview())
scoring.register_model('advice-improve-resume', _AdviceImproveResume())
예제 #2
0
            try:
                geo.get_departement_name(own_departement)
            except KeyError:
                logging.warning(
                    'We cannot find the name of the French département "%s"',
                    own_departement)

        # We only advice departements that are better than own departement.
        min_offers = departement_to_offers.get(own_departement, 0)

        if not min_offers:
            return []

        # Compute the score for each departement.
        sorted_departements = sorted(departement_to_offers.items(),
                                     key=lambda x: x[1],
                                     reverse=True)

        # Get only departements that are strictly better than own departement.
        top_departements = [
            project_pb2.DepartementScore(name=geo.get_departement_name(dep[0]),
                                         offer_ratio=dep[1] / min_offers)
            for dep in sorted_departements if dep[1] > min_offers
        ]

        # Return at most 10 departements.
        return top_departements[:10]


scoring.register_model('advice-relocate', _AdviceRelocateScoringModel())
예제 #3
0
    @scoring.ScoringProject.cached('events')
    def list_events(self, project):
        """List all events close to the project's target."""
        today = project.now.strftime('%Y-%m-%d')
        all_events = [
            e for e in self._db.get_collection(project.database)
            if e.start_date >= today
        ]
        return list(
            scoring.filter_using_score(all_events, lambda e: e.filters,
                                       project))

    def compute_extra_data(self, project):
        """Compute extra data for this module to render a card in the client."""
        all_events = self.list_events(project)
        if not all_events:
            return None
        return project_pb2.EventsData(event_name=all_events[0].title)

    def get_expanded_card_data(self, project):
        """Retrieve data for the expanded card."""
        events = self.list_events(project)
        sorted_events = sorted(
            events,
            key=lambda j: (j.start_date, -len(j.filters), random.random()))
        return event_pb2.Events(events=sorted_events)


scoring.register_model('advice-event', _AdviceEventScoringModel())
예제 #4
0
        """Compute departements that propose seasonal jobs."""
        top_departements = seasonal_jobbing_pb2.MonthlySeasonalJobbingStats()

        # TODO(guillaume): Cache this to increase speed.
        proto.parse_from_mongo(
            project.database.seasonal_jobbing.find_one(
                {'_id': project.now.month}), top_departements)

        for departement in top_departements.departement_stats:
            # TODO(guillaume): If we don't use deeper jobgroups by october 1st 2017, trim the db.
            del departement.job_groups[6:]

            try:
                departement.departement_in_name = geo.get_in_a_departement_text(
                    departement.departement_id)
            except KeyError:
                logging.exception(
                    'Prefix or name not found for departement: %s',
                    departement.departement_id)
                continue

        for i, departement in enumerate(
                top_departements.departement_stats[::-1]):
            if not departement.departement_in_name:
                del top_departements.departement_stats[i]

        return top_departements or []


scoring.register_model('advice-seasonal-relocate', _AdviceSeasonalRelocate())
예제 #5
0
        """Compute extra data for this module to render a card in the client."""
        association_names = [
            m.association_name
            for m in self.volunteering_missions(project).missions
        ]

        # Deduplicate association names.
        seen = set()
        association_names = [
            n for n in association_names if not (n in seen or seen.add(n))
        ]

        return project_pb2.VolunteerData(
            association_names=association_names[:3])

    def score(self, project):
        """Compute a score for the given ScoringProject."""
        missions = self.volunteering_missions(project).missions
        if not missions:
            return 0
        if project.details.job_search_length_months < 9:
            return 1
        return 2

    def get_expanded_card_data(self, project):
        """Retrieve data for the expanded card."""
        return self.volunteering_missions(project)


scoring.register_model('advice-volunteer', _AdviceVolunteer())
예제 #6
0
    def compute_extra_data(self, project):
        """Compute extra data for this module to render a card in the client."""
        jobboards = [
            j for j in self.list_jobboards(project) if not j.is_well_known
        ]
        if not jobboards:
            return None
        sorted_jobboards = sorted(jobboards,
                                  key=lambda j:
                                  (-len(j.filters), random.random()))
        best_job_board = sorted_jobboards[0]
        return project_pb2.JobBoardsData(
            job_board_title=best_job_board.title,
            is_specific_to_job_group=any(
                f.startswith('for-job') for f in best_job_board.filters),
            is_specific_to_region=any(
                f.startswith('for-departement')
                for f in best_job_board.filters),
        )

    def get_expanded_card_data(self, project):
        """Retrieve data for the expanded card."""
        jobboards = self.list_jobboards(project)
        sorted_jobboards = sorted(jobboards,
                                  key=lambda j:
                                  (-len(j.filters), random.random()))
        return jobboard_pb2.JobBoards(job_boards=sorted_jobboards)


scoring.register_model('advice-job-boards', _AdviceJobBoards())
예제 #7
0
        if user_pb2.MOTIVATION in project.user_profile.frustrations:
            return 3
        if len(associations
               ) >= 3 and project.details.job_search_length_months >= 6:
            return 3
        if project.details.job_search_length_months >= 12:
            return 3
        return 2

    def compute_extra_data(self, project):
        """Compute extra data for this module to render a card in the client."""
        associations = self.list_associations(project)
        if not associations:
            return None
        sorted_associations = sorted(associations,
                                     key=lambda j:
                                     (-len(j.filters), random.random()))
        return project_pb2.AssociationsData(
            association_name=sorted_associations[0].name)

    def get_expanded_card_data(self, project):
        """Retrieve data for the expanded card."""
        associations = self.list_associations(project)
        sorted_associations = sorted(associations,
                                     key=lambda j:
                                     (-len(j.filters), random.random()))
        return association_pb2.Associations(associations=sorted_associations)


scoring.register_model('advice-association-help', _AdviceAssociationHelp())
예제 #8
0
        if distance >= _MAX_CITY_DISTANCE:
            continue

        try:
            relative_offers = (hiring_city.offers /
                               hiring_city.city.population) / ref
        except ZeroDivisionError:
            relative_offers = 0

        yield commute_pb2.CommutingCity(
            name=hiring_city.city.name,
            relative_offers_per_inhabitant=relative_offers,
            distance_km=distance)


def _compute_square_distance(city_a, city_b):
    """Compute the approximative distance between two cities.

    Since we only look at short distances, we can approximate that:
     - 1° latitude = 111km
     - 1° longitude = 111km * cos(lat)
    """
    delta_y = (city_a.latitude - city_b.latitude) * 111
    mean_latitude = (city_a.latitude + city_b.latitude) / 2
    delta_x = (city_a.longitude - city_b.longitude) * 111 * math.cos(
        math.radians(mean_latitude))
    return delta_x * delta_x + delta_y * delta_y


scoring.register_model('advice-commute', _AdviceCommuteScoringModel())
예제 #9
0
        specific_jobs = project.requirements().specific_jobs

        if not specific_jobs:
            return None

        extra_data = project_pb2.BetterJobInGroupData()
        try:
            extra_data.num_better_jobs = next(
                i for i, job in enumerate(specific_jobs)
                if job.code_ogr == project.details.target_job.code_ogr)
        except StopIteration:
            # Target job is not mentionned in the specific jobs, do not mention
            # the number of better jobs.
            pass

        all_jobs = project.job_group_info().jobs
        try:
            best_job = next(
                job for job in all_jobs
                if job.code_ogr == specific_jobs[0].code_ogr)
            extra_data.better_job.CopyFrom(best_job)
        except StopIteration:
            logging.warning(
                'Better job "%s" is not listed in the group "%s"', specific_jobs[0].code_ogr,
                project.job_group_info().rome_id)

        return extra_data


scoring.register_model('advice-better-job-in-group', _AdviceBetterJobInGroup())
예제 #10
0
        card_content = project.populate_template(best_lead.card_content)
        return project_pb2.Advice(card_text=card_content)

    def get_expanded_card_data(self, project):
        """Retrieve data for the expanded card."""
        contact_leads = self._list_contact_leads(project)
        sorted_leads = sorted(contact_leads,
                              key=lambda l: (-len(l.filters), random.random()))
        return network_pb2.ContactLeads(leads=[
            network_pb2.ContactLead(
                name=project.populate_template(template.name),
                email_example=project.populate_template(
                    template.email_template),
                contact_tip=template.contact_tip) for template in sorted_leads
        ])

    @scoring.ScoringProject.cached('contact-leads')
    def _list_contact_leads(self, project):
        return scoring.filter_using_score(
            self._db.get_collection(project.database), lambda l: l.filters,
            project)


scoring.register_model('advice-better-network',
                       _ImproveYourNetworkScoringModel(2))
scoring.register_model('advice-improve-network',
                       _ImproveYourNetworkScoringModel(1))
scoring.register_model('advice-use-good-network',
                       _ImproveYourNetworkScoringModel(3))