mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-04-21 18:13:14 +02:00

Moved AppLibrary, Configuration, and PlayReport namespaces to Ryujinx.Systems, add the compat list stuff in the base Ryujinx.Systems namespace. Moved the compatibility UI stuff to the proper UI view/viewmodel folders.
151 lines
6.6 KiB
C#
151 lines
6.6 KiB
C#
using Gommon;
|
|
using Ryujinx.Ava.Systems.AppLibrary;
|
|
using Ryujinx.Common.Logging;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
|
|
namespace Ryujinx.Ava.Systems.PlayReport
|
|
{
|
|
/// <summary>
|
|
/// The entrypoint for the Play Report analysis system.
|
|
/// </summary>
|
|
public class Analyzer
|
|
{
|
|
private readonly List<GameSpec> _specs = [];
|
|
|
|
public string[] TitleIds => Specs.SelectMany(x => x.TitleIds).ToArray();
|
|
|
|
public IReadOnlyList<GameSpec> Specs => new ReadOnlyCollection<GameSpec>(_specs);
|
|
|
|
public GameSpec GetSpec(string titleId) => _specs.First(x => x.TitleIds.ContainsIgnoreCase(titleId));
|
|
|
|
public bool TryGetSpec(string titleId, out GameSpec gameSpec)
|
|
=> (gameSpec = _specs.FirstOrDefault(x => x.TitleIds.ContainsIgnoreCase(titleId))) != null;
|
|
|
|
/// <summary>
|
|
/// Add an analysis spec matching a specific game by title ID, with the provided spec configuration.
|
|
/// </summary>
|
|
/// <param name="titleId">The ID of the game to listen to Play Reports in.</param>
|
|
/// <param name="transform">The configuration function for the analysis spec.</param>
|
|
/// <returns>The current <see cref="Analyzer"/>, for chaining convenience.</returns>
|
|
public Analyzer AddSpec(string titleId, Func<GameSpec, GameSpec> transform)
|
|
{
|
|
if (ulong.TryParse(titleId, NumberStyles.HexNumber, null, out _))
|
|
return AddSpec(transform(GameSpec.Create(titleId)));
|
|
|
|
Logger.Notice.PrintMsg(LogClass.Application,
|
|
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{titleId}'");
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add an analysis spec matching a specific game by title ID, with the provided spec configuration.
|
|
/// </summary>
|
|
/// <param name="titleId">The ID of the game to listen to Play Reports in.</param>
|
|
/// <param name="transform">The configuration function for the analysis spec.</param>
|
|
/// <returns>The current <see cref="Analyzer"/>, for chaining convenience.</returns>
|
|
public Analyzer AddSpec(string titleId, Action<GameSpec> transform)
|
|
{
|
|
if (ulong.TryParse(titleId, NumberStyles.HexNumber, null, out _))
|
|
return AddSpec(GameSpec.Create(titleId).Apply(transform));
|
|
|
|
Logger.Notice.PrintMsg(LogClass.Application,
|
|
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{titleId}'");
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add an analysis spec matching a specific set of games by title IDs, with the provided spec configuration.
|
|
/// </summary>
|
|
/// <param name="titleIds">The IDs of the games to listen to Play Reports in.</param>
|
|
/// <param name="transform">The configuration function for the analysis spec.</param>
|
|
/// <returns>The current <see cref="Analyzer"/>, for chaining convenience.</returns>
|
|
public Analyzer AddSpec(IEnumerable<string> titleIds,
|
|
Func<GameSpec, GameSpec> transform)
|
|
{
|
|
string[] tids = titleIds.ToArray();
|
|
if (tids.All(x => ulong.TryParse(x, NumberStyles.HexNumber, null, out _) && !string.IsNullOrEmpty(x)))
|
|
return AddSpec(transform(GameSpec.Create(tids)));
|
|
|
|
Logger.Notice.PrintMsg(LogClass.Application,
|
|
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{
|
|
tids.FormatCollection(
|
|
x => x,
|
|
separator: ", ",
|
|
prefix: "[",
|
|
suffix: "]"
|
|
)
|
|
}'");
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add an analysis spec matching a specific set of games by title IDs, with the provided spec configuration.
|
|
/// </summary>
|
|
/// <param name="titleIds">The IDs of the games to listen to Play Reports in.</param>
|
|
/// <param name="transform">The configuration function for the analysis spec.</param>
|
|
/// <returns>The current <see cref="Analyzer"/>, for chaining convenience.</returns>
|
|
public Analyzer AddSpec(IEnumerable<string> titleIds, Action<GameSpec> transform)
|
|
{
|
|
string[] tids = titleIds.ToArray();
|
|
if (tids.All(x => ulong.TryParse(x, NumberStyles.HexNumber, null, out _) && !string.IsNullOrEmpty(x)))
|
|
return AddSpec(GameSpec.Create(tids).Apply(transform));
|
|
|
|
Logger.Notice.PrintMsg(LogClass.Application,
|
|
$"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{
|
|
tids.FormatCollection(
|
|
x => x,
|
|
separator: ", ",
|
|
prefix: "[",
|
|
suffix: "]"
|
|
)
|
|
}'");
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add an analysis spec matching a specific game by title ID, with the provided pre-configured spec.
|
|
/// </summary>
|
|
/// <param name="spec">The <see cref="GameSpec"/> to add.</param>
|
|
/// <returns>The current <see cref="Analyzer"/>, for chaining convenience.</returns>
|
|
public Analyzer AddSpec(GameSpec spec)
|
|
{
|
|
_specs.Add(spec);
|
|
return this;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Runs the configured <see cref="FormatterSpec"/> for the specified game title ID.
|
|
/// </summary>
|
|
/// <param name="runningGameId">The game currently running.</param>
|
|
/// <param name="appMeta">The Application metadata information, including localized game name and play time information.</param>
|
|
/// <param name="playReport">The Play Report received from HLE.</param>
|
|
/// <returns>A struct representing a possible formatted value.</returns>
|
|
public FormattedValue Format(
|
|
string runningGameId,
|
|
ApplicationMetadata appMeta,
|
|
Horizon.Prepo.Types.PlayReport playReport
|
|
)
|
|
{
|
|
if (!playReport.ReportData.IsDictionary)
|
|
return FormattedValue.Unhandled;
|
|
|
|
if (!TryGetSpec(runningGameId, out GameSpec spec))
|
|
return FormattedValue.Unhandled;
|
|
|
|
foreach (FormatterSpecBase formatSpec in spec.ValueFormatters.OrderBy(x => x.Priority))
|
|
{
|
|
if (!formatSpec.TryFormat(appMeta, playReport, out FormattedValue value))
|
|
continue;
|
|
|
|
return value;
|
|
}
|
|
|
|
return FormattedValue.Unhandled;
|
|
}
|
|
}
|
|
}
|