Пример #1
0
 def get_ability_markers(spawn_list, ship_stats):
     """
     Parse a spawn list of lines and take the Engine, Shield, Systems
     and CoPilot ability activations and create markers for them to
     be put in the TimeLine.
     """
     # TODO: Use ship_statistics to create availability markers
     categories = ["engines", "shields", "copilot", "systems"]
     player_id_list = Parser.get_player_id_list(spawn_list)
     results = {key: [] for key in categories}
     # Activation markers
     for line in spawn_list:
         if not isinstance(line, dict):
             line = Parser.line_to_dictionary(line)
         ability = line["ability"]
         if (line["source"] != line["target"] or line["source"] not in player_id_list or
                 "AbilityActivate" not in line["effect"]):
             continue
         if ability in abilities.copilots:
             category = "copilot"
         elif ability in abilities.shields:
             category = "shields"
         elif ability in abilities.systems:
             category = "systems"
         elif ability in abilities.engines:
             category = "engines"
         else:
             continue
         start = FileHandler.datetime_to_float(line["time"])
         args = ("abilities", start, start + 1/60)
         kwargs = {"background": FileHandler.colors[category]}
         results[category].append((args, kwargs))
     return results
Пример #2
0
 def test_get_effects_ability_eligible(self):
     with open(self.FILE) as fi:
         lindex = fi.readlines()
         index = lindex.index(self.EFFECT)
         no_effect = lindex.index(self.LINE)
     lines = Parser.read_file(self.FILE)
     player = Parser.get_player_id_list(lines)
     line = Parser.line_to_dictionary(lines[index], player)
     effect = Parser.get_effects_ability(line, lines, "2963000049645")
     self.assertIsInstance(effect, dict)
     self.assertTrue(len(effect) > 0)
     # Tests get_effects_eligible
     self.assertFalse(Parser.get_effects_ability(lines[no_effect], lines, "2963000048240"))
Пример #3
0
 def insert_spawn(self, spawn, player_name, active_ids: list = None):
     """Insert the events of a spawn into the Treeview"""
     self.delete_all()
     if len(spawn) == 0:
         raise ValueError("Invalid spawn passed.")
     spawn = spawn if isinstance(spawn[0], dict) else [Parser.line_to_dictionary(line) for line in spawn]
     start_time = spawn[0]["time"]
     active_ids = Parser.get_player_id_list(spawn) if active_ids is None else active_ids
     for line in spawn:
         if "custom" not in line or line["custom"] is False:
             line_event_dict = Parser.line_to_event_dictionary(line, active_ids, spawn)
         else:
             line_event_dict = line
         self.insert_event(line_event_dict, player_name, active_ids, start_time)
Пример #4
0
def spawn_statistics(file_name, spawn, spawn_timing, sharing_db=None):
    """Build strings to show in the StatsFrame"""
    # Retrieve required data
    lines = Parser.read_file(file_name, sharing_db)
    player_numbers = Parser.get_player_id_list(lines)
    (abilities_dict, dmg_t, dmg_d, healing, dmg_s, enemies, critcount,
     crit_luck, hitcount, ships_list, enemy_dmg_d, enemy_dmg_t) = \
        Parser.parse_spawn(spawn, player_numbers)
    name = Parser.get_player_name(lines)
    # Build the statistics string
    stat_string = "{name}\n{enemies} enemies\n{dmg_d}\n{dmg_t}\n{dmg_r:.1f} : 1.0\n" \
                  "{dmg_s}\n{healing}\n{hitcount}\n{critcount}\n{crit_luck:.2f}\n" \
                  "{deaths}\n{minutes}:{seconds:.0f}\n{dps:.1f}"
    start = spawn_timing
    finish = Parser.line_to_dictionary(spawn[-1])["time"]
    delta = finish - start
    minutes, seconds = divmod(delta.total_seconds(), 60)
    killsassists = sum(True if enemy_dmg_t[enemy] > 0 else False for enemy in enemies if enemy in enemy_dmg_t)
    stat_string = stat_string.format(
        name=name,
        enemies=killsassists,
        dmg_d=dmg_d,
        dmg_t=dmg_t,
        dmg_r=dmg_d / dmg_t if dmg_t != 0 else 0,
        dmg_s=dmg_s,
        healing=healing,
        hitcount=hitcount,
        critcount=critcount,
        crit_luck=critcount / hitcount if hitcount != 0 else 0,
        deaths="-",
        minutes=minutes,
        seconds=seconds,
        dps=dmg_d / delta.total_seconds() if delta.total_seconds() != 0 else 0
    )
    # Build the components list
    components = {key: "" for key in abilities.component_types}
    for component in [ability for ability in abilities_dict.keys() if ability in abilities.components]:
        for type in components.keys():
            if component not in getattr(abilities, type):
                continue
            # Dual primary/secondary weapons
            if components[type] != "":
                components[type] += " / {}".format(component)
                break
            components[type] = component
            break
    components = [components[category] for category in abilities.component_types]
    # Return
    return name, spawn, abilities_dict, stat_string, ships_list, components, enemies, enemy_dmg_d, enemy_dmg_t
