telemetry.core.parsing

Docstring for telemetry.core.parsing

This module contains the logic for parsing game output json files. This module is responsible for reading the event log JSON files, and instantiating the ValidEvent object which corresponds to the event parsed.

  1"""
  2Docstring for telemetry.core.parsing
  3
  4This module contains the logic for parsing game output json files. This
  5module is responsible for reading the event log JSON files, and
  6instantiating the ValidEvent object which corresponds to the event 
  7parsed.
  8"""
  9
 10import json
 11from typing import TypeAlias
 12from datetime import datetime
 13from pathlib import Path
 14
 15from telemetry.core.events import (
 16    KillEnemy,
 17    EventParameter,
 18    BossEncounterFail,
 19    GainCoin,
 20    EventType,
 21    StartSession,
 22    BuyUpgrade,
 23    NormalEncounterStart,
 24    EndSession,
 25    NormalEncounterComplete,
 26    SettingsChange,
 27    BossEncounterComplete,
 28    NormalEncounterFail,
 29    BossEncounterStart,
 30)
 31
 32
 33ValidEvent: TypeAlias = (
 34    StartSession
 35    | NormalEncounterStart
 36    | NormalEncounterComplete
 37    | NormalEncounterFail
 38    | BossEncounterStart
 39    | BossEncounterComplete
 40    | BossEncounterFail
 41    | GainCoin
 42    | BuyUpgrade
 43    | EndSession
 44    | SettingsChange
 45    | KillEnemy
 46)
 47
 48    
 49def convert_time(time_string: str) -> datetime:
 50    """
 51    :param time_string: Custom formatted string of timestamp.
 52    :type time_string: str
 53    :return: Datetime version of time_string.
 54    :rtype: datetime
 55    """
 56    return datetime.strptime(time_string, "%Y/%m/%d/%H/%M/%S")
 57
 58
 59def get_file(filename: Path) -> list[dict]:
 60    """
 61    This function parses a json file and returns a list of json objects.
 62    
 63    :param filename: filename for json to be parsed.
 64    :type filename: Path
 65    :return: List of json objects.
 66    :rtype: list[dict[str, Any]]
 67    """
 68    try: 
 69        with open(filename, 'r') as f:
 70            return json.load(f)
 71    except FileNotFoundError:
 72        raise FileNotFoundError(f"Could not find file: {filename}")
 73    except json.JSONDecodeError:
 74        raise RuntimeError(f"Could not parse - invalid json.")
 75
 76
 77def parse_file(filename: Path) -> list[ValidEvent]:
 78    """
 79    Creates a list of ValidEvent objects from a json file.
 80    
 81    :param filename: filename for json to be parsed.
 82    :type filename: Path
 83    :return: List of valid event objects.
 84    :rtype: list[ValidEvent]
 85    """
 86    events = get_file(filename)
 87    event_objects = []
 88    for event in events:
 89        event_objects.append(parse_event(event))
 90    return event_objects
 91
 92
 93def parse_event(event: dict) -> ValidEvent:
 94    """
 95    Creates a ValidEvent object from a json object.
 96    
 97    :param event: json object for a single event.
 98    :type event: dict
 99    :return: Valid event object translated from the json object.
100    :rtype: ValidEvent
101    :raises RuntimeError: If an event of an unknown type is found, or 
102    a required field is missing.
103    """
104    try:
105        event_type = event[EventParameter.EVENT_TYPE]
106    except KeyError:
107        raise RuntimeError("Event must have an \"event\" field")
108    
109    try:
110        match event_type:
111            case EventType.START_SESSION:
112                return StartSession(
113                    event[EventParameter.USER_ID],
114                    event[EventParameter.SESSION_ID],
115                    convert_time(event[EventParameter.TIMESTAMP]),
116                    event[EventParameter.DIFFICULTY]
117                )
118            case EventType.END_SESSION:
119                return EndSession(
120                    event[EventParameter.USER_ID],
121                    event[EventParameter.SESSION_ID],
122                    convert_time(event[EventParameter.TIMESTAMP])
123                )
124            case EventType.NORMAL_ENCOUNTER_START:
125                return NormalEncounterStart(
126                    event[EventParameter.USER_ID],
127                    event[EventParameter.SESSION_ID],
128                    convert_time(event[EventParameter.TIMESTAMP]),
129                    event[EventParameter.ENCOUNTER],
130                    event[EventParameter.DIFFICULTY],
131                    event[EventParameter.STAGE_NUMBER]
132                )
133            case EventType.NORMAL_ENCOUNTER_COMPLETE:
134                return NormalEncounterComplete(
135                    event[EventParameter.USER_ID],
136                    event[EventParameter.SESSION_ID],
137                    convert_time(event[EventParameter.TIMESTAMP]),
138                    event[EventParameter.ENCOUNTER],
139                    event[EventParameter.DIFFICULTY],
140                    event[EventParameter.STAGE_NUMBER],
141                    event[EventParameter.PLAYER_HP_REMAINING]
142                )
143            case EventType.NORMAL_ENCOUNTER_FAIL:
144                return NormalEncounterFail(
145                    event[EventParameter.USER_ID],
146                    event[EventParameter.SESSION_ID],
147                    convert_time(event[EventParameter.TIMESTAMP]),
148                    event[EventParameter.ENCOUNTER],
149                    event[EventParameter.DIFFICULTY],
150                    event[EventParameter.STAGE_NUMBER],
151                    event[EventParameter.LIVES_LEFT]
152                )
153            case EventType.BOSS_ENCOUNTER_START:
154                return BossEncounterStart(
155                    event[EventParameter.USER_ID],
156                    event[EventParameter.SESSION_ID],
157                    convert_time(event[EventParameter.TIMESTAMP]),
158                    event[EventParameter.ENCOUNTER],
159                    event[EventParameter.DIFFICULTY],
160                    event[EventParameter.STAGE_NUMBER]
161                )
162            case EventType.BOSS_ENCOUNTER_COMPLETE:
163                return BossEncounterComplete(
164                    event[EventParameter.USER_ID],
165                    event[EventParameter.SESSION_ID],
166                    convert_time(event[EventParameter.TIMESTAMP]),
167                    event[EventParameter.ENCOUNTER],
168                    event[EventParameter.DIFFICULTY],
169                    event[EventParameter.STAGE_NUMBER],
170                    event[EventParameter.PLAYER_HP_REMAINING]
171                )
172            case EventType.BOSS_ENCOUNTER_FAIL:
173                return BossEncounterFail(
174                    event[EventParameter.USER_ID],
175                    event[EventParameter.SESSION_ID],
176                    convert_time(event[EventParameter.TIMESTAMP]),
177                    event[EventParameter.ENCOUNTER],
178                    event[EventParameter.DIFFICULTY],
179                    event[EventParameter.STAGE_NUMBER],
180                    event[EventParameter.LIVES_LEFT]
181                )
182            case EventType.GAIN_COIN:
183                return GainCoin(
184                    event[EventParameter.USER_ID],
185                    event[EventParameter.SESSION_ID],
186                    convert_time(event[EventParameter.TIMESTAMP]),
187                    event[EventParameter.ENCOUNTER],
188                    event[EventParameter.DIFFICULTY],
189                    event[EventParameter.STAGE_NUMBER],
190                    event[EventParameter.COINS_GAINED]
191                )
192            case EventType.BUY_UPGRADE:
193                return BuyUpgrade(
194                    event[EventParameter.USER_ID],
195                    event[EventParameter.SESSION_ID],
196                    convert_time(event[EventParameter.TIMESTAMP]),
197                    event[EventParameter.STAGE_NUMBER],
198                    event[EventParameter.COINS_SPENT],
199                    event[EventParameter.UPGRADE_BOUGHT]
200                )
201            case EventType.SETTINGS_CHANGE:
202                return SettingsChange(
203                    event[EventParameter.USER_ID],
204                    convert_time(event[EventParameter.TIMESTAMP]),
205                    event[EventParameter.SETTING],
206                    event[EventParameter.SETTING_VALUE]
207                )
208            case EventType.KILL_ENEMY:
209                return KillEnemy(
210                    event[EventParameter.USER_ID],
211                    event[EventParameter.SESSION_ID],
212                    convert_time(event[EventParameter.TIMESTAMP]),
213                    event[EventParameter.ENCOUNTER],
214                    event[EventParameter.DIFFICULTY],
215                    event[EventParameter.STAGE_NUMBER],
216                    event[EventParameter.ENEMY_TYPE]
217                )
218            case _:
219                raise RuntimeError(
220                    f"Unexpected event type: {event_type}"
221                )
222    except KeyError as e:
223        raise RuntimeError(
224            f"An event of type {event_type} is missing the field {e}"
225        )
def convert_time(time_string: str) -> datetime.datetime:
50def convert_time(time_string: str) -> datetime:
51    """
52    :param time_string: Custom formatted string of timestamp.
53    :type time_string: str
54    :return: Datetime version of time_string.
55    :rtype: datetime
56    """
57    return datetime.strptime(time_string, "%Y/%m/%d/%H/%M/%S")
Parameters
  • time_string: Custom formatted string of timestamp.
