def normalize(d: Deck) -> str: try: name = d.original_name name = name.lower() name = replace_space_alternatives(name) name = remove_pd(name) name = remove_hashtags(name) name = remove_brackets(name) name = strip_leading_punctuation(name) name = remove_leading_deck(name) unabbreviated = expand_common_abbreviations(name) if unabbreviated != name or name in ABBREVIATIONS.values(): name = unabbreviated elif whitelisted(name): pass elif name and d.get('archetype_name') and name == d.get('archetype_name', '').lower(): pass else: name = add_colors_if_no_deckname(name, d.get('colors')) name = normalize_colors(name) name = add_archetype_if_just_colors(name, d.get('archetype_name')) name = remove_mono_if_not_first_word(name) name = remove_profanity(name) name = ucase_trailing_roman_numerals(name) name = titlecase.titlecase(name) return correct_case_of_color_names(name) except ValueError: raise InvalidDataException('Failed to normalize {d}'.format(d=repr(d)))
def set_stars_and_top8(d: Deck) -> None: if d.finish == 1 and d.competition_top_n >= 1: d.top8_safe = '<span title="Winner">①</span>' d.stars_safe = '★★★' elif d.finish == 2 and d.competition_top_n >= 2: d.top8_safe = '<span title="Losing Finalist">②</span>' d.stars_safe = '★★' elif d.finish == 3 and d.competition_top_n >= 3: d.top8_safe = '<span title="Losing Semifinalist">④</span>' d.stars_safe = '★★' elif d.finish == 5 and d.competition_top_n >= 5: d.top8_safe = '<span title="Losing Quarterfinalist">⑧</span>' d.stars_safe = '★' else: d.top8_safe = '' if d.get('wins') is not None and d.get('losses') is not None: if d.wins - 5 >= d.losses: d.stars_safe = '★★' elif d.wins - 3 >= d.losses: d.stars_safe = '★' else: d.stars_safe = '' else: d.stars_safe = '' if len(d.stars_safe) > 0: d.stars_safe = '<span class="stars" title="Success Rating">{stars}</span>'.format( stars=d.stars_safe)
def prepare_deck(self, d: Deck) -> None: set_stars_and_top8(d) if d.get('colors') is not None: d.colors_safe = colors_html(d.colors, d.colored_symbols) d.person_url = '/people/{id}/'.format(id=d.person_id) d.date_sort = dtutil.dt2ts(d.active_date) d.display_date = dtutil.display_date(d.active_date) d.show_record = d.wins or d.losses or d.draws if d.competition_id: d.competition_url = '/competitions/{id}/'.format(id=d.competition_id) d.url = '/decks/{id}/'.format(id=d.id) d.export_url = '/export/{id}/'.format(id=d.id) d.cmc_chart_url = '/charts/cmc/{id}-cmc.png'.format(id=d.id) if d.is_in_current_run(): d.active_safe = '<span class="active" title="Active in the current league">⊕</span>' d.stars_safe = '{active} {stars}'.format(active=d.active_safe, stars=d.stars_safe).strip() d.source_sort = '1' d.source_is_external = not d.source_name == 'League' d.comp_row_len = len('{comp_name} (Piloted by {person}'.format(comp_name=d.competition_name, person=d.person)) if d.get('archetype_id', None): d.archetype_url = '/archetypes/{id}/'.format(id=d.archetype_id) # We might be getting '43%'/'' from cache or '43'/None from the db. Cope with all possibilities. # It might be better to use display_omw and omw as separate properties rather than overwriting the numeric value. if d.get('omw') is None or d.omw == '': d.omw = '' elif '%' not in str(d.omw): d.omw = str(int(d.omw)) + '%' d.has_legal_format = len(d.legal_formats) > 0 d.pd_legal = 'Penny Dreadful' in d.legal_formats d.legal_icons = '' sets = rotation.SEASONS if 'Penny Dreadful' in d.legal_formats: icon = rotation.current_season_code().lower() n = sets.index(icon.upper()) + 1 d.legal_icons += '<a href="{url}"><i class="ss ss-{code} ss-rare ss-grad">S{n}</i></a>'.format(url='/seasons/{id}/'.format(id=n), code=icon, n=n) past_pd_formats = [fmt.replace('Penny Dreadful ', '') for fmt in d.legal_formats if 'Penny Dreadful ' in fmt] past_pd_formats.sort(key=lambda code: -sets.index(code)) for code in past_pd_formats: n = sets.index(code.upper()) + 1 d.legal_icons += '<a href="{url}"><i class="ss ss-{set} ss-common ss-grad">S{n}</i></a>'.format(url='/seasons/{id}/'.format(id=n), set=code.lower(), n=n) if 'Commander' in d.legal_formats: # I think C16 looks the nicest. d.legal_icons += '<i class="ss ss-c16 ss-uncommon ss-grad">CMDR</i>' if session.get('admin') or session.get('demimod') or not d.is_in_current_run(): d.decklist = str(d).replace('\n', '<br>') else: d.decklist = '' total, num_cards = 0, 0 for c in d.maindeck: if c.card.cmc is None: c.card.cmc = 0 if 'Land' not in c.card.type_line: num_cards += c['n'] total += c['n'] * c.card.cmc d.average_cmc = round(total / max(1, num_cards), 2)
def prepare_deck(d: Deck) -> None: set_stars_and_top8(d) if d.get('colors') is not None: d.colors_safe = colors_html(d.colors, d.colored_symbols) if d.get('mtgo_username'): d.person_url = f'/people/{d.mtgo_username}/' else: d.person_url = f'/people/id/{d.person_id}/' d.date_sort = dtutil.dt2ts(d.active_date) d.display_date = dtutil.display_date(d.active_date) d.show_record = d.wins or d.losses or d.draws if d.competition_id: d.competition_url = '/competitions/{id}/'.format(id=d.competition_id) d.url = '/decks/{id}/'.format(id=d.id) d.export_url = '/export/{id}/'.format(id=d.id) d.cmc_chart_url = '/charts/cmc/{id}-cmc.png'.format(id=d.id) if d.is_in_current_run(): d.active_safe = '<span class="active" title="Active in the current league">⊕</span>' d.stars_safe = '{active} {stars}'.format(active=d.active_safe, stars=d.stars_safe).strip() d.source_sort = '1' d.source_is_external = not d.source_name == 'League' d.comp_row_len = len('{comp_name} (Piloted by {person}'.format( comp_name=d.competition_name, person=d.person)) if d.get('archetype_id', None): d.archetype_url = '/archetypes/{id}/'.format(id=d.archetype_id) # We might be getting '43%'/'' from cache or '43'/None from the db. Cope with all possibilities. # It might be better to use display_omw and omw as separate properties rather than overwriting the numeric value. if d.get('omw') is None or d.omw == '': d.omw = '' elif '%' not in str(d.omw): d.omw = str(int(d.omw)) + '%' d.has_legal_format = len(d.legal_formats) > 0 d.pd_legal = 'Penny Dreadful' in d.legal_formats d.non_pd_legal_formats = { f for f in d.legal_formats if 'Penny Dreadful' not in f } set_legal_icons(d) if session.get('admin') or session.get( 'demimod') or not d.is_in_current_run(): d.decklist = str(d) else: d.decklist = '' total, num_cards = 0, 0 for c in d.maindeck: if c.card.cmc is None: c.card.cmc = 0 if 'Land' not in c.card.type_line: num_cards += c['n'] total += c['n'] * c.card.cmc d.average_cmc = round(total / max(1, num_cards), 2)
def deserialize_deck(sdeck: Container) -> Deck: deck = Deck(sdeck) deck.active_date = dtutil.ts2dt(deck.active_date) deck.created_date = dtutil.ts2dt(deck.created_date) deck.updated_date = dtutil.ts2dt(deck.updated_date) if deck.competition_end_date is not None: deck.competition_end_date = dtutil.ts2dt(deck.competition_end_date) deck.wins = int(deck.wins) deck.losses = int(deck.losses) deck.draws = int(deck.draws) if deck.get('omw') is not None: deck.omw = float(deck.omw) deck.maindeck = [CardRef(ref['name'], ref['n']) for ref in deck.maindeck] deck.sideboard = [CardRef(ref['name'], ref['n']) for ref in deck.sideboard] return deck
def prize(d: Deck) -> int: return prize_by_finish(d.get('finish') or sys.maxsize)