Exemple #1
0
def _make_strategy(
        project: scoring.ScoringProject, module: strategy_pb2.StrategyModule,
        advice_scores: dict[str, float]) -> Optional[strategy_pb2.Strategy]:
    if module.is_for_alpha and not project.features_enabled.alpha:
        return None
    score = project.score(module.trigger_scoring_model)
    if not score:
        return None
    score = min(score * 100 / 3, 100 - project.details.diagnostic.overall_score)
    pieces_of_advice = []
    for advice in module.pieces_of_advice:
        user_advice_id = next((a for a in advice_scores if a.startswith(advice.advice_id)), None)
        if not user_advice_id:
            if advice.is_required:
                # A necessary advice is missing, we drop everything.
                return None
            continue
        pieces_of_advice.append(strategy_pb2.StrategyAdvice(
            advice_id=user_advice_id,
            teaser=project.populate_template(project.translate_string(advice.teaser_template)),
            why=project.populate_template(project.translate_string(advice.why_template))))
    if _SPECIFIC_TO_JOB_ADVICE_ID in advice_scores:
        specific_to_job_config = project.specific_to_job_advice_config()
        if specific_to_job_config and module.strategy_id in specific_to_job_config.strategy_ids:
            pieces_of_advice.append(strategy_pb2.StrategyAdvice(
                advice_id=_SPECIFIC_TO_JOB_ADVICE_ID))
    if not pieces_of_advice and not module.external_url_template:
        # Don't want to show a strategy without any advice modules.
        return None
    strategy = project.details.strategies.add(
        description=project.populate_template(project.translate_airtable_string(
            'strategyModules', module.strategy_id, 'description_template',
            hint=module.description_template)),
        score=int(score),
        is_secondary=score <= 10,
        title=project.translate_airtable_string(
            'strategyModules', module.strategy_id, 'title', hint=module.title),
        header=project.populate_template(project.translate_airtable_string(
            'strategyModules', module.strategy_id, 'header_template',
            hint=module.header_template)),
        strategy_id=module.strategy_id,
        external_url=project.populate_template(module.external_url_template),
        infinitive_title=project.translate_airtable_string(
            'strategyModules', module.strategy_id, 'infinitive_title',
            hint=module.infinitive_title),
        action_ids=module.action_ids,
        description_speech=project.populate_template(project.translate_airtable_string(
            'strategyModules', module.strategy_id, 'description_speech',
            hint=module.description_speech, is_genderized=True)),
    )

    if strategy.external_url and pieces_of_advice:
        logging.error(
            'Strategy %s has both an external URL and some pieces of advice:\n%s',
            strategy.strategy_id, ', '.join(a.advice_id for a in pieces_of_advice))

    # Sort found pieces of advice by descending score.
    pieces_of_advice.sort(key=lambda a: advice_scores[a.advice_id], reverse=True)
    strategy.pieces_of_advice.extend(pieces_of_advice)
    return strategy
Exemple #2
0
def _compute_diagnostic_topic_score(
        topic: 'diagnostic_pb2.DiagnosticTopic',
        scorers: Iterable[diagnostic_pb2.DiagnosticSubmetricScorer],
        scoring_project: scoring.ScoringProject) \
        -> Optional[diagnostic_pb2.SubDiagnostic]:
    """Create the score for a given diagnostic submetric on a given project.

    Args:
        topic: the diagnostic topic we wish to evaluate
        scorers: a list of scorers for the given topic, with a weight on each.
        scoring_project: the project we want to score
    Returns:
        the populated subdiagnostic protobuf.
    """

    topic_score = 0.
    topic_weight = 0.
    sub_diagnostic = diagnostic_pb2.SubDiagnostic(topic=topic)

    for scorer in scorers:
        try:
            score = scoring_project.score(scorer.trigger_scoring_model)
        except scoring.NotEnoughDataException:
            continue
        # Use default weight of 1
        weight = scorer.weight or 1
        weighted_score = score * weight
        topic_score += weighted_score
        topic_weight += weight
    if not topic_weight:
        return None

    sub_diagnostic.score = round(topic_score / topic_weight * 100 / 3)

    return sub_diagnostic
