从一组闹钟中获取第一个闹钟时间

Getting the first alarm time from set of alarms

我目前正在研究具有多个(重复发生的)闹钟的闹钟。

我正在使用 raspberry pi 安装了 Microsoft IoT 和 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;

然而,这将花费 O(n) 的时间来处理每个警报,并且函数 a.repeatDay > now.DayOfWeek 不是一个简单的函数(如果当天是星期三并且下一个警报打开星期一,该功能不起作用)。

我要问的是如何以上述功能起作用的方式存储警报(并且最好比 O(n) 更快)或者我如何存储所述问题已解决的重复天数。

目前正在使用 SQLite.net-pcl 套餐

闹钟和 RepeatDay class:

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
    }
}    

我已经尝试实现 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();
    }
}