Пример #5
0
 def update_timeline(self, file, match, spawn, match_timings, spawn_timings, file_cube):
     """
     Update the TimeLine with the results of results the file and
     the screen results data
     """
     # Get start and end times of the spawn
     start = FileHandler.datetime_to_float(Parser.line_to_dictionary(file_cube[match][spawn][0])["time"])
     finish = FileHandler.datetime_to_float(Parser.line_to_dictionary(file_cube[match][spawn][-1])["time"])+1
     self.time_line.delete_marker(tk.ALL)
     self.time_line.config(start=start, finish=finish)
     # Update the TimeLine
     screen_data = FileHandler.get_data_dictionary()
     screen_dict = FileHandler.get_spawn_dictionary(
         screen_data, file, match_timings[2 * match], spawn_timings[match][spawn]
     )
     screen_dict = None if isinstance(screen_dict, str) or screen_dict is None else screen_dict
     spawn_list = file_cube[match][spawn]
     active_ids = Parser.get_player_id_list(spawn_list)
     markers = dict()
     if isinstance(screen_dict, dict):
         markers = FileHandler.get_markers(screen_dict, spawn_list, active_ids)
     markers["patterns"] = PatternParser.parse_patterns(spawn_list, screen_dict, Patterns.ALL_PATTERNS, active_ids)
     print("[TimeLine] Building {} markers.".format(sum(len(value) for value in markers.values())))
     for category, data in markers.items():
         for (args, kwargs) in data:
             try:
                 self.time_line.create_marker(*args, **kwargs)
             except (ValueError, TypeError, tk.TclError) as e:
                 print("[TimeLine] Marker creation failed: '{}', '{}', '{}', '{}': {}".format(
                     args[0], args[1], args[2], kwargs["background"], repr(e))
                 )
                 if isinstance(e, ValueError):
                     pass
                 else:
                     raise
     return
Пример #6
0
 def test_line_to_dictionary(self):
     line_dict = Parser.line_to_dictionary(self.LINE)
     self.assertIsInstance(line_dict, dict)
     KEYS = ["time", "source", "target", "target", "amount", "ability", "effect"]
     for key in KEYS:
         self.assertTrue(key in line_dict)
     self.assertIsInstance(line_dict["time"], datetime)
     if not isinstance(line_dict["time"], datetime):
         raise ValueError
     self.assertEqual(line_dict["time"].hour, 22)
     self.assertEqual(line_dict["source"], "2963000048128")
     self.assertEqual(line_dict["target"], "2963000048240")
     self.assertEqual(line_dict["ability"], "Quad Laser Cannon")
     self.assertTrue("Damage" in line_dict["effect"])
     self.assertEqual(int(line_dict["amount"]), 296)
Пример #7
0
 def read_file(path, skip, include=False):
     """Read the file in UnicodeDecodeError safe method"""
     with open(path, "rb") as fi:
         lines = fi.readlines()
     read = lines[skip:]
     if include and len(lines) > 0 and lines[0] not in read:
         read.insert(0, lines[0])
     dictionaries = []
     for line in read:
         try:
             line = line.decode()
         except UnicodeDecodeError:
             continue
         line = Parser.line_to_dictionary(line)
         if line is None:
             continue
         dictionaries.append(line)
     return dictionaries
