Пример #1
0
        /// <summary>
        /// Distributes the minimal amount to the specified result.
        /// </summary>
        /// <remarks>Immutable operation: creates other instance of allocation.</remarks>
        internal protected Allocation apply(Allocation allocation, int index)
        {
            Money[] results = allocation
                              .Select((m, i) => i != index ? m : m + m.MinValue)
                              .ToArray();

            return(new Allocation(allocation.Allocatable, results));
        }
Пример #2
0
        private static Allocation allocateRemainderIfNeeded(this Money money, IRemainderAllocator allocator, Allocation allocatedSoFar)
        {
            Money      remainder      = money - allocatedSoFar.TotalAllocated;
            Allocation beingAllocated = allocatedSoFar;

            if (remainder >= remainder.MinValue)
            {
                beingAllocated = allocator.Allocate(allocatedSoFar);
            }
            return(beingAllocated);
        }
Пример #3
0
        /// <summary>
        /// Allocates the sum of money 'fairly', discarding the remainder of an uneven allocation.
        /// </summary>
        /// <remarks>
        /// <para>
        /// A sum of money that can be allocated to each recipient exactly evenly is inherently 'fair'. For example, a US
        /// Dollar split four (4) ways leaves each recipient with 25 cents and everything is allocated.</para>
        /// <para>
        /// A US Dollar split three (3) ways cannot be distributed evenly and is therefore inherently 'unfair'. What will be done
        /// is allocate the maximum fair amount and leave the remainding amount for the caller to decide.</para>
        /// </remarks>
        /// <param name="numberOfRecipients">The number of times to split up the total.</param>
        /// <returns>
        /// The results of the even allocation with a length equal to <paramref name="numberOfRecipients"/>.
        /// <para>In the case of an even allocation, the allocation will be complete.<see cref="Allocation.IsComplete"/>, having a zero <see cref="Allocation.Remainder"/>.</para>
        /// <para>In the case of an uneven allocation, the allocation will not be complete <see cref="EvenAllocator(Money)"/>, having a non-zero <see cref="Allocation.Remainder"/>.</para>
        /// </returns>
        /// <seealso cref="EvenAllocator(Money)"/>
        public Allocation Allocate(int numberOfRecipients)
        {
            // if amount to allocate is too 'scarce' to allocate something to all
            // then effectively go into remainder allocation mode
            if (notEnoughToAllocateEvenly(numberOfRecipients))
            {
                return(Allocation.Zero(_toAllocate, numberOfRecipients));
            }

            decimal each = amountforEachRecipient(numberOfRecipients);

            Money[] results = Money.Some(each, _currency, numberOfRecipients);
            return(new Allocation(_toAllocate, results));
        }
Пример #4
0
        public static Allocation Allocate(this Money money, int numberOfRecipients, IRemainderAllocator allocator)
        {
            EvenAllocator.AssertNumberOfRecipients(nameof(numberOfRecipients), numberOfRecipients);

            if (money.notEnoughToAllocate())
            {
                return(Allocation.Zero(money, numberOfRecipients));
            }

            Allocation allocated = new EvenAllocator(money)
                                   .Allocate(numberOfRecipients);

            allocated = money.allocateRemainderIfNeeded(allocator, allocated);

            return(allocated);
        }
Пример #5
0
        public static Allocation Allocate(this Money money, RatioCollection ratios, IRemainderAllocator allocator)
        {
            Guard.AgainstNullArgument(nameof(ratios), ratios);

            if (money.notEnoughToAllocate())
            {
                return(Allocation.Zero(money, ratios.Count));
            }

            Allocation allocated = new ProRataAllocator(money)
                                   .Allocate(ratios);

            allocated = money.allocateRemainderIfNeeded(allocator, allocated);

            return(allocated);
        }
Пример #6
0
        public override Allocation Allocate(Allocation allocatedSoFar)
        {
            var rnd = new Random();

            // the number of recipients that can get an incremental share
            Money remainder          = allocatedSoFar.Remainder;
            var   numberOfRecipients = (int)(remainder.Amount / remainder.MinValue.Amount);

            // make a list of all indexes, order it randomly
            // and take the number of indexes we need
            var indexes = Enumerable
                          .Range(0, allocatedSoFar.Length)
                          .OrderBy(x => rnd.Next())
                          .Take(numberOfRecipients);

            return(indexes.Aggregate(allocatedSoFar, apply));
        }
Пример #7
0
 public abstract Allocation Allocate(Allocation allocatedSoFar);