2017-02-24 8 views
4

キープレスイベントなどのイベントレートを計算して表示します。私はまた最初の出来事が起こった後にだけ率計算を開始したいと思う。もう1つの要件は、特定の量のキープレスイベント後にレート計算を停止することです。それに私の現在のアプローチは、そうClojureチャンネルでのイベントレートの計算

(defn keypress-chan 
    "Returns a channel that receives keys" 
    [] 
    (let [out (chan) handler (fn [e] (put! out (.-key e)))] 
    (js/document.addEventListener "keypress" handler false) 
    out)) 

(defn tick 
    "Pushes to `out` 1000 ms later" 
    [out] 
    (go 
    (<! (timeout 1000)) 
    (>! out 1))) 

(defn get-rate 
    "Calculates keypress per minute rate" 
    [ticks pressed] 
    (quot (* pressed 60) ticks)) 

(defn complete? 
    [count] 
    (>= count 100)) 

(defn main-loop [] 
    (let [key-chan (keypress-chan) ticker-chan (chan)] 
    (go-loop [pressed 0 ticks 0] 
     (let [[value ch] (alts! [key-chan ticker-chan])] 
     (if (= ch key-chan) 
      (do 
      ;; Start timer to calculate keypress rate 
      (if (zero? pressed) 
       (tick ticker-chan)) 

      ;; Do something with `value`, i. e. the key being pressed 

      (when-not (complete?) 
       (recur (inc pressed) ticks))) 

      (let [speed (get-rate ticks pressed)] 
      (swap! app-state assoc :rate rate) 
      (tick ticker-chan) 
      (recur pressed (inc ticks)))))))) 

で、これは動作しますが、main-loop内のコードは、私には醜いようです。私は、最初の値がkey-chanに現れて初めてタイマーを起動する "トリガ"を持っていると考えていました。その後、必要に応じて別のトリガーがタイマーを停止します。しかし、私はClojureには新しく、asyncとの連携方法をよく知らないので、上記のコードよりも優れたものを作成できませんでした。

このループをどのように改善できますか? タイマを関数に移動し、key-chanの最初の値でタイマーを開始できますか? 後でそのタイマーを停止できますか?

+0

ソートされたリストに各キー押しのタイムスタンプを格納し、過去60秒間に移動平均レートを計算します。まず、古い値を破棄することは心配しません。現在の時間から60秒以内にすべての値を取り出し、数えれば平均レート/分です。 –

+0

@AlanThompson、アイデアありがとう!試してみる。 – coquin

答えて

0

私は次の解決策を考え出しました。

(ns ratecalc.core 
    (:require [cljs.core.async :refer [chan <! go-loop]]) 
    (:import [goog.date DateTime])) 

(defn calc-rate [input-chan do-fun max-count] 
    (go-loop [count 0 
      start-time nil] 
    (<! input-chan) 
    (let [inc-count (inc count) 
      now (.getTime (DateTime.)) 
      start-time* (if-not start-time now start-time) 
      rate-per-ms (/ inc-count (- now start-time*))] 
     (do-fun rate-per-ms) 
     (if (= count max-count) 
     rate-per-ms 
     (recur inc-count start-time*))))) 

calc-rate機能は、ミリ秒あたりのチャネル上のメッセージの数を算出します。現在の平均値を印刷するなどの副作用を行う関数に渡すことができます。最後の引数は、メッセージの最大数に計算を制限します。

(calc-rate (keypress-chan) println 10) 
関連する問題