-
Notifications
You must be signed in to change notification settings - Fork 0
F1 replay file sources #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
GamesDat/Telemetry/Sources/Formula1/F12022RaceReplaySource.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| namespace GamesDat.Core.Telemetry.Sources.Formula1 | ||
| { | ||
| /// <summary> | ||
| /// File watcher source for F1 2022 race replay files. | ||
| /// Monitors: Documents\My Games\F1 22\replays | ||
| /// </summary> | ||
| public class F12022RaceReplaySource : F1RaceReplaySourceBase | ||
| { | ||
| public F12022RaceReplaySource(FileWatcherOptions options) | ||
| : base(ApplyDefaults(options)) | ||
| { | ||
| } | ||
|
|
||
| public F12022RaceReplaySource(string? customPath = null) | ||
| : base(CreateDefaultOptions(customPath ?? GetDefaultReplayPath())) | ||
| { | ||
| } | ||
|
|
||
| public static string GetDefaultReplayPath() => GetReplayPathForYear("22"); | ||
|
|
||
| /// <summary> | ||
| /// Ensure options has a path set, defaulting to F1 22 if not provided | ||
| /// </summary> | ||
| private static FileWatcherOptions EnsurePath(FileWatcherOptions options) | ||
| { | ||
| if (string.IsNullOrEmpty(options.Path)) | ||
| { | ||
| return new FileWatcherOptions | ||
| { | ||
| Path = GetDefaultReplayPath(), | ||
| Patterns = options.Patterns, | ||
| IncludeSubdirectories = options.IncludeSubdirectories, | ||
| DebounceDelay = options.DebounceDelay | ||
| }; | ||
| } | ||
| return options; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Apply F1 22-specific defaults. Used by test discovery. | ||
| /// </summary> | ||
| private static new FileWatcherOptions ApplyDefaults(FileWatcherOptions options) | ||
| { | ||
| return F1RaceReplaySourceBase.ApplyDefaults(EnsurePath(options)); | ||
| } | ||
| } | ||
| } | ||
47 changes: 47 additions & 0 deletions
47
GamesDat/Telemetry/Sources/Formula1/F12023RaceReplaySource.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| namespace GamesDat.Core.Telemetry.Sources.Formula1 | ||
| { | ||
| /// <summary> | ||
| /// File watcher source for F1 2023 race replay files. | ||
| /// Monitors: Documents\My Games\F1 23\replays | ||
| /// </summary> | ||
| public class F12023RaceReplaySource : F1RaceReplaySourceBase | ||
| { | ||
| public F12023RaceReplaySource(FileWatcherOptions options) | ||
| : base(ApplyDefaults(options)) | ||
| { | ||
| } | ||
|
|
||
| public F12023RaceReplaySource(string? customPath = null) | ||
| : base(CreateDefaultOptions(customPath ?? GetDefaultReplayPath())) | ||
| { | ||
| } | ||
|
|
||
| public static string GetDefaultReplayPath() => GetReplayPathForYear("23"); | ||
|
|
||
| /// <summary> | ||
| /// Ensure options has a path set, defaulting to F1 23 if not provided | ||
| /// </summary> | ||
| private static FileWatcherOptions EnsurePath(FileWatcherOptions options) | ||
| { | ||
| if (string.IsNullOrEmpty(options.Path)) | ||
| { | ||
| return new FileWatcherOptions | ||
| { | ||
| Path = GetDefaultReplayPath(), | ||
| Patterns = options.Patterns, | ||
| IncludeSubdirectories = options.IncludeSubdirectories, | ||
| DebounceDelay = options.DebounceDelay | ||
| }; | ||
| } | ||
| return options; | ||
| } | ||
|
codegefluester marked this conversation as resolved.
|
||
|
|
||
| /// <summary> | ||
| /// Apply F1 23-specific defaults. Used by test discovery. | ||
| /// </summary> | ||
| private static new FileWatcherOptions ApplyDefaults(FileWatcherOptions options) | ||
| { | ||
| return F1RaceReplaySourceBase.ApplyDefaults(EnsurePath(options)); | ||
| } | ||
| } | ||
| } | ||
47 changes: 47 additions & 0 deletions
47
GamesDat/Telemetry/Sources/Formula1/F12024RaceReplaySource.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| namespace GamesDat.Core.Telemetry.Sources.Formula1 | ||
| { | ||
| /// <summary> | ||
| /// File watcher source for F1 2024 race replay files. | ||
| /// Monitors: Documents\My Games\F1 24\replays | ||
| /// </summary> | ||
| public class F12024RaceReplaySource : F1RaceReplaySourceBase | ||
| { | ||
| public F12024RaceReplaySource(FileWatcherOptions options) | ||
| : base(ApplyDefaults(options)) | ||
| { | ||
| } | ||
|
|
||
| public F12024RaceReplaySource(string? customPath = null) | ||
| : base(CreateDefaultOptions(customPath ?? GetDefaultReplayPath())) | ||
| { | ||
| } | ||
|
|
||
| public static string GetDefaultReplayPath() => GetReplayPathForYear("24"); | ||
|
|
||
| /// <summary> | ||
| /// Ensure options has a path set, defaulting to F1 24 if not provided | ||
| /// </summary> | ||
| private static FileWatcherOptions EnsurePath(FileWatcherOptions options) | ||
| { | ||
| if (string.IsNullOrEmpty(options.Path)) | ||
| { | ||
| return new FileWatcherOptions | ||
| { | ||
| Path = GetDefaultReplayPath(), | ||
| Patterns = options.Patterns, | ||
| IncludeSubdirectories = options.IncludeSubdirectories, | ||
| DebounceDelay = options.DebounceDelay | ||
| }; | ||
| } | ||
| return options; | ||
| } | ||
|
codegefluester marked this conversation as resolved.
|
||
|
|
||
| /// <summary> | ||
| /// Apply F1 24-specific defaults. Used by test discovery. | ||
| /// </summary> | ||
| private static new FileWatcherOptions ApplyDefaults(FileWatcherOptions options) | ||
| { | ||
| return F1RaceReplaySourceBase.ApplyDefaults(EnsurePath(options)); | ||
| } | ||
| } | ||
| } | ||
47 changes: 47 additions & 0 deletions
47
GamesDat/Telemetry/Sources/Formula1/F12025RaceReplaySource.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| namespace GamesDat.Core.Telemetry.Sources.Formula1 | ||
| { | ||
| /// <summary> | ||
| /// File watcher source for F1 2025 race replay files. | ||
| /// Monitors: Documents\My Games\F1 25\replays | ||
| /// </summary> | ||
| public class F12025RaceReplaySource : F1RaceReplaySourceBase | ||
| { | ||
| public F12025RaceReplaySource(FileWatcherOptions options) | ||
| : base(ApplyDefaults(options)) | ||
| { | ||
| } | ||
|
|
||
| public F12025RaceReplaySource(string? customPath = null) | ||
| : base(CreateDefaultOptions(customPath ?? GetDefaultReplayPath())) | ||
| { | ||
| } | ||
|
|
||
| public static string GetDefaultReplayPath() => GetReplayPathForYear("25"); | ||
|
|
||
| /// <summary> | ||
| /// Ensure options has a path set, defaulting to F1 25 if not provided | ||
| /// </summary> | ||
| private static FileWatcherOptions EnsurePath(FileWatcherOptions options) | ||
| { | ||
| if (string.IsNullOrEmpty(options.Path)) | ||
| { | ||
| return new FileWatcherOptions | ||
| { | ||
| Path = GetDefaultReplayPath(), | ||
| Patterns = options.Patterns, | ||
| IncludeSubdirectories = options.IncludeSubdirectories, | ||
| DebounceDelay = options.DebounceDelay | ||
| }; | ||
| } | ||
| return options; | ||
| } | ||
|
codegefluester marked this conversation as resolved.
|
||
|
|
||
| /// <summary> | ||
| /// Apply F1 25-specific defaults. Used by test discovery. | ||
| /// </summary> | ||
| private static new FileWatcherOptions ApplyDefaults(FileWatcherOptions options) | ||
| { | ||
| return F1RaceReplaySourceBase.ApplyDefaults(EnsurePath(options)); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| using System; | ||
| using System.IO; | ||
| using System.Linq; | ||
|
|
||
| namespace GamesDat.Core.Telemetry.Sources.Formula1 | ||
| { | ||
| /// <summary> | ||
| /// File watcher source for F1 race replay files. | ||
| /// Defaults to F1 25, but can auto-detect the latest installed F1 game. | ||
| /// For monitoring specific years or multiple years simultaneously, use year-specific sources: | ||
| /// F12025RaceReplaySource, F12024RaceReplaySource, F12023RaceReplaySource, F12022RaceReplaySource | ||
| /// </summary> | ||
| public class F1RaceReplaySource : F1RaceReplaySourceBase | ||
| { | ||
| public F1RaceReplaySource(FileWatcherOptions options) | ||
| : base(ApplyDefaults(options)) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Ensure options has a path set, defaulting to F1 25 if not provided | ||
| /// </summary> | ||
| private static FileWatcherOptions EnsurePath(FileWatcherOptions options) | ||
| { | ||
| if (string.IsNullOrEmpty(options.Path)) | ||
| { | ||
| return new FileWatcherOptions | ||
| { | ||
| Path = F12025RaceReplaySource.GetDefaultReplayPath(), | ||
| Patterns = options.Patterns, | ||
| IncludeSubdirectories = options.IncludeSubdirectories, | ||
| DebounceDelay = options.DebounceDelay | ||
| }; | ||
| } | ||
| return options; | ||
|
codegefluester marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /// <summary> | ||
| /// Apply F1 defaults. Used by test discovery. | ||
| /// </summary> | ||
| private static new FileWatcherOptions ApplyDefaults(FileWatcherOptions options) | ||
| { | ||
| return F1RaceReplaySourceBase.ApplyDefaults(EnsurePath(options)); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create F1 replay source with optional custom path and detection strategy | ||
| /// </summary> | ||
| /// <param name="customPath">Custom replay folder path. If provided, autoDetectLatestInstalled is ignored.</param> | ||
| /// <param name="autoDetectLatestInstalled">If true and customPath is null, auto-detects the latest installed F1 game (checks 25, 24, 23, 22). If false, defaults to F1 25.</param> | ||
| public F1RaceReplaySource(string? customPath = null, bool autoDetectLatestInstalled = false) | ||
| : base(CreateDefaultOptions(ResolveReplayPath(customPath, autoDetectLatestInstalled))) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get the default F1 replay folder path (F1 25) | ||
| /// </summary> | ||
| public static string GetDefaultReplayPath() => F12025RaceReplaySource.GetDefaultReplayPath(); | ||
|
|
||
| /// <summary> | ||
| /// Auto-detect the latest installed F1 game's replay folder. | ||
| /// Checks F1 25, F1 24, F1 23, F1 22 in order and returns the first that exists. | ||
| /// Note: This checks for folder existence, which may include cases where the game | ||
| /// is uninstalled but replay folders remain. | ||
| /// </summary> | ||
| public static string GetLatestInstalledReplayPath() | ||
| { | ||
| var years = new[] { "25", "24", "23", "22" }; | ||
| var existingPath = years | ||
| .Select(GetReplayPathForYear) | ||
| .FirstOrDefault(Directory.Exists); | ||
|
|
||
| // Default to F1 25 even if it doesn't exist | ||
| return existingPath ?? GetReplayPathForYear("25"); | ||
| } | ||
|
|
||
| private static string ResolveReplayPath(string? customPath, bool autoDetectLatestInstalled) | ||
| { | ||
| if (customPath != null) | ||
| { | ||
| return customPath; | ||
| } | ||
|
|
||
| if (autoDetectLatestInstalled) | ||
| { | ||
| return GetLatestInstalledReplayPath(); | ||
| } | ||
|
|
||
| return GetDefaultReplayPath(); | ||
| } | ||
|
codegefluester marked this conversation as resolved.
|
||
| } | ||
| } | ||
77 changes: 77 additions & 0 deletions
77
GamesDat/Telemetry/Sources/Formula1/F1RaceReplaySourceBase.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| using System; | ||
|
|
||
| namespace GamesDat.Core.Telemetry.Sources.Formula1 | ||
| { | ||
| /// <summary> | ||
| /// Abstract base class for F1 race replay file sources across different game years. | ||
| /// Provides common functionality for monitoring F1 replay directories. | ||
| /// </summary> | ||
| public abstract class F1RaceReplaySourceBase : FileWatcherSourceBase | ||
| { | ||
| /// <summary> | ||
| /// The default debounce delay used by FileWatcherOptions (1 second). | ||
| /// Note: This mirrors the default in FileWatcherOptions.DebounceDelay. | ||
| /// If that default changes, this constant should be updated to match. | ||
| /// </summary> | ||
| private static readonly TimeSpan LibraryDefaultDebounceDelay = TimeSpan.FromSeconds(1); | ||
|
|
||
| /// <summary> | ||
| /// The F1-specific debounce delay (2 seconds) | ||
| /// </summary> | ||
| private static readonly TimeSpan F1DebounceDelay = TimeSpan.FromSeconds(2); | ||
|
|
||
| protected F1RaceReplaySourceBase(FileWatcherOptions options) : base(options) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Build the full replay path for a specific F1 game year | ||
| /// </summary> | ||
| protected static string GetReplayPathForYear(string gameYear) | ||
| { | ||
| var documentsFolder = Environment.GetFolderPath( | ||
| Environment.SpecialFolder.MyDocuments, | ||
| Environment.SpecialFolderOption.DoNotVerify); | ||
| return System.IO.Path.Combine(documentsFolder, "My Games", $"F1 {gameYear}", "replays"); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create default FileWatcherOptions for F1 replay monitoring | ||
| /// </summary> | ||
| protected static FileWatcherOptions CreateDefaultOptions(string path) | ||
| { | ||
| return new FileWatcherOptions | ||
| { | ||
| Path = path, | ||
| Patterns = new[] { "*.frr" }, | ||
| IncludeSubdirectories = false, | ||
| DebounceDelay = F1DebounceDelay | ||
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Apply F1-specific defaults to options. Requires Path to be non-empty. | ||
| /// </summary> | ||
| protected static FileWatcherOptions ApplyDefaults(FileWatcherOptions options) | ||
| { | ||
| if (string.IsNullOrEmpty(options.Path)) | ||
| { | ||
| throw new ArgumentException("FileWatcherOptions.Path cannot be null or empty. Provide a path before calling ApplyDefaults.", nameof(options)); | ||
| } | ||
|
|
||
| return new FileWatcherOptions | ||
| { | ||
| Path = options.Path, | ||
| Patterns = options.Patterns == null || options.Patterns.Length == 0 | ||
| ? new[] { "*.frr" } | ||
| : options.Patterns, | ||
| IncludeSubdirectories = options.IncludeSubdirectories, | ||
| // Check for both default (00:00:00, used when constructed via string path) | ||
| // and LibraryDefaultDebounceDelay (1s, used when constructed via options without explicit delay) | ||
| DebounceDelay = options.DebounceDelay == default || options.DebounceDelay == LibraryDefaultDebounceDelay | ||
| ? F1DebounceDelay | ||
| : options.DebounceDelay | ||
| }; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.