def test_player_class_distribution(_mock_lock):
    redis = fakeredis.FakeStrictRedis()
    distribution = get_player_class_distribution("FT_STANDARD", redis)

    current_ts = datetime.utcnow()
    # t_0 is 5 minutes in the past
    t_0 = current_ts - timedelta(seconds=300,
                                 microseconds=current_ts.microsecond)

    actual_games = defaultdict(int)
    actual_wins = defaultdict(int)
    # First populate the distribution for the last 5 minutes
    t_i = None
    for i in range(301):
        t_i = t_0 + timedelta(seconds=i)
        games_per_second = randrange(3, 14)
        for game_num in range(games_per_second):
            win = bool(randrange(0, 2))
            player_class = CardClass(randrange(2, 11))
            actual_games[player_class.name] += 1
            if win:
                actual_wins[player_class.name] += 1
            distribution.increment(key=player_class.name, win=win, as_of=t_i)

    # Then validate the data distribution
    data = distribution.distribution(start_ts=t_0, end_ts=t_i)
    for i in range(2, 11):
        player_class = CardClass(i)
        assert player_class.name in data
        player_class_data = data[player_class.name]
        assert player_class_data["games"] == actual_games[player_class.name]
        assert player_class_data["wins"] == actual_wins[player_class.name]
Beispiel #2
0
def setup_game():
    """
    initializes a game between two players
    Returns:
        game: A game entity representing the start of the game after the mulligan phase
    """

    #choose classes (priest, rogue, shaman, warlock)
    p1 = random.randint(6, 9)
    p2 = random.randint(6, 9)
    #initialize players and randomly draft decks
    #pdb.set_trace()
    deck1 = random_draft(CardClass(p1))
    deck2 = random_draft(CardClass(p2))
    player1 = Player("Player1", deck1, CardClass(p1).default_hero)
    player2 = Player("Player2", deck2, CardClass(p2).default_hero)
    #begin the game
    game = Game(players=(player1, player2))
    game.start()

    #Skip mulligan for now
    for player in game.players:
        cards_to_mulligan = random.sample(player.choice.cards, 0)
        player.choice.choose(*cards_to_mulligan)

    return game
Beispiel #3
0
    def getInitGame(self):
        """
        Returns:
            startBoard: a representation of the board (ideally this is the form
                        that will be the input to your neural network)
        """
        if self.isolate:
            self.isolateSet()

        cards.db.initialize()
        if self.is_basic:  #create quick simple game
            # with open('notbasic.data', 'rb') as f:
            #     extra_set = pickle.load(f)

            extra_set = cards.filter(card_set=[
                CardSet.EXPERT1, CardSet.HOF, CardSet.NAXX, CardSet.GVG,
                CardSet.BRM, CardSet.TGT, CardSet.LOE, CardSet.OG, CardSet.
                KARA, CardSet.GANGS, CardSet.UNGORO, CardSet.ICECROWN, CardSet.
                LOOTAPALOOZA, CardSet.GILNEAS, CardSet.BOOMSDAY, CardSet.TROLL
            ])
            # LOOTAPALOOZA = Kobolds and Catacombs # GILNEAS = Witchwood # TROLL = Rasthakan's Rumble

            # p1 = 6 #priest
            p1 = 7  #rogue
            p2 = 7  #rogue
            # p1 = 4 # mage
            # p2 = 4 # mage
            # deck1 = random_draft(CardClass(p1), exclude=extra_set)
            # deck2 = random_draft(CardClass(p2), exclude=extra_set)
            deck1 = self.roguebasic_draft(
            )  # use same shuffled rogue AI basic decks for now
            deck2 = self.roguebasic_draft()
        else:
            p1 = random.randint(1, 9)
            p2 = random.randint(1, 9)
            deck1 = random_draft(CardClass(p1))
            deck2 = random_draft(CardClass(p2))
        self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero)
        self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero)
        game = Game(players=self.players)
        game.start()

        # Skip mulligan for now (only mulligan expensive cards)
        for player in game.players:
            # if player.name == 'Player1':
            # cards_to_mulligan = [c for c in player.choice.cards if c.cost > 3]
            # else:
            cards_to_mulligan = random.sample(player.choice.cards, 0)
            player.choice.choose(*cards_to_mulligan)

        # track played card list
        self.players[0].playedcards = []
        self.players[1].playedcards = []

        #game.player_to_start = game.current_player      # obsolete?
        self.game = game
        return game