Returns

Datetime version of time_string.

def get_file(filename: pathlib.Path) -> list[dict]:
60def get_file(filename: Path) -> list[dict]:
61    """
62    This function parses a json file and returns a list of json objects.
63    
64    :param filename: filename for json to be parsed.
65    :type filename: Path
66    :return: List of json objects.
67    :rtype: list[dict[str, Any]]
68    """
69    try: 
70        with open(filename, 'r') as f:
71            return json.load(f)
72    except FileNotFoundError:
73        raise FileNotFoundError(f"Could not find file: {filename}")
74    except json.JSONDecodeError:
75        raise RuntimeError(f"Could not parse - invalid json.")

This function parses a json file and returns a list of json objects.

Parameters
  • filename: filename for json to be parsed.
Returns

List of json objects.

78def parse_file(filename: Path) -> list[ValidEvent]:
79    """
80    Creates a list of ValidEvent objects from a json file.
81    
82    :param filename: filename for json to be parsed.
83    :type filename: Path
84    :return: List of valid event objects.
85    :rtype: list[ValidEvent]
86    """
87    events = get_file(filename)
88    event_objects = []
89    for event in events:
90        event_objects.append(parse_event(event))
91    return event_objects

Creates a list of ValidEvent objects from a json file.

Parameters
  • filename: filename for json to be parsed.
