OmniAICreator/Qiita-1.07M huggingface dataset:
riot.js codemirror tagを作る。

### \<cm\>\</cm\>でいくつでも複製可能、web componentが期待されている点はこの辺。
```html
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.36.0/codemirror.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.36.0/codemirror.js"></script>
<script src="//gnjo.github.io/riot.js"></script>
<cm></cm>
<cm></cm>
<cm></cm>
<cm></cm>
<cm></cm>
<cm></cm>
```
```js
riot.tag(`cm`
 ,`<form><textarea ref="code"></textarea></form>
<style>.CodeMirror {
  border: 1px solid #eee;
  height: auto;
} cm+cm>form{margin-top:1rem}</style>
`         
,function(opt){
  let cm=null,C=CodeMirror;
  this.on('mount',function(){
   console.log('in')
   cm = C.fromTextArea(this.refs.code,{lineNumbers: true,viewportMargin: Infinity});
  })
})
;
riot.mount('cm',{})
```

### 注意
riot.tag(tag,html,css,constructor)
riot.tagの第三引数にはcssを入れることが出来るが、headの末尾に挿入されてしまう。component化しているのだからscopedで入れて欲しい所だが、仕様のようなのでhtmlの中に\<style\>\</style\>を入れる。

```js
riot.tag(...,...<style>
.CodeMirror {
 border: 1px solid #eee;
 height: auto;
}
</style>,...)
```
TensorFlow.jsを使って手書き数字解析器を作る上で躓いたこととか

