<commit_before>""" Module for interacting with the achievements """

import imp
import pymongo

import api

from functools import wraps
from os.path import join
from datetime import datetime
from voluptuous import Schema, Required, Range
from api.common import check, InternalException, SevereInternalException, validate, safe_fail, WebException

processor_base_path = "./processors"

achievement_schema = Schema({
    Required("name"): check(
        ("The achievement's display name must be a string.", [str])),
    Required("score"): check(
        ("Score must be a positive integer.", [int, Range(min=0)])),
    Required("event"): check(
        ("Type must be a string.", [str])),
    Required("description"): check(
        ("The description must be a string.", [str])),
    Required("processor"): check(
        ("The processor path must be a string.", [str])),
    Required("hidden"): check(
        ("An achievement's hidden state is either True or False.", [
            lambda hidden: type(hidden) == bool])),
    Required("image"): check(
        ("An achievement's image path must be a string.", [str])),
    "disabled": check(
        ("An achievement's disabled state is either True or False.", [
            lambda disabled: type(disabled) == bool])),
    "aid": check(
        ("You should not specify a aid for an achievement.", [lambda _: False])),
    "_id": check(
        ("Your achievements should not already have _ids.", [lambda id: False]))
})

def get_all_events(show_disabled=False):
    """
    Gets the set of distinct achievement events.

    Args:
        show_disabled: Whether to include events that are only on disabled achievements
    Returns:
        The set of distinct achievement events.
    """

    db = api.common.get_conn()

    match = {}
    if not show_disabled:
        match.update({"disabled": False})

    return db.achievemets.find(match).distinct("event")

def get_achievement(aid=None, name=None, show_disabled=False):
    """
    Gets a single achievement

    Args:
        aid: the achievement id
        name: the name of the achievement
        show_disabled: Boolean indicating whether or not to show disabled achievements.
    """

    db = api.common.get_conn()

    match = {}

    if aid is not None:
        match.update({'aid': aid})
    elif name is not None:
        match.update({'name': name})
    else:
        raise InternalException("Must supply aid or display name")

    if not show_disabled:
        match.update({"disabled": False})

    db = api.common.get_conn()
    achievement = db.achievements.find_one(match, {"_id":0})

    if achievement is None:
        raise SevereInternalException("Could not find achievement! You gave " + str(match))

    return achievement

def get_all_achievements(event=None, show_disabled=False):
    """
    Gets all of the achievements in the database.

    Args:
        event: Optional parameter to restrict which achievements are returned
        show_disabled: Boolean indicating whether or not to show disabled achievements.
    Returns:
        List of achievements from the database
    """

    db = api.common.get_conn()

    match = {}
    if event is not None:
        match.update({'event': event})

    if not show_disabled:
        match.update({'disabled': False})

    return list(db.achievements.find(match, {"_id":0}).sort('score', pymongo.ASCENDING))

def get_earned_achievement_entries(tid=None, uid=None, aid=None):
    """
    Gets the solved achievements for a given team or user.

    Args:
        tid: The team id
        event: Optional parameter to restrict which achievements are returned
    Returns:
        List of solved achievements
    """

    db = api.common.get_conn()

    match = {}

    if uid is not None:
        match.update({"uid": uid})
    elif tid is not None:
        match.update({"tid": tid})

    if aid is not None:
        match.update({"aid": aid})

    return list(db.earned_achievements.find(match, {"_id":0}))

def get_earned_aids(tid=None, uid=None, aid=None):
    """
    Gets the solved aids for a given team or user.

    Args:
        tid: The team id
        event: Optional parameter to restrict which achievements are returned
    Returns:
        List of solved achievement ids
    """

    return [a["aid"] for a in get_earned_achievement_entries(tid=tid, uid=uid, aid=aid)]

def set_earned_achievements_seen(tid=None, uid=None):
    """
    Sets all earned achievements from a team or user seen.

    Args:
        tid: the team id
        uid: the user id
    """

    db = api.common.get_conn()

    match = {}

    if tid is not None:
        match.update({"tid": tid})
    elif uid is not None:
        match.update({"uid": uid})
    else:
        raise InternalException("You must specify either a tid or uid")

    db.earned_achievements.update(match, {"$set": {"seen": True}}, multi=True)

def get_earned_achievements(tid=None, uid=None):
    """
    Gets the solved achievements for a given team or user.

    Args:
        tid: The team id
        tid: The user id
    Returns:
        List of solved achievement dictionaries
    """

    achievements = [get_achievement(aid=achievement["aid"]) for achievement in get_earned_achievement_entries(tid=tid, uid=uid)]
    set_earned_achievements_seen(tid=tid, uid=uid)

    for achievement in achievements:
        if achievement["hidden"]:
            achievement["description"] = ""

    return achievements

def reevaluate_earned_achievements(aid):
    """
    In the case of the achievement or processor being updated, this will reevaluate earned achievements for an achievement.

    Args:
        aid: the aid of the achievement to be reevaluated.
    """

    db = api.common.get_conn()

    get_achievement(aid=aid, show_disabled=True)

    keys = []<commit_msg>Prevent leaking information from achievements.<commit_after>""" Module for interacting with the achievements """

import imp
import pymongo

import api

