示例#1
0
def load_notes(person_id: int = None) -> List[Container]:
    where = f'subject_id = {person_id}' if person_id else 'TRUE'
    sql = """
        SELECT
            pn.created_date,
            pn.creator_id,
            {creator_query} AS creator,
            pn.subject_id,
            {subject_query} AS subject,
            note
        FROM
            person_note AS pn
        INNER JOIN
            person AS c ON pn.creator_id = c.id
        INNER JOIN
            person AS s ON pn.subject_id = s.id
        WHERE
            {where}
        ORDER BY
            s.id,
            pn.created_date DESC
    """.format(creator_query=query.person_query('c'),
               subject_query=query.person_query('s'),
               where=where)
    notes = [Container(r) for r in db().select(sql)]
    for n in notes:
        n.created_date = dtutil.ts2dt(n.created_date)
        n.display_date = dtutil.display_date(n.created_date)
    return notes
示例#2
0
def matches_api() -> Response:
    """
    Grab a slice of results from a 0-indexed resultset of matches.
    Input:
        {
            'competitionId': <int?>,
            'page': <int>,
            'pageSize': <int>,
            'q': <str>,
            'sortBy': <str>,
            'sortOrder': <'ASC'|'DESC'>,
            'seasonId': <int|'all'?>
        }
    Output:
        {
            'page': <int>,
            'objects': [<entry>],
            'total': <int>
        }
    """
    order_by = query.matches_order_by(request.args.get('sortBy'),
                                      request.args.get('sortOrder'))
    page_size = int(request.args.get('pageSize', DEFAULT_LIVE_TABLE_PAGE_SIZE))
    page = int(request.args.get('page', 0))
    start = page * page_size
    limit = f'LIMIT {start}, {page_size}'
    q = request.args.get('q', '').strip()
    person_where = query.text_match_where(query.person_query(),
                                          q) if q else 'TRUE'
    opponent_where = query.text_match_where(query.person_query('o'),
                                            q) if q else 'TRUE'
    where = f'({person_where} OR {opponent_where})'
    try:
        competition_id = int(request.args.get('competitionId', ''))
        where += f' AND (c.id = {competition_id})'
        season_id = None
    except ValueError:
        season_id = seasons.season_id(str(request.args.get('seasonId')), None)
    entries = match.load_matches(where=where,
                                 order_by=order_by,
                                 limit=limit,
                                 season_id=season_id,
                                 show_active_deck_names=session.get(
                                     'admin', False))
    prepare_matches(entries)
    total = match.load_matches_count(where=where, season_id=season_id)
    r = {'page': page, 'total': total, 'objects': entries}
    resp = return_json(r, camelize=True)
    resp.set_cookie('page_size', str(page_size))
    return resp
示例#3
0
def load_people(where='1 = 1', order_by='`season_num_decks` DESC, `all_num_decks` DESC, name'):
    sql = """
        SELECT
            p.id,
            {person_query} AS name,
            p.mtgo_username,
            p.tappedout_username,
            p.mtggoldfish_username,
            p.discord_id,
            p.elo,
            {all_select},
            SUM(DISTINCT CASE WHEN d.competition_id IS NOT NULL THEN 1 ELSE 0 END) AS `all_num_competitions`,
            {season_select},
            SUM(DISTINCT CASE WHEN d.created_date >= %s AND d.competition_id IS NOT NULL THEN 1 ELSE 0 END) AS `season_num_competitions`
        FROM
            person AS p
        LEFT JOIN
            deck AS d ON p.id = d.person_id
        {nwdl_join}
        WHERE
            {where}
        GROUP BY
            p.id
        ORDER BY
            {order_by}
    """.format(person_query=query.person_query(), all_select=deck.nwdl_all_select(), season_select=deck.nwdl_season_select(), nwdl_join=deck.nwdl_join(), where=where, order_by=order_by)
    people = [Person(r) for r in db().execute(sql, [int(rotation.last_rotation().timestamp())])]
    if len(people) > 0:
        set_decks(people)
        set_achievements(people)
        set_head_to_head(people)
    return people
示例#4
0
def load_people(where: str = 'TRUE',
                order_by_name: bool = False,
                season_id: Optional[int] = None) -> Sequence[Person]:
    # First we retrieve the people because we want to return a Person for each person that exists even if they have no decks.
    # This is two separate queries for performance reasons. See #5564.
    sql = """
        SELECT
            p.id,
            {person_query} AS name,
            p.mtgo_username,
            p.tappedout_username,
            p.mtggoldfish_username,
            p.discord_id,
            p.elo,
            p.locale
        FROM
            person AS p
        WHERE
            {where}
    """.format(person_query=query.person_query(), where=where)
    people = [Person(r) for r in db().select(sql)]
    stats = load_people_stats(where, season_id)
    for p in people:
        p.update(stats.get(p.id, {}))
        p.season_id = season_id
    if order_by_name:
        people.sort(key=lambda p: p.get('name') or 'ZZZZZZZZZZ')
    else:
        people.sort(key=lambda p:
                    (-p.get('num_decks', 0), 1))  # (, p.get('name')))
    return people
示例#5
0
def load_people(where='1 = 1'):
    sql = """
        SELECT p.id, {person_query} AS name,

        COUNT(d.id) AS `all.num_decks`,
        SUM(d.wins) AS `all.wins`,
        SUM(d.losses) AS `all.losses`,
        SUM(d.draws) AS `all.draws`,
        IFNULL(ROUND((SUM(d.wins) / SUM(d.wins + d.losses)) * 100, 1), '') AS `all.win_percent`,
        SUM(CASE WHEN d.competition_id IS NOT NULL THEN 1 ELSE 0 END) AS `all.num_competitions`,

        SUM(CASE WHEN d.created_date >= %s THEN 1 ELSE 0 END) AS `season.num_decks`,
        SUM(CASE WHEN d.created_date >= %s THEN wins ELSE 0 END) AS `season.wins`,
        SUM(CASE WHEN d.created_date >= %s THEN losses ELSE 0 END) AS `season.losses`,
        SUM(CASE WHEN d.created_date >= %s THEN draws ELSE 0 END) AS `season.draws`,
        IFNULL(ROUND((SUM(CASE WHEN d.created_date >= %s THEN wins ELSE 0 END) / SUM(CASE WHEN d.created_date >= %s THEN wins ELSE 0 END + CASE WHEN d.created_date >= %s THEN losses ELSE 0 END)) * 100, 1), '') AS `season.win_percent`,
        SUM(CASE WHEN d.created_date >= %s AND d.competition_id IS NOT NULL THEN 1 ELSE 0 END) AS `season.num_competitions`

        FROM person AS p
        LEFT JOIN deck AS d ON p.id = d.person_id
        WHERE {where}
        GROUP BY p.id
        ORDER BY `season.num_decks` DESC, `all.num_decks` DESC, name
    """.format(person_query=query.person_query(), where=where)
    people = [Person(r) for r in db().execute(sql, [rotation.last_rotation().timestamp()] * 8)]
    if len(people) > 0:
        set_decks(people)
    return people
