I'm trying to create a Rx.Net operator that will have the following behavior:
- When an event is of "normal kind", return that event directly
- When an event is of "special kind", wait that you have received repeated events of that kind during a certain amount of time
I would like to have something like the following marble.
When the message type is A or B, we send it through directly. When the message is C, we want to make sure that it's not just a transitive state and only send it if it was like that for a certain amount of time. This is measured by the time between the first C and the current C that we receive. After that specific amount of time, all C is "accepted" and we pass them through as normal ones.
Here's what it looks when we have received C that was just transitive and we want to ignore it.
I've tried to do something with the Scan operator, playing with returning the previous/current values when I have a specific value, but it feels really hacky.
Here's some code that I wrote for a demonstration of what I tried. In that case, the "special kind" is just when the value is 999, but in the operator, I'd like to do it could be another test or even a function passed to my operator.
var oneObservable = Observable.Interval(TimeSpan.FromSeconds(1)).Select(_ => 999);
var intObservable = Observable.Interval(TimeSpan.FromSeconds(1)).Select(value => (int)value);
var myObservable = intObservable.Take(4).Concat(oneObservable.Take(3)).Timestamp().Repeat();
var test = myObservable.Scan(
(previous: default(Timestamped<int>), current: default(Timestamped<int>)),
(accumulated, current) =>
{
if (current.Value == 999)
{
if (accumulated.previous.Value != 999)
{
return (accumulated.current, current);
}
return (accumulated.previous, current);
}
else if(accumulated.current.Value == 999){
return (accumulated.previous, current);
}
return (accumulated.current, current);
})
.Where(
value => value.current.Value != 999
|| (value.previous.Value == 999 && value.current.Timestamp - value.previous.Timestamp > TimeSpan.FromSeconds(1.5)))
.Select(value => value.current);

