OmniAICreator/Qiita-1.07M huggingface dataset:
回文判定 Manacher in Python

# manacher
線形時間で回文判定ができる。(判定するリストまたは文字列に&が入っていたら違う文字や数字に書き換えて使う)
このアルゴリズムは同じ文字列やリストについて、複数回、複数区間の回文判定を行うときに強い。
まず線形時間でself.r配列を作って、その後の判定については定数時間で動きます。
判定回数がO(n)だった場合、普通に実装するとO(n^2)となってとても間に合わないが、manacherではO(n)でmake_rしたのち、定数時間の判定をO(n)回するので全体でO(n)で済む。


```python:manacher.py
"""Module for palindrome."""


class manacher:
    """Cache radius array of palindrome to judge in linear time."""

    def __init__(self, l):
        """Insert '&' to judge both even and odd length palindrome."""
        self.n = len(l)
        self.m = 2*self.n+1
        self.d = ['&']*self.m
        self.r = [0]*self.m
        for i in range(self.n):
            self.d[2*i+1] = l[i]
        self.make_r()

    def make_r(self):
        """Make self.r[i] (radius of palindrome whose center is self.d[i])."""
        i, j = 0, 0
        while i < self.m:
            while j <= i < self.m-j and self.d[i-j] == self.d[i+j]:
                j += 1
            self.r[i] = j
            k = 1
            while k <= i < self.m-k and k+self.r[i-k] < j:
                self.r[i+k] = self.r[i-k]
                k += 1
            i += k
            j -= k

    def judge(self, start, end):
        """Return 1 if l[start, end) is a palindrome."""
        center = start+end
        return 2*end-1 < center+self.r[center]

```


#使用例

```python:
l=[1, 0, 0, 0, 1, 2]
s = manacher(l)
for i in range(6):
    for j in range(i+1, 7):
        print(l[i:j], s.judge(i, j))
```

実行結果

```
[1] True
[1, 0] False
[1, 0, 0] False
[1, 0, 0, 0] False
[1, 0, 0, 0, 1] True
[1, 0, 0, 0, 1, 2] False
[0] True
[0, 0] True
[0, 0, 0] True
[0, 0, 0, 1] False
[0, 0, 0, 1, 2] False
[0] True
[0, 0] True
[0, 0, 1] False
[0, 0, 1, 2] False
[0] True
[0, 1] False
[0, 1, 2] False
[1] True
[1, 2] False
[2] True
```

引数start, endに対して[start, end)区間が回文になっているかどうかを返します。

#追記
self.dの比較のところを奇遇で場合分けしてあげれば無駄なメモリを使わなくて済みそう

```python:manacher.py
def make_r(self, l):
        """
        Make self.r whose length is self.m.

        if l="01221" then considering "&01&2&2&1&" (=l_ temporarily)
        self.r[i] is radius of palindrome whose center is l_[i].
        """
        i, j = 0, 0
        while i < self.m:
            while j <= i < self.m-j and self.compare(l, i-j, i+j):
                j += 1
            self.r[i] = j
            k = 1
            while k <= i < self.m-k and k+self.r[i-k] < j:
                self.r[i+k] = self.r[i-k]
                k += 1
            i += k
            j -= k

def compare(self, l, left, right):
    """If left%2=1 then compare l[left//2] with l[right//2]."""
    return l[left//2] == l[right//2] if left & 1 else True
```
ESP32でDHT11を使う

####DHT11（デジット社の説明書より）
相対湿度　20～90%（25℃時、精度±5%）
温度　0～50℃（精度±2℃）
データ線にプルアップ4.7kΩ
応答時間　湿度6～15秒、温度6～30秒
電源電圧　3.3～5VDC

####準備（ライブラリ）
https://github.com/adafruit/Adafruit_Sensor
https://github.com/adafruit/DHT-sensor-library

####最小プログラム

```C

#include "DHT.h"

DHT dht(2,DHT11);  //2番ポート

void setup() {
  Serial.begin(115200);
  Serial.println("DHT11 trial");
  dht.begin();

}

void loop() {

  delay(3000);

  float h = dht.readHumidity();
  float t = dht.readTemperature();

  Serial.print("Humidity : ");
  Serial.println(h);
  Serial.print("Temperature : ");
  Serial.println(t);
}

```

出力は小数点以下2桁だけど、出力は整数値だった
Humidity : 36.00
Temperature : 23.00
みたいに。

####次：
アナログ入力を試す
Ransack の sort_link が MySQL で動作しない（ incompatible with DISTINCT）


#はじめに
ローカルのSQLiteでの開発環境では問題なく動いていたのですが、本番環境（MySQL）にデプロイすると、Ransackを利用したソート機能で例外が発生してしまいました。
対処過程のメモを残しておきます。


#エラー内容
ログに出力されているエラー内容は以下になります。

```shell
 ActionView::Template::Error (Mysql2::Error: Expression ¥#1 of ORDER BY clause is not in SELECT list, references column 'DB名.テーブル名.カラム名' which is not in SELECT list; this is incompatible with DISTINCT: 
```

#参考URL
以下のページを参考に対処しました。感謝です。

