反应 - 香蕉节流事件 [英] reactive-banana throttling events

查看:117
本文介绍了反应 - 香蕉节流事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在反应式香蕉中实施某种类型的事件限制。它应该起作用,以使得如果从最后一次通过的事件到达的时间少于三秒,事件就不会通过。如果它没有通过,那么它将被存储并在最后一次触发事件的增量秒后触发。

下面是一个程序,用于实现这个时间戳数字列表。这是否有可能将其转化为反应性香蕉?



另外,在反应性香蕉中,在其他事件进入后x秒钟内如何发生事件? p>

 
模块Main其中

导入Data.List

- 1秒throtling
- 逻辑在输出最后一个值之后的1秒之前从不输出一个值。

main :: IO()
main = print $ test [(0.0,1.0),(1.1,2.0),(1.5,3.0),(1.7,4.0),(2.2) ,5.0)]
- 应该输出[(0.0,1.0),(1.1,2.0),(2.1,4.0),(3.1,5.0)]

test :: [( Double,Double)] - > [(Double,Double)]
test list = gv(concat xs)
其中
(v,xs)= mapAccumL f(-50,Nothing)list
g(t,Just x)ys = ys ++ [(t + 1,x)]
g _ ys = ys
f(lasttime,Just holdvalue)(t,x)= if t >(lasttime + 1)then
if t>(lasttime + 2)then
((t,Nothing),[(lasttime + 1,holdvalue),(t,x)])
else((lasttime + 1,Just x),[(lasttime + 1,holdvalue)])
else
((lasttime,Just x),[])
f(lasttime,Nothing )(t,x)= if t>(lasttime + 1)then
((t,Nothing) ,[(t,x)])
else((lasttime,Just x),[])


解决方案

好的,我设法实现了我在我的问题中描述的内容。我不是很高兴IO需要通过反应来控制计时器。我不知道是否可以用节气门标记油门:: Event ta - > Int - > Event ta ...

ps:我很新手在Haskell中,所以代码可能会更紧凑或优雅。

  {----------- -------------------------------------------------- ---------------- 

-------------------------- -------------------------------------------------- - }
{ - #LANGUAGE ScopedTypeVariables# - } - 允许forall t。NetworkDescription t

import Graphics.UI.WX隐藏(事件)
导入无效。 Banana
import Reactive.Banana.WX
import Data.Time

{---------------------- -------------------------------------------------- -----

------------------------------------ ------------------------------------------}

数据ThrottledValue a = FireStoredValue a | FireNowAndStartTimer a | HoldIt a |停止导出显示
数据ThrottledEvent a = TimerEvent | RealEvent派生Show

main = start $ do
f< - frame [text:=Countercesss]
sl1< - hslider f False 0 100 []
sl2 < - hslider f False 0 100 []
set f [layout:= column 0 [widget sl1,widget sl2]]
t < - timer f []
set t [enabled:= False]
让networkDescription :: forall t。 NetworkDescription t()
networkDescription = do
slEv< - event0 sl1命令
tick< - event0 t命令
slB< - 行为sl1选择
let throttledEv,reactimates)= throttle(slB <@slEv)tick t 100
reactimates
reactimates $ fmap(\ x - > set sl2 [selection:= x])throttledEv
net < - 编译网络描述
启动网络

throttle :: Event ta - >事件t() - >定时器 - > Int - > (事件ta,NetworkDescription t())
throttle ev tick timer dt =(throttledEv,reactimates)
其中
all = union(fmap(\ x-> RealEvent x)ev) (fmap(\ x - > TimerEvent)tick)
result = accumE已停止$ fmap h全部
其中
h(RealEvent x)Stopped = FireNowAndStartTimer x
h TimerEvent Stopped = Stopped
h(RealEvent x)(FireEowAndStartTimer _)= HoldIt x
h TimerEvent(FireNowAndStartTimer _)=已停止
h(RealEvent x)(HoldIt _)= HoldIt x
h(TimerEvent) y)= FireStoredValue y
h(RealEvent x)(FireStoredValue _)= HoldIt x
h(TimerEvent)(FireStoredValue _)= Stopped
start(FireStoredValue a)= Just $ resetTimer timer dt
start(FireNowAndStartTimer a)= Just $ resetTimer timer dt
start _ = Nothing
stop Stopped = Just $ stopTimer timer
stop _ = Nothing
reactimates = do
reactimate $ filterJust $ fmap停止结果
reactimate $ filterJust $ fmap开始结果
filterFired(FireStoredValue a)=只需
filterFired(FireNowAndStartTimer a)=只需
filterFired _ = Nothing
throttledEv = filterJust $ fmap filterFired result
$ b startTimer t dt = set t [enabled:= True,interval:= dt]
stopTimer t = set t [enabled := False]
resetTimer t dt = stopTimer t>> startTimer t dt


