99 lines
4.3 KiB
C#
99 lines
4.3 KiB
C#
using RpgRoller.Contracts;
|
|
using RpgRoller.Domain;
|
|
|
|
namespace RpgRoller.Services;
|
|
|
|
public static class CampaignLogSummaryBuilder
|
|
{
|
|
public static string BuildCompactLogSummary(IReadOnlyList<RollDieResult> dice)
|
|
{
|
|
if (dice.Count == 0)
|
|
return "No detail available.";
|
|
|
|
if (dice.Any(die => IsRolemasterDieKind(die.Kind)))
|
|
return BuildRolemasterCompactLogSummary(dice);
|
|
|
|
return string.Join(", ", dice.Select(die => die.Roll.ToString()));
|
|
}
|
|
|
|
public static string[]? BuildCompactLogEventBadges(RulesetKind ruleset, string? expression, IReadOnlyList<RollDieResult> dice)
|
|
{
|
|
var badges = new List<string>();
|
|
|
|
switch (ruleset)
|
|
{
|
|
case RulesetKind.D6:
|
|
AddBadgeIfMissing(badges, dice.Any(die => die is { Wild: true, Roll: 6 }), "w6");
|
|
AddBadgeIfMissing(badges, dice.Any(die => die is { Wild: true, Roll: 1 }), "w1");
|
|
break;
|
|
case RulesetKind.Dnd5e:
|
|
if (!string.IsNullOrWhiteSpace(expression) && IsSingleD20Expression(expression))
|
|
{
|
|
AddBadgeIfMissing(badges, dice.Any(die => die.Roll == 20), "n20");
|
|
AddBadgeIfMissing(badges, dice.Any(die => die.Roll == 1), "n1");
|
|
}
|
|
|
|
break;
|
|
case RulesetKind.Rolemaster:
|
|
AddBadgeIfMissing(badges, dice.Any(die => string.Equals(die.Kind, RollDieKinds.RolemasterOpenEndedInitial, StringComparison.Ordinal) && !die.SignedContribution.HasValue), "rf");
|
|
AddBadgeIfMissing(badges, dice.Any(die => die.Roll == 100), "r100");
|
|
AddBadgeIfMissing(badges, dice.Any(die => die.Roll == 66), "r66");
|
|
break;
|
|
}
|
|
|
|
return badges.Count == 0 ? null : badges.ToArray();
|
|
}
|
|
|
|
public static string? ExtractCustomRollExpression(string breakdown, string separator)
|
|
{
|
|
var separatorIndex = breakdown.IndexOf(separator, StringComparison.Ordinal);
|
|
if (separatorIndex <= 0)
|
|
return null;
|
|
|
|
return breakdown[..separatorIndex];
|
|
}
|
|
|
|
private static string BuildRolemasterCompactLogSummary(IReadOnlyList<RollDieResult> dice)
|
|
{
|
|
var openEndedInitial = dice.FirstOrDefault(die => string.Equals(die.Kind, RollDieKinds.RolemasterOpenEndedInitial, StringComparison.Ordinal));
|
|
if (openEndedInitial is not null)
|
|
{
|
|
var highFollowUps = dice.Where(die => string.Equals(die.Kind, RollDieKinds.RolemasterOpenEndedHigh, StringComparison.Ordinal)).Select(die => die.Roll.ToString()).ToArray();
|
|
if (highFollowUps.Length > 0)
|
|
return $"{openEndedInitial.Roll} + {string.Join(" + ", highFollowUps)} | open-ended high";
|
|
|
|
var lowFollowUps = dice.Where(die => string.Equals(die.Kind, RollDieKinds.RolemasterOpenEndedLowSubtract, StringComparison.Ordinal)).Select(die => die.Roll.ToString()).ToArray();
|
|
if (lowFollowUps.Length > 0)
|
|
return $"({RollBreakdownFormatter.FormatRolemasterTriggerRoll(openEndedInitial.Roll)}) {string.Join(" ", lowFollowUps.Select(roll => $"-{roll}"))} | open-ended low";
|
|
|
|
return $"{openEndedInitial.Roll} | open-ended";
|
|
}
|
|
|
|
if (dice.Any(die => string.Equals(die.Kind, RollDieKinds.RolemasterStandard, StringComparison.Ordinal)))
|
|
{
|
|
var preview = string.Join(" + ", dice.Select(die => die.Roll.ToString()));
|
|
return $"{preview} | rolemaster";
|
|
}
|
|
|
|
return string.Join(", ", dice.Select(die => die.Roll.ToString()));
|
|
}
|
|
|
|
private static bool IsRolemasterDieKind(string? kind)
|
|
{
|
|
return kind is RollDieKinds.RolemasterStandard or RollDieKinds.RolemasterOpenEndedInitial or RollDieKinds.RolemasterOpenEndedHigh or RollDieKinds.RolemasterOpenEndedLowSubtract;
|
|
}
|
|
|
|
private static void AddBadgeIfMissing(List<string> badges, bool condition, string code)
|
|
{
|
|
if (!condition || badges.Any(badge => string.Equals(badge, code, StringComparison.Ordinal)))
|
|
return;
|
|
|
|
badges.Add(code);
|
|
}
|
|
|
|
private static bool IsSingleD20Expression(string expression)
|
|
{
|
|
var parsedExpression = DiceRules.ParseExpression(RulesetKind.Dnd5e, expression);
|
|
return parsedExpression.Succeeded && parsedExpression.Value!.DiceCount == 1 && parsedExpression.Value.Sides == 20;
|
|
}
|
|
} |