示例#6
0
def get_matches(d, should_load_decks=False):
    sql = """
        SELECT
            m.`date`, m.id, m.round, m.elimination,
            dm1.games AS game_wins,
            dm2.deck_id AS opponent_deck_id, IFNULL(dm2.games, 0) AS game_losses,
            d2.name AS opponent_deck_name,
            {person_query} AS opponent
        FROM `match` AS m
        INNER JOIN deck_match AS dm1 ON m.id = dm1.match_id AND dm1.deck_id = %s
        LEFT JOIN deck_match AS dm2 ON m.id = dm2.match_id AND dm2.deck_id <> %s
        INNER JOIN deck AS d1 ON dm1.deck_id = d1.id
        LEFT JOIN deck AS d2 ON dm2.deck_id = d2.id
        LEFT JOIN person AS p ON p.id = d2.person_id
        ORDER BY round
    """.format(person_query=query.person_query())
    matches = [Container(m) for m in db().execute(sql, [d.id, d.id])]
    if should_load_decks and len(matches) > 0:
        decks = load_decks('d.id IN ({ids})'.format(ids=', '.join([
            sqlescape(str(m.opponent_deck_id)) for m in matches
            if m.opponent_deck_id is not None
        ])))
        decks_by_id = {d.id: d for d in decks}
    for m in matches:
        m.date = dtutil.ts2dt(m.date)
        if should_load_decks and m.opponent_deck_id is not None:
            m.opponent_deck = decks_by_id[m.opponent_deck_id]
        elif should_load_decks:
            m.opponent_deck = None
    return matches
示例#7
0
def leaderboards(where: str = "ct.name = 'Gatherling'",
                 season_id: Optional[int] = None) -> List[Dict[str, Any]]:
    sql = """
        SELECT
            p.id AS person_id,
            {person_query} AS person,
            cs.name AS competition_series_name,
            sp.name AS sponsor_name,
            COUNT(DISTINCT d.id) AS tournaments,
            SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS wins,
            COUNT(DISTINCT d.id) + SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS points
        FROM
            competition AS c
        INNER JOIN
            competition_series AS cs ON cs.id = c.competition_series_id
        LEFT JOIN
            sponsor AS sp ON sp.id = cs.sponsor_id
        INNER JOIN
            competition_type AS ct ON ct.id = cs.competition_type_id
        INNER JOIN
            deck AS d ON d.competition_id = c.id
        INNER JOIN
            person AS p ON d.person_id = p.id
        LEFT JOIN
            deck_match AS dm ON dm.deck_id = d.id
        LEFT JOIN
            deck_match AS odm ON odm.match_id = dm.match_id AND odm.deck_id <> d.id
        {season_join}
        WHERE
            ({where}) AND ({season_query})
        GROUP BY
            cs.id,
            p.id
        ORDER BY
            cs.id,
            points DESC,
            wins DESC,
            tournaments DESC,
            person
    """.format(person_query=query.person_query(),
               season_join=query.season_join(),
               where=where,
               season_query=query.season_query(season_id))
    results = []
    current: Dict[str, Any] = {}
    for row in db().select(sql):
        k = row['competition_series_name']
        if current.get('competition_series_name', None) != k:
            if len(current) > 0:
                results.append(current)
            current = {
                'competition_series_name': row['competition_series_name'],
                'entries': [],
                'sponsor_name': row['sponsor_name']
            }
        row.pop('competition_series_name')
        current['entries'] = current['entries'] + [Container(row)]
    if len(current) > 0:
        results.append(current)
    return results
    def leaderboard(
            self,
            season_id: Optional[int] = None) -> Optional[List[Container]]:
        season_condition = query.season_query(season_id)
        person_query = query.person_query()
        sql = f"""
            SELECT
                {person_query} AS person,
                SUM({self.key}) AS points,
                p.id AS person_id
            FROM
                person AS p
            JOIN
                _achievements
            ON
                p.id = _achievements.person_id
            WHERE
                {season_condition}
            GROUP BY
                p.id
            HAVING
                points >=
                    (   -- Work out the minimum score to make top N, counting ties
                        SELECT
                            MIN(s)
                        FROM
                            (
                                SELECT
                                    SUM({self.key}) AS s
                                FROM
                                    _achievements
                                WHERE
                                    {season_condition}
                                GROUP BY
                                    person_id
                                HAVING
                                    s > 0
                                ORDER BY
                                    s DESC
                                LIMIT
                                    {LEADERBOARD_TOP_N}
                            ) AS _
                    )
            ORDER BY
                points DESC,
                name
            LIMIT {LEADERBOARD_LIMIT}
        """
        leaderboard = []
        for row in db().select(sql):
            c = Container(row)
            c.score = c.points
            leaderboard.append(c)

        return leaderboard if len(leaderboard) > 0 else None
示例#9
0
def leaderboards_api() -> Response:
    """
    Grab a slice of results from a 0-indexed resultset of leaderboard entries.
    Input:
        {
            'competitionId': <int?>,
            'competitionSeriesId': <int?>
            'page': <int>,
            'pageSize': <int>,
            'sortBy': <str>,
            'sortOrder': <'ASC'|'DESC'>,
            'seasonId': <int|'all'?>,
            'q': <str>
        }
    Output:
        {
            'page': <int>,
            'objects': [<entry>],
            'total': <int>
        }
    """
    order_by = query.leaderboard_order_by(request.args.get('sortBy'),
                                          request.args.get('sortOrder'))
    page_size = int(request.args.get('pageSize', DEFAULT_LIVE_TABLE_PAGE_SIZE))
    page = int(request.args.get('page', 0))
    start = page * page_size
    limit = f'LIMIT {start}, {page_size}'

    q = request.args.get('q', '').strip()
    where = query.text_match_where(query.person_query(), q) if q else 'TRUE'
    try:
        competition_id = int(request.args.get('competitionId', ''))
        where += f' AND (c.id = {competition_id})'
        season_id = None
    except ValueError:
        season_id = seasons.season_id(str(request.args.get('seasonId')), None)
    try:
        competition_series_id = int(request.args.get('competitionSeriesId',
                                                     ''))
        where += f' AND (cs.id = {competition_series_id})'
    except ValueError:
        pass
    entries = comp.load_leaderboard(where=where,
                                    group_by='p.id',
                                    order_by=order_by,
                                    limit=limit,
                                    season_id=season_id)
    prepare_leaderboard(entries)
    total = comp.load_leaderboard_count(where=where, season_id=season_id)
    r = {'page': page, 'total': total, 'objects': entries}
    resp = return_json(r, camelize=True)
    resp.set_cookie('page_size', str(page_size))
    return resp
