我正在制作一个有多个(重新发生)闹钟的闹钟。
我使用安装了Microsoft IoT的raspberry pi和UWP(C#)作为布局和底层算法。
我遇到的问题是检索下一个闹钟时间。
伪代码:
Select nextAlarm()
For all alarms a
if (((a.time >= now.time AND a.repeatDay == now.DayOfWeek)
OR a.repeatDay > now.DayOfWeek) AND a.dateTime < currentAlarm.dateTime)
currentAlarm = a;
然而,对于每个警报和函数a.repeatDay&gt;这将花费O(n)时间。 now.DayOfWeek不是一个简单的函数(如果当前日是星期三,下一个警报是星期一,则该函数不起作用)。
我要问的是如何以上述功能的工作方式(最好比O(n)更快)存储警报,或者如何存储所述问题解决的重复日期。
目前正在使用SQLite.net-pcl包
Alarm和RepeatDay类:
public class Alarm
{
[PrimaryKey, AutoIncrement]
public long Id { get; set; }
[NotNull]
public string Name { get; set; }
[NotNull]
public DateTime Time { get; set; }
[NotNull]
public int Repeat { get; set; }
public Alarm(string name, DateTime time, RepeatWeek repeat)
{
this.Name = name;
this.Time = time;
this.Repeat = repeat;
}
}
public class RepeatWeek
{
int repeat = 0;
public static implicit operator int(RepeatWeek w)
{
return w.repeat;
}
public void setDay(DayOfWeek w)
{
repeat |= 1 << (int)w;
}
public void removeDay(DayOfWeek w)
{
repeat &= ~(1 << (int)w);
}
public DayOfWeek getNext(DayOfWeek d, bool inclToday = false)
{
throw new NotImplementedException();
return DayOfWeek.Monday; //Needs work
}
}
答案 0 :(得分:1)
我已经尝试过实施GetNextDay。然后,实现Alarm.GetNext变得很简单,更简单的LINQ查询可以满足您的要求。我留下了一些让你实施,所以你可以说你做到了。
public class Alarm
{
public long Id { get; set; }
public string Name { get; set; }
public DateTime Time { get; set; }
public int Repeat { get; set; }
public Alarm(string name, DateTime time, RepeatWeek repeat)
{
this.Name = name;
this.Time = time;
this.Repeat = repeat;
}
public DateTime GetNext()
{
var includeToday = true;
if (DateTime.Now.TimeOfDay > Time.TimeOfDay)
{
includeToday = false;
}
var repeat = new RepeatWeek(Repeat);
var nextDayOfWeek = repeat.GetNextDay(includeToday);
return MergeDayOfWeekAndTime(nextDayOfWeek, Time);
}
private DateTime MergeDayOfWeekAndTime(DayOfWeek? nextDayOfWeek, DateTime Time)
{
//Left as exercise to the reader.
throw new NotImplementedException();
}
}
public class RepeatWeek
{
int Repeat;
public RepeatWeek(int repeat = 0)
{
Repeat = repeat;
}
public static implicit operator int(RepeatWeek w)
{
return w.Repeat;
}
public void setDay(DayOfWeek w)
{
Repeat |= 1 << (int)w;
}
public void removeDay(DayOfWeek w)
{
Repeat &= ~(1 << (int)w);
}
public static DayOfWeek FollowingDayOfWeek(DayOfWeek day)
{
if (day == DayOfWeek.Saturday)
{
return DayOfWeek.Sunday;
}
else
{
return day + 1;
}
}
public DayOfWeek? GetNextDay(bool inclToday = false)
{
var inspect = DateTime.Now.DayOfWeek;
if (!inclToday)
{
inspect = FollowingDayOfWeek(inspect);
}
for (int i = 0; i < 7; i++)
{
if ((Repeat & (1 << (int)inspect)) > 0) return inspect;
inspect = FollowingDayOfWeek(inspect);
}
return null;
}
}
[TestClass]
public class MyTestClass
{
[TestMethod]
public void GetNextDayOfWeek()
{
var repeat = new RepeatWeek();
repeat.setDay(DayOfWeek.Monday);
repeat.setDay(DayOfWeek.Tuesday);
var expected = DayOfWeek.Monday;
if (DateTime.Now.DayOfWeek == DayOfWeek.Monday)
{
expected = DayOfWeek.Tuesday;
}
var actual = repeat.GetNextDay();
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void GetNextAlarm()
{
//Populate this yourself.
var alarms = new List<Alarm>();
var nextAlarm = alarms.Select(a => a.GetNext()).OrderBy(a => a.Ticks).FirstOrDefault();
}
}