我一直在努力满足某些日子的需求,而且我认为我正在努力实现它。我想做一些流体旋转/换档系统。这应该是一个向导/随机函数功能,只是为了帮助用户创建“一次性”时间表(设施管理)。我想让它尽可能通用。
X员工数量
X每日轮班(例如早上,午餐,晚上和晚上)
X期间(例如4周 - 期间为一周)
这将导致以下设置:
第1周:早上(*),午餐,晚上和晚上
第2周:早上,午餐(*),傍晚和晚上
第3周:早上,午餐,晚上(*)和晚上
第4周:早上,午餐,晚上和晚上(*)
每位员工每周必须轮班,但在接下来的几周内班次不得相同。我可以要求应该有足够的工作人员来填补所有周的每个班次。每次执行结果都应该是随机的。
示例:
如果我有8名员工,每周4班。每周每班至少应有2名员工。
如果我有4名员工,每周4班。每周每班至少应有1名员工。
员工人数必须始终等于或超过轮班金额。
是否存在“残羹剩饭”这是可以的,当员工数量与班次数量不匹配时,用户必须定义更多轮班或员工。
示例可以在这里看到: http://v2.iclean.dk/shifts
我有以下代码:
类
[DebuggerDisplay("ID: {ID}, Name: {Name}")]
public class Staff
{
public Staff(int id, string name)
{
ID = id;
Name = name;
Schedulers = new List<StaffScheduler>();
}
public int ID { get; set; }
public string Name { get; set; }
public List<StaffScheduler> Schedulers { get; set; }
}
public class StaffMap
{
public StaffMap(Staff staff, StaffScheduler scheduler)
{
Staff = staff;
Scheduler = scheduler;
}
public Staff Staff { get; set; }
public StaffScheduler Scheduler { get; set; }
}
[DebuggerDisplay("ID: {ID}, Name: {Name}")]
public class StaffScheduler
{
public StaffScheduler(int id, string name)
{
ID = id;
Name = name;
}
public int ID { get; set; }
public string Name { get; set; }
}
[DebuggerDisplay("Name: {Name}, Start: {DateStart}, End: {DateEnd}")]
public class DateRangeShift
{
public DateRangeShift()
{
Staff = new List<StaffMap>();
}
public DateRangeShift(string name, DateTime start, DateTime end)
: this()
{
Name = name;
DateStart = start;
DateEnd = new DateTime(end.Year, end.Month, end.Day, 23, 59, 59);
}
public string Name { get; set; }
public DateTime DateStart { get; set; }
public DateTime DateEnd { get; set; }
public List<StaffMap> Staff { get; set; }
}
MVC控制器代码
private readonly int SHIFTS_MAX_SHUFFLE_RETRIES = 50;
public ActionResult Index()
{
var dailySchedules = new List<StaffScheduler>() {
new StaffScheduler(1, "Morning"),
new StaffScheduler(2, "Lunch"),
new StaffScheduler(3, "Evening"),
new StaffScheduler(4, "Night")
};
List<DateRangeShift> shiftList = new List<DateRangeShift>();
shiftList.Add(new DateRangeShift("Week 1", new DateTime(2013, 3, 4), new DateTime(2013, 3, 10)));
shiftList.Add(new DateRangeShift("Week 2", new DateTime(2013, 3, 11), new DateTime(2013, 3, 17)));
shiftList.Add(new DateRangeShift("Week 3", new DateTime(2013, 3, 18), new DateTime(2013, 3, 24)));
shiftList.Add(new DateRangeShift("Week 4", new DateTime(2013, 3, 25), new DateTime(2013, 3, 31)));
List<Staff> staffList = new List<Staff>();
staffList.Add(new Staff(1, "Fred Smith"));
staffList.Add(new Staff(2, "Charlie Brown"));
staffList.Add(new Staff(3, "Samantha Green"));
staffList.Add(new Staff(4, "Bash Malik"));
staffList.Add(new Staff(5, "Bryan Griffiths"));
staffList.Add(new Staff(6, "Akaash Patel"));
staffList.Add(new Staff(7, "Kang-Hyun Kim"));
staffList.Add(new Staff(8, "Pedro Morales"));
var shiftSegmentSize = (int)Math.Floor((double)staffList.Count / (double)dailySchedules.Count)
int shuffleCount = 0;
bool shuffleMatchedSize = true;
do
{
shiftList.ForEach(e => e.Staff.Clear());
shuffleMatchedSize = true;
foreach (var shift in shiftList)
{
foreach (var scheduler in dailySchedules)
{
var schedulerEmployees = staffList.OrderByDescending(e => e.Schedulers.Count()).ThenBy(e => Guid.NewGuid()).Where(e => !shiftList.Any(sl => sl.Staff.Any(s => s.Scheduler.ID == scheduler.ID && s.Staff.ID == e.ID)) && !shift.Staff.Any(s => s.Staff.ID == e.ID)).Take(shiftSegmentSize).ToList();
if (schedulerEmployees.Count < shiftSegmentSize)
{
shuffleMatchedSize = false;
shuffleCount++;
break;
}
while (schedulerEmployees.Count > 0)
{
var staffSelector = schedulerEmployees.FirstOrDefault();
var staff = staffList.FirstOrDefault(e => e.ID == staffSelector.ID);
staff.Schedulers.Add(scheduler);
shift.Staff.Add(new StaffMap(staff, scheduler));
schedulerEmployees.Remove(staffSelector);
}
}
if (!shuffleMatchedSize)
break;
}
} while (!shuffleMatchedSize && shuffleCount < SHIFTS_MAX_SHUFFLE_RETRIES);
ViewData["Iterations"] = shuffleCount;
return View(shiftList);
}
但是,因为我按照分配给员工的班次数量订购,然后随机订购..我有一个重试,直到我得到一分钟。工作人员/班次的匹配。
<h2>Week 1 <span>(04-03-2013 - 10-03-2013)</span></h2>
<table>
<tr>
<td>Morning</td>
<td>Akaash Patel, Bash Malik</td>
</tr>
<tr>
<td>Lunch</td>
<td>Fred Smith, Kang-Hyun Kim</td>
</tr>
<tr>
<td>Evening</td>
<td>Charlie Brown, Samantha Green</td>
</tr>
<tr>
<td>Night</td>
<td>Bryan Griffiths, Pedro Morales</td>
</tr>
</table>
<h2>Week 2 <span>(11-03-2013 - 17-03-2013)</span></h2>
<table>
<tr>
<td>Morning</td>
<td>Fred Smith, Kang-Hyun Kim</td>
</tr>
<tr>
<td>Lunch</td>
<td>Akaash Patel, Bash Malik</td>
</tr>
<tr>
<td>Evening</td>
<td>Bryan Griffiths, Pedro Morales</td>
</tr>
<tr>
<td>Night</td>
<td>Charlie Brown, Samantha Green</td>
</tr>
</table>
<h2>Week 3 <span>(18-03-2013 - 24-03-2013)</span></h2>
<table>
<tr>
<td>Morning</td>
<td>Charlie Brown, Samantha Green</td>
</tr>
<tr>
<td>Lunch</td>
<td>Bryan Griffiths, Pedro Morales</td>
</tr>
<tr>
<td>Evening</td>
<td>Akaash Patel, Fred Smith</td>
</tr>
<tr>
<td>Night</td>
<td>Bash Malik, Kang-Hyun Kim</td>
</tr>
</table>
<h2>Week 4 <span>(25-03-2013 - 31-03-2013)</span></h2>
<table>
<tr>
<td>Morning</td>
<td>Bryan Griffiths, Pedro Morales</td>
</tr>
<tr>
<td>Lunch</td>
<td>Charlie Brown, Samantha Green</td>
</tr>
<tr>
<td>Evening</td>
<td>Bash Malik, Kang-Hyun Kim</td>
</tr>
<tr>
<td>Night</td>
<td>Akaash Patel, Fred Smith</td>
</tr>
</table>
我无法理解如何做到这一点。希望有人能指导我。
答案 0 :(得分:1)
我认为这对你有用:
int maxLength = Math.Max(shiftList.Count, dailySchedules.Count);
var shiftSegmentSize = staffList.Count / maxLength;
var schedulerEmployees = staffList.OrderBy(e => Guid.NewGuid())
.Take(shiftSegmentSize * maxLength)
.ToArray(); //
for (int k = 0; k < shiftList.Count; k++)
{
for (int j = 0; j < dailySchedules.Count; j++)
{
int staffindex = (maxLength + j - k) % maxLength;
for (int i = 0; i < shiftSegmentSize; i++)
{
schedulerEmployees[staffindex + (i * maxLength)].Schedulers.Add(dailySchedules[j]);
shiftList[k].Staff.Add(new StaffMap(schedulerEmployees[staffindex + i * maxLength], dailySchedules[j]));
}
}
}
答案 1 :(得分:0)
我在这里玩你的代码,现在我认为它是正确的:
var dailySchedules = new List<StaffScheduler>() {
new StaffScheduler(1, "Morning"),
new StaffScheduler(2, "Lunch"),
new StaffScheduler(3, "Evening"),
new StaffScheduler(4, "Night")
};
List<DateRangeShift> shiftList = new List<DateRangeShift>();
shiftList.Add(new DateRangeShift("Week 1", new DateTime(2013, 3, 4), new DateTime(2013, 3, 10)));
shiftList.Add(new DateRangeShift("Week 2", new DateTime(2013, 3, 11), new DateTime(2013, 3, 17)));
shiftList.Add(new DateRangeShift("Week 3", new DateTime(2013, 3, 18), new DateTime(2013, 3, 24)));
shiftList.Add(new DateRangeShift("Week 4", new DateTime(2013, 3, 25), new DateTime(2013, 3, 31)));
List<Staff> staffList = new List<Staff>();
staffList.Add(new Staff(1, "Fred Smith"));
staffList.Add(new Staff(2, "Charlie Brown"));
staffList.Add(new Staff(3, "Samantha Green"));
staffList.Add(new Staff(4, "Bash Malik"));
staffList.Add(new Staff(5, "Bryan Griffiths"));
staffList.Add(new Staff(6, "Akaash Patel"));
staffList.Add(new Staff(7, "Kang-Hyun Kim"));
staffList.Add(new Staff(8, "Pedro Morales"));
var shiftSegmentSize = (int)Math.Floor((double)staffList.Count / (double)dailySchedules.Count);
Dictionary<StaffScheduler, Staff[]> map = new Dictionary<StaffScheduler, Staff[]>();
foreach (var schedule in dailySchedules)
{
map.Add(schedule, staffList.ToArray());
}
Random r = new Random();
foreach (var shift in shiftList)
{
shift.Staff = new List<StaffMap>();
foreach(var schedule in dailySchedules)
{
int randomStaff_Index = r.Next(map[schedule].Length);
Staff randStaff = map[schedule][randomStaff_Index];
map[schedule] = map[schedule].Where(x => x != randStaff).ToArray();
shift.Staff.Add(new StaffMap(randStaff, schedule));
}
}
答案 2 :(得分:0)
最终结果变为:
<强>型号:强>
[DebuggerDisplay("ID: {ID}, Name: {Name}")]
public class Employee
{
public Employee(string name)
{
Name = name;
Schedules = new List<Schedule>();
}
public string Name { get; set; }
public List<Schedule> Schedules { get; set; }
}
public class EmployeeSchedule
{
public EmployeeSchedule(Employee employee, Schedule schedule)
{
Employee = employee;
Schedule = schedule;
}
public Employee Employee { get; set; }
public Schedule Schedule { get; set; }
}
[DebuggerDisplay("ID: {ID}, Name: {Name}")]
public class Schedule
{
public Schedule(string name)
{
Name = name;
}
public string Name { get; set; }
}
[DebuggerDisplay("Name: {Name}, Start: {DateStart}, End: {DateEnd}")]
public class Shift
{
public Shift()
{
EmployeeSchedules = new List<EmployeeSchedule>();
}
public Shift(string name, DateTime start, DateTime end) : this()
{
Name = name;
DateStart = start.Date;
DateEnd = new DateTime(end.Year, end.Month, end.Day, 23, 59, 59, 999);
}
public string Name { get; set; }
public DateTime DateStart { get; set; }
public DateTime DateEnd { get; set; }
public List<EmployeeSchedule> EmployeeSchedules { get; set; }
}
控制台应用代码:
class Program
{
static void Main(string[] args)
{
var schedules = new List<Schedule>();
schedules.Add(new Schedule("Morning"));
schedules.Add(new Schedule("Lunch"));
schedules.Add(new Schedule("Evening"));
schedules.Add(new Schedule("Night"));
var shifts = new List<Shift>();
shifts.Add(new Shift("Week 1", new DateTime(2013, 3, 4), new DateTime(2013, 3, 10)));
shifts.Add(new Shift("Week 2", new DateTime(2013, 3, 11), new DateTime(2013, 3, 17)));
shifts.Add(new Shift("Week 3", new DateTime(2013, 3, 18), new DateTime(2013, 3, 24)));
shifts.Add(new Shift("Week 4", new DateTime(2013, 3, 25), new DateTime(2013, 3, 31)));
var employees = new List<Employee>();
employees.Add(new Employee("Fred Smith"));
employees.Add(new Employee("Charlie Brown"));
employees.Add(new Employee("Samantha Green"));
employees.Add(new Employee("Bash Malik"));
employees.Add(new Employee("Bryan Griffiths"));
employees.Add(new Employee("Akaash Patel"));
employees.Add(new Employee("Kang-Hyun Kim"));
employees.Add(new Employee("Pedro Morales"));
ShuffleEmployees(ref shifts, schedules, employees);
var scheduleNameMaxLength = schedules.Max(e => e.Name.Length);
foreach (var shift in shifts)
{
Console.WriteLine($"{shift.Name} ({shift.DateStart:D} - {shift.DateEnd:D})");
foreach (var map in shift.EmployeeSchedules)
{
Console.WriteLine($"- {map.Schedule.Name.PadRight(scheduleNameMaxLength + 1, ' ')}: {map.Employee.Name}");
}
Console.WriteLine();
}
Console.WriteLine("Press any key to continue ...");
Console.ReadKey();
}
static void ShuffleEmployees(ref List<Shift> shifts, List<Schedule> schedules, List<Employee> employees)
{
var maxLength = Math.Max(shifts.Count, schedules.Count);
var shiftSegmentSize = (employees.Count / maxLength);
var employeeList = employees.OrderBy(e => Guid.NewGuid()).Take(shiftSegmentSize * maxLength).ToArray();
var shiftsCount = shifts.Count;
var schedulesCount = schedules.Count;
for (int shiftIndex = 0; shiftIndex < shiftsCount; shiftIndex++)
{
for (int scheduleIndex = 0; scheduleIndex < schedulesCount; scheduleIndex++)
{
var employeeIndex = (maxLength + scheduleIndex - shiftIndex) % maxLength;
for (int segment = 0; segment < shiftSegmentSize; segment++)
{
employeeList[employeeIndex + (segment * maxLength)].Schedules.Add(schedules[scheduleIndex]);
shifts[shiftIndex].EmployeeSchedules.Add(new EmployeeSchedule(employeeList[employeeIndex + segment * maxLength], schedules[scheduleIndex]));
}
}
}
}
}