示例#10
0
def load_notes():
    sql = """
        SELECT
            pn.created_date,
            pn.creator_id,
            {creator_query} AS creator,
            pn.subject_id,
            {subject_query} AS subject,
            note
        FROM
            person_note AS pn
        INNER JOIN
            person AS c ON pn.creator_id = c.id
        INNER JOIN
            person AS s ON pn.subject_id = s.id
        ORDER BY
            s.id,
            pn.created_date DESC
    """.format(creator_query=query.person_query('c'), subject_query=query.person_query('s'))
    notes = [Container(r) for r in db().execute(sql)]
    for n in notes:
        n.created_date = dtutil.ts2dt(n.created_date)
    return notes
示例#11
0
def load_people(
        where: str = 'TRUE',
        order_by: str = 'num_decks DESC, p.name',
        limit: str = '',
        season_id: Optional[Union[str, int]] = None) -> Sequence[Person]:
    person_query = query.person_query()
    season_join = query.season_join() if season_id else ''
    season_query = query.season_query(season_id, 'season.id')
    sql = f"""
        SELECT
            p.id,
            {person_query} AS name,
            p.mtgo_username,
            p.tappedout_username,
            p.mtggoldfish_username,
            p.discord_id,
            p.elo,
            p.locale,
            SUM(1) AS num_decks,
            SUM(dc.wins) AS wins,
            SUM(dc.losses) AS losses,
            SUM(dc.draws) AS draws,
            SUM(wins - losses) AS record,
            SUM(CASE WHEN dc.wins >= 5 AND dc.losses = 0 AND d.source_id IN (SELECT id FROM source WHERE name = 'League') THEN 1 ELSE 0 END) AS perfect_runs,
            SUM(CASE WHEN d.finish = 1 THEN 1 ELSE 0 END) AS tournament_wins,
            SUM(CASE WHEN d.finish <= 8 THEN 1 ELSE 0 END) AS tournament_top8s,
            IFNULL(ROUND((SUM(dc.wins) / NULLIF(SUM(dc.wins + dc.losses), 0)) * 100, 1), '') AS win_percent,
            SUM(DISTINCT CASE WHEN d.competition_id IS NOT NULL THEN 1 ELSE 0 END) AS num_competitions
        FROM
            person AS p
        LEFT JOIN
            deck AS d ON d.person_id = p.id
        LEFT JOIN
            deck_cache AS dc ON d.id = dc.deck_id
        {season_join}
        WHERE
            ({where}) AND ({season_query})
        GROUP BY
            p.id
        ORDER BY
            {order_by}
        {limit}
    """
    people = [Person(r) for r in db().select(sql)]
    for p in people:
        p.season_id = season_id
    return people
示例#12
0
def load_people(where: str = '1 = 1',
                order_by: str = '`all_num_decks` DESC, name',
                season_id: Optional[int] = None) -> Sequence[Person]:
    sql = """
        SELECT
            p.id,
            {person_query} AS name,
            p.mtgo_username,
            p.tappedout_username,
            p.mtggoldfish_username,
            p.discord_id,
            p.elo,
            {all_select},
            SUM(DISTINCT CASE WHEN d.competition_id IS NOT NULL AND {season_query} THEN 1 ELSE 0 END) AS `all_num_competitions`
        FROM
            person AS p
        LEFT JOIN
            deck AS d ON p.id = d.person_id
        {season_join}
        {nwdl_join}
        WHERE
            ({where})
        GROUP BY
            p.id
        ORDER BY
            {order_by}
    """.format(person_query=query.person_query(),
               all_select=deck.nwdl_select('all_',
                                           query.season_query(season_id)),
               nwdl_join=deck.nwdl_join(),
               season_join=query.season_join(),
               where=where,
               season_query=query.season_query(season_id),
               order_by=order_by)

    people = [Person(r) for r in db().select(sql)]
    for p in people:
        p.season_id = season_id

    if len(people) > 0:
        set_achievements(people, season_id)
        set_head_to_head(people, season_id)
    return people
示例#13
0
def load_person_statless(where: str = 'TRUE',
                         season_id: Optional[int] = None) -> Person:
    person_query = query.person_query()
    sql = f"""
        SELECT
            p.id,
            {person_query} AS name,
            p.mtgo_username,
            p.tappedout_username,
            p.mtggoldfish_username,
            p.discord_id,
            p.elo,
            p.locale
        FROM
            person AS p
        WHERE
            {where}
        """
    people = [Person(r) for r in db().select(sql)]
    for p in people:
        p.season_id = season_id
    return guarantee.exactly_one(people)
示例#14
0
def people_api() -> Response:
    """
    Grab a slice of results from a 0-indexed resultset of people.
    Input:
        {
            'page': <int>,
            'pageSize': <int>,
            'sortBy': <str>,
            'sortOrder': <'ASC'|'DESC'>,
            'seasonId': <int|'all'>,
            'q': <str>
        }
    Output:
        {
            'page': <int>,
            'objects': [<person>],
            'total': <int>
        }
    """
    order_by = query.people_order_by(request.args.get('sortBy'),
                                     request.args.get('sortOrder'))
    page_size = int(request.args.get('pageSize', DEFAULT_LIVE_TABLE_PAGE_SIZE))
    page = int(request.args.get('page', 0))
    start = page * page_size
    limit = f'LIMIT {start}, {page_size}'
    season_id = seasons.season_id(str(request.args.get('seasonId')), None)
    q = request.args.get('q', '').strip()
    where = query.text_match_where(query.person_query(), q) if q else 'TRUE'
    people = ps.load_people(where=where,
                            order_by=order_by,
                            limit=limit,
                            season_id=season_id)
    prepare_people(people)
    total = ps.load_people_count(where=where, season_id=season_id)
    r = {'page': page, 'total': total, 'objects': people}
    resp = return_json(r, camelize=True)
    resp.set_cookie('page_size', str(page_size))
    return resp
