0

I want to create an extension method of the form:

IObservable<bool> CancellableTimer( this IObservable source, TimeSpan delay )
{
...
}

which produces a sequence which is always false when the source is, but will go true when the source sequence has stayed true for a period defined by a delay, t:

source: 0---1---------0--1-0-1-0-1-0-1----------0
            t------>                 t------> 
result: 0----------1--0---------------------1---0

I'm sure there must be a way to do this using Rx primitives but I'm new to Rx and having trouble getting my head round it. Any ideas please?

bighairdave
  • 592
  • 5
  • 19

1 Answers1

0

Okay so this is what I came up with. I also renamed the method to AsymetricDelay() as it seems like a more appropriate name:

    static public IObservable<bool> AsymetricDelay(this IObservable<bool> source, TimeSpan delay, IScheduler scheduler)
    {
        var distinct = source.DistinctUntilChanged();
        return distinct.
            Throttle(delay, scheduler) // Delay both trues and falses
            .Where(x => x)             // But we only want trues to be delayed
            .Merge(                   // Merge the trues with...
                distinct.Where(x=>!x) // non delayed falses
            )
            .DistinctUntilChanged(); // Get rid of any repeated values

    }

And here is a unit test to confirm its operation:

    [Fact]
    public static void Test_AsymetricDelay()
    {
        var scheduler = new TestScheduler();

        var xs = scheduler.CreateHotObservable(
            new Recorded<Notification<bool>>(10000000, Notification.CreateOnNext(true)),
            new Recorded<Notification<bool>>(60000000, Notification.CreateOnNext(false)),
            new Recorded<Notification<bool>>(70000000, Notification.CreateOnNext(true)),
            new Recorded<Notification<bool>>(80000000, Notification.CreateOnNext(false)),
            new Recorded<Notification<bool>>(100000000, Notification.CreateOnCompleted<bool>())
        );

        var dest = xs.DelayOn( TimeSpan.FromSeconds(2), scheduler);

        var testObserver = scheduler.Start(
            () => dest,            
            0,
            0,
            TimeSpan.FromSeconds(10).Ticks);


        testObserver.Messages.AssertEqual(
            new Recorded<Notification<bool>>(30000000, Notification.CreateOnNext(true)),
            new Recorded<Notification<bool>>(60000000, Notification.CreateOnNext(false)),
            new Recorded<Notification<bool>>(100000000, Notification.CreateOnCompleted<bool>())

        );
    }
bighairdave
  • 592
  • 5
  • 19