Beispiel #4
0
	def chartifyData(self, theDateUpdated=""):
		result = []

		i = 1
		for aCC in self.myClassClusters:
			plt.figure(i)
			myXs = []
			myYs = []
			myLabels = []
			clusters= {}
			for cluster in aCC.clusters:
				if cluster.name not in clusters:
					clusters[cluster.name] = []
				for dp in cluster.decks:
					myXs.append(dp["x"])
					myYs.append(dp["y"])
					myLabels.append(dp.classification)
					
					clusters[cluster.name].append(tuple((dp["x"], dp["y"])))
			#print(clusters)
			for c in clusters:
				first = [t[0] for t in clusters[c]]
				second = [t[1] for t in clusters[c]]
				plt.scatter(first, second, label=c)
			plt.title(CardClass(aCC.inGameClass).name)
			plt.ylabel("y")
			plt.xlabel("x")
			plt.legend()
			i+=1
			result.append(tuple((myXs, myYs, myLabels)))
		plt.show()
		return result
Beispiel #5
0
def setup_basic_game():
    p1 = 6 #priest
    p2 = 7 #rogue

    deck1 = random_draft(CardClass(p1))
    deck2 = random_draft(CardClass(p2))
    player1 = Player("Player1", deck1, CardClass(p1).default_hero)
    player2 = Player("Player2", deck2, CardClass(p2).default_hero)
    game = Game(players=(player1, player2))
    game.start()

    #Skip mulligan
    for player in game.players:
        cards_to_mulligan = random.sample(player.choice.cards, 0)
        player.choice.choose(*cards_to_mulligan)

    return game
Beispiel #6
0
	def handle(self, *args, **options):
		cursor = connection.cursor()
		lookback = options["lookback"]
		cursor.execute(QUERY % lookback)

		with open(options["out"], mode="wt") as out:
			for row in cursor.fetchall():
				record = "%s:%s\n" % (CardClass(row[0]).name, row[1])
				out.write(record)
    def handle(self, *args, **options):
        conn = redshift.get_new_redshift_connection()

        lookback_val = options["look_back"]
        if lookback_val:
            lookback = int(lookback_val[0])
        else:
            lookback = 14

        end_ts = date.today() - timedelta(days=1)
        start_ts = end_ts - timedelta(days=lookback)

        redis_host = options["redis_host"]
        if redis_host:
            redis_client = redis.StrictRedis(host=redis_host[0])
            pipeline = redis_client.pipeline(transaction=False)
        else:
            pipeline = None

        params = {"start_date": start_ts, "end_date": end_ts}
        compiled_statement = REDSHIFT_QUERY.params(params).compile(bind=conn)
        start_ts = time.time()
        for row in conn.execute(compiled_statement):
            as_of = row["match_start"]
            deck_id = row["deck_id"]
            dbf_map = {
                dbf_id: count
                for dbf_id, count in json.loads(row["deck_list"])
            }
            player_class = CardClass(row["player_class"])
            format = FormatType.FT_STANDARD if row[
                "game_type"] == 2 else FormatType.FT_WILD
            played_cards = json.loads(row["played_cards"])

            tree = deck_prediction_tree(player_class,
                                        format,
                                        redis_client=pipeline)
            min_played_cards = tree.max_depth - 1
            played_card_dbfs = played_cards[:min_played_cards]
            deck_size = sum(dbf_map.values())

            if deck_size == 30:
                tree.observe(deck_id, dbf_map, played_card_dbfs, as_of=as_of)

            if len(pipeline) >= 8000:
                pipeline.execute()

        if len(pipeline):
            pipeline.execute()

        end_ts = time.time()
        duration_seconds = round(end_ts - start_ts)
        print("Took: %i Seconds" % duration_seconds)
