77 lines
2.6 KiB
C#
77 lines
2.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace FishDice.LuckyDice
|
|
{
|
|
public sealed class LuckyDiceFlowService
|
|
{
|
|
private readonly IRandomSource _random;
|
|
|
|
public LuckyDiceFlowService(IRandomSource random)
|
|
{
|
|
_random = random ?? throw new ArgumentNullException(nameof(random));
|
|
}
|
|
|
|
public LuckyDiceSelectionResult Select(
|
|
IReadOnlyList<LuckyDiceCandidateConfig> candidates,
|
|
RollFlowRequest request,
|
|
DiceSetConfig luckyDiceSetConfig)
|
|
{
|
|
var source = candidates ?? Array.Empty<LuckyDiceCandidateConfig>();
|
|
var filtered = source
|
|
.Where(candidate => candidate.Enabled)
|
|
.Where(candidate => request.PlayerLevel >= candidate.MinLevel)
|
|
.Where(candidate => candidate.SourceFilter == null ||
|
|
candidate.SourceFilter.Count == 0 ||
|
|
candidate.SourceFilter.Contains(request.TriggerSource))
|
|
.ToArray();
|
|
|
|
var fallbackType = "None";
|
|
int? randomValue = null;
|
|
var selected = PickWeighted(filtered, out randomValue);
|
|
|
|
if (selected == null)
|
|
{
|
|
selected = filtered.FirstOrDefault(candidate => candidate.IsDefault);
|
|
fallbackType = selected == null ? "NormalRewardFallback" : "DefaultResult";
|
|
}
|
|
|
|
var slotCount = selected == null ? 0 : selected.ResultSlotCount ?? luckyDiceSetConfig.DefaultResultSlotCount ?? 3;
|
|
|
|
return new LuckyDiceSelectionResult(
|
|
selected,
|
|
source.Count,
|
|
filtered.Length,
|
|
randomValue,
|
|
fallbackType,
|
|
slotCount);
|
|
}
|
|
|
|
private LuckyDiceCandidateConfig PickWeighted(IReadOnlyList<LuckyDiceCandidateConfig> candidates, out int? randomValue)
|
|
{
|
|
var weighted = candidates.Where(candidate => candidate.Weight > 0).ToArray();
|
|
var totalWeight = weighted.Sum(candidate => candidate.Weight);
|
|
if (totalWeight <= 0)
|
|
{
|
|
randomValue = null;
|
|
return null;
|
|
}
|
|
|
|
var roll = _random.Next(0, totalWeight);
|
|
randomValue = roll;
|
|
var cursor = 0;
|
|
foreach (var candidate in weighted)
|
|
{
|
|
cursor += candidate.Weight;
|
|
if (roll < cursor)
|
|
{
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
return weighted[weighted.Length - 1];
|
|
}
|
|
}
|
|
}
|