Introduction

In this chapter I define the module summarise_rpl and I reviews how to extract a Replay's metadata with sc2reader. This metadata will allow me to index the replays when they are processed to group them by player and race to construct the players' profiles.

Exported Functions

  • get_replay_info

The Replay Object

sc2reader loads replay files into Repaly objects. Once these objects are defined, users can access their data in two ways.

  • The user can access descriptive information about a Replay by calling on some of the object's attributes. This data is useful for indexing and organising purposes.

  • Second, the Replay can provide access to other objects representing the different events, entities and behaviours that make up a StarCraft II match. This data is helpful to calculate and compose the player's performance indicators.

The following code shows how one can load a Replay into a variable.

rps_path = Path("./test_replays")
game_path = str(rps_path/"Jagannatha LE.SC2Replay")
single_replay = sc2reader.load_replay(game_path)
single_replay
<sc2reader.resources.Replay at 0x228b4feda30>

Having defined the object, I can summarise the match's descriptive information as shown in the following code.

print(f'File path: {single_replay.filename}')
print(f'File hash: {single_replay.filehash}')
print(f'Version of the game in which the replay was played: ',
    f'{single_replay.release_string}')

print(f'Expansion (WoL: Wingd of Liberty, HotS: Heart of the Swarm, ',
    f'LotV: Legacy of the Void): {single_replay.expansion}')

print(f'Game region: {single_replay.region}')
print(f'Game category: {single_replay.category}')
print(f'Game type: {single_replay.game_type}')
print(f'Map: {single_replay.map_name}')
print(f'Date start (datetime.datetime): {single_replay.start_time}')
print(f'Date end (datetime.datetime): {single_replay.end_time}')
print(f'Duration in MM.SS (minutes.seconds): {single_replay.game_length}')
print(f'Duration in MM.SS (minutes.seconds): ',
    f'{type(single_replay.length.seconds)}')

print(f'Duration in frames: {single_replay.frames}')
print(f'Frames per Second: {single_replay.game_fps}')
print(f'Players dict: {single_replay.player}')
print(f'Winner : {single_replay.winner}')
File path: test_replays\Jagannatha LE.SC2Replay
File hash: ffdcccf847aa496305a76be69e4d53c28422d308d59015558a149bd9363d0268
Version of the game in which the replay was played:  5.0.6.83830
Expansion (WoL: Wingd of Liberty, HotS: Heart of the Swarm,  LotV: Legacy of the Void): LotV
Game region: us
Game category: Ladder
Game type: 1v1
Map: Jagannatha LE
Date start (datetime.datetime): 2021-02-24 02:43:16
Date end (datetime.datetime): 2021-02-24 02:53:06
Duration in MM.SS (minutes.seconds): 09.50
Duration in MM.SS (minutes.seconds):  <class 'int'>
Duration in frames: 13224
Frames per Second: 16.0
Players dict: {1: Player 1 - HDEspino (Protoss), 2: Player 2 - MxChrisxM (Terran)}
Winner : Team 2: Player 2 - MxChrisxM (Terran)

The Participant Object

Beyond the information contained in a Replay's attributes, users can call upon the Participant objects associated with it to complement this data. These Participant objects record the match's players, what races they played with, and their results.

As such, one can summarise the entities encountered in replays as follows:

  • A Participant is a Player and a User
  • An Observer is a User and not a Player
  • A Computer is a Player and not a User

(Kim, 2015, p. 37)

With this in mind, here I access the match participans' information as follows:

player_one = single_replay.player[1]
player_two = single_replay.player[2]
type(player_one)
sc2reader.objects.Participant

This way I locate the each Participant within a variable, which allows me to extract meaningful information from these objects, as I show bellow.

print(f'User Name: {player_one.name}')
print(f'Race played in match: {player_one.play_race}')
print(f'Match result: {player_one.result}')
print(f'Player ID: {player_one.pid}')
User Name: HDEspino
Race played in match: Protoss
Match result: Loss
Player ID: 1
print(f'User Name: {player_two.name}')
print(f'Race played in match: {player_two.play_race}')
print(f'Match result: {player_two.result}')
print(f'Player ID: {player_two.pid}')
User Name: MxChrisxM
Race played in match: Terran
Match result: Win
Player ID: 2

Functions

Considering all of the above, I define a function that summarises the information I need to index and organise a set of replays.

