Files
RpgRoller/RpgRoller/Components/Pages/HomeControls/RulesetFormHelpers.cs

104 lines
3.8 KiB
C#

using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using RpgRoller.Domain;
using RpgRoller.Services;
namespace RpgRoller.Components.Pages.HomeControls;
[ExcludeFromCodeCoverage]
internal static class RulesetFormHelpers
{
internal static class RulesetIds
{
public const string D6 = "d6";
public const string Dnd5e = "dnd5e";
public const string Rolemaster = "rolemaster";
}
internal static class RolemasterRollTypes
{
public const string Initiative = "initiative";
public const string Percentile = "percentile";
public const string OpenEndedPercentile = "open-ended-percentile";
}
public static bool IsD6(string? rulesetId)
{
return string.Equals(rulesetId, RulesetIds.D6, StringComparison.OrdinalIgnoreCase);
}
public static bool IsRolemaster(string? rulesetId)
{
return string.Equals(rulesetId, RulesetIds.Rolemaster, StringComparison.OrdinalIgnoreCase);
}
public static string InferRolemasterRollType(string? expression)
{
var parseResult = TryParseRolemasterExpression(expression);
if (!parseResult.Succeeded || parseResult.Value is null)
return RolemasterRollTypes.Initiative;
return parseResult.Value.Kind switch
{
DiceExpressionKind.RolemasterPercentile => RolemasterRollTypes.Percentile,
DiceExpressionKind.RolemasterOpenEndedPercentile => RolemasterRollTypes.OpenEndedPercentile,
_ => RolemasterRollTypes.Initiative
};
}
public static int InferRolemasterModifier(string? expression)
{
var parseResult = TryParseRolemasterExpression(expression);
return parseResult.Succeeded && parseResult.Value is not null ? parseResult.Value.Modifier : 0;
}
public static string BuildRolemasterExpression(string? rollType, int modifier)
{
return rollType switch
{
RolemasterRollTypes.Percentile => $"d100{FormatModifier(modifier)}",
RolemasterRollTypes.OpenEndedPercentile => $"d100!{FormatModifier(modifier)}",
_ => $"2d10{FormatModifier(modifier)}"
};
}
public static string DescribeRolemasterExpression(string expression, int? fumbleRange)
{
var parseResult = TryParseRolemasterExpression(expression);
if (!parseResult.Succeeded || parseResult.Value is null)
return expression;
return parseResult.Value.Kind switch
{
DiceExpressionKind.RolemasterPercentile => $"Percentile: {parseResult.Value.Canonical}",
DiceExpressionKind.RolemasterOpenEndedPercentile => fumbleRange.HasValue
? $"Open-ended percentile: {parseResult.Value.Canonical}, fumble <= {fumbleRange.Value}"
: $"Open-ended percentile: {parseResult.Value.Canonical}",
_ => $"Initiative: {parseResult.Value.Canonical}"
};
}
public static string RolemasterExampleText(string? rollType)
{
return rollType switch
{
RolemasterRollTypes.Percentile => "Example: d100+48",
RolemasterRollTypes.OpenEndedPercentile => "Example: d100!+85",
_ => "Example: 2d10+48"
};
}
private static ServiceResult<DiceExpression> TryParseRolemasterExpression(string? expression)
{
if (string.IsNullOrWhiteSpace(expression))
return ServiceResult<DiceExpression>.Failure("invalid_expression", "Expression is required.");
return DiceRules.ParseExpression(RulesetKind.Rolemaster, expression);
}
private static string FormatModifier(int modifier)
{
return modifier >= 0 ? $"+{modifier}" : modifier.ToString(CultureInfo.InvariantCulture);
}
}