예제 #1
0
    def calculate_draw_odds(self, ignored_iids=None):
        if ignored_iids is None:
            ignored_iids = set()
        cards_not_in_library = set()
        for zone in self.all_zones:
            if zone != self.library:
                for card in zone.cards:
                    assert isinstance(card, GameCard)
                    if card.owner_seat_id == self.seat and card.mtga_id != -1:  # don't bother for unknown cards; they're unknown!
                        if card.game_id not in ignored_iids:
                            cards_not_in_library.add(card)
        assert isinstance(self.original_deck,
                          Deck), "{} {}".format(self.original_deck,
                                                type(self.original_deck))
        current_list = self.original_deck.cards.copy()
        for card in cards_not_in_library:
            simple_card = all_mtga_cards.find_one(card.mtga_id)
            try:
                current_list.remove(simple_card)
            except:
                mtga_watch_app.send_error("Card wasn't in library to remove?")
        odds = {}
        for card in current_list:
            if card.mtga_id not in odds.keys():
                odds[card.mtga_id] = {
                    "card": card.pretty_name,
                    "iid": None,
                    "colors": card.colors,
                    "cost": card.cost,
                    "card_type": card.card_type,
                    "card_subtype": card.sub_types,
                    "count_in_deck": 0,
                    "odds_unf": 0,
                    "odds_of_draw": 0,
                }
                if isinstance(card, GameCard):
                    odds[card.mtga_id]['iid'] = card.game_id

            odds[card.mtga_id]["count_in_deck"] += 1
            odds[card.mtga_id]["odds_unf"] = 100 * odds[
                card.mtga_id]["count_in_deck"] / len(current_list)
            odds[card.mtga_id]["odds_of_draw"] = "{:.2f}".format(
                odds[card.mtga_id]["odds_unf"])
        odds_list = [odds[k] for k in odds.keys()]
        odds_list.sort(key=lambda x: x["odds_unf"])
        info = {
            "stats": list(reversed(odds_list)),
            "deck_name": self.original_deck.pool_name,
            "total_cards_in_deck": len(current_list),
            "library_contents": [c.to_serializable() for c in current_list],
            "last_drawn": None
        }
        return info
예제 #2
0
파일: tasks.py 프로젝트: riQQ/mtgatracker
def block_watch_task(in_queue, out_queue):
    while all_die_queue.empty():
        block_recieved = in_queue.get()
        if block_recieved is None:
            out_queue.put(None)
            break

        log_line = None
        if isinstance(block_recieved, tuple):
            log_line, block_recieved = block_recieved

        if "[" not in block_recieved and "{" not in block_recieved:
            continue
        block_lines = block_recieved.split("\n")
        if len(block_lines) < 2:
            continue

        request_or_response = None
        json_str = ""  # hit the ex
        timestamp = None
        block_title_seq = None

        if block_lines[1] and block_lines[1].startswith(
                "==>") or block_lines[1].startswith("<=="):
            """
            these logs looks like:
            
            [UnityCrossThreadLogger]6/7/2018 7:21:03 PM
            ==> Log.Info(530):
            {
                "json": "stuff"
            }
            """
            title_line = block_lines[1]
            block_title = " ".join(title_line.split(" ")[1:]).split("(")[0]
            block_title_seq = None

            if "(" in title_line and ")" in title_line:
                block_title_seq = title_line.split("(")[1].split(")")[
                    0]  # wtf is this thing?
            request_or_response = "response"
            if title_line.startswith("==>"):
                request_or_response = "request"

            json_str = "\n".join(block_lines[2:]).strip()
            if json_str.startswith("["):
                # this is not valid json, we need to surround it with a header such that it's an object instead of a list
                json_str = '{{"{}": {}}}'.format(block_title, json_str)
        elif block_lines[1].strip() == "{":
            """
            these logs look like:
            
            [UnityCrossThreadLogger]6/7/2018 7:21:03 PM: Match to 26848417E29213FE: GreToClientEvent
            {
              "json": "stuff"
            }
            """
            try:
                timestamp = dateutil.parser.parse(
                    block_lines[0].split("]")[1].split(": ")[0])
            except:
                pass
            block_title = block_lines[0].split(" ")[-1]
            json_str = "\n".join(block_lines[1:])
        elif block_lines[0].strip().endswith("{"):
            """
            these blocks looks like: 
            
            [UnityCrossThreadLogger]7/2/2018 10:27:59 PM (-1) Incoming Rank.Updated {
              "json": "stuff
            }
            """
            block_title = block_lines[0].strip().split(" ")[
                -2]  # skip trailing {
            json_str = "{" + "\n".join(
                block_lines[1:]
            )  # just cut the first line and manually add { back in
        if json_str:
            try:
                blob = json.loads(json_str)
                if log_line:
                    blob["log_line"] = log_line
                if timestamp:
                    blob["timestamp"] = timestamp
                mtga_logger.info(
                    "{}success parsing blob: {}({}) / log_line {}".format(
                        util.ld(), block_title, block_title_seq, log_line))
                if request_or_response:
                    blob["request_or_response"] = request_or_response
                if block_title:
                    blob["block_title"] = block_title.strip()
                if block_title_seq:
                    blob["block_title_sequence"] = block_title_seq
                out_queue.put(blob)
            except Exception as e:
                mtga_logger.error("{}Could not parse json_blob `{}`".format(
                    util.ld(), json_str))
                mtga_watch_app.send_error(
                    "Could not parse json_blob {}".format(json_str))
