Edited at

初めてのRxJSをズンドコキヨシで

More than 3 years have passed since last update.

※RxJSのドキュメント読んで理解する度に更新してくかも

便乗した。

https://twitter.com/kumiromilk/status/707437861881180160

http://qiita.com/shunsugai@github/items/971a15461de29563bf90

RxJSのドキュメントをみてやっつけでやった。RxJS触るの初めてなので多分よくわかってない。

パターンわかってるからbufferWithCount使えば簡単なのだけど、それよりも途中でSubscribeやめる方法がよくわからんかったのでcompletedみたいな変数を作ってしまい負けた気分。念のため無限ループにはしてない。(一回ミスってjsfiddle固まった)

var zundoko = ["ズン", "ドコ"];

var completed = false;
var zundokoSource = Rx.Observable.generate(
0,
function(i) { return i < 10000 && !completed; },
function(i) { return i + 1;},
function() { return zundoko[Math.floor(Math.random() * 2 )]}
);

zundokoSource.bufferWithCount(5, 1).subscribe(
function(kotodama) {
if(kotodama.join(",") === "ズン,ズン,ズン,ズン,ドコ") {
console.log("キ・ヨ・シ!!");
completed = true;
}
}
);


リズム版

ズンズンズンズンドコにはリズムがある。ただ単純にズンドコが並べば良いわけではなく、一つ目のズンと二つ目のズンの間は少し長めに、それ以降のズンとドコの間は短めの間がある。

その"間"自体もstreamのデータとして扱い、

ズン 1500ms ズン 750ms ズン 750ms ズン 750ms ドコ

となったときだけ「キ・ヨ・シ」するようにした。1500とか750は別に曲から正確に測ったわけではなく、だいたいである。

実際1500msなり750ms待つこともあり、なかなか「キ・ヨ・シ」を発動できない。


generateWithRelativeTimeを使ったversion

var zundoko = ["ズン", "ドコ"];

var intervals = [1500,750];
var dom = document.getElementById('zundoko');
var completed = false;
var zundokoSource = Rx.Observable.generateWithRelativeTime(
0,
function() { return !completed; },
function() {},
function() {
var token = zundoko[Math.floor(Math.random() * 2 )];
var p = document.createElement("p");
p.innerHTML = token;
dom.appendChild(p);
return token;
},
function() {
return intervals[Math.floor(Math.random() * 2)];
}
).timeInterval();

var subscription = zundokoSource.bufferWithCount(5, 1).subscribe(
function(buffer) {
var zundoko = [];
var intervals = [];
buffer.forEach(function(word) {
zundoko.push(word.value);
// intervalは関数で指定しか時間ぴったりではなく
// 数msecずれるので丸め込む
intervals.push(Math.floor(word.interval / 10));
})
console.log(zundoko);
console.log(intervals.slice(1));
if(zundoko.join(",") === "ズン,ズン,ズン,ズン,ドコ" &&
intervals.slice(1).join(",") === "150,75,75,75") {
completed = true;
}
},
function(error) {
console.log("error");
},
function() {
var p = document.createElement("p");
p.innerHTML = "<strong>キ・ヨ・シ!!</srtong>";
dom.appendChild(p);
}
);


create使ったversion

var zundoko = ["ズン", "ドコ"];

var intervals = [1500,750];
var zundokoSource = Rx.Observable.create(function(observer) {
var completed = false;
function sing(interval) {
var span = interval / 750;
var zd = zundoko[Math.floor(Math.random() * 2)];
var nextInterval = intervals[Math.floor(Math.random() * 2)];
console.log(Array(span + 1).join("."));
console.log(zd);
observer.onNext(interval);
observer.onNext(zd);
if(!completed) {
setTimeout(function(){ sing(nextInterval); }, nextInterval);
}
}
sing(0);
return function() {
completed = true;
};
});

var subscription = zundokoSource.bufferWithCount(9, 1).subscribe(
function(kotodama) {
if(kotodama.join(",") === "ズン,1500,ズン,750,ズン,750,ズン,750,ドコ") {
console.log("キ・ヨ・シ!!");
subscription.dispose();
}
}
);