using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EvoBoat.EvoAlg.IntDivision
{
    /// <summary>
    /// A problem for dividing an integer into fractions
    /// </summary>
    public abstract class IntDivisionProblem<S> : IProblem<S, IntVector>
        where S : class, ISolution<IntVector>, new()
    {
        protected int total, dimension;
        public int Total { get { return total; } }
        public int Dimension { get { return dimension; } }
        double avg;
        public double Avg {  get { return avg; } }

        public IntDivisionProblem(int total, int n)
        {
            this.total = total;
            this.dimension = n;
            avg = (double)total / n;
        }

        public abstract double Evaluate(IntVector vector);
        public virtual double Evaluate(S sol)
        {
            sol.Fit = Evaluate(sol.Content);
            return sol.Fit;
        }

        public virtual bool IsFeasible(IntVector vector)
        {
            return (vector.Sum() == total);
        }

        public virtual int[] RepairAt<P>(EAlg<P, S, IntVector, int> alg, VecSolution<IntVector, int> sol, int d, int change)
            where P : IntDivisionProblem<S>
        {
            int[] changes = new int[dimension];
            int d1;
            while (change > 0)
            {
                d1 = alg.RandomSelectIndex(dimension, d);
                if (sol.Content[d1] > 0)
                {
                    sol.Content[d1]--;
                    changes[d1]--;
                    change--;
                }
            }
            while (change < 0)
            {
                d1 = alg.RandomSelectIndex(dimension, d);
                sol.Content[d1]++;
                changes[d1]++;
                change++;
            }
            return changes;
        }
    }
}