from functools import wraps
from os.path import join
from datetime import datetime
from voluptuous import Schema, Required, Range
from api.common import check, InternalException, SevereInternalException, validate, safe_fail, WebException

processor_base_path = "./processors"

achievement_schema = Schema({
    Required("name"): check(
        ("The achievement's display name must be a string.", [str])),
    Required("score"): check(
        ("Score must be a positive integer.", [int, Range(min=0)])),
    Required("event"): check(
        ("Type must be a string.", [str])),
    Required("description"): check(
        ("The description must be a string.", [str])),
    Required("processor"): check(
        ("The processor path must be a string.", [str])),
    Required("hidden"): check(
        ("An achievement's hidden state is either True or False.", [
            lambda hidden: type(hidden) == bool])),
    Required("image"): check(
        ("An achievement's image path must be a string.", [str])),
    "disabled": check(
        ("An achievement's disabled state is either True or False.", [
            lambda disabled: type(disabled) == bool])),
    "aid": check(
        ("You should not specify a aid for an achievement.", [lambda _: False])),
    "_id": check(
        ("Your achievements should not already have _ids.", [lambda id: False]))
})

def get_all_events(show_disabled=False):
    """
    Gets the set of distinct achievement events.

    Args:
        show_disabled: Whether to include events that are only on disabled achievements
    Returns:
        The set of distinct achievement events.
    """

    db = api.common.get_conn()

    match = {}
    if not show_disabled:
        match.update({"disabled": False})

    return db.achievemets.find(match).distinct("event")

def get_achievement(aid=None, name=None, show_disabled=False):
    """
    Gets a single achievement

    Args:
        aid: the achievement id
        name: the name of the achievement
        show_disabled: Boolean indicating whether or not to show disabled achievements.
    """

    db = api.common.get_conn()

    match = {}

    if aid is not None:
        match.update({'aid': aid})
    elif name is not None:
        match.update({'name': name})
    else:
        raise InternalException("Must supply aid or display name")

    if not show_disabled:
        match.update({"disabled": False})

    db = api.common.get_conn()
    achievement = db.achievements.find_one(match, {"_id":0})

    if achievement is None:
        raise SevereInternalException("Could not find achievement! You gave " + str(match))

    return achievement

def get_all_achievements(event=None, show_disabled=False):
    """
    Gets all of the achievements in the database.

    Args:
        event: Optional parameter to restrict which achievements are returned
        show_disabled: Boolean indicating whether or not to show disabled achievements.
    Returns:
        List of achievements from the database
    """

    db = api.common.get_conn()

    match = {}
    if event is not None:
        match.update({'event': event})

    if not show_disabled:
        match.update({'disabled': False})

    return list(db.achievements.find(match, {"_id":0}).sort('score', pymongo.ASCENDING))

def get_earned_achievement_entries(tid=None, uid=None, aid=None):
    """
    Gets the solved achievements for a given team or user.

    Args:
        tid: The team id
        event: Optional parameter to restrict which achievements are returned
    Returns:
        List of solved achievements
    """

    db = api.common.get_conn()

    match = {}

    if uid is not None:
        match.update({"uid": uid})
    elif tid is not None:
        match.update({"tid": tid})

    if aid is not None:
        match.update({"aid": aid})

    return list(db.earned_achievements.find(match, {"_id":0}))

def get_earned_aids(tid=None, uid=None, aid=None):
    """
    Gets the solved aids for a given team or user.

    Args:
        tid: The team id
        event: Optional parameter to restrict which achievements are returned
    Returns:
        List of solved achievement ids
    """

    return [a["aid"] for a in get_earned_achievement_entries(tid=tid, uid=uid, aid=aid)]

def set_earned_achievements_seen(tid=None, uid=None):
    """
    Sets all earned achievements from a team or user seen.

    Args:
        tid: the team id
        uid: the user id
    """

    db = api.common.get_conn()

    match = {}

    if tid is not None:
        match.update({"tid": tid})
    elif uid is not None:
        match.update({"uid": uid})
    else:
        raise InternalException("You must specify either a tid or uid")

    db.earned_achievements.update(match, {"$set": {"seen": True}}, multi=True)

def get_earned_achievements(tid=None, uid=None):
    """
    Gets the solved achievements for a given team or user.

    Args:
        tid: The team id
        tid: The user id
    Returns:
        List of solved achievement dictionaries
    """

    achievements = [get_achievement(aid=achievement["aid"]) for achievement in get_earned_achievement_entries(tid=tid, uid=uid)]
    set_earned_achievements_seen(tid=tid, uid=uid)

    for achievement in achievements:
        if achievement["hidden"]:
            achievement["description"] = ""
        achievement.pop("data")

    return achievements

def reevaluate_earned_achievements(aid):
    """
    In the case of the achievement or processor being updated, this will reevaluate earned achievements for an achievement.

    Args:
        aid: the aid of the achievement to be reevaluated.
    """

    db = api.common.get_conn()

    get_achievement(aid=aid, show_disabled=True)

    keys = []
{'fraction_non_alphanumeric': 0.10819138919797996, 'fraction_numerical': 0.0006847556278353163, 'mean_word_length': 2.949966193373901, 'pattern_counts': {'":': 30, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '801202', 'n_tokens_mistral': 3303, 'n_tokens_neox': 3241, 'n_words': 1141}