Ejemplo n.º 1
0
 def __init__(self, stats: Dict[int, Dict[str, Union[int, datetime.datetime]]]) -> None:
     super().__init__()
     seasons = self.all_seasons()
     seasons.pop()  # Don't show "all time" on this page as it is not fully supported yet.
     cards_count: Dict[str, int] = {}
     for c in oracle.CARDS_BY_NAME.values():
         for f, is_legal in c.legalities.items():
             if is_legal and 'Penny Dreadful' in f:
                 cards_count[f] = cards_count.get(f, 0) + 1
     self.seasons: List[Dict[str, Any]] = []
     for season_info in seasons:
         season: Dict[str, Any] = {}
         season.update(season_info)
         season_stats = stats.get(cast(int, season['num']), {})
         season.update(season_stats)
         if season.get('start_date') is None:
             continue
         season['num_legal_cards'] = cards_count[str(season_info['legality_name'])]
         for k, v in season.items():
             if isinstance(v, int):
                 season[k] = '{:,}'.format(v)  # Human-friendly number formatting like "29,000".
         season['start_date_display'] = dtutil.display_date(season['start_date'])
         season['length_in_days'] = season['length_in_days'] + ' days'
         if season.get('end_date'):
             season['end_date_display'] = dtutil.display_date(season['end_date'])
         else:
             season['end_date_display'] = 'Now'
             season['length_in_days'] += ' so far'
         self.seasons.append(season)
Ejemplo n.º 2
0
 def __init__(
         self, stats: Dict[int, Dict[str,
                                     Union[int,
                                           datetime.datetime]]]) -> None:
     super().__init__()
     seasons = self.all_seasons()
     seasons.pop(
     )  # Don't show "all time" on this page as it is not fully supported yet.
     self.seasons: List[Dict[str, Any]] = []
     for season_info in seasons:
         season: Dict[str, Any] = {}
         season.update(season_info)
         season_stats = stats.get(cast(int, season['num']), {})
         season.update(season_stats)
         if season.get('start_date') is None:
             continue
         for k, v in season.items():
             if isinstance(v, int):
                 season[k] = '{:,}'.format(
                     v)  # Human-friendly number formatting like "29,000".
         season['start_date_display'] = dtutil.display_date(
             season['start_date'])
         season['length_in_days'] = season['length_in_days'] + ' days'
         if season.get('end_date'):
             season['end_date_display'] = dtutil.display_date(
                 season['end_date'])
         else:
             season['end_date_display'] = 'Now'
             season['length_in_days'] += ' so far'
         self.seasons.append(season)
Ejemplo n.º 3
0
 def prepare_competitions(self):
     for c in getattr(self, 'competitions', []):
         c.competition_url = url_for('competition', competition_id=c.id)
         c.display_date = dtutil.display_date(c.start_date)
         c.ends = '' if c.end_date < dtutil.now() else dtutil.display_date(
             c.end_date)
         c.date_sort = dtutil.dt2ts(c.start_date)
Ejemplo n.º 4
0
 def __init__(self, interestingness: Optional[str] = None, rotation_query: Optional[str] = None, only_these: Optional[List[str]] = None) -> None:
     super().__init__()
     self.playability = card.playability()
     until_full_rotation = rotation.next_rotation() - dtutil.now()
     until_supplemental_rotation = rotation.next_supplemental() - dtutil.now()
     in_rotation = configuration.get_bool('always_show_rotation')
     if until_full_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Full rotation is in progress, ends ' + dtutil.display_date(rotation.next_rotation(), 2)
     elif until_supplemental_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Supplemental rotation is in progress, ends ' + dtutil.display_date(rotation.next_supplemental(), 2)
     elif until_full_rotation < until_supplemental_rotation:
         self.rotation_msg = 'Full rotation is ' + dtutil.display_date(rotation.next_rotation(), 2)
     else:
         self.rotation_msg = 'Supplemental rotation is ' + dtutil.display_date(rotation.next_supplemental(), 2)
     self.cards: List[Card] = []
     if in_rotation:
         self.read_rotation_files()
     self.show_interesting = True
     if interestingness:
         self.cards = [c for c in self.cards if c.get('interestingness') == interestingness]
     if only_these:
         self.cards = [c for c in self.cards if c.name in only_these]
     self.num_cards = len(self.cards)
     self.rotation_query = rotation_query or ''