Beispiel #8
0
    def getInitGame(self):
        """
        Returns:
            startBoard: a representation of the board (ideally this is the form
                        that will be the input to your neural network)
        """
        if self.isolate:
            self.isolateSet()

        cards.db.initialize()
        if self.is_basic:  #create quick simple game
            with open('notbasic.data', 'rb') as f:
                extra_set = pickle.load(f)
            p1 = 6  #priest
            p2 = 7  #rogue
            deck1 = random_draft(CardClass(p1), exclude=extra_set)
            deck2 = random_draft(CardClass(p2), exclude=extra_set)
        else:
            p1 = random.randint(1, 9)
            p2 = random.randint(1, 9)
            deck1 = random_draft(CardClass(p1))
            deck2 = random_draft(CardClass(p2))
        self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero)
        self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero)
        game = Game(players=self.players)
        game.start()

        # Skip mulligan for now
        for player in game.players:
            cards_to_mulligan = random.sample(player.choice.cards, 0)
            player.choice.choose(*cards_to_mulligan)

        game.player_to_start = game.current_player
        self.game = game
        return game
Beispiel #9
0
    def initGame(self):
        cards.db.initialize()
        if self.is_basic: #create quick simple game
            with open('notbasic.data', 'rb') as f:
                extra_set = pickle.load(f)
            p1 = 6 #priest
            p2 = 7 #rogue
            deck1 = random_draft(CardClass(p1), exclude=extra_set)
            deck2 = random_draft(CardClass(p2), exclude=extra_set)
        else:
            p1 = random.randint(1, 9)
            p2 = random.randint(1, 9)
            deck1 = random_draft(CardClass(p1))
            deck2 = random_draft(CardClass(p2))
        Board.players[0] = Player("Player1", deck1, CardClass(p1).default_hero)
        Board.players[1] = Player("Player2", deck2, CardClass(p2).default_hero)
        game = Game(players=self.players)
        game.start()

        # Skip mulligan for now
        for player in game.players:
            cards_to_mulligan = random.sample(player.choice.cards, 0)
            player.choice.choose(*cards_to_mulligan)

        # self.start_player = game.current_player
        game.player_to_start = game.current_player
        Board.game = game
        return game
Beispiel #10
0
    def initGame(self):
        self.init_envi()

        if self.is_basic:  #create quick simple game
            p1 = 6  #priest
            p2 = 7  #rogue
        else:
            p1 = random.randint(1, 9)
            p2 = random.randint(1, 9)
        deck1 = random_draft(CardClass(p1))
        deck2 = random_draft(CardClass(p2))
        self.players[0] = Player("Player1", deck1, CardClass(p1).default_hero)
        self.players[1] = Player("Player2", deck2, CardClass(p2).default_hero)
        game = Game(players=self.players)
        game.start()

        #Skip mulligan for now
        for player in self.game.players:
            cards_to_mulligan = random.sample(player.choice.cards, 0)
            player.choice.choose(*cards_to_mulligan)

        return game
Beispiel #11
0
def inverse_lookup_table(game_format: FormatType,
                         player_class: CardClass,
                         redis_client=None) -> BaseInverseLookupTable:
    if not redis_client:
        from django.core.cache import caches
        redis_client = caches["ilt_deck_prediction"].client.get_client()

    game_format = FormatType(int(game_format))
    player_class = CardClass(int(player_class))

    required_cards = ClusterSnapshot.objects.get_required_cards_for_player_class(
        game_format, player_class)

    return RedisInverseLookupTable(redis_client, game_format, player_class,
                                   required_cards)
