def countPlayers():
    """Returns the number of players currently registered."""

    qry = """SELECT COUNT(*) FROM Players"""
    with Cursor(tournament_database) as cursor:
        cursor.execute(qry)
        results = cursor.fetchone()
    return results[0]
def playerStandings():
    """Returns a list of the players and their win records, sorted by wins.

    The first entry in the list should be the player in first place, or a player
    tied for first place if there is currently a tie.

    Returns:
      A list of tuples, each of which contains (id, name, wins, matches):
        id: the player's unique id (assigned by the database)
        name: the player's full name (as registered)
        wins: the number of matches the player has won
        matches: the number of matches the player has played
    """

    qry = """WITH w AS (
    SELECT winner AS id, COUNT(winner) AS wins FROM matches GROUP BY winner),
    l AS (
    SELECT loser AS id, COUNT(loser) AS losses FROM matches GROUP BY loser)
    SELECT p.id, p.firstname, p.lastname, wins, losses FROM w FULL OUTER JOIN l ON (w.id = l.id)
    RIGHT OUTER JOIN Players p ON (w.id = p.id OR l.id = p.id);"""

    with Cursor(tournament_database) as cursor:
        cursor.execute(qry)
        standings = sorted([(pid, " ".join([fn, ln]), (w or 0),
                             (w or 0) + (l or 0))
                            for pid, fn, ln, w, l in cursor.fetchall()],
                           key=lambda x: x[2],
                           reverse=True)

    n = len(standings)
    i = 0
    while i < n - 1:
        # Search the standings for ties
        # Break any ties found by sending all tied players
        # in a list to be sorted by the OWM scores
        # i the is index of the first player with score = x, and
        # j is the index of the first player (sequencially from i) with score != x.
        # This leaves us a slice of players [i:j], where each player as the same score.
        j = i
        while j < n - 1 and standings[i][2] == standings[j][2]:
            j += 1
        tied_players = standings[i:j]

        if len(tied_players) > 1:
            # There are 2 or more tied players.
            # Sort the sublist containing them by their OWM scores
            OWM_sorted_players = sortByOWM(tied_players)
            standings[i:j] = OWM_sorted_players
        i = j

    return standings
def reportMatch(winner, loser):
    """Records the outcome of a single match between two players.

    Args:
      winner:  the id number of the player who won
      loser:  the id number of the player who lost
    """

    # qry = """INSERT INTO Matches (id, winner, loser)
    # VALUES (DEFAULT, (%s), (%s))"""
    qry = "INSERT INTO MATCHES VALUES (DEFAULT, %s, %s)"

    with Cursor(tournament_database) as cursor:
        cursor.execute(qry, [winner, loser])
def registerPlayer(name):
    """Adds a player to the tournament database.

    The database assigns a unique serial id number for the player.  (This
    should be handled by your SQL database schema, not in your Python code.)

    Args:
      name: the player's full name (need not be unique).
    """

    qry = """INSERT INTO Players (firstname, lastname)
    VALUES ((%s), (%s));"""
    full_name = name.split(" ")

    # Get the first and last name of the player. If name cannot be split
    # into 2, set the last name as the empty string
    fname, lname = full_name if len(full_name) == 2 else [name, ""]

    # Names may have a single-quote in them, escape it:
    with Cursor(tournament_database) as cursor:
        cursor.execute(qry, [fname, lname])
def opponentMatchWins(p):
    '''Returns player p's oppenents match wins count'''

    match_qry = """SELECT winner, loser
    FROM Matches
    WHERE winner = (%s)
    OR
    loser = (%s)"""

    # wins_qry = """SELECT wins FROM Players WHERE id = (%s)"""
    wins_qry = """SELECT COUNT(*) FROM Matches WHERE winner = (%s)"""
    OWM = 0

    with Cursor(tournament_database) as cursor:
        cursor.execute(match_qry, [p, p])
        p_opps = [opp for tpl in cursor.fetchall() for opp in tpl if opp != p]

        for opp in p_opps:
            qry = wins_qry
            cursor.execute(qry, [opp])
            OWM += cursor.fetchone()[0]

    return OWM
def deletePlayers():
    """Remove all the player records from the database."""

    qry = """TRUNCATE Players RESTART IDENTITY CASCADE"""
    with Cursor(tournament_database) as cursor:
        cursor.execute(qry)
def deleteMatches():
    """Remove all the match records from the database."""

    qry_del = """TRUNCATE Matches RESTART IDENTITY CASCADE"""
    with Cursor(tournament_database) as cursor:
        cursor.execute(qry_del)