Beispiel #1
0
def load_card(name):
    c = guarantee.exactly_one(oracle.load_cards([name]))
    c.decks = deck.load_decks(
        'd.id IN (SELECT deck_id FROM deck_card WHERE card = {name})'.format(
            name=sqlescape(name)))
    c.season = Container()
    c.all = Container()
    c.all.wins = sum(filter(None, [d.wins for d in c.decks]))
    c.all.losses = sum(filter(None, [d.losses for d in c.decks]))
    c.all.draws = sum(filter(None, [d.draws for d in c.decks]))
    if c.all.wins or c.all.losses or c.all.draws:
        c.all.win_percent = round(
            (c.all.wins / (c.all.wins + c.all.losses)) * 100, 1)
    else:
        c.all.win_percent = ''
    c.all.num_decks = len(c.decks)
    season_decks = [
        d for d in c.decks if d.created_date > rotation.last_rotation()
    ]
    c.season.wins = sum(filter(None, [d.wins for d in season_decks]))
    c.season.losses = sum(filter(None, [d.losses for d in season_decks]))
    c.season.draws = sum(filter(None, [d.draws for d in season_decks]))
    if c.season.wins or c.season.losses or c.season.draws:
        c.season.win_percent = round(
            (c.season.wins / (c.season.wins + c.season.losses)) * 100, 1)
    else:
        c.season.win_percent = ''
    c.season.num_decks = len(season_decks)
    c.played_competitively = c.all.wins or c.all.losses or c.all.draws
    return c
def doubled_decks() -> List[Deck]:
    sql = """
        SELECT
            deck_id,
            GROUP_CONCAT(archetype_id) AS archetype_ids,
            GROUP_CONCAT(archetype_name SEPARATOR '|') AS archetype_names
        FROM
            _applied_rules
        GROUP BY
            deck_id
        HAVING
            COUNT(DISTINCT archetype_id) > 1
        """
    archetypes_from_rules: Dict[int, List[Container]] = {}
    for r in [Container(row) for row in db().select(sql)]:
        matching_archetypes = zip(r.archetype_ids.split(','),
                                  r.archetype_names.split('|'))
        archetypes_from_rules[r.deck_id] = [
            Container({
                'archetype_id': archetype_id,
                'archetype_name': archetype_name
            }) for archetype_id, archetype_name in matching_archetypes
        ]
    if not archetypes_from_rules:
        return []
    ids_list = ', '.join(str(deck_id) for deck_id in archetypes_from_rules)
    result = deck.load_decks(where=f'd.id IN ({ids_list})')
    for d in result:
        d.archetypes_from_rules = archetypes_from_rules[d.id]
        d.archetypes_from_rules_names = ', '.join(
            a.archetype_name for a in archetypes_from_rules[d.id])
    return result
Beispiel #3
0
def load_all_rules() -> List[Container]:
    result = []
    result_by_id = {}
    sql = """
        SELECT
            rule.id AS id,
            archetype.id AS archetype_id,
            archetype.name AS archetype_name,
            COUNT(DISTINCT _applied_rules.deck_id) as num_decks
        FROM
            rule
        INNER JOIN
            archetype
        ON
            rule.archetype_id = archetype.id
        LEFT JOIN
            _applied_rules
        ON
            rule.id = _applied_rules.rule_id
        GROUP BY
            id
        """
    for r in (Container(row) for row in db().select(sql)):
        result.append(r)
        result_by_id[r.id] = r
        r.included_cards = []
        r.excluded_cards = []
    sql = 'SELECT rule_id, card, n, include FROM rule_card'
    for r in (Container(row) for row in db().select(sql)):
        if r.include:
            result_by_id[r.rule_id].included_cards.append({'n': r.n, 'card': r.card})
        else:
            result_by_id[r.rule_id].excluded_cards.append({'n': r.n, 'card': r.card})
    return result
