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
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
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
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
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
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
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])]
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)]
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
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]] = {}
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 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
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 = []
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)
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
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
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'])
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
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
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
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
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()
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
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 []
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
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