Beispiel #12
0
    def init_game(self):
        """
        initializes a game between two players
        Returns:
            game: A game entity representing the start of the game after the mulligan phase
        """
        if self.is_basic:  #create quick simple game
            p1 = 6  #priest
            p2 = 7  #rogue
            deck1 = random_draft(CardClass(p1))
            deck2 = random_draft(CardClass(p2))
            self.players[0] = Player("Player1", deck1,
                                     CardClass(p1).default_hero)
            self.players[1] = Player("Player2", deck2,
                                     CardClass(p2).default_hero)
            self.game = Game(players=self.players)
            self.game.start()

            #Skip mulligan
            for player in self.game.players:
                cards_to_mulligan = random.sample(player.choice.cards, 0)
                player.choice.choose(*cards_to_mulligan)

            return self.game

        else:
            p1 = random.randint(1, 9)
            p2 = random.randint(1, 9)
            #initialize players and randomly draft decks
            #pdb.set_trace()
            deck1 = random_draft(CardClass(p1))
            deck2 = random_draft(CardClass(p2))
            self.players[0] = Player("Player1", deck1,
                                     CardClass(p1).default_hero)
            self.players[1] = Player("Player2", deck2,
                                     CardClass(p2).default_hero)
            #begin the game
            self.game = Game(players=self.players)
            self.game.start()

            #Skip mulligan for now
            for player in self.game.players:
                cards_to_mulligan = random.sample(player.choice.cards, 0)
                player.choice.choose(*cards_to_mulligan)

            return self.game
Beispiel #13
0
def deck_prediction_tree(player_class, game_format, redis_client=None):
    from django.core.cache import caches

    player_class = CardClass(int(player_class))
    game_format = FormatType(int(game_format))
    if redis_client is None:
        redis_primary = caches["deck_prediction_primary"]
        redis_replica = _get_random_cache(
            caches, "deck_prediction_replica") or redis_primary
        redis_primary = redis_primary.client.get_client()
        redis_replica = redis_replica.client.get_client()
    else:
        redis_primary = redis_client
        redis_replica = redis_primary

    return DeckPredictionTree(player_class, game_format, redis_primary,
                              redis_replica)
Beispiel #14
0
def canonical_decks(request):
    result = []
    archetypes = Archetype.objects.prefetch_related(
        "canonical_decks__deck__includes").all()
    for archetype in archetypes:
        record = {
            "name": archetype.name,
            "archetype_id": archetype.id,
            "player_class_id": archetype.player_class,
            "player_class_name": CardClass(archetype.player_class).name
        }

        canonical_deck = archetype.canonical_decks.order_by("-created").first()
        if canonical_deck:
            record["representative_deck"] = {
                "card_ids": canonical_deck.deck.card_id_list(),
                "digest": canonical_deck.deck.digest
            }

        result.append(record)

    return JsonResponse(result, safe=False)