예제 #3
0
파일: tasks.py 프로젝트: riQQ/mtgatracker
def json_blob_reader_task(in_queue, out_queue):
    def check_for_client_id(blob):
        if "authenticateResponse" in blob:
            if "clientId" in blob["authenticateResponse"]:
                # screw it, no one else is going to use this message, mess up the timestamp, who cares
                with mtga_watch_app.game_lock:
                    if mtga_watch_app.player_id != blob[
                            "authenticateResponse"]['clientId']:
                        mtga_watch_app.player_id = blob[
                            "authenticateResponse"]['clientId']
                        mtga_logger.debug(
                            "{}check_for_client_id: got new clientId".format(
                                util.ld()))
                        mtga_watch_app.save_settings()
                general_output_queue.put(
                    {"authenticateResponse": blob["authenticateResponse"]})

    last_blob = None
    last_decklist = None
    error_count = 0
    while all_die_queue.empty():
        json_recieved = in_queue.get()

        if json_recieved is None:
            out_queue.put(None)
            break

        if last_blob == json_recieved:
            continue  # don't double fire

        # check for decklist changes
        if mtga_watch_app.player_decks != last_decklist:
            last_decklist = mtga_watch_app.player_decks
            decklist_change_queue.put({
                k: v.to_serializable(transform_to_counted=True)
                for k, v in last_decklist.items()
            })

        # check for gamestate changes
        try:
            hero_library_hash = -1
            opponent_hand_hash = -1
            if mtga_watch_app.game:
                hero_library_hash = hash(mtga_watch_app.game.hero.library)
                opponent_hand_hash = hash(mtga_watch_app.game.opponent.hand)

            check_for_client_id(json_recieved)
            dispatchers.dispatch_blob(json_recieved)
            mtga_watch_app.last_blob = json_recieved
            error_count = 0

            hero_library_hash_post = -1
            opponent_hand_hash_post = -1
            if mtga_watch_app.game:
                hero_library_hash_post = hash(mtga_watch_app.game.hero.library)
                opponent_hand_hash_post = hash(
                    mtga_watch_app.game.opponent.hand)
                if hero_library_hash != hero_library_hash_post or opponent_hand_hash != opponent_hand_hash_post:
                    game_state_change_queue.put(mtga_watch_app.game.game_state(
                    ))  # TODO: BREAKPOINT HERE
                if mtga_watch_app.game.final:
                    game_state_change_queue.put({
                        "match_complete":
                        True,
                        "gameID":
                        mtga_watch_app.game.match_id
                    })
        except:
            import traceback
            exc = traceback.format_exc()
            stack = traceback.format_stack()
            mtga_logger.error("{}Exception @ count {}".format(
                util.ld(True), mtga_watch_app.error_count))
            mtga_logger.error(exc)
            mtga_logger.error(stack)
            mtga_watch_app.send_error(
                "Exception during check game state. Check log for more details"
            )
            if error_count > 5:
                mtga_logger.error("{}error count too high; exiting".format(
                    util.ld()))
                return

        last_blob = json_recieved
