Esempio n. 1
0
        /// <summary>
        /// Creator: Jordan Lindo
        /// Created: 4/27/2020
        /// Approver: Chase Schulte
        ///
        /// List Shuffle method.
        /// </summary>
        /// <remarks>
        /// Updater: NA
        /// Updated: NA
        /// Update: NA
        ///
        /// </remarks>
        /// <param name="list"></param>
        /// <returns></returns>
        private List <PUUserVMAvailability> listShuffle(List <PUUserVMAvailability> list)
        {
            Random random = new Random();
            int    number = list.Count;
            int    sides  = 2;
            int    chance = random.Next(sides);

            if (number > 2 || chance > 0)
            {
                while (number > 1)
                {
                    int randInt = random.Next(number);
                    number--;
                    PUUserVMAvailability temp = list[randInt];
                    list[randInt] = list[number];
                    list[number]  = temp;
                }
            }
            return(list);
        }
Esempio n. 2
0
        /// <summary>
        /// Creator: Jordan Lindo
        /// Created: 4/23/2020
        /// Approver: Chase Schulte
        ///
        /// Method for generating a schedule
        /// </summary>
        /// <remarks>
        /// Updater: Jordan Lindo
        /// Updated: 4/28/2020
        /// Update: Added limit to the number allowed.
        ///
        /// </remarks>
        /// <param name="date"></param>
        /// <param name="lines"></param>
        /// <returns></returns>
        public ScheduleVM GenerateSchedule(DateTime date, List <BaseScheduleLine> lines)
        {
            ScheduleVM schedule = new ScheduleVM();

            schedule.ScheduleLines = new List <ShiftUserVM>();
            int daysInSchedule = 14;

            schedule.StartDate = date;
            schedule.EndDate   = date.AddDays(daysInSchedule);
            _openPositions     = new List <OpenPosition>();

            // List for storing which employee is scheduled by day
            List <List <int> > employeeIDsInSchedule = new List <List <int> >();

            // List for recording the count of hours for each employee;
            _employeeHours = new List <PUUserVMHours>();
            try
            {
                int scheduleCount = _scheduleAccessor.GetCountOfActiveSchedules();

                if (scheduleCount < 4)
                {
                    // A loop for repeating for each day in the schedule.
                    for (int i = 0; i < daysInSchedule; i++)
                    {
                        // The list representing the day of the week
                        employeeIDsInSchedule.Add(new List <int>());

                        // A loop to work through a base schedule
                        foreach (BaseScheduleLine line in lines)
                        {
                            // Skip if none are needed.
                            if (line.Count > 0)
                            {
                                // Get a list of possible choices.
                                List <PUUserVMAvailability> shuffle   = _scheduleAccessor.GetListOfAvailableEmployees(date.AddDays(i), line);
                                List <PUUserVMAvailability> avaliable = listShuffle(shuffle);
                                // Skip if no choices are available.
                                if (avaliable != null && avaliable.Count > 0)
                                {
                                    PetUniverseShiftTime shiftTime   = _shiftTimeAccessor.SelectShiftTimeByID(line.ShiftTimeID);
                                    DateTime             shiftStart  = DateTime.Parse(shiftTime.StartTime);
                                    DateTime             shiftEnd    = DateTime.Parse(shiftTime.EndTime);
                                    TimeSpan             shiftLength = shiftEnd - shiftStart;
                                    double minimumHoursToWork        = 6;

                                    bool end = false;
                                    // A loop for the number of positions to fill.
                                    for (int j = line.Count; j > 0 && !end; j--)
                                    {
                                        bool found = false;
                                        int  index = 0;
                                        PUUserVMAvailability candidate = avaliable[index];
                                        PUUserVMAvailability chosen    = null;
                                        int next = index;
                                        do
                                        {
                                            // Check if the candidate is already scheduled on a day.
                                            if (!employeeIDsInSchedule[i].Contains(candidate.PUUserID))
                                            {
                                                DateTime availabilityStart = DateTime.Parse(candidate.Availability.StartTime);
                                                DateTime availabilityEnd   = DateTime.Parse(candidate.Availability.EndTime);
                                                TimeSpan availableLength   = availabilityEnd.Subtract(availabilityStart);

                                                // Short availabilities will be skipped.
                                                if (availableLength.TotalHours >= minimumHoursToWork)
                                                {
                                                    // If the shift start time is after or equal to the availability start time.
                                                    if (shiftStart.CompareTo(availabilityStart) >= 0)
                                                    {
                                                        // If the shift end time is after or equal with the availability end time.
                                                        if (shiftEnd.CompareTo(availabilityEnd) >= 0)
                                                        {
                                                            // If the diference between availability start and
                                                            if (availabilityEnd.Subtract(shiftStart).TotalHours >= minimumHoursToWork)
                                                            {
                                                                shiftEnd = availabilityEnd;
                                                                found    = true;
                                                            }
                                                        }
                                                        else
                                                        {
                                                            found = true;
                                                        }
                                                    }
                                                    // Checks if the person is available for enough of the shift to be scheduled.
                                                    else if ((shiftEnd.Subtract(availabilityStart)).TotalHours >= minimumHoursToWork)
                                                    {
                                                        shiftStart = availabilityStart;
                                                        found      = true;
                                                    }

                                                    if (found)
                                                    {
                                                        bool allowed = true;
                                                        // A loop to see if a person is already scheduled the current day.
                                                        foreach (PUUserVMHours userVMHours in _employeeHours)
                                                        {
                                                            // If the person is found on the current day
                                                            if (userVMHours.PUUserID.Equals(candidate.PUUserID))
                                                            {
                                                                // If the date is in the first week
                                                                if (i < (daysInSchedule / 2))
                                                                {
                                                                    // Check if the user is already scheduled for 40 hours
                                                                    if (userVMHours.Week1Hours >= 40)
                                                                    {
                                                                        allowed = false;
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    if (userVMHours.Week2Hours >= 40)
                                                                    {
                                                                        allowed = false;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        // If the user hasn't already been scheduled for 40 hours in a week.
                                                        if (allowed)
                                                        {
                                                            // UserId is added to the list of people scheduled on a day.
                                                            employeeIDsInSchedule[i].Add(candidate.PUUserID);
                                                            chosen = candidate;
                                                            bool inList = false;
                                                            // Loop to see if a corresponding user is in the list of hours.
                                                            foreach (PUUserVMHours userVMHours in _employeeHours)
                                                            {
                                                                // If user matches an member
                                                                if (userVMHours.PUUserID.Equals(chosen.PUUserID))
                                                                {
                                                                    inList = true;
                                                                    // Find which week's total hours to update
                                                                    if (i < (daysInSchedule / 2))
                                                                    {
                                                                        userVMHours.Week1Hours += (decimal)(shiftEnd.Subtract(shiftStart)).TotalHours;
                                                                    }
                                                                    else
                                                                    {
                                                                        userVMHours.Week2Hours += (decimal)(shiftEnd.Subtract(shiftStart)).TotalHours;
                                                                    }
                                                                }
                                                            }
                                                            if (!inList)
                                                            {
                                                                // Build a new userVMHours add the hours to the correct week.
                                                                PUUserVMHours userVMHours = new PUUserVMHours
                                                                {
                                                                    PUUserID  = chosen.PUUserID,
                                                                    Email     = chosen.Email,
                                                                    FirstName = chosen.FirstName,
                                                                    LastName  = chosen.LastName
                                                                };
                                                                if (i < (daysInSchedule / 2))
                                                                {
                                                                    userVMHours.Week1Hours += (decimal)(shiftEnd.Subtract(shiftStart)).TotalHours;
                                                                    userVMHours.Week2Hours  = 0;
                                                                }
                                                                else
                                                                {
                                                                    userVMHours.Week1Hours  = 0;
                                                                    userVMHours.Week2Hours += (decimal)(shiftEnd.Subtract(shiftStart)).TotalHours;
                                                                }
                                                                _employeeHours.Add(userVMHours);
                                                            }
                                                        }
                                                        // If it was found, but failed to meet the alternate requirements set found back to false.
                                                        else
                                                        {
                                                            found = false;
                                                        }
                                                    }
                                                }
                                            }
                                            // Move to the next list item.
                                            next++;
                                            if (next != avaliable.Count)
                                            {
                                                candidate = avaliable[next];
                                            }
                                            // Decide if the loop continues
                                        } while (!found && next < avaliable.Count);

                                        // If an appropriate user was found a shift is added to the schedule.
                                        if (found)
                                        {
                                            schedule.ScheduleLines.Add(new ShiftUserVM
                                            {
                                                ShiftTimeID  = line.ShiftTimeID,
                                                ShiftDate    = date.AddDays(i),
                                                RoleID       = line.ERoleID,
                                                EmployeeID   = chosen.PUUserID,
                                                EmployeeName = chosen.LastName + ", " + chosen.FirstName,
                                                ShiftStart   = shiftStart.ToShortTimeString(),
                                                ShiftEnd     = shiftEnd.ToShortTimeString()
                                            });
                                        }
                                        // If no users were available the openings are recorded in the open positions list.
                                        else
                                        {
                                            _openPositions.Add(new OpenPosition
                                            {
                                                ERoleID = line.ERoleID,
                                                count   = j
                                            });
                                            // To prevent more checks for this baseSchedule line based on the remaining count.
                                            end = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    throw new ApplicationException("That schedule is too far in the future.");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return(schedule);
        }