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)
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)
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)
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()