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.
我有放在日历上的任务:
现在让我给出一些背景信息:每天在这里“持续”7.5 小时。但是我使用了一个名为 DayHours 的变量(现在是 7.5)。(DayHours 也用于锁定时间,这将在下面描述)。
此日历的目标是为员工安排 7.5 小时的工作日。
我需要的是一种算法,它可以正确地告诉我一天实际占用了多少小时。
这看起来很简单,但实际上是相当递归的。
首先,一些笔记。您会注意到案例经理在 14 小时时可以在 7.5 小时的 2 天中完成,剩下 1 小时。它被延长到 3 天,因为 1. 计划是 5 小时长,以及 2. 直到当天的前置任务完成后才能开始。
还有锁定时间的概念。紫色是锁定时间。这是一个 10 小时的锁定时间块。这意味着,在 12 日,我只能做 (7.5 - 7.5) 小时的工作,而周一也只能做 (7.5 - 2.5) 小时的工作。
我已经有一个函数来计算实际一天的可用时间来解决这个问题:
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;
}
还有携带时间的概念。
这是一个例子:
现在让我们以 18 号星期四为例(18 号有 1 个案例):
要找到该员工这一天的小时数,我们需要首先查看当天开始、结束或落入当天的任务。
我不知道我在 18 号可以做多少小时,因为那天结束的任务可能有携带时间。所以我去看看执行单元测试的开始日。我也想不通,因为 NWDM 当天完成,它可能需要几个小时。
所以现在我去评估 NWDM。啊,这一天没有结束,所以我知道日程安排需要 5 / 7.5 小时。
所以我继续前进,每天通过的时间增加 7.5 小时。
然后我到了 NWDM 的最后一天。在那之前,我工作了 5 + 7.5 + 7.5 + 7.5 小时,
所以我投入了 27.5 小时,所以我会在 22 日投入 (30 - 27.5 = 2.5h) 来完成它。所以我还有 5 个小时的时间来进行执行单元测试。
这意味着我需要 1.5 小时才能完成它。现在案例是 1 小时。
如果案例是 7.5 - 1.5 或更多,我们说这一天已满并返回 DayHours。
因此,我们完成了。返回值为 1.5 + 1 = 2.5。
该函数应该看起来有点像这样:
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;
}
要获取在给定日期内开始、结束或落下的事件,我使用:
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;
}
附表有以下相关字段:
DateFrom
DateTo
Hours
EmployeeID
时间表看起来像:
[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();
}
}
任何人都可以帮助我开发一种可以做到这一点的算法吗?