telemetry.core.logic
Docstring for telemetry.core.logic
This module provides the logic for aggregating and analysing the data parsed by the parsing module, namely sorting by difficulty, getting averages by difficulty, etc...
This functionality is provided by the EventLogicEngine class.
1""" 2Docstring for telemetry.core.logic 3 4This module provides the logic for aggregating and analysing the data 5parsed by the parsing module, namely sorting by difficulty, getting 6averages by difficulty, etc... 7 8This functionality is provided by the EventLogicEngine class. 9""" 10 11from pathlib import Path 12 13from telemetry.core.events import ( 14 BossEncounterComplete, 15 BossEncounterFail, 16 BossEncounterStart, 17 BuyUpgrade, 18 Difficulty, 19 EndSession, 20 GainCoin, 21 KillEnemy, 22 NormalEncounterComplete, 23 NormalEncounterFail, 24 NormalEncounterStart, 25 SettingsChange, 26 StartSession, 27) 28from telemetry.core.parsing import parse_file, ValidEvent 29 30 31class EventLogicEngine: 32 def __init__(self): 33 self.start_session_events: set[ 34 StartSession 35 ] = set() 36 self.end_session_events: set[ 37 EndSession 38 ] = set() 39 self.normal_encounter_start_events: set[ 40 NormalEncounterStart 41 ] = set() 42 self.normal_encounter_complete_events: set[ 43 NormalEncounterComplete 44 ] = set() 45 self.normal_encounter_fail_events: set[ 46 NormalEncounterFail 47 ] = set() 48 self.boss_encounter_start_events: set[ 49 BossEncounterStart 50 ] = set() 51 self.boss_encounter_complete_events: set[ 52 BossEncounterComplete 53 ] = set() 54 self.boss_encounter_fail_events: set[ 55 BossEncounterFail 56 ] = set() 57 self.gain_coin_events: set[ 58 GainCoin 59 ] = set() 60 self.buy_upgrade_events: set[ 61 BuyUpgrade 62 ] = set() 63 self.settings_change_events: set[ 64 SettingsChange 65 ] = set() 66 self.kill_enemy_events: set[ 67 KillEnemy 68 ] = set() 69 70 self._attributes = [ 71 self.start_session_events, 72 self.end_session_events, 73 self.normal_encounter_start_events, 74 self.normal_encounter_complete_events, 75 self.normal_encounter_fail_events, 76 self.boss_encounter_start_events, 77 self.boss_encounter_complete_events, 78 self.boss_encounter_fail_events, 79 self.gain_coin_events, 80 self.buy_upgrade_events, 81 self.settings_change_events, 82 self.kill_enemy_events 83 ] 84 85 86 def categorise_events(self, filename: Path) -> None: 87 """ 88 Creates objects from the json file provided. 89 90 :param filename: json file with custom schema. 91 :type filename: Path 92 """ 93 # TODO: We would need to implement __eq__ methods for our 94 # event classes if we want the set() functionality of 95 # avoiding duplicates. Until then, temporary fix: clear the 96 # attributes before reading them back in again. 97 for attr in self._attributes: 98 attr.clear() 99 100 events: list[ValidEvent] = parse_file(filename) 101 for event in events: 102 if isinstance(event, StartSession): 103 self.start_session_events.add(event) 104 elif isinstance(event, EndSession): 105 self.end_session_events.add(event) 106 elif isinstance(event, NormalEncounterStart): 107 self.normal_encounter_start_events.add(event) 108 elif isinstance(event, NormalEncounterComplete): 109 self.normal_encounter_complete_events.add(event) 110 elif isinstance(event, NormalEncounterFail): 111 self.normal_encounter_fail_events.add(event) 112 elif isinstance(event, BossEncounterStart): 113 self.boss_encounter_start_events.add(event) 114 elif isinstance(event, BossEncounterComplete): 115 self.boss_encounter_complete_events.add(event) 116 elif isinstance(event, BossEncounterFail): 117 self.boss_encounter_fail_events.add(event) 118 elif isinstance(event, GainCoin): 119 self.gain_coin_events.add(event) 120 elif isinstance(event, BuyUpgrade): 121 self.buy_upgrade_events.add(event) 122 elif isinstance(event, SettingsChange): 123 self.settings_change_events.add(event) 124 elif isinstance(event, KillEnemy): 125 self.kill_enemy_events.add(event) 126 127 128 def fail_difficulty_spikes(self) -> dict[int, int]: 129 """ 130 Output failure rate by stage. 131 132 :return: dictionary of key stage number and value number of 133 failures. 134 :rtype: dict[int, int] 135 """ 136 difficulty_output = {stage_number: 0 for stage_number in range(1,11)} 137 for event in self.normal_encounter_fail_events: 138 difficulty_output[event.stage_number] += 1 139 for event in self.boss_encounter_fail_events: 140 difficulty_output[event.stage_number] += 1 141 return difficulty_output 142 143 144 def get_number_of_session_starts(self) -> int: 145 """ 146 Get the number of start session events. 147 148 :return: Returns the number of unique session start events. 149 :rtype: int 150 """ 151 return len(self.start_session_events) 152 153 154 def get_unique_userIDs(self) -> set[int]: 155 """ 156 Returns the set of unique user IDs. 157 158 :return: set of unique user IDs. 159 :rtype: set[int] 160 """ 161 uniqueIDs = set() 162 for event in self.start_session_events: 163 uniqueIDs.add(event.userID) 164 return uniqueIDs 165 166 167 def count_starts(self, stage_number) -> int: 168 """ 169 Counts the number of starts of a given stage. 170 171 :param stage_number: stage number in question. 172 :return: number of starts of that stage. 173 :rtype: int 174 """ 175 start_count = 0 176 if stage_number in [3, 6, 9, 10]: 177 for start_event in self.boss_encounter_start_events: 178 start_count += start_event.stage_number == stage_number 179 return start_count 180 for start_event in self.normal_encounter_start_events: 181 start_count += start_event.stage_number == stage_number 182 return start_count 183 184 185 def count_fails(self, stage_number) -> int: 186 """ 187 Counts the number of failures on a given stage. 188 189 :param stage_number: stage number in question. 190 :return: number of fails at that stage. 191 :rtype: int 192 """ 193 fail_count = 0 194 if stage_number in [3, 6, 9, 10]: 195 for fail_event in self.boss_encounter_fail_events: 196 fail_count += fail_event.stage_number == stage_number 197 return fail_count 198 for fail_event in self.normal_encounter_fail_events: 199 fail_count += fail_event.stage_number == stage_number 200 return fail_count 201 202 203 def funnel_view(self) -> dict[int, int]: 204 """ 205 Output number of players passing a given stage. 206 207 :return: dictionary of key stage number and value number of 208 players left. 209 :rtype: dict[int, int] 210 """ 211 return { 212 stage_number: 213 self.count_starts(stage_number) - self.count_fails(stage_number) 214 for stage_number in range(1,11) 215 } 216 217 218 def health_per_stage(self, sessionID: int) -> dict[int, int]: 219 """ 220 Output the health a session has per stage. 221 222 :param sessionID: session stage to check. 223 :type sessionID: int 224 :return: dictionary of key stage number and value player HP 225 remaining. 226 :rtype: dict[int, int] 227 """ 228 health_remaining_per_stage = {stage_number: 0 229 for stage_number in range(1,11)} 230 for event in self.normal_encounter_complete_events: 231 if event.sessionID == sessionID: 232 health_remaining_per_stage[ 233 event.stage_number 234 ] = event.player_HP_remaining 235 for event in self.boss_encounter_complete_events: 236 if event.sessionID == sessionID: 237 health_remaining_per_stage[ 238 event.stage_number 239 ] = event.player_HP_remaining 240 return health_remaining_per_stage 241 242 243 def get_difficulty(self, sessionID: int) -> Difficulty: 244 """ 245 Get the difficulty for a given session. 246 247 :param sessionID: sessionID of the session to get difficulty of. 248 :type sessionID: int 249 :return: Difficulty value of the session. 250 :rtype: Difficulty 251 """ 252 for start_event in self.start_session_events: 253 if start_event.sessionID == sessionID: 254 return start_event.difficulty 255 raise RuntimeError("No session start event for provided " \ 256 f"session ID: {sessionID}") 257 258 259 def get_sessionIDs_of_difficulty(self, difficulty: Difficulty) -> list[int]: 260 """ 261 Get the list of all sessionIDs of a given difficulty. 262 263 :param difficulty: The difficulty level to search for. 264 :type difficulty: Difficulty 265 :return: The list of sessionIDs with the given difficulty. 266 :rtype: list[int] 267 """ 268 difficulty_sessionIDs: list[int] = [] 269 for start_event in self.start_session_events: 270 if start_event.difficulty == difficulty: 271 difficulty_sessionIDs.append(start_event.sessionID) 272 return difficulty_sessionIDs 273 274 275 def get_health_per_stage_by_difficulty( 276 self, 277 difficulty: Difficulty 278 ) -> list[dict[int, int]]: 279 """ 280 Returns a health_per_stage dictionary for all sessions with a 281 given difficulty. 282 283 :param difficulty: Given difficulty. 284 :type difficulty: Difficulty 285 :return: List of health per stage for each session with the 286 specified difficulty level. 287 :rtype: list[dict[int, int]] 288 """ 289 health_per_stage = [] 290 for sessionID in self.get_sessionIDs_of_difficulty(difficulty): 291 health_per_stage.append(self.health_per_stage(sessionID)) 292 return health_per_stage 293 294 295 def compare_health_per_stage_per_difficulty( 296 self 297 ) -> dict[Difficulty, list[dict[int, int]]]: 298 """ 299 Get a dictionary with difficulty level as the key, and the list 300 of the health_per_stage objects of all sessions with that 301 difficulty level as the value. 302 303 :return: Dictionary of difficulty level to list of all 304 health_per_stage dictionaries of all sessions with the given 305 difficulty level. 306 :rtype: dict[Difficulty, list[dict[int, int]]] 307 """ 308 return {diff: self.get_health_per_stage_by_difficulty(diff) 309 for diff in Difficulty} 310 311 312 def get_coins_gained_per_stage( 313 self, 314 sessionID: int 315 ) -> dict[int, int]: 316 """ 317 Get the number of coins gained at each stage for a given 318 session. 319 320 :param sessionID: sessionID in question. 321 :type sessionID: int 322 :return: Stage number -> coins gained at that stage. 323 :rtype: dict[int, int] 324 """ 325 coins_gained_per_stage: dict[int, int] = {i: 0 for i in range(1, 11)} 326 for event in self.gain_coin_events: 327 if event.sessionID == sessionID: 328 coins_gained_per_stage[event.stage_number] += event.coins_gained 329 return coins_gained_per_stage 330 331 332 def get_coins_per_stage_by_difficulty( 333 self, 334 difficulty: Difficulty 335 ) -> list[dict[int, int]]: 336 """ 337 Returns the coins gained per stage dictionary for all sessions 338 with a given difficulty. 339 340 :param difficulty: Given difficulty. 341 :type difficulty: Difficulty 342 :return: List of coins per stage for each session with the 343 specified difficulty level. 344 :rtype: list[dict[int, int]] 345 """ 346 coins_per_stage = [] 347 for sessionID in self.get_sessionIDs_of_difficulty(difficulty): 348 coins_per_stage.append(self.get_coins_gained_per_stage(sessionID)) 349 return coins_per_stage 350 351 352 def compare_coins_per_stage_per_difficulty( 353 self 354 ) -> dict[Difficulty, list[dict[int, int]]]: 355 """ 356 Get a dictionary with difficulty level as the key, and the list 357 of the coins gained per stage dictionary objects of all sessions 358 with that difficulty level as the value. 359 360 :return: Dictionary of difficulty level to list of all 361 coins gained per stage dictionaries of all sessions with the 362 given difficulty level. 363 :rtype: dict[Difficulty, list[dict[int, int]]] 364 """ 365 return {diff: self.get_coins_per_stage_by_difficulty(diff) 366 for diff in Difficulty}
32class EventLogicEngine: 33 def __init__(self): 34 self.start_session_events: set[ 35 StartSession 36 ] = set() 37 self.end_session_events: set[ 38 EndSession 39 ] = set() 40 self.normal_encounter_start_events: set[ 41 NormalEncounterStart 42 ] = set() 43 self.normal_encounter_complete_events: set[ 44 NormalEncounterComplete 45 ] = set() 46 self.normal_encounter_fail_events: set[ 47 NormalEncounterFail 48 ] = set() 49 self.boss_encounter_start_events: set[ 50 BossEncounterStart 51 ] = set() 52 self.boss_encounter_complete_events: set[ 53 BossEncounterComplete 54 ] = set() 55 self.boss_encounter_fail_events: set[ 56 BossEncounterFail 57 ] = set() 58 self.gain_coin_events: set[ 59 GainCoin 60 ] = set() 61 self.buy_upgrade_events: set[ 62 BuyUpgrade 63 ] = set() 64 self.settings_change_events: set[ 65 SettingsChange 66 ] = set() 67 self.kill_enemy_events: set[ 68 KillEnemy 69 ] = set() 70 71 self._attributes = [ 72 self.start_session_events, 73 self.end_session_events, 74 self.normal_encounter_start_events, 75 self.normal_encounter_complete_events, 76 self.normal_encounter_fail_events, 77 self.boss_encounter_start_events, 78 self.boss_encounter_complete_events, 79 self.boss_encounter_fail_events, 80 self.gain_coin_events, 81 self.buy_upgrade_events, 82 self.settings_change_events, 83 self.kill_enemy_events 84 ] 85 86 87 def categorise_events(self, filename: Path) -> None: 88 """ 89 Creates objects from the json file provided. 90 91 :param filename: json file with custom schema. 92 :type filename: Path 93 """ 94 # TODO: We would need to implement __eq__ methods for our 95 # event classes if we want the set() functionality of 96 # avoiding duplicates. Until then, temporary fix: clear the 97 # attributes before reading them back in again. 98 for attr in self._attributes: 99 attr.clear() 100 101 events: list[ValidEvent] = parse_file(filename) 102 for event in events: 103 if isinstance(event, StartSession): 104 self.start_session_events.add(event) 105 elif isinstance(event, EndSession): 106 self.end_session_events.add(event) 107 elif isinstance(event, NormalEncounterStart): 108 self.normal_encounter_start_events.add(event) 109 elif isinstance(event, NormalEncounterComplete): 110 self.normal_encounter_complete_events.add(event) 111 elif isinstance(event, NormalEncounterFail): 112 self.normal_encounter_fail_events.add(event) 113 elif isinstance(event, BossEncounterStart): 114 self.boss_encounter_start_events.add(event) 115 elif isinstance(event, BossEncounterComplete): 116 self.boss_encounter_complete_events.add(event) 117 elif isinstance(event, BossEncounterFail): 118 self.boss_encounter_fail_events.add(event) 119 elif isinstance(event, GainCoin): 120 self.gain_coin_events.add(event) 121 elif isinstance(event, BuyUpgrade): 122 self.buy_upgrade_events.add(event) 123 elif isinstance(event, SettingsChange): 124 self.settings_change_events.add(event) 125 elif isinstance(event, KillEnemy): 126 self.kill_enemy_events.add(event) 127 128 129 def fail_difficulty_spikes(self) -> dict[int, int]: 130 """ 131 Output failure rate by stage. 132 133 :return: dictionary of key stage number and value number of 134 failures. 135 :rtype: dict[int, int] 136 """ 137 difficulty_output = {stage_number: 0 for stage_number in range(1,11)} 138 for event in self.normal_encounter_fail_events: 139 difficulty_output[event.stage_number] += 1 140 for event in self.boss_encounter_fail_events: 141 difficulty_output[event.stage_number] += 1 142 return difficulty_output 143 144 145 def get_number_of_session_starts(self) -> int: 146 """ 147 Get the number of start session events. 148 149 :return: Returns the number of unique session start events. 150 :rtype: int 151 """ 152 return len(self.start_session_events) 153 154 155 def get_unique_userIDs(self) -> set[int]: 156 """ 157 Returns the set of unique user IDs. 158 159 :return: set of unique user IDs. 160 :rtype: set[int] 161 """ 162 uniqueIDs = set() 163 for event in self.start_session_events: 164 uniqueIDs.add(event.userID) 165 return uniqueIDs 166 167 168 def count_starts(self, stage_number) -> int: 169 """ 170 Counts the number of starts of a given stage. 171 172 :param stage_number: stage number in question. 173 :return: number of starts of that stage. 174 :rtype: int 175 """ 176 start_count = 0 177 if stage_number in [3, 6, 9, 10]: 178 for start_event in self.boss_encounter_start_events: 179 start_count += start_event.stage_number == stage_number 180 return start_count 181 for start_event in self.normal_encounter_start_events: 182 start_count += start_event.stage_number == stage_number 183 return start_count 184 185 186 def count_fails(self, stage_number) -> int: 187 """ 188 Counts the number of failures on a given stage. 189 190 :param stage_number: stage number in question. 191 :return: number of fails at that stage. 192 :rtype: int 193 """ 194 fail_count = 0 195 if stage_number in [3, 6, 9, 10]: 196 for fail_event in self.boss_encounter_fail_events: 197 fail_count += fail_event.stage_number == stage_number 198 return fail_count 199 for fail_event in self.normal_encounter_fail_events: 200 fail_count += fail_event.stage_number == stage_number 201 return fail_count 202 203 204 def funnel_view(self) -> dict[int, int]: 205 """ 206 Output number of players passing a given stage. 207 208 :return: dictionary of key stage number and value number of 209 players left. 210 :rtype: dict[int, int] 211 """ 212 return { 213 stage_number: 214 self.count_starts(stage_number) - self.count_fails(stage_number) 215 for stage_number in range(1,11) 216 } 217 218 219 def health_per_stage(self, sessionID: int) -> dict[int, int]: 220 """ 221 Output the health a session has per stage. 222 223 :param sessionID: session stage to check. 224 :type sessionID: int 225 :return: dictionary of key stage number and value player HP 226 remaining. 227 :rtype: dict[int, int] 228 """ 229 health_remaining_per_stage = {stage_number: 0 230 for stage_number in range(1,11)} 231 for event in self.normal_encounter_complete_events: 232 if event.sessionID == sessionID: 233 health_remaining_per_stage[ 234 event.stage_number 235 ] = event.player_HP_remaining 236 for event in self.boss_encounter_complete_events: 237 if event.sessionID == sessionID: 238 health_remaining_per_stage[ 239 event.stage_number 240 ] = event.player_HP_remaining 241 return health_remaining_per_stage 242 243 244 def get_difficulty(self, sessionID: int) -> Difficulty: 245 """ 246 Get the difficulty for a given session. 247 248 :param sessionID: sessionID of the session to get difficulty of. 249 :type sessionID: int 250 :return: Difficulty value of the session. 251 :rtype: Difficulty 252 """ 253 for start_event in self.start_session_events: 254 if start_event.sessionID == sessionID: 255 return start_event.difficulty 256 raise RuntimeError("No session start event for provided " \ 257 f"session ID: {sessionID}") 258 259 260 def get_sessionIDs_of_difficulty(self, difficulty: Difficulty) -> list[int]: 261 """ 262 Get the list of all sessionIDs of a given difficulty. 263 264 :param difficulty: The difficulty level to search for. 265 :type difficulty: Difficulty 266 :return: The list of sessionIDs with the given difficulty. 267 :rtype: list[int] 268 """ 269 difficulty_sessionIDs: list[int] = [] 270 for start_event in self.start_session_events: 271 if start_event.difficulty == difficulty: 272 difficulty_sessionIDs.append(start_event.sessionID) 273 return difficulty_sessionIDs 274 275 276 def get_health_per_stage_by_difficulty( 277 self, 278 difficulty: Difficulty 279 ) -> list[dict[int, int]]: 280 """ 281 Returns a health_per_stage dictionary for all sessions with a 282 given difficulty. 283 284 :param difficulty: Given difficulty. 285 :type difficulty: Difficulty 286 :return: List of health per stage for each session with the 287 specified difficulty level. 288 :rtype: list[dict[int, int]] 289 """ 290 health_per_stage = [] 291 for sessionID in self.get_sessionIDs_of_difficulty(difficulty): 292 health_per_stage.append(self.health_per_stage(sessionID)) 293 return health_per_stage 294 295 296 def compare_health_per_stage_per_difficulty( 297 self 298 ) -> dict[Difficulty, list[dict[int, int]]]: 299 """ 300 Get a dictionary with difficulty level as the key, and the list 301 of the health_per_stage objects of all sessions with that 302 difficulty level as the value. 303 304 :return: Dictionary of difficulty level to list of all 305 health_per_stage dictionaries of all sessions with the given 306 difficulty level. 307 :rtype: dict[Difficulty, list[dict[int, int]]] 308 """ 309 return {diff: self.get_health_per_stage_by_difficulty(diff) 310 for diff in Difficulty} 311 312 313 def get_coins_gained_per_stage( 314 self, 315 sessionID: int 316 ) -> dict[int, int]: 317 """ 318 Get the number of coins gained at each stage for a given 319 session. 320 321 :param sessionID: sessionID in question. 322 :type sessionID: int 323 :return: Stage number -> coins gained at that stage. 324 :rtype: dict[int, int] 325 """ 326 coins_gained_per_stage: dict[int, int] = {i: 0 for i in range(1, 11)} 327 for event in self.gain_coin_events: 328 if event.sessionID == sessionID: 329 coins_gained_per_stage[event.stage_number] += event.coins_gained 330 return coins_gained_per_stage 331 332 333 def get_coins_per_stage_by_difficulty( 334 self, 335 difficulty: Difficulty 336 ) -> list[dict[int, int]]: 337 """ 338 Returns the coins gained per stage dictionary for all sessions 339 with a given difficulty. 340 341 :param difficulty: Given difficulty. 342 :type difficulty: Difficulty 343 :return: List of coins per stage for each session with the 344 specified difficulty level. 345 :rtype: list[dict[int, int]] 346 """ 347 coins_per_stage = [] 348 for sessionID in self.get_sessionIDs_of_difficulty(difficulty): 349 coins_per_stage.append(self.get_coins_gained_per_stage(sessionID)) 350 return coins_per_stage 351 352 353 def compare_coins_per_stage_per_difficulty( 354 self 355 ) -> dict[Difficulty, list[dict[int, int]]]: 356 """ 357 Get a dictionary with difficulty level as the key, and the list 358 of the coins gained per stage dictionary objects of all sessions 359 with that difficulty level as the value. 360 361 :return: Dictionary of difficulty level to list of all 362 coins gained per stage dictionaries of all sessions with the 363 given difficulty level. 364 :rtype: dict[Difficulty, list[dict[int, int]]] 365 """ 366 return {diff: self.get_coins_per_stage_by_difficulty(diff) 367 for diff in Difficulty}
87 def categorise_events(self, filename: Path) -> None: 88 """ 89 Creates objects from the json file provided. 90 91 :param filename: json file with custom schema. 92 :type filename: Path 93 """ 94 # TODO: We would need to implement __eq__ methods for our 95 # event classes if we want the set() functionality of 96 # avoiding duplicates. Until then, temporary fix: clear the 97 # attributes before reading them back in again. 98 for attr in self._attributes: 99 attr.clear() 100 101 events: list[ValidEvent] = parse_file(filename) 102 for event in events: 103 if isinstance(event, StartSession): 104 self.start_session_events.add(event) 105 elif isinstance(event, EndSession): 106 self.end_session_events.add(event) 107 elif isinstance(event, NormalEncounterStart): 108 self.normal_encounter_start_events.add(event) 109 elif isinstance(event, NormalEncounterComplete): 110 self.normal_encounter_complete_events.add(event) 111 elif isinstance(event, NormalEncounterFail): 112 self.normal_encounter_fail_events.add(event) 113 elif isinstance(event, BossEncounterStart): 114 self.boss_encounter_start_events.add(event) 115 elif isinstance(event, BossEncounterComplete): 116 self.boss_encounter_complete_events.add(event) 117 elif isinstance(event, BossEncounterFail): 118 self.boss_encounter_fail_events.add(event) 119 elif isinstance(event, GainCoin): 120 self.gain_coin_events.add(event) 121 elif isinstance(event, BuyUpgrade): 122 self.buy_upgrade_events.add(event) 123 elif isinstance(event, SettingsChange): 124 self.settings_change_events.add(event) 125 elif isinstance(event, KillEnemy): 126 self.kill_enemy_events.add(event)
Creates objects from the json file provided.
Parameters
- filename: json file with custom schema.
129 def fail_difficulty_spikes(self) -> dict[int, int]: 130 """ 131 Output failure rate by stage. 132 133 :return: dictionary of key stage number and value number of 134 failures. 135 :rtype: dict[int, int] 136 """ 137 difficulty_output = {stage_number: 0 for stage_number in range(1,11)} 138 for event in self.normal_encounter_fail_events: 139 difficulty_output[event.stage_number] += 1 140 for event in self.boss_encounter_fail_events: 141 difficulty_output[event.stage_number] += 1 142 return difficulty_output
Output failure rate by stage.
Returns
dictionary of key stage number and value number of failures.
145 def get_number_of_session_starts(self) -> int: 146 """ 147 Get the number of start session events. 148 149 :return: Returns the number of unique session start events. 150 :rtype: int 151 """ 152 return len(self.start_session_events)
Get the number of start session events.
Returns
Returns the number of unique session start events.
155 def get_unique_userIDs(self) -> set[int]: 156 """ 157 Returns the set of unique user IDs. 158 159 :return: set of unique user IDs. 160 :rtype: set[int] 161 """ 162 uniqueIDs = set() 163 for event in self.start_session_events: 164 uniqueIDs.add(event.userID) 165 return uniqueIDs
Returns the set of unique user IDs.
Returns
set of unique user IDs.
168 def count_starts(self, stage_number) -> int: 169 """ 170 Counts the number of starts of a given stage. 171 172 :param stage_number: stage number in question. 173 :return: number of starts of that stage. 174 :rtype: int 175 """ 176 start_count = 0 177 if stage_number in [3, 6, 9, 10]: 178 for start_event in self.boss_encounter_start_events: 179 start_count += start_event.stage_number == stage_number 180 return start_count 181 for start_event in self.normal_encounter_start_events: 182 start_count += start_event.stage_number == stage_number 183 return start_count
Counts the number of starts of a given stage.
Parameters
- stage_number: stage number in question.
Returns
number of starts of that stage.
186 def count_fails(self, stage_number) -> int: 187 """ 188 Counts the number of failures on a given stage. 189 190 :param stage_number: stage number in question. 191 :return: number of fails at that stage. 192 :rtype: int 193 """ 194 fail_count = 0 195 if stage_number in [3, 6, 9, 10]: 196 for fail_event in self.boss_encounter_fail_events: 197 fail_count += fail_event.stage_number == stage_number 198 return fail_count 199 for fail_event in self.normal_encounter_fail_events: 200 fail_count += fail_event.stage_number == stage_number 201 return fail_count
Counts the number of failures on a given stage.
Parameters
- stage_number: stage number in question.
Returns
number of fails at that stage.
204 def funnel_view(self) -> dict[int, int]: 205 """ 206 Output number of players passing a given stage. 207 208 :return: dictionary of key stage number and value number of 209 players left. 210 :rtype: dict[int, int] 211 """ 212 return { 213 stage_number: 214 self.count_starts(stage_number) - self.count_fails(stage_number) 215 for stage_number in range(1,11) 216 }
Output number of players passing a given stage.
Returns
dictionary of key stage number and value number of players left.
219 def health_per_stage(self, sessionID: int) -> dict[int, int]: 220 """ 221 Output the health a session has per stage. 222 223 :param sessionID: session stage to check. 224 :type sessionID: int 225 :return: dictionary of key stage number and value player HP 226 remaining. 227 :rtype: dict[int, int] 228 """ 229 health_remaining_per_stage = {stage_number: 0 230 for stage_number in range(1,11)} 231 for event in self.normal_encounter_complete_events: 232 if event.sessionID == sessionID: 233 health_remaining_per_stage[ 234 event.stage_number 235 ] = event.player_HP_remaining 236 for event in self.boss_encounter_complete_events: 237 if event.sessionID == sessionID: 238 health_remaining_per_stage[ 239 event.stage_number 240 ] = event.player_HP_remaining 241 return health_remaining_per_stage
Output the health a session has per stage.
Parameters
- sessionID: session stage to check.
Returns
dictionary of key stage number and value player HP remaining.
244 def get_difficulty(self, sessionID: int) -> Difficulty: 245 """ 246 Get the difficulty for a given session. 247 248 :param sessionID: sessionID of the session to get difficulty of. 249 :type sessionID: int 250 :return: Difficulty value of the session. 251 :rtype: Difficulty 252 """ 253 for start_event in self.start_session_events: 254 if start_event.sessionID == sessionID: 255 return start_event.difficulty 256 raise RuntimeError("No session start event for provided " \ 257 f"session ID: {sessionID}")
Get the difficulty for a given session.
Parameters
- sessionID: sessionID of the session to get difficulty of.
Returns
Difficulty value of the session.
260 def get_sessionIDs_of_difficulty(self, difficulty: Difficulty) -> list[int]: 261 """ 262 Get the list of all sessionIDs of a given difficulty. 263 264 :param difficulty: The difficulty level to search for. 265 :type difficulty: Difficulty 266 :return: The list of sessionIDs with the given difficulty. 267 :rtype: list[int] 268 """ 269 difficulty_sessionIDs: list[int] = [] 270 for start_event in self.start_session_events: 271 if start_event.difficulty == difficulty: 272 difficulty_sessionIDs.append(start_event.sessionID) 273 return difficulty_sessionIDs
Get the list of all sessionIDs of a given difficulty.
Parameters
- difficulty: The difficulty level to search for.
Returns
The list of sessionIDs with the given difficulty.
276 def get_health_per_stage_by_difficulty( 277 self, 278 difficulty: Difficulty 279 ) -> list[dict[int, int]]: 280 """ 281 Returns a health_per_stage dictionary for all sessions with a 282 given difficulty. 283 284 :param difficulty: Given difficulty. 285 :type difficulty: Difficulty 286 :return: List of health per stage for each session with the 287 specified difficulty level. 288 :rtype: list[dict[int, int]] 289 """ 290 health_per_stage = [] 291 for sessionID in self.get_sessionIDs_of_difficulty(difficulty): 292 health_per_stage.append(self.health_per_stage(sessionID)) 293 return health_per_stage
Returns a health_per_stage dictionary for all sessions with a given difficulty.
Parameters
- difficulty: Given difficulty.
Returns
List of health per stage for each session with the specified difficulty level.
296 def compare_health_per_stage_per_difficulty( 297 self 298 ) -> dict[Difficulty, list[dict[int, int]]]: 299 """ 300 Get a dictionary with difficulty level as the key, and the list 301 of the health_per_stage objects of all sessions with that 302 difficulty level as the value. 303 304 :return: Dictionary of difficulty level to list of all 305 health_per_stage dictionaries of all sessions with the given 306 difficulty level. 307 :rtype: dict[Difficulty, list[dict[int, int]]] 308 """ 309 return {diff: self.get_health_per_stage_by_difficulty(diff) 310 for diff in Difficulty}
Get a dictionary with difficulty level as the key, and the list of the health_per_stage objects of all sessions with that difficulty level as the value.
Returns
Dictionary of difficulty level to list of all health_per_stage dictionaries of all sessions with the given difficulty level.
313 def get_coins_gained_per_stage( 314 self, 315 sessionID: int 316 ) -> dict[int, int]: 317 """ 318 Get the number of coins gained at each stage for a given 319 session. 320 321 :param sessionID: sessionID in question. 322 :type sessionID: int 323 :return: Stage number -> coins gained at that stage. 324 :rtype: dict[int, int] 325 """ 326 coins_gained_per_stage: dict[int, int] = {i: 0 for i in range(1, 11)} 327 for event in self.gain_coin_events: 328 if event.sessionID == sessionID: 329 coins_gained_per_stage[event.stage_number] += event.coins_gained 330 return coins_gained_per_stage
Get the number of coins gained at each stage for a given session.
Parameters
- sessionID: sessionID in question.
Returns
Stage number -> coins gained at that stage.
333 def get_coins_per_stage_by_difficulty( 334 self, 335 difficulty: Difficulty 336 ) -> list[dict[int, int]]: 337 """ 338 Returns the coins gained per stage dictionary for all sessions 339 with a given difficulty. 340 341 :param difficulty: Given difficulty. 342 :type difficulty: Difficulty 343 :return: List of coins per stage for each session with the 344 specified difficulty level. 345 :rtype: list[dict[int, int]] 346 """ 347 coins_per_stage = [] 348 for sessionID in self.get_sessionIDs_of_difficulty(difficulty): 349 coins_per_stage.append(self.get_coins_gained_per_stage(sessionID)) 350 return coins_per_stage
Returns the coins gained per stage dictionary for all sessions with a given difficulty.
Parameters
- difficulty: Given difficulty.
Returns
List of coins per stage for each session with the specified difficulty level.
353 def compare_coins_per_stage_per_difficulty( 354 self 355 ) -> dict[Difficulty, list[dict[int, int]]]: 356 """ 357 Get a dictionary with difficulty level as the key, and the list 358 of the coins gained per stage dictionary objects of all sessions 359 with that difficulty level as the value. 360 361 :return: Dictionary of difficulty level to list of all 362 coins gained per stage dictionaries of all sessions with the 363 given difficulty level. 364 :rtype: dict[Difficulty, list[dict[int, int]]] 365 """ 366 return {diff: self.get_coins_per_stage_by_difficulty(diff) 367 for diff in Difficulty}
Get a dictionary with difficulty level as the key, and the list of the coins gained per stage dictionary objects of all sessions with that difficulty level as the value.
Returns
Dictionary of difficulty level to list of all coins gained per stage dictionaries of all sessions with the given difficulty level.