Ejemplo n.º 5
0
 def __init__(self, interestingness: Optional[str] = None, query: Optional[str] = '') -> None:
     super().__init__()
     until_rotation = seasons.next_rotation() - dtutil.now()
     in_rotation = configuration.get_bool('always_show_rotation')
     if until_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Rotation is in progress, ends ' + dtutil.display_date(seasons.next_rotation(), 2)
     else:
         self.rotation_msg = 'Rotation is ' + dtutil.display_date(seasons.next_rotation(), 2)
     if in_rotation:
         self.in_rotation = in_rotation
         self.show_interestingness_filter = True
         self.runs, self.runs_percent, self.cards = rotation.read_rotation_files()
         # Now add interestingness to the cards, which only decksite knows not magic.rotation.
         playability = card.playability()
         c: Card
         for c in self.cards:
             c.interestingness = rotation.interesting(playability, c)
     else:
         self.cards = []
     self.show_interesting = True
     if interestingness:
         self.cards = [c for c in self.cards if c.get('interestingness') == interestingness]
     self.num_cards = len(self.cards)
     self.query = query
     self.show_filters_toggle = True
     self.cards = [c for c in self.cards if visible(c)]
Ejemplo n.º 6
0
 def __init__(self) -> None:
     super().__init__()
     self.playability = card.playability()
     until_full_rotation = rotation.next_rotation() - dtutil.now()
     until_supplemental_rotation = rotation.next_supplemental(
     ) - dtutil.now()
     in_rotation = False
     if until_full_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Full rotation is in progress, ends ' + dtutil.display_date(
             rotation.next_rotation(), 2)
     elif until_supplemental_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Supplemental rotation is in progress, ends ' + dtutil.display_date(
             rotation.next_supplemental(), 2)
     elif until_full_rotation < until_supplemental_rotation:
         self.rotation_msg = 'Full rotation is ' + dtutil.display_date(
             rotation.next_rotation(), 2)
     else:
         self.rotation_msg = 'Supplemental rotation is ' + dtutil.display_date(
             rotation.next_supplemental(), 2)
     self.cards: List[Card] = []
     if in_rotation:
         self.read_rotation_files()
     self.show_interesting = True
Ejemplo n.º 7
0
 def setup_rotation(self) -> None:
     self.season_start_display = dtutil.display_date(seasons.last_rotation())
     self.season_end_display = dtutil.display_date(seasons.next_rotation())
     self.scryfall_url = 'https://scryfall.com/search?q=f%3Apd'
     self.legal_cards_url = 'http://pdmtgo.com/legal_cards.txt'
     self.in_rotation = rotation.in_rotation()
     self.rotation_msg = 'Rotation is in progress.'
     self.rotation_url = url_for('rotation')
Ejemplo n.º 8
0
 def prepare_competitions(self) -> None:
     for c in getattr(self, 'competitions', []):
         c.competition_url = '/competitions/{id}/'.format(id=c.id)
         c.display_date = dtutil.display_date(c.start_date)
         c.competition_ends = '' if c.end_date < dtutil.now() else dtutil.display_date(c.end_date)
         c.date_sort = dtutil.dt2ts(c.start_date)
         c.league = c.type == 'League'
         title_safe = ''
         try:
             for k, v in c.base_archetypes_data().items():
                 if v > 0:
                     title_safe += '{v} {k}<br>'.format(v=v, k=html.escape(k))
         except KeyError:
             archetype.rebuild_archetypes()
Ejemplo n.º 9
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
Ejemplo n.º 10
0
def all_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()
    news: List[Container] = []
    news += load_news(start_date, end_date, max_items)
    news += tournament_winners(start_date, end_date, max_items)
    news += perfect_league_runs(start_date, end_date, max_items)
    news += code_merges(start_date, end_date, max_items)
    news += subreddit(start_date, end_date, max_items)
    news = sorted(news, key=lambda item: item.date, reverse=True)
    results = []
    for item in news:
        if item.date > end_date:
            continue
        if item.date < start_date:
            break
        item.display_date = dtutil.display_date(item.date)
        results.append(item)
        if len(results) >= max_items:
            break
    return results
