def test_extract_tourney_name(url, expected):
    """Extract the Challonge tourney name from URL."""
    try:
        assert util_challonge.extract_tourney_name(url) == expected
    except ValueError as e:
        if expected != ValueError:
            raise e
Beispiel #2
0
def update_seeds(tourney_url, sorted_participants):
    """This is a helper function to be called from the webapp."""
    tourney_name = util_challonge.extract_tourney_name(tourney_url)
    for seed, participant in enumerate(sorted_participants, 1):
        challonge.participants.update(tourney_name,
                                      participant["id"],
                                      seed=seed)
Beispiel #3
0
def seed_tournament(tourney_url, shuffle):
    """
    @params: same as argparse params

    @returns: a tuple consisting of:
        * List of participants sorted by seed, ascending.
        * List of players whose rank could not be found, along with what
            rank they were seeded.

    """
    # Make sure the tournament exists.
    tourney_name = util_challonge.extract_tourney_name(tourney_url)
    if not util_challonge.get_tourney_info(tourney_name):
        raise NoSuchTournamentError(
            "No tourney exists at {0}.".format(tourney_url))

    # Get the seeds for the participants.
    participants = challonge.participants.index(tourney_name)
    participant_names = [
        util_challonge.get_participant_name(x) for x in participants
    ]
    # ranks = garpr_seeds.get_garpr_ranks(participant_names, region)
    ranks = garpr_seeds.get_braacket_ranks(participant_names)
    new_seeds = garpr_seeds.ranks_to_seeds(ranks)

    # Let the user know which participants couldn't be found.
    players_unknown = []
    for i, _ in enumerate(participants):
        if ranks[i] == garpr_seeds.UNKNOWN_RANK:
            unknown = {"name": participant_names[i], "seed": new_seeds[i]}
            players_unknown.append(unknown)

    # Sort the participants on Challonge. They need to be sorted
    # before updating their seed, or else the order of the seeds could get
    # disrupted from reordering as seeds are changed.
    sorted_participants = _sort_by_seeds(participants, new_seeds)

    # Shuffle the seeds to vary up the bracket a bit.
    if shuffle:
        shuffled_seeds = shuffle_seeds.get_shuffled_seeds(len(participants))
        sorted_participants = _sort_by_seeds(sorted_participants,
                                             shuffled_seeds)

    return sorted_participants, players_unknown
        "URL for your tournament",
    )
    argparser.add_argument(
        "--config_file",
        default=defaults.DEFAULT_CONFIG_FILENAME,
        help="the config file to read your Challonge "
        "credentials from",
    )
    args = argparser.parse_args()

    initialized = util_challonge.set_challonge_credentials_from_config(
        args.config_file)
    if not initialized:
        sys.exit(1)

    tourney_name = util_challonge.extract_tourney_name(args.tourney_name)
    tourney_url = "http://challonge.com/{0}".format(tourney_name)
    tourney_info = challonge.tournaments.show(tourney_name)
    if tourney_info["state"] != "pending":
        sys.stderr.write("Can only run {0} on tournaments that haven't "
                         "started.\n".format(sys.argv[0]))
        sys.exit(1)

    # The participants need to be sorted by seed so their index in the
    # list matches up with the shuffled seeds list.
    participant_infos = sorted(challonge.participants.index(tourney_name),
                               key=lambda x: x["seed"])
    num_participants = len(participant_infos)
    new_seeds = shuffle_seeds.get_shuffled_seeds(num_participants)

    for i, new_seed in enumerate(new_seeds):