Beispiel #4
0
async def test_command(discordbot: Bot, cmd: str, kwargs: Dict[str, Any]) -> None: # pylint: disable=redefined-outer-name
    command: discord.ext.commands.Command = discordbot.all_commands[cmd]
    ctx = TestContext()
    ctx.bot = discordbot
    ctx.message = Container()
    ctx.message.channel = Container({'id': '1'})
    ctx.message.channel.typing = ctx.typing
    ctx.message.channel.send = ctx.send
    ctx.author = Container()
    ctx.author.mention = '<@111111111111>'
    await command.callback(ctx, **kwargs)
    assert ctx.sent
def mistagged_decks() -> List[Deck]:
    sql = """
            SELECT
                deck_id,
                rule_archetype.id AS rule_archetype_id,
                rule_archetype.name AS rule_archetype_name,
                tagged_archetype.name AS tagged_archetype_name
            FROM
                _applied_rules
            INNER JOIN
                deck
            ON
                _applied_rules.deck_id = deck.id
            INNER JOIN
                archetype AS rule_archetype
            ON
                rule_archetype.id = _applied_rules.archetype_id
            INNER JOIN
                archetype AS tagged_archetype
            ON
                tagged_archetype.id = deck.archetype_id
            WHERE
                rule_archetype.id != tagged_archetype.id
            """
    rule_archetypes = {}
    for r in (Container(row) for row in db().select(sql)):
        rule_archetypes[r.deck_id] = (r.rule_archetype_id,
                                      r.rule_archetype_name)
    if not rule_archetypes:
        return []
    ids_list = ', '.join(str(deck_id) for deck_id in rule_archetypes)
    result = deck.load_decks(where=f'd.id IN ({ids_list})')
    for d in result:
        d.rule_archetype_id, d.rule_archetype_name = rule_archetypes[d.id]
    return result
Beispiel #6
0
def load_season(season=None):
    if season is None:
        where = 'start. start_date <= UNIX_TIMESTAMP() AND `end`.start_date > UNIX_TIMESTAMP()'
    else:
        try:
            number = int(season)
            code = "'{season}'".format(season=season)
        except ValueError:
            number = 0
            code = sqlescape(season)
        where = 'start.`number` = {number} OR start.`code` = {code}'.format(
            number=number, code=code)
    sql = """
        SELECT start.`number`, start.`code`, `start`.start_date, `end`.start_date AS end_date
        FROM season AS `start`
        LEFT JOIN season AS `end`
        ON `start`.`number` + 1 = `end`.`number`
        WHERE {where}
    """.format(where=where)
    season = Container(guarantee.exactly_one(db().execute(sql)))
    season.decks = load_decks(
        'd.created_date >= {start_ts} AND d.created_date < IFNULL({end_ts}, 999999999999)'
        .format(start_ts=season.start_date, end_ts=season.end_date))
    season.start_date = dtutil.ts2dt(season.start_date)
    season.end_date = dtutil.ts2dt(season.end_date)
    return season
Beispiel #7
0
def load_news(start_date=0, end_date=sys.maxsize, max_items=sys.maxsize):
    sql = """
        SELECT
            id,
            `date`,
            title,
            body
        FROM
            news_item
        WHERE
            `date` >= %s
        AND
            `date` <= %s
        ORDER BY
            `date` DESC
        LIMIT
            %s
    """
    results = [
        Container(r)
        for r in db().execute(sql, [start_date, end_date, max_items])
    ]
    for result in results:
        result.date = dtutil.ts2dt(result.date)
        result.form_date = dtutil.form_date(result.date, dtutil.WOTC_TZ)
        result.display_date = dtutil.display_date(result.date)
    return results
Beispiel #8
0
def played_cards(where='1 = 1'):
    sql = """
        SELECT
            card AS name,
            {all_select},
            {season_select},
            {week_select}
        FROM
            deck_card AS dc
        INNER JOIN
            deck AS d ON dc.deck_id = d.id
        {nwdl_join}
        WHERE
            {where}
        GROUP BY
            dc.card
        ORDER BY
            season_num_decks DESC,
            SUM(CASE WHEN dsum.created_date >= %s THEN dsum.wins - dsum.losses ELSE 0 END) DESC,
            name
    """.format(all_select=deck.nwdl_all_select(),
               season_select=deck.nwdl_season_select(),
               week_select=deck.nwdl_week_select(),
               nwdl_join=deck.nwdl_join(),
               where=where)
    cs = [
        Container(r)
        for r in db().execute(sql, [int(rotation.last_rotation().timestamp())])
    ]
    cards = oracle.cards_by_name()
    for c in cs:
        c.update(cards[c.name])
    return cs
