Ejemplo n.º 1
0
        /// <summary>
        /// To force a split having the most populated class.
        /// If ParameterMostPopulatedClassInEverySplitsValue = 1
        /// else it will be skipped
        /// </summary>
        /// <param name="s"></param>
        private bool AddMostPopulatedClassInTheSplitIfMissing(List <Split> splits, Split s)
        {
            bool ret = false;

            // if we want  the most populated class on each split
            if (true /*ParameterMostPopulatedClassInEverySplits*/)
            {
                // add most populated class in the split :

                // first, the the list not classes not in this split
                List <int> classesNotInThisSplit = new List <int>();
                for (int i = 0; i < carClassesIds.Count - 2; i++)
                {
                    if (s.CountClassCars(i) == 0)
                    {
                        classesNotInThisSplit.Add(carClassesIds[i]);
                    }
                }

                // get the most populated class id we want to have
                int mostPopClassId = carClassesIds.Last();

                // create a move dictionnary
                // KEY : populated class id
                // VALUES : missing cars to fit the good number of cars in this populated class
                Dictionary <int, int> mostPopAdd = new Dictionary <int, int>();
                int mostPopTarget = TakeCars(carClassesIds, splits, s, mostPopClassId, null, fieldSize);
                mostPopTarget -= s.CountClassCars(carClassesIds.Count - 1);
                // -->

                // there is a move up to do
                if (mostPopTarget > 0)
                {
                    // so do it
                    mostPopAdd.Add(mostPopClassId, mostPopTarget);
                    UpCarsToSplit(carClassesIds, splits, s, mostPopAdd);
                    ret = true;
                    // -->
                }
            }
            return(ret);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This method generate a split from combination (Truth Tabl)
        /// It will convert fill corresponding classes described in a combination (with true/false)
        /// with concrete cars list, taking the right number
        /// </summary>
        /// <param name="splitNumber"></param>
        /// <param name="c"></param>
        /// <param name="previousSplit"></param>
        /// <returns></returns>
        private Split GenerateSplitFromCombination(int splitNumber, Calc.Combination c, Split previousSplit = null)
        {
            // create a new split
            Split s = new Split(splitNumber);

            // how may classes in this combination
            int splitClasses = c.ClassesId.Length;

            // foreach enabled classes
            var enabledClassesId = c.EnabledClassesId;

            for (int i = 0; i < splitClasses; i++)
            {
                if (c.Enabled[i])
                {
                    // get class info
                    int classId    = c.ClassesId[i];
                    int classIndex = classesIds.IndexOf(classId);

                    // call the affineDistributor to calc the right number of cars
                    int totake = affineDistributor.TakeCars(classId, enabledClassesId, fieldSize);

                    int toskip = 0;
                    if (previousSplit != null)
                    {
                        // if this split is the second, and have a previous split
                        // we need to skip cars already in that previous split
                        toskip = previousSplit.CountClassCars(classIndex);
                    }

                    // get cars
                    var cars = classesQueues[classIndex].GetFirstCars(toskip, totake);

                    // put them in the split
                    s.SetClass(classIndex, cars, classId);
                }
            }
            return(s);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// If there is too much cars in the split (more than fieldSize)
        /// Than this method will move down the excess
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        private List <int> MoveDownExcessCarsInTheSplit(List <Split> splits, Split s)
        {
            List <int> classesToReducted = new List <int>();

            // list classes in this split and class not in this splits
            List <int> classesInTheSplit    = new List <int>();
            List <int> classesNotInTheSplit = new List <int>();

            for (int i = 0; i < carClassesIds.Count; i++)
            {
                if (s.CountClassCars(i) > 0)
                {
                    classesInTheSplit.Add(carClassesIds[i]);
                }
                else
                {
                    classesNotInTheSplit.Add(carClassesIds[i]);
                }
            }
            // -->



            // get limits list by querying nominal cars count for a
            // complete field size with same car classes
            // KEY = classid
            // VALUE = targetted cars number
            Dictionary <int, int> classLimits = new Dictionary <int, int>();

            foreach (var c in classesInTheSplit)
            {
                int limit = TakeCars(splits, s, c, classesNotInTheSplit, fieldSize);
                classLimits.Add(c, limit);
            }
            // -->

            // for each limit
            foreach (var limit in classLimits)
            {
                // get class and max cars count wanted
                int classId    = limit.Key;
                int classIndex = carClassesIds.IndexOf(classId);
                int max        = limit.Value;

                // count if to much cars
                int carsToMove = s.CountClassCars(classIndex) - max;

                // yes there are cars in excess for that class
                // while there is
                for (int i = 0; i < carsToMove; i++)
                {
                    // get the next split containng the same class
                    var nextSplitContainingSameClassCars = (from r in splits
                                                            where r.Number > s.Number &&
                                                            r.CountClassCars(classIndex) > 0
                                                            select r).FirstOrDefault();

                    // it the parameter to force most populated class in every
                    // split is set to yes, than simply get the next split
                    // nevermind if it contains the same class or not we will add it
                    if (true /*ParameterMostPopulatedClassInEverySplits*/)
                    {
                        if (classIndex == carClassesIds.Count - 1)
                        {
                            // so get the next split
                            nextSplitContainingSameClassCars = (from r in splits
                                                                where r.Number > s.Number
                                                                select r).FirstOrDefault();

                            if (nextSplitContainingSameClassCars != null)
                            {
                                // if this split does not contains the class yet, create it
                                if (nextSplitContainingSameClassCars.GetClassId(classIndex) != classId)
                                {
                                    nextSplitContainingSameClassCars.SetClass(classIndex, classId);
                                }
                                // -->
                            }
                        }
                    }

                    // -->


                    // if the next split to put cars on is not found
                    if (nextSplitContainingSameClassCars == null)
                    {
                        // just get the next one neverless contains the class yet
                        nextSplitContainingSameClassCars = (from r in splits
                                                            where r.Number > s.Number
                                                            select r).FirstOrDefault();
                        if (nextSplitContainingSameClassCars != null)
                        {
                            // if this split does not contains the class yet, create it
                            if (nextSplitContainingSameClassCars.GetClassId(classIndex) != classId)
                            {
                                nextSplitContainingSameClassCars.SetClass(classIndex, classId);
                            }
                            // -->
                        }
                    }

                    // is the target split is here ?
                    if (nextSplitContainingSameClassCars != null)
                    {
                        // pick one car to the current split 's' (in excess)
                        var pick = s.PickClassCars(classIndex, 1, true);
                        // and append them to the targeted one
                        nextSplitContainingSameClassCars.AppendClassCars(classIndex, pick);
                    }
                    else
                    {
                        // no... hm
                        // no move possible
                        // keeps car in it for the moment
                    }

                    // add to the return on that method the classId we reduced
                    if (!classesToReducted.Contains(classId))
                    {
                        classesToReducted.Add(classId);
                    }
                }
                // end ot the for loop 'carsToMove'
            } // end of the foreach loop class limit

            // return the list of classesId reduced
            return(classesToReducted);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Move down cars from a split to the lower one
        /// </summary>
        /// <param name="s"></param>
        /// <param name="splitIndex"></param>
        public void MoveDownCarsSplits(List <Split> splits, Split s, int splitIndex, int?forceMoveDownOfClassIndex = null)
        {
            List <int> classesSof = CalcSplitSofs(s);


            // classes we move down in this split
            List <int> movedCategories = new List <int>();
            // -->

            // ensure most populated category is filled it option set
            bool mostPopCatAsBeenFilled = AddMostPopulatedClassInTheSplitIfMissing(splits, s);
            // -->

            // move cars down
            int classesToMoveDown = classesSof.Count - 1;

            if (false /*ParameterMostPopulatedClassInEverySplits*/)
            {
                // if the parameter MostPopulatedClassInEverySplits is disabled
                // then we will also check the last class
                classesToMoveDown++;
            }

            for (int i = classesToMoveDown - 1; i >= 0; i--)
            //for (int i = 0; i < classesToMoveDown; i++)
            {
                // test: do we need to move down ?
                bool doTheMoveDown = false;
                if (forceMoveDownOfClassIndex != null)
                {
                    doTheMoveDown = (i == forceMoveDownOfClassIndex.Value);
                }
                else
                {
                    doTheMoveDown = HaveToMoveDown(s, i, classesSof);
                }

                if (forceMoveDownOfClassIndex == null &&
                    INTERRUPT_BEFORE_MOVEDOWN_SPLITNUMBER == s.Number &&
                    INTERRUPT_BEFORE_MOVEDOWN_CLASSINDEX == i)
                {
                    // to help debugging
                    return;
                }

                // if we have to move the class to the next split
                if (doTheMoveDown)
                {
                    // pick all the class cars
                    var cars = s.PickClassCars(i);
                    s.SetClassTarget(i, 0);

                    // add them to the next split
                    Split nextSplit = GetSplit(splits, splitIndex + 1);
                    AppendCarsToSplit(nextSplit, i, cars);

                    if (cars.Count > 0)
                    {
                        movedCategories.Add(carClassesIds[i]);
                    }
                }
            }

            // -->

            // reset next split ?
            //if (s.Number + 1 < splits.Count)
            //{
            //    var nextSplit2 = splits[s.Number + 1];
            //    ResetSplitWithAllClassesFilled(splits, nextSplit2);
            //}
            // -->

            // up cars to fill leaved slots
            List <int> doNotUpCategories = new List <int>();

            doNotUpCategories.AddRange(movedCategories);
            if (mostPopCatAsBeenFilled)
            {
                int mostPopupClassId = carClassesIds[carClassesIds.Count - 1];
                if (!doNotUpCategories.Contains(mostPopupClassId))
                {
                    doNotUpCategories.Add(mostPopupClassId);
                }
            }
            UpCarsToSplit(splits, s, doNotUpCategories);
            // -->

            // to much cars in the split, move them down
            // reducedClasses is the ids of the classes recudes
            // keep then in a variable because we don't want
            // to update them again after that
            var reducedClasses = MoveDownExcessCarsInTheSplit(splits, s);

            for (int e = s.Number; e < splits.Count - 1; e++)
            {
                MoveDownExcessCarsInTheSplit(splits, splits[e]);
            }
            // -->


            // build the exception list to classes to lock on this split
            // movedCategories = union of [movedCategories + reducedClasses + empty classes of 0 cars]
            foreach (var c in reducedClasses)
            {
                if (!movedCategories.Contains(c))
                {
                    movedCategories.Add(c);
                }
            }
            foreach (var c in carClassesIds)
            {
                int classIndex = carClassesIds.IndexOf(c);
                if (s.CountClassCars(classIndex) == 0)
                {
                    if (!movedCategories.Contains(c))
                    {
                        movedCategories.Add(c);
                    }
                }
            }
            // -->

            // up cars to fill leaved slot again
            // for classe not in the exception list 'movedCategories'
            UpCarsToSplit(splits, s, movedCategories);
            // -->
        }