[MySQLでdistinctが効かない。mysqlバージョン5.7からの変更。](http://blog.prophet.jp/2951)




#MySQLのversion確認

まずはMySQLのバージョンを確認。参考サイトの情報に該当しそうだ。。。

```shell
mysqld --version
mysqld  Ver 5.7.25 for Linux on x86_64 (MySQL Community Server (GPL))
```


#SQLモードの確認

続いて、SQLモードの内容を確認。やはり同様である。

```shell
mysql> SELECT @@GLOBAL.sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@GLOBAL.sql_mode                                                                                                                         |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```


#設定を変更して動作確認

MySQLのconfigファイルを修正してsql_modeを空にする。

```shell
sudo vi /etc/my.cnf
```

```shell:my.cnf
[mysqld]
sql-mode=""
```

修正が終わったら再起動して動作確認

```shell
sudo systemctl restart mysqld.service
```

ソートが動作することを確認できました。


#終わりに
ONLY_FULL_GROUP_BY　が原因のようなので、それだけオフにすることも後々検討したい。
また、その他の項目にも是非を確認して設定を見直したい。

こういった事をきちんと出来るようになりたいと思いつつ、忙しさを言い訳にしてまずはこれで良しとしちゃいます。
PlayFab VisualStudioAppCenterとの連携が可能に！

原文は[こちら](https://blog.playfab.com/blog/playfab-visual-studio-app-center-is-a-win-for-developers)

PlayFabがVisualStudioAppCenterとの連携ができるようになりましたよという話

### よりLiveOpsを加速するためのアプリの情報も素早くキャッチしよう！
PlayFabはユーザの動向をリアルタイムに分析して解析するのに特化したツールです
ですがアプリのバグやクラッシュレポートも当然早くキャッチする必要がある
そのためのツールもPlayFabに取り込んで一元管理しましょう！

### そもそもLiveOpsとは?
ゲーム開発作業のほとんどは事前に行うのが一般的な手法でした
ゲームが十分な成果を出すかどうかを事前に知るのは困難なため、期待通りに動作するか確認するのに長期間を要していたからです。
そのため測定データをきわめて早期に取得し、ユーザーからのフィードバックに基づいて調整を行う必要性が出てきました。
ゲーム自体をサービスとして考えて、機能を継続的に追加することで、長期的な収益化と顧客定着を実現していく、という考え方です

### VisualStudioAppCenter って何？
もっと詳しく書いてある記事はたくさんあると思うので、要約すると

>アプリをクラウドでビルドして
自動でテストを行い
テストユーザーにメールで配布/各ストア、Intuneに配布し
配布されたアプリがクラッシュした場合にはレポートし
ユーザやデバイス、地理属性ごとにログ分析をし
プッシュ通知をユーザに送る


ことができるツールとのこと
(引用：モバイル アプリの開発/運用を Visual Studio App Center と Azure で加速させよう!)


### で、どうやって始めるの？
現状まだプライベートプレビュー状態のため、テストしたい場合はPlayFabチームに連絡が必要とのこと
あらかじめAppCenterのアカウントを作成しておく必要もあります(無料)
Add-Onから簡単に追加することが可能になる

### 今後の流れ
PlayStreamとの統合を進めていて、アプリ内で発生したことにリアルタイムで反応することができるようになるとのこと
プレーヤーに影響を与えているクラッシュデータを使用して、それらをセグメント化し、
ターゲットを絞ったメッセージングを作成し、ユーザへの素早いアプローチを行うことができます。
GDC2019でデモが見れるようなので、また情報アップデートできればと思います。
JavaScript - function syntax between ES5 and ES6

```javascript:ES5
function foo() {
...
}

foo();
```

```javascript:ES6
const foo = () => {
...
}

foo();
```

```javascript:ES5_Return
function foo() {
    return 'Hello Taiwan';
}
```

```javascript:ES6_Return
const foo = () => 'Hello Taiwan';
```

```javascript:ES5_Return_Parameters
function foo(a, b) {
    return a+b;
}
```

```javascript:ES6_Return_Parameters
const foo = (a, b) => a+b;
```
https://medium.freecodecamp.org/es6-functions-9f61c72b1e86
https://pjchender.blogspot.com/2017/01/es6-arrow-function.html
https://medium.com/@thejasonfile/es5-functions-vs-es6-fat-arrow-functions-864033baa1a
AWS ElasticBeanstalk環境でEC2立ち上がり時にEIPを自動で振り当てる

ElasticBeanstalk環境でEC2インスタンスが立ち上がった時、EIPを自動で割り当てるスクリプトを作ってみました。

オートスケーリングでEC２インスタンスが増えた場合、PublicIPが自動で割り当てられますが、
サービスによっては外部連携していて、許可されたIPのみ疎通が許可されているなどあるかと思います。
ElasticBeanstalk環境では`.ebextensions`ディレクトリ配下にスクリプトを配置しておけば、EC2インスタンスが立ち上がったタイミングで実行されます。


```yaml
files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/00_associate_eipalloc.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash

      env=$(/opt/elasticbeanstalk/bin/get-config optionsettings -n aws:elasticbeanstalk:application:environment -o RACK_ENV)
      
      # プールしているEIPのAllocationIDを環境毎に用意
      if [ ${env} = "production" ]; then
        eipalloc_ids="eipalloc-aaaaaaaa eipalloc-bbbbbbbb eipalloc-cccccccc eipalloc-dddddddd"
      elif [ ${env} = "test" ]; then
        eipalloc_ids="eipalloc-xxxxxxxx eipalloc-yyyyyyyy"
      fi

      if [ -z ${eipalloc_ids} ]; then
        echo Not exist AllocationID in the ${env} environment
      else
        instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
        region=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//')

        export AWS_DEFAULT_REGION=${region}

        available_alloc_id=$(aws ec2 describe-addresses --allocation-ids ${eipalloc_ids} | jq -r '[.Addresses[] | select(.InstanceId == null)][0] | .AllocationId')
　　　　　
　　　　　echo available_alloc_id=${available_alloc_id}

        if [ ${available_allocid} = null ]; then
          echo "Already associated"
        else
          aws ec2 associate-address --instance-id ${instance_id} --allocation-id ${available_alloc_id}
        fi
      fi
```

参考
https://dev.classmethod.jp/cloud/aws/choose-eip-from-addresspool/
Windows proxy認証環境下(@含)でのpip

# proxy認証(@含)でのpip
- Qiitaの記載記事も、ネットの記事もうまくいかない場合ためしてみてください。
- Windowsの場合、環境変数に登録すれば問題は解決しますが、ここでは別の手法を提案します。

### pipでエラー
```type:bat
(venv) $ pip install request
Collecting request
  Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('
<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x000001BF9A115668>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',)': /simple/request/
```
### pip --proxyでエラー
```type:bat
(venv) $ pip install request
Collecting request
  Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('
<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x000001BF9A115668>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',)': /simple/request/
```
## set proxy
- [ここらへんを参考に](https://qiita.com/nshinya/items/08db9be2c5255c91e6a0)

```type:bat
(venv) $ set set HTTP_PROXY=http://[username]%40[userdomain]:[password]@[proxy]:[port]
(venv) $ set set HTTPS_PROXY=http://[username]%40[userdomain]:[password]@[proxy]:[port]
(venv) $ pip install request
Collecting request
  Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('
<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x000001BF9A115668>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',)': /simple/request/
```

## 結論
- 環境変数に登録する
    - HTTP_PROXY=http://[username]%40[userdomain]:[password]@[proxy]:[port]
- もしくは！set コマンドを使う
    - ただし「%%40」にする
        - set HTTP_PROXY=http://[username]%%40[userdomain]:[password]@[proxy]:[port]
 
```type:bat
set HTTP_PROXY=http://[username]%%40[userdomain]:[password]@[proxy]:[port]
set HTTP_PROXY=http://[username]%%40[userdomain]:[password]@[proxy]:[port]
pip install request
```

## pipをバッチにしておく
- ppipというバッチを作り、Proxyを気にしないpipを準備します。
- ppipはPATHに通してください

```type:ppip.bat
@echo off

if "%1" equ "install" (
  goto proxy_install
)
if "%1" equ "show" (
  goto show
)

:show
pip freeze
goto end


:proxy_install
rem batの場合%%40
set HTTP_PROXY=http://[username]%%40[userdomain]:[password]@[proxy]:[port]
set HTTP_PROXY=http://[username]%%40[userdomain]:[password]@[proxy]:[port]
pip install %2
goto end


:end
```
```type:python
ppip install request
```
スクロール中を検知する方法（必要な設定など）

探しましたが、意外と一から十まで手順を書いてくれてるサイトは見つかりませんでした。
せっかくなので<font color="Red">一から十まで</font>書こうかと思います。

今回は「スクロール中であることを検知する方法」に絞ります。


①UIScrollViewDelegateを継承する

```swift
class ViewController: UIViewController, UIScrollViewDelegate{
}
```

②ストーリーボードのscrollViewを引っ張る
controlを押しながらソースコードにギュインってやつです

```swift
class ViewController: UIViewController, UIScrollViewDelegate{
    @IBOutlet weak var scrollView: UIScrollView!
}
```

そしたらこんなのが生成されます。
で、次がなくてはならないけどあまり出てこなかったやつなのですが

③delegateをセットする

```swift
class ViewController: UIViewController, UIScrollViewDelegate{
    @IBOutlet weak var scrollView: UIScrollView! {
        didSet{
            scrollView.delegate = self
        }
    }
}
```


④スクロール中に呼び出されるメソッド（scrollViewDidScroll）を配置

```swift
class ViewController: UIViewController, UIScrollViewDelegate{
    @IBOutlet weak var scrollView: UIScrollView! {
        didSet{
            scrollView.delegate = self
        }
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("scroll中です")
    }
}
```

これらを書けば動くかと思います。
scrollViewDidScroll以外にも沢山のメソッドがありますが、検索すればメソッドは沢山出てきました。
検索してみてください。
[Node.js]Promiseで再帰処理を使ってwhileっぽいループ処理を行う

Promiseを使ったループ処理のサンプルはいくつかあるけど、
Promiseの結果を使ってwhileっぽく処理するやり方があまりなかったのでメモ。

変なところやもっといいやり方があればコメントください

```javascript

function loopUnit() {
  return new Promise(resolve => {
    /* ループ処理本体 */
    resolve(result)
  })
}

function looper() {
  return new Promise(resolve => {
    // 永久ループにならないように限界条件を入れる (optional)
    if ( /* 限界条件 */) {
      resolve()
      return
    }

    // ループ処理
    loopUnit().then(result => {
      if ( /* while条件 */ ) {
        looper().then(() => resolve())
      } else {
        resolve()
      }
    })
  }) 
}

looper()
```
リモートワークのススメ iPad Pro

#iPad Proでリモートワークがどこまでできるか？
昨今、働き方改革を絶賛実践検証中・・・
週1回のリモートワーク（在宅）と出張先でのリモート作業をおこなっています。

**（主な業務内容）**
- メールの閲覧（office365 outlook）
- チャットツールでのコミュニケーションと会議（office365 Teams）
- 業務処理 主にブラウザで処理（ie）
- 開発 （notes / visual studio / node-red / 独自プラットフォーム(JavaScripts)）
<img width="768" alt="スクリーンショット 2019-03-14 10.54.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/375988/f171a114-cb97-5b5a-cf59-06595341aad9.png">

**（会社の環境）**
- MacBookPro ParalleslsでWindows10
- 主要サーバーはほぼ仮想環境

#リモート環境の構築
- iPad Pro 11インチ　＋　SmartKeybord
- Microsoft Outlook
- Microsoft Teams
- Word
- Excel
- リモートツール（※別途記事にしたい　Parallels Client/VNC Viewer/Chromeリモートデスクトップ）


#リモートを擬似的にオフィス内でやってみました
ほぼ会議かメールのやりとりで1日が過ぎていってます。開発をやるときは気合いがのっている日に半日みっちりみたいな感じです。

####メール・コミュニケーション・会議
メールはOutlook、雑多な連絡とTV会議はTeams、これはiPad ProのOutlook/Teamsはめちゃめちゃつかいやすい！十分リモートで通用するレベルです。もしろ邪魔が入らない分リモートの方がいい。

####開発
開発を実施するためにリモート環境を整えようとしました。（別途記事にはしたいです。）
いろいろなリモートツールをためしてみました。
- Parallels Client
- VNC Viewer
- Chromeリモートデスクトップ

**結果！　開発できん！**

いろいろな人が記事あげてますが、iPad Proでリモートで開発（プログラミング）はやっぱ厳しいのですかね？
以下マイナスポイントです。
- マウスが使えない　GUIの開発は致命的
- キー配列がに違う　生産性ダウン
- 打感が悪い　好みもあります

####業務処理
ブラウザベースで業務処理はおこなえます。経理的な処理だったり総務的な処理だったり、
主に経理的なとこの申請が多いです。

しかし！うちの基幹システムはサポートがほぼ**IE**また主要な業務で**Notes**が残っていたりします。
Macユーザーが一番苦手なところです。
**開発**で書いたリモートツールでいろいろ頑張ったのですが、やはりストレスありますね。。


#まとめ
開発を行う以外はiPadでリモートでやった方が効率よさそう。環境もかわることでいいアイディアとかうまれるかもしれません。なんてったってiPadは軽い
週１回程度の在宅・出張だけだったらiPad Proでいいかなぁという感じです。

ただ、メイン機種でMacBookProつかってるんで在宅だったら家に持って帰りますね・・・。
Mathクラスのすすめ

# ○○以上の時に××としたいなぁ
数値を扱うときに、○○以上の数値は××として扱いたいときありますよね？（ある）
コードで書くとこんな感じ↓
※○○は「num」、××は「max」とします。

```SampleClass.cs
        public static void Sample(int num, int max)
        {
            if (num > max)
            {
                num = max;
            }
        }

```

うーん、いまいち

よし、じゃあ三項条件演算子つかおうっと

```SampleClass.cs
        public static void Sample(int num, int max)
        {
            num = num > max ? max : num;
        }
```

うーん、なんか可読性悪いなぁ・・・
いや1行でかけてはいるけどね・・・

# そんなときのMathクラス
```SampleClass.cs
        public static void Sample(int num, int max)
        {
            num = Math.Min(num, max);
        }
```

おお、可読性がよくてコメントがなくてもわかりやすいし、1行で書けたぞ！

Mathクラスを使えば逆も↓

```SampleClass.cs
        public static void Sample(int num, int min)
        {
            num = Math.Max (num, min);
        }
```

ええやんかぁ・・・

負の数だけ正の数にしたいなぁ↓

```SampleClass.cs
        public static void Sample(int num)
        {
            // イマイチ
            if (num < 0)
            {
                // こうとか
                num = num * -1;

                // こうとか
                num = -num;

                // ↑なんか微妙
            }

            // Math.Absですっきり
            num = Math.Abs(num);
        }
```

ええやんかぁ・・・

# Mathクラスとか数学使う人専用でしょ？？

そんなこと思っててすみませんでした。
PlayFab コミュニケーションツールのローカライズ

原文は[こちら](https://blog.playfab.com/blog/localized-player-communications)


ユーザとのコミュニケーションツールがローカライズされましたというお話し
(すでにされているとおもってましたが、管理画面だけだったようで)

今回ローカライズされたのは下記3つの機能

〇Email通知
![playfab_locarize_01.png](https://qiita-image-store.s3.amazonaws.com/0/313446/c01e63c3-7335-1baa-b4d0-5fd590bdc1d0.png)

〇Push通知
![playfab_locarize_02.png](https://qiita-image-store.s3.amazonaws.com/0/313446/97b8fd96-6b3b-f1e5-2a6d-0c714dc54b43.png)

〇News
![playfab_locarize_03.png](https://qiita-image-store.s3.amazonaws.com/0/313446/420cb5cb-6eda-34c8-7b83-e749d9ca2916.png)


デフォルトで設定されている言語は、管理画面のローカライズとして設定した言語ですが、
追加で別の言語でも設定できるので、グルーピングで通知の出し分けができる模様
「Exception inputs are all NaN」が出て詰んだ件に関して

#自己紹介
この度Smart Tradeでインターンすることになったゴンです。 

ゴンについて、知りたい方はこちら。
ブログ読んでねー

https://www.investor-gon.com/


ツイッターはこちら
https://twitter.com/gon_gon_tarou


初めての記事はこちら(QuantXを初めてみて)
https://qiita.com/investor-gon/items/2b1952ae5c2c88334c74


#「Exception inputs are all NaN」のエラーで詰みました。

<br>

グーグル先生に教えてもらおうとして思ったら、ヒット！！！

<br>

https://www.quantopian.com/posts/help-exception-inputs-are-all-nan

<br>

読もうと思った英語かい〜
つらいーと思ったそこのあなた。
安心してください

ちょー簡単に訳してあげますよ！！

![スクリーンショット 2019-03-01 16.51.15.png](https://qiita-image-store.s3.amazonaws.com/0/332034/19f1fb93-560c-df4d-4f0e-a72f9829fba2.png)

Quantopian (海外の似たようなアルゴのサイト)で、「Exception inputs are all NaN」がでました。
助けてください。MACDとRSIの指標をtalibを使って計算するとエラーになってしまいます。



![スクリーンショット 2019-03-01 16.52.46.png](https://qiita-image-store.s3.amazonaws.com/0/332034/a5e2773e-3633-56b6-2870-311788930f1b.png)

それは、talibのバグでした。ごめんちゃい。


って感じでした。

#エラーが出た理由について（自分なりの考察）

過去の株価がない(空もしくは0)のに、talibで計算しようとしてしまい、エラーになったのかなっと思ってます。

ちなみに東芝などの古くからある銘柄を入れてもエラーでした。



#じゃあどうするの？

よくわかりませんね。

<b>とりあえず、なんの銘柄がエラーを出しているのかを特定して、その銘柄を削除しました。</b>

新しい銘柄ばっかりのアルゴリズムは、バックテストを表示できないので、販売まで行うのは厳しそうな感じですね。

<br>
ちなみに、どれがエラーを知るにはこのコードを使いました。

```
ctx.logger.debug(変数名)
```

それでは
Dockerでアプリケーションを配布する場合に、(一部界隈で)デファクトスタンダードになっている設定項目を環境変数とするパターン

なにかしらアプリケーションを開発しており、公式のDockerイメージを配布する。最近よく見かけますね。
利用者側の意見として、アプリケーションの設定には環境変数が使えると助かったりします。

なんで？

- ADD/COPYがいらない
  - 変更のたびビルドしなくていい
- Mountつかわなくていい
  - Mount用のファイルを管理しなくていい
- docker-compose.ymlなどで完結

で、この環境変数からアプリケーションの設定というやり方、一部界隈のDockerイメージで命名規則が次のように、

- `{アプリケーション名}_{ディレクティブ}_{サブディレクティブ}`
- `{アプリケーション名}_{設定項目名}`

という感じの環境変数をUppercaseでアプリケーションに渡せば、設定ファイルの同じ項目を指定・または上書きするというルールがあります。

別にどんなイメージでもこうすればよいという主張ではなく、なんかしらの公式イメージとかを作って不特定多数に使ってもらう際にはこのようにしておくやり方もありますという話です。


例えばこれらがそんなアプローチを取っています。

- kafka(Confluent)とその周りのモジュール [confluentinc/cp-docker-images at v5.1.2](https://github.com/confluentinc/cp-docker-images/tree/v5.1.2)
- graylog [Graylog2/graylog-docker at 3.0.0-1](https://github.com/Graylog2/graylog-docker/tree/3.0.0-1)

> 追記: 後でもすこし触れているけど、設定ファイルのリファレンスがそのまま環境変数に置き換えられるのがこの規則の良いとこです。

## 環境変数から、Dockerコンテナ起動時に設定ファイルに追記するタイプ

例であげたkafka(Confluent)は、Dockerコンテナが起動する際に環境変数から設定ファイルへの追記を行います。

[confluentinc/cp-docker-images at v5.1.2](https://github.com/confluentinc/cp-docker-images/tree/v5.1.2)

設定ファイルに追記したい設定項目があれば、下記のような対応で環境変数をセットしてあげます。

- `default.replication.factor` <= `KAFKA_DEFAULT_REPLICATION_FACTOR`
- `kafka.num.partitions` <= `KAFKA_NUM_PARTITIONS`

このようにすることで、あらゆるパラメータを環境変数経由で設定できるようにしています。

実際どのようにやっているかは、下記のエントリーポイントファイル群を見るとなんとなくわかります。

- https://github.com/confluentinc/cp-docker-images/tree/v5.1.2/debian/kafka/include/etc/confluent/docker

自作？のラッパーで追記してるようですね。(流石につらくはあるので、冒頭でアプリケーション配布側であればできるようにしたほうがよい、程度の表現になってます。)


## 環境変数があったら、優先して使うタイプ

多分Graylog(未確定)がこのタイプなんだと思うのです。エントリーポイントをざっと見てもファイル変更してるように思えなかった。(Java力もないのでそれ以上追いかけませんでした。)

- [Graylog2/graylog-docker at 3.0.0-1](https://github.com/Graylog2/graylog-docker/tree/3.0.0-1)

graylogはkafkaと違い、設定ファイル上の区切りが`_`なので、``GRAYLOG_*`の環境変数の後半部分がlowercaseとアンダースコアの設定項目に対応してます。

- `is_master` <= `GRAYLOG_IS_MASTER`
- `password_secret` <= `GRAYLOG_PASSWORD_SECRET`

設定ファイルのリファレンスを読みながら、環境変数に起こしていきやすいですね。
そのためか、次のような質問も、法則があるからそれに従おうぜという回答で締められています。

- [Please document GRAYLOG_ELASTICSEARCH_HOSTS · Issue #8 · Graylog2/graylog-docker](https://github.com/Graylog2/graylog-docker/issues/8)

### おまけ、Rubygems例

ちなみに、Rubygemsの[thekompanee/chamber](https://github.com/thekompanee/chamber) なんかもそのパターンで、設定用のyamlファイル上にあるキーと環境変数が対になるような使い方ができるのでたまに使っています。

- [thekompanee/chamber: A surprisingly configurable convention-based approach to managing your application's custom configuration settings.](https://github.com/thekompanee/chamber)

こっちの環境変数があったら、優先して使うタイプはDockerコンテナに限らず利用できる点もよいですね。

## おわりに

このアプローチはわりと浸透している気もしますが、はっきりこうだという話もあまり出てないなと思ったので書いときました。

テンプレートからコンフィグファイルを作る、とかは項目が多くなってくると分岐で肥大化しちゃうことと、管理対象はなるべく少なくするのがやっぱりよいです。
使う側としても嬉しいし、自分で何か配布するときはそういうように作りたいな。
graphene-djangoではrelayを使う前提であるので注意

# graphene-djangoではrelayが必須
grahpene-djangoのハマりポイントとして、filterを作る際にフロントではrelayを使う前提であると言うことが一つ挙げられる。

[graphene-django](https://docs.graphene-python.org/en/latest/quickstart/:embed:cite)


順調にquery, mutationを実装していき、relayを使わない決断をしてしまったあと、filterを実装するとき、公式サイトでこれを見つける。

[graphene-django tutorial using relay](https://docs.graphene-python.org/projects/django/en/latest/tutorial-relay)

[graphene-django filter](https://docs.graphene-python.org/projects/django/en/latest/filtering/)


```python
# cookbook/ingredients/schema.py
from graphene import relay, ObjectType
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField

from ingredients.models import Category, Ingredient


# Graphene will automatically map the Category model's fields onto the CategoryNode.
# This is configured in the CategoryNode's Meta class (as you can see below)
class CategoryNode(DjangoObjectType):
    class Meta:
        model = Category
        filter_fields = ['name', 'ingredients']
        interfaces = (relay.Node, )


class IngredientNode(DjangoObjectType):
    class Meta:
        model = Ingredient
        # Allow for some more advanced filtering here
        filter_fields = {
            'name': ['exact', 'icontains', 'istartswith'],
            'notes': ['exact', 'icontains'],
            'category': ['exact'],
            'category__name': ['exact'],
        }
        interfaces = (relay.Node, )


class Query(object):
    category = relay.Node.Field(CategoryNode)
    all_categories = DjangoFilterConnectionField(CategoryNode)

    ingredient = relay.Node.Field(IngredientNode)
    all_ingredients = DjangoFilterConnectionField(IngredientNode)
```

```jsonnet:relay有りquery例
query {
  allCategories {
    edges {
      node {
        name,
        ingredients {
          edges {
            node {
              name
            }
          }
        }
      }
    }
  }
}
```


これはあんまりイケてない。relayを使うとそうなのかもしれないけれど、relayを使っていないのにこのqueryの返りはダメだ。
本当はこうしたい

```jsonnet:relay無しのquery例
query {
  allCategories {
    name,
    ingredients {
      name
    }
  }
}
```

なるほど、もしかするとrelayを使わないといけないの？と思いissueを確認すると、

[Separating django-filter from relay connection](https://github.com/graphql-python/graphene-django/issues/206)

引用

>
 Did you have any feedback on whether your propose is valid? It would be awesome to have that baked in graphene-django (I really don't want to use relay).
I'd gladly help with the implementation



>
I still do not understand why graphene-django only focuses on the implementation of graphql with Relay since Django can be used with any frontend framework


とにかくみんな困っているみたいだ。(I really don't want to use relay).


# 解決法 graphene-django-extrasを使う
[graphene-django-extras](https://github.com/eamigo86/graphene-django-extras:embed:cite)

>
This package add some extra functionalities to graphene-django to facilitate the graphql use without Relay:
+ Allows pagination and filtering on Queries.
+ Allows to define DjangoRestFramework serializers based Mutations.
+ Allows use Directives on Queries and Fragments.


つまり without Relayでfilterやpagenationを実装できると言うことである。
5000円寄付しました。ありがとうeamigo86。
[WIP] DynamoDB を開発環境に導入するときに、調べたことまとめ

# 概要

DynamoDBを実環境に導入するにあたって、開発環境を整備する必要がある。
そのため、開発環境を整備するために、必要なことを調べて見た。

# 開発環境構築前提

1. DynamoDBは別ネットワーク
2. Dockerを使うこと

# そもそもDynamoDbとは

- マネージド型のNoSQLデータベース
- 読み込み書き込みが早い
- 原則API経由で操作し、SQLとはデータの扱い方が異なる
- スループットに応じてスケーリング
- 利用中に読み込み/書き込み性能(キャパシティユニット)の変更が可能
- AWSのクレデンシャル情報でアクセス
- アクセスはインターネット経由となる

# 今回実現したい環境

1. 他の環境にアクセスするDBに必要な情報を問い合わせたい。
2. 複数のアイテムを取得できるようにするのは旨味があるか

# 必要な手順

1. DynamoDbのDocker公式イメージを使う
2. aws-cliの設定を行う
3. DynamoDbにアクセスしたい環境側にSDKを導入

# DynamoDBの仕様

## 予約語について

[DynamoDB の予約語](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/ReservedWords.html)


# 調べたリンクまとめ

- [Amazon DynamoDB（初心者向け 超速マスター編）JAWSUG大阪](https://www.slideshare.net/shimy_net/amazon-dynamodb-23315068)
- [DynamoDBローカルをDockerコンテナとして動かす](https://qiita.com/tamo_breaker/items/7a2344032bc7e736b071)
- [DynamoDBローカルのDockerコンテナにsharedDBオプションを付与する](https://qiita.com/tamo_breaker/items/f86c9b5fc6991813e3ca)
- [Amazon DynamoDB とは](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Introduction.html)
- [DynamoDB の基礎知識とまとめ](https://qiita.com/hshimo/items/e5ad98b21786d796f1da)
- [Class: AWS.Config](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#constructor-property)
- [DynamoDB の AWS SDK サポートの概要](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Programming.SDKOverview.html)
- [aws/aws-sdk-php - GitHub](https://github.com/aws/aws-sdk-PHP/)
- [awsdocs/aws-php-developers-guide](https://github.com/awsdocs/aws-php-developers-guide/blob/master/doc_source/getting-started_installation.rst)
- [AWS再入門 Amazon DynamoDB 編](https://dev.classmethod.jp/cloud/aws/cm-advent-calendar-2015-aws-re-entering-dynamodb/)
- [aws-cli のインストール](https://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html)
- [dynamodb-admin - DynamoDbローカルのGUIのOSS](https://github.com/aaronshaf/dynamodb-admin)
- [instructure/dynamo-local-admin-docker - Dockerイメージとセットで諸々やってくれる aws-cliのセットアップがいらない](https://github.com/instructure/dynamo-local-admin-docker)
- [CLIの初期設定について（認証情報とコマンド補完）](https://www.task-notes.com/entry/20141026/1414322858)
- [Docker（Docker Compose）から DynamoDB Local を使う際にデータを永続化する](https://qiita.com/okashoi/items/f1c757279574d37b812e)
- [Dynamoがlocalで実行できる事を知ったので、Docker Container上で動かせるようにして、公開してみたお話。](https://qiita.com/shinofara/items/15180ad1d117f3a32ad7)
- [docker-compose.yml を分割して external_links でコンテナを接続](https://qiita.com/va034600/items/5f363803e8bd59cbb173)
- [docker-compose で別の docker-compose.yml で作ったコンテナとリンクする (ネットワークを繋げる)](https://qiita.com/reneice/items/20e981062b093264cd0a)
- [今更だけどdocker composeのベストプラクティス](http://innossh.hatenablog.com/entry/2017/04/22/192743)
- [shinofara/dynamodb-local](https://github.com/shinofara/dynamodb-local)
- [amazon/dynamodb-local](https://hub.docker.com/r/amazon/dynamodb-local)
- [Serverless Frameworkでローカル環境のセットアップからAWSへDeployまでを試してみる](https://kcf-developers.hatenablog.jp/entry/2018/10/11/114516#DynamoDB-Local%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
storybook ビルド時に、すべてのファイルを消して作り直す




rimrafを入れる
rimrafはフォルダごと削除する。

```shell
yarn add rimraf dev
```

build-storybookコマンドに、rimrafを追加

```js
    "build-storybook": "rimraf ./storybook-static && build-storybook"
```
Alibaba Cloudの現状〜2019年〜

## キッカケ
AWSを数年間触ってると「コストが高い」という声を聞く事が多くなり、AWS以外のパブリッククラウドの採用を考え始めました。大手であれば基本機能はおよそ同じという想定の元、Alibaba Cloudの現状について調べてみました。

## Alibaba Cloudとは
[Alibaba Cloud](https://jp.alibabacloud.com)はAWS、GCP、Azure以外で唯一シェアを伸ばしているパブリッククラウドです。[（参考）](https://www.publickey1.jp/blog/19/awsazuregoogle20184synergy_research_group.html) 
中国経済を背景にしてシェアを拡大している印象が強いですが、基本サービスはAWSやAzureとも遜色ないようです。

下記はAWSとの簡易比較

|カテゴリ|AWS| Alibaba Cloud|
|:----------:|:----------:|:-----------:|
| 仮想サーバ    | EC2   | Elastic Compute Service |
|コンテナ| ECS       |Container Service |
|プログラム実行| Lambda        |Function Compute|
| ネットワーク |  VPC       | Virtual Private Cloud (同名)|仮想プライベートネットーワークサービス|
|ロードバランサー| ELB      |Server Load Balancer |
|データベース  |  RDS   |ApsaraDB for RDS|
|キャッシュ| ElastiCache    |ApsaraDB for Redis|


リージョン数も2019年3月時点で欧米亜の12箇所、日本リージョンは2016年より開設しているので、業務に支障はないレベルかと思います。

## Alibaba Cloudの疑問
### 中国政府にデータが漏洩されるんじゃないの？
→中国政府にデータが漏洩する事は一切ありません。（との事です）

AWSやGCPと同様の規約という事で、データは現地（日本）のデータセンターに保管され、事業者はその中身を確認しません。また下記の通り、第三者機関からも「データ漏洩はない」という旨をお墨付きされています。

>　Alibaba Cloudは、ISO 27001、CSA Star、PCI-DSSなど国際的な業界固有のコンプライアンス基準や、米国のHIPPA、ドイツのC5、シンガポールのMTCSなど国ごとの基準を満たしている。第三者機関によるSOCレポートも発行しており、2019年からは日本語のSOCレポートが提供されるようになった。
[引用元](https://ascii.jp/elem/000/001/805/1805495/)

### そうは言っても、密かにデータ流出してるんじゃないの？
→国際基準の認証認可を取得していることに加えて、Alibaba Cloudの日本リージョンは、SBクラウドというソフトバンク系列の国内の会社が提供しています。

言い換えれば、日本企業の[プライベートポリシー](https://www.sbcloud.co.jp/privacy/cloud)にも準拠されているので、全く心配ないと言って良いでしょう。

### サポートは中国語？中国品質じゃないの？
→サポートも日本語です。サポート品質は未確認ですが、[日本語ドキュメント](https://jp.alibabacloud.com/help)の充実さから見て、日本品質に近いと思われます。

### 中国の通貨（元）で払わなくてはいけないの？
→円払いでOKです。これは他クラウドと違い、日本のSBクラウドが主幹としてサービス提供している為のようです。
　https://jp.alibabacloud.com/pricing

### インフラ自動化したいんだけど？
→Terraformに対応しているので可能です。これ個人的に一番驚きました。
　https://www.terraform.io/docs/providers/alicloud/index.html

### 資格試験は存在するの？
→存在します。Pearsonより可能です。ただ２０１９年3月時点で英語のみ、日本語は未対応のようです。
https://www.pearsonvue.co.jp/Clients/Alibaba-Cloud-Certification.aspx
　※日本語対応したら、アップデートします

## 結論
というわけで、安価で”普通のクラウド”を利用するという点で言えば、Alibaba Cloudはなくはない選択肢かなと思います。
勿論AWSのネームバリューとコミュニティが圧倒的なので、パブリッククラウド未経験の方はAWSの方が学習しやすいと思いますが、「AWSたけーな」と思い始めてきた人は[Alibaba Cloud](https://jp.alibabacloud.com)を触ってみるのはアリかと思います。

## 補足
じゃあどれだけコスト安くなるの？って所はまた調べて、別記事で投稿したいと思います
Docker Dockerfile

##1.命令##
|命令|説明|
|---|---| 
|FROM |ベースイメージの指定|
|MAINTAINER|作成者情報を設定|
|RUN|ベースイメージから起動したコンテナ内で実行するコマンドを設定|
|ENV|環境変数を設定|
|WORKDIR|場所(ディレクトリ)を移動|
|USER|ユーザ変更設定|
|LABEL|メタ情報(バージョンやコメントなど)設定|
|EXPOSE|公開ポート番号設定|
|ADD|ファイルやディレクトリを取得（リモート可）|
|COPY|ファイルやディレクトリを取得（ローカルのみ）|
|VOLUME|ボリューム設定|
|ONBUILD|次のbuild時に実行されるコマンドを設定|
|CMD|作成したイメージが起動されたら実行するコマンドを設定|
|ENTRYPOINT|作成したイメージが起動されたら実行するコマンドを設定|


##2.Dockerfileを作成する##

```Dockerfile:Dockerfile
FROM centos

LABEL title="test1"\
      version="1.0"\
      description="This is a test1"

RUN mkdir /test1
RUN echo "hello world" > /test1/aaa
VOLUME /test1

ENV hoge=hogehoge

EXPOSE 80

WORKDIR /tmp
RUN ["pwd"]

ADD https://github.com/docker/cli/blob/master/README.md /tmp

COPY sample.txt /tmp
```


##3.Dockerfile からイメージを作成する##

作成された Dockerfile を実行。

```
$ docker image build -f Dockerfile .
```

1つずつ実行され完了。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/dad31b4a-d76f-a970-d8eb-76b1cb94601a.png)

イメージが作成されたことを確認。

```
$ docker images
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/be142b1a-1c70-2eb2-a75c-75ba4cae06c5.png)

ちょっと名前を付け忘れたので、tag をつけておく。

```
$ docker images tag 0025fec43609 test:1
```

メタ情報が反映されているか確認してみる。

```
$ docker image inspect test:1
```


##4.docker を実行する##

作成したイメージで docker を実行してみる。

```
$ docker container run -it test:1
```


##5.内容を確認する##

起動したDockerからひとつずつイメージの内容と合致しているか確認してみましょう。

1.WORKDIR /tmp から開始されていることがわかります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/0f18a90d-29e0-ee43-2109-8caf93f02d82.png)

2.FROM centos かを確認する。

```
$ cat /etc/redhat-release
```

3./test1/aaa で hello world が表示されているか確認する。

```
$ cat /test1/aaa
```

4.環境変数が登録されているか確認する。

```
$ printenv | grep hoge
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/b303a623-3fd4-e78c-1882-1256ee82e488.png)


5./tmp にGitHubのファイルが保存されているか確認する。

```
$ docker ls /tmp
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/7b06bc2f-e3f5-5b96-308c-a1f0599ca88d.png)
gzip の使えない UNIX 環境で tar を圧縮する方法

# 概要

gzip の使える環境では以下のようにワンライナーで tar まとめと zip 圧縮を同時に行うことができます。

```
tar cvzf [アーカイブ名.tar.gz] [対象ファイル...]
```

一方で、UNIX環境(AIX、HP-UX、Solarisなど)では gzip が標準で入っていないため、zip 圧縮するための z オプションを使うことができません。本記事ではUNIX環境で tar をワンライナーで圧縮する方法についてご紹介します。

# コマンド

tar コマンドの内容を compress コマンドへ渡してファイルへリダイレクトすることで対応できます。

```
tar cvf - [対象ファイル...] | compress -c > [アーカイブ名.taz]
```

compress コマンドは LZW (Lempel-Ziv-Welch) というアルゴリズムで圧縮するため、一般的には拡張子を tar.Z や taz とします。
また、LZW は gzip と比べて圧縮率や展開速度が劣るため、gzip が使える環境であれば gzip を使うようにしましょう。
micro:bitのmyポートフォリオ

#My ポートフォリオ（作品集）
- マイクロビット関係のページが増えてきたので，まとめておきます．

## [micro:bitのLEDをそろばんにみたてて整数：10万までを表示](https://qiita.com/tmdoi/items/208aa2526273e305ee4a)

- 私のオリジナルコード．
- 0-99,999までを5x5 LEDに表示できるので，アナログ入力値の確認などに便利．
- イチオシの作品です

## [micro:bitでロト7の乱数マシーンをつくってみた](https://qiita.com/tmdoi/items/811c3ec9f639180aaf27)

- 遊びでつくった乱数発生器を，ロト７の乱数発生器として作品にしました．
- リンクをスマートフォンで開けば，本体がなくても，使用できることに驚いた

## [micro:bitで名札をつくってみた](https://qiita.com/tmdoi/items/bea74257dd2e6a30f19b)

- 学内でmicro:bitを流行らせるために，名札をつくってみました．
- 2019.3.14の終業式で反応を見る予定

## [micro:bitでデータ取得してExcelにて取得](micro:bitでデータ取得してExcelにて取得)

- Excelのマクロをつかって，リアルタイムかつダイレクトにExcelに数値入力ができるというサイトの情報をもとに，検証してみました．
- 安定性がもう少し向上してくれれば...

## [micro:bitで超簡単計測→csv](https://qiita.com/tmdoi/items/27fca0ab519800d012d2)

- ファームを最新にして，Chromeで接続すると，とても簡単にcsvファイルが取得できるというサイト情報をもとに，検証してみました．
- これは，とても驚きでした．オフライン取得で予定のであれば，簡易的なデータロガーとして使えそうです．

## [micro:bitとmacのターミナルでシリアル通信](https://qiita.com/tmdoi/items/9ba2bd57a06a538b163c)

- サイト情報をもとにシリアル通信の検証してみました．
- とても簡単に接続できることがわかりました．
- 外部の装置やロボットの制御がArduinoと比較しても同等程度に簡単にできそうです．

## [micro:bitで力センサーを入力としたカウンターを作ってみた](https://qiita.com/tmdoi/items/d6bc3ee1cf8223098687)

- 力センサーをデジタル入力のスイッチとして，カウンタをつくってみました．
- 別途開発したことのある[中小企業向けのIoTカウンタ](https://qiita.com/tmdoi/items/407bf6ce6aea6fa228c5)と同程度のものができました．
- 音がなることも検証しました．
Prettierの対象から一部ファイルを除外する




readme のファイルまでPrettierで整形されたりする時があったので、
一部ファイルだけ除外したい。


## 方法

プロジェクト直下に`.prettierignore`を作成して、除外したいファイル、フォルダを列挙する。

例

```js:.prettierignore
package.json
package-lock.json
testEslint/
testProject/
testTslint/
testWorkspaceFolder/
```



## 参考

[Ignoring Code · Prettier](https://prettier.io/docs/en/ignore.html)

[prettier-vscode/.prettierignore at master · prettier/prettier-vscode](https://github.com/prettier/prettier-vscode/blob/master/.prettierignore)
Amazon Linux で goofys を使う


EC2 のディスク容量はいつも心配事。AWS EFS も出てきましたけれど、月額100ドル以上ぐらい払わないとアクセス速後が遅いまま。なので S3 のバケットを EC2 にマウントするという方法があります。

# お断り

## データ転送量

安価にスタートできますが、 **データ転送量が2重** にかかります。 

データの流れは、S3 -(1)-> EC2 -(2)-> ユーザーになります。

(1) では S3 のデータ転送料金、

(2) は EC2 のデータ転送料金がかかります。

## ディスク読み込み速度

S3<->EC2 では、VPC の外と通信するのでネットワーク速度は必然的に落ちます。
ディスクアクセススピードが求められるファイルは置かないようにしましょう (SWAP とか)。


# AWS アカウント側の設定 (マネージメントコンソール)

## S3 バケットを作成

書き込み許可をさせたい S3 バケットを作成。

## S3 用の Policy と IAM ユーザー作成

Policy を作成。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::[S3バケット名]",
                "arn:aws:s3:::[S3バケット名]/*"
            ]
        }
    ]
}
```

IAM ユーザーを作成し、さきほどのポリシーを付与。
Access ID & Secret Key をゲットする。

# EC2 側の goofys のインストールと設定

## goofys のインストール

```
$ # root ユーザー
$ yum -y install golang fuse
$ aws configure
# AWS S3 の IAM Access ID/Secret Key を設定
$ vi .bash_profile
export GOPATH=$HOME/go
PATH=${PATH}:${GOPATH}/bin
$ echo $GOPATH
#パスが正常に設定されているか確認
$ go get github.com/kahing/goofys
$ go install github.com/kahing/goofys

```
 
## S3 ストレージをマウント

```
$ # root ユーザー
$ mkdir -p [マウントポイント]
$ id [許可したいuser] # [uid] [gid] を書き留める
$ goofys -o nonempty -o allow_other --uid=[uid] --gid=[gid] --dir-mode=0777 --file-mode=0666 [S3バケット名] [マウントポイント]
```

## 再起動しても自動マウントされるよう設定

```
$ # root ユーザー
$ vi /etc/fstab
$ /root/go/bin/goofys#[S3バケット名] [マウントポイント] fuse _netdev,allow_other,--dir-mode=0777,--file-mode=0666,--uid=[uid],--gid=[gid] 0 0
$ mount -a
```

`--dir-mode` & `--file-mode` は適宜変更。
EC2 内から chmod & chown できなく、すべてこの設定が有効化される。

# 参考情報

参考
https://qiita.com/kooohei/items/a14f22cb0381342d1861

http://caters.works/2016/08/%E3%81%95%E3%81%8F%E3%82%89%E3%81%AEvps%E3%81%AB-goofys-%E3%81%A7-s3-%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88/
graphene-djangoでのenum.Enumの扱い

djangoでmodelを書いていてchoiceFieldでは普通enumを用いる。

これをmutationなどの引数にしたいとする。

通常以下の様にgraphene.Enumを用いる事になるが、
graphene-djangoはpythonのenumをgraphene.enumを書かずに自動で変換してくれる。


```python
import graphene

class BarEnum(graphene.Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

```

[graphene-djangoでのEnumsの説明](https://docs.graphene-python.org/en/latest/types/enums/)

このgrapheneのEnumsの説明ではpythonのEnum.enumは次のように使えるとなっている。

```python:mutation.py

import enum

# pythonのenum
class BarEnum(enum.Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

class CreateFoo(graphene.Mutation):
    Foo = graphene.Field(FooType)

    class Arguments:
        bar = graphene.Enum.from_enum(BarEnum)
    
    def mutate(self, info, **kwargs):
        pass
```

だがこれだと以下のエラーが出る。

```
ValueError: Unknown argument "bar"
```


正しくは以下

```python:
class CreateFoo(graphene.Mutation):
    Foo = graphene.Field(FooType)

    class Arguments:
        bar = graphene.Enum.from_enum(BarEnum)(required=True)
    
```


また、二つ同じenumを変換するとエラーとなる。

```
AssertionError: Found different types with the same name in the schema: FooEnum, FooEnum.
```

これを回避するには

```python
class EnumInput():
    Foo = graphene.Enum.from_enum(FooEnum)


class AInput(graphene.InputObjectType):
    foo = EnumInput.Foo(required=True)
    baz = graphene.String(required=False)


class BInput(graphene.InputObjectType):
    foo = EnumInput.Foo(required=True)
    baz = graphene.Int(required=False)


class CreateFoo(graphene.Mutation):
    bar = graphene.Field(BarType)

    class Arguments:
        a = graphene.Argument(AInput)
        b = graphene.Argument(BInput)

```
Go(golang) echoとVue-cliをつなげる

Vue-cliでフロントを作ってgo(echo)でホスティングするまでの手順。

## Vue-cliでフロントを作る

Vue-cliで作るフロントエンド適当に作ってみます。

```
vue create frontend
  :
```

Vue-cliを使ったフロントエンド開発は [こちら](https://qiita.com/567000/items/dde495d6a8ad1c25fa43) 含め様々な記事があるのでご参考にしていただくとして細かいところは省略。


## Go echoでバックエンドサーバを作る

次に本編であるバックエンドを作ります。

```
mkdir backend
cd backend
go get -u github.com/labstack/echo
```

> -u オプションは依存関係の解決です
> proxyが必要な方は http_proxy と https_proxy を環境変数で設定してください

これでgo echoの環境ができたので簡単なサーバを書きます。

```go:main.go
package main

import (
    "net/http"
    "github.com/labstack/echo")

func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello,World!")
    })
    e.Logger.Fatal(e.Start(":8080"))
}
```

動かしてみます。

```bash
$ go run main.go
```

ブラウザで `http://localhost:8080` でアクセスして `Hello,World!` と出ることを確認してみましょう。

今回はフロントエンドには`Vue-cli`を使いたいので静的ファイルを返すようにサーバーのコードを書き換えます。
`/` に来たアクセスに対して `public` フォルダを見るようにルーティングを追加します。

とりあえず`public`フォルダを作っておいて、

```bash
cd backend
mkdir public
```

コードでは `e.Static("/","public/")` のように静的ファイルのルーティングを追加。

```go:main.go
package main

import (
    "net/http"
    "github.com/labstack/echo")

func main() {
    e := echo.New()
    e.Static("/","public/")
    e.GET("/hello", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello,World!")
    })
    e.Logger.Fatal(e.Start(":8080"))
}
```

ここまででバックエンド側の準備はいったんおしまい。

次に、準備ができたところでVue-cliで作ったフロントエンドとつなげます。
つまりはVue-cliのビルド結果（通常は`dist`フォルダ）を先ほど作ったbackendの `public` に出力するように変更していきます。

configの2か所のパスを書き換えます。

```javascript:frontend/config/index.js
    :
  build: {
    // Template for index.html
    index: path.resolve(__dirname, '../../backend/public/index.html'),  ← ここ

    // Paths
    assetsRoot: path.resolve(__dirname, '../../backend/public'),  ← ここ
    :
```

そしてVueのビルドを行います。

```bash
cd ../frontend
npm run build
```

これで元々は`dist`に出ていたファイル一式が `../backend/public` にできるはずです。

> ../backend/public/index.html や ../backend/public/static/ が出来上がっていることを確認してください

ということで改めてgoのサーバを起動します。

```bash
go run main.go
```

`http://localhost:8080/` では`Vue-cli`で作ったフロントエンドが表示されて、
`http://localhost:8080/hello` ではGoで作ったAPIで `Hello.World!` が表示されたと思います。

## まとめ

ということでGo EchoでVue-cliのフロントのホスティングができて、ついでに、Go Echo のAPIも動かせました。

> APIといっても Hello,World! 返してるだけですが、jsonとか返すようにすれば立派なAPIになります

フロントはVueで組んでちょっとしたAPIはGoで作る環境が整ったということで、モダンなWebサービスの環境が構築することができました。

おしまい
Amazon S3 での静的ウェブサイトのホスティング方法

# S3でバケットを作る
まずは公開する画像なりhtmlなりのコンテンツを置くバケットを作る
![S3 Management Console.png](https://qiita-image-store.s3.amazonaws.com/0/112584/87f5d2c8-7e7f-b404-ecea-6e5e8a842a07.png)

バケット名を入力し、リージョンを選んで「作成」
このバケット名とリージョンがurlに使われます
![S3 Management Console1.png](https://qiita-image-store.s3.amazonaws.com/0/112584/1504ddea-2727-0b29-e79f-3a7b0307e1d0.png)

# 静的ホスティングの設定
作成したバケットを選択し、上部タブの「プロパティ」から「Static Website hosting」を選択
![S3 Management Console2.png](https://qiita-image-store.s3.amazonaws.com/0/112584/566d2423-b87b-2b7d-110d-f4bdc7e83ce6.png)

インデックスドキュメントとエラードキュメントを入力して「保存」
ここで入力したファイルは実際になくても、アクセスした際にはAWSのデフォルトのエラー画面が出てくれるので
とりあえず動かすには問題ありません。
![S3 Management Console4.png](https://qiita-image-store.s3.amazonaws.com/0/112584/7935b7e8-df03-8a72-ba3f-4f093d2663ba.png)

# アクセス権限の設定
「アクセス権限」タブ→「パブリックアクセス設定」→編集
![S3 Management Console5.png](https://qiita-image-store.s3.amazonaws.com/0/112584/b87ea6ae-fcc4-cd88-6eb6-efe7de396f20.png)

下２つのチェックを外して保存します。
![S3 Management Console6.png](https://qiita-image-store.s3.amazonaws.com/0/112584/1917df21-39e6-4420-88d8-ab7a2fc8bb2d.png)

以下のバケットポリシーを入力し、保存します。
アップロードしたコンテンツのパブリックアクセスを有効にします。
![S3 Management Console7.png](https://qiita-image-store.s3.amazonaws.com/0/112584/4f587cd0-8e2d-400c-c366-f837ece892ae.png)

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::バケット名/*"
        }
    ]
}
```
うまく設定できればアクセス権限にパブリックの文字が付きます。
念のため「アクセス権限」タブ→「パブリックアクセス設定」→編集で
「新規のパブリックバケットポリシーをブロックする」のチェックを元に戻し、保存しておきましょう。

![S3 Management Console8.png](https://qiita-image-store.s3.amazonaws.com/0/112584/b82c8681-3d3d-9aac-ebd9-c9ceedbeb6f9.png)


# 完了
これでこのバケットにhtmlをアップロードすれば静的ウェブサイトの出来上がりです。

アクセスについては、例えばtest.jpgをアップロードした場合は
http://バケット名.s3-website-リージョン名.amazonaws.com/test.jpg
（上の例では`http://test.docs.s3-website-us-east-1.amazonaws.com/test.jpg`)

本当に静的webサイトとして運用するなら、https化や独自ドメイン設定も必要かと思いますが。
この記事ではここまでとします。
Kotlin 1.3のCoroutineのキャンセル④（finally句でリソースを閉じる）

# 検証環境
この記事の内容は、以下の環境で検証しました。

* Intellij IDEA ULTIMATE 2018.2
* Kotlin 1.3.0
* Gradle Projectで作成
* GradleファイルはKotlinで記述（KotlinでDSL）

# 準備
詳細は下記の準備を参照してください。
https://qiita.com/naoi/items/8abf2cddfc2cb3802daa

# Cancelling coroutine execution
[前回](https://qiita.com/naoi/items/a78e355d80c490a771a2)に引き続き、[公式サイト](http://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html#closing-resources-with-finally)を読み解いていきます。

タイトルをみると、わからなくもないです。
キャンセルしたときにfinally句でリソースクローズする話だろうなとイメージはわきます。

それでは、読み進めてみます。

>Cancellable suspending functions throw CancellationException on cancellation which can be handled in a usual way. 
>For example, try {...} finally {...} expression and Kotlin use function execute their finalization actions normally when coroutine is cancelled:

意訳込みですが、訳すと以下のとおりです。

> キャンセル可能なSuspend（以降、サスペンド）関数は、キャンセルすると **CancellationException** 例外が発生します。
>例えばtry-finnalyで囲い、キャンセル時に何かしらの終了処理をするには以下のように記述します。

なるほど、確かにキャンセル処理でfinally句が利用できれば、便利ですね。
サンプルコードをみてみます。

```kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    //sampleStart
    val job = launch {
        try {
            repeat(1000) { i ->
                println("I'm sleeping $i ...")
                delay(500L)
            }
        } finally {
            println("I'm running finally")
        }
    }
    delay(1300L) // delay a bit
    println("main: I'm tired of waiting!")
    job.cancelAndJoin() // cancels the job and waits for its completion
    println("main: Now I can quit.")
//sampleEnd    
}
```

実行結果は以下のようになります。

```text
I'm sleeping 0 ...
I'm sleeping 1 ...
I'm sleeping 2 ...
main: I'm tired of waiting!
 **I'm running finally** 
main: Now I can quit.
```

たしかにキャンセルされたときにfinnaly句が実行されています。
このブロック最後の説明文にも以下のように記載されています。

> Both join and cancelAndJoin wait for all the finalization actions to complete, so the example above produces the following output:

訳すと

> joinとcancelAndJoinは、終了処理（finally句）が完了するまで、処理を待ちます。
> 結果として、上記のような結果になります。


# まとめ
このブロックで理解できたことは以下のことだと思います。

* キャンセル可能なサスペンド関数はtry-finallyで終了処理を実装できる
４行で平成の次の元号予想してみた

**「ネットで見たんだけどエンジニアの人がＡＩで元号予想してるんだって！」**
**「もしかして君もこれ作れたりする？」** **「確か君、機械学習と自然言語処理得意だもんね！」**

嫁にキラキラした目で言われたので、「実は末端で雑用してるザコなんです！！なんでもかんでもやってるだけです。」という真実はとてもとても伝えられず、**「楽勝だわ！１０行でできるわ！！」**と言い切ってしまいました。言ってしまったものはちかたないのでさっさと作ってみました。


#実装
```python
def gengoGen():
  # ２文字をランダム抽出
  gengoFile = open('kanji.list')
  gengoList = gengoFile.read()
  gengoFile.close()
  return random.sample(gengoList, 2)
```

**やったー！！実質４行でかけた！！**
**ひょっとして俺！天才じゃない？！？！**

あ、漢字のリストは[青空文庫様](https://www.aozora.gr.jp/kanji_table/)から拝借しました。この場を借りて感謝申し上げます。私と同じことをする ~~バカ~~物好きはいないと思いますが、使うときは全角スペース除去だけお忘れなく。

しかし。
**俺「できた！できた！！１０分でできた！！」**
とサーバー上で適当に動かして見せたところ、
**嫁「何これ？」**と言われてしまいました。
どうもインパクトが足りないらしいので、画像生成をしてみた。

https://www.irasutoya.com/2018/12/blog-post_475.html
いらすとやさんの画像にPILでdraw.textして、
結果
![D1i4Uy0XgAA9G26.png](https://qiita-image-store.s3.amazonaws.com/0/211046/c84a6993-b3da-3569-fda5-3c8c5d0a4a47.png)

さらに「これTwitterでBot作ったら最強じゃない？」と気が付いたので早速作ってみた。
https://twitter.com/gen_go_gen

これで最強の元号予想を30分に1度投稿できるようになったぞ！最強すぎる！！
**10年くらい回してたら正解が出る**ぞ！！たぶん！！きっと！！

**嫁「この漢字どう見ても元号としてあかんやろｗｗｗ」**
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">AIの解析によると次の元号は点痢です！ <a href="https://t.co/ETfdC9h5aD">pic.twitter.com/ETfdC9h5aD</a></p>&mdash; 年号予想AI (@gen_go_gen) <a href="https://twitter.com/gen_go_gen/status/1105928756366135297?ref_src=twsrc%5Etfw">2019年3月13日</a></blockquote>


**嫁「当たる前に【淫】【夢】とか出てネット民のおもちゃにされるほうが絶対早い」**

#ネタばれ
 バラすほどのことすらありませんが、crondで30分に一回起動させてTwitterのAPIたたいてPOSTするだけの程度の低いスクリプトです。常用漢字からランダムで引っ張り出しているだけで、妥当性どころか重複チェックとかNGチェックすら通していません。

 細かいことを考えなくても「これできるかな？」は今は大体誰かがモジュールを作ってるので、非常に実装が楽でした。かかった時間は全部で3時間ほどで、一番時間がかかったのは、Twitter開発者APIの登録と画像の処理でした。簡単なのはわかったので、くだらないネタをどんどん回して作っていって遊びたい次第です。

元ネタの**平成の次の元号を、AIだけで決めさせる物語**
https://qiita.com/youwht/items/0b204c3575c94fc786b8
https://qiita.com/youwht/items/7b1118ecd91bd2e232bb

こちらはとてもすごいのでぜひご一読を。いち自然言語エンジニアとして、当たることを心から願っています。年号は正直嫌な思いしかしていませんし、後出しされて稼働が上がるのもだいぶムカついてるので、これが当たったら相当スカっとします。

私のやつももし**奇跡**で当たったらちやほやしてくださいね！
Pipfile/Pipfile.lockの必要性 -requirements.txtを用いる手法と比較して-

Pythonの開発環境構築にPipenvをつかっていると、ライブラリのバージョン管理のためにPipfile/Pipfile.lock（以下、両者の総称として"Pipfile"と呼びます）が使われます。

一方、Pipfile以前から使われてきたバージョン管理のファイル形式として、requirements.txtがあります。

なぜPipenvでは、既存のrequirements.txtでの管理を捨て、Pipfileを用いたバージョン管理を行うのでしょうか。

requirements.txtでのバージョン管理の問題点についてPipenvの開発者が触れている記事があったので、この内容を元に、Pipfileのメリットについて確認しようと思います。
https://www.kennethreitz.org/essays/a-better-pip-workflow

## tl;dr
Pipfileを用いたバージョン管理は、以下を実現しています。
①全ライブラリのバージョンの固定
②バージョンアップ時の利便性


## requirements.txtを用いたバージョン管理の問題点
requirements.txtの書き方のパターンとしては、主に以下の２つがあります。

1. 最上位のライブラリのみ記載するシンプルな書き方。
2. プロジェクトが依存する全てのライブラリのバージョンを指定する書き方。

### ①シンプルな書き方

```text:requirements.txt
requests[security]
flask
gunicorn==19.4.5
```
シンプルに必要なライブラリ名のみ記載する書き方です。
最低限の環境構築はこれを`$ pip install`すれば十分です。バージョン指定のないライブラリは常に最新のバージョンをインストールする書き方です。
#### 問題点
`$ pip install`の結果インストールされるバージョンが毎回同じであることは全く担保されません。
公開するプロジェクトでは、基本的にはこの書き方ではNGです。

### ②全ライブラリのバージョンを指定する書き方

```text:requirements.txt
cffi==1.5.2
cryptography==1.2.2
enum34==1.1.2
Flask==0.10.1
gunicorn==19.4.5
idna==2.0
ipaddress==1.0.16
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
ndg-httpsclient==0.4.0
pyasn1==0.1.9
pycparser==2.14
pyOpenSSL==0.15.1
requests==2.9.1
six==1.10.0
Werkzeug==0.11.4
```
依存する全てのライブラリのバージョンを記載した、確実な方法です。
`$ pip freeze`で生成されるのはこれですね。
誰がいつどこで`$ pip install`しても、全く同じライブラリがインストールされます。
#### 問題点
このリストを元に、依存関係を解決しつつ全てのライブラリのアップデートをするのは困難です。
一つの方法として、目視で最上位ライブラリを探し出し
`$ pip install requests[security] flask --upgrade`
でアップデートすることもできますが、非効率で、非確実です。

## requirements.txtでのベストプラクティス

そこで元記事で提案しているのが、**①シンプルな書き方**と**②全ライブラリのバージョンを指定する書き方**を併用する運用フローです。

このフローでは、以下の二つのファイルを作成します。

- requirements-to-freeze.txt（①）
- requirements.txt（②）

requirements-to-freeze.txtにはプロジェクトで使用する最上位のライブラリのみを指定し、
`$ pip install -r requirements-to-freeze.txt`
したあと
`$ pip freeze > requirements.txt`
でrequirements.txtを生成します。

ライブラリのアップデートは
`$ pip install -r requirements-to-freeze.txt --update`
コマンドで行い、都度requirements.txtを更新します。

このフローでは、

- ①の問題点であったバージョンが固定されない点
- ②の問題点であったアップデートの煩わしさ

の両方が解決されています。

## requirements.txtじゃだめ？

結論から言うと、上記の運用をすれば「だめ」ではなさそうです。

ですが、上記のフローで運用するならば、Pipfileが便利です。
ちなみに、名前からなんとなく想像できますが、①を担うのがPipfile, ②がPipfile.lockです。
Pipfileの詳細は[こちら](https://github.com/pypa/pipfile)でご確認ください（丸投げ）
プログラミンでfizzbuzz

#概要

プログラミンでfizzbuzzやってみた。

#写真

![image](https://qiita-image-store.s3.amazonaws.com/0/18104/03cac9be-d586-0769-5ae8-e2d0195b0af5.png)


#成果物

http://www.mext.go.jp/programin/share/?share_id=f909b38448adb34138f23a32e7298335


以上。