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 only_played_by(person_id: int, season_id: Optional[int] = None) -> List[Card]: sql = """ SELECT card AS name FROM deck_card AS dc INNER JOIN deck AS d ON dc.deck_id = d.id {season_join} WHERE deck_id IN ( SELECT DISTINCT deck_id FROM deck_match ) -- Only include cards that actually got played competitively rather than just posted to Goldfish as "new cards this season" or similar. AND ({season_query}) GROUP BY card HAVING COUNT(DISTINCT d.person_id) = 1 AND MAX(d.person_id) = {person_id} -- In MySQL 5.7+ this could/should be ANY_VALUE not MAX but this works with any version. The COUNT(DISTINCT p.id) ensures this only has one possible value but MySQL can't work that out.-- In MySQL 5.7+ this could/should be ANY_VALUE not MAX but this works with any version. The COUNT(DISTINCT p.id) ensures this only has one possible value but MySQL can't work that out. """.format(season_join=query.season_join(), season_query=query.season_query(season_id), person_id=sqlescape(person_id)) cards = {c.name: c for c in oracle.load_cards()} return [cards[r['name']] for r in db().execute(sql)]
def test_split_cards() -> None: cards = oracle.load_cards(['Armed // Dangerous']) assert len(cards) == 1 assert image_fetcher.download_image(cards) is not None names = command.parse_queries('[Toil // Trouble]', False) assert len(names) == 1 results = command.results_from_queries(names) assert len(results) == 1
def test_split_cards(): cards = oracle.load_cards(['Armed // Dangerous']) assert len(cards) == 1 assert image_fetcher.download_image(cards) is not None names = command.parse_queries('[Toil // Trouble]') assert len(names) == 1 results = command.results_from_queries(names, whoosh_search.WhooshSearcher())[0] assert len(results) == 1
def test_deck_sort_x_last(): cards = oracle.load_cards( ['Ghitu Fire', 'Flash of Insight', 'Frantic Search']) assert len(cards) == 3 cards = {c.name: c for c in cards} assert oracle.deck_sort(cards.get('Ghitu Fire')) < oracle.deck_sort( cards.get('Flash of Insight')) assert oracle.deck_sort(cards.get('Ghitu Fire')) > oracle.deck_sort( cards.get('Frantic Search'))
def test_deck_sort_x_last() -> None: cards = oracle.load_cards( ['Ghitu Fire', 'Flash of Insight', 'Frantic Search']) assert len(cards) == 3 cards_by_name = {c.name: c for c in cards} assert oracle.deck_sort(cards_by_name['Ghitu Fire']) < oracle.deck_sort( cards_by_name['Flash of Insight']) assert oracle.deck_sort(cards_by_name['Ghitu Fire']) > oracle.deck_sort( cards_by_name['Frantic Search'])
def only_played_by(person_id): sql = """ SELECT card AS name, p.id FROM deck_card AS dc INNER JOIN deck AS d ON d.id = dc.deck_id INNER JOIN person AS p ON p.id = d.person_id GROUP BY card HAVING COUNT(DISTINCT p.id) = 1 AND p.id = {person_id} AND SUM(d.wins + d.draws + d.losses) > 0 """.format(person_id=sqlescape(person_id)) cs = [Container(r) for r in db().execute(sql)] cards = {c.name: c for c in oracle.load_cards()} for c in cs: c.update(cards[c.name]) return cs
def load_card(name: str, season_id: Optional[int] = None) -> Card: 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)), season_id=season_id) 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: 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) c.played_competitively = c.all_wins or c.all_losses or c.all_draws return c
def fancy_cards(): return legality.cards_legal_in_format( oracle.load_cards([ 'Mother of Runes', 'Treasure Cruise', 'Hymn to Tourach', 'Hermit Druid', 'Frantic Search', 'Necropotence', 'Tendrils of Agony', 'Hypergenesis', "Mind's Desire", 'Recurring Nightmare', 'Worldgorger Dragon', 'Astral Slide', 'Dark Ritual', 'Fact or Fiction', 'High Tide', "Nevinyrral's Disk", 'Lake of the Dead', 'Braids, Cabal Minion', 'Channel', 'Chain Lightning', 'Brain Freeze', 'Dragonstorm', 'Day of Judgment', 'Cruel Ultimatum', 'Mana Leak', 'Burning of Xinye', 'Psychatog', 'Smokestack', 'Llanowar Elves', 'Animate Dead', 'Demonic Consultation' ]), 'Penny Dreadful')
def image(c: str = '') -> Response: names = c.split('|') try: requested_cards = oracle.load_cards(names) path = image_fetcher.download_image(requested_cards) if path is None: raise InternalServerError( f'Failed to get image for {c}') # type: ignore return send_file( os.path.abspath(path) ) # Send abspath to work around monolith root versus web root. except TooFewItemsException as e: print(e) return '', 400
def promo_explanation() -> Tuple[str, Dict[str, str]]: explanation = 'Some cards have promos that are much cheaper than all other versions. The bot reports the cheapest version in stock.\nOther bot chains will have copies.' have_cheap_promos = [ 'Barbarian Ring', 'Buried Alive', 'Crystal Vein', 'Eureka', 'Figure of Destiny', 'Lake of the Dead', ] legal_cheap_promos = [c for c in oracle.load_cards(have_cheap_promos) if c.pd_legal] if len(legal_cheap_promos) > 0: explanation += ' Affected cards include: ' + ', '.join(c.name for c in legal_cheap_promos) return(explanation, {})
def image(c: str = '') -> wrappers.Response: names = c.split('|') try: requested_cards = oracle.load_cards(names) path = image_fetcher.download_image(requested_cards) if path is None: raise InternalServerError(f'Failed to get image for {c}') return send_file( os.path.abspath(path) ) # Send abspath to work around monolith root versus web root. except TooFewItemsException as e: logger.info(f'Did not find an image for {c}: {e}') if len(names) == 1: return redirect( f'https://api.scryfall.com/cards/named?exact={c}&format=image', code=303) return make_response('', 400)
def vivify(decklist): validated, invalid_names = {'maindeck': {}, 'sideboard': {}}, set() for section in ['maindeck', 'sideboard']: for name, n in decklist[section].items(): try: validated[section][oracle.valid_name(name)] = n except InvalidDataException: invalid_names.add(name) if invalid_names: raise InvalidDataException('Invalid cards: {invalid_names}'.format(invalid_names='; '.join(invalid_names))) validated_names = list(validated['maindeck'].keys()) + list(validated['sideboard'].keys()) cards = {c.name: c for c in oracle.load_cards(validated_names)} d = Deck({'maindeck': [], 'sideboard': []}) for section in ['maindeck', 'sideboard']: for name, n in validated[section].items(): d[section].append({'n': n, 'name': name, 'card': cards[name]}) return d
def image(c: str = '') -> Union[Tuple[str, int], wrappers.Response]: names = c.split('|') try: requested_cards = oracle.load_cards(names) path = image_fetcher.download_image(requested_cards) if path is None: raise InternalServerError( f'Failed to get image for {c}') # type: ignore return send_file( os.path.abspath(path) ) # Send abspath to work around monolith root versus web root. except TooFewItemsException as e: print(e) if len(names) == 1: return redirect( f'https://api.scryfall.com/cards/named?exact={c}&format=image', code=303) return '', 400
def load_card(name: str, season_id: Optional[int] = None) -> Card: c = guarantee.exactly_one(oracle.load_cards([name])) c.decks = deck.load_decks(query.card_where(name), season_id=season_id) c.wins, c.losses, c.draws, c.tournament_wins, c.tournament_top8s, c.perfect_runs = 0, 0, 0, 0, 0, 0 for d in c.decks: c.wins += d.get('wins', 0) c.losses += d.get('losses', 0) c.draws += d.get('draws', 0) c.tournament_wins += 1 if d.get('finish') == 1 else 0 c.tournament_top8s += 1 if (d.get('finish') or sys.maxsize) <= 8 else 0 c.perfect_runs += 1 if d.get('source_name') == 'League' and d.get('wins', 0) >= 5 and d.get('losses', 0) == 0 else 0 if c.wins or c.losses: c.win_percent = round((c.wins / (c.wins + c.losses)) * 100, 1) else: c.win_percent = '' c.num_decks = len(c.decks) c.played_competitively = c.wins or c.losses or c.draws return c
def load_card(name: str, season_id: Optional[int] = None) -> Card: 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)), season_id=season_id) c.all_wins, c.all_losses, c.all_draws, c.all_tournament_wins, c.all_tournament_top8s, c.all_perfect_runs = 0, 0, 0, 0, 0, 0 for d in c.decks: c.all_wins += d.get('wins', 0) c.all_losses += d.get('losses', 0) c.all_draws += d.get('draws', 0) c.all_tournament_wins += 1 if d.get('finish') == 1 else 0 c.all_tournament_top8s += 1 if (d.get('finish') or sys.maxsize) <= 8 else 0 c.all_perfect_runs += 1 if d.get('source_name') == 'League' and d.get( 'wins', 0) >= 5 and d.get('losses', 0) == 0 else 0 if c.all_wins or c.all_losses: 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) c.played_competitively = c.all_wins or c.all_losses or c.all_draws return c
def __init__(self, exception): self.exception = str(exception) self.card = random.choice(oracle.load_cards(where="c.name LIKE '%%Lost%%'")) self.cards = [self.card]
def __init__(self, person: ps.Person, cards: List[Card], archetypes: List[Archetype], all_archetypes: List[Archetype], your_cards: Dict[str, List[str]], seasons_active: Sequence[int], season_id: Optional[int]) -> None: super().__init__() self.all_archetypes = all_archetypes self.person = person self.people = [person] self.decks = person.decks self.has_decks = len(person.decks) > 0 self.archetypes = archetypes self.hide_person = True self.cards = cards self.show_seasons = True self.displayed_achievements = [{ 'title': a.title, 'detail': titlecase.titlecase(a.display(self.person)) } for a in Achievement.all_achievements if a.display(self.person)] self.achievements_url = url_for('.achievements') self.person_achievements_url = url_for('.person_achievements', person_id=person.id) colors: Dict[str, int] = {} for d in self.decks: for c in d.colors: colors[c] = colors.get(c, 0) + 1 self.charts = [ { 'title': 'Colors Played', 'type': 'horizontalBar', 'labels': json.dumps( ['White', 'Blue', 'Black', 'Red', 'Green', 'Colorless']), 'series': json.dumps([ colors.get('W'), colors.get('U'), colors.get('B'), colors.get('R'), colors.get('G'), colors.get('C') ]), 'options': json.dumps({ 'responsive': True, 'scales': { 'xAxes': [{ 'ticks': { 'precision': 0 } }] } }), # Only display whole numbers on x axis. }, ] self.add_note_url = url_for('post_player_note') self.matches_url = url_for( '.person_matches', person_id=person.id, season_id=None if season_id == seasons.current_season_num() else season_id) self.is_person_page = True self.trailblazer_cards = oracle.load_cards(your_cards['trailblazer']) self.has_trailblazer_cards = len(self.trailblazer_cards) > 0 self.unique_cards = oracle.load_cards(your_cards['unique']) self.has_unique_cards = len(self.unique_cards) > 0 self.cards += self.trailblazer_cards + self.unique_cards self.setup_active_seasons(seasons_active)
def __init__(self, exception): self.exception = str(exception) self.card = random.choice( oracle.load_cards( ['Erratic Explosion', 'Curse of Chaos', 'Anarchy'])) self.cards = [self.card]
def test_load_cards() -> None: cards = oracle.load_cards(['Think Twice', 'Swamp']) assert len(cards) == 2 assert 'Think Twice' in [c.name for c in cards] assert 'Swamp' in [c.name for c in cards]