Beispiel #9
0
def test_cards_from_queries2():
    bot = Container()
    bot.searcher = whoosh_search.WhooshSearcher()
    result = command.cards_from_queries2(['bolt'], bot)[0]
    assert result.has_match()
    assert not result.is_ambiguous()
    assert result.get_best_match() == 'Lightning Bolt'
def load_matchups(archetype_id, season_id=None):
    sql = """
        SELECT
            oa.id,
            oa.name,
            SUM(CASE WHEN dm.games > IFNULL(odm.games, 0) THEN 1 ELSE 0 END) AS all_wins, -- IFNULL so we still count byes as wins.
            SUM(CASE WHEN dm.games < odm.games THEN 1 ELSE 0 END) AS all_losses,
            SUM(CASE WHEN dm.games = odm.games THEN 1 ELSE 0 END) AS all_draws,
            IFNULL(ROUND((SUM(CASE WHEN dm.games > odm.games THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN dm.games <> IFNULL(odm.games, 0) THEN 1 ELSE 0 END), 0)) * 100, 1), '') AS all_win_percent
        FROM
            archetype AS a
        INNER JOIN
            deck AS d ON d.archetype_id IN (SELECT descendant FROM archetype_closure WHERE ancestor = a.id)
        INNER JOIN
            deck_match AS dm ON d.id = dm.deck_id
        INNER JOIN
            deck_match AS odm ON dm.match_id = odm.match_id AND odm.deck_id <> d.id
        INNER JOIN
            deck AS od ON od.id = odm.deck_id
        INNER JOIN
            archetype AS oa ON od.archetype_id IN (SELECT descendant FROM archetype_closure WHERE ancestor = oa.id)
        {season_join}
        WHERE
            (a.id = %s) AND ({season_query})
        GROUP BY
            oa.id
        ORDER BY
            `all_wins` DESC, oa.name
    """.format(season_join=query.season_join(),
               season_query=query.season_query(season_id))
    return [Container(m) for m in db().execute(sql, [archetype_id])]
Beispiel #11
0
def load_head_to_head(
        person_id: int,
        where: str = 'TRUE',
        order_by:
    str = 'num_matches DESC, record DESC, win_percent DESC, wins DESC, opp_mtgo_username',
        limit: str = '',
        season_id: int = None) -> Sequence[Container]:
    season_query = query.season_query(season_id)
    sql = f"""
        SELECT
            hths.person_id AS id,
            LOWER(opp.mtgo_username) AS opp_mtgo_username,
            SUM(num_matches) AS num_matches,
            SUM(wins) - SUM(losses) AS record,
            SUM(wins) AS wins,
            SUM(losses) AS losses,
            SUM(draws) AS draws,
            IFNULL(ROUND((SUM(wins) / NULLIF(SUM(wins + losses), 0)) * 100, 1), '') AS win_percent
        FROM
            _head_to_head_stats AS hths
        INNER JOIN
            person AS opp ON hths.opponent_id = opp.id
        WHERE
            ({where}) AND (hths.person_id = {person_id}) AND ({season_query})
        GROUP BY
            hths.person_id,
            hths.opponent_id
        ORDER BY
            {order_by}
        {limit}
    """
    return [Container(r) for r in db().select(sql)]
Beispiel #12
0
def played_cards_by_person(person_id: int, season_id: int) -> List[Card]:
    sql = """
        SELECT
            name,
            SUM(num_decks) AS num_decks,
            SUM(wins) AS wins,
            SUM(losses) AS losses,
            SUM(draws) AS draws,
            SUM(wins - losses) AS record,
            IFNULL(ROUND((SUM(wins) / NULLIF(SUM(wins + losses), 0)) * 100, 1), '') AS win_percent
        FROM
            _played_card_person_stats
        WHERE
            person_id = %s
        AND
            {season_query}
        GROUP BY
            name
        HAVING
            name IS NOT NULL
    """.format(season_query=query.season_query(season_id))
    print(sql)
    cs = [Container(r) for r in decksite_db().select(sql, [person_id])]
    print(len(cs))
    cards = oracle.cards_by_name()
    for c in cs:
        c.update(cards[c.name])
    return cs