示例#15
0
def load_decks(where: str = '1 = 1',
               having: str = '1 = 1',
               order_by: Optional[str] = None,
               limit: str = '',
               season_id: Optional[int] = None
              ) -> List[Deck]:
    if not redis.enabled():
        return load_decks_heavy(where, having, order_by, limit, season_id)
    if order_by is None:
        order_by = 'active_date DESC, d.finish IS NULL, d.finish'
    sql = """
        SELECT
            d.id,
            d.finish,
            d.decklist_hash,
            cache.active_date,
            cache.wins,
            cache.losses,
            cache.draws,
            ct.name AS competition_type_name
        FROM
            deck AS d
        """
    if 'p.' in where or 'p.' in order_by:
        sql += """
        LEFT JOIN
            person AS p ON d.person_id = p.id
        """
    if 's.' in where or 's.' in order_by:
        sql += """
        LEFT JOIN
            source AS s ON d.source_id = s.id
        """
    if 'a.' in where or 'a.' in order_by:
        sql += """
        LEFT JOIN
            archetype AS a ON d.archetype_id = a.id
        """
    sql += """
        {competition_join}
        LEFT JOIN
            deck_cache AS cache ON d.id = cache.deck_id
        {season_join}
        WHERE
            ({where}) AND ({season_query})
        GROUP BY
            d.id,
            d.competition_id, -- Every deck has only one competition_id but if we want to use competition_id in the HAVING clause we need this.
            season.id -- In theory this is not necessary as all decks are in a single season and we join on the date but MySQL cannot work that out so give it the hint it needs.
        HAVING
            {having}
        ORDER BY
            {order_by}
        {limit}
    """
    sql = sql.format(person_query=query.person_query(), competition_join=query.competition_join(), season_query=query.season_query(season_id, 'season.id'), season_join=query.season_join(), where=where, having=having, order_by=order_by, limit=limit)
    db().execute('SET group_concat_max_len=100000')
    rows = db().select(sql)
    decks_by_id = {}
    heavy = []
    for row in rows:
        d = redis.get_container('decksite:deck:{id}'.format(id=row['id']))
        if d is None or d.name is None:
            heavy.append(row['id'])
        else:
            decks_by_id[row['id']] = deserialize_deck(d)
    if heavy:
        where = 'd.id IN ({deck_ids})'.format(deck_ids=', '.join(map(sqlescape, map(str, heavy))))
        loaded_decks = load_decks_heavy(where)
        for d in loaded_decks:
            decks_by_id[d.id] = d
    decks = []
    for row in rows:
        decks.append(decks_by_id[row['id']])
    return decks
示例#16
0
def load_decks_heavy(where: str = '1 = 1',
                     having: str = '1 = 1',
                     order_by: Optional[str] = None,
                     limit: str = '',
                     season_id: Optional[int] = None
                    ) -> List[Deck]:
    if order_by is None:
        order_by = 'active_date DESC, d.finish IS NULL, d.finish'
    sql = """
        SELECT
            d.id,
            d.name AS original_name,
            d.created_date,
            d.updated_date,
            SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS wins,
            SUM(CASE WHEN dm.games < odm.games THEN 1 ELSE 0 END) AS losses,
            SUM(CASE WHEN dm.games = odm.games THEN 1 ELSE 0 END) AS draws,
            d.finish,
            d.archetype_id,
            d.url AS source_url,
            d.competition_id,
            c.name AS competition_name,
            c.end_date AS competition_end_date,
            c.top_n AS competition_top_n,
            ct.name AS competition_type_name,
            d.identifier,
            {person_query} AS person,
            p.id AS person_id,
            p.banned,
            p.discord_id,
            d.decklist_hash,
            d.retired,
            d.reviewed,
            s.name AS source_name,
            IFNULL(a.name, '') AS archetype_name,
            cache.normalized_name AS name,
            cache.colors,
            cache.colored_symbols,
            cache.legal_formats,
            ROUND(cache.omw * 100, 2) AS omw,
            season.id AS season_id,
            IFNULL(MAX(m.date), d.created_date) AS active_date
        FROM
            deck AS d
        LEFT JOIN
            person AS p ON d.person_id = p.id
        LEFT JOIN
            source AS s ON d.source_id = s.id
        LEFT JOIN
            archetype AS a ON d.archetype_id = a.id
        {competition_join}
        LEFT JOIN
            deck_cache AS cache ON d.id = cache.deck_id
        LEFT JOIN
            deck_match AS dm ON d.id = dm.deck_id
        LEFT JOIN
            `match` AS m ON dm.match_id = m.id
        LEFT JOIN
            deck_match AS odm ON odm.deck_id <> d.id AND dm.match_id = odm.match_id
        {season_join}
        WHERE
            ({where}) AND ({season_query})
        GROUP BY
            d.id,
            d.competition_id, -- Every deck has only one competition_id but if we want to use competition_id in the HAVING clause we need this.
            season.id -- In theory this is not necessary as all decks are in a single season and we join on the date but MySQL cannot work that out so give it the hint it needs.
        HAVING
            {having}
        ORDER BY
            {order_by}
        {limit}
    """.format(person_query=query.person_query(), competition_join=query.competition_join(), season_join=query.season_join(), where=where, season_query=query.season_query(season_id, 'season.id'), having=having, order_by=order_by, limit=limit)
    db().execute('SET group_concat_max_len=100000')
    rows = db().select(sql)
    decks = []
    for row in rows:
        d = Deck(row)
        d.maindeck = []
        d.sideboard = []
        d.competition_top_n = Top(d.competition_top_n or 0)
        d.colored_symbols = json.loads(d.colored_symbols or '[]')
        d.colors = json.loads(d.colors or '[]')
        d.legal_formats = set(json.loads(d.legal_formats or '[]'))
        d.active_date = dtutil.ts2dt(d.active_date)
        d.created_date = dtutil.ts2dt(d.created_date)
        d.updated_date = dtutil.ts2dt(d.updated_date)
        if d.competition_end_date:
            d.competition_end_date = dtutil.ts2dt(d.competition_end_date)
        d.can_draw = 'Divine Intervention' in [card.name for card in d.all_cards()]
        d.wins = int(d.wins)
        d.losses = int(d.losses)
        d.draws = int(d.draws)
        decks.append(d)
    load_cards(decks)
    load_competitive_stats(decks)
    for d in decks:
        expiry = 60 if d.is_in_current_run() else 3600
        redis.store('decksite:deck:{id}'.format(id=d.id), d, ex=expiry)
    return decks