예제 #4
0
def block_watch_task(in_queue, out_queue):
    while all_die_queue.empty():
        block_recieved = in_queue.get()
        if block_recieved is None:
            out_queue.put(None)
            break
        if "[" not in block_recieved and "{" not in block_recieved:
            continue
        square_index = block_recieved.index(
            "[") if "[" in block_recieved else -1
        curly_index = block_recieved.index(
            "{") if "{" in block_recieved else -1
        if square_index != -1 and (square_index < curly_index
                                   or curly_index == -1):
            # TODO: this, but better
            """ 
            found a log with a block that looked like this:

            ```
            Unloading 6 Unused Serialized files (Serialized files now loaded: 46)
            3/6/2018 9:35:53 PM: Match to 6A250A78F6933705: GreToClientEvent
            {
              "greToClientEvent": {
               ...
            ```

            so it misses the elif clause below. I guess delete the crap in front of it? shrugggg
            """
            # try list first
            pre_block = block_recieved[:square_index]
            if " " in pre_block:
                block_title = pre_block.split(" ")[-2]
                block_recieved = block_title + " " + block_recieved[
                    square_index:]
            else:
                block_recieved = block_recieved[square_index:]
        if curly_index != -1 and (curly_index < square_index
                                  or square_index == -1):
            pre_block = block_recieved[:curly_index]
            if " " in pre_block:
                block_title = pre_block.split(" ")[-2]
                block_recieved = block_title + " " + block_recieved[
                    curly_index:]
            else:
                block_recieved = block_recieved[curly_index:]
            # try object parsing
        block_lines = block_recieved.split("\n")
        first_line = block_lines[0].strip()
        second_line = None
        if len(block_lines) > 1:
            second_line = block_lines[1].strip()
        if first_line and first_line[-1] == "[":
            list_name = first_line.split(" ")[-2]
            idx_first_sq_bracket = block_recieved.index("[")
            idx_last_sq_bracket = block_recieved.rindex("]") + 1
            list_blob = '{{"{}": '.format(list_name) + block_recieved[
                idx_first_sq_bracket:idx_last_sq_bracket] + " }"
            try:
                blob = json.loads(list_blob)
                out_queue.put(blob)
            except:
                mtga_logger.error(
                    "Could not parse list_blob {}".format(list_blob))
                mtga_watch_app.send_error(
                    "Could not parse list_blob {}".format(list_blob))
        elif first_line and first_line[
                -1] == "{" or second_line and second_line == "{":
            idx_first_bracket = block_recieved.index("{")
            idx_last_bracket = block_recieved.rindex("}") + 1

            json_blob = block_recieved[idx_first_bracket:idx_last_bracket]
            try:
                blob = json.loads(json_blob)
                if block_title:
                    blob["block_title"] = block_title.strip()
                out_queue.put(blob)
            except:
                mtga_logger.error(
                    "Could not parse json_blob {}".format(json_blob))
                mtga_watch_app.send_error(
                    "Could not parse json_blob {}".format(json_blob))