Beispiel #13
0
 def __init__(self, form: ImmutableMultiDict, person_id: Optional[int],
              mtgo_username: Optional[str]) -> None:
     super().__init__(form)
     if person_id is not None:
         ps = person.load_person_by_id(person_id)
         self.recent_decks: List[Dict[str, Any]] = []
         for d in sorted(ps.decks,
                         key=lambda deck: deck['created_date'],
                         reverse=True)[0:10]:
             recent_deck = {'name': d['name'], 'main': [], 'sb': []}
             for c in d.maindeck:
                 recent_deck['main'].append('{n} {c}'.format(n=c['n'],
                                                             c=c['name']))
             for c in d.sideboard:
                 recent_deck['sb'].append('{n} {c}'.format(n=c['n'],
                                                           c=c['name']))
             self.recent_decks.append({
                 'name': d['name'],
                 'list': json.dumps(recent_deck)
             })
     if mtgo_username is not None:
         self.mtgo_username = mtgo_username
     self.deck = Container()
     self.card_errors: Dict[str, Set[str]] = {}
     self.card_warnings: Dict[str, Set[str]] = {}
Beispiel #14
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
Beispiel #15
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
Beispiel #16
0
def set_head_to_head(people: List[Person], season_id: int = None) -> None:
    people_by_id = {person.id: person for person in people}
    sql = """
        SELECT
            hths.person_id AS id,
            LOWER(opp.mtgo_username) AS opp_mtgo_username,
            SUM(num_matches) AS num_matches,
            SUM(wins) AS wins,
            SUM(losses) AS losses,
            SUM(draws) AS draws,
            IFNULL(ROUND((SUM(wins) / NULLIF(SUM(wins + losses), 0)) * 100, 1), '') AS win_percent
        FROM
            _head_to_head_stats AS hths
        INNER JOIN
            person AS opp ON hths.opponent_id = opp.id
        WHERE
            hths.person_id IN ({ids}) AND ({season_query})
        GROUP BY
            hths.person_id,
            hths.opponent_id
        ORDER BY
            SUM(num_matches) DESC,
            SUM(wins - losses) DESC,
            win_percent DESC,
            SUM(wins) DESC,
            opp_mtgo_username
    """.format(ids=', '.join(str(k) for k in people_by_id.keys()),
               season_query=query.season_query(season_id))
    results = [Container(r) for r in db().select(sql)]
    for result in results:
        people_by_id[result.id].head_to_head = people_by_id[result.id].get(
            'head_to_head', []) + [result]
    for person in people:
        if person.get('head_to_head') is None:
            person.head_to_head = []
Beispiel #17
0
def scrape_one(url: str) -> Container:
    d = Container({'source': 'MTG Goldfish'})
    identifier_match = re.match('.*/deck/([^#]*)(?:#.*)?', url)
    if identifier_match is None:
        raise InvalidDataException(
            'Cannot find identifier in URL. Is it a valid MTG Goldfish decklist URL?'
        )
    d.identifier = identifier_match.group(1)
    d.url = url
    soup = BeautifulSoup(
        fetcher.internal.fetch(d.url, character_encoding='utf-8'),
        'html.parser')
    d.name = str(soup.select_one('h2.deck-view-title').contents[0]).strip()
    d.mtggoldfish_username = without_by(
        str(soup.select_one('span.deck-view-author').contents[0].strip()))
    d.created_date = parse_created_date(soup)
    try:
        d.cards = scrape_decklist(d)
    except InvalidDataException as e:
        raise InvalidDataException(
            f'Unable to scrape decklist for {d} because of {e}')
    error = vivify_or_error(d)
    if error:
        raise InvalidDataException(error)
    return deck.add_deck(d)