I would like to implement a certain type of throttling of events in reactive-banana. It should work such that an event is not let through if arrives at less then delta seconds from the last event that passed through. If it is not let through then it is stored and is fired after delta seconds from the last fired event.

Below is a program that implements this for lists of time stamped numbers. Would it be possible to translate this to reactive-banana ?

Also, in reactive-banana how do I fire an event x seconds after some other event comes in ?

module Main where

import Data.List

-- 1 second throtling
-- logic is to never output a value before 1 second has passed since last value was outputed.

main :: IO()
main = print $ test [ (0.0, 1.0), (1.1, 2.0), (1.5,3.0), (1.7,4.0),  (2.2, 5.0)  ]
--should output  [ (0.0, 1.0), (1.1, 2.0), (2.1,4.0), (3.1, 5.0) ]

test :: [(Double,Double)] -> [(Double,Double)]
test list = g v (concat xs)
       where
               (v, xs) = mapAccumL f (-50,Nothing) list
               g (t, Just x) ys = ys ++ [ (t+1,x) ]
               g _ ys  = ys
               f (lasttime, Just holdvalue) (t,x) = if t > (lasttime+1) then
                               if t > (lasttime + 2) then
                                       ( (t, Nothing), [ (lasttime+1,holdvalue), (t,x)] )
                               else ( (lasttime+1, Just x) , [ (lasttime+1,holdvalue) ] )
                       else        
                               ( (lasttime, Just x), [] )
               f (lasttime, Nothing) (t,x) = if t > (lasttime+1) then
                        ( (t,Nothing) , [ (t, x ) ] ) 
                        else ( (lasttime, Just x), [] )

解决方案

Ok, I managed to implement what I described in my question. I'm not so happy that IO is needed to control the timer via reactimate. I wonder if it would be possible to have a throttle with signature throttle::Event t a -> Int -> Event t a ...

ps: I'm very novice in Haskell so the code could probably a lot more compact or elegant.

{-----------------------------------------------------------------------------

------------------------------------------------------------------------------}
{-# LANGUAGE ScopedTypeVariables #-} -- allows "forall t. NetworkDescription t"

import Graphics.UI.WX hiding (Event)
import Reactive.Banana
import Reactive.Banana.WX
import Data.Time

{-----------------------------------------------------------------------------
    Main
------------------------------------------------------------------------------}

data ThrottledValue a = FireStoredValue a | FireNowAndStartTimer a| HoldIt a | Stopped deriving Show
data ThrottledEvent a = TimerEvent | RealEvent a deriving Show

main = start $ do
    f   <- frame [text := "Countercesss"]
    sl1  <- hslider f False 0 100 []
    sl2  <- hslider f False 0 100 []
    set f [ layout := column 0 [widget sl1, widget sl2] ]
    t <- timer f []
    set t [ enabled := False ] 
    let networkDescription :: forall t. NetworkDescription t ()
        networkDescription = do
        slEv <- event0 sl1 command
        tick <- event0 t command 
        slB <- behavior sl1 selection
        let (throttledEv, reactimates) = throttle (slB <@ slEv) tick t 100
        reactimates
        reactimate $ fmap (\x ->  set sl2 [selection := x]) throttledEv       
    net <- compile networkDescription
    actuate net            

throttle::Event t a -> Event t () -> Timer -> Int -> (Event t a, NetworkDescription t () )    
throttle ev tick timer dt = (throttledEv, reactimates)
        where   
                all = union (fmap (\x-> RealEvent x) ev) (fmap (\x -> TimerEvent) tick)
                result = accumE Stopped $ fmap h all
                        where
                        h (RealEvent x) Stopped = FireNowAndStartTimer x
                        h TimerEvent Stopped = Stopped
                        h (RealEvent x) (FireNowAndStartTimer _) = HoldIt x
                        h TimerEvent (FireNowAndStartTimer _) = Stopped
                        h (RealEvent x) (HoldIt _) = HoldIt x
                        h (TimerEvent) (HoldIt y) = FireStoredValue y
                        h (RealEvent x) (FireStoredValue _) = HoldIt x
                        h (TimerEvent) (FireStoredValue _) = Stopped          
                start (FireStoredValue a) = Just $ resetTimer timer dt
                start (FireNowAndStartTimer a) = Just $ resetTimer timer dt
                start _ = Nothing  
                stop Stopped = Just $ stopTimer timer
                stop _ = Nothing  
                reactimates = do
                        reactimate $ filterJust $ fmap stop result   
                        reactimate $ filterJust $ fmap start result
                filterFired (FireStoredValue a) = Just a
                filterFired (FireNowAndStartTimer a) = Just a
                filterFired _ = Nothing
                throttledEv = filterJust $ fmap filterFired result                 

startTimer t dt = set t [ enabled := True, interval := dt ]
stopTimer t = set t [ enabled := False ]
resetTimer t dt = stopTimer t >> startTimer t dt

这篇关于反应 - 香蕉节流事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