Returns

List of valid event objects.

 94def parse_event(event: dict) -> ValidEvent:
 95    """
 96    Creates a ValidEvent object from a json object.
 97    
 98    :param event: json object for a single event.
 99    :type event: dict
100    :return: Valid event object translated from the json object.
101    :rtype: ValidEvent
102    :raises RuntimeError: If an event of an unknown type is found, or 
103    a required field is missing.
104    """
105    try:
106        event_type = event[EventParameter.EVENT_TYPE]
107    except KeyError:
108        raise RuntimeError("Event must have an \"event\" field")
109    
110    try:
111        match event_type:
112            case EventType.START_SESSION:
113                return StartSession(
114                    event[EventParameter.USER_ID],
115                    event[EventParameter.SESSION_ID],
116                    convert_time(event[EventParameter.TIMESTAMP]),
117                    event[EventParameter.DIFFICULTY]
118                )
119            case EventType.END_SESSION:
120                return EndSession(
121                    event[EventParameter.USER_ID],
122                    event[EventParameter.SESSION_ID],
123                    convert_time(event[EventParameter.TIMESTAMP])
124                )
125            case EventType.NORMAL_ENCOUNTER_START:
126                return NormalEncounterStart(
127                    event[EventParameter.USER_ID],
128                    event[EventParameter.SESSION_ID],
129                    convert_time(event[EventParameter.TIMESTAMP]),
130                    event[EventParameter.ENCOUNTER],
131                    event[EventParameter.DIFFICULTY],
132                    event[EventParameter.STAGE_NUMBER]
133                )
134            case EventType.NORMAL_ENCOUNTER_COMPLETE:
135                return NormalEncounterComplete(
136                    event[EventParameter.USER_ID],
137                    event[EventParameter.SESSION_ID],
138                    convert_time(event[EventParameter.TIMESTAMP]),
139                    event[EventParameter.ENCOUNTER],
140                    event[EventParameter.DIFFICULTY],
141                    event[EventParameter.STAGE_NUMBER],
142                    event[EventParameter.PLAYER_HP_REMAINING]
143                )
144            case EventType.NORMAL_ENCOUNTER_FAIL:
145                return NormalEncounterFail(
146                    event[EventParameter.USER_ID],
147                    event[EventParameter.SESSION_ID],
148                    convert_time(event[EventParameter.TIMESTAMP]),
149                    event[EventParameter.ENCOUNTER],
150                    event[EventParameter.DIFFICULTY],
151                    event[EventParameter.STAGE_NUMBER],
152                    event[EventParameter.LIVES_LEFT]
153                )
154            case EventType.BOSS_ENCOUNTER_START:
155                return BossEncounterStart(
156                    event[EventParameter.USER_ID],
157                    event[EventParameter.SESSION_ID],
158                    convert_time(event[EventParameter.TIMESTAMP]),
159                    event[EventParameter.ENCOUNTER],
160                    event[EventParameter.DIFFICULTY],
161                    event[EventParameter.STAGE_NUMBER]
162                )
163            case EventType.BOSS_ENCOUNTER_COMPLETE:
164                return BossEncounterComplete(
165                    event[EventParameter.USER_ID],
166                    event[EventParameter.SESSION_ID],
167                    convert_time(event[EventParameter.TIMESTAMP]),
168                    event[EventParameter.ENCOUNTER],
169                    event[EventParameter.DIFFICULTY],
170                    event[EventParameter.STAGE_NUMBER],
171                    event[EventParameter.PLAYER_HP_REMAINING]
172                )
173            case EventType.BOSS_ENCOUNTER_FAIL:
174                return BossEncounterFail(
175                    event[EventParameter.USER_ID],
176                    event[EventParameter.SESSION_ID],
177                    convert_time(event[EventParameter.TIMESTAMP]),
178                    event[EventParameter.ENCOUNTER],
179                    event[EventParameter.DIFFICULTY],
180                    event[EventParameter.STAGE_NUMBER],
181                    event[EventParameter.LIVES_LEFT]
182                )
183            case EventType.GAIN_COIN:
184                return GainCoin(
185                    event[EventParameter.USER_ID],
186                    event[EventParameter.SESSION_ID],
187                    convert_time(event[EventParameter.TIMESTAMP]),
188                    event[EventParameter.ENCOUNTER],
189                    event[EventParameter.DIFFICULTY],
190                    event[EventParameter.STAGE_NUMBER],
191                    event[EventParameter.COINS_GAINED]
192                )
193            case EventType.BUY_UPGRADE:
194                return BuyUpgrade(
195                    event[EventParameter.USER_ID],
196                    event[EventParameter.SESSION_ID],
197                    convert_time(event[EventParameter.TIMESTAMP]),
198                    event[EventParameter.STAGE_NUMBER],
199                    event[EventParameter.COINS_SPENT],
200                    event[EventParameter.UPGRADE_BOUGHT]
201                )
202            case EventType.SETTINGS_CHANGE:
203                return SettingsChange(
204                    event[EventParameter.USER_ID],
205                    convert_time(event[EventParameter.TIMESTAMP]),
206                    event[EventParameter.SETTING],
207                    event[EventParameter.SETTING_VALUE]
208                )
209            case EventType.KILL_ENEMY:
210                return KillEnemy(
211                    event[EventParameter.USER_ID],
212                    event[EventParameter.SESSION_ID],
213                    convert_time(event[EventParameter.TIMESTAMP]),
214                    event[EventParameter.ENCOUNTER],
215                    event[EventParameter.DIFFICULTY],
216                    event[EventParameter.STAGE_NUMBER],
217                    event[EventParameter.ENEMY_TYPE]
218                )
219            case _:
220                raise RuntimeError(
221                    f"Unexpected event type: {event_type}"
222                )
223    except KeyError as e:
224        raise RuntimeError(
225            f"An event of type {event_type} is missing the field {e}"
226        )

Creates a ValidEvent object from a json object.

Parameters
  • event: json object for a single event.
Returns

Valid event object translated from the json object.

Raises
  • RuntimeError: If an event of an unknown type is found, or a required field is missing.