Beispiel #18
0
 def setup_matchups(self, archetypes: List[Archetype],
                    matchups: List[Container], min_matches: int) -> None:
     for hero in archetypes:
         hero.matchups = []
         matchups_by_enemy_id = {
             mu.id: mu
             for mu in matchups if mu.archetype_id == hero.id
         }
         for enemy in archetypes:
             mu = matchups_by_enemy_id.get(
                 enemy.id, Container({
                     'wins': 0,
                     'losses': 0
                 }))
             if mu.wins + mu.losses >= min_matches:
                 hero.show_as_hero = True
                 enemy.show_as_enemy = True
                 self.show_matchup_grid = True
             if mu and mu.wins + mu.losses > 0:
                 prepare_matchup(mu, enemy)
                 hero.matchups.append(mu)
             else:
                 hero.matchups.append(empty_matchup(enemy))
     for hero in archetypes:
         for mu in hero.matchups:
             mu.show_as_enemy = mu.opponent_archetype.get(
                 'show_as_enemy', False)
     self.matchup_archetypes = archetypes
Beispiel #19
0
def empty_matchup(opponent_archetype: Archetype) -> Container:
    mu = Container()
    mu.has_data = False
    mu.win_percent = None
    mu.color_cell = False
    mu.opponent_archetype = opponent_archetype
    return mu
Beispiel #20
0
def insert_scryfall_card(sfcard: Dict, rebuild_cache: bool = True) -> None:
    imagename = '{set}_{number}'.format(set=sfcard['set'], number=sfcard['collector_number'])
    c = Container({
        'layout': sfcard['layout'],
        'cmc': int(float(sfcard['cmc'])),
        'imageName': imagename,
        'legalities': [],
        'printings': [sfcard['set']],
        'rarity': sfcard['rarity'],
        'names': []
    })
    faces = sfcard.get('card_faces', [sfcard])
    names = [face['name'] for face in faces]
    for face in faces:
        tl = face['type_line'].split('—')
        types = tl[0]
        subtypes = tl[1] if len(tl) > 1 else []

        c.update({
            'name': face['name'],
            'type': face['type_line'],
            'types': types, # This technically includes supertypes.
            'subtypes': subtypes,
            'text': face.get('oracle_text', ''),
            'manaCost': face.get('mana_cost', None)
        })
        c.names = names
        multiverse.insert_card(c)
    if rebuild_cache:
        multiverse.update_cache()
        CARDS_BY_NAME[sfcard['name']] = load_card(sfcard['name'])
Beispiel #21
0
def played_cards(where: str = '1 = 1',
                 season_id: Optional[int] = None) -> List[Card]:
    sql = """
        SELECT
            card AS name,
            {all_select},
            {season_select}, -- We use the season data on the homepage to calculate movement, even though we no longer use it on /cards/.
            {week_select}
        FROM
            deck_card AS dc
        INNER JOIN
            deck AS d ON dc.deck_id = d.id
        {season_join}
        {nwdl_join}
        WHERE ({where}) AND ({season_query})
        GROUP BY
            dc.card
        ORDER BY
            all_num_decks DESC,
            SUM(dsum.wins - dsum.losses) DESC,
            name
    """.format(all_select=deck.nwdl_all_select(),
               season_select=deck.nwdl_season_select(),
               week_select=deck.nwdl_week_select(),
               season_join=query.season_join(),
               nwdl_join=deck.nwdl_join(),
               where=where,
               season_query=query.season_query(season_id))
    cs = [Container(r) for r in db().execute(sql)]
    cards = oracle.cards_by_name()
    for c in cs:
        c.update(cards[c.name])
    return cs
Beispiel #22
0
def load_matches(where='1 = 1'):
    sql = """
        SELECT m.date, m.id, GROUP_CONCAT(dm.deck_id) AS deck_ids, GROUP_CONCAT(dm.games) AS games
        FROM `match` AS m
        INNER JOIN deck_match AS dm ON m.id = dm.match_id
        WHERE {where}
        GROUP BY m.id
        ORDER BY m.date DESC
    """.format(where=where)
    matches = [Container(m) for m in db().execute(sql)]
    for m in matches:
        m.date = dtutil.ts2dt(m.date)
        deck_ids = m.deck_ids.split(',')
        games = m.games.split(',')
        m.left_id = deck_ids[0]
        m.left_games = int(games[0])
        try:
            m.right_id = deck_ids[1]
            m.right_games = int(games[1])
        except IndexError:
            m.right_id = None
            m.right_games = 0
        if m.left_games > m.right_games:
            m.winner = m.left_id
            m.loser = m.right_id
        elif m.right_games > m.left_games:
            m.winner = m.right_id
            m.loser = m.left_id
        else:
            m.winner = None
            m.loser = None
    return matches