Data structures

First, I define a couple of frozen datacasses that can store the data I will extract from the Replay.

The Player_data class will store a sumary of each player's basic information.

class Player_data[source]

Player_data(player_number:int, username:str, race:str, result:str)

Immutable dataclass that contains Information that describes a player's attributes in a match.

Attributes:

- player_number (int):
    Player number in the match. In a 1v1, match there would be a
    Player 1 and 2.
- username (str):
    The player's user name.
- race (str):
    The game race (Protoss, Terran, Zerg) with which the player
    played this match.
- result (str):
    Variable descriving whether the player was the matches winner
    ('Win') or loser ('Loss').

The following is an example of this class.

p_one = Player_data(single_replay.player[1].pid, 
                    single_replay.player[1].name,
                    single_replay.player[1].play_race,
                    single_replay.player[1].result)

print(p_one)
Player Number:          1
User Name:       HDEspino
Race:             Protoss
Result:              Loss

Meanwhile, the Replay_data class stores the information on the match. This includes a list of Player_data instances that consolidate the information of the match's players in a single location.

class Replay_data[source]

Replay_data(replay_name:str, replay_id:str, date_time:datetime, game_length:int, match_type:str, game_release:str, map_name:str, category:str, winner:int, players:list[Player_data])

Immutable dataclass that contains information summarising a match's main attributes.

Attributes:

- replay_name (str):
    Absolute path of where the Replay was stored when uploaded.
- replay_id (str):
    Name of the SC2Replay file.
- date_time (datetime):
    Date and time when the match was played and recorded.
- game_length (int):
    Length of the match in seconds.
- match_type (str):
    Descrives the team configuration of the match (eg '1v1', '2v2').
- game_release (str):
    Version and patch number for the game release where the match
    played.
- map_name (str):
    Name of the match's map.
- category (str):
    Descrives if the match was 'Ladder' or other type of match.
- winner (str):
    User name of the match's winner
- players (list):
    Summarised information of the match's players (see Player_data
    class).

Helper Functions

To illustrate how this dataclass works, let me define a helper function (get_players) to iterate through the match's list of players converting each one into a Player_data instance and returning a new list with this summaries.

With this function, I can store a summary of the matches meta-data in a Replay_data instance like this:

match = Replay_data(
        replay_name= single_replay.filename,
        replay_id= Path(single_replay.filename).name,
        date_time= single_replay.date,
        game_length= single_replay.length.seconds,
        match_type= single_replay.game_type,
        game_release= single_replay.release_string,
        map_name= single_replay.map_name,
        category= single_replay.category,
        winner= single_replay.winner,
        players= get_players(single_replay.player)) # note the use of the
                                                    # helper function here

print(match)
File path:                   test_replays\Jagannatha LE.SC2Replay 
File name:                   Jagannatha LE.SC2Replay 
Date (datetime.datetime):    2021-02-24 02:53:06 
Duration (seconds):          590 
Game type:                   1v1 
Game release:                5.0.6.83830 
Map:                         Jagannatha LE 
Game category:               Ladder 
winner:                      Team 2: Player 2 - MxChrisxM (Terran) 
players:                     [(1, 'HDEspino', 'Protoss', 'Loss'), (2, 'MxChrisxM', 'Terran', 'Win')] 

Exported Functions

Having defined these data structures, I define the get_replay_info function which receives a Replay and returns its summary as a Replay_data instance.

get_replay_info[source]

get_replay_info(replay:Replay)

Extracts a summary of a match's general information into a Replay_data dataclass instance.

Args:

- replay (sc2reader.resources.Replay):
    Replay object to be analysed.

Returns:

- Replay_data
    Summary of a matches main descriptive information.

The following code demonstrates the use of this function.

match = get_replay_info(single_replay)
print(match)
File path:                   test_replays\Jagannatha LE.SC2Replay 
File name:                   Jagannatha LE.SC2Replay 
Date (datetime.datetime):    2021-02-24 02:53:06 
Duration (seconds):          590 
Game type:                   1v1 
Game release:                5.0.6.83830 
Map:                         Jagannatha LE 
Game category:               Ladder 
winner:                      2 
players:                     [(1, 'HDEspino', 'Protoss', 'Loss'), (2, 'MxChrisxM', 'Terran', 'Win')] 

References