Ejemplo n.º 11
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
Ejemplo n.º 12
0
 def __init__(self, d):
     self._deck = d
     self.prepare_deck(self._deck)
     self.cards = d.all_cards()
     # This is called 'decks' and not something more sane because of limitations of Mustache and our desire to use a partial for decktable.
     self.decks = deck.get_similar_decks(d)
     self.has_similar = len(self.decks) > 0
     self.matches = deck.get_matches(d, True)
     for m in self.matches:
         m.display_date = dtutil.display_date(m.date)
         if m.opponent:
             m.opponent_url = url_for('person', person_id=m.opponent)
         else:
             m.opponent = 'BYE'
             m.opponent_url = False
         if m.opponent_deck_id:
             m.opponent_deck_url = url_for('decks',
                                           deck_id=m.opponent_deck_id)
         else:
             m.opponent_deck_url = False
         if m.opponent_deck:
             m.opponent_deck_name = deck_name.normalize(m.opponent_deck)
         else:
             m.opponent_deck_name = '-'
         if self.has_rounds():
             m.display_round = display_round(m)
     self._deck['maindeck'].sort(key=lambda x: oracle.deck_sort(x['card']))
     self._deck['sideboard'].sort(key=lambda x: oracle.deck_sort(x['card']))
     self.admin = session.get('admin', False)
     if self.admin:
         self.archetypes = archetype.load_archetypes_deckless(
             order_by='a.name')
         self.edit_archetype_url = url_for('edit_archetypes')
     self.cardhoarder_url = fetcher.cardhoarder_url(d)
Ejemplo n.º 13
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
Ejemplo n.º 14
0
 def __init__(self, notes: Iterable[Container],
              people: Iterable[Person]) -> None:
     super().__init__()
     for n in notes:
         n.date_sort = dtutil.dt2ts(n.created_date)
         n.display_date = dtutil.display_date(n.created_date)
     self.notes = notes
     self.people = people
Ejemplo n.º 15
0
 def __init__(self):
     until_full_rotation = rotation.next_rotation() - dtutil.now()
     until_supplemental_rotation = rotation.next_supplemental() - dtutil.now()
     in_rotation = False
     if until_full_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Full rotation is in progress, ends ' + dtutil.display_date(rotation.next_rotation(), 2)
     elif until_supplemental_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Supplemental rotation is in progress, ends ' + dtutil.display_date(rotation.next_supplemental(), 2)
     elif until_full_rotation < until_supplemental_rotation:
         self.rotation_msg = 'Full rotation is ' + dtutil.display_date(rotation.next_rotation(), 2)
     else:
         self.rotation_msg = 'Supplemental rotation is ' + dtutil.display_date(rotation.next_supplemental(), 2)
     if in_rotation:
         self.read_rotation_files()
     self.show_interesting = True
Ejemplo n.º 16
0
 def prepare_deck(self, d):
     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.date)
     d.display_date = dtutil.display_date(d.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 = False if d.source_name == 'League' else True
     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)
     if d.get('omw') is not None:
         d.omw = str(int(d.omw)) + '%'
     else:
         d.omw = ''
     d.has_legal_format = len(d.legal_formats) > 0
     d.pd_legal = 'Penny Dreadful' in d.legal_formats
     d.legal_icons = ''
     sets = multiverse.SEASONS
     if 'Penny Dreadful' in d.legal_formats:
         icon = rotation.last_rotation_ex()['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 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 'Land' not in c['card'].type:
             num_cards += c['n']
             total += c['n'] * c['card'].cmc
     d.average_cmc = round(total / max(1, num_cards), 2)
Ejemplo n.º 17
0
 def __init__(self) -> None:
     super().__init__()
     until_rotation = seasons.next_rotation() - dtutil.now()
     in_rotation = configuration.get_bool('always_show_rotation')
     if until_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Rotation is in progress, ends ' + dtutil.display_date(
             seasons.next_rotation(), 2)
     else:
         self.rotation_msg = 'Rotation is ' + dtutil.display_date(
             seasons.next_rotation(), 2)
     if in_rotation:
         self.in_rotation = in_rotation
         self.runs, self.runs_percent, self.cards = rotation.read_rotation_files(
         )
     else:
         self.cards = []
     self.num_cards = len(self.cards)