Beispiel #15
0
def random_class():
    return CardClass(random.randint(2, 10))
    def handle(self, *args, **options):
        conn = redshift.get_new_redshift_connection()
        is_dry_run = options["dry_run"]
        verbosity = options["verbosity"]

        end_ts = date.today()
        start_ts = end_ts - timedelta(days=options["lookback"])

        params = {"start_date": start_ts, "end_date": end_ts}
        compiled_statement = REDSHIFT_QUERY.params(params).compile(bind=conn)

        for card_class in CardClass:
            if 2 <= card_class <= 10:
                for a in Archetype.objects.live().filter(
                        player_class=card_class):
                    self.archetype_map[a.id] = a

                # Standard Signature Weights
                standard_weight_values = ClusterSnapshot.objects.get_signature_weights(
                    FormatType.FT_STANDARD, card_class)
                if len(standard_weight_values):
                    self.signature_weights[FormatType.FT_STANDARD][
                        card_class] = standard_weight_values

                # Wild Signature Weights
                wild_weight_values = ClusterSnapshot.objects.get_signature_weights(
                    FormatType.FT_WILD, card_class)
                if len(wild_weight_values):
                    self.signature_weights[FormatType.FormatType.FT_WILD][
                        card_class] = wild_weight_values

        result_set = list(conn.execute(compiled_statement))
        total_rows = len(result_set)
        self.stdout.write("%i decks to update" % (total_rows))
        if is_dry_run:
            self.stdout.write("Dry run, will not flush to databases")

        for counter, row in enumerate(result_set):
            deck_id = row["deck_id"]
            if not is_dry_run and counter % 100000 == 0:
                self.flush_db_buffer()
                self.flush_firehose_buffer()

            if deck_id is None:
                self.stderr.write("Got deck_id %r ... skipping" % (deck_id))
                continue

            current_archetype_id = row["archetype_id"]
            player_class = CardClass(row["player_class"])
            if player_class == CardClass.NEUTRAL:
                # Most likely noise
                self.stderr.write("Found and skipping NEUTRAL data: %r" %
                                  (row))
                continue
            format = FormatType.FT_STANDARD if row[
                "game_type"] == 2 else FormatType.FT_WILD

            dbf_map = {
                dbf_id: count
                for dbf_id, count in json.loads(row["deck_list"])
            }
            if player_class not in self.signature_weights[format]:
                raise RuntimeError(
                    "%r not found for %r. Are signatures present?" %
                    (player_class, format))

            if self.signature_weights[format][player_class]:
                new_archetype_id = classify_deck(
                    dbf_map, self.signature_weights[format][player_class])

                if new_archetype_id == current_archetype_id:
                    if verbosity > 1:
                        self.stdout.write("Deck %r - Nothing to do." %
                                          (deck_id))
                    continue

                current_name = self.get_archetype_name(current_archetype_id)
                new_name = self.get_archetype_name(new_archetype_id)

                pct_complete = str(math.floor(100.0 * counter / total_rows))

                self.stdout.write(
                    "\t[%s%%] Reclassifying deck %r: %s => %s\n" %
                    (pct_complete, deck_id, current_name, new_name))

                if not is_dry_run:
                    self.buffer_archetype_update(deck_id, new_archetype_id)

        if not is_dry_run:
            self.flush_db_buffer()
            self.flush_firehose_buffer()
        else:
            self.stdout.write("Dry run complete")
