Esempio n. 1
0
def complete_match(pattern: str, scope=None):
    """ Find a user or users who match the given pattern.

    :param pattern: Pattern to match on. The format is "[nick][:account]",
        with [] denoting an optional field. Exact matches are tried, and then
        prefix matches (stripping special characters as needed). If both a nick
        and an account are specified, both must match.
    :param Optional[Iterable[User]] scope: Users to match pattern against. If None,
        search against all users.
    :returns: A Match object describing whether or not the match succeeded.
    :rtype: Match[User]
    """
    if scope is None:
        scope = _users
    matches = []
    nick_search, _, acct_search = lower(pattern).partition(":")
    if not nick_search and not acct_search:
        return Match([])

    direct_match = False
    for user in scope:
        nick = lower(user.nick)
        stripped_nick = nick.lstrip("[{\\^_`|}]")
        if nick_search:
            if nick == nick_search:
                if not direct_match:
                    matches.clear()
                    direct_match = True
                matches.append(user)
            elif not direct_match and (nick.startswith(nick_search) or
                                       stripped_nick.startswith(nick_search)):
                matches.append(user)
        else:
            matches.append(user)

    if acct_search:
        scope = list(matches)
        matches.clear()
        direct_match = False
        for user in scope:
            if not user.account:
                continue  # fakes don't have accounts, so this search won't be able to find them
            acct = lower(user.account)
            stripped_acct = acct.lstrip("[{\\^_`|}]")
            if acct == acct_search:
                if not direct_match:
                    matches.clear()
                    direct_match = True
                matches.append(user)
            elif not direct_match and (acct.startswith(acct_search) or
                                       stripped_acct.startswith(acct_search)):
                matches.append(user)

    return Match(matches)
Esempio n. 2
0
def match_totem(var,
                totem: str,
                scope: Optional[Iterable[str]] = None) -> Match[LocalTotem]:
    """ Match a partial totem into the internal totem key.

    :param var: Game state
    :param totem: Partial totem to match on
    :param scope: Limit matched modes to these explicitly passed-in totems (iterable of internal totem names).
    :return: Match object with all matches (see src.match.match_all)
    """
    mode = totem.lower()
    totem_map = messages.get_totem_mapping(reverse=True)
    matches = match_all(totem, totem_map.keys())

    # strip matches that aren't in scope, and convert to LocalMode objects
    filtered_matches = set()
    if scope is not None:
        allowed = set(scope)
    else:
        allowed = set(totem_map.keys())

    for match in matches:
        if totem_map[match] in allowed:
            filtered_matches.add(LocalTotem(totem_map[match], match))

    return Match(filtered_matches)
Esempio n. 3
0
def match_role(var,
               role: str,
               remove_spaces: bool = False,
               allow_extra: bool = False,
               allow_special: bool = True,
               scope: Optional[Iterable[str]] = None) -> Match[LocalRole]:
    """ Match a partial role or alias name into the internal role key.

    :param var: Game state
    :param role: Partial role to match on
    :param remove_spaces: Whether or not to remove all spaces before matching.
        This is meant for contexts where we truly cannot allow spaces somewhere; otherwise we should
        prefer that the user matches including spaces where possible for friendlier-looking commands.
    :param allow_extra: Whether to allow keys that are defined in the translation file but do not exist in the bot.
        Typically these are roles that were previously removed.
    :param allow_special: Whether to allow special keys (lover, vg activated, etc.).
        If scope is set, this parameter is ignored.
    :param scope: Limit matched roles to these explicitly passed-in roles (iterable of internal role names).
    :return: Match object with all matches (see src.match.match_all)
    """
    role = role.lower()
    if remove_spaces:
        role = role.replace(" ", "")

    role_map = messages.get_role_mapping(reverse=True,
                                         remove_spaces=remove_spaces)

    special_keys = set()
    if scope is None and allow_special:
        evt = Event("get_role_metadata", {})
        evt.dispatch(var, "special_keys")
        special_keys = functools.reduce(lambda x, y: x | y, evt.data.values(),
                                        special_keys)

    matches = match_all(role, role_map.keys())

    # strip matches that don't refer to actual roles or special keys (i.e. refer to team names)
    filtered_matches = set()
    if scope is not None:
        allowed = set(scope)
    elif allow_extra:
        allowed = set(role_map.values()) | special_keys
    else:
        allowed = All.roles | special_keys

    for match in matches:
        if role_map[match] in allowed:
            filtered_matches.add(LocalRole(role_map[match], match))

    return Match(filtered_matches)
Esempio n. 4
0
def match_mode(var,
               mode: str,
               remove_spaces: bool = False,
               allow_extra: bool = False,
               scope: Optional[Iterable[str]] = None) -> Match[LocalMode]:
    """ Match a partial game mode into the internal game mode key.

    :param var: Game state
    :param mode: Partial game mode to match on
    :param remove_spaces: Whether or not to remove all spaces before matching.
        This is meant for contexts where we truly cannot allow spaces somewhere; otherwise we should
        prefer that the user matches including spaces where possible for friendlier-looking commands.
    :param allow_extra: Whether to allow keys that are defined in the translation file but do not exist in the bot.
        Typically these are game modes that were previously removed.
    :param scope: Limit matched modes to these explicitly passed-in modes (iterable of internal mode names).
    :return: Match object with all matches (see src.match.match_all)
    """
    mode = mode.lower()
    if remove_spaces:
        mode = mode.replace(" ", "")

    mode_map = messages.get_mode_mapping(reverse=True,
                                         remove_spaces=remove_spaces)
    matches = match_all(mode, mode_map.keys())

    # strip matches that aren't in scope, and convert to LocalMode objects
    filtered_matches = set()
    if scope is not None:
        allowed = set(scope)
    elif allow_extra:
        allowed = set(mode_map.values())
    else:
        allowed = set(var.GAME_MODES)

    for match in matches:
        if mode_map[match] in allowed:
            filtered_matches.add(LocalMode(mode_map[match], match))

    return Match(filtered_matches)
goodWinnerPlayer = [
    0.6, 0.05, 0.99, 0.003, 0.1, 0.04, 0.8, 0.005, 0.9, 0.1, 0.85, 0.07
]
goodReturnPlayer = [
    0.57, 0.02, 0.98, 0.003, 0.075, 0.03, 0.85, 0.015, 0.95, 0.2, 0.8, 0.05
]
goodBaselinePlayer = [
    0.6, 0.03, 0.99, 0.002, 0.07, 0.03, 0.85, 0.005, 0.925, 0.075, 0.9, 0.02
]

# create instances of two players who play a match
player1 = Player("Milos Raonic", goodServePlayer)
player2 = Player("Andy Murray", goodWinnerPlayer)
player3 = Player("Kei Nishikori", goodBaselinePlayer)
player4 = Player("Tomas Berdych", goodReturnPlayer)

# create an instance of a match featuring both players
sf1match = Match(player1, player2, 3).run()
sf2match = Match(player3, player4, 3).run()
# starts the match
if (sf1match == 1):
    if (sf2match == 1):
        fmatch = Match(player1, player3, 3).run()
    else:
        fmatch = Match(player1, player4, 3).run()
else:
    if (sf2match == 1):
        fmatch = Match(player2, player3, 3).run()
    else:
        fmatch = Match(player2, player4, 3).run()