예제 #1
0
    def parse(self, write_json=False):
        """ Parses the demofiles in self.match_dir

        Attributes:
            write_json (boolean) : Boolean indicating if JSON will write

        Returns:
            Dictionary of dictionaries, where the first level keys are maps, and the second level keys correspond to that map's set of data.
        """
        for f in self.demofiles:
            map_name = f[3:-4]
            parser = DemoParser(demofile=self.match_dir + f,
                                match_id=self.match_id)
            self.game_data[map_name] = parser.parse()
            if write_json:
                parser.write_json()
        return self.game_data
예제 #2
0
파일: main.py 프로젝트: Wazti/csgo-api
from csgo.parser import DemoParser

# Create parser object
# Set log=True above if you want to produce a logfile for the parser
demo_parser = DemoParser(
    demofile="DemoManager/SKADE/Inferno/18-04-2021&Young Ninjas.dem",
    match_id="astralis-vs-liquid-m1-inferno.dem")

# Parse the demofile, output results to dictionary with df name as key
data = demo_parser.parse()

# The following keys exist
data["Rounds"]
data["Kills"]
data["Damages"]
data["Grenades"]
data["BombEvents"]
data["Footsteps"]

# You can also write the demofile data to JSON using
demo_parser.write_json()
예제 #3
0
class TestDemoParser:
    """ Class to test the match parser
    """

    def setup_class(self):
        """ Setup class by instantiating parser
        """
        self.parser = DemoParser(
            demofile="tests/natus-vincere-vs-astralis-m1-dust2.dem",
            log=True,
            match_id="natus-vincere-vs-astralis-m1-dust2",
        )

    def teardown_class(self):
        """ Set parser to none
        """
        self.parser = None

    def test_match_id(self):
        """ Tests if a match_id is not given is parsed properly
        """
        self.parser = DemoParser(
            demofile="tests/natus-vincere-vs-astralis-m1-dust2.dem", log=True,
        )
        assert self.parser.match_id == "natus-vincere-vs-astralis-m1-dust2"

    def test_demo_error(self):
        """ Tests if the parser encountered a corrupted demofile. If it did, the
        parser would set the `demo_error` attribute to True. Since this demofile is
        not corrupted, this test should have parser.demo_error as FALSE
        """
        self.parser._parse_demofile()
        assert not self.parser.demo_error

    def test_logger(self):
        """ Tests if the parser logs correctly.
        """
        assert self.parser.logger.name == "CSGODemoParser"
        assert os.path.exists("csgo_parser.log")

    def test_parse_match(self):
        """ Tests if the parser parses the match without issue. Our test demo had 21 total rounds.
        """
        self.parser._parse_match()
        assert len(self.parser.rounds) == 21

    def test_parse(self):
        """ Tests if parse wrapper method works
        """
        output = self.parser.parse()
        assert not self.parser.demo_error
        assert len(self.parser.rounds) == 21
        assert len(output.keys()) == 7

    def test_clean_match(self):
        """ Tests if the clean_rounds works. Should still return 21.
        """
        self.parser._clean_rounds()
        assert len(self.parser.rounds) == 21

    def test_last_round_reason(self):
        """ Tests if the last round had the correct win reason. It should be "CTWin".
        """
        assert self.parser.rounds[-1].reason == "CTWin"

    def test_round_cash_eq(self):
        """ Tests if cash and equipment values are parsing properly.
        """
        assert self.parser.rounds[0].t_eq_val == 4050
        assert self.parser.rounds[0].ct_eq_val == 4400
        assert self.parser.rounds[0].t_cash_spent_total == 3550
        assert self.parser.rounds[0].ct_cash_spent_total == 3650
        assert self.parser.rounds[0].t_cash_spent_round == 3550
        assert self.parser.rounds[0].ct_cash_spent_round == 3650

    def test_round_type(self):
        """ Tests if round types are properly functioning.
        """
        assert self.parser.rounds[0].ct_round_type == "Pistol"
        assert self.parser.rounds[0].t_round_type == "Pistol"
        assert self.parser.rounds[1].ct_round_type == "Half Buy"
        assert self.parser.rounds[2].ct_round_type == "Eco"

    def test_kills_total(self):
        """ Tests if the kill totals are correct. s1mple should have 25 kills.
        """
        self.parser.write_kills()
        kills_df = self.parser.kills_df.groupby("AttackerName").size().reset_index()
        kills_df.columns = ["AttackerName", "Kills"]
        assert kills_df[kills_df["AttackerName"] == "s1mple"].Kills.values[0] == 25

    def test_bomb_plant(self):
        """ Tests for bomb plant events. There should be a plant and a defuse event for this round.
        """
        self.parser.write_bomb_events()
        bomb_df = self.parser.bomb_df
        assert (
            bomb_df.loc[bomb_df["RoundNum"] == 16, ["Tick", "EventType"]].shape[0] == 2
        )

    def test_damage_total(self):
        """ Tests for correct damage per round.
        """
        self.parser.write_damages()
        damage_df = self.parser.damages_df
        damage_df["Damage"] = damage_df["HpDamage"] + damage_df["ArmorDamage"]
        damage_df["KillDamage"] = damage_df["KillHpDamage"] + damage_df["ArmorDamage"]
        dmg = (
            (damage_df.groupby(["AttackerName"]).Damage.sum() / 21)
            .reset_index()
            .iloc[0, 1]
        )
        kill_dmg = (
            (damage_df.groupby(["AttackerName"]).KillDamage.sum() / 21)
            .reset_index()
            .iloc[0, 1]
        )
        assert (dmg == 94.9047619047619) and (kill_dmg == 88.23809523809524)

    def test_grenade_total(self):
        """ Tests for correct number of grenade events.
        """
        self.parser.write_grenades()
        grenades_df = self.parser.grenades_df
        assert grenades_df.shape[0] == 550

    def test_footsteps(self):
        """ Tests for correct trajectory parsing.
        """
        self.parser.write_footsteps()
        footsteps_df = self.parser.footsteps_df
        assert footsteps_df.iloc[777, :].X == 583.253906
        assert footsteps_df.iloc[777, :].Y == 592.542297
        assert footsteps_df.iloc[777, :].Z == 2.59956
        assert footsteps_df.iloc[777, :].XViz == 695.284979
        assert footsteps_df.iloc[777, :].YViz == -601.46766
        assert footsteps_df.iloc[777, :].AreaId == 1432
        assert footsteps_df.iloc[777, :].AreaName == "LongDoors"

    def test_write_data(self):
        """ Tests write data method.
        """
        df_dict = self.parser.write_data()
        assert len(df_dict.keys()) == 7
        assert df_dict["Rounds"].shape[0] == 21

    def test_parse_error(self):
        """ Tests if parser errors on bad file
        """
        self.parser = DemoParser(demofile="tests/file-no-exist.dem", match_id="test",)
        self.parser._parse_demofile()
        assert self.parser.demo_error == True

    def test_json_write(self):
        """ Tests if parser can write to JSON
        """
        self.parser.write_json()
        assert os.path.exists("natus-vincere-vs-astralis-m1-dust2_de_dust2.json")
        assert (
            os.path.getsize("natus-vincere-vs-astralis-m1-dust2_de_dust2.json")
            < 10000000
        )

    def test_json_write_with_footsteps(self):
        """ Tests if parser can write to JSON, including footsteps
        """
        self.parser.write_json(write_footsteps=True)
        assert os.path.exists("natus-vincere-vs-astralis-m1-dust2_de_dust2.json")
        assert (
            os.path.getsize("natus-vincere-vs-astralis-m1-dust2_de_dust2.json")
            > 10000000
        )

    def test_write_map_name(self):
        """ Tests if the parser writes the map name to a dictionary
        """
        df_dict = self.parser.write_data()
        assert df_dict["Map"] == "de_dust2"