System.Reactive puzzle


After working on the Reactive Framework with Erik, Wes and the rest of our team for over a year, it is great to see  that the word about System.Reactive is out (as described here, here, here and here).


I thought it might be fun to post a little puzzle challenge showing the power of the Reactive Framework. I asked the same question to my team members a while back and everyone got a different solution, from very declarative to very imperative.


here is the puzzle:

A while back, if found a jQuery implementation of tripple click of course this can be done very elegantly in Rx.


The first question is: can you implement this using Rx (for the Silverlight Button)? 
the second question is: can you generalize it like this:


public static IObservable<RoutedEventArgs> GetMultiClickScan(this ButtonBase button, int count, int multiClickSpeedInMilliSeconds)


The third and final question is: Can you implement this without timers?


To give you a head start, here is the code to get an IObservable<RoutedEventArgs>that fires for each click:



var click = Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>
    (i => i.Invoke, i => button.Click += i , i => button.Click -= i).Select(e => e.EventArgs);


Rules:
-feel free to ask questions in the comments if you’re stuck, can’t promise I’ll be able to answer you immediately or give everything away though 🙂
-feel free to post answers in the comments, if you don’t want to be spoiled, don’t read the comments 🙂
-No prizes, only eternal satisfaction with an awesome implementation can be won here 🙂


I’ll post some of our teams answers to this puzzle in a couple of days..


 


 

Comments (3)

  1. Steffen Zeidler says:

    amazing Rx, hier are my first solutions

    1. solution with Scan

    return click

       .Scan(new { e = new RoutedEventArgs(), t = DateTime.Now, c = 0 }, (a, e) => new

       {

           e,

           t = DateTime.Now,

           c = ((DateTime.Now – a.t).TotalMilliseconds < multiClickSpeedInMilliSeconds) ? (a.c + 1) : 1 })

       .Skip(1)

       .Where(a => a.c % count == 0)

       .Select(a => a.e);

    2. solution without Scan

    return click

       .Skip(count)

       .Zip(click.Select(_ => DateTime.Now), (e, t) => new { e, t = DateTime.Now – t })

       .Where(e => e.t.TotalMilliseconds < multiClickSpeedInMilliSeconds)

       .Select(e => e.e)

  2. jhusain says:

    Jeffrey:  Spoke too soon.  🙂 Your solutions work – and very well too. Very nice!  Wish I’d thought of them :-).