Ejemplo n.º 18
0
def test_display_date() -> None:
    dt = dtutil.parse('2008-03-29', '%Y-%m-%d', dtutil.WOTC_TZ)
    assert dtutil.display_date(dt) == 'Mar 2008'
    dt = dtutil.parse('2008-03-29 02:00', '%Y-%m-%d %H:%M', timezone('UTC'))
    assert dtutil.display_date(dt) == 'Mar 2008'
    dt = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=10)
    assert dtutil.display_date(dt).find('seconds ago') >= 0
    dt = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=72)
    assert dtutil.display_date(dt).find('days') >= 0
    assert dtutil.display_date(dt).find('from now') >= 0
    assert dtutil.display_date(dt).find('ago') == -1
    dt = datetime.datetime.now(datetime.timezone.utc)
    assert dtutil.display_date(dt).find('just now') >= 0
    assert dtutil.display_date(dt).find('from now') == -1
    dt = datetime.datetime.now(dtutil.WOTC_TZ) + datetime.timedelta(days=28, hours=15, minutes=35)
    assert dtutil.display_date(dt) == '4 weeks from now'
Ejemplo n.º 19
0
 def prepare_matches(self) -> None:
     for m in getattr(self, 'matches', []):
         if m.get('date'):
             m.display_date = dtutil.display_date(m.date)
             m.date_sort = dtutil.dt2ts(m.date)
         if m.get('deck_id'):
             m.deck_url = url_for('deck', deck_id=m.deck_id)
         if m.get('opponent'):
             m.opponent_url = url_for('person', person_id=m.opponent)
         if m.get('opponent_deck_id'):
             m.opponent_deck_url = url_for('deck', deck_id=m.opponent_deck_id)
Ejemplo n.º 20
0
 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)
Ejemplo n.º 21
0
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)
Ejemplo n.º 22
0
 def __init__(self, interestingness: Optional[str] = None, query: Optional[str] = '') -> None:
     super().__init__()
     until_full_rotation = rotation.next_rotation() - dtutil.now()
     until_supplemental_rotation = rotation.next_supplemental() - dtutil.now()
     in_rotation = configuration.get_bool('always_show_rotation')
     if until_full_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Full rotation is in progress, ends ' + dtutil.display_date(rotation.next_rotation(), 2)
     elif until_supplemental_rotation < datetime.timedelta(7):
         in_rotation = True
         self.rotation_msg = 'Supplemental rotation is in progress, ends ' + dtutil.display_date(rotation.next_supplemental(), 2)
     elif until_full_rotation < until_supplemental_rotation:
         self.rotation_msg = 'Full rotation is ' + dtutil.display_date(rotation.next_rotation(), 2)
     else:
         self.rotation_msg = 'Supplemental rotation is ' + dtutil.display_date(rotation.next_supplemental(), 2)
     if in_rotation:
         self.in_rotation = in_rotation
         self.show_interestingness_filter = True
         self.runs, self.runs_percent, self.cards = rotation.read_rotation_files()
         # Now add interestingness to the cards, which only decksite knows not magic.rotation.
         playability = card.playability()
         c: Card
         for c in self.cards:
             c.interestingness = rotation.interesting(playability, c)
     else:
         self.cards = []
     self.show_interesting = True
     if interestingness:
         self.cards = [c for c in self.cards if c.get('interestingness') == interestingness]
     self.num_cards = len(self.cards)
     self.query = query
     for c in self.cards:
         if c.status != 'Undecided':
             continue
         c.hits = redact(c.hits)
         c.hits_needed = redact(c.hits_needed)
         c.percent = redact(c.percent)
         c.percent_needed = redact(c.percent_needed)
     self.show_filters_toggle = True
Ejemplo n.º 23
0
 def __init__(self, competition: Comp) -> None:
     super().__init__()
     self.competition = competition
     self.competitions = [self.competition]
     self.decks = competition.decks
     self.hide_source = True
     self.has_external_source = competition.type != 'League'
     if competition.type == 'League':
         self.skinny_leaderboard = True  # Try and bunch it up on the right of decks table if at all possible.
         self.show_omw = True
         self.hide_top8 = True
         self.has_leaderboard = True
     self.date = dtutil.display_date(competition.start_date)
     self.sponsor_name = competition.sponsor_name
