def build_charts_data()

in pontoon/insights/tasks.py [0:0]


def build_charts_data(start_of_today):
    """Fetch and prepare data needed to render charts."""
    res = dict()

    sync_user = User.objects.get(email="pontoon-sync@example.com").pk
    pretranslation_users = User.objects.filter(
        email__in=[
            "pontoon-tm@example.com",
            "pontoon-gt@example.com",
        ]
    ).values_list("pk", flat=True)

    actions = query_actions(start_of_today)
    approved_translations = get_approved_translations(actions, pretranslation_users)

    for action in actions:
        key = (action["translation__locale"], action["project"])
        if key not in res:
            res[key] = {
                "human_translations": set(),
                "machinery_translations": set(),
                "new_suggestions": set(),
                "peer_approved": set(),
                "self_approved": set(),
                "rejected": set(),
                "pretranslations_chrf_scores": list(),
                "pretranslations_approved": set(),
                "pretranslations_rejected": set(),
                "pretranslations_new": set(),
                "times_to_review_suggestions": list(),
                "times_to_review_pretranslations": list(),
            }
        data = res[key]

        action_type = action["action_type"]
        performed_by = action["performed_by"]
        translation = action["translation"]

        # Review actions performed by the sync process are ignored, because they
        # aren't explicit user review actions.
        performed_by_sync = performed_by == sync_user

        if action_type == "translation:created":
            if len(action["machinery_sources"]) == 0:
                data["human_translations"].add(translation)
            else:
                data["machinery_translations"].add(translation)

            if not action["approved_date"] or action["approved_date"] > action["date"]:
                data["new_suggestions"].add(translation)

            if action["user"] in pretranslation_users:
                data["pretranslations_new"].add(translation)

            # Self-approval can also happen on translation submission
            if performed_by == action["approved_user"] and not performed_by_sync:
                data["self_approved"].add(translation)

        elif action_type == "translation:approved" and not performed_by_sync:
            if performed_by == action["user"]:
                data["self_approved"].add(translation)
            else:
                data["peer_approved"].add(translation)
                if action["approved_date"]:
                    review_time = action["approved_date"] - action["date"]
                    data["times_to_review_suggestions"].append(review_time)
                    if action["user"] in pretranslation_users:
                        data["times_to_review_pretranslations"].append(review_time)
            if action["user"] in pretranslation_users:
                data["pretranslations_approved"].add(translation)
                # Translation has been approved, no need to claculate the chrF++ score.
                # Note that the score is assigned to the pretranslation review date
                # rather than its creation date, which would be preferable.
                data["pretranslations_chrf_scores"].append(100)

        elif action_type == "translation:rejected" and not performed_by_sync:
            data["rejected"].add(translation)
            if action["rejected_date"]:
                review_time = action["rejected_date"] - action["date"]
                data["times_to_review_suggestions"].append(review_time)
                if action["user"] in pretranslation_users:
                    data["times_to_review_pretranslations"].append(review_time)
            if action["user"] in pretranslation_users:
                data["pretranslations_rejected"].add(translation)
                score = get_chrf_score(action, approved_translations)
                if score:
                    data["pretranslations_chrf_scores"].append(score)

    return res