假设我有一个这样的列表:
List<Timer> bosses = new List<Timer>();
bosses.Add(new Timer { Boss = "Tequatl", Priority = BossPriority.HardCore, SpawnTimes = {
DateTime.ParseExact("07:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("11:30 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("16:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("19:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("00:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("03:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture)
}, Runtime = new TimeSpan(0, 30, 0) });
bosses.Add(new Timer { Boss = "The Shatterer", Priority = BossPriority.Standard, SpawnTimes = {
DateTime.ParseExact("07:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("10:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("13:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("16:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("19:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("22:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("01:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("04:00 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
}, Runtime = new TimeSpan(0, 30, 0) });
bosses.Add(new Timer { Boss = "Jungle Wurm", Priority = BossPriority.LowLevel, SpawnTimes = {
DateTime.ParseExact("07:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("09:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("11:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("13:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("15:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("17:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("19:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("21:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("23:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("01:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("03:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
DateTime.ParseExact("05:15 +0000", "HH:mm zzz", CultureInfo.InvariantCulture),
}, Runtime = new TimeSpan(0,30, 0) });
每个单独的日期时间都是一天中的时间,因此应该每天计算以上日期。
由此我需要找到当前正在运行的DateTimes(与关联的Boss类),每个Timer对象都有一个运行时,它指定运行的时间。例如,我的第一个DateTime从UTC时间7:00开始,到UTC时间7:30结束。
我该怎么做?我希望用LINQ做这个,但我不知道如何订购这些项目,以便日期时间按时间顺序排列。
我想的可能是“扁平化”整个列表,并创建一个新列表,如下所示:
List<BossDatetime> orderedList = new List<BossDatetime>();
foreach (Timer boss in bosses)
{
foreach (DateTime item in boss.SpawnTimes)
{
orderedList.Add(new BossDatetime { Timer = boss, SpawnTime = item });
}
}
orderedList = orderedList.OrderBy(x => x.SpawnTime).ToList();
这似乎是一种不好的做法,也引发了一些新问题,例如列表告诉我关闭Datetime是最后一个:
总结一下我的要求:
bosses
列表关闭我,并引用计时器,所以我知道它是什么老板,最好是通过LINQ 答案 0 :(得分:1)
激战2,对吧? ; P
由于每个老板最多只有一个时间可以在任何时刻激活,所以只需过滤掉当前正在运行的那些老板就足够了。因此,您实际上不需要展平列表以检查每时间。
因此,您需要选择当前有效的所有老板(使用now = DateTime.Now
):
bosses.Where(b => b.SpawnTimes.Where(t => t.TimeOfDay < now.TimeOfDay && now.TimeOfDay < t.TimeOfDay + b.Runtime).Count() > 0)
但是,我个人更喜欢采用不同的方法。由于除了硬核之外的所有老板都出现在一个重复周期中,因此只需记下该周期,然后计算任何给定时间,即周期内的位置。
为此,我将三个boss类型分开,这使得周期变得更加简单(例如,低级别的老板在一个周期中只有4个不同的项目;标准老板在一个周期中有6个不同的项目)。您可以在官方维基上查看我的exemplary implementation,但是用wiki解析器代码编写。这个想法很简单;例如对于标准老板来说,这就是获得当前老板的必要条件:
string[] standardBosses = new string[] { "Taidha Covington", "Megadestroyer", "The Shatterer", "Modniir Ulgoth", "Golem Mark II", "Claw of Jormag" };
Console.WriteLine(standardBosses[((int)DateTime.UtcNow.TimeOfDay.TotalMinutes / 30) % 6]);
答案 1 :(得分:0)
这应该让你当前正在运行老板。由于它返回了老板,因此您获得了所需的所有数据。我不确定我是否理解第1点。
bosses.Where(x => x.SpawnTimes != null &&
x.SpawnTimes.Count > 0 &&
x.SpawnTimes.Any(y => y.TimeOfDay <= DateTime.UtcNow.TimeOfDay &&
y.TimeOfDay >= DateTime.UtcNow.TimeOfDay.Subtract(x.Runtime))).ToList();
请注意,您当前的代码会将这些日期时间移动2小时+。
答案 2 :(得分:0)
我不确定它是否与您相关,但这些实现似乎都没有正确处理周期性 - 即前一天晚上开始的事件可能仍然在早上很早就开始运行。
这应该可以解决问题:
/// <summary>
/// Check if a time falls inside a repeating daily event of a given duration.
/// </summary>
/// <param name="spawnTime">Start time of an event</param>
/// <param name="runTime">Duration of the event</param>
/// <param name="now">Time to test</param>
/// <returns>true if the test time is inside the duration of the specified event.</returns>
public static bool IsDailyEventActive(DateTime spawnTime, TimeSpan runTime, DateTime now)
{
// Are we inside an event that started today?
DateTime spawnTimeToday = now.Date + spawnTime.TimeOfDay;
if (now >= spawnTimeToday && now <= spawnTimeToday + runTime)
return true;
// Are we still inside an event that started yesterday?
DateTime spawnTimeYesterday = now.Date.AddDays(-1) + spawnTime.TimeOfDay;
if (now >= spawnTimeYesterday && now <= spawnTimeYesterday + runTime)
return true;
return false;
}