Beispiel #17
0
def update_global_players(global_game, entity_tree, meta, upload_event,
                          exporter):
    # Fill the player metadata and objects
    players = {}
    played_cards = exporter.export_played_cards()

    is_spectated_replay = meta.get("spectator_mode", False)
    is_dungeon_run = meta.get("scenario_id", 0) == 2663

    for player in entity_tree.players:
        is_friendly_player = player.player_id == meta["friendly_player"]
        player_meta = meta.get("player%i" % (player.player_id), {})

        decklist_from_meta = player_meta.get("deck")
        decklist_from_replay = [
            c.initial_card_id for c in player.initial_deck if c.card_id
        ]

        meta_decklist_is_superset = _is_decklist_superset(
            decklist_from_meta, decklist_from_replay)

        # We disregard the meta decklist if it's not matching the replay decklist
        # We always want to use it in dungeon run though, since the initial deck is garbage
        disregard_meta = not meta_decklist_is_superset and (
            not is_dungeon_run or not is_friendly_player)

        if not decklist_from_meta or is_spectated_replay or disregard_meta:
            # Spectated replays never know more than is in the replay data
            # But may have erroneous data from the spectator's client's memory
            # Read from before they entered the spectated game
            decklist = decklist_from_replay
        else:
            decklist = decklist_from_meta

        name, real_name = get_player_names(player)
        player_hero_id = player._hero.card_id

        try:
            deck, _ = Deck.objects.get_or_create_from_id_list(
                decklist,
                hero_id=player_hero_id,
                game_type=global_game.game_type,
                classify_archetype=True)
            log.debug("Prepared deck %i (created=%r)", deck.id, _)
        except IntegrityError as e:
            # This will happen if cards in the deck are not in the DB
            # For example, during a patch release
            influx_metric(
                "replay_deck_create_failure", {
                    "count": 1,
                    "build": meta["build"],
                    "global_game_id": global_game.id,
                    "server_ip": meta.get("server_ip", ""),
                    "upload_ip": upload_event.upload_ip,
                    "error": str(e),
                })
            log.exception("Could not create deck for player %r", player)
            global_game.tainted_decks = True
            # Replace with an empty deck
            deck, _ = Deck.objects.get_or_create_from_id_list([])

        capture_played_card_stats(
            global_game, [c.dbf_id for c in played_cards[player.player_id]],
            is_friendly_player)

        eligible_formats = [FormatType.FT_STANDARD, FormatType.FT_WILD]
        is_eligible_format = global_game.format in eligible_formats

        deck_prediction_enabled = getattr(settings,
                                          "FULL_DECK_PREDICTION_ENABLED", True)
        if deck_prediction_enabled and is_eligible_format and settings.ENV_AWS:
            try:
                player_class = Deck.objects._convert_hero_id_to_player_class(
                    player_hero_id)
                tree = deck_prediction_tree(player_class, global_game.format)
                played_cards_for_player = played_cards[player.player_id]

                # 5 played cards partitions a 14 day window into buckets of ~ 500 or less
                # We can search through ~ 2,000 decks in 100ms so that gives us plenty of headroom
                min_played_cards = tree.max_depth - 1

                # We can control via settings the minumum number of cards we need
                # To know about in the deck list before we attempt to guess the full deck
                min_observed_cards = settings.DECK_PREDICTION_MINIMUM_CARDS

                played_card_dbfs = [c.dbf_id for c in played_cards_for_player
                                    ][:min_played_cards]
                played_card_names = [c.name for c in played_cards_for_player
                                     ][:min_played_cards]

                if deck.size is not None:
                    deck_size = deck.size
                else:
                    deck_size = sum(i.count for i in deck.includes.all())

                has_enough_observed_cards = deck_size >= min_observed_cards
                has_enough_played_cards = len(
                    played_card_dbfs) >= min_played_cards

                if deck_size == 30:
                    tree.observe(deck.id, deck.dbf_map(), played_card_dbfs)
                    # deck_id == proxy_deck_id for complete decks
                    deck.guessed_full_deck = deck
                    deck.save()
                elif has_enough_observed_cards and has_enough_played_cards:
                    res = tree.lookup(
                        deck.dbf_map(),
                        played_card_dbfs,
                    )
                    predicted_deck_id = res.predicted_deck_id

                    fields = {
                        "actual_deck_id":
                        deck.id,
                        "deck_size":
                        deck_size,
                        "game_id":
                        global_game.id,
                        "sequence":
                        "->".join("[%s]" % c for c in played_card_names),
                        "predicted_deck_id":
                        res.predicted_deck_id,
                        "match_attempts":
                        res.match_attempts,
                        "tie":
                        res.tie
                    }

                    if settings.DETAILED_PREDICTION_METRICS:
                        fields["actual_deck"] = repr(deck)

                        if res.predicted_deck_id:
                            predicted_deck = Deck.objects.get(
                                id=res.predicted_deck_id)
                            fields["predicted_deck"] = repr(predicted_deck)

                    if res.node:
                        fields["depth"] = res.node.depth

                        if settings.DETAILED_PREDICTION_METRICS:
                            node_labels = []
                            for path_dbf_id in res.path():
                                if path_dbf_id == "ROOT":
                                    path_str = path_dbf_id
                                else:
                                    path_card = Card.objects.get(
                                        dbf_id=path_dbf_id)
                                    path_str = path_card.name
                                node_labels.append("[%s]" % path_str)
                            fields["node"] = "->".join(node_labels)

                            popularity = res.popularity_distribution.popularity(
                                res.predicted_deck_id)
                            fields["predicted_deck_popularity"] = popularity

                            deck_count = res.popularity_distribution.size()
                            fields["distribution_deck_count"] = deck_count

                            observation_count = res.popularity_distribution.observations(
                            )
                            fields[
                                "distribution_observation_count"] = observation_count

                    tree_depth = res.node.depth if res.node else None
                    influx_metric(
                        "deck_prediction",
                        fields,
                        missing_cards=30 - deck_size,
                        player_class=CardClass(int(player_class)).name,
                        format=FormatType(int(global_game.format)).name,
                        tree_depth=tree_depth,
                        made_prediction=predicted_deck_id is not None)

                    if predicted_deck_id:
                        deck.guessed_full_deck = Deck.objects.get(
                            id=predicted_deck_id)
                        deck.save()
            except Exception as e:
                error_handler(e)

        # Create the BlizzardAccount first
        defaults = {
            "region": BnetRegion.from_account_hi(player.account_hi),
            "battletag": name,
        }

        if not is_spectated_replay and not player.is_ai and is_friendly_player:
            user = upload_event.token.user if upload_event.token else None
            if user and not user.is_fake:
                # and user.battletag and user.battletag.startswith(player.name):
                defaults["user"] = user

        blizzard_account, created = BlizzardAccount.objects.get_or_create(
            account_hi=player.account_hi,
            account_lo=player.account_lo,
            defaults=defaults)
        if not created and not blizzard_account.user and "user" in defaults:
            # Set BlizzardAccount.user if it's an available claim for the user
            influx_metric(
                "pegasus_account_claimed", {
                    "count": 1,
                    "account": str(blizzard_account.id),
                    "region": str(blizzard_account.region),
                    "account_lo": str(blizzard_account.account_lo),
                    "game": str(global_game.id)
                })
            blizzard_account.user = defaults["user"]
            blizzard_account.save()

        log.debug("Prepared BlizzardAccount %r", blizzard_account)

        # Now create the GlobalGamePlayer object
        common = {
            "game": global_game,
            "player_id": player.player_id,
        }
        defaults = {
            "is_first": player.tags.get(GameTag.FIRST_PLAYER, False),
            "is_ai": player.is_ai,
            "hero_id": player_hero_id,
            "hero_premium": player._hero.tags.get(GameTag.PREMIUM, False),
            "final_state": player.tags.get(GameTag.PLAYSTATE, 0),
            "extra_turns": player.tags.get(GameTag.EXTRA_TURNS_TAKEN_THIS_GAME,
                                           0),
            "deck_list": deck,
        }

        update = {
            "name": name,
            "real_name": real_name,
            "pegasus_account": blizzard_account,
            "rank": player_meta.get("rank"),
            "legend_rank": player_meta.get("legend_rank"),
            "stars": player_meta.get("stars"),
            "wins": player_meta.get("wins"),
            "losses": player_meta.get("losses"),
            "deck_id": player_meta.get("deck_id") or None,
            "cardback_id": player_meta.get("cardback"),
        }

        defaults.update(update)
        game_player, created = GlobalGamePlayer.objects.get_or_create(
            defaults=defaults, **common)
        log.debug("Prepared player %r (%i) (created=%r)", game_player,
                  game_player.id, created)

        if not created:
            # Go through the update dict and update values on the player
            # This gets us extra data we might not have had when the player was first created
            updated = False
            for k, v in update.items():
                if v and getattr(game_player, k) != v:
                    setattr(game_player, k, v)
                    updated = True

            # Skip updating the deck if we already have a bigger one
            # TODO: We should make deck_list nullable and only create it here
            if game_player.deck_list.size is None or len(
                    decklist) > game_player.deck_list.size:
                # XXX: Maybe we should also check friendly_player_id for good measure
                game_player.deck_list = deck
                updated = True

            if updated:
                log.debug("Saving updated player to the database.")
                game_player.save()

        players[player.player_id] = game_player

    return players
Beispiel #18
0
	def getInGameClass(self):
		return CardClass(self.inGameClass).name