Beispiel #5
0
def create_amateur_bracket(tourney_url,
                           single_elimination,
                           losers_round_cutoff,
                           randomize_seeds,
                           associate_challonge_accounts=False,
                           incomplete=False,
                           interactive=False):
    """
    Create the amateur bracket.

    Most of the params are the same as their argparse counterpart.

    @param interactive: If this is being run on the command line and can take
        user input.

    @returns: URL of the generated amateur bracket.

    """
    # Create the info for our amateur's bracket.
    tourney_name = util_challonge.extract_tourney_name(tourney_url)
    tourney_info = challonge.tournaments.show(tourney_name)
    tourney_title = tourney_info["name"]
    amateur_tourney_title = tourney_title + " Amateur's Bracket"
    amateur_tourney_name = tourney_name + "_amateur"
    amateur_tourney_url = util_challonge.tourney_name_to_url(
        amateur_tourney_name)
    if single_elimination:
        amateur_tourney_type = "single elimination"
    else:
        amateur_tourney_type = "double elimination"

    # Make sure the tournament doesn't already exist.
    existing_amateur_tournament = util_challonge.get_tourney_info(
        amateur_tourney_name)
    if existing_amateur_tournament:
        raise AmateurBracketAlreadyExistsError(
            "Amateur tournament already exists at {}.".format(
                amateur_tourney_url))

    # Get all decided loser's matches until the cutoff.
    cutoff = losers_round_cutoff
    matches = challonge.matches.index(tourney_name)
    amateur_deciding_matches = _get_losers_matches_determining_amateurs(
        matches, cutoff)
    num_completed_deciding_matches = sum(
        1 for x in amateur_deciding_matches
        if x[_PARAMS_STATE] == _MATCH_STATE_COMPLETE)
    num_amateurs = _get_num_amateurs(tourney_info["participants_count"],
                                     cutoff)

    # If they're not all complete, we don't have enough info to create the
    # amateur bracket.
    if num_completed_deciding_matches != num_amateurs:
        matches_remaining = num_amateurs - num_completed_deciding_matches
        err = AmateurBracketRequiredMatchesIncompleteError(
            "There are still {0} matches incomplete before loser's round {1}.\n"
            "Please wait for these matches to complete before creating the\n"
            "amateur bracket.\n"
            "The last loser's round for amateur's qualification can be\n"
            "configured using the --losers_round_cutoff flag.\n".format(
                matches_remaining, cutoff + 1), matches_remaining)

        if interactive:
            print(err)

            if not incomplete:
                print("Alternatively, we can 'approximate' the amateur\n"
                      "bracket if you pass in the --incomplete flag.")
                sys.exit()
            else:
                if not util.prompt_yes_no("Create amateur bracket anyway?"):
                    sys.exit()

        elif not incomplete:
            raise err

    # Gather up all the amateurs.
    amateur_infos = get_amateur_participants(tourney_name,
                                             amateur_deciding_matches)

    # Sort them based on seeding.
    if randomize_seeds:
        seed_fn = lambda x: random.random()
    else:
        seed_fn = lambda x: x[_PARAMS_SEED]
    amateur_infos = sorted(amateur_infos, key=seed_fn)

    all_amateur_params = [
        _get_params_to_create_participant(
            amateur_info,
            associate_challonge_account=associate_challonge_accounts,
            seed=seed) for seed, amateur_info in enumerate(amateur_infos, 1)
    ]

    if interactive:
        # Confirm with the user that this is all okay.
        print("I creeped your tourney at http://challonge.com/{0}...".format(
            tourney_name))
        print((
            "Here's what I think the amateur bracket should look like, taking\n"
            "all people eliminated before Loser's Round {0}:".format(cutoff +
                                                                     1)))
        print()
        print("Title: {0}".format(amateur_tourney_title))
        print("URL: {0}".format(amateur_tourney_url))
        print("Elimination Type: {0}".format(amateur_tourney_type))
        print()
        print("Seeds:")
        need_to_send_at_least_one_invite = any(
            x.get(_PARAMS_CHALLONGE_USERNAME) for x in all_amateur_params)
        if need_to_send_at_least_one_invite:
            # I really don't want people accidentally sending email invites, so
            # we're very explicit about email invites and how to turn them off.
            print(
                "(to disable invites, use --associate_challonge_accounts=False)"
            )
        for amateur_params in all_amateur_params:
            print("\t{0}. {1}".format(amateur_params[_PARAMS_SEED],
                                      amateur_params[_PARAMS_NAME]))
            if amateur_params.get(_PARAMS_CHALLONGE_USERNAME):
                print("\t\t- Challonge account will receive email invite.")
        print()
        if not util.prompt_yes_no(
                "Is it okay to create this amateur's bracket?"):
            print("Aw man. Alright, I'm not creating this amateur's bracket.")
            print(random.choice(puns.AMATEUR_PUNS))
            print("( Feel free to report bugs and request features at "
                  "https://github.com/akbiggs/challonge-tools/issues )")
            sys.exit(1)

    # We've got confirmation. Go ahead and create the amateur bracket.
    tourney, subdomain = util_challonge.tourney_name_to_parts(
        amateur_tourney_name)
    challonge.tournaments.create(amateur_tourney_title,
                                 tourney,
                                 amateur_tourney_type,
                                 subdomain=subdomain)

    for amateur_params in all_amateur_params:
        challonge.participants.create(amateur_tourney_name, **amateur_params)

    if interactive:
        print("Created {0} at {1}.".format(amateur_tourney_title,
                                           amateur_tourney_url))
        print("Start the amateur bracket at the above URL when you're ready!")

    return amateur_tourney_url
    """Extract the numbers at the end of tournament series."""
    m = re.search(r'(\d+)$', tourney_id)
    return int(m.group(1))

# Get config file from args.
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--ini', default='create_next.ini',
                    help='config file to read from')
args = parser.parse_args()

config = configparser.ConfigParser()
config.read(args.ini)
latest_url = config['Settings']['latest_tournament_url']
user = config['Settings']['user']
api_key = config['Settings']['api_key']
tourney_id = util_challonge.extract_tourney_name(latest_url)

challonge.set_credentials(user, api_key)
# Parameters to copy from previous tournament.
parameters = challonge.tournaments.show(tourney_id)
important_keys = {
    'name', 'tournament_type', 'url', 'subdomain', 'description',
    'open_signup', 'hold_third_place_match', 'pts_for_match_win',
    'pts_for_match_tie', 'pts_for_game_win', 'pts_for_game_tie',
    'pts_for_bye', 'swiss_rounds', 'ranked_by', 'rr_pts_for_match_win',
    'rr_pts_for_match_tie', 'rr_pts_for_game_win', 'rr_pts_for_game_tie',
    'accept_attachments', 'hide_forum', 'show_rounds', 'private',
    'notify_users_when_matches_open',
    'notify_users_when_the_tournament_ends', 'sequential_pairings',
    'signup_cap', 'check_in_duration', 'grand_finals_modifier',
}