Exemple #3
0
def _make_strategy(
        project: scoring.ScoringProject, module: strategy_pb2.StrategyModule,
        advice_scores: Dict[str, float]) -> Optional[strategy_pb2.Strategy]:
    score = project.score(module.trigger_scoring_model)
    if not score:
        return None
    score = min(score * 100 / 3,
                100 - project.details.diagnostic.overall_score)
    pieces_of_advice = []
    for advice in module.pieces_of_advice:
        user_advice_id = next(
            (a for a in advice_scores if a.startswith(advice.advice_id)), None)
        if not user_advice_id:
            if advice.is_required:
                # A necessary advice is missing, we drop everything.
                return None
            continue
        pieces_of_advice.append(
            strategy_pb2.StrategyAdvice(
                advice_id=user_advice_id,
                teaser=project.populate_template(
                    project.translate_string(advice.teaser_template)),
                header=project.populate_template(
                    project.translate_string(advice.header_template))))
    if _SPECIFIC_TO_JOB_ADVICE_ID in advice_scores:
        specific_to_job_config = project.specific_to_job_advice_config()
        if specific_to_job_config and module.strategy_id in specific_to_job_config.strategy_ids:
            pieces_of_advice.append(
                strategy_pb2.StrategyAdvice(
                    advice_id=_SPECIFIC_TO_JOB_ADVICE_ID))
    if not pieces_of_advice:
        # Don't want to show a strategy without any advice modules.
        return None
    strategy = project.details.strategies.add(
        description=project.populate_template(
            project.translate_string(module.description_template)),
        score=int(score),
        is_secondary=score <= 10,
        title=project.translate_string(module.title),
        header=project.populate_template(
            project.translate_string(module.header_template)),
        strategy_id=module.strategy_id)

    # Sort found pieces of advice by descending score.
    pieces_of_advice.sort(key=lambda a: advice_scores[a.advice_id],
                          reverse=True)
    strategy.pieces_of_advice.extend(pieces_of_advice)
    return strategy
Exemple #4
0
def _get_relevance_from_its_model(
        main_challenge: diagnostic_pb2.DiagnosticMainChallenge,
        project: scoring.ScoringProject,
        has_missing_fields: bool,
        relevant_should_be_neutral: bool) \
        -> 'diagnostic_pb2.MainChallengeRelevance.V':
    if main_challenge.relevance_scoring_model:
        relevance_score = project.score(main_challenge.relevance_scoring_model)
        if relevance_score <= 0:
            return diagnostic_pb2.NOT_RELEVANT
        if relevance_score >= 3 and not relevant_should_be_neutral:
            return diagnostic_pb2.RELEVANT_AND_GOOD
        return diagnostic_pb2.NEUTRAL_RELEVANCE
    if has_missing_fields:
        return diagnostic_pb2.NEUTRAL_RELEVANCE
    return diagnostic_pb2.NEUTRAL_RELEVANCE if relevant_should_be_neutral else \
        diagnostic_pb2.RELEVANT_AND_GOOD
Exemple #5
0
def _get_relevance_from_its_model(
        category: diagnostic_pb2.DiagnosticCategory,
        project: scoring.ScoringProject,
        has_missing_fields: bool) \
        -> diagnostic_pb2.CategoryRelevance:
    if category.relevance_scoring_model:
        relevance_score = project.score(category.relevance_scoring_model)
        if relevance_score <= 0:
            return diagnostic_pb2.NOT_RELEVANT
        if relevance_score >= 3:
            return diagnostic_pb2.RELEVANT_AND_GOOD
        return diagnostic_pb2.NEUTRAL_RELEVANCE
    try:
        return _CATEGORIES_RELEVANCE_GETTERS[category.category_id](project)
    except KeyError:
        if has_missing_fields:
            return diagnostic_pb2.NEUTRAL_RELEVANCE
        return diagnostic_pb2.RELEVANT_AND_GOOD