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 m.date, round """.format(person_query=query.person_query()) matches = [Container(m) for m in db().execute(sql, [d.id, d.id])] if should_load_decks: opponents = [m.opponent_deck_id for m in matches if m.opponent_deck_id is not None] if len(opponents) > 0: decks = deck.load_decks('d.id IN ({ids})'.format(ids=', '.join([sqlescape(str(deck_id)) for deck_id in opponents]))) else: decks = [] 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
def person_status(): r = { 'mtgo_username': auth.mtgo_username(), 'discord_id': auth.discord_id(), 'admin': session.get('admin', False), 'demimod': session.get('demimod', False), 'hide_intro': request.cookies.get('hide_intro', False) or auth.hide_intro() or auth.mtgo_username() or auth.discord_id(), 'in_guild': session.get('in_guild', False), } if auth.mtgo_username(): d = guarantee_at_most_one_or_retire( league.active_decks_by(auth.mtgo_username())) if d is not None: r['deck'] = { 'name': d.name, 'url': url_for('deck', deck_id=d.id), 'wins': d.get('wins', 0), 'losses': d.get('losses', 0) } if r['admin'] or r['demimod']: r['archetypes_to_tag'] = len(deck.load_decks('NOT d.reviewed')) return return_json(r)
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_archetypes(where='1 = 1', merge=False): decks = deck.load_decks(where) archetypes = {} for d in decks: if d.archetype_id is None: continue key = 'merge' if merge else d.archetype_id archetype = archetypes.get(key, Archetype()) archetype.id = d.archetype_id archetype.name = d.archetype_name archetype.decks = archetype.get('decks', []) + [d] archetype.all = archetype.get('all', Archetype()) archetype.season = archetype.all.get('season', Archetype()) archetype.all.wins = archetype.all.get('wins', 0) + (d.get('wins') or 0) archetype.all.losses = archetype.all.get('losses', 0) + (d.get('losses') or 0) archetype.all.draws = archetype.all.get('draws', 0) + (d.get('draws') or 0) if d.created_date >= rotation.last_rotation(): archetype.season.wins = archetype.season.get( 'wins', 0) + (d.get('wins') or 0) archetype.season.losses = archetype.season.get( 'losses', 0) + (d.get('losses') or 0) archetype.season.draws = archetype.season.get( 'draws', 0) + (d.get('draws') or 0) archetypes[key] = archetype archetypes = list(archetypes.values()) return archetypes
def active_decks(additional_where: str = 'TRUE') -> List[deck.Deck]: where = """ d.id IN ( SELECT id FROM deck WHERE competition_id = ({active_competition_id_query}) ) AND ( SELECT COUNT(id) FROM deck_match AS dm WHERE dm.deck_id = d.id ) <= 4 AND NOT d.retired AND ({additional_where}) """.format(active_competition_id_query=active_competition_id_query(), additional_where=additional_where) decks = deck.load_decks(where) return sorted(decks, key=lambda d: '{person}{deck}'.format( person=d.person.ljust(100), deck=d.name))
def load_archetypes(where: str = '1 = 1', merge: bool = False, season_id: int = None) -> List[Archetype]: decks = deck.load_decks(where, season_id=season_id) archetypes: Dict[str, Archetype] = {} for d in decks: if d.archetype_id is None: continue key = 'merge' if merge else d.archetype_id archetype = archetypes.get(key, Archetype()) archetype.id = d.archetype_id archetype.name = d.archetype_name archetype.decks = archetype.get('decks', []) + [d] archetype.all_wins = archetype.get('all_wins', 0) + (d.get('all_wins') or 0) archetype.all_losses = archetype.get('all_losses', 0) + (d.get('all_losses') or 0) archetype.all_draws = archetype.get('all_draws', 0) + (d.get('all_draws') or 0) if d.get('finish') == 1: archetype.all_tournament_wins = archetype.get('all_tournament_wins', 0) + 1 if (d.get('finish') or sys.maxsize) <= 8: archetype.all_top8s = archetype.get('all_top8s', 0) + 1 archetype.all_perfect_runs = archetype.get('all_perfect_runs', 0) + 1 if d.active_date >= rotation.last_rotation(): archetype.season_wins = archetype.get('season_wins', 0) + (d.get('season_wins') or 0) archetype.season_losses = archetype.get('season_losses', 0) + (d.get('season_losses') or 0) archetype.season_draws = archetype.get('season_draws', 0) + (d.get('season_draws') or 0) if d.get('finish') == 1: archetype.season_tournament_wins = archetype.get('season_tournament_wins', 0) + 1 if (d.get('finish') or sys.maxsize) <= 8: archetype.season_top8s = archetype.get('season_top8s', 0) + 1 if d.source_name == 'League' and d.wins >= 5 and d.losses == 0: archetype.season_perfect_runs = archetype.get('season_all_perfect_runs', 0) + 1 archetypes[key] = archetype archetype_list = list(archetypes.values()) return archetype_list
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 ad_hoc() -> None: try: start = dtutil.parse(sys.argv[2], '%Y-%m-%d', dtutil.GATHERLING_TZ) except (IndexError, TypeError, ValueError): start = dtutil.now() - datetime.timedelta(days=7) print( f'Checking all Gatherling decks from {start}. To check from a different date supply it as a commandline arg in the form YYYY-MM-DD' ) decks = deck.load_decks( f"d.created_date >= UNIX_TIMESTAMP('{start}') AND ct.name = 'Gatherling'" ) print(f'Found {len(decks)} decks.') searcher = WhooshSearcher() for d in decks: comments = fetcher.gatherling_deck_comments(d) for c in comments: if '=' not in c: print(f'Ignoring {c}') continue print(c) def best_match_f(s: str) -> Optional[str]: return searcher.search(s.strip()).get_best_match() placeholder, real = map(best_match_f, c.split('=')) print( f'I think this means replace {placeholder} with {real}. Go ahead? (Y/n)' ) answer = input() if answer == '' or answer.lower() == 'y': rows_affected = db().execute( 'UPDATE deck_card SET card = %s WHERE deck_id = %s AND card = %s', [real, d.id, placeholder]) print(f'{rows_affected} rows were updated.')
def __init__(self, archetypes: List[Archetype], search_results: List[Deck], q: str, notq: str) -> None: super().__init__() self.archetypes = archetypes self.archetypes_preordered = archetype.preorder(archetypes) self.queue = deck.load_decks(where='NOT d.reviewed', order_by='updated_date DESC') deck.load_queue_similarity(self.queue) rule.apply_rules_to_decks(self.queue) for d in self.queue: prepare.prepare_deck(d) d.archetype_url = url_for('.archetype', archetype_id=d.archetype_name) if d.get('rule_archetype_name'): d.rule_archetype_url = url_for( '.archetype', archetype_id=d.rule_archetype_name) d.archetypes = [] for a in self.archetypes: if a.id == d.rule_archetype_id: d.archetypes.append({ 'id': a.id, 'name': a.name, 'selected': True }) else: d.archetypes.append(a) self.has_search_results = len(search_results) > 0 self.search_results = search_results for d in self.search_results: prepare.prepare_deck(d) self.query = q self.notquery = notq
def overlooked_decks() -> List[Deck]: sql = """ SELECT deck.id as deck_id FROM deck LEFT JOIN _applied_rules ON deck.id = _applied_rules.deck_id WHERE deck.created_date < UNIX_TIMESTAMP(NOW() - INTERVAL 1 DAY) -- Very new decks won't be in _applied_rules yet, but that doesn't mean they have been overlooked just that the caching hasn't run since they were created. AND _applied_rules.rule_id IS NULL AND deck.archetype_id IN ( SELECT DISTINCT archetype_id FROM rule ) """ deck_ids = [str(row['deck_id']) for row in db().select(sql)] if not deck_ids: return [] ids_list = ', '.join(deck_ids) return deck.load_decks(where=f'd.id IN ({ids_list})')
def run() -> None: all_decks = deck.load_decks() for d in all_decks: # Recalculate all hashes, in case they've changed. Or we've changed the default sort order. cards = {'maindeck': d['maindeck'], 'sideboard': d['sideboard']} deckhash = hashlib.sha1(repr(cards).encode('utf-8')).hexdigest() db().execute('UPDATE deck SET decklist_hash = %s WHERE id = %s', [deckhash, d['id']])
def scrape(ignore_competition_ids=None): if ignore_competition_ids is None: ignore_competition_ids = [] where = "d.id NOT IN (SELECT deck_id FROM deck_match) AND d.source_id = (SELECT id FROM source WHERE name = 'Gatherling')" if ignore_competition_ids: where += ' AND d.competition_id NOT IN ({ids})'.format( ids=', '.join([str(id) for id in ignore_competition_ids])) decks = deck.load_decks(where, order_by='d.competition_id') if len(decks) == 0: logger.warning('No more competitions to insert matches for.') return ds, competition_id = [], decks[0].competition_id for d in decks: if d.competition_id != competition_id: # Arbitrary cutoff of number of decks to say "these are decks with no matches not a full unlogged competition". if len(ds) >= 4: break else: logger.warning( 'Skipping {id} because deck count is {n}.'.format( id=competition_id, n=len(ds))) ds = [] competition_id = d.competition_id ds.append(d) matches = [] for d in ds: matches += gatherling.tournament_matches(d) if len(matches) == 0: logger.warning( 'Found no matches in {id} so trying the next competition.'.format( id=competition_id)) scrape(ignore_competition_ids + [competition_id]) gatherling.add_ids(matches, ds) gatherling.insert_matches_without_dupes(ds[0].created_date, matches)
def run(): multiverse.update_cache() oracle.init() ds = deck.load_decks() for d in ds: deck.prime_cache(d) return 'Done'
def load_archetypes(where: str = 'TRUE', merge: bool = False, season_id: int = None) -> List[Archetype]: decks = deck.load_decks(where, season_id=season_id) archetypes: Dict[str, Archetype] = {} for d in decks: if d.archetype_id is None: continue key = 'merge' if merge else d.archetype_id archetype = archetypes.get(key, Archetype()) archetype.id = d.archetype_id archetype.name = d.archetype_name archetype.decks = archetype.get('decks', []) + [d] archetype.wins = archetype.get('wins', 0) + (d.get('wins') or 0) archetype.losses = archetype.get('losses', 0) + (d.get('losses') or 0) archetype.draws = archetype.get('draws', 0) + (d.get('draws') or 0) if d.get('finish') == 1: archetype.tournament_wins = archetype.get('tournament_wins', 0) + 1 if (d.get('finish') or sys.maxsize) <= 8: archetype.top8s = archetype.get('top8s', 0) + 1 archetype.perfect_runs = archetype.get('perfect_runs', 0) + 1 archetypes[key] = archetype archetype_list = list(archetypes.values()) return archetype_list
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 set_decks(people): people_by_id = {person.id: person for person in people} where = 'd.person_id IN ({ids})'.format(ids=', '.join(str(k) for k in people_by_id.keys())) decks = deck.load_decks(where) for p in people: p.decks = [] for d in decks: people_by_id[d.person_id].decks.append(d)
def active_decks(additional_where='1 = 1'): where = "d.id IN (SELECT id FROM deck WHERE competition_id = ({active_competition_id_query})) AND (d.wins + d.losses + d.draws < 5) AND NOT d.retired AND ({additional_where})".format( active_competition_id_query=active_competition_id_query(), additional_where=additional_where) decks = deck.load_decks(where) return sorted(decks, key=lambda d: '{person}{deck}'.format( person=d.person.ljust(100), deck=d.name))
def random_legal_deck() -> Optional[Deck]: where = 'd.reviewed AND d.created_date > (SELECT start_date FROM season WHERE number = {current_season_num})'.format(current_season_num=seasons.current_season_num()) having = '(d.competition_id NOT IN ({active_competition_id_query}) OR SUM(cache.wins + cache.draws + cache.losses) >= 5)'.format(active_competition_id_query=active_competition_id_query()) try: return deck.load_decks(where=where, having=having, order_by='RAND()', limit='LIMIT 1')[0] except IndexError: # For a short while at the start of a season there are no decks that match the WHERE/HAVING clauses. return None
def run() -> None: decks = deck.load_decks('NOT reviewed') deck.calculate_similar_decks(decks) for d in decks: for s in d.similar_decks: if s.reviewed and s.archetype_id is not None: sim = int(100 * deck.similarity_score(d, s)) archetype.assign(d.id, s.archetype_id, None, False, sim) break
def matchup(hero: Dict[str, str], enemy: Dict[str, str], season_id: int = None) -> Dict[str, Union[str, int, List[int]]]: where = 'TRUE' prefix = None args: List[Union[str, int]] = [] if season_id: where += ' AND (season.id = %s)' args.append(season_id) for criteria in [hero, enemy]: prefix = '' if prefix is None else 'o' if criteria.get('person_id'): where += f' AND ({prefix}d.person_id = %s)' args.append(criteria['person_id']) if criteria.get('archetype_id'): where += f' AND ({prefix}d.archetype_id IN (SELECT descendant FROM archetype_closure WHERE ancestor = %s))' args.append(criteria['archetype_id']) if criteria.get('card'): where += f' AND ({prefix}d.id IN (SELECT deck_id FROM deck_card WHERE card = %s))' args.append(criteria['card']) season_join = query.season_join() sql = f""" SELECT GROUP_CONCAT(DISTINCT d.id) AS hero_deck_ids, GROUP_CONCAT(DISTINCT od.id) AS enemy_deck_ids, GROUP_CONCAT(DISTINCT m.id) AS match_ids, IFNULL(SUM(CASE WHEN dm.games > odm.games THEN 1 ELSE 0 END), 0) AS wins, IFNULL(SUM(CASE WHEN dm.games = odm.games THEN 1 ELSE 0 END), 0) AS draws, IFNULL(SUM(CASE WHEN odm.games > dm.games THEN 1 ELSE 0 END), 0) AS losses FROM deck AS d LEFT JOIN deck_match AS dm ON dm.deck_id = d.id LEFT JOIN `match` AS m ON dm.match_id = m.id LEFT JOIN deck_match AS odm ON m.id = odm.match_id AND odm.deck_id <> d.id LEFT JOIN deck AS od ON odm.deck_id = od.id {season_join} WHERE {where} """ results = guarantee.exactly_one(db().select(sql, args)) results['hero_deck_ids'] = results['hero_deck_ids'].split( ',') if results['hero_deck_ids'] else [] results['hero_decks'] = deck.load_decks( 'd.id IN (' + ', '.join(results['hero_deck_ids']) + ')') if results['hero_deck_ids'] else [] results['enemy_deck_ids'] = results['enemy_deck_ids'].split( ',') if results['enemy_deck_ids'] else [] results['match_ids'] = results['match_ids'].split( ',') if results['match_ids'] else [] results['matches'] = match.load_matches( where='m.id IN (' + ', '.join(results['match_ids']) + ')') if results['match_ids'] else [] return results
def set_decks(people: List[Person], season_id: int = None) -> None: people_by_id = {person.id: person for person in people} where = 'd.person_id IN ({ids})'.format(ids=', '.join( str(k) for k in people_by_id.keys())) decks = deck.load_decks(where, season_id=season_id) for p in people: p.decks = [] for d in decks: people_by_id[d.person_id].decks.append(d)
def set_decks(competitions): if competitions == []: return competitions_by_id = {c.id: c for c in competitions} where = 'd.competition_id IN ({ids})'.format(ids=', '.join(str(k) for k in competitions_by_id.keys())) decks = deck.load_decks(where) for c in competitions: c.decks = [] for d in decks: competitions_by_id[d.competition_id].decks.append(d)
def run() -> None: all_decks = deck.load_decks() for d in all_decks: # Recalculate all hashes, in case they've changed. Or we've changed the default sort order. cards = {'maindeck': d['maindeck'], 'sideboard': d['sideboard']} deckhash = hashlib.sha1(repr(cards).encode('utf-8')).hexdigest() if d['decklist_hash'] != deckhash: print(f"{d.id}: hash was {d['decklist_hash']} now {deckhash}") db().execute('UPDATE deck SET decklist_hash = %s WHERE id = %s', [deckhash, d['id']]) redis.clear(f'decksite:deck:{d.id}')
def decks_api() -> Response: """ Grab a slice of results from a 0-indexed resultset of decks. Input: { 'archetypeId': <int?>, 'cardName': <str?>, 'competitionId': <int?>, 'personId': <int?>, 'deckType': <'league'|'tournament'|'all'>, 'page': <int>, 'pageSize': <int>, 'personId': <int?>, 'sortBy': <str>, 'sortOrder': <'ASC'|'DESC'>, 'seasonId': <int|'all'> } Output: { 'page': <int>, 'pages': <int>, 'decks': [<deck>] } """ if not request.args.get('sortBy') and request.args.get('competitionId'): sort_by = 'top8' sort_order = 'ASC' elif not request.args.get('sortBy'): sort_by = 'date' sort_order = 'DESC' else: sort_by = str(request.args.get('sortBy')) sort_order = str(request.args.get('sortOrder')) assert sort_order in ['ASC', 'DESC'] order_by = query.decks_order_by(sort_by, sort_order) page_size = int(request.args.get('pageSize', 20)) page = int(request.args.get('page', 0)) start = page * page_size limit = f'LIMIT {start}, {page_size}' # Don't restrict by season if we're loading something with a date by its id. season_id = 'all' if request.args.get( 'competitionId') else rotation.season_id( str(request.args.get('seasonId')), None) where = query.decks_where(request.args, session.get('person_id')) total = deck.load_decks_count(where=where, season_id=season_id) pages = max(ceil(total / page_size) - 1, 0) # 0-indexed ds = deck.load_decks(where=where, order_by=order_by, limit=limit, season_id=season_id) prepare_decks(ds) r = {'page': page, 'pages': pages, 'decks': ds} resp = return_json(r, camelize=True) resp.set_cookie('page_size', str(page_size)) return resp
def run(): multiverse.update_cache() oracle.init() ds = deck.load_decks() for d in ds: redis.clear(f'decksite:deck:{d.id}') deck.prime_cache(d) archetype.preaggregate() card.preaggregate() deck.preaggregate_omw() return 'Done'
def __init__(self, archetypes, search_results) -> None: super().__init__() self.archetypes = archetypes self.roots = [a for a in self.archetypes if a.is_root] self.queue = deck.load_decks(where='NOT d.reviewed', order_by='updated_date DESC') for d in self.queue: self.prepare_deck(d) self.has_search_results = len(search_results) > 0 self.search_results = search_results for d in self.search_results: self.prepare_deck(d)
def menu(self): archetypes_badge = None if session.get('admin') is True: n = len(deck.load_decks('NOT d.reviewed')) if n > 0: archetypes_badge = { 'url': url_for('edit_archetypes'), 'text': n } menu = [{ 'name': 'Decks', 'url': url_for('home') }, { 'name': 'Competitions', 'url': url_for('competitions') }, { 'name': 'People', 'url': url_for('people') }, { 'name': 'Cards', 'url': url_for('cards') }, { 'name': 'Archetypes', 'url': url_for('archetypes'), 'badge': archetypes_badge }, { 'name': 'Resources', 'url': url_for('resources') }] if (rotation.next_rotation() - dtutil.now()) < datetime.timedelta(7): menu += [{'name': 'Rotation', 'url': url_for('rotation')}] menu += [{ 'name': 'About', 'url': url_for('about') }, { 'name': 'League', 'url': url_for('league'), 'has_submenu': True, 'submenu': [{ 'name': 'Sign Up', 'url': url_for('signup') }, { 'name': 'Report', 'url': url_for('report') }, { 'name': 'Records', 'url': url_for('current_league') }] }] return menu
def run() -> None: multiverse.rebuild_cache() oracle.init() ds = deck.load_decks() for d in ds: redis.clear(f'decksite:deck:{d.id}') deck.prime_cache(d) redis.clear(f'decksite:deck:{d.id}') archetype.preaggregate() person.preaggregate() card.preaggregate() deck.preaggregate() season.preaggregate()
def run() -> None: multiverse.update_cache() oracle.init() ds = deck.load_decks() for d in ds: redis.clear(f'decksite:deck:{d.id}') deck.prime_cache(d) redis.clear(f'decksite:deck:{d.id}') archetype.preaggregate() person.preaggregate() card.preaggregate() deck.preaggregate_omw() rule.cache_all_rules()
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