OmniAICreator/Qiita-1.07M huggingface dataset:
Ansible: ignore_errorsを使用せずに、対象ホスト上でのコマンド実行結果により処理を変更させる

#問題
対象ホスト上でのコマンド実行結果により処理を変更させるには、shellなどでignore_errors: trueとしてコマンドを実行させ、制御対象モジュールにて、whenを用いて実行可否を決める対応が可能だが、

```yml
- shell: ls -d /tmp/abc      # コマンド実行
  register: file_ck          # 実行結果保存
  ignore_errors: true        # コマンドがエラーであってもansible処理を継続させる

- debug: msg="ファイルなし"
  when: file_ck is failed    # 上のコマンド実行結果がfailedならば実行

- debug: msg="ファイルあり"
  when: file_ck is success   # 上のコマンド実行結果がsuccessならば実行
```

しかしこの場合、コマンド実行結果がfailedのケースでは、(意図通りではあるが、)出力がfatal:となり、Ansibleとしての実行が失敗した様にも見えてしまう。

```
TASK [shell] *****************************************************************************
fatal: [ansiblepush-centos-7]: FAILED! => {"changed": true, "cmd": "ls -d /tmp/abc", "delta": "0:00:00.004833", "end": "2018-11-07 03:13:54.603112", "msg": "non-zero return code", "rc": 2, "start": "2018-11-07 03:13:54.598279", "stderr": "ls: /tmp/abc にアクセスできません: そのようなファイルやディレクトリはありません", "stderr_lines": ["ls: /tmp/abc にアクセスできません: そのようなファイルやディレクトリはありません"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [debug] *****************************************************************************
ok: [ansiblepush-centos-7] => {
    "msg": "ファイルなし"
}

TASK [debug] *****************************************************************************
skipping: [ansiblepush-centos-7]
```

#解決
この様な表示を防ぐには、failed_when: falseとして常にsuccessと認識させ、判定はシンプルにrcで確認すれば良い。


```yml

- shell: ls -d /tmp/abc
  register: file_ck
  failed_when: false     # 常にsuccessと認識させる。rcなどの属性は変更しない。

#- debug: var=file_ck    # file_ckの内容詳細を表示するにはコメントイン

- debug: msg="ファイルなし"
  when: file_ck.rc != 0  # failedとはならないので、file_ck is failed では識別できない。

- debug: msg="ファイルあり"
  when: file_ck.rc == 0
```

```
TASK [shell] *****************************************************************************
changed: [ansiblepush-centos-7]

TASK [debug] *****************************************************************************
ok: [ansiblepush-centos-7] => {
    "msg": "ファイルなし"
}

TASK [debug] *****************************************************************************
skipping: [ansiblepush-centos-7]
```

#補足
なお、shellなどを使用した状況確認時には、changedとしてカウントされる。
shellなどによる実行内容が変更を行わないことが明らかならば、合わせてchanged_when: falseをつけてchangedとカウントさせない様にしておけば良いでしょう。


```yml

- shell: ls -d /tmp/abc
  register: file_ck
  failed_when: false
  changed_when: false  # これでchangedとカウントされない

- debug: msg="ファイルなし"
  when: file_ck.rc != 0

- debug: msg="ファイルあり"
  when: file_ck.rc == 0
```


```
TASK [shell] *****************************************************************************
ok: [ansiblepush-centos-7]  # changed:から変更されている

TASK [debug] *****************************************************************************
ok: [ansiblepush-centos-7] => {
    "msg": "ファイルなし"
}

TASK [debug] *****************************************************************************
skipping: [ansiblepush-centos-7]
```

# 追記

- もう少し頑張ってみる例
    - Ansible: shellモジュールに冪等性および正しいchanged結果を持たせる為のロジック例
    - https://qiita.com/hiroyuki_onodera/items/e2cf26d02f5bda85cd4d
pythonで他の.pyプログラムを実行する

yobu.py
yobareru.py
があったとして、yobu.pyを実行すると、yobareru.pyの中身を出してくれるみたいな。そんなやつ。


# 呼ばれる.py
まずは呼ばれる中身を書いていきます。

```yobareru.py
def test():
    print('Hello World!')

if __name__ == '__main__':#直接yobareru.pyを実行した時だけ、def test()を実行する
    test()

print('モジュール名：{}'.format(__name__))  #実行したモジュール名を表示する
```
直接このyobareru.pyを実行した場合は・・・
`python yobareru.py`
↓のようにでるはず。

```
Hello World!
モジュール名：__main__
```


#呼ぶ.py
呼ぶやつと呼ばれるやつは、同じ階層に入れておいてくださいね。

```yobu.py
import yobareru
```
一行だけかいて実行してみましょう。
`python yobu.py`

```
モジュール名:yobareru
```
testの中身は実行されず、print文だけ表示されました。
しかも実行したのはyobareruなので、モジュール名が変わっています。

#def testを呼び出す
では、yobu.pyからyobareru.pyのdef関数を実行しましょう。

```yobu.py
import yobareru

yobareru.test()
```
外部ファイルの関数を実行するときは、
まずインポートして
次に インポートファイル.関数名()
で実行できます。

`python yobu.py`

```
モジュール名：yobareru
Hello World!
```
まずインポートで必ず出る、yobareru.pyのprint文が最初に表示され（モジュール名:yobareru です）
次に、yobareru.test()で指定した　ハローワールドが表示されます。



なんとなくわかってきたような気がしないでもない。
OV5642のSCCBメモ