示例#17
0
def load_decks(where='1 = 1', order_by=None, limit=''):
    if order_by is None:
        order_by = 'd.created_date DESC, d.finish IS NULL, d.finish'
    sql = """
        SELECT
            d.id,
            d.name AS original_name,
            d.created_date,
            d.updated_date,
            SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS wins,
            SUM(CASE WHEN dm.games < odm.games THEN 1 ELSE 0 END) AS losses,
            SUM(CASE WHEN dm.games = odm.games THEN 1 ELSE 0 END) AS draws,
            d.finish,
            d.archetype_id,
            d.url AS source_url,
            d.competition_id,
            c.name AS competition_name,
            c.end_date AS competition_end_date,
            ct.name AS competition_type_name,
            d.identifier,
            {person_query} AS person,
            p.id AS person_id,
            p.banned,
            p.discord_id,
            d.created_date AS `date`,
            d.decklist_hash,
            d.retired,
            s.name AS source_name,
            IFNULL(a.name, '') AS archetype_name,
            cache.normalized_name AS name,
            cache.colors,
            cache.colored_symbols,
            cache.legal_formats
        FROM
            deck AS d
        LEFT JOIN
            person AS p ON d.person_id = p.id
        LEFT JOIN
            source AS s ON d.source_id = s.id
        LEFT JOIN
            archetype AS a ON d.archetype_id = a.id
        {competition_join}
        LEFT JOIN
            deck_cache AS cache ON d.id = cache.deck_id
        LEFT JOIN
            deck_match AS dm ON d.id = dm.deck_id
        LEFT JOIN
            deck_match AS odm ON odm.deck_id <> d.id AND dm.match_id = odm.match_id
        WHERE
            {where}
        GROUP BY
            d.id
        ORDER BY
            {order_by}
        {limit}
    """.format(person_query=query.person_query(),
               competition_join=query.competition_join(),
               where=where,
               order_by=order_by,
               limit=limit)
    db().execute('SET group_concat_max_len=100000')
    rows = db().execute(sql)
    decks = []
    for row in rows:
        d = Deck(row)
        d.maindeck = []
        d.sideboard = []
        d.colored_symbols = json.loads(d.colored_symbols or '[]')
        d.colors = json.loads(d.colors or '[]')
        d.legal_formats = set(json.loads(d.legal_formats or '[]'))
        d.created_date = dtutil.ts2dt(d.created_date)
        d.updated_date = dtutil.ts2dt(d.updated_date)
        if d.competition_end_date:
            d.competition_end_date = dtutil.ts2dt(d.competition_end_date)
        d.date = dtutil.ts2dt(d.date)
        d.can_draw = 'Divine Intervention' in [
            card.name for card in d.all_cards()
        ]
        decks.append(d)
    load_cards(decks)
    load_opponent_stats(decks)
    return decks
def leaderboards(where="ct.name = 'Gatherling' AND season.id = (SELECT id FROM season WHERE start_date = (SELECT MAX(start_date) FROM season WHERE start_date < UNIX_TIMESTAMP(NOW())))"):
    sql = """
        SELECT
            p.id AS person_id,
            season.code AS season_code,
            {person_query} AS person,
            cs.name AS competition_series_name,
            COUNT(DISTINCT d.id) AS tournaments,
            SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS wins,
            COUNT(DISTINCT d.id) + SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS points
        FROM
            competition AS c
        INNER JOIN
            competition_series AS cs ON cs.id = c.competition_series_id
        INNER JOIN
            competition_type AS ct ON ct.id = cs.competition_type_id
        INNER JOIN
            deck AS d ON d.competition_id = c.id
        INNER JOIN
            person AS p ON d.person_id = p.id
        LEFT JOIN
            deck_match AS dm ON dm.deck_id = d.id
        LEFT JOIN
            deck_match AS odm ON odm.match_id = dm.match_id AND odm.deck_id <> d.id
        INNER JOIN
            (
                SELECT
                    s.id,
                    s.code,
                    s.start_date AS start_date,
                    s2.start_date AS end_date
                FROM
                    season AS s
                LEFT JOIN
                    season AS s2
                ON
                    s2.start_date = (SELECT MIN(start_date) FROM season WHERE start_date > s.start_date)
            ) AS season ON c.start_date >= season.start_date AND (c.start_date < season.end_date OR season.end_date IS NULL)
        WHERE
            {where}
            GROUP BY
                cs.id,
                p.id,
                season.id
            ORDER BY
                cs.id,
                points DESC,
                wins DESC,
                tournaments DESC,
                person
    """.format(person_query=query.person_query(), where=where)
    results = []
    current = {}
    for row in db().execute(sql):
        k = (row['competition_series_name'], row['season_code'])
        if (current.get('competition_series_name', None), current.get('season_code', None)) != k:
            if len(current) > 0:
                results.append(current)
            current = {
                'competition_series_name': row['competition_series_name'],
                'season_code': row['season_code'],
                'entries': []
            }
        row.pop('competition_series_name')
        row.pop('season_code')
        current['entries'] = current['entries'] + [Container(row)]
    if len(current) > 0:
        results.append(current)
    return results
示例#19
0
def load_decks(where='1 = 1', order_by=None, limit='', season_id=None) -> List[Deck]:
    if order_by is None:
        order_by = 'active_date DESC, d.finish IS NULL, d.finish'
    sql = """
        SELECT
            d.id,
            d.name AS original_name,
            d.created_date,
            d.updated_date,
            SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS wins,
            SUM(CASE WHEN dm.games < odm.games THEN 1 ELSE 0 END) AS losses,
            SUM(CASE WHEN dm.games = odm.games THEN 1 ELSE 0 END) AS draws,
            d.finish,
            d.archetype_id,
            d.url AS source_url,
            d.competition_id,
            c.name AS competition_name,
            c.end_date AS competition_end_date,
            c.top_n AS competition_top_n,
            ct.name AS competition_type_name,
            d.identifier,
            {person_query} AS person,
            p.id AS person_id,
            p.banned,
            p.discord_id,
            d.decklist_hash,
            d.retired,
            s.name AS source_name,
            IFNULL(a.name, '') AS archetype_name,
            cache.normalized_name AS name,
            cache.colors,
            cache.colored_symbols,
            cache.legal_formats,
            season.id AS season_id,
            IFNULL(MAX(m.date), d.created_date) AS active_date
        FROM
            deck AS d
        LEFT JOIN
            person AS p ON d.person_id = p.id
        LEFT JOIN
            source AS s ON d.source_id = s.id
        LEFT JOIN
            archetype AS a ON d.archetype_id = a.id
        {competition_join}
        LEFT JOIN
            deck_cache AS cache ON d.id = cache.deck_id
        LEFT JOIN
            deck_match AS dm ON d.id = dm.deck_id
        LEFT JOIN
            `match` AS m ON dm.match_id = m.id
        LEFT JOIN
            deck_match AS odm ON odm.deck_id <> d.id AND dm.match_id = odm.match_id
        {season_join}
        WHERE ({where}) AND ({season_query})
        GROUP BY
            d.id,
            season.id -- In theory this is not necessary as all decks are in a single season and we join on the date but MySQL cannot work that out so give it the hint it needs.
        ORDER BY
            {order_by}
        {limit}
    """.format(person_query=query.person_query(), competition_join=query.competition_join(), where=where, order_by=order_by, limit=limit, season_query=query.season_query(season_id), season_join=query.season_join())
    db().execute('SET group_concat_max_len=100000')
    rows = db().execute(sql)
    decks = []
    for row in rows:
        d = Deck(row)
        d.maindeck = []
        d.sideboard = []
        d.competition_top_n = Top(d.competition_top_n or 0)
        d.colored_symbols = json.loads(d.colored_symbols or '[]')
        d.colors = json.loads(d.colors or '[]')
        d.legal_formats = set(json.loads(d.legal_formats or '[]'))
        d.active_date = dtutil.ts2dt(d.active_date)
        d.created_date = dtutil.ts2dt(d.created_date)
        d.updated_date = dtutil.ts2dt(d.updated_date)
        if d.competition_end_date:
            d.competition_end_date = dtutil.ts2dt(d.competition_end_date)
        d.can_draw = 'Divine Intervention' in [card.name for card in d.all_cards()]
        decks.append(d)
    load_cards(decks)
    load_competitive_stats(decks)
    return decks
