public Pocket[] AutoSelectPockets(SmartLabel recipient) { var knownPockets = NonPrivatePockets.Where(x => x.Labels != CoinPocketHelper.UnlabelledFundsText).ToArray(); var unknownPockets = NonPrivatePockets.Except(knownPockets).ToArray(); var privateAndUnknownPockets = _allPockets.Except(knownPockets).ToArray(); var privateAndKnownPockets = _allPockets.Except(unknownPockets).ToArray(); var knownByRecipientPockets = knownPockets.Where(pocket => pocket.Labels.Any(label => recipient.Contains(label, StringComparer.OrdinalIgnoreCase))).ToArray(); var onlyKnownByRecipientPockets = knownByRecipientPockets .Where(pocket => pocket.Labels.Count() == recipient.Count() && pocket.Labels.All(label => recipient.Contains(label, StringComparer.OrdinalIgnoreCase))) .ToArray(); if (onlyKnownByRecipientPockets.Sum(x => x.Amount) >= _targetAmount) { return(onlyKnownByRecipientPockets); } if (_privatePocket.Amount >= _targetAmount) { return(new[] { _privatePocket }); } if (TryGetBestKnownByRecipientPockets(knownByRecipientPockets, _targetAmount, recipient, out var pockets)) { return(pockets); } if (knownPockets.Sum(x => x.Amount) >= _targetAmount) { return(knownPockets); } if (unknownPockets.Sum(x => x.Amount) >= _targetAmount) { return(unknownPockets); } if (NonPrivatePockets.Sum(x => x.Amount) >= _targetAmount) { return(NonPrivatePockets); } if (privateAndKnownPockets.Sum(x => x.Amount) >= _targetAmount) { return(privateAndKnownPockets); } if (privateAndUnknownPockets.Sum(x => x.Amount) >= _targetAmount) { return(privateAndUnknownPockets); } return(_allPockets.ToArray()); }
private bool TryGetBestKnownByRecipientPockets(Pocket[] knownByRecipientPockets, Money targetAmount, SmartLabel recipient, [NotNullWhen(true)] out Pocket[]?pockets) { pockets = null; if (knownByRecipientPockets.Sum(x => x.Amount) < _targetAmount) { return(false); } var privacyRankedPockets = knownByRecipientPockets .Select(pocket => { var containedRecipientLabelsCount = pocket.Labels.Count(label => recipient.Contains(label, StringComparer.OrdinalIgnoreCase)); var totalPocketLabelsCount = pocket.Labels.Count(); var totalRecipientLabelsCount = recipient.Count(); var index = ((double)containedRecipientLabelsCount / totalPocketLabelsCount) + ((double)containedRecipientLabelsCount / totalRecipientLabelsCount); return(acceptabilityIndex: index, pocket); }) .OrderByDescending(tup => tup.acceptabilityIndex) .ThenBy(tup => tup.pocket.Labels.Count()) .ThenByDescending(tup => tup.pocket.Amount) .Select(tup => tup.pocket) .ToArray(); var bestPockets = new List <Pocket>(); foreach (var p in privacyRankedPockets) { bestPockets.Add(p); if (bestPockets.Sum(x => x.Amount) >= targetAmount) { break; } } foreach (var p in bestPockets.OrderBy(x => x.Amount).ThenByDescending(x => x.Labels.Count()).ToImmutableArray()) { if (bestPockets.Sum(x => x.Amount) - p.Amount >= targetAmount) { bestPockets.Remove(p); } else { break; } } pockets = bestPockets.ToArray(); return(true); }