Пример #8
0
 def get_markers(screen_dict: dict, spawn_list: list, active_ids: list):
     """
     Generate a dictionary of markers to insert into the TimeLine
     widget of the StatsFrame. This marker dictionary is built-up
     as follows:
     {category: [(args, kwargs)]}
     The args and kwargs are passed onto the create_marker function
     for the TimeLine widget.
     """
     if "ship" in screen_dict and screen_dict["ship"] is not None:
         stats = ShipStats(screen_dict["ship"], None, None)
     else:
         stats = None
     results = {}
     start_time = Parser.line_to_dictionary(spawn_list[-1])["time"]
     results.update(FileHandler.get_weapon_markers(screen_dict, spawn_list))
     results.update(FileHandler.get_health_markers(screen_dict, start_time))
     results.update(FileHandler.get_tracking_markers(screen_dict, stats))
     results.update(FileHandler.get_power_mgmt_markers(screen_dict, start_time))
     results.update(FileHandler.get_ability_markers(spawn_list, stats))
     results.update(FileHandler.get_engine_boost_markers(screen_dict, start_time))
     return results
Пример #9
0
 def get_weapon_markers(dictionary, spawn):
     """
     Parse the given screen dictionary and spawn line list to
     generate markers for the TimeLine for the Primary Weapon
     and Secondary Weapon categories.
     The clicks are parsed into lightly coloured markers, while
     ability activations (hits) are parsed into bright markers.
     """
     # Retrieve pre-requisite data
     player_list = Parser.get_player_id_list(spawn)
     # Create lists that will hold markers
     results = {"primaries": [], "secondaries": []}
     """
     File Data
     """
     # Loop over contents of spawn
     for line in spawn:
         if isinstance(line, str):
             line = Parser.line_to_dictionary(line)
         # Retrieve the ability of the line
         ability = line["ability"]
         # If the ability was self-targeted, then it is not a weapon
         # If the ability was not activated by self, then it is not damage dealt
         if line["self"] is True or line["target"] not in player_list:
             continue
         # Determine the category of this ability
         if ability in abilities.primaries:
             category = "primaries"
         elif ability in abilities.secondaries:
             category = "secondaries"
         else:  # Ability is not a weapon
             continue
         # Generate the arguments for the marker creation
         start = FileHandler.datetime_to_float(line["time"])
         args = (category, start, start + 1 / 60)
         # Save the marker
         results[category].append((args, {"background": FileHandler.colors[category]}))
     # If screen data does not contain mouse data, then return the
     # markers created so far
     if "clicks" not in dictionary or len(dictionary["clicks"]) == 0:
         return results
     """
     Screen Data
     """
     # This dictionary will hold when each button press was started
     buttons = {Button.left: None, Button.right: None}
     # This dictionary is for backwards compatibility, see loop
     buttons_press = {Button.left: False, Button.right: False}
     # Start looping over the data found in the screen dictionary
     for time, data in sorted(dictionary["clicks"].items()):
         # Backwards compatibility
         if isinstance(data, tuple):
             # The current interface for screen results
             button, press = data
             # Also for backwards-compatibility
             press = "press" in press if isinstance(press, str) else press
         else:
             # An older version of the interface saved only the button as value for the dictionary
             # This means that determining if the button was pressed has to be determined manually
             button = data
             # Does not support any other buttons than right and left
             if button not in (Button.left, Button.right):
                 continue
             # Update if the button was pressed
             buttons_press[button] = not buttons_press[button]
             press = buttons_press[button]
         # Determine the category of the button press
         category = "primaries" if button == Button.left else ("secondaries" if button == Button.right else None)
         if category is None:
             continue
         # If the button was actually pressed, then save the time for use later
         if press is True:
             buttons[button] = time
         # If the button was already pressed, then a new marker can be created
         else:
             results[category].append(
                 ((category, buttons[button], time), {"background": FileHandler.click_colors[category]})
             )
     return results
Пример #10
0
 def test_get_effect_allied(self):
     line = Parser.line_to_dictionary(self.LINE)
     effect = Parser.line_to_dictionary(self.EFFECT)
     self.assertTrue(Parser.get_effect_allied(effect["ability"]))
     self.assertFalse(Parser.get_effect_allied(line["ability"]))
Пример #11
0
 def test_get_event_category(self):
     line = Parser.line_to_dictionary(self.LINE)
     self.assertEqual(Parser.get_event_category(line, "2963000048240"), "dmgt_pri")
     line = Parser.line_to_dictionary(self.EFFECT)
     self.assertEqual(Parser.get_event_category(line, "2963000049645"), "other")