From 995469aae0693990fe3941a4ae237751b86e9d00 Mon Sep 17 00:00:00 2001 From: Derek Hirotsu <132305781+derek-hirotsu@users.noreply.github.com> Date: Tue, 19 Sep 2023 09:56:16 -0700 Subject: [PATCH] Audit RDR2 (#31) * remove graphics presets * remove unused assets * pep8 lint * update readme * lint * add resolution func * implement get resolution stub for rdr2 --- F1_23/f1_23_utils.py | 2 +- reddeadredemption2/README.md | 46 ++------ .../images/1080/confirm_benchmark_1080.png | Bin 370 -> 0 bytes .../images/1080/exit_benchmark_1080.png | Bin 345 -> 0 bytes .../images/1080/graphics_1080.png | Bin 4429 -> 0 bytes .../images/1080/run_benchmark_x_1080.png | Bin 550 -> 0 bytes .../images/1080/settings_z_1080.png | Bin 415 -> 0 bytes reddeadredemption2/manifest.yaml | 6 +- reddeadredemption2/presets/system_sample.xml | 103 ------------------ reddeadredemption2/pyproject.toml | 21 ---- .../red_dead_redemption_2_utils.py | 38 ++++++- reddeadredemption2/reddeadredemption2.py | 58 +++++----- 12 files changed, 76 insertions(+), 198 deletions(-) delete mode 100644 reddeadredemption2/images/1080/confirm_benchmark_1080.png delete mode 100644 reddeadredemption2/images/1080/exit_benchmark_1080.png delete mode 100644 reddeadredemption2/images/1080/graphics_1080.png delete mode 100644 reddeadredemption2/images/1080/run_benchmark_x_1080.png delete mode 100644 reddeadredemption2/images/1080/settings_z_1080.png delete mode 100644 reddeadredemption2/presets/system_sample.xml delete mode 100644 reddeadredemption2/pyproject.toml diff --git a/F1_23/f1_23_utils.py b/F1_23/f1_23_utils.py index 40461e0..d0324cb 100644 --- a/F1_23/f1_23_utils.py +++ b/F1_23/f1_23_utils.py @@ -4,7 +4,7 @@ import re import winreg import logging -def get_resolution() -> tuple[int]: +def get_resolution() -> tuple[int]: """Gets resolution width and height from local xml file created by game.""" username = os.getlogin() config_path = f"C:\\Users\\{username}\\Documents\\My Games\\F1 22\\hardwaresettings" diff --git a/reddeadredemption2/README.md b/reddeadredemption2/README.md index dc2876a..5eb3068 100644 --- a/reddeadredemption2/README.md +++ b/reddeadredemption2/README.md @@ -1,45 +1,15 @@ # Red Dead Redemption 2 +This script navigates through in-game menus to the built in benchmark and runs it with the current settings. + ## Prerequisites - Python 3.10+ -- Red Dead Redemp installed. +- Red Dead Redemption 2 installed via Steam. -## Setup - - 1. Follow the setup instructions for the framework. If you have done so, all required python dependencies *should* be installed. - 2. Install Red Dead Redemption 2 from steam. - 1. Location does not matter, this harness uses steam to launch the game. - -## Configuration - -Below is an example use of this harness as a test in a benchmark configuration. - -```yaml -... -... -tests: - - name: reddeadredemption2 - executable: "reddeadredemption2.py" - process_name: "RDR2.exe" - output_dir: - - 'harness/reddeadredemption2/run' -``` - -__name__ : _(required)_ name of the test. This much match the name of a directory in the harness folder so the framework -can find the executable and any supplementary files. - -__executable__ : _(required)_ the entry point to the test harness. In this case a python script. - -__process_name__ : _(required)_ The process name that should be the target for FPS recording (ex: PresentMon). - -__output_dir__: _(optional)_ Directory containing files to aggregate copies of after a successful test run. If a directory path is -given, the contents are copied. - -__args__ : _(optional)_ list of arguments to be appended to the command to execute. All the arguments will be passed to -the executable when invoked by the framework. - -### Arguments - -## Common Issues +## Output +report.json +- `resolution`: string representing the resolution the test was run at, formatted as "[width]x[heigt]", e.x. `1920x1080` +- `start_time`: number representing a timestamp of the test's start time in milliseconds +- `end_time`: number representing a timestamp of the test's end time in milliseconds diff --git a/reddeadredemption2/images/1080/confirm_benchmark_1080.png b/reddeadredemption2/images/1080/confirm_benchmark_1080.png deleted file mode 100644 index f8493624976b8131844547a577c8e3754cd5165a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 370 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 TQeA8?00000NkvXXu0mjf%_-3S diff --git a/reddeadredemption2/images/1080/run_benchmark_x_1080.png b/reddeadredemption2/images/1080/run_benchmark_x_1080.png deleted file mode 100644 index 05fbfcbdf8d1638a564ab3705baf5d95dce4514d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 550 zcmV+>0@?kEP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D01|XXSaefwW^{L9 za%BKVa%E+1b7*gLUR4MM0004 zGSiY)vuGJCuDM{bSTtCd2V(GnVNEQ8WtesE&%5V6Y@W*-FYOl&=i{;;dOwu(AIW8z zkjpZGB}`x>2!)%uh-A#GtGEN$iQGQfTmWfAv%sjT{d#E<#Gv)V7*>bmyMk4dcEqp4pY0` z#^s|f8#x({Mzh(3tkr7WZa3<(k(1&02@~RKwW2N?Ihkcy(2U1p#NlvAT{aT3{eEAm zRG`^xHi&q-;y9)m4++_PK8M3FjQjoGXf%-fzE3kAT-oFC=yW;|;6+Ah+ct93G{uw& zSGL>j@O7}=Zc&PdxLhtrQ6v^{;L1j$(Z@HqYACT=qMXfUVgU!14EOgJYP~d{&nLCs oA#p(dPAPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D01|XXSaefwW^{L9 za%BKVa%E+1b7*gLUR4MM0003NNkl&tsq6aj|Jt_2iI$)jMG;`0 z=WW}D6D<*M97n@2z{~R-CvqZQQ51l|+v)orCvqa5@B82dL4dzGvAwSAG))7qEK8g? zvArzI05eTRnZQIMT;KYpK>$o z7I - - - - kSettingsConfig_Auto - - kSettingLevel_High - kSettingLevel_Ultra - kSettingLevel_High - kSettingLevel_Low - kSettingLevel_Ultra - kSettingLevel_Ultra - kSettingLevel_Ultra - kSettingLevel_Medium - kSettingLevel_High - kSettingLevel_Ultra - kSettingLevel_Ultra - kSettingLevel_Ultra - - - - kSettingLevel_High - - - - - - - - - - - - kSettingAPI_Vulkan - - - - kSettingLevel_Ultra - - - kSettingLevel_Medium - - kSettingLevel_High - kSettingLevel_High - - kSettingLevel_Ultra - kSettingLevel_Medium - - kSettingLevel_High - - - - - - - kSettingLevel_Ultra - kSettingLevel_Ultra - kSettingLevel_Ultra - - kSettingLevel_High - - kSettingLevel_High - - - - - kSettingLevel_Low - - - - kSettingLevel_Ultra - - kSettingScale_Mode1o1 - - - - - - - kSettingLevel_Medium - kSettingLevel_High - - - - NVIDIA NVIDIA GeForce RTX 3080 Ti - \ No newline at end of file diff --git a/reddeadredemption2/pyproject.toml b/reddeadredemption2/pyproject.toml deleted file mode 100644 index f5e78dd..0000000 --- a/reddeadredemption2/pyproject.toml +++ /dev/null @@ -1,21 +0,0 @@ -[tool.poetry] -name = "reddeadredemption2-harness" -version = "0.1.0" -description = "" -authors = ["Nikolas Harris =1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/reddeadredemption2/red_dead_redemption_2_utils.py b/reddeadredemption2/red_dead_redemption_2_utils.py index 26dc5df..ec78f3a 100644 --- a/reddeadredemption2/red_dead_redemption_2_utils.py +++ b/reddeadredemption2/red_dead_redemption_2_utils.py @@ -1,3 +1,35 @@ -# stub -def get_resolution(config_path: str) -> tuple[int]: - return 0, 0 \ No newline at end of file +"""Utility functions supporting RDR2 test script.""" +import getpass +import pathlib +import re + + +def get_resolution() -> tuple[int]: + """Gets resolution width and height from local xml file created by game.""" + # C:\Users\User\Documents\Rockstar Games\Red Dead Redemption 2\Settings\system.xml" + path = pathlib.Path( + "C:/Users/", getpass.getuser(), + "Documents", "Rockstar Games", "Red Dead Redemption 2", "Settings", + "system.xml" + ) + width = "0" + height = "0" + + screen_width = re.compile(r"") + screen_height = re.compile(r"") + + try: + with open(path, encoding="utf-8") as file: + lines = file.readlines() + for line in lines: + width_match = screen_width.search(line) + height_match = screen_height.search(line) + if width_match is not None: + width = width_match.group(1) + if height_match is not None: + height = height_match.group(1) + except OSError: + width = "0" + height = "0" + + return (width, height) diff --git a/reddeadredemption2/reddeadredemption2.py b/reddeadredemption2/reddeadredemption2.py index f87dcf0..a2b6806 100644 --- a/reddeadredemption2/reddeadredemption2.py +++ b/reddeadredemption2/reddeadredemption2.py @@ -1,49 +1,58 @@ +"""Red Dead Redemption 2 test script""" import logging import os -import pydirectinput as user import time from subprocess import Popen import sys +import pydirectinput as user from red_dead_redemption_2_utils import get_resolution sys.path.insert(1, os.path.join(sys.path[0], '..')) -from harness_utils.logging import * +#pylint: disable=wrong-import-position +from harness_utils.logging import ( + format_resolution, + seconds_to_milliseconds, + setup_log_directory, + write_report_json, + DEFAULT_LOGGING_FORMAT, + DEFAULT_DATE_FORMAT, +) from harness_utils.process import terminate_processes from harness_utils.steam import get_run_game_id_command, DEFAULT_EXECUTABLE_PATH as STEAM_PATH +#pylint: enable=wrong-import-position STEAM_GAME_ID = 1174180 PROCESS_NAME = "RDR2" SCRIPT_DIRECTORY = os.path.dirname(os.path.realpath(__file__)) LOG_DIRECTORY = os.path.join(SCRIPT_DIRECTORY, "run") -config_path = os.path.join(os.environ["HOMEPATH"], "Documents" ,"Rockstar Games", "Red Dead Redemption 2", "Settings", "system.xml") +config_path = os.path.join( + os.environ["HOMEPATH"], "Documents" ,"Rockstar Games", + "Red Dead Redemption 2", "Settings", "system.xml" +) def start_game(): + """Starts the game via steam command""" steam_run_arg = get_run_game_id_command(STEAM_GAME_ID) - logging.info(STEAM_PATH + " " + steam_run_arg) + logging.info("%s %s", STEAM_PATH, steam_run_arg) return Popen([STEAM_PATH, steam_run_arg]) def run_benchmark(): - ## + """Starts the benchmark""" # Wait for game to load to main menu - ## - t1 = time.time() + setup_start_time = time.time() start_game() time.sleep(65) - ## # Press Z to enter settings - ## user.press("z") time.sleep(3) - ## # Enter graphics menu - ## ## ensure we are starting from the top left of the screen user.press("up") user.press("up") @@ -54,31 +63,26 @@ def run_benchmark(): user.press("enter") time.sleep(3) - ## # Run benchmark by holding X for 2 seconds - ## user.keyDown('x') time.sleep(1.5) user.keyUp("x") - ## # Press enter to confirm benchmark - ## - t2 = time.time() - logging.info(f"Harness setup took {round((t2 - t1), 2)} seconds") + elapsed_setup_time = round(time.time() - setup_start_time, 2) + logging.info("Setup took %f seconds", elapsed_setup_time) user.press("enter") - start_time = time.time() + test_start_time = time.time() - ## # Wait for the benchmark to complete - ## time.sleep(315) # 5 min, 15 seconds. - end_time = time.time() - logging.info(f"Benchark took {round((end_time - start_time), 2)} seconds") + test_end_time = time.time() + elapsed_test_time = round(test_end_time - test_start_time, 2) + logging.info("Benchmark took %f seconds", elapsed_test_time) # Exit terminate_processes(PROCESS_NAME) - return start_time, end_time + return test_start_time, test_end_time setup_log_directory(LOG_DIRECTORY) @@ -95,16 +99,16 @@ logging.getLogger('').addHandler(console) try: start_time, end_time = run_benchmark() width, height = get_resolution(config_path) - result = { + report = { "resolution": format_resolution(width, height), - "graphics_preset": "current", "start_time": seconds_to_milliseconds(start_time), "end_time": seconds_to_milliseconds(end_time) } - write_report_json(LOG_DIRECTORY, "report.json", result) + write_report_json(LOG_DIRECTORY, "report.json", report) +#pylint: disable=broad-exception-caught except Exception as e: logging.error("Something went wrong running the benchmark!") logging.exception(e) terminate_processes(PROCESS_NAME) - exit(1) + sys.exit(1)