示例#20
0
def load_decks(where='1 = 1', order_by=None, limit=''):
    if order_by is None:
        order_by = 'd.created_date DESC, IFNULL(d.finish, 9999999999)'
    sql = """
        SELECT d.id, d.name, d.created_date, d.updated_date, d.wins, d.losses, d.draws, d.finish, d.archetype_id, d.url AS source_url,
            d.competition_id, c.name AS competition_name, c.end_date AS competition_end_date, ct.name AS competition_type_name, d.identifier,
            {person_query} AS person, p.id AS person_id,
            d.created_date AS `date`, d.decklist_hash, d.retired,
            s.name AS source_name, IFNULL(a.name, '') AS archetype_name,
            SUM(opp.wins) AS opp_wins, SUM(opp.losses) AS opp_losses, ROUND(SUM(opp.wins) / (SUM(opp.wins) + SUM(opp.losses)), 2) * 100 AS omw,
            GROUP_CONCAT(DISTINCT CONCAT(dc.card, '|', dc.n, '|', dc.sideboard) SEPARATOR '█') AS cards,
            cache.colors, cache.colored_symbols, cache.legal_formats,
            IFNULL(MIN(CASE WHEN m.elimination > 0 THEN m.elimination END), 0) AS stage_reached,
            GROUP_CONCAT(m.elimination) AS elim
        FROM deck AS d
        INNER JOIN person AS p ON d.person_id = p.id
        LEFT JOIN competition AS c ON d.competition_id = c.id
        INNER JOIN source AS s ON d.source_id = s.id
        LEFT JOIN archetype AS a ON d.archetype_id = a.id
        LEFT JOIN deck AS opp ON opp.id IN (SELECT deck_id FROM deck_match WHERE deck_id <> d.id AND match_id IN (SELECT match_id FROM deck_match WHERE deck_id = d.id))
        LEFT JOIN competition_type AS ct ON ct.id = c.competition_type_id
        LEFT JOIN deck_card AS dc ON d.id = dc.deck_id
        LEFT JOIN deck_cache AS cache ON d.id = cache.deck_id
        LEFT JOIN deck_match AS dm ON d.id = dm.deck_id
        LEFT JOIN `match` AS m ON m.id = dm.match_id
        WHERE {where}
        GROUP BY d.id
        ORDER BY {order_by}
        {limit}
    """.format(person_query=query.person_query(),
               where=where,
               order_by=order_by,
               limit=limit)
    db().execute('SET group_concat_max_len=100000')
    rows = db().execute(sql)
    cards = oracle.cards_by_name()
    decks = []
    for row in rows:
        d = Deck(row)
        d.maindeck = []
        d.sideboard = []
        cards_s = (row['cards'] or '')
        for entry in filter(None, cards_s.split('█')):
            name, n, is_sideboard = entry.split('|')
            location = 'sideboard' if bool(int(is_sideboard)) else 'maindeck'
            d[location].append({
                'n': int(n),
                'name': name,
                'card': cards[name]
            })
        d.colored_symbols = json.loads(d.colored_symbols or '[]')
        d.colors = json.loads(d.colors or '[]')
        d.legal_formats = set(json.loads(d.legal_formats or '[]'))
        d.created_date = dtutil.ts2dt(d.created_date)
        d.updated_date = dtutil.ts2dt(d.updated_date)
        if d.competition_end_date:
            d.competition_end_date = dtutil.ts2dt(d.competition_end_date)
        d.date = dtutil.ts2dt(d.date)
        d.can_draw = 'Divine Intervention' in [
            card.name for card in d.all_cards()
        ]
        decks.append(d)
    return decks
示例#21
0
def load_people(where: str = '1 = 1',
                order_by: str = '`num_decks` DESC, name',
                season_id: Optional[int] = None) -> Sequence[Person]:
    sql = """
        SELECT
            p.id,
            {person_query} AS name,
            p.mtgo_username,
            p.tappedout_username,
            p.mtggoldfish_username,
            p.discord_id,
            p.elo,
            num_decks,
            wins,
            losses,
            draws,
            perfect_runs,
            tournament_wins,
            tournament_top8s,
            win_percent,
            num_competitions
        FROM
            person AS p
        LEFT JOIN
            (
                SELECT
                    d.person_id,
                    COUNT(d.id) AS num_decks,
                    SUM(wins) AS wins,
                    SUM(losses) AS losses,
                    SUM(draws) AS draws,
                    SUM(CASE WHEN wins >= 5 AND losses = 0 AND d.source_id IN (SELECT id FROM source WHERE name = 'League') THEN 1 ELSE 0 END) AS perfect_runs,
                    SUM(CASE WHEN d.finish = 1 THEN 1 ELSE 0 END) AS tournament_wins,
                    SUM(CASE WHEN d.finish <= 8 THEN 1 ELSE 0 END) AS tournament_top8s,
                    IFNULL(ROUND((SUM(wins) / NULLIF(SUM(wins + losses), 0)) * 100, 1), '') AS win_percent,
                    SUM(DISTINCT CASE WHEN d.competition_id IS NOT NULL THEN 1 ELSE 0 END) AS num_competitions
                FROM
                    deck AS d
                LEFT JOIN
                    deck_cache AS dc ON d.id = dc.deck_id
                {season_join}
                WHERE
                    {season_query}
                GROUP BY
                    d.person_id
            ) AS stats ON p.id = stats.person_id
        WHERE
            {where}
        GROUP BY
            p.id
        ORDER BY
            {order_by}
    """.format(person_query=query.person_query(),
               season_join=query.season_join(),
               where=where,
               season_query=query.season_query(season_id, 'season.id'),
               order_by=order_by)
    people = [Person(r) for r in db().select(sql)]
    for p in people:
        p.season_id = season_id
    return people
