Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactive programming - value is greater than X for N seconds

I have a stream randStream which emit random value every half second and boolStream which converts value from randStream into boolean.

let randStream = Kefir.fromPoll(500, () => Math.random())
let boolStream = Kefir.map((rand) => rand > 0.5)

I want to emit true when boolStream emits true for 5 seconds (in a row). Otherwise emit false.

I'm using Kefir.js library.

Do you have any ideas? Thanks.

like image 602
user1518183 Avatar asked May 12 '15 08:05

user1518183


People also ask

What is reactive programming and how does it work?

“Reactive programming is a declarative programming paradigm concerned with data streams and the propagation of change. ” — Wikipedia The basic idea behind this definition is that, with reactive programming, application logic is based on data streams, which are sequences of events over time. Each event can bring data along with it.

What is ReactiveX in Java?

ReactiveX or Raective Extension is the most famous implementation of reactive programming. The working of ReactiveX depends upon the following two classes − This class is the source of data stream or events and it packs the incoming data so that the data can be passed from one thread to another.

What is the next greater for each element in the array?

For an array that is sorted in decreasing order, all elements have the next greater element as -1. For the input array [4, 5, 2, 25], the next greater elements for each element are as follows. d) For the input array [13, 7, 6, 12}, the next greater elements for each element are as follows.

What is the difference between event-driven and reactive programming?

The difference between event-driven and reactive programming is that event-driven programming revolves around events and reactive programming revolves around data. ReactiveX or Raective Extension is the most famous implementation of reactive programming. The working of ReactiveX depends upon the following two classes −


2 Answers

With given conditions when you know exact rate at which randStream emit numbers, it pretty easy to achieve with .slidingWindow:

let result = boolStream
  .slidingWindow(10, 10)
  .map(items => _.every(items))
  .skipDuplicates();

If you want it to work with any rate of events, you can try something like:

let result = boolStream
  .scan(({mostRecentFalse, latestValue}, bool) => {
    return bool ? 
      {mostRecentFalse, latestValue: true} : 
      {mostRecentFalse: Date.now(), lastValue: false}
  }, {mostRecentFalse: Date.now()})
  .changes()
  .map(({mostRecentFalse, latestValue}) => 
    latestValue && (Date.now() - mostRecentFalse > 5000))
  .skipDuplicates();
like image 175
Roman Pominov Avatar answered Oct 04 '22 01:10

Roman Pominov


Sorry I can't write ES6 yet, but... the idea is, if your original stream is sampling once each half-second, five seconds of true is eleven trues in a row, right?

// generate random numbers
var randStream = Kefir.fromPoll(500, function() {
  return Math.random();
});

// make into booleans
var boolStream = randStream.map(function(rand) {
  return rand > 0.5;
});

// count trues in a row
var trueStreakStream = boolStream.scan(function(numTrue, curr) {
  return curr ? numTrue + 1 : 0;
}, 0);

// see when there's exactly 11 of them
var elevenTruesStream = trueStreakStream.filter(function(numTrue) {
  return numTrue == 11;
});

// react
elevenTruesStream.onValue(function(numTrue) {
  console.log("five seconds of true!");
});

EDIT: I just read your question again; if you want a stream that will be true if all of your last 5 seconds were true, then use map instead of filter (and >= rather than ==):

var lastElevenAreTrueStream = trueStreakStream.map(function(numTrue) {
  return numTrue >= 11;
});
like image 38
Amadan Avatar answered Oct 04 '22 03:10

Amadan