Ejemplo n.º 24
0
def report(form: ReportForm) -> bool:
    try:
        db().get_lock('deck_id:{id}'.format(id=form.entry))
        db().get_lock('deck_id:{id}'.format(id=form.opponent))

        for m in match.get_matches(form):
            if int(form.opponent) == m.opponent_deck_id:
                form.errors[
                    'result'] = 'This match was reported as You {game_wins}–{game_losses} {opponent} {date}'.format(
                        game_wins=m.game_wins,
                        game_losses=m.game_losses,
                        opponent=m.opponent,
                        date=dtutil.display_date(m.date))
                return False

        counts = deck.count_matches(form.entry, form.opponent)
        if counts[int(form.entry)] >= 5:
            form.errors['entry'] = 'You already have 5 matches reported'
            return False
        if counts[int(form.opponent)] >= 5:
            form.errors[
                'opponent'] = 'Your opponent already has 5 matches reported'
            return False
        pdbot = form.get('api_token',
                         None) == configuration.get('pdbot_api_token')
        if pdbot:
            mtgo_match_id = form.get('matchID', None)
        else:
            mtgo_match_id = None
            entry_name = deck.load_deck(int(form.entry)).person
            opp_name = deck.load_deck(int(form.opponent)).person
            fetcher.post_discord_webhook(
                configuration.get_str('league_webhook_id'),
                configuration.get_str('league_webhook_token'),
                '{entry} reported {f.entry_games}-{f.opponent_games} vs {opponent}'
                .format(f=form, entry=entry_name, opponent=opp_name))

        db().begin()
        match.insert_match(dtutil.now(), form.entry, form.entry_games,
                           form.opponent, form.opponent_games, None, None,
                           mtgo_match_id)
        db().commit()
        return True
    except LockNotAcquiredException:
        form.errors[
            'entry'] = 'Cannot report right now, somebody else is reporting a match for you or your opponent. Try again a bit later'
        return False
    finally:
        db().release_lock('deck_id:{id}'.format(id=form.opponent))
        db().release_lock('deck_id:{id}'.format(id=form.entry))
