Esempio n. 1
0
    def _get_multicolor_cards(self, pretend=False):

        if pretend:
            if self.sort_spec.get('multicolor_subsections', False):
                return {}
            else:
                return []

        cube_cards = Card.objects.filter(cube=self.cube)
        log.debug('all cube cards: {}', cube_cards)
        # this is going to leverage the assumptions that magic has not
        # yet combined one color of a "special" mana with a different color
        # of mana, except in the case of multicolor hybrid, which is being
        # handled
        qs = cube_cards.filter(_mono_hybrid_mana_bitfield=0,
                               _phyrexian_mana_bitfield=0)

        log.debug('cards that don\'t have special stuff: {}', qs)

        for color_name in color_bitfield_keys:
            color_value = int(getattr(Card._standard_mana_bitfield,
                                      color_name))
            # checking against the int values of these flags checks for EXACTLY
            # those values, e.g. not green AND black
            qs = qs.exclude(_standard_mana_bitfield=color_value)
            log.debug('cards after removing {}: {}', color_name, qs)
        qs = qs.exclude(_standard_mana_bitfield=0)

        hybrid_cards = cube_cards.exclude(_hybrid_mana_bitfield=0)

        log.debug('non-hybrid multicolor cards left: {}', qs)

        return cube_cards.filter(Q(name__in=hybrid_cards.values("name"))|
                                 Q(name__in=qs.values("name"))).distinct()
Esempio n. 2
0
    def get_all_inserted_names(cls, redis_conn=None):
        """
        Used to test what names are associated with cards in the database.

        :return: a set of all cards in database, this needs to be added
            to after server startup to stay current
        """

        if redis_conn is None:
            redis_conn = cls._get_redis()

        if not redis_conn.llen('_inserted'):
            log.debug('reupdating the list of inserted names')
            cls.update_all_inserted_names(redis_conn)

        return [name.decode('utf8')
                for name in (redis_conn.lrange('_inserted', 0, -1) or [])]
Esempio n. 3
0
    def _get_monocolor_cards(self, multicolor_cards, colorless_cards, pretend):
        """
        :param multicolor_cards: what constitutes a mono-colored card is based
            on what is not a multicolor card
        """

        if pretend:
            return []

        cube_cards = Card.objects.filter(cube=self.cube)
        log.debug('all cube cards: {}', cube_cards)
        log.debug('multicolor cards: {}', multicolor_cards)
        not_multicolor_cards = cube_cards.exclude(name__in=multicolor_cards.values('name'))
        log.debug('not multicolor cards: {}', not_multicolor_cards)
        monocolor_cards = not_multicolor_cards.exclude(name__in=colorless_cards.values('name'))
        log.debug('monocolor cards: {}', monocolor_cards)

        return monocolor_cards
Esempio n. 4
0
    def _get_colorless_cards(self, multicolor_cards, pretend=False):

        if pretend:
            return []
        log.debug("looking for colorless cards")
        cube_cards = Card.objects.filter(cube=self.cube)
        not_mc_cards = cube_cards.exclude(name__in=multicolor_cards.values('name'))
        log.debug("not multicolor: {}", not_mc_cards)
        colorless_cards = not_mc_cards.filter(Q(mana_cost__contains="Land")|
                                              (Q(_standard_mana_bitfield=0)&
                                               Q(_hybrid_mana_bitfield=0)&
                                               Q(_mono_hybrid_mana_bitfield=0)&
                                               Q(_phyrexian_mana_bitfield=0))
        )
        log.debug("colorless: {}", colorless_cards)
        return colorless_cards
Esempio n. 5
0
def insert_cards(names, redis_conn, post_insert_hook=None):
    """
    Search gather for cards with the given name, insert that information into
    the database. This doesn't check for existing cards that have that name,
    and the act of inserting them
    :param names: the names of the cards to insert
    :param redis_conn: used to cache information about the cards
    :param post_insert_hook: this callable will be invoked with the card that
        was just inserted
    :return: if names were provided: {
        'inserted': cards_to_insert,
        'refetched': refetched_cards,
        'mismatches': relevant_mismatches,
        'invalid': invalid_names,
    }

    else, empty dict
    """
    if not names:
        return {}

    invalid_names = []
    refetched_names = []
    inserted_cards = []
    relevant_mismatches = {}
    content_map = {}
    unique_names = Counter(names)
    duplicate_inserts = []
    inserted_names = Card.get_all_inserted_names()

    if post_insert_hook is None:
        post_insert_hook = lambda c: log.debug('inserted: {.name}', c)

    for name in unique_names:
        try:
            card_content = get_json_card_content(name)
        except CardFetchingError:
            invalid_names.append(name)
            log.debug('problem fetching card with name: %r', name)
            continue

        fetched_name = card_content['name']
        if name != fetched_name:
            Card.add_new_mismatches({name: fetched_name}, redis_conn)
            relevant_mismatches[name] = fetched_name
            if fetched_name in inserted_names:
                refetched_names.append(fetched_name)
                continue
        else:
            # mitigation against isse #14 .e.g make a mismatch mapping
            # proactively to support searching with ascii names
            Card.add_new_mismatches({name: fetched_name}, redis_conn)

        if fetched_name not in content_map:
            content_map[fetched_name] = card_content
            card = Card(**card_content)
            try:
                card.save()
            except IntegrityError:
                # assume a different thread inserted it
                duplicate_inserts.append(card.name)
                card = None
            except:
                log.exception('unknown error inserting %r', card)
                card = None
            else:
                Card.mark_card_as_inserted(card, redis_conn)
                inserted_cards.append(card)
            finally:
                post_insert_hook(card)
        else:
            duplicate_inserts.append(fetched_name)

    refetched_cards = list(Card.objects.filter(name__in=refetched_names))

    disposition = {
        'inserted': inserted_cards,
        'refetched': refetched_cards,
        'mismatches': relevant_mismatches,
        'invalid': invalid_names,
    }

    # this needs to actually account for mismatched names
    # if settings.DEBUG:
    #     assertExpectatations(inserted_cards + refetched_cards +
    #                          invalid_names + duplicate_inserts,
    #                          unique_names)

    return disposition