104 lines
3.8 KiB
C#
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);
|
|
}
|
|
}
|