Beispiel #23
0
def load_queue_similarity(decks: List[Deck]) -> None:
    sql = 'SELECT deck.id, deck_cache.similarity FROM deck JOIN deck_cache ON deck.id = deck_cache.deck_id WHERE NOT deck.reviewed'
    sim = {}
    for row in (Container(r) for r in db().select(sql)):
        sim[row.id] = row.similarity
    for deck in decks:
        deck.similarity = '{0}%'.format(sim[deck.id]) if sim[deck.id] is not None else ''
def load_season(season=None, league_only=False):
    if season is None:
        where = 'start. start_date <= UNIX_TIMESTAMP() AND `end`.start_date > UNIX_TIMESTAMP()'
    else:
        try:
            number = int(season)
            code = "'{season}'".format(season=season)
        except ValueError:
            number = 0
            code = sqlescape(season)
        where = 'start.`number` = {number} OR start.`code` = {code}'.format(
            number=number, code=code)
    sql = """
        SELECT start.`number`, start.`code`, `start`.start_date, `end`.start_date AS end_date
        FROM season AS `start`
        LEFT JOIN season AS `end`
        ON `start`.`number` + 1 = `end`.`number`
        WHERE {where}
    """.format(where=where)
    season = Container(guarantee.exactly_one(db().execute(sql)))
    where = 'd.created_date >= {start_ts}'.format(start_ts=season.start_date)
    if season.end_date:
        where = '{where} AND d.created_date < {end_ts}'.format(
            where=where, end_ts=season.end_date)
    if league_only:
        where = "{where} AND d.competition_id IN ({competition_ids_by_type_select})".format(
            where=where,
            competition_ids_by_type_select=query.
            competition_ids_by_type_select('League'))
    season.decks = load_decks(where)
    season.start_date = dtutil.ts2dt(season.start_date)
    season.end_date = dtutil.ts2dt(
        season.end_date) if season.end_date else None
    return season
Beispiel #25
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
Beispiel #26
0
 async def on_reaction_add(self, reaction: Reaction,
                           author: Member) -> None:
     if reaction.message.author == self.user:
         c = reaction.count
         if reaction.me:
             c = c - 1
         if c > 0 and not reaction.custom_emoji and reaction.emoji == '❎':
             await reaction.message.delete()
         elif c > 0 and 'Ambiguous name for ' in reaction.message.content and reaction.emoji in command.DISAMBIGUATION_EMOJIS_BY_NUMBER.values(
         ):
             async with reaction.message.channel.typing():
                 search = re.search(
                     r'Ambiguous name for ([^\.]*)\. Suggestions: (.*)',
                     reaction.message.content)
                 if search:
                     previous_command, suggestions = search.group(1, 2)
                     card = re.findall(
                         r':[^:]*?: ([^:]*) ', suggestions +
                         ' ')[command.DISAMBIGUATION_NUMBERS_BY_EMOJI[
                             reaction.emoji] - 1]
                     message = Container(content='!{c} {a}'.format(
                         c=previous_command, a=card),
                                         channel=reaction.message.channel,
                                         author=author,
                                         reactions=[])
                     await self.on_message(message)
                     await reaction.message.delete()
