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
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))
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
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))
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))
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))