示例#22
0
def load_decks_query(
    columns: str,
    where: str = 'TRUE',
    group_by: Optional[str] = None,
    having: str = 'TRUE',
    order_by: Optional[str] = None,
    limit: str = '',
    season_id: Optional[Union[str, int]] = None,
) -> str:
    if order_by is None:
        order_by = 'active_date DESC, d.finish IS NULL, d.finish'
    if group_by is None:
        group_by = ''
    else:
        group_by = f'GROUP BY {group_by}'
    sql = """
        SELECT
            {columns}
        FROM
            deck AS d
        """
    if 'p.' in where or 'p.' in order_by:
        sql += """
        LEFT JOIN
            person AS p ON d.person_id = p.id
        """
    if 's.' in where or 's.' in order_by:
        sql += """
        LEFT JOIN
            source AS s ON d.source_id = s.id
        """
    if 'a.' in where or 'a.' in order_by:
        sql += """
        LEFT JOIN
            archetype AS a ON d.archetype_id = a.id
        """
    sql += """
        {competition_join}
        LEFT JOIN
            deck_cache AS cache ON d.id = cache.deck_id
        {season_join}
        WHERE
            ({where}) AND ({season_query})
        {group_by}
        HAVING
            {having}
        ORDER BY
            {order_by}
        {limit}
    """
    sql = sql.format(columns=columns,
                     person_query=query.person_query(),
                     competition_join=query.competition_join(),
                     season_query=query.season_query(season_id, 'season.id'),
                     season_join=query.season_join(),
                     where=where,
                     group_by=group_by,
                     having=having,
                     order_by=order_by,
                     limit=limit)
    return sql
示例#23
0
def load_matches(where: str = 'TRUE',
                 season_id: Optional[int] = None,
                 should_load_decks: bool = False) -> List[Container]:
    person_query = query.person_query(table='o')
    competition_join = query.competition_join()
    season_join = query.season_join()
    season_query = query.season_query(season_id, 'season.id')
    sql = f"""
        SELECT
            m.`date`,
            m.id,
            m.`round`,
            m.elimination,
            m.mtgo_id,
            d.id AS deck_id,
            dc.normalized_name AS deck_name,
            od.id AS opponent_deck_id,
            odc.normalized_name AS opponent_deck_name,
            dm.games AS game_wins,
            IFNULL(odm.games, 0) AS game_losses,
            c.id AS competition_id,
            ct.name AS competition_type_name,
            c.end_date AS competition_end_date,
            {person_query} AS opponent,
            odc.wins,
            odc.draws,
            odc.losses,
            od.retired
        FROM
            `match` AS m
        INNER JOIN
            deck_match AS dm ON m.id = dm.match_id
        INNER JOIN
            deck AS d ON dm.deck_id = d.id
        INNER JOIN
            deck_cache AS dc ON d.id = dc.deck_id
        LEFT JOIN
            deck_match AS odm ON dm.match_id = odm.match_id AND odm.deck_id <> d.id
        LEFT JOIN
            deck AS od ON odm.deck_id = od.id
        LEFT JOIN
            deck_cache AS odc ON od.id = odc.deck_id
        LEFT JOIN
            person AS o ON od.person_id = o.id
        {competition_join}
        {season_join}
        WHERE
            {where}
        AND
            {season_query}
        ORDER BY
            m.`date`,
            m.`round`
    """
    matches = [Container(r) for r in db().select(sql)]
    if should_load_decks:
        opponents = [
            m.opponent_deck_id for m in matches
            if m.opponent_deck_id is not None
        ]
        if len(opponents) > 0:
            decks = deck.load_decks('d.id IN ({ids})'.format(ids=', '.join(
                [sqlescape(str(deck_id)) for deck_id in opponents])))
        else:
            decks = []
        decks_by_id = {d.id: d for d in decks}
    for m in matches:
        m.date = dtutil.ts2dt(m.date)
        m.competition_end_date = dtutil.ts2dt(m.competition_end_date)
        m.competition_url = url_for('competition',
                                    competition_id=m.competition_id)
        if Deck(m).is_in_current_run():
            m.opponent_deck_name = '(Active League Run)'
        if should_load_decks and m.opponent_deck_id is not None and decks_by_id.get(
                m.opponent_deck_id):
            m.opponent_deck = decks_by_id[m.opponent_deck_id]
        elif should_load_decks:
            m.opponent_deck = None
    return matches
示例#24
0
def load_decks(where: str = '1 = 1',
               order_by: Optional[str] = None,
               limit: str = '',
               season_id: Optional[int] = None) -> List[Deck]:
    if redis.REDIS is None:
        return load_decks_heavy(where, order_by, limit, season_id)
    if order_by is None:
        order_by = 'active_date DESC, d.finish IS NULL, d.finish'
    sql = """
        SELECT
            d.id,
            d.finish,
            IFNULL(MAX(m.date), d.created_date) AS active_date
        FROM
            deck AS d
        LEFT JOIN
            deck_match AS dm ON d.id = dm.deck_id
        LEFT JOIN
            `match` AS m ON dm.match_id = m.id
        LEFT JOIN
            deck_match AS odm ON odm.deck_id <> d.id AND dm.match_id = odm.match_id
        """
    if 'p.' in where or 'p.' in order_by:
        sql += """
        LEFT JOIN
            person AS p ON d.person_id = p.id
        """
    if 's.' in where or 's.' in order_by:
        sql += """
        LEFT JOIN
            source AS s ON d.source_id = s.id
        """
    if 'a.' in where or 'a.' in order_by:
        sql += """
        LEFT JOIN
            archetype AS a ON d.archetype_id = a.id
        """
    sql += """
        {competition_join}
        """
    if 'cache.' in where or 'cache.' in order_by:
        sql += """
        LEFT JOIN
            deck_cache AS cache ON d.id = cache.deck_id
        """
    sql += """
        {season_join}
        WHERE ({where}) AND ({season_query})
        GROUP BY
            d.id,
            season.id -- In theory this is not necessary as all decks are in a single season and we join on the date but MySQL cannot work that out so give it the hint it needs.
        ORDER BY
            {order_by}
        {limit}
    """
    sql = sql.format(person_query=query.person_query(),
                     competition_join=query.competition_join(),
                     where=where,
                     order_by=order_by,
                     limit=limit,
                     season_query=query.season_query(season_id),
                     season_join=query.season_join())
    db().execute('SET group_concat_max_len=100000')
    rows = db().execute(sql)
    decks = []
    heavy = []
    for row in rows:
        d = redis.get_container('decksite:deck:{id}'.format(id=row['id']))
        if d is None or d.name is None:
            heavy.append(row['id'])
            # decks.append(guarantee.exactly_one(load_decks_heavy('d.id = {id}'.format(id=row['id']))))
        else:
            decks.append(deserialize_deck(d))
    if heavy:
        # This currently messes up the order.
        where = 'd.id IN ({deck_ids})'.format(
            deck_ids=', '.join(map(sqlescape, map(str, heavy))))
        decks.extend(load_decks_heavy(where))
    return decks