예제 #5
0
def block_watch_task(in_queue, out_queue):
    BLOCK_SEQ = 0
    while all_die_queue.empty():
        block_recieved = in_queue.get()
        if block_recieved is None:
            out_queue.put(None)
            break
        log_line = None
        if isinstance(block_recieved, tuple):
            log_line, block_recieved = block_recieved

        if "[" not in block_recieved and "{" not in block_recieved:
            continue
        block_lines = block_recieved.split("\n")

        request_or_response = None
        json_str = ""  # hit the ex
        timestamp = None
        block_title_seq = None
        if block_lines[0] and block_lines[0].startswith(
                "[UnityCrossThreadLogger]"):
            line = block_lines[0].split("[UnityCrossThreadLogger]")[1]
            if line.startswith("==>") or line.startswith("<=="):
                request_or_response = "response"
                if line.startswith("==>"):
                    request_or_response = "request"
                line = line[4:]
                block_title = line.split(" ")[0]
                indexes = []
                if "{" in line:
                    indexes.append(line.index("{"))
                if "[" in line:
                    indexes.append(line.index("["))
                first_open_bracket = min(indexes)
                json_str = line[first_open_bracket:]
            elif len(block_lines) > 1:
                try:
                    timestamp = dateutil.parser.parse(
                        block_lines[0].split("]")[1].split(": ")[0])
                except:
                    pass
                block_title = block_lines[0].split(" ")[-1]
                json_str = "\n".join(block_lines[1:])
        # I think everything below this is deprecated...
        elif block_lines[1] and block_lines[1].startswith(
                "==>") or block_lines[1].startswith("<=="):
            """
            these logs looks like:
            
            [UnityCrossThreadLogger]6/7/2018 7:21:03 PM
            ==> Log.Info(530):
            {
                "json": "stuff"
            }
            """
            title_line = block_lines[1]
            block_title = " ".join(title_line.split(" ")[1:]).split("(")[0]
            block_title_seq = None

            if "(" in title_line and ")" in title_line:
                block_title_seq = title_line.split("(")[1].split(")")[
                    0]  # wtf is this thing?
            request_or_response = "response"
            if title_line.startswith("==>"):
                request_or_response = "request"

            json_str = "\n".join(block_lines[2:]).strip()
            if json_str.startswith("["):
                # this is not valid json, we need to surround it with a header such that it's an object instead of a list
                json_str = '{{"{}": {}}}'.format(block_title, json_str)
        elif block_lines[1].strip() == "{":
            """ DEPRECATED
            these logs look like:
            
            [UnityCrossThreadLogger]6/7/2018 7:21:03 PM: Match to 26848417E29213FE: GreToClientEvent
            {
              "json": "stuff"
            }
            """
            try:
                timestamp = dateutil.parser.parse(
                    block_lines[0].split("]")[1].split(": ")[0])
            except:
                pass
            block_title = block_lines[0].split(" ")[-1]
            json_str = "\n".join(block_lines[1:])
        elif block_lines[1].strip().endswith("{"):
            """
            these blocks looks like: 
            
            [UnityCrossThreadLogger]7/2/2018 10:27:59 PM
            (-1) Incoming Rank.Updated {
              "json": "stuff
            }
            """
            block_title = block_lines[1].strip().split(" ")[
                -2]  # skip trailing {
            json_str = "{" + "\n".join(
                block_lines[2:]
            )  # cut the first two lines and manually add { back in
        if json_str:
            try:
                blob = json.loads(json_str)
                BLOCK_SEQ += 1
                # useful: next time you're trying to figure out why a blob isn't getting through the queue:
                # if "DirectGame" in json_str and "method" in blob:
                #     import pprint
                #     pprint.pprint(blob)
                if log_line:
                    blob["log_line"] = log_line
                if timestamp:
                    blob["timestamp"] = timestamp
                mtga_logger.info(
                    "{}success parsing blob: {}({}) / log_line {}".format(
                        util.ld(), block_title, block_title_seq, log_line))
                if request_or_response:
                    blob["request_or_response"] = request_or_response
                if block_title:
                    blob["block_title"] = block_title.strip()
                blob["block_title_sequence"] = BLOCK_SEQ
                out_queue.put(blob)
            except Exception as e:
                mtga_logger.error("{}Could not parse json_blob `{}`".format(
                    util.ld(), json_str))
                mtga_watch_app.send_error(
                    "Could not parse json_blob {}".format(json_str))
예제 #6
0
def block_watch_task(in_queue, out_queue):
    while all_die_queue.empty():
        block_recieved = in_queue.get()
        if block_recieved is None:
            out_queue.put(None)
            break
        if "[" not in block_recieved and "{" not in block_recieved:
            continue
        block_lines = block_recieved.split("\n")
        if len(block_lines) < 2:
            continue

        request_or_response = None
        json_str = ""  # hit the ex

        if block_lines[1] and block_lines[1].startswith(
                "==>") or block_lines[1].startswith("<=="):
            """
            these logs looks like:
            
            [UnityCrossThreadLogger]6/7/2018 7:21:03 PM
            ==> Log.Info(530):
            {
                "json": "stuff"
            }
            """
            title_line = block_lines[1]
            block_title = " ".join(title_line.split(" ")[1:]).split("(")[0]
            block_title_seq = None

            if "(" in title_line and ")" in title_line:
                block_title_seq = title_line.split("(")[1].split(")")[
                    0]  # wtf is this thing?
            request_or_response = "response"
            if title_line.startswith("==>"):
                request_or_response = "request"

            json_str = "\n".join(block_lines[2:]).strip()
            if json_str.startswith("["):
                # this is not valid json, we need to surround it with a header such that it's an object instead of a list
                json_str = '{{"{}": {}}}'.format(block_title, json_str)
        elif block_lines[1].strip() == "{":
            """
            these logs look like:
            
            [UnityCrossThreadLogger]6/7/2018 7:21:03 PM: Match to 26848417E29213FE: GreToClientEvent
            {
              "json": "stuff"
            }
            """
            block_title = block_lines[0].split(" ")[-1]
            json_str = "\n".join(block_lines[1:])

        if json_str:
            try:
                blob = json.loads(json_str)
                mtga_logger.info("{}success parsing blob: {}({})".format(
                    util.ld(), block_title, block_title_seq))
                if request_or_response:
                    blob["request_or_response"] = request_or_response
                if block_title:
                    blob["block_title"] = block_title.strip()
                if block_title_seq:
                    blob["block_title_sequence"] = block_title_seq
                out_queue.put(blob)
            except:
                mtga_logger.error("{}Could not parse json_blob `{}`".format(
                    util.ld(), json_str))
                mtga_watch_app.send_error(
                    "Could not parse json_blob {}".format(json_str))