Edit:
Steps:
Start at target day.
Then move backwards until no events are carried over from another day.
From there, start counting hours, and keep track of carried over hours.
Day cannot last more than ActualDayLength()
Then, once you know that, work your way back to target and then calculate actual occupied hours.
Tôi có nhiệm vụ được đặt trên một lịch:Thuật toán hàng giờ bị chiếm đóng trong ngày bởi nhiệm vụ
Bây giờ hãy để tôi cung cấp cho này một số bối cảnh: Mỗi ngày 'kéo dài' 7,5 giờ đây . Nhưng tôi làm việc với một biến gọi là DayHours (mà ngay bây giờ là 7.5). (DayHours cũng được sử dụng trong thời gian bị khóa mà Ill mô tả dưới đây).
Mục tiêu của lịch này là lên lịch 7,5 ngày làm việc cho nhân viên.
Những gì tôi cần, là một thuật toán có thể cho tôi biết chính xác số giờ thực sự bị chiếm đóng trong một ngày.
Điều này có vẻ đơn giản, nhưng thực sự khá đệ quy.
Đầu tiên, một vài ghi chú. Bạn sẽ nhận thấy trường hợp quản lý, tại 14 giờ, có thể được thực hiện trong 2 ngày của 7,5 giờ với 1 giờ còn lại. Nó được kéo dài đến 3 ngày bởi vì 1. Lịch trình, là 5 giờ dài, và 2. không thể bắt đầu cho đến khi nhiệm vụ tiền nhiệm của ngày được hoàn thành.
Ngoài ra còn có khái niệm về Thời gian bị khóa. Màu tím là Thời gian đã khóa. Đây là khoảng thời gian bị khóa 10 giờ. Điều này có nghĩa là, vào ngày 12, tôi chỉ có thể làm (7,5 - 7,5) giờ làm việc, và thứ hai, chỉ (7,5 - 2,5) là tốt.
Tôi đã có một hàm để tính toán giờ có sẵn một ngày thực tế để giải thích cho điều này:
public decimal GetActualDayLength(DateTime day, Schedule s)
{
var e = Schedules.GetAllWithElement();
var t = Timeless(day);
var locked = from p in e
where p.EmployeID == s.EmployeID &&
((p.DateTo.Value.Date) >= t &&
Timeless(p.DateFrom.Value) <= t) &&
p.IsLocked
select p;
decimal hrs = 0.0M;
foreach (var c in locked)
{
if (c.Hours.Value <= DaysManager.GetDayHours())
hrs += c.Hours.Value;
else if (Timeless(c.DateTo.Value) != t)
hrs += DaysManager.GetDayHours();
else
{
if (c.Hours.Value % DaysManager.GetDayHours() > 0)
hrs += c.Hours.Value % DaysManager.GetDayHours();
else
hrs += DaysManager.GetDayHours();
}
}
return DaysManager.GetDayHours() - hrs;
}
Ngoài ra còn có các khái niệm về giờ carry.
Dưới đây là một ví dụ:
Bây giờ chúng ta hãy thứ năm 18 (The 18th có 1. Trường hợp):
Để tìm số giờ trong ngày này có cho nhân viên đó, trước tiên chúng ta cần xem xét các nhiệm vụ bắt đầu, kết thúc hoặc rơi vào ngày đó.
Tôi không biết bao nhiêu giờ tôi có thể làm vào ngày 18 vì nhiệm vụ kết thúc ngày hôm đó có thể đã mang theo giờ. Vì vậy, tôi sẽ xem xét ngày bắt đầu của Perform unit test. Tôi không thể tìm ra điều đó vì NWDM kết thúc ngày hôm đó và nó có thể mang theo giờ.
Vì vậy, bây giờ tôi đi đánh giá NWDM. Ahh, cái này không có gì kết thúc vào ngày hôm đó, vì vậy tôi biết Lịch biểu sẽ mất 5/7,5 giờ.
Vì vậy, tôi tiếp tục, thêm 7,5 giờ mỗi ngày tôi vượt qua.
Sau đó, tôi đến ngày cuối cùng của NWDM. Cho đến lúc đó, tôi đã làm việc 5 + 7,5 + 7,5 + 7,5 giờ trên đó,
Vì vậy, tôi đặt trong 27,5 giờ, vì vậy tôi sẽ đưa vào (30 - 27,5 = 2,5h) vào ngày 22 để hoàn thành. Vì vậy, tôi còn 5 giờ để thực hiện Bài kiểm tra thực hiện đơn vị.
Điều này có nghĩa là tôi sẽ cần 1.5h để hoàn thành. Trường hợp bây giờ là 1 giờ.
Trường hợp đã xảy ra từ 7.5 - 1.5 trở lên, chúng tôi cho biết ngày đó đã đầy và trả lại DayHours.
Vì vậy, chúng tôi đã hoàn tất. Giá trị trả về là 1,5 + 1 = 2,5.
Chức năng nên xem xét một chút như thế này:
public decimal GetHours(IEnumerable<Schedule> s, DateTime today)
{
DateTime t = Timeless(today);
decimal hrs = 0;
foreach (Schedule c in s)
{
if (c.Hours.Value <= DaysManager.GetDayHours())
hrs += c.Hours.Value;
else if (Timeless(c.DateTo.Value) != t)
hrs += DaysManager.GetDayHours();
else
{
if (c.Hours.Value % DaysManager.GetDayHours() > 0)
hrs += c.Hours.Value % DaysManager.GetDayHours();
else
hrs += DaysManager.GetDayHours();
}
}
return hrs;
}
Để có được những sự kiện bắt đầu, kết thúc, hoặc nằm trong một ngày nhất định, tôi sử dụng:
public IEnumerable<Schedule> GetAllToday(DateTime date, int employeeID, Schedule current)
{
DateTime t = Timeless(date);
int sid = current == null ? -1 : current.ScheduleID;
var e = Schedules.GetAllWithElement();
return from p in e
where (((Timeless(p.DateTo.Value) >= t &&
Timeless(p.DateFrom.Value) <= t &&
p.EmployeID == employeeID) &&
(p.IsLocked || (Timeless(p.DateFrom.Value) < t &&
(sid == -1 ? true : Timeless(p.DateFrom.Value) < current.DateFrom.Value)) ||
bumpedList.Any(d => d.ScheduleID == p.ScheduleID)) &&
p.ScheduleID != sid) ||
((Timeless(p.DateTo.Value) >= t &&
(Timeless(p.DateFrom.Value) == t || (Timeless(p.DateFrom.Value) < t &&
(sid == -1 ? true : Timeless(p.DateFrom.Value) > current.DateFrom.Value))) &&
p.EmployeID == employeeID) &&
!p.IsLocked &&
!bumpedList.Any(d => d.ScheduleID == p.ScheduleID) &&
p.ScheduleID != sid)) &&
p.ScheduleID != sid
select p;
}
Các Schedule có các trường có liên quan sau:
DateFrom
DateTo
Hours
EmployeeID
Lịch biểu trông giống như sau:
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Schedule")]
public partial class Schedule : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _ScheduleID;
private System.Nullable<System.DateTime> _DateFrom;
private System.Nullable<decimal> _Hours;
private System.Nullable<int> _EmployeID;
private System.Nullable<int> _RecurringID;
private System.Nullable<int> _Priority;
private System.Nullable<System.DateTime> _DateTo;
private bool _IsLocked;
private System.Nullable<int> _BumpPriority;
private EntitySet<Case> _Cases;
private EntitySet<Project> _Projects;
private EntitySet<Task> _Tasks;
private EntitySet<Task> _Tasks1;
private EntityRef<Employee> _Employee;
private EntityRef<Recurring> _Recurring;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnScheduleIDChanging(int value);
partial void OnScheduleIDChanged();
partial void OnDateFromChanging(System.Nullable<System.DateTime> value);
partial void OnDateFromChanged();
partial void OnHoursChanging(System.Nullable<decimal> value);
partial void OnHoursChanged();
partial void OnEmployeIDChanging(System.Nullable<int> value);
partial void OnEmployeIDChanged();
partial void OnRecurringIDChanging(System.Nullable<int> value);
partial void OnRecurringIDChanged();
partial void OnPriorityChanging(System.Nullable<int> value);
partial void OnPriorityChanged();
partial void OnDateToChanging(System.Nullable<System.DateTime> value);
partial void OnDateToChanged();
partial void OnIsLockedChanging(bool value);
partial void OnIsLockedChanged();
partial void OnBumpPriorityChanging(System.Nullable<int> value);
partial void OnBumpPriorityChanged();
#endregion
public Schedule()
{
this._Cases = new EntitySet<Case>(new Action<Case>(this.attach_Cases), new Action<Case>(this.detach_Cases));
this._Projects = new EntitySet<Project>(new Action<Project>(this.attach_Projects), new Action<Project>(this.detach_Projects));
this._Tasks = new EntitySet<Task>(new Action<Task>(this.attach_Tasks), new Action<Task>(this.detach_Tasks));
this._Tasks1 = new EntitySet<Task>(new Action<Task>(this.attach_Tasks1), new Action<Task>(this.detach_Tasks1));
this._Employee = default(EntityRef<Employee>);
this._Recurring = default(EntityRef<Recurring>);
OnCreated();
}
}
Có ai có thể giúp tôi phát triển thuật toán có thể thực hiện việc này không?
Bạn có thể, cố gắng và ngưng tụ sự cố của mình thành một bộ câu được xác định rõ ràng hoặc ít nhất được đánh dấu rõ ràng không? Tôi mất một chút thời gian để tìm ra câu hỏi thực tế. –
Tôi không chắc chắn cách chỉnh sửa theo cách này ... về cơ bản, bắt đầu vào ngày mục tiêu, sau đó di chuyển về phía sau cho đến khi không có gì được chuyển từ một ngày khác, từ đó, bắt đầu đếm giờ và theo dõi được mang theo giờ. Cũng xem xét rằng chiều dài ngày có thể được rút ngắn do thời gian bị khóa ... Sau đó, một khi bạn biết điều đó, hãy làm việc theo cách của bạn trở lại để nhắm mục tiêu và sau đó tính giờ thực tế chiếm đóng. – jmasterx
Tôi đã cố gắng để đưa điều này vào một số loại bước. – jmasterx