def tournament(players=None): """ Runs a Magic limited event (draft or sealed). players: List of player names (defaults to DEFAULT_PLAYERS, with the option to change the list). """ if not players: players = DEFAULT_PLAYERS change = DEFAULT_STRING while change: change = menu("Players", players, footer="Enter a name to add or " "remove a player (ENTER for none).") if change and (change in players): players -= {change} elif change: players.add(change) players = {p: Player(p) for p in players} items = MAIN_MENU.keys() items.sort() call = menu("Main Menu", items, input_range=range(1, len(items) + 1)) while MAIN_MENU[items[int(call) - 1]]: MAIN_MENU[items[int(call) - 1]](players) call = menu("Main Menu", items, input_range=range(1, len(items) + 1))
def seat_players(players): active = active_players(players) names = active.keys() random.shuffle(names) table_count = number_of_tables(len(active)) table_size = int(math.ceil(float(len(active)) / table_count)) print "Players: {}".format(len(active)) print "Tables: {}".format(table_count) print "Seats per Table: {}".format(table_size) rows = [] for table in xrange(table_count): for seat in xrange(table_size): index = (table * table_size) + seat if len(active) <= index: break else: active[names[index]].table = table + 1 active[names[index]].seat = seat + 1 rows.append((table + 1, seat + 1, names[index])) menu("Seating", *zip(*rows), headers=["Table", "Seat", "Player"], footer="ENTER to continue.")
def standings(players): player_list = players.values() player_list.sort(reverse=True) names = [p.name for p in player_list] points = [p.points() for p in player_list] tiebreaker_1 = [p.tb_1() for p in player_list] tiebreaker_2 = [p.tb_2() for p in player_list] tiebreaker_3 = [p.tb_3() for p in player_list] dropped = ["" if p.active else "Yes" for p in player_list] menu("Standings", names, points, tiebreaker_1, tiebreaker_2, tiebreaker_3, dropped, footer="ENTER to continue.", headers=["Player", "Points", "TB 1", "TB 2", "TB 3", "Dropped?"])
def drop_player(players): drop = DEFAULT_STRING while drop: drop = menu("Drop Players", players.keys(), ["" if players[k].active else "Yes" for k in players.keys()], headers=["Player", "Dropped?"], footer="Enter a name to drop that player " "(ENTER for none).", input_range=players.keys()+[""]) if drop: players[drop].drop()
def player_stats(players): p = DEFAULT_STRING while p: p = menu("Display Player Stats", players.keys(), ["" if players[k].active else "Yes" for k in players.keys()], headers=["Player", "Dropped?"], footer="Enter a name to " "view that player's stats. (ENTER for none).", input_range=players.keys()+[""]) if p: players[p].display()
def label_episodes(series, directory, season, episode, dvd): episodes = season_information(series, dvd) if season not in episodes: print "No information found for season {}.".format(season) return files = os.listdir(directory) # Remove directories and files that don't match the pattern, if any. files = [f for f in files if os.path.isfile(os.path.join(directory, f)) and extension(f).lower() in FILE_TYPES] if len(files) < 1: print 'Found no media files in "{}".'.format(directory) return files.sort() rename = [] s, e = season, episode - 1 print 'Found {} media files in "{}".'.format(len(files), directory) print "Identifying episodes in season {}...".format(s) for f in files: if e >= len(episodes[s]): if s + 1 in episodes: e = 0 s += 1 print "Moving on to season {}...".format(s) else: print "Unable to rename {}: no episodes remain.".format(f) rename.append((f, None)) continue file_name = create_file_name(series, episodes[s][e], extension(f)) rename.append((f, file_name)) e += 1 choice = menu("Confirm New File Names", *zip(*rename), headers=["Current Name", "New Name"], input_range=["yes", "y", "no", "n"], footer="Would you like " "to proceed with renaming the files? (yes/no)") if choice[0] == "n": return for r in rename: if r[1]: print "Renaming {} to {}...".format(*r) os.rename(os.path.join(directory, r[0]), os.path.join(directory, r[1])) else: print "Skipping {}...".format(r[0]) print "Done."
def pair_players(players): active = active_players(players) reported = [active[k].reported for k in active.keys()] pairs = [] # Warn if some players have reported and some haven't. if any(reported) and not all(reported): print "Warning: Reporting is incomplete! Are you sure you want to " \ "re-pair?" response = DEFAULT_STRING while response[0].lower() not in ['y', 'n']: response = raw_input(">> ") if response[0].lower() == 'n': return # Begin a new round, by setting everyone's "reported" status to false. for p in active.keys(): active[p].reported = False active[p].opponent = None # If no one has any points, it's the first round, so pair people by seat. bye_player = None player_list = active.values() player_count = len(active) table = 1 if sum([p.points() for p in player_list]) == 0: if any([p.seat == None for p in player_list]): print "Warning: You must seat players before pairing! (ENTER to " \ "continue.)" raw_input(">> ") return # For each draft table, pair players as far as possible. Then pair any # leftover players together between tables. Then, if anyone is left # that player gets a bye. unpaired = [] draft_tables = [[p for p in player_list if p.table == t] for t in {p.table for p in player_list}] for current_players in draft_tables: current_players.sort(key=lambda p: p.seat) player_count = len(current_players) if player_count % 2 != 0: # The player in the last seat is not paired at this table. unpaired.append(current_players[player_count - 1]) player_count -= 1 # Each player will face an opponent halfway around their table. for i in xrange(player_count / 2): opponent = current_players[(i + (player_count / 2)) % player_count] current_players[i].opponent = opponent opponent.opponent = current_players[i] pairs.append((table, current_players[i].name, opponent.name)) current_players[i].table = table opponent.table = table table += 1 player_count = len(unpaired) # Pair any players that couldn't be paired with their own draft tables. if player_count: if player_count % 2 != 0: # The player in the last seat is not paired at this table. bye_player = unpaired[player_count - 1] player_count -= 1 # Each player will face an opponent halfway around their table. for i in xrange(player_count / 2): opponent = unpaired[(i + (player_count / 2)) % player_count] unpaired[i].opponent = opponent opponent.opponent = unpaired[i] pairs.append((table, unpaired[i].name, opponent.name)) unpaired[i].table = table opponent.table = table table += 1 # First, assign BYE to worst player that hasn't had a BYE. Then, for each # player, generate a list of opponents they could play... Not sure that'd # work, and I don't have time to implement it... So never mind! # Pair based upon points. else: # player_list.sort(key=lambda p: p.points(), reverse=True) player_list.sort(reverse=True) # Each player faces an opponent not previously faced of similar rank. for i in xrange(player_count): for j in xrange(i + 1, player_count): if not player_list[i].opponent and not \ player_list[j].opponent and player_list[i].name not in\ [p.name for p in player_list[j].past_opponents]: player_list[i].opponent = player_list[j] player_list[j].opponent = player_list[i] pair = (table, player_list[i].name, player_list[j].name) pairs.append(pair) player_list[i].table = table player_list[j].table = table table += 1 break else: if not player_list[i].opponent: bye_player = player_list[i] if bye_player: pairs.append((table, bye_player.name, BYE)) bye_player.opponent, BYE.opponent = BYE, bye_player bye_player.table, BYE.table = table, table menu("Pairings", *zip(*pairs), headers=["Table", "Player", "Opponent"], footer="ENTER to continue.")
def report_results(players): active = active_players(players) reported = [active[k].reported for k in active.keys()] while not all(reported): pairs, choices = [], [] for p in active.values(): if p.opponent and not p.reported: if p.opponent is BYE: p.reported = True p.byes += 1 p.opponent = None elif p.name not in [i.name for sub in pairs for i in sub if isinstance(i, Player)]: pairs.append((p.table, p, p.opponent)) choices.append(p.table) if not pairs: print "Warning: You must pair players before reporting! (ENTER " \ "to continue.)" raw_input(">> ") return pairs.sort() # Sort by table number. choices.sort() choice = menu("Report Match Results", *zip(*pairs), headers=["Table", "Player", "Opponent"], footer="Select a table to report (ENTER to cancel).", input_range=choices+[""]) if not choice: return # Convert from table number to list index. choice = choices.index(int(choice)) p = pairs[choice][1] wins = menu("Match Results: {} versus {}".format(p.name, p.opponent.name), ["How many games did {} " "win?".format(p.name)], footer="ENTER to cancel.", input_range=[0, 1, 2, ""]) if not wins: continue losses = menu("Match Results: {} versus {}".format(p.name, p.opponent.name), ["How many games did {} " "win?".format(p.opponent.name)], footer="ENTER to " "cancel.", input_range=[0, 1, 2, ""]) if not losses: continue draws = menu("Match Results: {} versus {}".format(p.name, p.opponent.name), ["How many games did ended in a draw?"], footer="ENTER to cancel.", input_range=[0, 1, 2, ""]) if not draws: continue wins, losses, draws = int(wins), int(losses), int(draws) games = sum([wins, losses, draws]) if games < 1 or games > 3: print "Warning: Matches are best two of three. You have reported" \ " an invalid number of matches. (ENTER to continue.)" raw_input(">> ") continue p.matches += 1 p.opponent.matches += 1 p.games += games p.opponent.games += games p.match_wins += wins > losses p.opponent.match_wins += wins < losses p.match_draws += wins == losses p.opponent.match_draws += wins == losses p.game_wins += wins p.opponent.game_wins += losses p.game_draws += draws p.opponent.game_draws += draws p.reported, p.opponent.reported = True, True p.past_opponents.append(p.opponent) p.opponent.past_opponents.append(p) p.opponent.opponent = None p.opponent = None reported = [active[k].reported for k in active.keys()] print "All players have reported. (ENTER to continue.)" raw_input(">> ")
def edit_pairings(players): active = active_players(players) player_list = active.values() reported = [p.reported for p in player_list] opponents = [p.opponent for p in player_list] if any(reported): print "Warning: You cannot edit pairings after reporting has begun!" \ " (ENTER to continue.)" raw_input(">> ") return if not any(opponents): print "Warning: You must pair players before editing the pairings." \ " (ENTER to continue.)" raw_input(">> ") return while True: player_list.sort(key=lambda p: p.table) pairs = [(player_list[i].table, player_list[i].name, player_list[i].opponent.name) for i in range(0, len(player_list), 2)] player_1 = menu("Pairings", *zip(*pairs), headers=["Table", "Player", "Opponent"], footer="Enter a player's name to change " "that player's opponent. (ENTER to cancel.)", input_range=[p.name for p in player_list] + [""]) if not player_1: return other_players = [p.name for p in player_list if p.name != player_1] print "Pair {} with which player? (ENTER to cancel.)".format(player_1) player_2 = DEFAULT_STRING while player_2: player_2 = raw_input(">> ") if player_2 in other_players: player_1, player_2 = players[player_1], players[player_2] opponent_1, opponent_2 = player_1.opponent, player_2.opponent player_1.opponent = player_2 player_2.opponent = player_1 player_2.table = player_1.table opponent_1.opponent = opponent_2 opponent_2.opponent = opponent_1 opponent_1.table = opponent_2.table text = "{} is now paired with {}. ".format(player_1.name, player_2.name) if opponent_1 is BYE: text += "As a result, {} now has a BYE.".format( opponent_2.name) elif opponent_2 is BYE: text += "As a result, {} now has a BYE.".format( opponent_1.name) else: text += "As a result, {} is now paired with {}.".format( opponent_1, opponent_2) text += " (ENTER to continue.)" print text raw_input(">> ") break
def season_information(series, dvd): # Randomly selects a mirror to connect to. response = urllib2.urlopen(MIRROR_URL.format(key=KEY)) xml = response.read() root = et.fromstring(xml) mirrors = root.findall("Mirror") if len(mirrors) < 1: print "Warning: No mirrors found. Failing over to TheTVDB.com..." mirror = "http://thetvdb.com" else: mirror = grab(mirrors[random.randint(0, len(mirrors) - 1)], "mirrorpath") print "Mirror: {}".format(mirror) # Identify the series by name, and retrieve its ID from TheTVDB.com. print "Search: {}".format(series) series = series.replace(" ", "%20") response = urllib2.urlopen(SERIES_URL.format(mirror=mirror, name=series)) xml = response.read() root = et.fromstring(xml) series = root.findall("Series") if len(series) == 1: series_id = grab(series[0], "seriesid") series_name = grab(series[0], "SeriesName") else: rows = [] for i in xrange(len(series)): name = grab(series[i], "SeriesName") aired = grab(series[i], "FirstAired") if aired is not None: aired = "{:%Y}".format(datetime.datetime.strptime(aired, "%Y-%m-%d")) rows.append((i + 1, name, aired)) choice = menu("Matches", *zip(*rows), headers=["#", "Series Name", "First Aired"], input_range=range(1, len(series) + 1), footer="To select a series, enter its number.") series_id = grab(series[int(choice) - 1], "seriesid") series_name = grab(series[int(choice) - 1], "SeriesName") print "Series Name: {}".format(series_name) print "Series ID: {}".format(series_id) # Retrieve the episode list for the series. response = urllib2.urlopen(EPISODE_URL.format(mirror=mirror, key=KEY, series_id=series_id)) xml = response.read() root = et.fromstring(xml) episodes = [{"season": grab(e, SEASON, int), "episode": grab(e, EPISODE, int), "dvd_season": grab(e, DVD_S, int), "dvd_episode": grab(e, DVD_E, int), "name": grab(e, EPISODE_NAME), "date": grab(e, AIR_DATE, DATE_CONVERSION), "description": grab(e, DESCRIPTION)} for e in root.findall("Episode")] if dvd: dvd_episodes = [{"season": e["dvd_season"], "episode": e["dvd_episode"], "name": e["name"], "date": e["date"], "description": e["description"]} for e in episodes if e["dvd_season"] is not None and e["dvd_episode"] is not None] # If no DVD information is defined, just use the aired information. if dvd_episodes: episodes = dvd_episodes # Show table of seasons, with the number of episodes in them. episodes.sort(key=lambda e: e["episode"]) episodes.sort(key=lambda e: e["season"]) season_list = list({e["season"] for e in episodes}) season_list.sort() # Turn episodes into a dictionary, organizing the episodes into seasons. # The reason I chose a dict of lists, rather than a list of lists, is # because some shows have a season 0 (which usually means specials, etc.), # while others start at season 1. A dict allows us to index directly to # season 1 in either case. episodes = {s: [e for e in episodes if e["season"] == s] for s in season_list} # Optionally display episode information for each season. done = False while not done: s = menu("Season Information", season_list, [len(episodes[s]) for s in season_list], headers=["Season", "Episodes"], footer="Enter a season number for more information. (ENTER to" " continue.)", input_range=season_list+[""]) if s: s = int(s) rows = [(e["episode"], e["name"], e["date"], short_description(e["description"])) for e in episodes[s]] #print rows menu("Season {}".format(s), *zip(*rows), headers=["Episode", "Name", "Air Date", "Description"], footer="ENTER to continue.") else: done = True return episodes