この記事は[ここ](https://cretgp.com/blog/20180409%20TensorFlow.js%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E6%89%8B%E6%9B%B8%E3%81%8D%E6%95%B0%E5%AD%97%E8%A7%A3%E6%9E%90%E5%99%A8%E3%82%92%E4%BD%9C%E3%82%8B%E4%B8%8A%E3%81%A7%E8%BA%93%E3%81%84%E3%81%9F%E3%81%93%E3%81%A8%E3%81%A8%E3%81%8B.html.php)のコピーです。

今日はTensorFlow.jsという比較的新しくできた[^1] TensorFlowという機械学習に使えるライブラリのJavascript版を使ってみようということで機械学習分野のHelloWorldらしいMNISTを使っての手書き数字解析器を作りたいと思いました。


Github: https://github.com/CreativeGP/tensorflowjs-mnist/
Avaliable at: https://cretgp.com/lab/mnist/


制作の上では[こちらの記事](https://qiita.com/kaneU/items/ca84c4bfcb47ac53af99)を参考にさせていただきました。この記事はモデル作成からTensorFlow.jsを使ってWebアプリを作るところまでを幅広くカバーしているので同じような内容の記事が２つあってもデータの無駄、ということでこの記事はTensorFlow.jsを使う際に躓いたことに焦点を当てて書いています（先程の記事では大まかな手順だけ書かれていたところですね。


[^1]: 一応TensorFlowのリポジトリは2017年8月くらいに[初期コミットがされてます](https://github.com/tensorflow/tfjs-core/tree/9d1d224caf9f936e0ace0ee5854caefb660800f2)が、この親であるdeeplearn.jsはもっと前から開発がされているようです。


※なんかここから常体になってますが気にしないで下さい※


# ImageDataの縮小
ユーザーから入力された200x200のCanvasの画像を推論にかけるには28x28に縮小しなければならない。CanvasからはImageDataというオブジェクトが取得してこれが各ピクセルの色データを保持している。


このやり方も情報が少なく、[このページ](https://stackoverflow.com/questions/3448347/how-to-scale-an-imagedata-in-html-canvas)が唯一僕が見つけられるページだった。
ここのコメントにもあるようにこの回答は少し冗長なやり方をしているので改善したものをjsFiddleにうｐしたので参考にしていただきたい。


https://jsfiddle.net/Hm2xq/673/


# 入力用Tensorを作成
ImageDataはプロパティが全て読み取り専用だということで、つまりコンストラクタから生成しなければならないのだが、コンストラクタに指定できる配列のサイズが決まっていることと、型も決まっていることで扱いにくい。このような特性のせいで正規化をする際に小数の格納ができない。


なので最初にtf.fromPixels()を使ってTensorを生成しなければならないのだがここでハマった。


tf.fromPixels()はImageDataと1~4のチャンネル数をとる。チャンネル数が4の場合は


```TypeScript
[255, 200, 0, 100, 50, 3, 80, 72, 40]:ImageData.data -> [[255, 200, 0, 100], [3, 80, 72, 40]]:Tensor
```


という風に色データが単純に４個ずつに区切られて入力される。この場合はモノクロなのでチャンネル数を１にするのだがこのときは、


```TypeScript
[255, 200, 0, 100, 50, 3, 80, 72, 40]:ImageData.data -> [[255], [3]]:Tensor
```


という風に４個ずつに分解されたときの一番最初の要素だけを使ってTensorが構成される。しかし、Canvasから取得した色データはユーザーの入力が$4i + 3$番目に入っており、普通に渡したのでは期待する動作をしてくれないので、変換を行う必要があった[^2]。行った変換は単純で


```javascript
let monodata = [];
for (let i=0, len = imgdata.data.length/4; i < len; i += 1) {
    monodata.push(imgdata.data[i*4+3]);
    monodata.push(0);
    monodata.push(0);
    monodata.push(0);
}
let monoimgdata = new ImageData(new Uint8ClampedArray(monodata), 28, 28);
```

新たな配列を作ってそこにユーザーの入力データが$4i$番目に来るようにして後は0パディングするようにし、その後で新たなImageDataるようなものである。パディングはImageDataのコンストラクタに渡す配列の大きさは$width×height×4$のサイズしか許されなかった為必須である。


ようやくできたmonoimgdataをtf.fromPixelsに渡して、整形して、型を変換して[^3]、正規化すれば[^4]、入力用テンソルが完成する。


```javascript
let input = tf.fromPixels(monoimgdata, 1).reshape([1, 28, 28, 1]).cast('float32').div(tf.scalar(255));
```

[^2]: この変換はCanvasの塗る色の設定を変えることで不要になるかもしれない。


[^3]: 理由は、この学習データを使った推論の入力Tensorはfloat32ではないといけないと怒られるということと、255で割ると小数が出てくるからということがある。


[^4]: データは0~255の範囲にあるので255で割る。


# まとめ
作ってみた感想としては、なかなかいい制度ができにくいな、ってのが正直な感想です。僕が制作したのはWebのインターフェースのみなので改善のしようはアルゴリズムレベルでしかないとは思いますが特に「１」がひどいです。[ぜひ試してみて下さい](https://cretgp.com/lab/mnist/)！
２つの超高速開発ツールのServiceNowとOutSystemsを比べてみる

# 概要
ServiceNowとOutSystemsはともに、クラウド上で超高速にアプリケーションを開発するツールとして使用が可能。
ただし、ServiceNowはインシデント管理、資産管理、ワークフロー管理などのアプリケーションが用意されており、ITILを提供するプラットフォームの性格が強い。OutSystemsは、アプリケーション開発からデプロイまでをアジャイル開発手法を使って統合することを狙っている。
そのため、使用目的がそもそも異なるため、この２つのツールがプラッットフォームの選定対象として同じ土俵にあがる事は少ないと考えられる。にも関わらず共通点も多いことから本稿では比較してみる。

|比較項目 |ServiceNow | OutSystems|
|---|---|---|
|比較対象バージョン|KINGSTONE|10.0|
|クラウド上のサーバー提供|○|○|
|他社クラウド上でのサーバー動作|×|○|
|オンプレミス上でのサーバー動作|×|○|
|ブラウザーでのクライアント開発|○|△（＊１）|
|Windowsアプリでのクライアント開発|×|○|
|開発言語|JavaScript|独自のフローチャート（＊２）|
|UIによるデータ操作|○|○|
|SQLによるデータ操作|×|○|
|外部ライブライの組み込み|○|○|
|画面の自動生成|○|○|
|画面のカスタマイズ|○（＊３）|○（＊４）|
|外部SOAPサービスの呼び出し|○|○|
|外部RESTサービスの呼び出し|○|○|
|外部SAPインターフェイスの呼び出し|×|○|
|SOAPサービスの公開|○|○|
|RESTサービスの公開|○|○|
|単体テスト|○（＊５）|○（＊６）|
|GitHubとの統合|○|×|
|独自のソース管理ツール|×|○|
|入門レベルの日本語ドキュメント|○|○|
|高度な日本語ドキュメント|×|×|
|ユーザーコミュニティ（英語）|○|○|
|開発者向け無償開発環境の提供|○|○|


＊１ OutSystemsはブラウザーでの開発はWindowsアプリに比べて機能上の制約あり
＊２ OutSystemsはVisioでフローチャートを作成するように、分岐やループ、画面遷移などのブロックを画面に貼り付け、それぞれのブロックのプロパティ設定を行うことにより、業務ロジックを開発する方法がメインの開発手法となる。
＊３ ServiceNowで独自の画面を生成する場合には、HTML、Jelly、ServiceNowが提供するライブラリを使って行う。
＊４ OutSystemsで独自の画面を作成する場合には、Visual StudioのフォームエディターのようなUIにより開発を行う。
＊５ ServiceNow自体にAutomated Test Frameworkという独自のテストフレームワークが提供されている。またテストスクリプトにはjasmineを使用することも可能だが、Automated Test Frameのみで単体テストは可能。
＊６ OutSystemsではUnit Testing FrameworkやBDDFrameworkというテストフレームワークがオープンソースで提供されています。

# 参考

[ServiceNowのテストフレームワークでSeleniumのような画面のテストの自動化をする](https://qiita.com/sukkyxp/items/13f4df18ad06bfeae67e)
【CSS】意外と知らないiOSでのtopとbottomの挙動

`position: absolute;`などを使うときにわりとお世話になる`top`とか`bottom`ですが、フルスクリーンで画面を覆いたいとき、

```sample.css
.mask {
    position: fixed;
    width: 100vw;
    height: 100vh;
    top: 0;
    left: 0;
    z-index: 1;
}
```

こんな書き方しませんか？(私はします)
こんなとき、「とりあえず上にべったり付けたいから`top: 0;`にしておこう」としがちではないでしょうか？
実は`top`と`bottom`は**iOS**で別の動きをするので、メモがてら残しておきます。

## top、bottomについて
それぞれ、画面上部・下部からの位置を指定することができるのですが、`position`プロパティが`static`以外のときに適用されます。
`top: 0;`と指定すると、画面上部にべたっと張り付く形になります。
`bottom: 0;`とすると、画面下部にべたっと張り付く形になります。
全画面を覆う場合は`top`でも`bottom`でも関係なさそうに見えるのですが、実はそうではありません。

## 敵はsafari
iOSデフォルトブラウザであるsafariの場合、ちょっとスクロールすると画面上部のアドレスバーと、画面下部のナビゲーションバーが小さくなります。
が、上にスクロールすると再度拡大表示され、ページの表示領域がちょっとだけ減ります。
これが実は曲者で、上にスクロールしなくても、画面下部をタップすると拡大されてしまいます。
そのため、画面下部にあるコンテンツが隠れてしまう、と言う現象が発生します。
たとえば

![IMG_8329.png](https://qiita-image-store.s3.amazonaws.com/0/218417/c24226ca-1b23-9c5c-3797-f74258bbe5dd.png)

この画面、`top: 0;`で指定しているのですが、

![IMG_8327_2.png](https://qiita-image-store.s3.amazonaws.com/0/218417/f7ffcd00-1281-b108-4929-f808ee5313c8.png)

ナビゲーションバーが隠れた状態で「ご予約後の流れについて」の部分をタップすると

![IMG_8328_2.png](https://qiita-image-store.s3.amazonaws.com/0/218417/84c7f8b5-3221-f2fb-aae5-b47604c3e7ea.png)

こんな感じでナビゲーションバーが出てきて文字が隠れます。
これが厄介で、marginを余計に指定しておかないと、画面下部のリンクがタップできない現象が発生します。
これを`bottom: 0;`で指定してやると

![IMG_8331.png](https://qiita-image-store.s3.amazonaws.com/0/218417/78126cdc-25f6-33fd-d7aa-1413f40f0d29.png)

こんな感じで下にべったりついた状態でナビゲーションバーが現れます。
ただし、アドレスバーで画面上部が隠れてしまうため、場合によっては不自然な形になります。

大半は画面を上にくっ付ける実装になるかと思いますが、画面下部にくっつけたいのに`top`で指定する、などトリッキーなことをすると意図しない動作をするのでご注意ください。
三角関数で角度から座標を導くふたつの式の使い途

三角関数の$sin$と$cos$を使うと、角度から座標を求めることができます。おもに用いられるのは、ふたつの方程式です。それぞれがどのようなところで、どのように使われるのかをご説明します。


#三角関数で角度から座標を定めるふたつの方程式
まずは、ふたつの方程式を以下に示しましょう。第1は、原点$(0, 0)$からの距離$r$と$x$軸正方向となす角度$\theta$から座標$(x, y)$を求めます。

```math
x = r\cos\theta\\
y = r\sin\theta
```

第2は、座標$(x, y)$を原点$(0, 0)$から角度$\theta$回して、新たな座標$(x', y')$を導く式です。

```math
x' = x\cos\theta - y\sin\theta\\
y' = x\sin\theta + y\cos\theta
```


#原点からの距離と角度で座標を定める ー 極座標
第1の方程式は、[三角関数の定義](https://ja.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0#%E5%8D%98%E4%BD%8D%E5%86%86%E3%81%AB%E3%82%88%E3%82%8B%E5%AE%9A%E7%BE%A9)にもとづきます。半径1の円(単位円)の円周上の点$P(x, y)$と原点$O$を結ぶ$OA$が$x$軸の正方向となす角度を$\theta$としたとき、座標$(x, y)$はつぎのように定められています。

```math
x = \cos\theta\\
y = \sin\theta
```

####三角関数のsinとcos
![図001](https://qiita-image-store.s3.amazonaws.com/0/128949/8bdaad21-321b-9a8d-3914-8b4f5b2ee7f3.png)

すると、原点が$(x_o, y_o)$で距離は$r$、角度が$\theta$のときは、座標$(x, y)$はつぎの式で表されます。距離と角度からレーダーのように定める座標は「極座標」と呼ばれます。

```math
x = r\cos\theta + x_o\\
y = r\sin\theta + y_o
```

座標を原点から一定角回した新たな座標も計算できます。まず、座標の原点からの距離および$x$軸となす角度を求めます。つぎに、距離はそのまま、回す角度を足し込んで導けばよいのです。

JavaScriptコードで書くなら、つぎのとおりです。なお、ECMAScript 2015の[`Math.hypot()`メソッド](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot)は、座標の原点からの距離を返します。

```js
const r = Math.hypot(x, y);
const angle = Math.atan2(y, x);
const newX = r * Math.cos(angle + rotation);
const newY = r * Math.sin(angle + rotation);
```


#座標を原点から決められた角度回す
座標を原点から決められた角度回す場合には、第2の方程式を使う方が無駄な手間は省けます。もとの座標の原点からの距離も角度も求めなくて済むからです。とくに、たくさんの座標を同じ角度回すときなら、$sin$と$cos$の値は一度計算すれば使い回せるので、さらにお得になります(「[任意の座標を原点から指定した角度回す](https://qiita.com/FumioNonaka/items/c246aca8f1b1b03a66be)」参照)。

```math
x' = x\cos\theta - y\sin\theta\\
y' = x\sin\theta + y\cos\theta
```

原点が$(x_o, y_o)$のときは、それらの値を$(x, y)$座標から差し引いて回し、そのあとで原点座標を足し込みます。

```math
x' = (x - x_o)\cos\theta - (y - y_o)\sin\theta + x_o\\
y' = (x - x_o)\sin\theta + (y - y_o)\cos\theta + y_o
```


#三角関数のふたつの式を使った作例
つぎの[judo.itの作例](http://jsdo.it/FumioNonaka/uqXE)はふたつの方程式を使ってみました。[CreateJS](http://createjs.com/)を用いたアニメーションです。ウィンドウ内をクリックするたびに、円がランダムに置かれて、中心から回ります。

####ランダムに置いた円を回す
[![1804002_001.png](https://qiita-image-store.s3.amazonaws.com/0/128949/6be31f37-14f4-cfd1-3c33-0af71d113f61.png)](http://jsdo.it/FumioNonaka/uqXE)
[\>\> jsdo.itへ](http://jsdo.it/FumioNonaka/uqXE)

円の配置は、中心からの距離と角度をランダムに決めて、第1の方程式で定めました。距離には範囲を定めて、円は中心近くには置かず、真ん中は空白にしています。

```js
function getPolar(r, angle, center) {
	const x = r * Math.cos(angle) + center.x;
	const y = r * Math.sin(angle) + center.y;
	return {x: x, y: y};
}
```

多くの座標を同じ角度回すときは、第2の方程式がお得でした。$cos$と$sin$の値ははじめに求め、それをすべての座標計算に使い回しています。引数に受け取る複数の座標は、配列に納められている前提です。

```js
function rotatePoints(points, angle, center) {
	const cos = Math.cos(angle);
	const sin = Math.sin(angle);
	points.forEach((point) => {
		const x = point.x - center.x;
		const y = point.y - center.y;
		point.x = x * cos - y * sin + center.x;
		point.y = x * sin + y * cos + center.y;
	});
}
```
Power BIでUTCの時刻をJSTで表示する

時系列データをPower BIで手っ取り早く可視化する場合、実データの時刻をUTCで管理していても、UIではJSTで表示できた方が分かりやすい場合があります。
特にWebのPower BIに発行した場合にもJSTで表示したい場合には本記事の方法が使えます。

# 手順

例えばセンサーデータをAzureのTable Storageに、計測時刻はUTCで記録しているものとします。

Power BI Desktopで「クエリを編集」をクリックし、Power Queryエディターを立ち上げ、UI上で対象となる時刻カラムを「日付/時刻/タイムゾーン」に変換しておきます。

「詳細エディター」をクリックし、詳細エディターを立ち上げ、クエリーを次のように編集します。`DateTimeZone.SwitchZone`を使います。

```:編集前
let
    ソース = AzureStorage.Tables("storagename"),
    temperature = ソース{[Name="temperature"]}[Data],
    #"展開された Content" = Table.ExpandRecordColumn(temperature, "Content", {"measured_at", "sensor", "temperature"}, {"Content.measured_at", "Content.sensor", "Content.temperature"}),
    変更された型 = Table.TransformColumnTypes(#"展開された Content",{{"Content.measured_at", type datetimezone}, {"Timestamp", type datetimezone}, {"Content.temperature", type number}})
in
    変更された型
```

```:編集後
let
    change_tz = (x as datetimezone) as datetimezone => DateTimeZone.SwitchZone(x, 9),
    ソース = AzureStorage.Tables("storagename"),
    temperature = ソース{[Name="temperature"]}[Data],
    #"展開された Content" = Table.ExpandRecordColumn(temperature, "Content", {"measured_at", "sensor", "temperature"}, {"Content.measured_at", "Content.sensor", "Content.temperature"}),
    変更された型 = Table.TransformColumnTypes(#"展開された Content",{{"Content.measured_at", type datetimezone}, {"Timestamp", type datetimezone}, {"Content.temperature", type number}}),
    tzchanged = Table.TransformColumns(変更された型, {{"Content.measured_at", change_tz}, {"Timestamp", change_tz}})
in
    tzchanged
```

「完了」をクリックし詳細エディターを閉じ、「閉じて適用」クリックしPower Queryエディターを閉じ、レポートビューで変更結果を確認します。

# 参考

[Power Query M Reference](https://msdn.microsoft.com/ja-jp/query-bi/m/power-query-m-reference)
機械学習使っても技術的負債を残しにくいAWSのインフラ構成

# はじめに
## それでも機械学習を使いたい
googleの[機械学習：技術的負債の高利子クレジットカード論文](https://research.google.com/pubs/pub43146.html)を読んで感銘を受けたので、ここのところ機械学習の恩恵に預かりつつ技術的負債の返済で死なない方法を考えていました。

昨今のAIブームの中、なんか分からんけど良い結果が出るので機械学習的システムを導入したはいいものの、保守・運用で馬鹿でかいコストを払っている会社は少なくないはずだと思います。
「<b>こんなに保守・運用でコストかかるなら、今後のシステムで機械学習使うのは慎重にならざるを得ないな・・・</b>」と思い始めている人も多いかと思います。
それでもやっぱり機械学習は便利なので、これから新しいシステムやアプリケーションを作る際に「ガンガン機械学習使っていこう！」と言えるようなシステム構成を考えてみました。

## この記事の目的・対象読者
### 記事の目的
立ち上げ期のWebアプリケーションに機械学習を組み込む際のAWSインフラパターンを共有すること

### 対象読者
* これから機械学習を用いたWebアプリを作成する人
* 技術的負債をできるだけ残したくない人
* 保守・運用・拡張をできるだけ低コストで実現したい人

## 考えたアーキテクチャ
以下、作ってみた構成です。
ポイントは、「Main Application（メインアプリケーション）」と「Machine Learning System（機械学習システム）」に分かれているところです。
いわゆるフェイルソフトなんですが、今回は<b>立ち上げの小規模チームでもフェイルソフトをするために必要な構成とはどんなものか</b>を考えているところがポイントです。

![Data friend architecture (3).png](https://qiita-image-store.s3.amazonaws.com/0/108223/780975dd-29f9-f8a3-d798-334090c8407d.png)


# アーキテクチャの説明
## メインアプリケーション
ぶっちゃけここはできるエンジニアがいれば、どんな構成でも良いです。笑


が、[Elastic Beanstalk](https://aws.amazon.com/jp/elasticbeanstalk/)を使うことによってインフラ構築と運用のコストを極力まで抑えています。
Elastic Beanstalkで構築するアプリケーションは、PythonでもRubyでもPHPでもOKです。
フレームワークも有名どころは一通り揃えているので、開発者の好き・得意で作れるのは良いですね。（自分はRailsが使えるのが神だと思いました。）

## 機械学習システム
[Lambda](https://aws.amazon.com/jp/lambda/)と[API Gateway](https://aws.amazon.com/jp/documentation/apigateway/)を使うことによって、ほとんど「コード乗っけてハイおしまい」状態になります。
また、ここ最近で機械学習と言ったらほぼPython一択な雰囲気を感じますが、LambdaではPython2系、3系をカバーしているので、このあたりの実装で困ることはほぼないかと思います。
[AWS Lambdaによるサーバーレスな機械学習APIの作り方](https://qiita.com/yamitzky/items/fb6b74fa320ee6f7021e) なんかが参考になります。
Lambda + API Gatewayの構成では面倒なスケーリングやモニタリング等は全てAWSに任せることができ、エンジニアやデータサイエンティストは本来の主業務である分析やモデルの磨き込みに時間を使うことができます。

予測などに使うモデルやベクトル値などを保存して置くためにサーバーを立てるのも面倒なのでフルマネージドなデータストアである[Dyanamo DB](https://aws.amazon.com/jp/dynamodb/)を使っています。
あまりにもでかいモデルなどは[S3](https://aws.amazon.com/jp/s3/)などに保存していただければと思います。



## メインアプリケーションと機械学習システムの繋ぎ方
今回示したインフラ構成の一番のキモです。
基本的にはAPI Gatewayを通してRESTなやり取りをします。

ポイントは<b>APIが死んでもアプリケーションは死なないようにすること</b>です。
以下、具体的な例で確認していきます。

### 例1） 本のEコマース
Amazonのようなサービスを考えます。
メインアプリケーションは「顧客管理、本の購入」などの機能を担い、機械学習システムではユーザーの購入履歴に基づいたレコメンドを行うとします。
事前にレコメンド結果（APIのレスポンス）がどうであれば正常か異常かを事前に定めておき、異常であればレコメンド結果を表示しないようにしておきます。

さらに、検索結果を機械学習に基づいて並び替えたい場合も上記と同様に事前に「異常・正常」を定めて置くことで、<b>APIのレスポンスがおかしな時はAPIの結果を無視</b>することができます。

### 例2） ソーシャルネットワーキングサービス
FacebookのようなSNSを考えます。
Main Applicationは「友人と繋がる、近況の投稿、友人の近況閲覧」などの機能を担います。
そして機械学習システムではユーザー直近の行動に基づいた広告の表示を行うとします。
Main Applicationは、APIを通してユーザーの興味ある広告を取得しますが、もしこの時APIの挙動がおかしい場合は事前に準備しておいた別の方法（例えばルールベース）の代価手段を用いて広告を出すようにします。

さらに、ユーザーが好きそうな投稿を中心にタイムラインに並べたいとなった際は、タイムラインの並び替え機能など<b>新たな機能をさくっとAPIに持たせて</b>そこでやり取りさせるようにします。


# おわりに
## 関わる人みんながハッピーなシステムを
機械学習でシステムを作ることができる人は世の中にたくさんいますが、<b>作った後に運用したり保守したりする人がいる</b>ということまできちんと考えてシステムを作れる人はどれだけいるでしょうか。
エンドユーザーがハッピーになるからといってやたら高度な機能を作りまくって、考えなしに高利子なシステムを本番環境に乗っけてはならないと思っております。
システムと人は良い関係でありたいですねー。

上記の構成は自分が個人的に運営しているサイトで使っています。
今のところ問題は起こっていないので、引き続き運用してみようと思います。

## 注意
クラウドサービスに関する体型的知識を持たないまま書いてしまったので、間違っている部分があるかと思っています。
間違い等ありましたら、ご指摘いただけると嬉しいです。

それから、AWS等のクラウドサービスでアーキテクチャ考えてる人いたら情報交換したいです！

余力があれば、次回はこのインフラ構成を実際にAWSで作る記事を書こうかと思います（意外にハマりポイントあったので）。
GCPで簡単にHPCクラスタを構築する (Part 1)

ハイパフォーマンスコンピューティング（HPC）は創薬や金融サービス、気象予測など、様々な分野で利用されています。HPCと聞くと利用や構築するための敷居が高いというイメージを持つ方もおられるかもしれませんが、GCPを使ってHPCクラスタ環境を簡単に構築できるということをご紹介したいと思います。

今回は以下の図に示すシステムをGCP上で構築します。
<img width="672" alt="Screen Shot 2018-04-09 at 11.07.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/95399/f1785dc2-bff5-92dc-beb5-27740da3296e.png">


ジョブスケジューラにはSlurmを利用します。SlurmはTop500でも多く採用されていて実績のあるジョブスケジューラです。ShcedMDと協力し、GCP上でSlrumのクラスタ環境を簡単に構築するためのツールが提供されていますので、今回はそのツールを利用して環境構築します。

#手順1. 準備
CloudShellで作業を行います。まずはじめに以下のGitHub Repositoryをクローンします。

```
git clone https://github.com/SchedMD/slurm.git
cd slurm/contribs/gcp/
```

Slurmでは認証機構としてMUNGEを利用しています。作成するクラスタにMUNGEの鍵を設定するため、以下のコマンドでMUNGEの鍵を生成します。(今回はデモ用なので簡易に作成しています。）

```
date +%s | sha512sum | cut -d' ' -f1
```

Deployment Managerに渡すslurm-cluster.yamlファイルの下記項目を修正します。それ以外の項目は今回は修正せず、デフォルトのまま使用します。

```slurm-cluster.yaml
・・・
default_users           : tyotsu <- アカウント名
munge_key               : 先ほど作成したmunge keyを記載
・・・
```

#手順2. Deployment Managerで環境構築
以下のコマンドを実行し、SLURMのクラスタ環境を構築します。

```
gcloud deployment-manager deployments create slurm --config 
slurm-cluster.yaml
```

GCP ConsoleのDeployment Managerでデプロイメントの状況を確認できます。”slurm has been deployed”と表示されていればデプロイメントは正常に行われています。

ここまでで環境構築は完了です。以下のインスタンスが作成されていることをGCPコンソールのCompue Engineの画面から確認することができます。
- ログインノード：1台
- コントローラノード：1台
- 計算ノード：2台

# 手順3. 動作確認

構築したクラスタの環境が正常に動作しているか確認するため、CloudShellからログインノードにログインします。

```
gcloud compute ssh login1
```

まずは/homeと/optが正常にマウントされているか確認します。マウントされてない場合は、ノードを再起動するかmountコマンドでappsとhomeをマウントしてください。

```
[tyotsu@login1 ~]$ df -h -t nfs4
Filesystem        Size  Used Avail Use% Mounted on
controller:/apps  100G  2.9G   98G   3% /apps
controller:/home  100G  2.9G   98G   3% /home
```

以下のようなジョブファイルを作成します。(今回はシンプルに計算ノードのホスト名を返すジョブを使用します）。

```
[tyotsu@login1 ~]$ cat test.sh
#!/bin/bash
#
#SBATCH --job-name=test     <- ジョブ名
#SBATCH --output=res.txt    <- 出力ファイル

srun hostname               <- 計算ノードで実行したいコマンド
srun sleep 10               <- hostnameだけだとすぐにジョブが終了するため
```

このジョブをSlurmジョブスケジューラに投入します。-Nで実行するノード数を指定します。ここでは既に起動している2台の計算ノードを使うように2を指定しています。

```
[tyotsu@login1 ~]$ sbatch -N 2 test.sh
Submitted batch job 8
```

ジョブの実行状態を確認します。STがRなので実行中であることが確認できます。

```
[tyotsu@login1 ~]$ squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                 8     debug     test   tyotsu  R       0:02      2 compute[1-2]
```

結果ファイル(res.txt)が出力されているので、内容を確認します。２つの計算ノード上でジョブが割り当てられ、実行されていることが確認できます。

```
[tyotsu@login1 ~]$ cat res.txt
compute2
compute1
```

それではこの結果ファイルを削除し、次に4台の計算ノードでジョブを実行してみます。

```
[tyotsu@login1 ~]$ sbatch -N 4 test.sh
Submitted batch job 9
[tyotsu@login1 ~]$ squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                 9     debug     test   tyotsu CF       0:33      4 compute[1-4]
[tyotsu@login1 ~]$ cat res.txt
compute2
compute3
compute1
compute4
```

新しく2台のインスタンスがプロビジョニングされ、全体で4つの計算ノードを使用し、ジョブが実行されたことを確認できます。Slrumの詳細な使い方はここでは省略します。詳細はhttps://slurm.schedmd.com/などを参照してください。

# まとめ
スケールアウトするクラスタ環境が構築できることを確認できました。
ただこのままだとMPIジョブは使えないですし、並列ファイルシステムもないので、HPCクラスタと呼ぶには少し早いと思います。
gitignoreでハマったメモ

.gitignoreで日本語ファイルを除外するときにハマってしましました。
そこで、一度日本語ファイルを追加した.gitignoreをコミットして
git diff HEAD
で前回のコミットとの変更箇所を見てみると、("/日本語ファイル.txt"を追加)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/192068/e02b2aa0-1545-be89-10b0-d3a42ce07351.png)
/日本語ファイル.txtがバイトコードで表示されています。
この状態では日本語のファイルをignoreすることが出来ませんでした。

gitで日本語は避けたほうが良いです。
riot.js eachにおける自分自身の参照の仕方

### ２通り。eachで指定した要素、イベントから降りてくるitem（riotが定義）。
```js
console.log(this.user,ev.item.user)
```
それでもわからない場合は parent かevを確認。

```js
console.log('more',this.parent,ev)
```
### 全部
```html
<script src="//gnjo.github.io/riot.js"></script>
<loop></loop>
```
```js
riot.tag(`loop`
,`<ul><li each="{ user in users }" onclick={click}>{user.id}</li></ul>`
,function (opts){
 let f=()=>{return Math.random().toString(36).slice(-8)}
 ,ary= this.users = [
  { name: 'Gian', id:f()},
  { name: 'Dan', id:f()},
  { name: 'Teo', id:f()}
 ]
 click=function(ev){console.log(this.user,ev.item.user); console.log('more',this.parent,ev) }
})
riot.mount('loop')
;
```
【Raspberry Pi 2 Model B】USB Wi-fiドングルを複数接続したときの設定

##概要
USB Wi-fiドングルを2つさして、Wi-fiクライアントとアクセスポイントを共存させようとしたら、意外と苦労したので記録として残そうと思います。
![DSCN5665.JPG](https://qiita-image-store.s3.amazonaws.com/0/247920/b6d92086-8586-15b7-6360-95021c569aea.jpeg)

##構成イメージ
　InternetRouter：192.168.1.1（アクセスポイント）
　　│
　　│
　　│wlan0：192.168.1.2（Wi-fiクライアント）
　Raspberry Pi 2 Model B
　　│wlan1：192.168.2.1（アクセスポイント／DHCPサーバ）
　　│
　　│
　端末：192.168.2.100～200（Wi-fiクライアント／DHCPクライアント）

ちなみに今回はルーティングさせないつもりです。

##前提条件
Raspberry Pi

- モデル : Raspberry Pi 2 Model B
- OS : Raspbian Stretch

```Bash:
$ uname -a
Linux raspberrypi 4.14.32-v7+ #1106 SMP Wed Apr 4 18:19:23 BST 2018 armv7l GNU/Linux
```

##事前準備
とりあえずのお約束作業です。

```Bash:
$ sudo apt-get update
$ sudo apt-get upgrade
```

##ネットワーク設定
地味にはまったところから。終わってみればあっけないほど単純でしたが。。。
編集するファイルは３つ。

- /etc/dhcpcd.conf
- /etc/network/interfaces
- /etc/wpa_supplicant/wpa_supplicant.conf

```Bash:
$ sudo vi /etc/dhcpcd.conf
```
初期構築時に以下の設定を追記しました。それはそれでちゃんと認識していたのですが・・・

```Bash:
作業前
・・・
interface wlan0
static ip_address=192.168.1.2/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

interface wlan1
static ip_address=192.168.2.1/24
static routers=192.168.2.1
static domain_name_servers=192.168.2.1

作業後
・・・
#interface wlan0
#static ip_address=192.168.1.2/24
#static routers=192.168.1.1
#static domain_name_servers=192.168.1.1

#interface wlan1
#static ip_address=192.168.2.1/24
#static routers=192.168.2.1
#static domain_name_servers=192.168.2.1
```
追記した分を全部コメントアウトしました。

```Bash:
$ sudo vi /etc/network/interfaces
```
IPアドレスを固定にするときは、/etc/dhcpcd.confに記載するという記述があったので、初期構築時は特に編集していませんでした。

```Bash:
作業後
・・・
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.1.2
netmask 255.255.255.0
gateway 192.168.1.1
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet static
address 192.168.2.1
netmask 255.255.255.0
gateway 192.168.2.1
```
正しいかわからないのですが、/etc/network/interfacesに設定を移しました。

```Bash:
$ sudo vi /etc/wpa_supplicant/wpa_supplicant.conf
```
初期構築時にssidとpskを編集し使用可能な状態でした。これは変更なし。

```Bash:
作業前後変わらず
network={
        ssid="SSID"
        psk="パスワード"
}
```
終わってみれば、/etc/dhcpcd.confでなく、/etc/network/interfacesにしただけです。正しいやり方かどうかはわかりませんが動作してます！

##アクセスポイントとDHCPサーバのインストールおよび設定
このあたりは書きつくされているのでサクッと流れだけ。。。

参考サイト：
https://qiita.com/mt08/items/f2e4f9d3b1ed00849e23

```Bash:
$ sudo apt-get install hostapd
$ sudo apt-get install isc-dhcp-server
```
```Bash:
$ sudo vi /etc/hostapd/hostapd.conf
interface=wlan1
driver=nl80211 # ドライバがnl80211ではないときはもうひと手間あるっぽい
ssid=PI
hw_mode=g
channel=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=12345678
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
```
```Bash:
$ sudo vi /etc/default/hostapd
DAEMON_CONF="/etc/hostapd/hostapd.conf"
```
```Bash:
$ sudo vi /etc/dhcp/dhcpd.conf
authoritative;

subnet 192.168.2.0 netmask 255.255.255.0{
  range 192.168.2.100 192.168.2.200;
  option routers 192.168.2.1;
  option broadcast-address 192.168.2.255;
  default-lease-time 600;
  max-lease-time 7200;
}
```
```Bash:
$ sudo vi /etc/default/isc-dhcp-server
INTERFACES="wlan1"
```
```Bash:
$ sudo reboot
```
iOSのモダールを閉じるボタンは右上

# iOSのモダールを閉じるボタンは右上
iOSのモーダル画面を閉じるボタンの場所は右上か左上かはあまり意識されずにデザインされたり、
配置場所が分からないという人も多いと思う。

モーダルの閉じる画面は例外を除いて右上に配置すべきだろう。

この記事では、その**理由と例外**について解説する。

## I.　理由１ 「戻る」が常に左にある
UINavigationControllerの「戻る」ボタンが、左上にある場合が多いという理由。そのため右上しか場所がない。

### ModalとPush
iOSでの画面遷移はAppleによって用意された２種類に明確に分類される。
画面のより深い階層へ移動するものがPushであり、一時情報を表示するものがModalである。

Modalはその時に居るPushで深い階層へ移動するメインストリームから離れた情報を表示する等への利用が推奨される。

またModal内でもPushによる画面遷移を実装ケースは一般的である。

### Pushは左上に「戻る」が付く
Pushによる画面遷移には、自動的に左上に「戻る」ボタンが配置される。これはAppleによって定義されたものでほぼ100%このルールに従う。

### 「閉じる」の場所は右上だけ
左上が「戻る」ボタンで占有されるので必然的にModalを閉じるボタンは右上となる。

## II. 理由２　「戻る」がない場合も右上の一貫性
### 右上という一貫性
Modal画面内でPush遷移を行わない場合は、左上の場所が空いている状態になる。この場合でも一貫性を持たせるという理由からModalを「閉じる」ボタンは右上に配置するのが良いだろう。

###  「戻る」と「閉じる」は異なる動作なので、それらを一貫した場所へ
「戻る」と「閉じる」は似て非なるものである。「戻る」は一つ上の階層に戻るため、もう一回項目を選択することで「戻る前」へ再度復帰できる。

対照的に「閉じる」は１回以上のPushを含んだ一連のモーダルを全て閉じてしまう。状況によっては一連の作業内容がすべて失われ、「閉じる前」への復帰は困難な場合が多い。

ユーザーが反射的に「戻る」を押したと思って、モーダルが閉じられ情報が失われるようなことは避けるべきである。このような理由からも、「閉じる」は一貫して右上へ配置すべきだろう。


## III. Modalを閉じるボタンが２つある場合
Modalを閉じるボタンが２つあるケースがある。
完了を示すボタン（Done, Save etc.)とキャンセルを示すボタン(Cancel, Close、× etc.)などの
ボタンが両方ある場合がこのケースである。

多くの場合右上のボタンは完了を示すものであるので、**右上に完了系のボタン、左上にキャンセル系のボタン**を配置するのが良いだろう。

## VI. 参考文献
[WITH IOS BUTTONS, KNOW YOUR RIGHT FROM YOUR LEFT](https://bigmedium.com/ideas/ios-button-placement.html)
[Back Button Placement](http://ignorethecode.net/blog/2012/06/10/back_button_placement/)
CentOS7でGeforce GTX1080TiのドライバをインストールしたもののKernelをアップデートしてしまったときの個人的メモ

完全な備忘録として残しておきます。

カーネルをアップデートしてしまい、PCを立ち上げたときにGnome DesktopかMateの起動で止まるのでログイン画面にいかない状態になりました。そのときに行ったことです。

カーネル選択画面でeを押してEdit画面に行く

LANG=en_US.UTF-8 のあとを以下のように追加し、Ctrl + X で実行。ランレベルを強制する
(ここはmulti-userでもよかったかも)

```bash
LANG=en_US.UTF-8 systemd.unit=rescue.target
```

[CentOS7でGeforce GTX1080Tiのドライバをインストールする](https://qiita.com/crgstar/items/2fa7cccfd8309e2fcb72)の手順を踏み、nouveauを無効化する

```bash
sudo mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r)-nouveau.img
```

の手順は非常に危険なのでcpにした方がいいが、そうするとdracutでエラーが出るので--forceを追加する(と多分上書きできたと思う)

```bash
sudo dracut --force --omit-drivers nouveau /boot/initramfs-$(uname -r).img $(uname -r)
```

再起動して、今度はマルチユーザでログインする

```bash
reboot
```

カーネルのEdit画面

```bash
LANG=en_US.UTF-8 systemd.unit=multi-user.target
```

保存しておいたドライバをインストール後、再起動

```bash
sudo sh NVIDIA-Linux-x86_64-390.25.run 
reboot
```

これでうまくいったと思ったが、MATEが壊れていて動かなかったので、GNOME Desktopでログインし、ネットに繋ぐためにドライバ e1000eをインストールし、その後MATEをインストールし直した。
壁紙だけ変わったのが不安だけどとりあえずは元通り？になった。
pythonのmatplotlibで図をたくさん表示してその中にグラフを沢山表示していっぱいプロットしてリアルタイムに表示する。

#経緯
pythonでプログラムを書いていたら、

- リアルタイムに更新したい
- グラフを複数表示したい
- １つの図にたくさんのグラフを出したい

ということがあった。
やり方がわかったのでまとめる

![やりたいこと_trimmed.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/195504/2d42451e-642b-872b-366d-4cb73776d750.gif)


#実行環境
python     =>3.6
matplotlib =>2.0.2

#とりあえずコード
とりあえず普通に　sin cos tan　(三角関数)　をプロットするときの例

```python:main.py
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt

import numpy as np


def main():
    x = np.linspace(-2 * np.pi, 2 * np.pi, 10000)
    y1 = np.sin(x)
    y2 = np.cos(x)
    y3 = np.tan(x)
    y4 = np.arctan(x)

    # 図1を定義
    fig1 = plt.figure()

    # タイトルをつける
    fig1.suptitle("trigonometric function", fontsize=16)

    # 図の中にサブプロットを追加する
    fig1_a = fig1.add_subplot(3, 1, 1)
    fig1_b = fig1.add_subplot(3, 1, 2)
    fig1_c = fig1.add_subplot(3, 1, 3)

    # 図１(a)にプロットする
    fig1_a_1, = fig1_a.plot(x, y1)

    # 2個以上プロットするときはこう
    # fig1_a_2, = fig1_a.plot(x, y2)

    # 図１(a)のタイトルを記入
    fig1_a.set_title("(a) y = sin(x)")

    # x軸の範囲を決める
    fig1_a.set_ylim(y1.min(), y1.max())
    fig1_a.set_xlim(x.min(), x.max())

    fig1_b_1, = fig1_b.plot(x, y2)
    fig1_b.set_title("(b) y = cos(x)")

    fig1_c_1, = fig1_c.plot(x, y3)
    fig1_c.set_ylim(-5, 5)
    fig1_c.set_title("(c) y = tan(x)")

    # 図１のタイトルと図がかぶるのでこれでOK
    fig1.tight_layout()
    fig1.subplots_adjust(top=0.85)

    # 図２を追加。図１と同じ感じでレイアウト可能
    fig2 = plt.figure()

    fig2_a = fig2.add_subplot(3, 2, 1)
    fig2_b = fig2.add_subplot(3, 2, 2)
    fig2_c = fig2.add_subplot(3, 2, 3)
    fig2_d = fig2.add_subplot(3, 2, 4)
    fig2_e = fig2.add_subplot(3, 2, 5)
    fig2_f = fig2.add_subplot(3, 2, 6)

    # 更新した値を表示する
    while True:
        plt.pause(0.1)

        x += 0.1
        y1 = np.sin(x)
        y2 = np.cos(x)
        y3 = np.tan(x)

        fig1_a_1.set_data(x, y1)
        fig1_a.set_ylim(y1.min(), y1.max())
        fig1_a.set_xlim(x.min(), x.max())

        fig1_b_1.set_data(x, y2)
        fig1_b.set_ylim(y2.min(), y2.max())
        fig1_b.set_xlim(x.min(), x.max())

        fig1_c_1.set_data(x, y3)
        fig1_c.set_xlim(x.min(), x.max())


if __name__ == '__main__':
    main()

```

#
追加のドライバ不要でUSBシリアルが利用できるArduino互換機一覧

- なるべく安くUSBシリアル対応のデバイスをつくりたいけどVID取得するのは面倒だなというときに小さいArduino互換機使うと便利
- せっかくだから追加のドライバ入れずに使えるようにしたい
- USB CDC 対応のMCU（32u4など）を搭載していればMacでもLinuxでも追加のUSBドライバなしでUSBシリアルが利用できるぞ


| 製品名            | 価格 |  MCU      | USBタイプ | 動作（Mac/Linux/Windows） |
|:-----------------|:---:|:---------:|:--------:|:------------------------:|
| [Arduino UNO](https://www.switch-science.com/catalog/789/) | 3240円 | ATmega328P/16U2 | B | ◯/◯/- |
| [What's Next Pink](https://www.switch-science.com/catalog/3525/) | 1976円 | ATmega32u4 | micro B | ◯/◯/- |
| [Metro Mini](https://www.switch-science.com/catalog/2334/) | 1760円 | ATmega328 |  micro B |                    ✕/-/- |
| [Adafruit Itsy Bitsy 32u4](https://www.switch-science.com/catalog/3626/) |  1501円 | ATmega32u4      | micro B | ◯/-/- |
「iScroll.js と drawer.js のハンバーガーメニューがAndroidで動かない」のがさらにiOS11.3でリンクが機能しない

drawer.jsを使ってハンバーガーメニューを実装するにあたって、下記記事を参考にバグを解決し設置をしていました。

[iScroll.js と drawer.js のハンバーガーメニューがAndroidで動かない](https://qiita.com/YujiHatanaka/items/64b6a6c8facb3a2f69b5)

ありがたいことにこの方法で問題なく動いていたのですが、iOS11.3でメニュー内のaタグが押せなくなってしまいました。

色々模索したところ、iscroll.jsの

```iscroll.js
preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },
```
↓
こちらを
↓

```iscroll.js
preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|A)$/ },
```
に修正したところリンクが機能するようになりました。
参考までに。
Ubuntu で Apache2 のモジュールを有効にする

## 前書き

Ubuntu で Apache2 の設定するたびに、「あれ？どうやんだっけ？」ってなるので備忘録としてここに記す。

以下、毎回忘れる自分へ（**戒めを込めて煽り気味に**）。

**「`a2enmod` だ！思い出しただろ？」**

## 環境

### OS

```/etc/os-release
NAME="Ubuntu"
VERSION="16.04.4 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.4 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
```

### Apache

```shell
$ apache2 -v
Server version: Apache/2.4.18 (Ubuntu)
Server built:   2017-09-18T15:09:02
```

## モジュールの有効化

あれ？思い出せない？黙って、 `a2enmod` を実行するんだ。

```
$ sudo a2enmod
Your choices are: access_compat actions alias allowmethods asis auth_basic auth_digest auth_form auth_mysql authn_anon authn_core authn_dbd authn_dbm authn_file authn_socache authnz_ldap authz_core authz_dbd authz_dbm authz_groupfile authz_host authz_owner authz_user autoindex buffer cache cache_disk cache_socache cgi cgid charset_lite data dav dav_fs dav_lock dbd deflate dialup dir dump_io echo env expires ext_filter file_cache filter headers heartbeat heartmonitor include info lbmethod_bybusyness lbmethod_byrequests lbmethod_bytraffic lbmethod_heartbeat ldap log_debug log_forensic lua macro mime mime_magic mpm_event mpm_prefork mpm_worker negotiation php5 proxy proxy_ajp proxy_balancer proxy_connect proxy_express proxy_fcgi proxy_fdpass proxy_ftp proxy_html proxy_http proxy_scgi proxy_wstunnel ratelimit reflector remoteip reqtimeout request rewrite sed session session_cookie session_crypto session_dbd setenvif slotmem_plain slotmem_shm socache_dbm socache_memcache socache_shmcb speling ssl status substitute suexec unique_id userdir usertrack vhost_alias xml2enc
Which module(s) do you want to enable (wildcards ok)?
```

Thank you interactive!

親切にどのモジュールを有効化したいか尋ねてくれてるぞ。

`mod_rewrite` を有効化したいって？ `rewrite` と入力して Enter だ。

```
...
Which module(s) do you want to enable (wildcards ok)?
rewrite
Enabling module rewrite.
To activate the new configuration, you need to run:
  service apache2 restart
```

再起動まで案内してくれている。とても優しい奴だ。

```
$ sudo service apache2 restart
```

インタラクティブじゃなくても良いって？分かったよ。

```
$ sudo a2enmod rewrite
$ sudo service apache2 restart
```

## モジュールの無効化

ついでに無効化も記しておく。

```
$ sudo a2dismod
Your choices are: access_compat alias auth_basic authn_core authn_file authz_core authz_host authz_user autoindex deflate dir env filter mime mpm_event negotiation rewrite setenvif status
Which module(s) do you want to disable (wildcards ok)?
rewrite
Module rewrite disabled.
To activate the new configuration, you need to run:
  service apache2 restart
$ sudo service apache2 restart
```

or

```
$ sudo a2dismod rewrite
$ sudo service apache2 restart
```
lambda@edgeを使おうとしたらroleにハマった

## はじめに

ユーザからのアクセスログをEC2を使わず、lambdaからDynamoDBに保管しようと考え、いつもどおりAPIGateway経由でlambdaにリクエストを渡そうとしたが、どうにもダルいのでlambda@edgeを使おうと思った。

## CloudFrontの設定でつまづいた

 - 設定するLambdaFunctionは必ず`us-east-1`で作らなければならない
 - ランタイムは`Node.js 6.10`でないとならない
 - ロール(role)を調整しないとならない　←　これにハマった

## ロールの設定

ロールを設定しないと

```
com.amazonaws.services.cloudfront.model.InvalidLambdaFunctionAssociationException: 
The function execution role must be assumable with edgelambda.amazonaws.com as well as lambda.amazonaws.com principals
```
みたいな感じで怒られる。

なので、IAMを覗くとポリシーというものがあるので、そこから新規にポリシーを作成し、既存のロールにアタッチすると想像した。

```json
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "Service": [
               "lambda.amazonaws.com",
               "edgelambda.amazonaws.com"
            ]
         },
         "Action": "sts:AssumeRole"
      }
   ]
}
```
上記は公式のドキュメントサンプル。
こちらを設定しようとすると、

```
このポリシーには、「Has prohibited field Principal」というエラーが含まれています For more information about the IAM policy grammar, see AWS IAM Policies
```

というエラーが出て受け付けてもらえない。
調べてみると、同じような問題にぶつかっている人もいるようだし、解決に時間がかかった。


## そもそも設定する場所が違っていた

ポリシーを新しく作成したり、選択したりして権限を与えるというのがそもそもの間違いだった。
ポリシーではなく**ロール**からlambda作成時に設定したロールを選択し、**信頼関係/信頼関係の編集**で上記サンプルを入力すると受け付けてもらえる。



とても初歩的だけど、もしかしたら同じ問題に直面してる人もいるかもしれないので。
メモ書き: Rubyでレーベンシュタイン距離を求めるプログラム

##説明
未記入

##コード

```ruby:ruby

def levenshtein_distance(str1, str2)
    matrix = Array.new(str1.length + 1).map{Array.new(str2.length + 1)}
    (0..str1.length).each do |i1|
        matrix[i1][0] = i1
    end

    (0..str2.length).each do |i2|
        matrix[0][i2] = i2
    end
    (1..str1.length).each do |i1|
        (1..str2.length).each do |i2|
            cost = str1[i1 - 1] == str2[i2 - 1] ? 0 : 1
            matrix[i1][i2] = [
                matrix[i1 - 1][i2] + 1,
                matrix[i1][i2 - 1] + 1,
                matrix[i1- 1][i2-1] + cost
            ].min
        end
    end
    matrix[str1.length][str2.length]
end

```

```ruby:ruby
p levenshtein_distance("abc", "abc")
p levenshtein_distance("abc", "abcd")
p levenshtein_distance("abd", "abcd")

=> 0
=> 1
=> 1
```
UserDefaultsとKeyChainのバックアップ・リストアの仕様

2017年10月頃に調査した内容のまとめです。

## UserDefaultsのバックアップ・リストア

[こちら](https://qiita.com/jumperson/items/c1b879fb7e614aa5b93f)にまとめた通り、いずれのパターンであってもバックアップ・リストアで、データが復元されます。

## KeyChainのバックアップ・リストア

[こちら](https://qiita.com/yusuga/items/adbe12b97ce38e544c8f)にまとまっている通りです。  
要約すると

* 同一デバイスであればいずれのケースもデータが復元される
* 異なるデバイスの場合は、 `暗号化されたiTunesバックアップから復元` の場合のみデータが復元される
* 上記以外のiTunesバックアップ、iCloudバックアップからの復元ではデータが復元されない
Numpyのsumのaxisについて理解する

sumやmeanについてくるaxisのパラメーター。頭がこんがらがってしまったので、for文で置き換えて整理してみました。

```python
import numpy as np

A = np.arange(30).reshape(2,3,5)
print(A)

# axis = 0の場合
S0 = np.zeros(A.shape[1:], dtype="int32") #=(3,5)
for i in range(A.shape[0]):
    S0 += A[i, :, :]

print(S0)
print(A.sum(axis=0))


# axis = 1の場合
S1 = np.zeros(A.shape[::2], dtype="int32") #=(2,5)
for j in range(A.shape[1]):
    S1 += A[:, j, :]

print(S1)
print(A.sum(axis=1))


# axis = 2の場合
S2 = np.zeros(A.shape[:-1], dtype="int32") #=(2,3)
for k in range(A.shape[2]):
    S2 += A[:, :, k]

print(S2)
print(A.sum(axis=2))
```

結果：

```python
>>> print(A)
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]]

 [[15 16 17 18 19]
  [20 21 22 23 24]
  [25 26 27 28 29]]]

>>> print(S0)
[[15 17 19 21 23]
 [25 27 29 31 33]
 [35 37 39 41 43]]
>>> print(A.sum(axis=0))
[[15 17 19 21 23]
 [25 27 29 31 33]
 [35 37 39 41 43]]

>>> print(S1)
[[15 18 21 24 27]
 [60 63 66 69 72]]
>>> print(A.sum(axis=1))
[[15 18 21 24 27]
 [60 63 66 69 72]]

>>> print(S2)
[[ 10  35  60]
 [ 85 110 135]]
>>> print(A.sum(axis=2))
[[ 10  35  60]
 [ 85 110 135]]
```

理解のためにfor文で書き換えただけで、for文を使った書き方は遅いだけなのでやめたほうがいいです。
行、列で集計と覚えていると3階以上のときにわけわからなくなるので、インデックスで覚えたほうがわかりやすいかと思います。
技術書ランキングサイトをQiita記事の集計から作ったら、約4000冊の技術本がいい感じに並んだ

QiitaのAPIから投稿記事を取り出し、技術書籍を紹介している箇所を集計して、ランキングサイトを作った。作った本人が言うのも何だけど、できあがった技術書ランキングがやたらエンジニア指向で便利で面白いなー、と。

<a href="https://techbookrank.com/">技術書ランキングをQiita記事の集計から作成した
テック・ブック・ランク</a>

エンジニアにとって技術書の選定はまーまー苦労する。単なる発行部数ランキングでは「人気あるからって技術書として参考になるとはかぎらない」と、なってしまいがち。ブログでオススメされている書評なんかも参考にするが、結局それらは書評を書いた人の主観で書かれたのであって客観的指標にはなりえない。
そこで「Qiitaにある技術ブログ記事内で紹介されている書籍情報を集計すればひと味違った書籍ランキングになるのでは？」と考えた。

で、以下の条件に当てはまる本を「いい本」とした

- たくさんのQiita記事で紹介されている本
- 人気のあるQiita記事で紹介されている本
- 新しい記事で紹介されている本

結果としてできあがったランキングの総合部門トップ６はこんな感じになった。当たり前だけど「売れてる本」と「技術記事で紹介したい本」はちょっと違う。本当の意味で<b>有用な技術本</b>というのは後者の「紹介したい本」の要素が多いかな、と。

<img width="372" alt="og_image.png" src="https://qiita-image-store.s3.amazonaws.com/0/108761/e422f7ad-981e-122e-5816-ef9bf653bc76.png">


いい感じに古くからずっと支持されている古典的名書と最新の人気ある書籍がトップに入っている。「[リーダブルコード](https://techbookrank.com/books/5ab6c45330e8410004196087)」なんかはいつまでも廃れることのない名著だし、最近出たばかりの「[エンジニアリング組織論への招待](https://techbookrank.com/books/5ab6c3de30e8410004195c10)」や[@jnchitoさん](https://qiita.com/jnchito)の「[プロを目指す人のためのRuby入門](https://techbookrank.com/books/5ab6df0a30e841000419eabb)」がトップ１０に入っていて、気に入っている。ちなみに恣意的に特定の本のランクを上げたりは絶対にしていない。同じルールの元で公平に集計測定した結果がこれ。

Qiita記事にあるタグがいい効果を発揮している。Qiita記事に貼ってあるタグはそのまま紹介されている書籍のタグとした。つまりタグ=>記事=>書籍となっているのでタグと書籍の関係は直接ではなく、ゆるーく繋がっているだけ。そこがいいなと思っている。

例えば「[人工知能は人間を超えるか](https://techbookrank.com/books/5ab6c69b30e84100041972d3)」という本の場合、この本には２０以上のタグが付いている。

<img width="250" alt="Screen Shot 2018-04-05 at 09.47.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/108761/7f60d34d-8f71-61b8-c8ae-16874cfbbc19.png">

ウェブサイトで見ていただくとドーナツグラフでタグの分析結果が見れるようにした。

PythonやTesorFlowのタグが付いているが本書にはこれらの技術に関する言及は無い。でもタグがあって、それは「この本を紹介するエンジニアはだいたいPythonやTesorFlowに関係する記事を書いてますよ」という意味になる。このゆるーい関係のタグ付けがいいと思った。他にもRubyの本にGitHubがタグ付けされていたり、書籍の内容には関係無さそうだけど実務では関係あるタグ付けがなされている。

自分で作ったサイトながら、そのタグをクリックして関連タグで人気順にソートされた技術本ランキングを次々に眺めるのが面白くて、しばらくサイト内を巡回していた。例えばAという技術のタグを押しても全てがAに関する書籍ではなかったりするので、<b>「おーこんな本もあったのか」</b>という発見がある。なのでタグを目立つようにして、検索窓は右上に必要な時だけ表示する仕組みにした。サイトのコンセプトとして検索してピンポイントで必要な書籍情報だけを見るよりも、タグをクリックしていろいろ巡回して見た方がこのサイトは面白いと思ったからだ。

本についてはその本を読むこと以前に「その本との出会い」がとても重要だと思っている。売れている順や人気順のランキングならばアマゾンので十分だ。
テック・ブック・ランクは他には無い「本との出会い」がある。なぜならそのランキングに使っている指標が限りなくエンジニア目線を元にした指標だからだ。人工知能の本にTesorFlowのタグを付ける、なんてやるのはエンジニアだけだろう。

Qiitaの技術記事ってそれなりにちゃんと書かないとLike数なりView数なりで人気を得ることは難しい。なのでそれらと連動した技術本のランキングもそれなりに信用に値するかな、と思っている。

それとご自身で投稿したQiita記事で技術本を紹介されていたら、それが[テック・ブック・ランク](https://techbookrank.com/)にちゃんと反映されているか確かめてみたら面白いかも。というかもし反映されてなかったら、ご連絡いただければ幸いです。APIからの本のリンク読み取りっていろいろ種類があって全てはカバーできていないので。

[テック・ブック・ランク](https://techbookrank.com/)が皆さんの<b>「こんな本があったのか！」</b>をたくさん提供することを願って公開した。ご感想なり、批評なりなんでもコメントください。

<a href="https://techbookrank.com/">技術書ランキングをQiita記事の集計から作成した
テック・ブック・ランク</a>


### テック・ブック・ランクのサイト構築に使った技術

- Rails
- GraphQL
- React + Redux
- Google Cloud Platform
- AWS S3
- Heroku
- CloudFlare


### 公開した後のこと

[開設後３週間で収益１０万円を得た個人開発サイトでやったことの全部を公開する](https://qiita.com/jabba/items/1a49e860a09a613b09d4)
riot.js key list add del

### keyはriotが使うだけなので一意であれば何でも良い。
```js
 let f=()=>{return Math.random().toString(36).slice(-8)} //f2it9yrq
```
### 配列の変更そのものが内部的にelementの生成になる。
```js
 del=function(ev){ let me=this.user; this.users.splice( this.users.indexOf(me),1) }
 add=function(ev){ this.users.splice(this.users.length,0,def())}
```
### 全部
```html
<script src="//gnjo.github.io/riot.js"></script>
<loop></loop>

<script type="text/plain" name="cheat-sheet">
let data=['a','b','c','d','e'];
//splice NO chain array; return value NO self.
//[].splice(target_number,change_count,target_data)
//data.splice(0,0,'f'); //unshift//f a b c d e //parent.prependTo
//data.splice(data.length,0,'f');//same push// a b c d e f //parent.appendTo
//if(~data.indexOf('c')) data.splice(data.indexOf('c'),1,'f');//replace c->f//a b f d e// element.replace 
//if(~data.indexOf('c')) data.splice(data.indexOf('c'),0,'f');//before push//a b f c d e// prepend siblingsTo
//if(~data.indexOf('c')) data.splice(data.indexOf('c')+1,0,'f');//after push//a b c f d e// siblingsTo
//if(~data.indexOf('c'))
data.splice(data.indexOf('c'),1);//remove me
console.log(data)
</script>
```
```js
riot.tag(`loop`
,`<ul>
    <li onclick={tadd}>+ topadd</li>
    <li onclick={add}>+ tailadd</li>
    <li each="{ user in users }" key="{ user.id }"  contextmenu={del}>
<label onclick={click}>{ user.show }</label>
<label onclick={tsadd}>[^+]</label><label onclick={sadd}>[+]</label>
</li>
    <li onclick={tcut}>- topcut</li>
    <li onclick={cut}>- tailcut</li>
  </ul>
`
,function (opts){
 let f=()=>{return Math.random().toString(36).slice(-8)}
 ,def=()=>{let id=f(); return {name:'xyz',id:id,show:id} }
 ,ary= this.users = [
  { name: 'Gian', id:f() ,show:'Gian'},
  { name: 'Dan', id:f() ,show:'Dan' },
  { name: 'Teo', id:f() ,show:'Teo' }
 ]
 click=function(ev){ let u=this.user; u.show =(u.show===u.name)?u.id:u.name; }
 del=function(ev){ ev.preventDefault();let me=this.user; ary.splice( ary.indexOf(me),1) }
 tadd=function(ev){ary.splice(0,0,def())}
 add=function(ev){ary.splice(ary.length,0,def())}
 tcut=function(ev){ary.splice(0,1)} 
 cut=function(ev){ary.splice(-1,1)}
 //
 tsadd=function(ev){let me=this.user; ary.splice(ary.indexOf(me),0,def()) }
 sadd=function(ev){let me=this.user; ary.splice(ary.indexOf(me)+1,0,def()) }
})
riot.mount('loop')
;
```
RedashからAWS Athenaに接続する。2018-04-09

# 内容
RedashからAthenaに繋いでselectします

# 準備
Redashを利用可能な状態にしておきます

参考: [RedashをDockerでお試し](https://qiita.com/abetomo/items/6e0d0c19240366b1c182)

# 設定
Redashなので画面でぽちぽち設定していきます

## /data_sources
![スクリーンショット 2018-04-09 17.53.06.png](https://qiita-image-store.s3.amazonaws.com/0/3800/65d3a9ae-19e5-cf90-4321-aa1b300791fa.png)

「+New Data Source」から追加します

## /data_sources/new
* 設定に迷いそうな項目は特にありません
* 必要な項目を埋めていきます
* 今回はGlueのData Catalogを使うのでチェックを入れています
* （`S3 Staging Path` に結果が保存されます）

![スクリーンショット 2018-04-09 17.56.45.png](https://qiita-image-store.s3.amazonaws.com/0/3800/85081725-3548-5831-792e-946d9cece489.png)

必要な項目を入力したら「Save」します

## select
sampledbのtableにselectしてみます

```sql
SELECT *
FROM sampledb.elb_logs limit 15
```

![スクリーンショット 2018-04-09 18.05.42.png](https://qiita-image-store.s3.amazonaws.com/0/3800/34da01a1-1fb6-38df-7dc4-939ae1f67fd9.png)

結果が取得できました！

# まとめ
ぽちぽちするだけでRedashからAthenaに接続してselectできました

# 注意
**データベース名にハイフンなどがあると、Redashなどからselectできない可能性があるので注意**

## 詳細
* Athena + Glue でAWSのWebコンソールからselect
* SDKからselect

などの場合はSQL内にDB名が登場しないので気になりませんが、

Redashからselectする場合など、SQLにDB名が登場する場合DB名にハイフンなどがあるとうまくselectできないっぽい。
（例: `select * FROM DB名.テーブル名`）


```
`DB名`.テーブル名
```

 とかやってもダメっぽい



**回避策があったら知りたい！**
ubuntu16.04 備忘録

個人メモです。

# バージョン確認

```bash
$ cat /etc/os-release
```

# リポジトリ更新

```bash
$ apt update
$ apt upgrade
```

```bash
$ apt install -y aptitude
```

# ディスク容量の確認

```bash
$ df -BM
```

# rootのパスワード設定

```bash
$ sudo passwd
```

# ホスト名変更

```bash
$ sudo hostnamectl set-hostname ${yourhostname}
```

```bash
$ sudo vi /etc/hosts
```


# locale設定(ja_JP.UTF-8)

```bash
$ echo $LANG
en_US.UTF-8
```

```bash
$ sudo apt install language-pack-ja
$ sudo update-locale LANG=ja_JP.UTF-8
```

# 時刻設定(Asia/Tokyo)

```bash
$ sudo timedatectl set-timezone Asia/Tokyo
```

# sudoグループに追加

```
# gpasswd -a user_name sudo
```

# エディタ

## デフォルトのエディタ変更

### vimのダウンロード

```bash
$ sudo apt install -y vim
```

### 変更

3の`Basic`を選択。

```bash
$ sudo update-alternatives --config editor
alternative editor (/usr/bin/editor を提供) には 4 個の選択肢があります。

  選択肢    パス              優先度  状態
------------------------------------------------------------
* 0            /bin/nano            40        自動モード
  1            /bin/ed             -100       手動モード
  2            /bin/nano            40        手動モード
  3            /usr/bin/vim.basic   30        手動モード
  4            /usr/bin/vim.tiny    10        手動モード

現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください: 3
$
```

## nanoエディタ終了
`Ctrl + x`



# サービスの操作

## sshd

```bash
$ sudo /etc/init.d/ssh restart
```

## network

```bash
$ sudo /etc/init.d/networking restart
```

# ソフトウェアインストール

## Ansible

最新バージョンのインストールは[公式のガイド](http://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#latest-releases-via-apt-ubuntu)を参照


## Docker

同様に最新バージョンのインストールは[公式のガイド](https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-docker-ce-1)を参照
Spine 未整理 Memo ToUnity

#自分用：雑メモSpineToUnity
###■Unity側のセットアップ
1. https://github.com/EsotericSoftware/spine-runtimes/<br>からspine-runtimes-3.6をダウンロード<br>http://ja.esotericsoftware.com/spine-unity-download/<br>公式からも直接ダウンロードできるっぽい。
2. ~~解凍してspine-csharpとspine-unityのフォルダーをUnityプロジェクトのAsset下にドラッグコピー<br>※アセットインポートじゃないので注意。~~
<br>現在はアセットインポートになってるみたいです。
<br>なのでメニュー -> Assets -> Import Package -> Custom Packageからインポートします。

###■Spine側の出力設定
1. **[メニュー]**＞**[エクスポート]**
2. エクスポートダイアログで**JSON**を選択
3. 出力フォルダを指定した後、アトラス作成にチェックを入れて設定ダイアログを開く
4. PackSettingsの画面右下**[オプション項目]**の**[アトラス拡張子]**の語尾に**[.txt]**を追加する。<br>（**[XX.atlas]**→**[XX.atlas.txt]**）　
5. OKを押してエクスポートダイアログに戻り、エクスポートボタンを押す。
 
###■SpineデータをUnityにインポート
1. Spineからエクスポートしたデータ（.json/.png/.atlas.txt)をAsset下にドラッグコピー
2. AtlasSet/Material/SkeletonDataが自動生成される。
3. SkeletonDataをsceneにドラッグ
4. SkeletonAnimation/SkeletonGraphic(UI)/SkeletonAnimatorのどれかを選ぶ。
5. HierarchyでSkeletonDataを選択してInspector内で調整する。

- SkeletonAnimation
   - Animationコンポーネントがセットされる。とりあえず動かしたい場合に選択。
- SkeletonGraphic(UI)
    - UIのアニメーションデータ用。Canvas下に配置しないと描画されない。
- SkeletonAnimaator
    - Animatorコンポーネントがセットされる。Mecanimを使用する場合に選択。
       
###■UnityでSpineSkeletonを動かす。
1. HierarchyでSpineデータを選択。（又はProjectでPrefabを選択）<br>元データではなく、エイリアスデータを選択する事。
2. Inspectorの**[SkeletonAnimation(Script)]**＞**[Advanced]**を展開
3. **[AddSkeletonUnity]**というボタンを押す。
4. **[SkeletonUnity(Script)]**というコンポーネントが追加される。
5. **[SpawnHiererchy]**を押してFollow又はOverrideを選ぶ
6. HierarchyにSkeletonが表示される。

- followは表示させるだけで動かせない。
- OverrineはUnity上で骨を動かせる。
- RootOnlyを選ぶとRootのみ表示される。
- 表示させた骨のInspectorでFollowとOverrideの切り替えが可能。<br>又、内包している子供のボーンも指定して表示可能。

###■UnityでSpine内のSlotにアクセスする。
- Spineから出力した元データのInspectorの**[Preview]**＞**[Slot]**＞**[ShowSlot]**で確認できる。
- Slotの内部データにアクセスはできるが切り替えもアニメーションクリップに組み込まれてしまうのでアニメーター側からは制御できない。エンジニアに拡張してもらう必要があるかと思われる。

###■Spine出力Name
Spineのエクスポートで出力されるファイル名はSpineツリー最上部のスケルトン名になる。
※セーブ時のプロジェクトファイル名じゃないので注意。
※SkeletonSetが複数の場合、セットごとに.json/.png/.atlas.txtがそれぞれ生成される。
（→1つのスケルトンセットで１データというくくり）

###■Spine再出力時のUnity側の更新
クリップの追加や削除などをしてAnimatorを使用していた場合、Spineから出力した元データのInspectorの**[SkeletonAnimator]**＞**[FarceUpdateAnmationClips]**でController内のクリップを更新できる。
（Controller内に追加したクリップが無い場合に押そう！）
RDSのmysqlでトリガーが作れない I couldn't create trigger in mysql RDS

RDSでmysqldumpで取得したファイルをインポートしようとしたら、以下のエラーが出ました。
その中には、トリガーも含まれていたので、以下のような記述もありました。
I got dump file by using mysqldump, and tried to import it into mysql on RDS.
But, this error occurred.


```
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `product_log` AFTER INSERT ON `product`
FOR EACH ROW
    INSERT INTO ........
```

RDSではsuper権限は持てないので、以下を設定しましょう、というのは、公式ドキュメントにも載っているので、設定してみた。
In RDS, super privilege is unavailable. We need to change a parameter group.

https://aws.amazon.com/jp/premiumsupport/knowledge-center/error-1227-mysqldump/

```
ERROR 1419 (HY000) at line 3155: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
```

この状況を緩和するには、RDS カスタムパラメーターグループの log_bin_trust_function_creators システム変数に 1 を設定します。
To relax this condition, set the global log_bin_trust_function_creators system variables to 1 through the RDS custom parameter group.

しかし、状況は解決せず、筆者の環境では、それでも以下のエラーが出た。
But, the problem wasn't solved. the error below occurred in my case.

```
ERROR 1227 (42000) Access denied; you need (at least one of) the SUPER privilege(s) for this operation
```

トリガーなどの作成時にDEFINER属性が含まれていると、作成時にDEFINER属性で指定したユーザーを使おうとしてしまうので、上記のエラーが出てしまう。そのため、
If dumpfile includes DEFINER attribute, mysql tries to create trigger with the specified user in DEFINER attribute.
To solve this is that remove the DEFINER attribute.

```
DEFINER=`root`@`localhost`
```

この部分を削除してあげれば、問題なく作成することができます。
My problem was solved by removal of this attribute!
RedashをDockerでお試し。2018-04-09

# 内容
Redashをお試ししたいので、Dockerで動かしてみます

# 準備
* git
* docker
* docker-compose

などが必要です

が、インストール方法などは割愛します

# 手順
## git clone
```
# 適当な作業ディレクトリに移動して
% git clone https://github.com/getredash/redash.git
% cd redash/
```

## docker-compose up
```
# 今回はとりあえずお試しするだけなので特に編集せずそのまま
# `docker-compose.production.yml` を使います。
% docker-compose -f ./docker-compose.production.yml up -d
...略。初回はimageのダウンロードなどで時間がかかります。
...
Creating redash_postgres_1
Creating redash_worker_1
Creating redash_redis_1
Creating redash_server_1
Creating redash_nginx_1
```

### データベース作成
```
% docker-compose -f docker-compose.production.yml run --rm server create_db
```

## ブラウザで確認
ここまで終われば http://localhost にアクセスします。ログイン画面が確認できます。

![スクリーンショット 2018-04-09 17.43.32.png](https://qiita-image-store.s3.amazonaws.com/0/3800/64cb0a83-6834-c64f-1ede-11ec4c8bd9e0.png)

適当に入力して「Setup」すればログインできます。
![スクリーンショット 2018-04-09 17.47.08.png](https://qiita-image-store.s3.amazonaws.com/0/3800/84a79157-656d-05d7-60df-251e0c66651e.png)

あとは接続先の設定など適宜行います。

# まとめ
DockerでRedashをお試しできる状態にしました