示例#1
0
文件: Instance.cs 项目: fvoska/HMO
        private void ParseCover(string line)
        {
            var lineSplit        = line.Split(',');
            CoverRequirement req = new CoverRequirement(lineSplit[1], Convert.ToInt32(lineSplit[2]), Convert.ToInt32(lineSplit[3]), Convert.ToInt32(lineSplit[4]));

            if (!DailyRequirements.ContainsKey(Convert.ToInt32(lineSplit[0])))
            {
                DailyRequirements[Convert.ToInt32(lineSplit[0])] = new List <CoverRequirement>();
            }
            DailyRequirements[Convert.ToInt32(lineSplit[0])].Add(req);
        }
示例#2
0
文件: Instance.cs 项目: fvoska/HMO
        public static void Assign()
        {
            for (int day = 0; day < Days; day++)
            {
                bool isWeekend = false;
                if ((day + 1) % 7 == 0 || (day + 2) % 7 == 0)
                {
                    isWeekend = true;
                }
                Console.WriteLine("Day #" + day + " (is weekend: " + isWeekend + ")");
                foreach (KeyValuePair <string, Shift> shift in Shifts)
                {
                    Dictionary <string, Worker> potentialWorkers  = Workers.ToDictionary(d => d.Key, d => d.Value);
                    CoverRequirement            coverRequirements = DailyRequirements[day].Where(r => r.ShiftID == shift.Value.ID).First();

                    Console.WriteLine("\tShift " + shift.Value.ID + " (cover target: " + coverRequirements.Requirement + ")");

                    // Nikada nećemo u jednom danu uzeti više od preporučenog broja radnika, ali možda nećemo moći odabrati točno taj broj nego neki manji broj jer nam nije preostalo dovoljno radnika (npr. sve smo ih odbacili jakim ograničenjima).
                    // (3.bullet slabih ogr., broj radnika smjene)
                    for (int assignedNumberOfWorkers = 0; assignedNumberOfWorkers < coverRequirements.Requirement * 1.5; assignedNumberOfWorkers++)
                    {
                        Console.WriteLine("\t\tTrying to assign worker " + (assignedNumberOfWorkers + 1) + "/" + coverRequirements.Requirement);

                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers.");

                        // Odbaci radnike koji su ovaj dan već dobili smjenu.
                        // (1. bullet jakih org.)
                        removeByShiftAlreadyAssignedToday(potentialWorkers, day);
                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers who already worked today.");

                        // Odbaci radnike koji ne mogu raditi u smjeni s jer su radili u nekoj ranijoj smjeni.
                        // (2.bullet jakih ogr., SECTION_SHIFTS -Shifts which cannot follow this shift)
                        removeByShiftRotation(potentialWorkers, day, shift.Value);
                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers based on shift rotation.");

                        // (3. bullet jakit ogr.)
                        removeByShiftType(potentialWorkers, shift.Value);
                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers based on shift type.");

                        // Odbaci radnike za koje vrijedi:
                        //      Do sada sveukupni broj minuta koje su odravili + vrijeme trajanja smjene s > MaxTotalMinutes.
                        // (4.bullet jakih, SECTION_STAFF - MaxTotalMinutes)
                        removeByMaxTotalMinutes(potentialWorkers, shift.Value);
                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers who reached max minutes.");

                        // Odbaci radnike kojima bi rad u ovoj smjeni prekršio ograničenje maksimalnog broja uzastopnih smjena (takvi moraju na odmor).
                        // (5.bullet jakih, SECTION_STAFF - MaxConsectiveShifts)
                        removeByMaxConsectiveShifts(potentialWorkers, day);
                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers by max consecutive shifts.");

                        // Odbaci radnike koji još nisu bili na odmoru minimalni broj dana(moraju još biti na odmoru).
                        // (7.bullet jakih, SECTION_STAFF - MinConsecutiveDaysOff)
                        removeByMinConsecutiveDaysOff(potentialWorkers, day);
                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers by min days off.");

                        // Ako je dan d subota ili nedjelja:
                        //      Odbaci radnike koji su već na maksimalnom broju radnih vikenda.
                        // (8.bullet jakih)
                        if (isWeekend)
                        {
                            removeByMaxWeekends(potentialWorkers);
                            Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers who worked max weekends.");
                        }

                        // Odbaci radnike kojima je dan d označen kao neradni.
                        // (9.bullet jakih)
                        removeByDaysOff(potentialWorkers, day);
                        Console.WriteLine("\t\t\tConsidering " + potentialWorkers.Count + " workers after removing workers who have this day off.");

                        // Ako među preostalim korisnicima postoji jedan ili više korisnika za koje bi ako ne dobiju neku smjenu ovog dana bilo prekršeno ograničenje minimalnog broja uzastopnih radnih dana(smjena, 1 smjena == 1 dan) koje moraju odraditi za redom:
                        //      Odbaci sve ostale radnike i nastavi dalje samo s onima koji su u opasnosti da ne zadovolje ograničenje minimalnog broja uzastopnih radnih dana.
                        // (6.bullet jakih)

                        /*var tmp = checkForMinConsecutiveShifts(potentialWorkers, day);
                         * if (tmp.Count > 0)
                         * {
                         *  potentialWorkers = tmp;
                         * }*/

                        if (potentialWorkers.Count > 0)
                        {
                            var    workersByRemainingMinutes = potentialWorkers.Values.OrderBy(w => w.RemainingMinutes).ToList();
                            int    depthLimit = 50;
                            int    depth      = 0;
                            float  remMin     = workersByRemainingMinutes.First().RemainingMinutes;
                            Worker aw         = null;
                            foreach (Worker ww in workersByRemainingMinutes)
                            {
                                if (ww.DaysOff.Contains(day + 1) && !ww.Assignments.ContainsKey(day - 1))
                                {
                                    continue;
                                }
                                if (ww.ShiftOffRequests.ContainsKey(day))
                                {
                                    continue;
                                }
                                if (ww.RemainingMinutes != remMin)
                                {
                                    remMin = ww.RemainingMinutes;
                                    depth++;
                                }
                                if (depth > depthLimit)
                                {
                                    break;
                                }
                                if (ww.ShiftOnRequests.ContainsKey(day))
                                {
                                    aw = ww;
                                    break;
                                }
                            }
                            if (aw == null)
                            {
                                aw = workersByRemainingMinutes.First();
                            }
                            Assignment a = new Assignment();
                            a.Day               = day;
                            a.Shift             = Shifts[shift.Value.ID];
                            a.Worker            = aw;
                            aw.Assignments[day] = a;
                            if (isWeekend)
                            {
                                aw.WorkedWeekends++;
                            }
                        }
                    }
                }
            }
            ExpandRight();
            ExpandLeft();
            FixMaxConsecutive();
            RemoveSingles();
            ExpandRight();
            ExpandLeft();
            FixMaxConsecutive();
            RemoveMinConsecutive();
            SplitMinRest();
            //TryFill();
            //FixSingleDayBefore();
            //FixSingleDayAfter();
        }