示例#25
0
def load_matches(where: str = 'TRUE',
                 order_by: str = 'm.`date`, m.`round`',
                 limit: str = '',
                 season_id: Union[int, str, None] = None,
                 should_load_decks: bool = False,
                 show_active_deck_names: bool = False) -> List[Container]:
    person_query = query.person_query()
    opponent_person_query = query.person_query(table='o')
    competition_join = query.competition_join()
    season_join = query.season_join()
    season_query = query.season_query(season_id, 'season.id')
    sql = f"""
        SELECT
            m.`date`,
            m.id,
            m.`round`,
            m.elimination,
            m.mtgo_id,
            d.id AS deck_id,
            {person_query} AS person,
            dc.normalized_name AS deck_name,
            od.id AS opponent_deck_id,
            odc.normalized_name AS opponent_deck_name,
            dm.games AS game_wins,
            IFNULL(odm.games, 0) AS game_losses,
            c.id AS competition_id,
            ct.name AS competition_type_name,
            c.end_date AS competition_end_date,
            {opponent_person_query} AS opponent,
            odc.wins,
            odc.draws,
            odc.losses,
            od.retired
        FROM
            `match` AS m
        INNER JOIN
            deck_match AS dm ON m.id = dm.match_id
        INNER JOIN
            deck AS d ON dm.deck_id = d.id
        INNER JOIN
            deck_cache AS dc ON d.id = dc.deck_id
        INNER JOIN
            person AS p ON d.person_id = p.id
        LEFT JOIN
            deck_match AS odm ON dm.match_id = odm.match_id AND odm.deck_id <> d.id
        LEFT JOIN
            deck AS od ON odm.deck_id = od.id
        LEFT JOIN
            deck_cache AS odc ON od.id = odc.deck_id
        LEFT JOIN
            person AS o ON od.person_id = o.id
        {competition_join}
        {season_join}
        WHERE
            {where}
        AND
            {season_query}
        GROUP BY
            m.id -- We don't want an row for each deck in a match (when the WHERE doesn't include a person)
        ORDER BY
            {order_by}
        {limit}
    """
    matches = [Container(r) for r in db().select(sql)]
    if should_load_decks:
        opponents = [
            m.opponent_deck_id for m in matches
            if m.opponent_deck_id is not None
        ]
        if len(opponents) > 0:
            decks = deck.load_decks('d.id IN ({ids})'.format(ids=', '.join(
                [sqlescape(str(deck_id)) for deck_id in opponents])))
        else:
            decks = []
        decks_by_id = {d.id: d for d in decks}
    for m in matches:
        m.date = dtutil.ts2dt(m.date)
        m.competition_end_date = dtutil.ts2dt(m.competition_end_date)
        if g:  # https://github.com/PennyDreadfulMTG/Penny-Dreadful-Tools/issues/8435
            m.competition_url = url_for('competition',
                                        competition_id=m.competition_id)
        if Deck(m).is_in_current_run() and not show_active_deck_names:
            m.opponent_deck_name = '(Active League Run)'
        if should_load_decks and m.opponent_deck_id is not None and decks_by_id.get(
                m.opponent_deck_id):
            m.opponent_deck = decks_by_id[m.opponent_deck_id]
        elif should_load_decks:
            m.opponent_deck = None
    return matches
示例#26
0
def load_matches(where: str = 'TRUE',
                 order_by: str = 'm.`date`, m.`round`',
                 limit: str = '',
                 season_id: Union[int, str, None] = None,
                 should_load_decks: bool = False,
                 show_active_deck_names: bool = False) -> List[Container]:
    person_query = query.person_query()
    opponent_person_query = query.person_query(table='o')
    competition_join = query.competition_join()
    season_join = query.season_join()
    season_query = query.season_query(season_id, 'season.id')
    sql = f"""
        SELECT
            m.`date`,
            m.id,
            m.`round`,
            m.elimination,
            m.mtgo_id,
            d.id AS deck_id,
            {person_query} AS person,
            dc.normalized_name AS deck_name,
            od.id AS opponent_deck_id,
            odc.normalized_name AS opponent_deck_name,
            dm.games AS game_wins,
            IFNULL(odm.games, 0) AS game_losses,
            c.id AS competition_id,
            ct.name AS competition_type_name,
            c.end_date AS competition_end_date,
            {opponent_person_query} AS opponent,
            odc.wins,
            odc.draws,
            odc.losses,
            od.retired
        FROM
            `match` AS m
        INNER JOIN
            deck_match AS dm ON m.id = dm.match_id
        INNER JOIN
            deck AS d ON dm.deck_id = d.id
        INNER JOIN
            deck_cache AS dc ON d.id = dc.deck_id
        INNER JOIN
            person AS p ON d.person_id = p.id
        LEFT JOIN
            deck_match AS odm ON dm.match_id = odm.match_id AND odm.deck_id <> d.id
        LEFT JOIN
            deck AS od ON odm.deck_id = od.id
        LEFT JOIN
            deck_cache AS odc ON od.id = odc.deck_id
        LEFT JOIN
            person AS o ON od.person_id = o.id
        {competition_join}
        {season_join}
        WHERE
            {where}
        AND
            {season_query}
        GROUP BY
            m.id -- We don't want an row for each deck in a match (when the WHERE doesn't include a person)
        ORDER BY
            {order_by}
        {limit}
    """
    matches = [Container(r) for r in db().select(sql)]
    decks = []
    if should_load_decks:
        opponents = [
            m.opponent_deck_id for m in matches
            if m.opponent_deck_id is not None
        ]
        if len(opponents) > 0:
            decks = deck.load_decks('d.id IN ({ids})'.format(ids=', '.join(
                [sqlescape(str(deck_id)) for deck_id in opponents])))
    decks_by_id = {d.id: d for d in decks}
    setup_matches(should_load_decks, show_active_deck_names, decks_by_id,
                  matches)
    return matches