Ejemplo n.º 25
0
 def prepare_deck(self, d):
     set_stars_and_top8(d)
     if d.get('colors') is not None:
         d.colors_safe = colors_html(d.colors, d.colored_symbols)
         d.name = deck_name.normalize(d)
     d.person_url = url_for('person', person_id=d.person_id)
     d.date_sort = dtutil.dt2ts(d.date)
     d.display_date = dtutil.display_date(d.date)
     d.show_record = d.wins or d.losses or d.draws
     if d.competition_id:
         d.competition_url = url_for('competition',
                                     competition_id=d.competition_id)
     d.url = url_for('decks', deck_id=d.id)
     d.export_url = url_for('export', deck_id=d.id)
     d.cmc_chart_url = url_for('cmc_chart', deck_id=d.id)
     if d.source_name == 'League' and d.wins + d.losses < 5 and d.competition_end_date > dtutil.now(
     ) and not d.get('retired', False):
         d.stars_safe = '<span title="Active in the current league">⊕</span> {stars}'.format(
             stars=d.stars_safe).strip()
         d.source_sort = '1'
     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 = url_for('archetype', archetype_id=d.archetype_id)
     if d.omw is not None:
         d.omw = str(int(d.omw)) + '%'
     else:
         d.omw = ''
     d.has_legal_format = len(d.legal_formats) > 0
     d.pd_legal = 'Penny Dreadful' in d.legal_formats
     d.legal_icons = ''
     sets = legality.SEASONS
     if 'Penny Dreadful' in d.legal_formats:
         icon = rotation.last_rotation_ex()['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=url_for('season', season_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=url_for('season', season_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>'
     d.decklist = str(d).replace('\n', '<br>')
Ejemplo n.º 26
0
 def prepare_matches(self) -> None:
     for m in getattr(self, 'matches', []):
         if m.get('date'):
             m.display_date = dtutil.display_date(m.date)
             m.date_sort = dtutil.dt2ts(m.date)
         if m.get('deck_id'):
             m.deck_url = url_for('deck', deck_id=m.deck_id)
         if m.get('opponent'):
             m.opponent_url = url_for('.person', person_id=m.opponent)
         if m.get('opponent_deck_id'):
             m.opponent_deck_url = url_for('deck',
                                           deck_id=m.opponent_deck_id)
         if m.get('mtgo_id'):
             m.log_url = fetcher.logsite_url(
                 '/match/{id}/'.format(id=m.get('mtgo_id')))
 def __init__(self, matches) -> None:
     super().__init__()
     self.matches = matches
     if matches:
         deck_ids = [m.left_id for m in self.matches] + [m.right_id for m in self.matches if m.right_id is not None]
         decks_by_id = {int(d.id): d for d in deck.load_decks('d.id IN ({deck_ids})'.format(deck_ids=', '.join(deck_ids)))}
         for m in self.matches:
             m.display_date = dtutil.display_date(m.date)
             m.left_deck = decks_by_id.get(int(m.left_id))
             m.right_deck = decks_by_id.get(int(m.right_id))
             m.left_url = url_for('deck', deck_id=m.left_id)
             if m.get('right_url'):
                 m.right_url = url_for('deck', deck_id=m.right_id)
             else:
                 m.right_url = None
Ejemplo n.º 28
0
 def __init__(self, decks: List[Deck], matches: List[Container]) -> None:
     super().__init__()
     self.matches = matches
     self.hide_active_runs = False
     self.decks = sorted(decks,
                         key=lambda d: d.person + str(d.created_date))
     decks_by_id = {d.id: d for d in decks}
     for m in self.matches:
         m.display_date = dtutil.display_date(m.date)
         m.left_deck = decks_by_id.get(int(m.left_id))
         m.right_deck = decks_by_id.get(int(m.right_id))
         m.left_url = url_for('deck', deck_id=m.left_id)
         if m.get('right_id'):
             m.right_url = url_for('deck', deck_id=m.right_id)
         else:
             m.right_url = None
Ejemplo n.º 29
0
def prepare_matches(ms: Sequence[Container]) -> None:
    for m in ms:
        if m.get('date'):
            m.display_date = dtutil.display_date(m.date)
            m.date_sort = dtutil.dt2ts(m.date)
        if m.get('person'):
            m.person_url = url_for('person', mtgo_username=m.person)
        if m.get('deck_id'):
            m.deck_url = url_for('deck', deck_id=m.deck_id)
        if m.get('opponent'):
            m.opponent_url = url_for('.person', mtgo_username=m.opponent)
        if m.get('opponent_deck_id'):
            m.opponent_deck_url = url_for('deck', deck_id=m.opponent_deck_id)
        if m.get('mtgo_id'):
            m.log_url = fetcher.logsite_url(
                '/match/{id}/'.format(id=m.get('mtgo_id')))
Ejemplo n.º 30
0
 def __init__(self,
              d: deck.Deck,
              person_id: Optional[int] = None,
              discord_id: Optional[int] = None) -> None:
     super().__init__()
     self.deck = d
     self.prepare_deck(self.deck)
     self.cards = d.all_cards()
     if not self.deck.is_in_current_run():
         deck.load_similar_decks([d])
         # This is called 'decks' and not something more sane because of limitations of Mustache and our desire to use a partial for decktable.
         self.decks = [
             sd for sd in d.similar_decks if not sd.is_in_current_run()
         ]
     else:
         self.decks = []
     self.has_similar = len(self.decks) > 0
     self.matches = match.get_matches(d, True)
     for m in self.matches:
         m.display_date = dtutil.display_date(m.date)
         if m.opponent:
             m.opponent_url = url_for('person', person_id=m.opponent)
         else:
             m.opponent = 'BYE'
             m.opponent_url = False
         if m.opponent_deck_id:
             m.opponent_deck_url = url_for('deck',
                                           deck_id=m.opponent_deck_id)
         else:
             m.opponent_deck_url = False
         if m.opponent_deck and m.opponent_deck.is_in_current_run():
             m.opponent_deck_name = '(Active League Run)'
         elif m.opponent_deck:
             m.opponent_deck_name = m.opponent_deck.name
         else:
             m.opponent_deck_name = '-'
         if self.has_rounds():
             m.display_round = display_round(m)
     self.deck['maindeck'].sort(key=lambda x: oracle.deck_sort(x['card']))
     self.deck['sideboard'].sort(key=lambda x: oracle.deck_sort(x['card']))
     self.archetypes = archetype.load_archetypes_deckless(order_by='a.name')
     self.edit_archetype_url = url_for('edit_archetypes')
     self.legal_formats = list(
         sorted(d.legal_formats, key=legality.order_score))
     self.is_in_current_run = d.is_in_current_run()
     self.person_id = person_id
     self.discord_id = discord_id