我真的很难做到这一点。我有一个开始和/或结束时间重叠的预订列表,我必须从中生成时间表项目。这些时间轴项目只能以3种样式生成:正常、警告或错误。
一天的默认开始时间为08:00,结束时间为18:00。
- 确认计数为1
- 警告计数为2
- 错误计数为3
每次超过阈值时,都应添加一个新的时间轴项目。结果来自以下保留:
- 预订时间:9:00至12:00
- 预订时间:10:00至12:00
- 预订时间:11:00至12:00
- 13:00至14:00预订
应给予这些时间轴项目作为结果:
- 从8:00到10:00的时间轴项目,单击“确定
- 时间轴项目从10:00到11:00,带警告(几乎满负荷)
- 时间轴项目从11:00到12:00,有错误(完整)
- 时间轴itsm从12:00到18:00与OK(0和1之间的保留在这段时间)
我已经尝试了一些for和foreach循环,但我真的被难倒了。目前,使用下面的代码,我遇到了错误的时间轴项目正在生成的问题。这很可能是由于我通过代码循环的方式。我想检查全天任何给定分钟的占用率,如果它超过了3个阈值之一,相应地创建一个新的时间线项目。而不需要每分钟都循环。
当前循环时的占用率除了循环的最后一次迭代外不会增加或减少。循环一天中的所有分钟并检查占用率可能会容易得多,但似乎效率真的很低。
转换WIP函数
var startTime = TimeSpan.FromHours(8);
var endTime = TimeSpan.FromHours(20);
var occupancy = 0;
var lastTime = startTime;
var timeLineItems = new List<TimeLineItem>();
var lastThresholdHit = 0;
var totalTime = (endTime - startTime).TotalMinutes;
for (var i = 0; i < totalTime; i++)
{
var currentTime = startTime + TimeSpan.FromMinutes(i);
var newOccupancy = processedReservations.Count(r => r.StartTime <= currentTime && r.EndTime >= currentTime);
if (occupancy != newOccupancy)
{
Debug.WriteLine(currentTime + ": " + newOccupancy);
if (newOccupancy <= _timeLineOkCount && lastThresholdHit != _timeLineOkCount)
{
var itemText = lastTime.ToString(@"hh\:mm") + " - " + currentTime.ToString(@"hh\:mm");
var item = new TimeLineItem(Color.Success, itemText);
timeLineItems.Add(item);
lastThresholdHit = _timeLineOkCount;
lastTime = currentTime;
} else
if (newOccupancy < _timeLineErrorCount && lastThresholdHit != _timeLineWarningCount)
{
var itemText = lastTime.ToString(@"hh\:mm") + " - " + currentTime.ToString(@"hh\:mm");
var item = new TimeLineItem(Color.Warning, itemText);
timeLineItems.Add(item);
lastThresholdHit = _timeLineWarningCount;
lastTime = currentTime;
}
else
if (lastThresholdHit != _timeLineErrorCount)
{
var itemText = lastTime.ToString(@"hh\:mm") + " - " + currentTime.ToString(@"hh\:mm");
var item = new TimeLineItem(Color.Error, itemText);
timeLineItems.Add(item);
lastThresholdHit = _timeLineErrorCount;
lastTime = currentTime;
}
}
occupancy = newOccupancy;
}
if (lastTime < endTime)
{
var itemText = lastTime.ToString(@"hh\:mm") + " - " + endTime.ToString(@"hh\:mm");
var item = new TimeLineItem(Color.Success, itemText);
timeLineItems.Add(item);
}
var orderedTimeLineItems = timeLineItems.OrderBy(i => i.ItemTimeText).ToList();
return orderedTimeLineItems;
我对上面的代码仍然有一些奇怪的地方。在某些情况下,调试日志返回的占用率为0,而它不应该返回,并且生成的项目还没有显示正确的时间。
时间线项目类
public class TimeLineItem
{
public Color ItemColor { get; set; }
public string ItemTimeText { get; set; }
public TimeLineItem(Color itemColor, string itemTimeText)
{
ItemColor = itemColor;
ItemTimeText = itemTimeText;
}
}
枚举类颜色
public enum Color
{
Success,
Warning,
Error
}
预订类
public class Reservation
{
public int Id { get; set; }
public TimeSpan StartTime { get; set; }
public TimeSpan EndTime { get; set; }
public DateTime Date { get; set; }
public Reservation(int id, TimeSpan startTime, TimeSpan endTime, DateTime date)
{
Id = id;
StartTime = startTime;
EndTime = endTime;
Date = date;
}
}
2条答案
按热度按时间emeijp431#
每当我试图解决这样的问题时,我发现将问题形象化是非常有用的,比如:
正如您所看到的,我们知道一个新的块只能在预订的开始时间或结束时间开始,所以代码可以简单地循环所有时间,以您需要的任何粒度,查找预订的开始时间或结束时间,并根据需要进行计算。
代码可以编写如下(假设粒度很小):
这将生成您所期望的输出:
示例:https://dotnetfiddle.net/WLomdH
肯定有一些边缘情况没有涵盖,但这应该给予你一个很好的基础来测试。
cwxwcias2#
功能完善,功能齐全
我决定使用.Aggregate()和其他一些LINQ方法,而不是使用分钟粒度和循环遍历每一分钟。最终结果非常好,除了由于某种原因开始项目时间为00:00。我通过检查项目开始时间是否早于允许的开始时间,然后将其设置为开始时间,来解决这个问题。
下面的代码块组合给予了最终结果工作函数。
主要功能
从可用性获取正确颜色的帮助函数
帮助程序类和记录
所有这些代码组合起来完全符合我的要求。