使ったカメラ
[ＯＶ５６４２使用５００万画素カメラ　Ｍ１２レンズ付き　Ｂ００２０: カメラ 秋月電子通商-電子部品・ネット通販](http://akizukidenshi.com/catalog/g/gM-13198/)

使ったボード
[ＳＴＭ３２　Ｎｕｃｌｅｏ　Ｂｏａｒｄ　ＳＴＭ３２Ｆ４４６ＲＥ: マイコン関連 秋月電子通商-電子部品・ネット通販](http://akizukidenshi.com/catalog/g/gM-10176/)

SCCBはI2Cに似ているが、今回はソフトで実装した。
バスは3.3kΩで吊ってる(今回使ったカメラにはプルアップは実装されていないっぽい)。

データシートとか読んでないので間違ったこと書いてる可能性大。

***

基本的に、ACKビットはSCKの立ち下がりエッジで開放される。

![2018-11-07_11-44.png](https://qiita-image-store.s3.amazonaws.com/0/264452/bdfea5d0-fc99-228f-d9f9-b53bf673ad99.png)


***

時々ACKビットが終わってもSDAが開放されず、Lowに固定される場合がある。
その場合、もう1クロック送ってやると開放される。
ある程度の時間待っても開放されないし、追加クロックではほぼ確実に開放されるので、、OV側でACKbitのクロックのエッジを取り逃してる?

![2018-11-07_11-45.png](https://qiita-image-store.s3.amazonaws.com/0/264452/fce512a6-acc3-6292-83ef-b8043455567e.png)

当然、次の1バイトは破壊されるので、再送が必要(ACKクロックを取り逃してるだけなら、次のデータを送れば受け取ってくれる? 未確認)。

***

連続して大量のレジスタを書き換える場合は、なんとなく、1msec周期くらい開けて転送してやると成功率が高い気がする。

![2018-11-07_11-46.png](https://qiita-image-store.s3.amazonaws.com/0/264452/59ffcfaf-67f3-be45-d8ae-071373c70456.png)

***

スレーブアドレスやデータの途中でNACKが帰ることがある。
適当な時間(5msec以上を目安に)開けて再送してやると成功する場合が高い。

![2018-11-07_11-47.png](https://qiita-image-store.s3.amazonaws.com/0/264452/055b8f63-3af7-7eec-418b-505ffb86b326.png)

複数回連続でNACKを返すときもある。

***

コンフィグでNACKやACK開放不良があったときは初期設定がうまくできない場合がある(破壊された画像が送られてくる)。
NACKの場合は比較的大丈夫な場合が多い気がする。
NACKやACK開放不良が1回もなくても(=すべてのパラメータが確実に送信できていても)破損画像が送られてくる場合がある。
パラメータ転送以外の問題?

***

STM32F446REは128KiBのRAMを持っている。
RTOSでDCMIで受けてPCに転送する、といった簡単な処理の場合、画像の保存に使えるのは100KiBくらい。
JPEGで転送した場合、VGAだと画像サイズは30KiB程度で、100KiBあれば余裕で入る。QVGAは100KiBだとまず足りない。
446RE単体で使う場合、VGAが限界かな? JPEGカメラっぽいモジュールを作るなら、FMCを積んだチップに外部RAMを接続する必要がある。
おとなしくフレームバッファ付きを買ったほうが楽そう。。
[Docker] awslogs-datetime-format の指定方法に注意

# [Docker] `awslogs-datetime-format` の指定方法に注意

## 背景
- Dockerの `awslogs` ログドライバでは，`awslogs-datetime-format` オプションがあり，指定した形式の日時がログのある行に含まれていれば，続く行も同じ日時とみなされる
- Stacktrace のようにログレコードが複数行にわたる場合，ログレコードが細分化されずに一つにまとまるので便利である

## 状況
- AWS ECS のタスク定義 JSON において，`awslogs-datetime-format` を以下のように `[日時]` となるように指定すると，タスク起動に失敗した

```json
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "AWSLOGS_GROUP_NAME",
          "awslogs-datetime-format": "[%Y-%m-%d %H:%M:%S]",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "PREFIX"
        }
      }
```

## 同様の事例
- `docker run` コマンドで `--log-opt` を指定して起動するとき，以下のように `awslogs-datetime-format` を指定すると，コンテナの立ち上げに失敗する
  - [Bountysource](https://www.bountysource.com/issues/53969952-awslogs-datetime-format)

``` bash
$ docker run --log-driver=awslogs \
             --log-opt awslogs-region=us-east-1 \
             --log-opt awslogs-group=myLogGroup \
             --log-opt awslogs-datetime-format='[%b %d, %Y %H:%M:%S]' \
             centos:latest /bin/bash
docker: Error response from daemon: failed to initialize logging driver: awslogs could not parse multiline pattern key "[\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1,2][0-9]|3[0,1])T(?:[0,1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]+00:00]": error parsing regexp: invalid character class range: `}-(`.
```

## 原因
- Docker の awslogs ログドライバにおいて `awslogs-datetime-format` オプションの Python `strftime` 形式の値は，正規表現に書き換えられる．その際，エスケープされていない `[ ]` は正規表現と解釈されて失敗する
  - [Issue with awslogs-datetime-format · Issue #1192 · aws/amazon-ecs-agent · GitHub](https://github.com/aws/amazon-ecs-agent/issues/1192)

## 解決方法
- `[ ]` を `\[ \]` にエスケープする

``` bash
$ docker run --log-driver=awslogs \
             --log-opt awslogs-region=us-east-1 \
             --log-opt awslogs-group=myLogGroup \
             --log-opt awslogs-datetime-format='\[%b %d, %Y %H:%M:%S\]' \
             centos:latest /bin/bash
```

- JSON ではさらに `\` を `\\` にエスケープしなければならないため，`\[ \]` は `\\[ \\]` とする．最終的に以下のようになる

```json
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "AWSLOGS_GROUP_NAME",
          "awslogs-datetime-format": "\\[%Y-%m-%d %H:%M:%S\\]",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "PREFIX"
        }
      }
```
スクロールに合わせて背景色がじわじわ切り替わるPageViewControllerの実装

![GIF image-41F1D5F44551-1.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/ecff4d94-86e2-60bd-d5c2-3dc0760cbd60.gif)

Snapchatっぽく、PageViewControllerに合わせて背景のalphaが変わるやつをやってみました。
ちなみに後ろにCameraのViewControllerを表示してその上にPageViewControllerを置いています。

## ①PageVCをUIScrollViewDelegateに準拠させる

```swift
    override func viewDidLoad() {
        super.viewDidLoad()
        
        for subView in self.view.subviews {
            if let scrollView = subView as? UIScrollView {
                scrollView.delegate = self
            }
        }
    }
```

## ②UIScrollViewDelegateでスクロール位置を把握し、alphaを変化させる

```swift
extension PageViewController: UIScrollViewDelegate {
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let offset = scrollView.contentOffset.x
        let alpha = (offset - screenWidth) / screenWidth
        
        switch currentNumber {
        case .first:
            self.view.backgroundColor = UIColor.yellow.withAlphaComponent(alpha)
        case .second:
            let reverseAlpha = 1.0 + alpha
            self.view.backgroundColor = UIColor.yellow.withAlphaComponent(reverseAlpha)
        }
    }
}
```

## 全体のコードはこちら
https://gist.github.com/kboy-silvergym/8103785e210486bc4485b72409373561
Swift4でタイムスタンプをString型で取得する方法

```swift

let timeInterval = NSDate().timeIntervalSince1970
let myTimeInterval = TimeInterval(timeInterval)
let time = NSDate(timeIntervalSince1970: TimeInterval(myTimeInterval))
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMddHHmmss"
let timestamp = formatter.string(from: time as Date)
```
GitHubの自分が所有しているリポジトリをcURLで取得する

[GitHubのAPI](https://developer.github.com/v3/)を使います。


# TOKENの取得
[こちら](https://github.com/settings/tokens)から取得します。

<img width="1158" alt="Screen Shot 2018-11-07 at 11.51.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/3d0f571a-e70a-c357-2fe9-4e1ccc8bf330.png">

権限は`repo`を出しておきます。（inviteとかいらないかも）

<img width="922" alt="Screen Shot 2018-11-07 at 11.51.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/b630fe2d-8227-f8ac-cdd2-d1bbcb128dc2.png">



取得したTOKENとGitHubユーザー名を環境変数に設定しておきます。

```bash
$ export TOKEN=xxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$ export USER=yousan
```

# 実行

```
$ curl -s -u $USER:$TOKEN "https://api.github.com/user/repos?per_page=100&visibility=all&page=1"
```

こんな感じで出てきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47327/6b396f9f-ccbc-c704-1ada-fdf16d0a76d3.png)

# オプション

指定できるオプションです。

| オプション名 | 説明 |
|-----|-----|
| per_page | 一回当たりの取得件数。100が最大値。 |
| visibility | パブリック(public)、プライベート(private)リポジトリを指定。両方はall。 |
| page | ペジネーション。1以上の数字で指定する。 |

# jq
出力結果はjqを入れておくと見やすいです。

参考: [jq コマンドを使う日常のご紹介](https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af)


## htmlのURL取得
リポジトリのURLを取得する絞り込み。

```bash
$ curl -s -u $USER:$TOKEN "https://api.github.com/user/repos?page=1&per_page=1000&visibility=public" | jq '.[].html_url'
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47327/039e823f-39a8-1695-e65d-2c0bab0e1e47.png)

`grep`と組み合わせれば簡易的な検索ができます。

## クォーテーションなし

```bash
$ curl -s  -u $USER:$TOKEN "https://api.github.com/user/repos?page=1&per_page=1000&visibility=public" | jq -r '.[].html_url' | head -n 20
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47327/66e6387e-7aa8-db08-b7e7-9eaebb189e88.png)

## SSHのURL取得

自分のリポジトリを手元にクローンして作業ときはSSHのURLが便利です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47327/9aeade31-4771-7cf2-aaa1-3b3416e1f010.png)

## 検索してクローン
応用して検索してクローンします。

```bash
git clone $(curl -s  -u $USER:$TOKEN "https://api.github.com/user/repos?page=1&per_page=1000&visibility=public" | jq -r '.[].ssh_url' | grep factorio)
```

ペジネーションと複数引っかかってしまうことに注意が必要です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47327/1a1c7622-8d7e-1bad-1533-c644cdb2f20a.png)

# その他
GitHubに限定ですが[hubコマンド](https://github.com/github/hub)がすごく便利です。
参考: [GitHubユーザーのためのhubコマンド](https://qiita.com/yaotti/items/a4a7f3f9a38d7d3415e3)

そこに検索が加わるとすごく便利だなぁと思ってます。
https://github.com/github/hub/issues/833


というかすでに良い感じのパッケージがあるっぽかったです。
[コマンドラインからgithubを検索してgit cloneをする with ghs, peco and ghq](https://qiita.com/sonatard/items/c11063cd3671c07b6e0a)
Dropzone.jsで複数ファイルアップロード後、削除したいファイルを指定したい

小一時間ほど調べた。
時間が勿体ないと思ったので書いておく。

```html:index.blade.php
<script type="text/javascript">
$(function(){
  // 初期設定とか
  Dropzone.autoDiscover = false;
  Dropzone.options.myAwesomeDropzone = {
    paramName : "file",
    paralleUploads : 1,
    acceptedFiles : 'image/*',
    maxFiles: 6,
    maxFilesize: 3,
    dictFileTooBig: "ファイルが大きすぎます。(@{{filesize}}MB). 最大サイズ: @{{maxFilesize}}MB.",
    dictInvalidFileType: "画像ファイルのみアップロードが可能です。",
    dictMaxFilesExceeded: "ファイルは6ファイルまで追加が可能です。",
    dictDefaultMessage: "ここへファイルをドラッグ＆ドロップするとアップロードされます。<br>最大6ファイルまでアップ可能です。<br><br>（もしくはここをクリックするとファイル選択ウインドウが表示されますのでそこで選択してもアップ可能です）"
  };

  // ここからがタイトルに書いた内容になる。
  var myDropzone = new Dropzone('div#my-dropzone', {
    url : "http://hogehoge.com/upload.php",
    addRemoveLinks: true,
    dictRemoveFile: "削除",
  }).on("success", function(file, serverResponse){
    // ファイルを受け取るphp側では、アップロードされたファイルの保存名を返すようにしておく
    // するとserverResponseにファイルの名前が返ってくる。
    console.log(serverResponse); // デバッグ用
    file.previewElement.querySelector("img").alt = serverResponse; // imgタグのalt属性にサーバから受け取ったファイル名を持たせておく
  }).on("removedfile", function(file){
    // 削除ボタンが押された時
    console.log( file.previewElement.querySelector("img").alt ); // 削除対象のファイル名が取得出来る
    $.ajax(...);//あとは非同期でファイル名を指定して削除するサーバサイドプログラムへリクエスト
  });
});
</script>
```
【備忘録】オフライン環境で Windows のデジタル証明書を更新する

オフライン環境とかでデジタル証明書が更新されず、アプリケーション側のチェックで引っかかるということがある
たとえば[この現象](http://support.embarcadero.com/jp/article/43655)ね

この様な場合、インターネットに接続できる PC から証明書ストア形式 (.SST) ファイルを作成して、そのファイルをオフラインの PC にインポートするという方法で更新することができます

## デジタル証明書の更新手順

##### 1. インターネットに接続できる PC に管理者としてログインします
##### 2. 更新プログラムのダウンロードとその適用を行います
MS のページ
https://support.microsoft.com/en-us/help/2813430/an-update-is-available-that-enables-administrators-to-update-trusted-a
より、該当する更新プログラムをダウンロードして適用します
##### 3. 証明書ストア形式ファイルを作成します
コマンドプロンプトを開き、以下のコマンドを実行します

```
　　CertUtil -generateSSTFromWU <任意のファイル名>.SST
```

このコマンドは、Windows Update サイトにある最新のリストから、Microsoft シリアル化された証明書ストア形式 (.SST) ファイルを作成します
##### 4. 作成した .SST ファイルをオフラインの PC へコピーします
##### 5. マイクロソフト管理コンソールを起動します
オフラインの PC 側で、[スタート] から、[プログラムとファイル検索] で、"mmc" と入力し、表示された「mmc.exe」をクリックします
起動した「マイクロソフト管理コンソール」の画面
![CTL01.png](https://qiita-image-store.s3.amazonaws.com/0/164551/01ca7cc2-0eba-75ee-2f7a-17fbe9e55482.png)

##### 6. [ファイル] - [スナップインの追加と削除] を選択します
![CTL02.png](https://qiita-image-store.s3.amazonaws.com/0/164551/a626876a-d1e4-3691-4ce2-fe786352df2e.png)

##### 7. [証明書] を選択し、[追加] をクリックします
![CTL03.png](https://qiita-image-store.s3.amazonaws.com/0/164551/ca09d1eb-c2a3-e5ce-4223-f251605e86a6.png)

##### 8. 証明書スナップインのダイアログで、"コンピューター アカウント" を選択して、[次へ] をクリックします
![CTL04.png](https://qiita-image-store.s3.amazonaws.com/0/164551/96dcb4a9-3bc2-651e-f538-b3c3809eee08.png)

##### 9. コンピュータの選択のダイアログで、"ローカルコンピューター" を選択して [完了] をクリックします
![CTL05.png](https://qiita-image-store.s3.amazonaws.com/0/164551/ed176fa9-20df-54ef-a9dc-92821fa7f846.png)

##### 10. スナップインの追加と削除の画面に設定した内容が反映されているのを確認し、[OK] をクリックします
![CTL06.png](https://qiita-image-store.s3.amazonaws.com/0/164551/96534cba-6f4a-bcb0-bab5-a85609f84549.png)
この後コンソール画面に戻ります

##### 11. インポートを行います
コンソール画面の左側ペインのツリーから、[証明書 (ローカル コンピューター)] - [信頼されたルート証明機関] を右クリックし、[すべてのタスク] - [インポート] をクリックします
![CTL07.png](https://qiita-image-store.s3.amazonaws.com/0/164551/b2950500-763d-4448-f0d4-c7594a45f275.png)

##### 12. [証明書のインポート ウィザードの開始] 画面が表示されますので、[次へ] をクリックします
![CTL08.png](https://qiita-image-store.s3.amazonaws.com/0/164551/2f1ecc59-e9e6-e201-9677-d3629f3100c7.png)

##### 13. [インポートする証明書ファイル] にて、[参照] ボタンをクリックして、コピーした .SST ファイルを指定し、[次へ] をクリックします
![CTL09.png](https://qiita-image-store.s3.amazonaws.com/0/164551/7661ef0b-9f22-5302-134e-231da7134d10.png)

##### 14. [証明書ストア] で、[証明書をすべて次のストアに配置する] - [信頼されたルート証明機関] となっていることを確認し、[次へ] をクリックします
![CTL10.png](https://qiita-image-store.s3.amazonaws.com/0/164551/d5d8afab-f4b8-1a39-2b9d-53e0a2a2ea4c.png)

##### 15. [証明書のインポート ウィザードの完了] にて、[完了] をクリックします
![CTL11.png](https://qiita-image-store.s3.amazonaws.com/0/164551/342b96f2-8fb0-f5a9-8971-ca65c0770d56.png)

## 参考
MS の記事
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn265983(v=ws.11)

## 追記
Windows 7 では [certlm.msc](https://docs.microsoft.com/ja-jp/dotnet/framework/tools/certmgr-exe-certificate-manager-tool) が無いのです (Visual Studio をインストールしている場合を除く)
S3に保存した大量のデータをAthenaで触ってみた

## やったこと

[この記事](https://qiita.com/naoko_s/items/d97f85d42b8bb5c77037)で作った電力予測システムをしばらく触っていなかったのでどれくらい学習データがたまったのかなぁ...とふと思いせっかくだしAthenaで見てみよう！ということでAthenaを触ってみました。

## ファイルの構成

現在以下のような構成で学習データは保存されています

```
BUCKET_NAME
  └ electric-predict
    └ train_data
      └ train_data.csv
```

## テーブルを作成する

コンソールのデザインが変わっている可能性があるので参考までに
(なぜか日本語のコンソールが最初でなくて一旦英語設定にして日本語設定に戻したら日本語で表示されました...)

<img width="329" alt="athena_dashboard_make_database.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/eb67d43f-3259-6ce3-cea7-091e73ce2b6a.png">

Athenaのダッシュボードを開いて左にある`テーブルの作成`を選択します

<img width="393" alt="athena_from_s3.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/87e3639a-1486-18ab-90ce-0f98d55b59a6.png">

上の画像のような選択肢が出てきます。今回はS3にためているデータを使うので`from S3 bucket data`を選択

<img width="1066" alt="athena_name_and_place.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/1be1fc52-147c-0823-91c4-9cda86d87ca0.png">


必要事項を記入します

<img width="700" alt="athena_csv.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/68b13050-2b9e-60a9-4c07-fdca2de24584.png">

今回はcsvを使用しているのでcsvにチェックをつけます

<img width="895" alt="athena_retsu.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/cc17094b-7ec1-3b48-1784-bd69a1a5d0b0.png">

今回はcsvのヘッダにある`MONTH`を列名として登録します。
パーティションの追加は今回必要ないのでこれでテーブルを作成できます。

<img width="594" alt="make_table_query.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/48e7d0e3-bd8d-4755-bf30-b6823bc68bf2.png">

こんな感じでクエリを作成してくれます。
このクエリを実行したらテーブルが作成されます。

## 件数を数えてみる

コンソール上でAthenaを使おうと思ったら基本的にコンソール上にあるクエリエディタにクエリを書いて投げるだけでいいみたいです。

まずは件数を数えてみました

```
select count(*) from sampledb.hoge;
```

上記のクエリをクエリエディタに入力して実行すると...

<img width="448" alt="athena_record_val.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/b9545159-e8b4-17b6-400f-ba89b6f99d3d.png">

わずか約1.6秒でレスポンスが！！！

どうやら16273件データを蓄積できていたようです。

お恥ずかしいことに初期の件数を覚えていないのですが...

順調に蓄積できていそう...

何故かファイルが残っていた2018年5月1日の学習ファイルには14760件のデータがあったので無事にシステムは動いている。と信じている...

クエリの書き方に関しては大学時代に講義で習った気がするけど殆ど覚えていないので[AWSのドキュメント](https://docs.aws.amazon.com/ja_jp/athena/latest/ug/functions-operators-reference-section.html)を調べて書いてみました。

```
select count(*) from sampledb.hoge where MONTH='1';
```

ためしに1月のデータは何件あるか調べてみました。

<img width="428" alt="athena_jan_count.png" src="https://qiita-image-store.s3.amazonaws.com/0/192406/03039807-907b-0d49-1c6b-c4c623ee45f4.png">

なるほど...
これも1.3秒ほどで出力されたしすごいな...

クエリの書き方を勉強するともっと便利に使えそう...

## まとめ

会社の先輩に教えてもらって使ってみたのですが初期設定がすごく簡単だしレスポンス早いし便利だし、
dynamoDBしか触ったことのないぺーぺーからしたらクエリをちょちょっと書いて件数が2秒弱で出てきた瞬間感動しましたwww
データベースの設計とかクエリの書き方とかに興味をもちました。
(このあとDQLの存在も教えていただき更に感動したのはまた別の話...)
Emacsのフォントサイズを変更する

## 概要

「emacs フォントサイズ変更」とかでググっても，関数がどうこうとか，GUIがどうこうとか，ややこしい話が上位に出てきてしまい，簡単にフォントサイズを変更する方法にすぐたどり着けなかったので，一番簡単と思われる方法を忘れないようにメモしておきます．

## 方法

emacsの設定ファイルを開きます．

```console
$ emacs ~/.emacs.d/init.el
```

以下を追記します．

```common-lisp
(add-to-list 'default-frame-alist
                       '(font . "DejaVu Sans Mono-12"))
```

以上でフォントサイズが12ptに変更されます．
もちろん数字のところを変えると他のサイズに変更できます．
PostgreSQL で Bulk Upsert

PostgreSQL 9.5 から `ON CONFLICT` が導入されて Upsert (Insert or Update) ができるようになったものの、<del>複数行まとめてやることはできなかった。</del>

**[2020.08 追記]**
コメントで指摘いただいたので追記。
`ON CONFLICT ... DO UPDATE` 内で使える `EXCLUDED` 句を使えば `VALUES` に複数行を指定して Bulk Upsert ができるらしい。(未検証)
**[追記おわり]**

`ON CONFLICT` を使わなくても、CTE を使うことで以下のように Bulk Upsert することができるっぽい。

``` SQL
WITH
-- write the new values
n(ip,visits,clicks) AS (
  VALUES ('192.168.1.1',2,12),
         ('192.168.1.2',6,18),
         ('192.168.1.3',3,4)
),
-- update existing rows
upsert AS (
  UPDATE page_views o
  SET visits=n.visits, clicks=n.clicks
  FROM n WHERE o.ip = n.ip
  RETURNING o.ip
)
-- insert missing rows
INSERT INTO page_views (ip,visits,clicks)
SELECT n.ip, n.visits, n.clicks FROM n
WHERE n.ip NOT IN (
  SELECT ip FROM upsert
)
```

**※ SQL は以下のページからの引用**
[Faster data updates with CartoDB — CARTO Blog](https://carto.com/blog/faster-data-updates-with-cartodb/)


## Python で Bulk Upsert
Python + Pandas + asyncpg で CSV ファイルの内容をそのまま PostgreSQL に Bulk Upsert するやつを書いてみた。

以下注意点。

- Pandas DataFrame のカラム名と PostgreSQL テーブルのカラム名が完全に一致している必要がある
- 複合ユニークキーを持つテーブルに対応させるために最後の INSERT 部分が相関サブクエリになっているので、大きなデータに対して実行するとものすごく遅い

``` python
import asyncio
import asyncpg
import pandas as pd


async def bulk_upsert(conn, df: pd.DataFrame, table: str, key_columns: list):
    assert len(df) > 0
    assert len(key_columns) > 0
    value_columns = df.iloc[:0].drop(key_columns, axis=1).columns.to_list()
    assert len(value_columns) > 0
    n = len(df.columns)
    statements = ','.join(['(' + ','.join(['$' + str(i * n + j + 1) for j in range(n)]) + ')' for i in range(len(df))])
    query = f"""
        WITH
        -- write the new values
        n({','.join(df.columns)}) AS (VALUES {statements}),
        -- update existing rows
        upsert AS (
          UPDATE {table} AS o
          SET {', '.join([f'{col}=n.{col}' for col in value_columns])}
          FROM n
          WHERE {' AND '.join([f'o.{col} = n.{col}' for col in key_columns])}
          RETURNING {', '.join([f'o.{col}' for col in key_columns])}
        )
        -- insert missing rows
        INSERT INTO {table} ({', '.join(df.columns)})
        SELECT {', '.join([f'n.{col}' for col in df.columns])}
        FROM n
        WHERE (
          SELECT COUNT(1)
          FROM upsert AS u
          WHERE {' AND '.join([f'u.{col} = n.{col}' for col in key_columns])}
        ) = 0
        """
    values = sum([list(row) for row in df.values], [])  # flatten
    await conn.execute(query, *values)


async def main():
    conn = await asyncpg.connect('postgresql://postgres@localhost/')
    await bulk_upsert(conn, pd.read_csv('users.csv'), 'users', ['id'])
    await conn.close()


if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())
```
KarmaとJasmineでAngular6の単体テスト環境を構築し、テストを行う際にChrome have not captured in 6000 ms, killingエラー


環境:Windows10 64bit、Angular6インストール済み

Angular6がインストールされていると、同時にKarmaやJasmineはインストールされているので、
基本的にはGoogle Chromeさえインストールすれば直ぐに単体テストに入れる。
単にコマンドプロンプトより
`ng test`と書けばChromeが起動し、Jasmineがテスト結果を表示してくれるはずだった。
しかし私の場合、タイトルに記載したようなエラーが出て、テスト結果が一向に表示されなかった。

犯人はProxy。
インターネットのプロパティを開き、「ローカルアドレスにはプロクシサーバを使用しない」をチェックするだけで解決。
特定のプロセスの所属するdockerコンテナIDを調べる 


```bash
$ docker ps | tail  -n +2 | awk '{print $1}' | xargs docker inspect -f '{{ .State.Pid }} {{ .Config.Hostname }}`
```
これでPIDとDockerコンテナ(`.Config.Hostname` == コンテナ名でいいのか？) の一覧が出るので、
気になったPIDでgrepをかければコンテナIDがわかる。

ちなみに、`tail` は `tail -n +<N>` で`N` 行目以降をプリントするらしい。初めて知った。
FPDFでheaders already sent byとwarningが出てoutput()できない時の解決策

![スクリーンショット 2018-11-07 11.16.54.png](https://qiita-image-store.s3.amazonaws.com/0/247390/e1675c48-143c-b425-baea-71c2a1cc81b0.png)

こんなエラーが出た時です。

#早速結論
下記を変更します


```php:fpdf.php
function FPDF($orientation='P', $unit='mm', $format='A4')
{
```

```php:fpdf.php
function __construct($orientation='P', $unit='mm', $format='A4')
{
```


#理由
Depressedがキーワードです。
FPDFのコンストラクタは、「クラス名と同名のメソッドは、コンストラクタとして扱う」という古いルールで書かれています。
それが今回引っかかったようです。新しい書き方に直してあげたところ正常に動作しました。
AWS EC2インスタンスからのスクレイピングがサイトからブロックされた話

ruby mechanizeを用いて
AWS　EC2インスタンスから某ファッションサイトにスクレイピングを実行したところ、

```
     9: from /usr/local/lib/ruby/2.5.0/net/http.rb:443:in `get_print'
     8: from /usr/local/lib/ruby/2.5.0/net/http.rb:485:in `get_response'
     7: from /usr/local/lib/ruby/2.5.0/net/http.rb:609:in `start'
     6: from /usr/local/lib/ruby/2.5.0/net/http.rb:909:in `start'
     5: from /usr/local/lib/ruby/2.5.0/net/http.rb:920:in `do_start'
     4: from /usr/local/lib/ruby/2.5.0/net/http.rb:935:in `connect'
     3: from /usr/local/lib/ruby/2.5.0/timeout.rb:103:in `timeout'
     2: from /usr/local/lib/ruby/2.5.0/net/http.rb:937:in `block in connect'
     1: from /usr/local/lib/ruby/2.5.0/net/http.rb:937:in `open'
/usr/local/lib/ruby/2.5.0/net/http.rb:937:in `initialize': execution expired (Net::OpenTimeout)
```

のようなエラーで処理が止まってしまった。これはどうやら調べてみると

https://webbigdata.jp/what-is-bigdata/page-207

の記事[4]に書いてあるように、
>大規模なサイトは、クローラーによるデータ収集が出来ないようにＩＰアドレスによる制限をかけてくる場合があります。

IP制限がかかっていると推測される。

他の方からの話を聞くと、

- heroku
- ec2

でのアクセスがブロックされているのは確認できた。もしかすると他のホスティングサービスでもブロックされているかもしれないとのこと

なのでもしスクレイピングが集中しているサイトだと、こういった制限がかけられているかもしれない。


疑問なところ
-
疑問点が一つあり、EC2のパブリックIP（Elastic IP）を確認したところ

```
52.194.435.49
124.113.457.237
54.924.8425.4222
```

のようにかなりばらけていることが確認できた。

こんなにばらけているのなら、サイト側はどのようにして
`ホスティングサービスからのアクセスなのか、他の一般ユーザーからのアクセスなのか`を識別しているのだろうか、わかる方がいらっしゃったら是非教えて欲しいです。
サーバー上にtensorflow用の仮想環境を構築する

# はじめに

ワケあって今まで使っていたサーバー上に環境を立てなくちゃいけなくなってハマり，相当な時間を無駄にしたので，自分への戒めと今後のためにメモ．~~(こういうハマり方する度に最上流に行きたくなる．)~~
ゴールは，サーバーのjupyter notebookをlocalのブラウザで開き，その上でtensorflowがきちんと動く環境を作ること．
今回やったことは，
- virtualenvで仮想環境構築
- numpyのversion上げ
- pyenvでpython2.7.9導入
- jupyter notebook起動時のoption付け

# 環境
色々試した後の環境(試す前の環境をメモするの忘れた)

ubuntu 14.04
python 2.7.6
tensorflow-gpu 1.2.1
numpy 1.15.4

# 本題

`import tensorflow`したら以下のエラーが出た．

    `RuntimeError: module compiled against API version 0xa but this version of numpy is 0x9`

    `ImportError: Traceback (most recent call last):
      File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/pywrap_tensorflow.py", line 41, in <module>
    from tensorflow.python.pywrap_tensorflow_internal import *
      File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/pywrap_tensorflow_internal.py", line 28, in <module>
    _pywrap_tensorflow_internal = swig_import_helper()
      File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/pywrap_tensorflow_internal.py", line 24, in swig_import_helper
    _mod = imp.load_module('_pywrap_tensorflow_internal', fp, pathname, description)
    ImportError: numpy.core.multiarray failed to import


    Failed to load the native TensorFlow runtime.

    See https://www.tensorflow.org/install/install_sources#common_installation_problems

    for some common reasons and solutions.  Include the entire stack trace
    above this error message when asking for help.`

URLが書いてあるが，ここ見てもよくわからない．
どうやらtensorflowが古いversionのnumpyを見に行ってるらしい．numpyなんかそう何個も入れないんだけどなぁ...
numpyのversionあげないとだが，OS管理下のnumpyをいじるのは怖いし，そもそも自分はこのサーバーのsudoer権限を持っていないので，virtualenvで仮想環境を立ててnumpyを更新することにした．

# pyenvでpython2.7.9を入れる
早速virtualenvで仮想環境作ってnumpyのversionをあげたいところだが，**python2.7.9以降でないとjupyter notebookが入らない**ので，まずはpyenvでpython2.7.9の環境を作る．

そもそもpyenvが入ってなかった(笑)ので，
`curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash`
でpyenvをインストールする．
あとは`pyenv install 2.7.9`でpython 2.7.9を入れて，`pyenv local 2.7.9`をすればpython 2.7.9の環境に入れる．

# virtualenvで仮想環境構築
pythonの環境が整ったので，ようやく仮想環境作りに入る．
なんのことはないが，
`virtualenv ENVNAME --no-site-package --python=PYTHON_PATH`
で仮想環境を構築した．
この時指定するPYTHON_PATHだが，前述したように**2.7.9以降でないとjupyter notebookが`pip install`できない**ので，それ以前の場合はまずpyenvで2.7.9以上のpythonを入れて，そのPATHである`~/.pyenv/versions/2.7.9/bin/python`を指定する．
直下に`./ENVNAME`ディレクトリが作成されているはずなので，`source ./ENVNAME/bin/activate`で仮想環境に入る．

あとは`pip install tensorflow`すればnumpyは一緒にインストールされるし，`pip install jupyter`も問題なく動くはず．

# サーバーのjupyter notebookに，localからアクセス
jupyter notebook起動時にちょっとしたオプションを付けないとうまく動いてくれなかった．
以前，ここ([分析サーバーでjupyter notebookを起動してローカルからアクセス](https://qiita.com/shinochin/items/23e78499bc78b90fbc62))を参考にポートフォワーディングの設定をしたので，
サーバー上で`jupyter notebook --ip localhost --port 8888`をして，localhostの自分が設定したportにアクセスすれば，jupyter notebookを触れる．
port番号は適宜書き換える．

# おわりに
すんなり環境構築できたみたいに見えるが，実際はいろんなページ飛び回ったり，仮想環境作った後で古いpythonだとjupyterが入らないことに気づいてやり直したりで，丸一日かかってしまった．
なんとか動くようにはなったが，最初のエラーがいきなり出た原因は不明なままなのでどうも腑に落ちない．
きちんと仮想環境整えなきゃなぁ思いつつ，バグが出る予感しかしないので，できれば~~一生~~やりたくない．
でもこのままだと，いずれ今回のような不具合が出るし，思い切ってやってしまおうか...
C言語で論理演算子とif構文とfor構文を学習します。

こんにちは。

今日は、以前より勉強していたC言語の学習本「やさしいC」の第５章と

第６章を勉強していきます。

開発環境は、gccです。

OSはCentOS7です。

```
#include <stdio.h>
int main
{

char res;

printf("あなたは男性ですか\n");
printf("printf("YまたはNを入力してください。\n");

res = getchar();

if(res == 'Y' || res == 'y'){
printf("あなたは男性ですね\n");
}else if(res == 'N' || res == 'n'){
printf("あなたは女性ですね"\n);
}else{
printf("YかNを入力してください。\n");
}

return 0;

}
```
といった感じでサンプルの構文を書き写しているだけなのですが

こんな感じの基礎的なif構文と論理演算子の「かつ」の使いかたに

関して学習していきます。

for構文もやり始めたらまた記事を書きたいと思います。
Angularをバージョン指定でインストールし、開発環境構築

環境:Windows10 64bit

Angular6の開発環境構築手順は以下３ステップ
１．node.jsのインストール
２．Angular6のインストール(はまる可能性あり)
３．Visual Studio Codeのインストール

尚、２を実行すると、単体試験時に使用する
・Karma
・Jasmine
も一緒にインストールされてくれる。

１．node.jsのインストール
　https://nodejs.org/en/
　にアクセスし、ダウンロードし、インストール。
　一応正常にインストールされたか確認するため、
　スタートメニューからNode.js command promptを起動。
　`node --version`を入力し、バージョン情報が正しく表示されることを確認する。
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/311820/5bdc0017-558c-e70d-de99-bb088e53ef09.png)


![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/311820/55981bed-5506-2e53-a0fc-f2528d27326d.png)

２．Angular6のインストール
　コマンドプロンプトを開く。
　Angular6はnpmのコマンドで、ネットワーク経由でインストールすることになる。
　従って、Proxyが設定されている環境だと上手くいかないことがある。
　proxyが設定されている人は、以下のコマンドで事前にProxyの情報を教えてあげる
　`npm config set proxy【proxyサーバ】`

　いよいよAngular6インストール。
　Angularのバージョンに拘らず、最新版が欲しい人は単に
　`npm install -g @angular/cli`
　で良い。
　しかし、私のように、集団で開発を行うために、特定のバージョンに合わせる必要がある人は、
　`npm install -g @angular/cli@6.2.6`
　のように、末尾にバージョンを指定する。
![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/311820/d89ae96c-fa4a-36e0-9538-9bc72b31a3bc.png)

　なお、余談だけど、Angularについてググると、良く旧バージョンの記事に行きつき、その情報が新バージョンでは適用されず、混乱を招くことがある。

　私はこのインストール時にうっかり、AngularJsの頃の記事を参照してしまい、Angular6ではなくAngularJSをインストールしてしまい、はまった。
　そんな風にうっかり間違えたバージョンをインスールした場合は、アンインストールのコマンドでアンインストール後、再実行。
　`npm uninstall -g @angular/cli`
　例によって正しくインストールされたか確認するため、
　バージョン情報を確かめる。
　`ng -v`
 

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/311820/5c4525fe-4c44-e779-09bd-6af6865263ff.png)


 これでインストール終わり。はまらなければ15分で終わる

３．Visual Studio Codeのインストール
　https://code.visualstudio.com/download
　ここからダウンロードしてインストールするだけ。
　なお、私みたいな初心者は、「インストールしたのがいいけど、どうやってソースを開くの？」と
　戸惑うが、慌てずにソースかプロジェクトフォルダを右クリックして「Open with code」。
　もしくは格好良くコマンドプロンプトから
　code 【開きたいファイル】
　でいける。

以上。
全くのゼロから始めるボードゲームのプログラミングと機械学習 [4日目]

#前回の振り返り
[全くのゼロから始めるボードゲームのプログラミングと機械学習 \[3日目\] \- Qiita](https://qiita.com/Coshian23/items/6c8f293f84277df2f69b)

- Pythonでクラスを定義してみる
- 標準ライブラリを使ってみる
- 擬似乱数とは何かとseedについて

一通りPythonの基本的な使い方を学んだので、いよいよPygameを使用してゲーム制作の入り口へ足を進めてみたいと思います。

#Pygameの歴史
以下、参考書籍より抜粋。

- PygameはSimple DirectMedia Layer(SDL)と呼ばれる他のゲーム作成ライブラリによって構築された
- SDLは他のプラットフォームからの移植ゲームタスクを簡易化するために作られた
- SDLはグラフィックスや入力デバイスについて複数のプラットフォーム上での表示や処理の一般的な方法提供する
- SDLはC言語で書かれていたがC++では遅い上にエラーが多かった
- プログラマはSDLを各々好きな言語へのバインディングを作成した
- 現在SDLはいかなる言語からでも使用可能でありPygameもその一つである

#Pygameをインストールしてみる
ではさっそくインストールしてみましょう。ということで書籍に従って[www\.pygame\.org](https://www.pygame.org/)へ行ったのですがDownloadsのリンクがありません。書籍の発行時期である2011年はあったのでしょうが、2018年現在はpipによるネット上のリポジトリからのインストールが主流ということでしょうかね。

下記記事を参考にpipを実行でインストールできました。
[PythonをインストールしてPygameを動かすまで \- Qiita](https://qiita.com/i-tanaka730/items/ad56461a4f223fdbb4e5)

```
python -m pip install pygame
```
ついでにインストール成功確認を兼ねてバージョンを確認してみます。

```python
>>> import pygame
>>> print pygame.ver
1.9.4
```
参考書籍はPygame1.9.2でしたので7年で大きくは変わっていないようですね。

#Pygameで画面表示
まずは画面を表示してみましょう。ゲームを作るからには何をおいてもそれが重要です。Pygameに於ける「Hello, World!」ということで参考書に沿って画面を表示してみました。
![helloworld.jpg](https://qiita-image-store.s3.amazonaws.com/0/308584/c50d2897-5b33-f349-3e8e-495f9e480e9c.jpeg)
超絶謎な画像ができあがりましたが、ひとまず背景画像とマウスの動きを追従するコウモリの画像が描写できました。ただこれだけのことですが、Pygameを使わずにPython以外で同じことをやろうとすると大変であることは想像できます。そもそもWEBサイトやバックエンドの開発しかしたことがない自分にとってはウィンドウを表示して動くものを作るという事自体結構斬新に感じました。

#今後の予定
1. ボードゲームをプログラミング
    2. Pythonの基礎勉強
    3. Pygameの基礎勉強　👈
2. ボードゲームのAI作成
3. 機械学習によるAI強化

しばらくはPygameを使ってのグラフィックスの勉強になると思います。

#今回の振り返り
- やったこと
    - Pygameの歴史を知る
    - Pygameのインストール
    - 謎の画像描写
- わかったこと
    - Pygameのインストール方法
    - Pygameパッケージのモジュール群
    - ウィンドウの表示方法
- つぎにやること
    - イベントの取得
    - フォントやビジュアル生成

#参考書籍
[Pythonゲームプログラミング入門 \| Will McGugan, 杉田臣輔, 郷古泰昭 \|本 \| 通販 \| Amazon](https://www.amazon.co.jp/Python%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-Will-McGugan/dp/4048704397/ref=sr_1_14?s=books&ie=UTF8&qid=1540967866&sr=1-14&refinements=p_n_feature_seven_browse-bin%3A3232405051)
dockerコンテナ内でctrl-pの挙動がおかしい問題

##　結論
dockerのdetachKeysという設定のデフォルトバインドが `ctrl-p` と被っていたせいだった。
バインドを変更したら治った。

```json:~/.docker/config.json
{
  "auths" : {
    "https://index.docker.io/v1/" : {
    }
  },
  "detachKeys" : "ctrl-\\"
}
```
[初心者向け]圧倒的エンジニアになる為の質問の仕方⇒3つのポイント

# はじめに
質問、してますか？

エンジニア諸氏は日々分からないこと、疑問点にぶつかっていることと思います。

そういう時の対処法としては人に聞くのが手っ取り早いですよね。
場合によってはGoogle先生に聞く方が早いかもしれませんが、「担当している処理独特の関数」「設計書の提出先」なんかはGoogle先生でも分かりません。

先輩、上司、お客さんに質問する時に気を付けておくといいポイントを3つ紹介します。

# 前提
紹介する前に。
良い質問と悪い質問の違いってなんだか分かりますか？

私は<b>「自分の得たいと思ってる回答に辿り着く時間」</b>だと思ってます。

質問やその回答にかかった時間は「相手に消費させてる時間」でもあります。
ただ、よく「先輩、上司も暇ではないのでその時間を使っているという自覚を持った方がいいでしょう。」なんて言いますが正直あまり気にしなくていいです。

分からないまま進められて後で大幅な手戻りが発生するより逐一「ほうれんそう」してくれた方が結果的にリスクが少なくなるからです。

かといって全く気にしないのも問題ですのでこの記事がちょっとした助けになると幸いです。

前置き長くてすいません…
~~釣りタイトルとか言わないで~~

## ポイント1. 質問内容は明確か？
これの悪い例としては(あってはならないことですが)「分からない所が分からない」というのが極致でしょう。

曖昧な質問をするな、ということですね。

自分では曖昧じゃないと思ってても相手からしたら「なぜその考えに至ったのか」も気になるところです。

なぜそういう質問・疑問が出てきたのか、そこに至るまでのロジック・意図を伝えてあげるとより明確に伝わると思います。

## ポイント2. できれば Yes or No で答えが来るようにする
これ以上ないほど簡潔な答えですよね。
作業が特に止まることもなく進めることができます。

質問というより確認、お伺いを立てるといった感じです。

とはいえこの世には「はいといいえ」だけでは答えることが出来ない事も多くあります。

そういう時は選択肢、こちらで考えた案をいくつか用意してあげることがポイントです。

- 例「こちらで考える対応と致しましては①,②,③の内どれかになると思われますがいかがでしょうか。」

こうすれば相手は選ぶだけですし、もしも適切でない場合は「こうしてください」と要望が飛んでくるでしょうから「自分の得たいと思ってる回答に辿り着く時間」の削減につながります。

## ポイント3. 自分は何が適正だと思っているか
ポイント2にも関連することですが、選択肢をいくつか出すときは自分がこうだと思っている、これが一番適正(めんどくさくない対応)だと思った択を提案することになります。

その為には担当している処理・機能についての理解や他の質問・課題と関連してないかを把握するスキルも必要になりますので初めの内は難しいと思います。

私も「これって規約に違反してるんじゃないか？」とか「これ設計書によっては表記がバラけてるけど、どっちに揃えればいいの？」といった疑問が既に他の人が出した課題によって解決されていることがままありました。

こういった「自明の理」であることをいちいち聞くのはかえって失礼となってしまうので注意が必要です。
ちょっとめんどくさい話ですがやはり礼節・マナーは大事です。

# まとめ
こういうことは学校でも研修でもあまり教えてくれませんが、大事なことだと思います。
どんどん質問してコミュニケーション取る人は伸びます。たぶん。

例え明確な質問が出来なくても、自分一人で悩んでても時間の浪費をするだけですので思い切って丸投げするのも大事です。
じゃあこの話はなんだったんだ！ってことになりますが笑

ちなみに私は選択肢でいくつか提案する時に、適正であり・工数がかからず・楽に対応できて・最もめんどくさくない提案を一番最初に置いています。
ちょっとしたコツですので活用できるときは活用してみてください笑


以上です。
UnityEngine.InputでOculus Goのコントローラを使う

UnityでOculus Goのコードを書くならOculus SDKを使うのが一般的でしょうが、今回使わないで書いて大変だったので記録を残しておきます。

## 確認環境
- Unity 2018.2.12f1
- Oculus Go
    - バージョン:3.51.56.125526086
    - ランタイムバージョン:3.4.11.126617889
    - OSバージョン:user-159390.2710.0

## 調査結果
以下のいずれかで使えます。

- **InputManagerでボタンと軸を割り当てた上で** `Input.GetButton()` 系や `Input.GetAxis()` を使う
- 直接 `Input.GetKey("joystick button XX")` `Input.GetKey(KeyCode.JoystickButtonXX)` 系を使う(タッチパッドスライド以外)

それぞれで指定するボタンや軸の名前をまとめます。

<ins>
(2018/12/20 追記)<br>
指定する値は<em><a href="https://qiita.com/R-Koubou/items/727b01812bed957c4820">右手と左手で異なる</a></em>ようです。<br>
(@R-Koubou さん情報ありがとうございます)<br>
たまたま確認に使ったGoが左手用の設定になっていたため、影響を受けてしまいました。
</ins>

|機能名|`OVRInput`|InputManagerなどの指定(左手用)|
|----|----|----|
|トリガーボタン|`Button.PrimaryIndexTrigger`|`"joystick button 14"`|
|バックボタン|`Button.Back`|`"joystick button 6"`|
|タッチパッド(接触)|`Touch.PrimaryTouchpad`|`"joystick button 16"`|
|タッチパッド(押し込み)|`Button.PrimaryTouchpad`|`"joystick button 8"`|
|タッチパッド(左右スライド)|`Axis2D.PrimaryTouchpad`|`"X axis"`|
|タッチパッド(上下スライド)|`Axis2D.PrimaryTouchpad`|`"Y axis"`|

### 詳細
期待通り動作しないものも含めた手元の環境での動作確認の結果です。

| | 結果 |
|----|----|
|InputManagerへの登録|可能|
|`Input.GetButton("Jump")` (※InputManager登録済み)|可能|
|`Input.GetButton("joystick button 8")`|動作せず|
|`Input.GetKey(KeyCode.JoystickButton8)`|タッチパッドスライド以外可能|
|`Input.GetKey("joystick button 8")`|タッチパッドスライド以外可能|
|`Input.GetAxis("Horizontal")` (※InputManager登録済み)|可能|
|`Input.GetAxis("X axis")`|動作せず|
|`Input.touchCount`|タッチパッドを操作しても0|

## 結論
素直にOculus SDKの `OVRInput` を使いましょう！

## 参考情報
- [Input](https://docs.unity3d.com/ja/current/ScriptReference/Input.html)
- [Oculusの入力](https://docs.unity3d.com/ja/current/Manual/OculusControllers.html)
- [Unity標準のVR機能（UnityEngine.XR）メモ](https://framesynthesis.jp/tech/unity/xr/)
Githubでよく見る @@ -a,b +c,d @@ の意味。(git diff header)

エンジニアなら知っておきたいGit豆知識

Github でよく見るこれ↓

![スクリーンショット 2018-11-07 10.36.57.png](https://qiita-image-store.s3.amazonaws.com/0/67424/0cfb8102-4ac6-cb3b-1d4a-641ad87c1cc6.png)

各数値がどういう意味だか知ってますか？

私は知りませんでした。というより気にしたことがありませんでした。

最近これの意味を理解する必要性が初めてでてきたので、ネットで公式ドキュメントを読んでいたんですが、意味不明だったので、
帰納的にこの数値の意味を割り出しました。

そもそも git では、 git diff したときのひとかたまりのことを `diff hunk` と呼ぶようです。

この数値は、各 `diff hunk` のメタ情報になります。

## git diff の header の各数値の意味
```
@@ -a,b +c,d @@
```
| 数値 | 意味 |
|:--:|:--:|
| a | 元ファイル始まり行 |
| b | 元ファイルのdiff hunkの行数 |
| c | 新ファイル始まり行 |
| d | 新ファイルのdiff hunkの行数 |

マイナスとかプラスとかあったので、増えた行とか減った行とか勝手に思ってましたが、全然違ってました。

Git使うなら覚えておいて損はないかなと思います。
Nuxt.jsのvuexでMoment.jsを利用する

2018/11/07 22:59 編集
moment.jsよりdate-fnsが良いらしいので、書き直しました。
=> [Nuxt.jsでVueコンポーネントでもVuexでもdate-fnsを使う](https://qiita.com/idani/items/69cbd5e1d98f2eac48d7)

# はじめに

Nuxt.jsを使っていて、VuexでMoment.jsがうまく動作しませんでした。そして、動かすまでの内容です。

# 経緯・敬意

@potato4d 花谷氏の[Nuxt.jsビギナーズガイド](https://amzn.to/2PeU88I)で勉強しています。
とてもよい学びになっています。ありがとうございます。

サンプルコードで、Nuxt.jsのプラグインとして、Moment.jsを導入されていますが、以下のようなエラーが発生してしまいました。

```plugins/moment.js
import 'moment/locale/ja'
import moment from 'moment'
moment.locale('ja')
export default moment
```

<img width="1116" alt="127_0_0_1_3000_posts.png" src="https://qiita-image-store.s3.amazonaws.com/0/133291/56e90478-5d28-1a08-de0c-2a5b3181d72d.png">

# 解決への道のり

「nuxt format.replace is not a function」で検索すると、[Problem with third-party plugins](https://github.com/nuxt/nuxt.js/issues/1605)というIssuが見つかりました（ただし解決済み）。

また、Qiitaで検索すると、 @dasisyouyu さんの記事がありましたので、早速導入。

* [nuxtでmomentを動かす](https://qiita.com/dasisyouyu/items/a52359949a78247cc1c2)
* [nuxtでmomentが使えない](https://qiita.com/dasisyouyu/items/69acdd6263f5c2d2fb61)

しかし、Vuexで動作しませんでしたOrz...

@dasisyouyu さんもIssueを投げられていました^^；

* [can't use in store.](https://github.com/nuxt-community/moment-module/issues/3)

こうなったら発想を転換して、[Axiosモジュール](https://github.com/nuxt-community/axios-module)のようにMoment.jsが使えると嬉しいなっと考えました。

プラグインについては、以下にかかれています。結構、簡単にインジェクションできますね。

* [Nuxt.jsドキュメント プラグイン〜注入する](https://ja.nuxtjs.org/guide/plugins/#%E7%B5%B1%E5%90%88%E3%81%95%E3%82%8C%E3%81%9F%E6%B3%A8%E5%85%A5)

moment.jsを日本語ロケールで初期化して、引数を渡してあげればよさそうです。
こんな感じにしました。

```plugin/moment.js
import 'moment/locale/ja'
import moment from 'moment'

moment.locale('ja')
export default ({ app }, inject) => {
  inject('moment', args => moment(args))
}

```
作成したmoment.jsプラグインを導入するために、「nuxt.config.js」に追記します。

```nuxt.config.js
module.exports = {
・・・
plugins: [
  '@/plugins/vuetify',
  '@/plugins/axios',
  '@/plugins/moment' ＜ーこれを追記
],
・・・
}
```

これでvuexでも使えるようになりました。

```store/posts.js
export const actions = {
  async publishPost({ commit }, { payload }) {
    const created_at = this.$moment().format()
  }
}
```

# おまけ〜moment.jsのロケールをしぼる。

moment.jsをそのままバンドルすると、様々な言語ファイルが入っているためファイルサイズが肥大化してしまいます。

このため[moment-locales-webpack-plugin](https://github.com/iamakulov/moment-locales-webpack-plugin)を使って、必要な言語（ここではja）以外は削除するようにします。
※en-usはデフォルト言語なので削除ができないそうです。


```console
yarn add moment-locales-webpack-plugin --dev
```

```nuxt.config.js
const MomentLocalesPlugin = require('moment-locales-webpack-plugin')

module.exports = {
・・・一部省略
  build: {
    vendeer: ['moment'],
    plugins: [
      new MomentLocalesPlugin({
        localesToKeep: ['es-us', 'ja']
      })
    ]
  }
}
```

この設定をすることで、168KiB節約することができました！

```
設定前：　e9b3116a7e644604073c.js    **587 KiB**       9  [emitted]  [big]  vendors.app
設定後：　6421c4c6c45adabb8508.js    **419 KiB**       9  [emitted]  [big]  vendors.app
```


# 参考文献

* [Nuxt.jsドキュメント プラグイン〜注入する](https://ja.nuxtjs.org/guide/plugins/#%E7%B5%B1%E5%90%88%E3%81%95%E3%82%8C%E3%81%9F%E6%B3%A8%E5%85%A5)
* [Nuxt.js Webpack プラグインを追加するには？](https://ja.nuxtjs.org/faq/webpack-plugins)
Raspberry pi model3 におけるKivyのインストール

# インストール方法

raspberry piへのKivyのインストール方法はkivyの公式ページがありますが、その手順通りにインストールを行ったところ、ImportErrorが発生していたので、以下の方法をとりました。同様の問題に悩んでいたいる人がいたら参考にして下さい。

## 公式ページでのインストール方法
公式ページにおけるインストール方法では、翻訳版と最新版(英語)が存在しますが、自分はどちらの方法でもインストールする事が出来ませんでした。以下に翻訳版と最新版のURLを示します。pip listでもkivyはインストールされているのは確認できます。

・[kivyインストール手順[翻訳版]](https://pyky.github.io/kivy-doc-ja/installation/installation-rpi.html)
・[kivyインストール手順[最新版]](https://kivy.org/doc/stable/installation/installation-rpi.html)

## 自身でのインストール方法
自分のインストールといっても、公式ページと異なる点はCythonのバージョンのみです。しかし、依存関係もあると思うので、以下に自身の環境を示します。

| ソフトもしくはハード        |       バージョン | 
|:-----------------:|:------------------:|
| Raspberry pi         |              Model 3 b+ |  
| ディスクイメージ           |            2018-10-09-raspbian-sterech |  
| Python             |              2.7 |    

まずは公式と同様に進めていきます。

```bash

$sudo apt-get update
$sudo apt-get upgrade
$sudo apt-get install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev \
   pkg-config libgl1-mesa-dev libgles2-mesa-dev \
   python-setuptools libgstreamer1.0-dev git-core \
   gstreamer1.0-plugins-{bad,base,good,ugly} \
   gstreamer1.0-{omx,alsa} python-dev libmtdev-dev \
   xclip xsel
```

次にCyhtonのインストールを行います。ここが公式と異なる点です。具体的には、Cythonをバージョンを指定してインストールするのですが、公式(翻訳版、最新版)の手順と同様のバージョンをインストールすると動きませんでした。なので、異なるバージョンを指定しました。

```bash

$sudo pip install -U Cython==0.25.2
```

Cythonは各kivyのバージョンにあったバージョンが必要になります。以下に対応表を示します。

| kivy Version        |       Cython Version | 
|:-----------------:|:------------------:|
| 1.10.1dev         |              0.27.3 |  
| 1.10.1           |            0.25.2 |  
| 1.9.1             |              0.23.1 |
| 1.9.0             |              0.21.2 |    

また、このバージョン対応に関しては、公式ページでも紹介されています。以下にURLを示します。

・[KivyのバージョンとCythonのバージョンについて](https://kivy.org/doc/stable/installation/deps-cython.html?highlight=kivy%20version)

Cythonのインストール後は、公式と同様に進めていきました。

```bash

$git clone https://github.com/kivy/kivy
$cd kivy

$make
$echo "export PYTHONPATH=$(pwd):\$PYTHONPATH" >> ~/.profile
$source ~/.profile
```

上記の手順の中で、cloneした後にmakeが一番時間がかかる(自分は20分くらい)ので時間があるときに実行した方がいいと思います。

## Finish Installing Kivy

インストール終了後には、kivyをimport出来るようになりました。Cythonのバージョンが異なる場合には、ImportErrorになるので、ImportErrorが発生している場合にはCythonのバージョンを確認した方がいいと思います。
eclipseのupdate siteをダウンロードするバッチ

うちの社内では協力会社の方がインターネットを使うことができないので
eclipseのプラグインをインストールしたくてもupdate siteに接続することができない。

そこで、update siteを社内で配布できるarchiveとしてダウンロードするバッチを作ってみた。

```
'**********初期設定***********
'eclipseのインストールディレクトリ(eclipse.exeの場所)
const eclipseDir = "C:\eclipse" 
'*****************************

'変数宣言
dim updateSite
dim cdir
dim tempDir
dim ZipFile
dim objWshShell
dim fso


set objWshShell = WScript.CreateObject("WScript.Shell")
set fso = CreateObject("Scripting.FileSystemObject")

'入力プロンプト
updateSite = InputBox("updateSiteのURLを入力してください。")

'カレントディレクトリに作成する
cdir = objWshShell.CurrentDirectory
tempDir = cdir & "\temp"
ZipFile = cdir & "\updateSite.zip"

'一時フォルダ存在チェック
If fso.FolderExists(tempDir) = True Then
    strMessage = "tempフォルダが既に存在するため作業を中断します。"
Else
    fso.CreateFolder(tempDir)
End If

'updatesiteのダウンロードを実行。非同期なので終わるまでループで待つ
objWshShell.Run eclipseDir & "\eclipse.exe -nosplash -verbose -application org.eclipse.equinox.p2.metadata.repository.mirrorApplication -source " & updateSite & " -destination " & tempDir, 0, False 
objWshShell.Run eclipseDir & "\eclipse.exe -nosplash -verbose -application org.eclipse.equinox.p2.artifact.repository.mirrorApplication -source " & updateSite & " -destination " & tempDir, 0, False 

dim fsize

'10秒間サイズが変わらなければダウンロード完了と見る
Do
    fsize = fso.GetFolder(tempDir).Size
    'ダウンロード開始に時間がかかるときがあるのでサイズ0のときは終わらないようにする
    if fsize = 0 then
    	fsize = -1
    end if
    wScript.Sleep 10000
Loop Until fso.GetFolder(tempDir).Size = fsize

'ダウンロードが終わったらzipに固める
fso.CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(tempDir).Items
objShell.NameSpace(ZipFile).CopyHere(source)

'10秒間サイズが変わらなければ圧縮完了とみなす
Do
    fsize = fso.GetFile(ZipFile).Size
    wScript.Sleep 10000
Loop Until fso.GetFile(ZipFile).Size = fsize

'一時フォルダは削除
fso.DeleteFolder tempDir
```
Vue.jsでナビゲーションガードを使用してデータを取得後に画面遷移させる方法

#背景
vue.jsでライフサイクルフックのcreatedを使って何らかのデータを取得すると画面の描画後にデータが反映されるため画面がガタついてしまいます。
解決策として、vue-routerを使用している場合はナビゲーションガードを使用することができるので、データを取得後に画面遷移するようにします。

以下、Promiseを使って複数のデータを取得後に画面遷移する実装です。

#実装例
```JavaScript
export default {
    data () {
        return {
            data1: '',
            data2: '',
        }
    },
    beforeRouteEnter(to, from, next) {
        Promise.all([
            function1(),
            function2(),
        ])
        .then((res) => {
            next(vm => {
                vm.dataSet(res[0], res[1]);
            });
        })
        .catch((e) => {
            console.log(e);
        });

        function function1() {
            return new Promise((resolve, reject) => {
                http.get('https://...', res => {
                    resolve(res.data);
                }, error => {
                    reject(error);
                })
            })
        }

        function function2() {
            return new Promise((resolve, reject) => {
                http.get('https://...', res => {
                    resolve(res.data);
                }, error => {
                    reject(error);
                })
            })
        }
    },
    methods: {
        dataSet(data1, data2) {
            this.data1 = data1;
            this.data2 = data2;
        }
    },
}
```
beforeRouteEnterで画面遷移を止めてnext関数で遷移します。
注意点としては、beforeRouteEnterはナビゲーションが確立する前に呼ばれるため、thisを使用することができません。そのため、データの取得のみをbeforeRouteEnterで行い、next関数のコールバックでデータをセットします。
今回の実装ではPromise.all()を使用して、複数のAPIを並列に実行してPromiseが成功した場合にnext関数で画面遷移させています。

以上です。
HyperledgerFabricで、いろいろと設定ファイルをいじったあげく、エラーが出た時の対処法（私の場合）

# はじめに

* そんなに仰々しいものではありません。当たり前のことです。クソ記事です。
* サンプルなどをいじったときに「うまく行かないなー」「なんかエラーが出てるなー」という時の覚書というか、戒めです。

# 結論

* 結論は最初に書くべきですね。
* いじった「**設定ファイルを見直せ**」 この一言に尽きると思います。（個人談）
    * ぐぐってみると、同じようなエラーが発生している人がたまにいますが、きっとその人も、なんか修正漏れやコピペミスがあるんだと思います。たぶん。

# 私の場合

* HyperledgerFabricの`fabric-samples/basic-network`をコピーし、いろいろといじっていました。その中で、触っていたのは下記。
	* docker-compose.yml
	* configtx.yaml
	* crypto-config.yaml
	* generate.sh
	* start.sh
* まぁ、だいたいいじりました。

* 私の場合、コピペしたままで`orgX`が同じになっていたり、Peerを追加しているのに`crypto-config.yaml`の`Template.Count`が「1」のままだったり、不要な文字列が入っていたり…etc…して「エラーが発生する」「動かない」といった事象が頻発していました。
	* 自分では、ちゃんとできていると思っているから、なおさら読み飛ばしたり、見当違いのエラー文言でググったりして、非常に時間を要しました。
	* 修正前後でdiffとったりするのが、きっと一般的なのでしょうね・・・(；´Д｀)


----

* これでどうにか、複数Org・チャンネル・Peerの接続を確認できたので、ぼちぼち動かしていこうと思います。
* 今回は以上です。ありがとうございました。
Photoshopでマーブル模様を作る方法

Phothoshopで、きれいなグラデーションになるような「マーブル模様」の作成をします。
まず、下図が完成イメージです。
<h2>完成イメージ</h2>
![marble.png](https://qiita-image-store.s3.amazonaws.com/0/311812/b6fc7ea2-9a61-c7f7-353a-08da29fd3b7e.png)

マーブル模様は、素材サイトなどに多くありますが、使いたいイメージと色がマッチしないことが多いですよね。
自分で作ってしまえば、色や混ざり具合などいくらでも調整が可能です。

たとえば、下図のようなピンクでポップなイメージもOK。
![marble_real.png](https://qiita-image-store.s3.amazonaws.com/0/311812/7618ccb5-d6af-3366-fd2f-abc3964b69c2.png)

制作方法は、いたって簡単、5分で出来ます。
フィルター効果を上手に重ねるだけなので、Photoshop初心者でもきれいに制作可能です。

<h2>制作方法</h2>
まず、アートボードの設定で、2500×1600pxの150dpiとします。これは使いたいサイズでOKです。
つぎに流れを箇条書きでお送りします。
<h3>制作の流れ</h3><ul><li>レイヤーにフィルター「雲模様2」を適用</li><li>レイヤー効果で色を適用</li><li>極座標フィルターを適用</li><li>渦巻フィルターを適用</li><li>仕上げ</li></ul>
極座標と渦巻きフィルターを重ねながら希望のマーブル模様ができるまで繰り返します。
ただこれだけで綺麗なグラデーションのマーブル模様が出来ます。

<h2>応用編</h2>
自分で制作することで、作りたいイメージそのものが作れますね。私はピンクのマーブル模様テクスチャが欲しかったので作り、販促用バッグのイメージを制作いたしました。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">年末販促用。Photoshopでイメージカラーのマーブル柄を作成しDimensionで3D化、adobe最高。これでクライアント提出完了。30分で終わるやつ。（実際はロゴをハメる）持ち手印刷は高そうだが、そこは後で調整調整調整。 <a href="https://t.co/9DG9Z3gijA">pic.twitter.com/9DG9Z3gijA</a></p>&mdash; life_zakk (@life_zakk) <a href="https://twitter.com/life_zakk/status/1059282329712046081?ref_src=twsrc%5Etfw">2018年11月5日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<h2>参考リンク</h2>
もっと詳しく知りたい方は、以下ブログからご覧ください。

「簡単に美しいマーブル模様をPhotoshop CCで作成する方法
<a href="https://blog.lifezakk.com/2018/11/05/photoshop-marble/">https://blog.lifezakk.com/2018/11/05/photoshop-marble/</a>