Beispiel #27
0
def load_news(start_date: datetime.datetime = None,
              end_date: datetime.datetime = None,
              max_items: int = sys.maxsize) -> List[Container]:
    if start_date is None:
        start_date = dtutil.ts2dt(0)
    if end_date is None:
        end_date = dtutil.now()
    sql = """
        SELECT
            id,
            `date`,
            title,
            url
        FROM
            news_item
        WHERE
            `date` >= %s
        AND
            `date` <= %s
        ORDER BY
            `date` DESC
        LIMIT
            %s
    """
    results = [
        Container(r) for r in db().select(
            sql, [dtutil.dt2ts(start_date),
                  dtutil.dt2ts(end_date), max_items])
    ]
    for result in results:
        result.date = dtutil.ts2dt(result.date)
        result.form_date = dtutil.form_date(result.date, dtutil.WOTC_TZ)
        result.display_date = dtutil.display_date(result.date)
        result.type = 'site-news'
    return results
Beispiel #28
0
def subreddit(start_date: datetime.datetime,
              end_date: datetime.datetime,
              max_items: int = sys.maxsize) -> List[Container]:
    try:
        redis_key = 'decksite:news:subreddit'
        items = redis.get_container_list(redis_key)
        if items:
            for item in items:
                item.date = dtutil.ts2dt(item.date)
            return items
        feed = fetcher.subreddit()
        items = []
        for entry in feed.entries:
            item = Container({
                'title':
                entry.title,
                'date':
                dtutil.parse(entry.updated, '%Y-%m-%dT%H:%M:%S+00:00',
                             dtutil.UTC_TZ),
                'url':
                entry.link,
                'type':
                'subreddit-post'
            })
            if item.date > end_date:
                continue
            if item.date < start_date:
                break
            items.append(item)
            if len(items) >= max_items:
                break
        redis.store(redis_key, items, ex=3600)
        return items
    except ConnectionError:
        return []
Beispiel #29
0
def load_cards(season_id: Optional[int] = None,
               person_id: Optional[int] = None,
               retry: bool = False) -> List[Card]:
    if person_id:
        table = '_card_person_stats'
        where = 'person_id = {person_id}'.format(
            person_id=sqlescape(person_id))
        group_by = 'person_id, name'
    else:
        table = '_card_stats'
        where = 'TRUE'
        group_by = 'name'
    sql = """
        SELECT
            name,
            SUM(num_decks) AS num_decks,
            SUM(wins) AS wins,
            SUM(losses) AS losses,
            SUM(draws) AS draws,
            SUM(wins - losses) AS record,
            SUM(num_decks_tournament) AS num_decks_tournament,
            SUM(wins_tournament) AS wins_tournament,
            SUM(losses_tournament) AS losses_tournament,
            SUM(draws_tournament) AS draws_tournament,
            SUM(wins_tournament - losses_tournament) AS record_tournament,
            SUM(perfect_runs) AS perfect_runs,
            SUM(tournament_wins) AS tournament_wins,
            SUM(tournament_top8s) AS tournament_top8s,
            IFNULL(ROUND((SUM(wins) / NULLIF(SUM(wins + losses), 0)) * 100, 1), '') AS win_percent,
            IFNULL(ROUND((SUM(wins_tournament) / NULLIF(SUM(wins_tournament + losses_tournament), 0)) * 100, 1), '') AS win_percent_tournament
        FROM
            {table} AS cs
        WHERE
            ({where}) AND ({season_query})
        GROUP BY
            {group_by}
        ORDER BY
            num_decks DESC,
            record,
            name
    """.format(table=table,
               season_query=query.season_query(season_id),
               where=where,
               group_by=group_by)
    try:
        cs = [Container(r) for r in db().select(sql)]
        cards = oracle.cards_by_name()
        for c in cs:
            c.update(cards[c.name])
        return cs
    except DatabaseException as e:
        if not retry:
            print(
                f"Got {e} trying to load_cards so trying to preaggregate. If this is happening on user time that's undesirable."
            )
            preaggregate()
            return load_cards(season_id, person_id, retry=True)
        print(f'Failed to preaggregate. Giving up.')
        raise e
Beispiel #30
0
def load_season(season_id: int = None, league_only: bool = False) -> Container:
    season = Container()
    where = 'TRUE'
    if league_only:
        where = 'd.competition_id IN ({competition_ids_by_type_select})'.format(competition_ids_by_type_select=query.competition_ids_by_type_select('League'))
    season.decks = load_decks(where, season_id=season_id)
    season.number = season_id
    return season