def test_legal_formats(): swamp = oracle.load_card('Swamp') think_twice = oracle.load_card('Think Twice') fork = oracle.load_card('Fork') d = deck.Deck({'id': 0}) d.maindeck = [{'n': 59, 'card': swamp}] d.sideboard = [] assert len(d.all_cards()) == 59 formats = legality.legal_formats(d) assert len(formats) == 0 d.maindeck = [{'n': 60, 'card': swamp}] formats = legality.legal_formats(d) assert 'Penny Dreadful' in formats assert 'Legacy' in formats assert 'Penny Dreadful EMN' in formats formats = legality.legal_formats(d, {'Penny Dreadful'}) assert len(formats) == 1 assert 'Penny Dreadful' in formats assert 'Legacy' not in formats d.maindeck = [{'n': 55, 'card': swamp}, {'n': 5, 'card': think_twice}] formats = legality.legal_formats(d) assert len(d.all_cards()) == 60 assert len(legality.legal_formats(d)) == 0 d.maindeck = [{'n': 56, 'card': swamp}, {'n': 4, 'card': think_twice}] formats = legality.legal_formats(d) assert 'Legacy' in formats assert 'Modern' in formats d.sideboard = [{'n': 15, 'card': swamp}, {'n': 1, 'card': think_twice}] formats = legality.legal_formats(d) assert len(legality.legal_formats(d)) == 0 d.maindeck = [{'n': 56, 'card': swamp}, {'n': 4, 'card': fork}] d.sideboard = [{'n': 15, 'card': swamp}] formats = legality.legal_formats(d) assert 'Legacy' in formats assert 'Modern' not in formats d.maindeck = [{'n': 60, 'card': swamp}] d.sideboard = [{'n': 15, 'card': swamp}] formats = legality.legal_formats(d) assert 'Standard' in formats assert 'Modern' in formats assert 'Legacy' in formats assert 'Vintage' in formats assert 'Penny Dreadful' in formats assert 'Penny Dreadful EMN' in formats
def test_legal_formats() -> None: d = Deck({'id': 0}) d.maindeck = [CardRef('Swamp', 59)] d.sideboard = [] assert len(d.all_cards()) == 59 formats = legality.legal_formats(d) assert len(formats) == 0 d.maindeck = [CardRef('Swamp', 60)] formats = legality.legal_formats(d) assert 'Penny Dreadful' in formats assert 'Legacy' in formats assert 'Penny Dreadful EMN' in formats formats = legality.legal_formats(d, {'Penny Dreadful'}) assert len(formats) == 1 assert 'Penny Dreadful' in formats assert 'Legacy' not in formats d.maindeck = [CardRef('Swamp', 55), CardRef('Think Twice', 5)] formats = legality.legal_formats(d) assert len(d.all_cards()) == 60 assert len(legality.legal_formats(d)) == 0 d.maindeck = [CardRef('Swamp', 56), CardRef('Think Twice', 4)] formats = legality.legal_formats(d) assert 'Legacy' in formats assert 'Modern' in formats d.sideboard = [CardRef('Swamp', 15), CardRef('Think Twice', 1)] formats = legality.legal_formats(d) assert len(legality.legal_formats(d)) == 0 d.maindeck = [CardRef('Swamp', 56), CardRef('Fork', 4)] d.sideboard = [CardRef('Swamp', 15)] formats = legality.legal_formats(d) assert 'Legacy' in formats assert 'Modern' not in formats d.maindeck = [CardRef('Swamp', 60)] d.sideboard = [CardRef('Swamp', 15)] formats = legality.legal_formats(d) assert 'Standard' in formats assert 'Modern' in formats assert 'Legacy' in formats assert 'Vintage' in formats assert 'Penny Dreadful' in formats assert 'Penny Dreadful EMN' in formats
def check_deck_legality(self) -> None: errors: Dict[str, Dict[str, Set[str]]] = {} if 'Penny Dreadful' not in legality.legal_formats( self.deck, None, errors): self.errors['decklist'] = ' '.join( errors.get('Penny Dreadful', {}).pop('Legality_General', ['Not a legal deck'])) self.card_errors = errors.get('Penny Dreadful', {}) banned_for_bugs = { c.name for c in self.deck.all_cards() if any([b.get('bannable', False) for b in c.bugs or []]) } playable_bugs = { c.name for c in self.deck.all_cards() if c.pd_legal and any([not b.get('bannable', False) for b in c.bugs or []]) } if len(banned_for_bugs) > 0: self.errors[ 'decklist'] = 'Deck contains cards with game-breaking bugs' self.card_errors['Legality_Bugs'] = banned_for_bugs if len(playable_bugs) > 0: self.warnings['decklist'] = 'Deck contains playable bugs' self.card_warnings['Warnings_Bugs'] = playable_bugs
def check_deck_legality(self): errors = {} if 'Penny Dreadful' not in legality.legal_formats(self.deck, None, errors): self.errors['decklist'] = ' '.join(errors.get('Penny Dreadful').pop('Legality_General', ['You have illegal cards.'])) self.card_errors = errors.get('Penny Dreadful') banned_for_bugs = set([c.name for c in self.deck.all_cards() if any([b.get('bannable') for b in c.bugs or []])]) if len(banned_for_bugs) > 0: self.card_errors['Legality_Bugs'] = [name for name in banned_for_bugs]
def scrape(limit: int = 255) -> None: page = 1 while page <= limit: time.sleep(0.1) url = 'https://www.mtggoldfish.com/deck/custom/penny_dreadful?page={n}#online'.format( n=page) soup = BeautifulSoup( fetcher.internal.fetch(url, character_encoding='utf-8'), 'html.parser') raw_decks = soup.find_all('div', {'class': 'deck-tile'}) if len(raw_decks) == 0: logger.warning( 'No decks found in {url} so stopping.'.format(url=url)) break for raw_deck in raw_decks: d = Container({'source': 'MTG Goldfish'}) a = raw_deck.select_one('h2 > span.deck-price-online > a') d.identifier = re.findall(r'/deck/(\d+)#online', a.get('href'))[0] d.url = 'https://www.mtggoldfish.com/deck/{identifier}#online'.format( identifier=d.identifier) d.name = a.contents[0].strip() d.mtggoldfish_username = raw_deck.select_one( 'div.deck-tile-author').contents[0].strip() remove_by = re.match(r'^(by )?(.*)$', d.mtggoldfish_username) if remove_by: d.mtggoldfish_username = remove_by.group(2) d.created_date = scrape_created_date(d) time.sleep(1) d.cards = scrape_decklist(d) try: vivified = decklist.vivify(d.cards) # MTGG doesn't do any validation of cards so some decks with fail here with card names like 'Stroke of Genuineness'. except InvalidDataException as e: logger.warning( 'Rejecting decklist of deck with identifier {identifier} because of {e}' .format(identifier=d.identifier, e=e)) continue if len([ f for f in legality.legal_formats(vivified) if 'Penny Dreadful' in f ]) == 0: logger.warning( 'Rejecting deck with identifier {identifier} because it is not legal in any PD formats.' .format(identifier=d.identifier)) continue if len(d.cards) == 0: logger.warning( 'Rejecting deck with identifier {identifier} because it has no cards.' .format(identifier=d.identifier)) continue deck.add_deck(d) page += 1
def vivify_or_error(d: Container) -> str: try: vivified = decklist.vivify(d.cards) # MTGG doesn't do any validation of cards so some decks with fail here with card names like 'Stroke of Genuineness'. except InvalidDataException as e: return 'Rejecting decklist of deck with identifier {identifier} because of {e}'.format( identifier=d.identifier, e=e) if len( [f for f in legality.legal_formats(vivified) if 'Penny Dreadful' in f]) == 0: return 'Rejecting deck with identifier {identifier} because it is not legal in any PD formats.'.format( identifier=d.identifier) if len(d.cards) == 0: return 'Rejecting deck with identifier {identifier} because it has no cards.'.format( identifier=d.identifier) return ''
def scrape_url(url: str) -> deck.Deck: if not url.endswith('/'): url += '/' path = urllib.parse.urlparse(url).path slug = path.split('/')[2] raw_deck: RawDeckType = {} raw_deck['slug'] = slug raw_deck['url'] = url if is_authorised(): raw_deck.update(fetch_deck_details(raw_deck)) # type: ignore else: raw_deck.update(parse_printable(raw_deck)) # type: ignore raw_deck = set_values(raw_deck) vivified = decklist.vivify(raw_deck['cards']) errors: Dict[str, Dict[str, Set[str]]] = {} if 'Penny Dreadful' not in legality.legal_formats(vivified, None, errors): raise InvalidDataException('Deck is not legal in Penny Dreadful - {error}'.format(error=errors.get('Penny Dreadful'))) return deck.add_deck(raw_deck)
def scrape_url(url): if not url.endswith('/'): url += '/' path = urllib.parse.urlparse(url).path slug = path.split('/')[2] raw_deck = dict() raw_deck['slug'] = slug raw_deck['url'] = url if is_authorised(): raw_deck.update(fetch_deck_details(raw_deck)) else: raw_deck.update(parse_printable(raw_deck)) raw_deck = set_values(raw_deck) vivified = decklist.vivify(raw_deck['cards']) if 'Penny Dreadful' not in legality.legal_formats(vivified): raise InvalidDataException('Deck is not legal in Penny Dreadful') else: return deck.add_deck(raw_deck)
def do_validation(self): if len(self.mtgo_username) == 0: self.errors['mtgo_username'] = "******" elif active_decks_by(self.mtgo_username.strip()): self.errors[ 'mtgo_username'] = "******" if len(self.name.strip()) == 0: self.errors['name'] = 'Deck Name is required' else: self.source = 'League' self.competition_id = db().value(active_competition_id_query()) self.identifier = identifier(self) self.url = url_for('competitions', competition_id=self.competition_id) self.decklist = self.decklist.strip() if len(self.decklist) == 0: self.errors['decklist'] = 'Decklist is required' else: self.cards = None if self.decklist.startswith('<?xml'): try: self.cards = decklist.parse_xml(self.decklist) except InvalidDataException as e: self.errors[ 'decklist'] = 'Unable to read .dek decklist. Try exporting from MTGO as Text and pasting the result.'.format( specific=str(e)) else: try: self.cards = decklist.parse(self.decklist) except InvalidDataException as e: self.errors[ 'decklist'] = '{specific}. Try exporting from MTGO as Text and pasting the result.'.format( specific=str(e)) if self.cards is not None: try: vivified = decklist.vivify(self.cards) errors = {} if 'Penny Dreadful' not in legality.legal_formats( vivified, None, errors): self.errors[ 'decklist'] = 'Deck is not legal in Penny Dreadful - {error}'.format( error=errors.get('Penny Dreadful')) except InvalidDataException as e: self.errors['decklist'] = str(e)
def check_deck_legality(self): errors = {} if 'Penny Dreadful' not in legality.legal_formats( self.deck, None, errors): self.errors[ 'decklist'] = 'Deck is not legal in Penny Dreadful - {error}'.format( error=errors.get('Penny Dreadful')) else: banned_for_bugs = set([ c.name for c in self.deck.all_cards() if any([b.get('bannable') for b in c.bugs or []]) ]) if len(banned_for_bugs) == 1: self.errors[ 'decklist'] = '{name} is currently not allowed because of a game-breaking Magic Online bug'.format( name=next(iter(banned_for_bugs))) if len(banned_for_bugs) > 1: self.errors[ 'decklist'] = '{names} are currently not allowed because of game-breaking Magic Online bugs'.format( names=', '.join([name for name in banned_for_bugs]))
def set_legality(d: Deck) -> None: d.legal_formats = legality.legal_formats(d)
def set_legality(d): d.legal_formats = legality.legal_formats(d)