余興を支えているかもしれない技術集

普段はインフラとかを担当しています。


# 余興とは

私の場合に限ってですが、何かしらのクイズ番組を再現すること（司会の立ち振る舞い含む）にあります。

# 過去に作ったもの

- クイズがダービーするやつ
- ミリオンがネアするやつ
- オールスターが感謝するやつ

このうち、ダービーするやつとネアするやつについては、過去にYAPC::Asia 2014の前夜祭で披露させていただきました。
http://debility.hateblo.jp/entry/2014/09/01/233954
で、感想でいただいた声の中でいくつか「技術的要素の話がない」といった声をいただいておりましたが、改めてどんな技術を使っていたのかを軽くおさらい。

# の前に、前提として

基本的には、時間がない中での開発になります（業務ではないですし）。
よっぽど時間をかけても3-4人日くらいで開発を終わらせる前提です。
また、出来る限り普段仕事で使っている技術の延長でがんばっています。

# 基本: JavaScript芸あれこれ

画面をあれこれ動かすので、JavaScript必須です。  

## よくある点滅

![correct.gif](https://qiita-image-store.s3.amazonaws.com/0/54590/d70edfe5-dc0c-403d-bc6a-94df1d082fde.gif)
よくある演出ですね。
jquery.toggle()とsetTimeoutを使ってさっくりと。

```
function toggle_correct_answer(c, count) {
    if (count % 2 == 0) {
      // 青 -> 赤 
      $("#answer_" + c).css('background-color', '#ff1763');
      $("#answer_count_" + c).css('background-color', '#ff1763');
    } else {
      // 赤 -> 青 
      $("#answer_" + c).css('background-color', '#0000ff');
      $("#answer_count_" + c).css('background-color', '#0000ff');
    }
    count++;
    if (count < 11) {
        setTimeout('toggle_correct_answer(' + c + ',' + count + ')', 200);
    }
}

toggle_correct_answer(correct_answer, 0);
```

timeoutの値(上記例だと200msec)と点滅回数を調整して、っぽく仕上げる感じです。
上記は背景色を明滅させていますが、画像のオンオフで表現することもあります。
この辺はお好み、というか完成度をどこまで求めるか次第です。
同様にhide()とshow()もふんだんに使用します。

## っぽいエフェクトをもう少しかけたい

![rank.gif](https://qiita-image-store.s3.amazonaws.com/0/54590/66e4e690-f3d4-9961-3eaf-787c713847fe.gif)
例えば↑の場合は、Animate.cssを使ったりしています。
https://daneden.github.io/animate.css/

```
var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
(中略)
$("#rank_" + n).addClass('animated flipInX').one(animationEnd, function() {
    $(this).removeClass('animated  flipInX');
}); 
```

この辺は必要に応じてそれっぽいものを探して、いろいろ試してみる感じですね。

## keyevent

司会兼操作役だったりするので、マウス操作をしたりコマンドを入力したりする暇は基本的にありません。
このため、大抵の操作はkeyeventで割り当てます。

```
$(document).keydown(function(ev) {

    // 1: OP
    if ((ev.which && ev.which === 49) || (ev.keyCode && ev.keyCode === 49)) {
        audio_clear();
        audio_opening.play();
    }

    // 2: ピリオド開始
    if ((ev.which && ev.which === 50) || (ev.keyCode && ev.keyCode === 50)) {
        hide_all();
        audio_clear();
        audio_standup.play();
    }

    // 3: 問題開始(デデン)  
    if ((ev.which && ev.which === 51) || (ev.keycode && ev.keycode === 51)) {

(以下略)
```

上記はChromeで実装した例ですが、まあ他のブラウザでも大差はないかと。

## 表示は拡張ディスプレイ側にして、操作系の画面は手元に残したい

表示画面側から別ウィンドウを開いておき、別ウィンドウ側に処理系を書く方法です。
処理系側でwindow.openerを使い、表示側の要素をいろいろ変化させます。
[cheet.js](http://lou.wtf/cheet.js/)を使ってコナミコマンド発火にしているのは、趣味の問題ですね。

表示側

```
$(function(){
    function controllopen(){
        window.open("/path/to/controller", "child", "width=700,height=600");
    }
    cheet('↑ ↑ ↓ ↓ ← → ← → b a', function () {
        controllopen();
    }
});
```

操作側

```
window.opener.$('.animatedBorderSprite').hide();
```

とかしておけば、操作系を完全に切り離せるので便利かもしれません。

# 応用: 音の話とかExcelの話とかインフラとか

audioタグを使って再生、で基本的にはOKです。

## audio.loop()だといい感じにループしてくれないので、複数回ループした音をあらかじめ長めに作る

ネアしたやつなんかは基本的に同じ曲のループなんですが、audio.loop()を使うとどうしても音が途切れてしまうので、元の音を編集して、充分な回数(5回とか)ループした音をあらかじめ作っています。
要は力技なんですが、音が途切れるとどうしても興冷めするので。

## 音に動きを合わせる

音源は毎回限られている(かつ自作するスキルはない)ので、違和感を少しでも減らそうと思うと、音に動きを合わせる必要が出てきます。
表示時間だったり、点滅回数だったり。
一例として

- おおよその動きを作る
- 音源の長さを測ったら11.37秒だった
- 1位を出す前に少しウェイトかける必要あるな
- じゃあ2位まで出すのに何秒くらいで、ウェイトがどのくらいで1位を出すか云々
- と考えて値を変えて、細かく調整(setTimeoutの秒数とかで)

みたいなことをやって、なるべく本物との違和感を減らしていきます。

![rank_up.gif](https://qiita-image-store.s3.amazonaws.com/0/54590/6e4a6c88-1519-4eba-c6bd-e262f503f66c.gif)

この辺の調整はだいたい誰も気付かない(or気にしていない)ところなので、趣味の領域かもしれないです。ちくしょう。
音源とか、素材が豊富だといろいろ解法も増えるのかなーとは思います。

## Excelで初期データ投入

お仕事でのデータ移行なんかでちょいちょい使う技なんですが。
![users_init.png](https://qiita-image-store.s3.amazonaws.com/0/54590/d59a7fa3-e866-4b2c-cdea-baaa358103bc.png)

```
=C4 & "'"& B4 &"', true, NOW(), NOW());"
```

みたいな感じで、&で文字列連結させてSQLを作って、がーっと投入。
会場で急遽「参加者が増えるけど対応できる？」「問題文変えなきゃ、順序も変えなきゃ」なんて言われても、これ用意しておけば「40秒いただければ」と回答できるので、ドーラおばさんも安心です。

## インフラ側の話

は割となくて、大量にリクエスト捌く必要がある部分だけnode.js使うとか、余裕があればansibleとか用意しておくと環境構築がいくらか楽だよね、といったくらいです。

# まとめ

- 技術的にキワいことをしているわけではないです
- なるべく似せるために、キワいところに凝ったりはしています
- 暇ではないです
- ハードルが思ったほど上がらなかったので、次の人(新卒)に頑張ってもらいます