OmniAICreator/Qiita-1.07M huggingface dataset:
axiosライブラリを使ってリクエストする

# 概要
deleteでの通信で割とはまったのでメモっておく。
# GET (参照)
クエリパラメータをセットする場合は、URLに直接記述するか、
第2引数にparamsというキー名でセットする。

```js
const queries = { id: '1000' };
Axios
    .get('/api/sample/', {params: queries})
    .then(res => {
        alert("「" + queries.id + "」参照完了");
        console.log(res);
    })
    .catch(error => {
        alert("「" + queries.id + "」参照失敗");
        console.log(error, queries);
    });
```
# POST (登録)
登録するデータは、第2引数に渡します。

```js
const data = { name: 'hoge' };
Axios
    .post('/api/sample/', data)
    .then(res => {
        alert("「" + data.name + "」登録完了");
        this.$router.push({path: '/articles/list'});
    })
    .catch(error => {
        alert("「" + data.name + "」登録失敗");
        console.log(error, data);
    });
```
# PUT (更新)
更新するデータは、第2引数に渡します。

```js
const id = '1000';
const modify = { name: 'hoge' };
Axios
    .put('/api/sample/' + id, modify)
    .then(res => {
        alert("「" + modify.name + "」更新完了");
        this.$router.push({path: '/articles/list'});
    })
    .catch(error => {
        alert("「" + modify.name + "」更新失敗");
        console.log(error, id, modify);
    });
```
# DELETE (削除)
bodyに値をセットする場合は、第2引数にdataというキー名でセットする。

```js
const id = '1000';
const params = { name: 'hoge' };
Axios
    .delete('/api/sample/' + id, {data: params})
    .then(res => {
        alert("「" + params.name + "」削除成功");
        this.$router.push({path: '/sample/list'});
    })
    .catch(error => {
        alert("「" + params.name + "」削除失敗");
        console.log(error, id, params);
    });
```


# 参考サイト
* [GitHub - axios/axios](https://github.com/axios/axios)
* [axiosライブラリを使って、柔軟にHTTP通信を行う](https://www.yoheim.net/blog.php?q=20170801)
* [axiosのパラメータ指定方法まとめ](https://qiita.com/taroc/items/f22f7dd5d6d5443c72a4)
Electronのアプリをパッケージング

## 概要
Electronで作ったアプリを配布できるようにパッケージングする。

## 手順
### ライブラリをインストール
electron-packagerをインストール

```
npm install electron-packager --save-dev
```

gulpをインストール

```
npm install gulp --save-dev
```

### 設定ファイルの作成
gulpfile.jsを作成

##### [ファイル構成例]
- /.vscode
- /node_modules
- /src
 - index.html
 - main.js
 - package.json
- package.json
- **gulpfile.js**  ←追加

```gulpfile.js
var gulp = require('gulp');
var packager = require('electron-packager');
var config = require('./package.json');

// Windows向けアプリの設定
gulp.task('packager-win', function(done) {
  packager({
    dir: './',                 // アプリ本体のフォルダ 
    out: './release',          // 出力先のフォルダ
    name: config.name,         // アプリ名
    arch: 'x64',               // 64bit
    platform: 'win32',         // Windows向け
    electronVersion: '2.0.9',  // Electronのバージョン
    overwrite: true,           // すでにフォルダがある場合は上書き
    asar: true,
    appVersion: config.version,// アプリバージョン
    appCopyright: '',     　　　// 著作権
  });
});

// Mac向けアプリの設定
gulp.task('packager-mac', function(done) {
  packager({
    dir: './',                 // アプリ本体のフォルダ 
    out: './release',          // 出力先のフォルダ
    name: config.name,         // アプリ名
    arch: 'x64',               // 64bit
    platform: 'darwin',        // Mac向け
    electronVersion: '2.0.9',  // Electronのバージョン
    overwrite: true,           // すでにフォルダがある場合は上書き
    asar: true,
    appVersion: config.version,// アプリバージョン
    appCopyright: '',     　　　// 著作権
  });
});
```

### パッケージング

#### Windows向け
Windows環境で実行する

```
./node_modules/.bin/gulp packager-win
```
* release/sample-win32-x64の中に**sample.exe**があるのでそれを実行するとアプリが起動する
* sample-win32-x64ごと配布すれば、他の環境でも動かすことができる

#### Mac向け
MacOS上で実行する

```
./node_modules/.bin/gulp packager-mac
```
release/sample-darwin-x64の中に**sample**があるのでそれを実行するとアプリが起動する

##### [ファイル構成例]
- /.vscode
- /node_modules
- /src
 - index.html
 - main.js
 - package.json
- **release**
 - **sample-win32-x64**  // ←Windows向けの時
 - **sample-darwin-x64** // ←Mac向けの時
- package.json
- gulpfile.js


## エラー
### Windows
#### その1　パッケージ後のsample.exeを起動したら「Cannot find module」エラー
##### index.jsが無いといわれた場合
一番外階層のpackage.jsonの"main"がindex.jsになっていないか確認する
(npm init をすると、デフォルトでは**index.js**になる)

ここを**./src/main.js**に変更

```
・・・
  "description": "",
  "main": "index.js", // ← ここを
  "scripts": {
・・・
```
↓

```
・・・
  "description": "",
  "main": "./src/main.js", // ← 変更する
  "scripts": {
・・・
```

#### その2 ./node_modules/.bin/gulp packager-winを実行したら「Error: EBUSY: resource busy or locked~~」
* アプリのプロセスが残っているのが原因。
* タスクマネージャを起動して、詳細タブから該当のプロセス（例：sample.exe）のタスクを終了する
Rails 5のflashにmaterializeのtoastを使用する


## toastって？
ユーザーに控えめな注意を促すUIです。トースターから出てくるように、ポンっと下から出ます。
![ezgif-5-306791934ad7.gif](https://qiita-image-store.s3.amazonaws.com/0/238663/fc4bdf1a-3c53-c98e-14fd-dc8fdba1f263.gif)


[本家の説明および実際のサンプル（英語。オプションやらプロパティの詳細も載ってます）](https://materializecss.com/toasts.html)

## 設定

```ruby:Gemfile

gem 'materialize-sass', '~> 1.0.0.rc2'
```



```js:app/assets/javascripts/application.js

// 省略
//= require materialize
```


```scss:app/assets/stylesheets/application.scss

// 省略
@import "materialize";
```


```haml:app/views/layouts/application.html.haml

  -# 省略
  %body
    = render("layouts/toast")
    = yield
```


```haml:app/views/layouts/_toast.html.haml

- flash.each do |type, msg|
  -# 色についてはhttps://materializecss.com/color.htmlを参照
  - color = 'light-blue lighten-3' if type == 'notice'
  - color = 'red lighten-1' if type == 'alert'

  = javascript_tag "M.toast({html: '#{msg}',
                             classes: '#{color}',
                             displayLength: 2000})"
```
CSSのセレクタの書き方を学んで、コードを簡潔に！(おまけ：コメントアウトのショートカットキー）

#CSSの基本的な書き方
CSS（Cascading Style Sheet）はHTMLで作成した要素に対して配置や色などのデザインを記述する言語です。

CSSでは次のような書き方をします。
`セレクタ { プロパティ: 値;}`

デザインを指定するとき、
1.「どこの」
2.「何を」
3.「何にする」
をHTMLに教えてあげなくてはいけません。
そこでCSSはセレクタ、プロパティ、値がそれぞれ
1．「どこの」←セレクタ
2．「何を」←プロパティ
3．「何にする」←値
を教えているのです。
※値を必要としないプロパティもあるので注意が必要です。

例えば、HTMLファイルのbodyタグ以下に
`<p>hogehoge</p>`
CSSファイルに
`p{ font-size: 20px;}`
と書かれていたとします。このときこのCSSファイルの文は
「pタグで区切られた範囲の文字の大きさ(font-size)を20ピクセルにするよ」
と言っています。ですから、`<p>`と`</p>`に挟まれたhogehogeが20ピクセルの大きさで表示されます。

#セレクタの書き方

セレクタにはいろんな書き方があります。


| セレクタ       |       意味 | 
|:------|:-----------------:|
|*             |すべての要素      |
|a,b             |a と b       |
| a b          　 |a 以下の全ての階層にある b |
| a>b          　 |a の1つ下の階層にある b |
| a+b             |a の次にある b|
| a.classの値             |指定したclassであるa|
| a#idの値             |指定したidであるa|

##階層ってどういうこと？
`a b`や`a>b`で言ってる階層がどういうことか具体的に説明していきます。

例えば、次のようにhtmlが記述されていたとします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/298418/876cdbb3-ff73-174c-81d0-58c4c619667f.png)
このとき、divの子要素は「とてもうまい」を囲んでいるspanとpです。
divの1つ下の階層は子要素がある場所です。
divの2つ下の階層は子要素の子要素がある場所のことです。つまりdiv
の孫要素です。ここではclassがpointsであるspanです。

ですから、もし`div>span`をセレクタにしたら、設定は「とてもうまい」を囲んでいるspanだけに反映されます。
一方で、`div span`をセレクタにすると設定は両方のspanに反映されるのです。

##classやidの指定方法は特殊？
一般的にclassやidだけでセレクタを記述する時は、
`.classの値`
`#idの値`
で指定します.
一見、上の表にはない特殊な書き方に見えるかもしれません。
しかし実はこれは
`*.classの値`
`*#idの値`
の`*`を省略したものであり、表に当てはまります。

##属性セレクタ
classやid以外の属性を使って要素を指定することもできます。

| セレクタ       |       意味 | 
|:------|:-----------------:|
|a[c]          |属性cをもつa|
|a[c="d"]             |属性cの属性値がdであるa|
|a[c~="d"]          　 |属性cの属性値にdが含まれているa |

HTMLの属性の中には、複数の属性値を指定できるものも存在します。
`<a c="d1 d2 …">`
`<a c="d1 d3 …">`
`<a c="d2 d4 …">`
このとき、セレクタを`a[c~="d1"]`とすると、d1を共通してもっている要素だけを指定できます。

#おまけ：Atomで選択範囲を一気にコメントアウト！
HTMLとCSSではコメントアウトの書き方が違います。
HTMLでは`<!-- コメント　-->`
CSSでは`/* コメント　*/`でコメントを記述しますが、正直いちいちめんどくさい！
CSSを編集しながら、HTMLも編集してたら今どっちの書き方でコメントアウトしたらいいんだっけ・・・って分からなくなることも。

それを解決してくれる魔法の呪文があるのです！

**「Ctrl-/」**

コメントアウトしたい範囲を選択して、キーボードを叩くと一気にコメントアウトができてしまいます！

逆にコメントアウトされている選択しているときは、コメントアウトを解除してくれちゃいます！htmlでもcssでも関係ありません！

これはエディタAtomで設定されているショットカットキーなので、エディタによっては必要な入力は異なるかもしれません。
一度自分が使っているエディタにこのようなショートカットキーがないか調べて確認してみることをお勧めします。
ぐぐっと生産性があがること間違いありません！
オープンソースライセンス、どれなら使っても良いの？？


定期的に調べては忘れているので覚書です。

## 結論
MIT、BSD、Apacheライセンスなどの非コピーレフトライセンスを使いましょう。
企業として使うなら、特許条項のあるApacheライセンスが一番安心ですかね。
BSDの場合、バージョン確認は行いましょう。
GPL系ライセンスは注意しましょう。


## 参考サイト

- http://ounziw.com/2013/05/17/agpl/
- http://www.catch.jp/oss-license/2013/09/10/github/
- https://www.sbbit.jp/article/cont1/34811
- https://jp.linux.com/linux-community/blog/236-mirainoitsuka/411872


## ライセンスごとの違い
ほとんどのライセンスに共通しているのは、

- 自己責任で使ってね
- 商用利用可
- 修正・配布可

違いは以下のようなことが主。

- 再配布するソフトウェアのソースコードを開示する必要があるか
- どこまで公開する必要があるか
    1. 改変部分のソースコード公開（コピーレフト）
    2. 他のコードと組み合わせたときに、そのコードまで公開（準コピーレフト）
    3. 公開する必要なし（非コピーレフト）


#### コピーレフトとは

著作権を保持したまま、利用者にコピー、改変、再配布を許可する（著作権を無効化する） という考え方。再配布物のライセンスを同じにすること！



## 商用利用はどうなのか
このページで記載しているライセンスはどれも商用利用可です。

コピーレフト・準コピーレフトライセンスだとソースコードの開示の必要がでてくるので実質的に商用利用は難しい。
非コピーレフトライセンスであれば、著作権・ライセンス条文表示するだけでほぼ自由に使うことができる。

## じゃあ社内利用は？？
自分ひとりで使う、社内利用として使う分には自由に改変して使ってOK！！


## 主要なライセンスの種類

**<u>太字</u>**は特によく見かけるもの。
さらにライセンスにはバージョンがあるものもある。

| ライセンス                                         |                | バージョン違い |
| -------------------------------------------------- | :------------: | -------------- |
| **<u>GPL</u>**（ GNU General Public License ）     |  コピーレフト  | 有り           |
| AGPL（ Affero GPL ）                               |       〃       | 有り           |
| LGPL（ Lesser GPL ）                               | 準コピーレフト |                |
| **<u>BSD</u>**（ Berkeley Software Distribution ） | 非コピーレフト | 有り           |
| **<u>MIT License</u>**                             |       〃       |                |
| **<u>Apache License</u>**                          |       〃       | 有り           |



## GPL

<u>主要ルール</u>

- 著作権表示
- 無保証
- 自由な複製・改変・頒布が許可
- 特許条項あり
- GPLのソフトウェアを改造またはそのまま再配布、GPLソフトウェアを利用したソフトウェアを再配布 → GPLライセンスでの再配布が必要

**<u>GPLライセンスでの配布</u>**

- GPLのライブラリ（DLLなど）をリンク
- GPLのソースコードを拝借
- プロセス間通信でGPLプログラムと協調動作（かなりグレー）


**<u>GPLでなくて良い条件</u>**
  - **<u>ネットワーク経由でGPLプログラムと協調動作</u>**
  - WebアプリであればGPLライセンスを使っても公開義務はない
  - 単独で利用するプロセスとしてバンドル
  - GPLのOS上（例えばLinux上）で動作するソフトウェア
  - GPLのシステムライブラリを利用する


## LGPL

- 基本はGPLだが、それを緩めたライセンス
- リンクする場合にはCopyleftは適用されない（DLLはOK）
- 改造して再配布の場合はライセンスを同じに。



## AGPL

- ネットワーク経由でアクセスしたユーザーに対してもソースコードを公開せよ！！
- AGPLのライセンスのOSSを使う場合には、すべてをさらけだす覚悟が必要。
- **<u>現時点で最強のCopyleft</u>**



## MIT License
作者の名前を記し、作者に一切の責任を求めない限り自由に扱える

- 再配布時には著作権表示と本許諾表示（ソース内でもOK）
- 無保証

## BSD License

４つのバージョンが存在（どれも緩い）

- 初期BSD
- 旧BSD、４条項BSD
  - 著作権・ライセンス表示
  - 宣伝条項
     - このソフトウェアの機能に言及するまたは使用するすべての宣伝物には、次の謝辞を表示する必要がある
     - 「この製品は、○○ によって開発されたソフトウェアが含まれています。」 

  - このソフトウェア開発の貢献者（継承元のソースコード開発者）の名前は、事前の許可なしに製品保証や販売促進に使ってはいけない
        - 「このソフトはかの有名な○○さんが開発したものを改良したものです」的なのはダメ！

- 修正BSD、３条項BSD
  - 著作権表示＋無保証
  - このソフトウェア開発の貢献者の名前は、事前の許可なしに製品保証や販売促進に使ってはいけない
- ２条項BSD
  - 著作権表示＋無保証



## Apache License v2

- Apache Licenseであることの表示のみでOK！

  > This software includes the work that is distributed in the Apache License 2.0 

- 改変した場合には、その旨を表示する必要あり。
- 特許条項あり
    - 配布されているOSSの中に特許が含まれていたら、それは無償で自由に実施してよい
    - 自身の特許がそのOSSに含まれていると主張した場合、そのOSSは使えない
    - 後出しジャンケンで特許料を徴収することを防いでいるのかと

## まとめ

企業としてはApacheライセンスが一番安心。
MIT、BSDも使ってよし。
BSDのバージョンの確認はしましょう。
p5.jsが面白い

![0zhd4-zqy2g.gif](https://qiita-image-store.s3.amazonaws.com/0/22001/e69239b3-3652-70c6-6a37-63f59da10876.gif)

## Processing
知っている人には今更な話なんですが processing という面白い言語（というかプラットフォーム）があります。
非常に手軽にアルゴリズムアートみたいなものを作れるので気に入っています。Cのようなjavaのような言語なのですが　いろいろとデフォルトの設定があるため、非常に簡単にCGプログラミングを始められるため、初心者にもおすすめの言語です。

## p5.js
その　processing が javascript に移植された、という事は聞いていたのですがそれほど期待していませんでした。がっ！ 私が間違っておりました!(土下座)

まずは以下のリンクを見ていただきたい
http://www.bnn.co.jp/support/generativedesign_p5js/
それぞれの作品（スケッチと呼ぶ）のアイコンをクリックすると Webエディターにジャンプしてソースコードを見ながら実行できます。

Generative Design(通称：鈍器) の内容がすべて p5.js に移植されているではないですか！
そしてなんとWebGLに対応している。。。

## 試してみました
それで試しに作成したのがこれ。
https://editor.p5js.org/wittyfool/sketches/Hk7-h_v57
三角形の再生ボタンを押すとプログラムが走ります

このwebエディターも本当に良くできているんですよ。
ローカルの開発環境は要らないかな・・・

参考
p5.jsがWebGL＆3D対応。軽くいじってみます
https://qiita.com/hp0me/items/1570694d9f61368f3ae6
C言語で挿入ソート

# 挿入ソートとは
先頭からi番目までが整列済みの時、i+1番目の要素を、正しい位置に挿入する。
整列済みのデータに新しいデータを追加し、再び整列するときなどに便利。

# サンプルコード
ここでは、int型の配列を、挿入ソートを用いて小さい順に並べ替える。

```c:insertion_sort.c
#include<stdio.h>

/* 値を入れ替える関数 */
void swap (int *x, int *y) {
  int temp;    // 値を一時保存する変数

  temp = *x;
  *x = *y;
  *y = temp;
}

/* 挿入ソート */
void insertion_sort (int array[], int array_size) {
  int i, j;

  for (i = 1; i < array_size; i++) {   // 先頭から順にソート
    j = i;
    while ((j > 0) && (array[j-1] > array[j])) {   //整列済みの場合は処理しない
      swap(&array[j-1], &array[j]);   // 整列されていない要素を交換
      j--;
    }
  }
}

int main (void) {
  int array[10] = { 2, 1, 8, 5, 4, 7, 9, 0, 6, 3 };
  int i;

  printf("Before sort: ");
  for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
  printf("\n");

  insertion_sort(array, 10);

  printf("After sort: ");
  for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
  printf("\n");

  return 0;
}
```

実行結果

```
Before sort: 2 1 8 5 4 7 9 0 6 3
After sort: 0 1 2 3 4 5 6 7 8 9
```
# 性能

- 最悪の場合：逆順にソート済み
  - while文の比較回数：約$n^2/2$
  - while文の実行回数：約$n^2/4$
  - 比較+実行=$O(n^2)$
- 最善の場合：ほぼ整列済み
  - while文の比較回数：$n-1$
  - while文の実行回数：$0$
  - 計算量はほぼ線形時間$O(n)$
Vue.Draggableでドラッグ領域を指定する方法

# 前置き
[Vue.Draggable](https://github.com/SortableJS/Vue.Draggable)、便利ですよね。
[Sortable.js](https://github.com/RubaXa/Sortable)というjavascriptライブラリを元にVueで使いやすい形で実装されています。
インストールしてdraggableタグで挟んで、modelなりcomputedなりを指定するだけでドラッグ&ドロップが利用できるリッチなUIを作ることができます。
# ちょっと困った
ただ実装している中で、リストの中の要素全体がドラッグ&ドロップできてしまうと困ってしまうことがあります。
モバイルレイアウトなどで以下のようなリストを実装したいときにスクロールできなくなってしまうわけです。
<img width="380" alt="スクリーンショット1.png" src="https://qiita-image-store.s3.amazonaws.com/0/179987/8027d5a6-6de1-47e7-edb4-9b2246800f65.png">
# そんな時は
この問題はdraggableタグにoptionsを追加することで解決することが可能です。


```html
<template>
  <draggable v-model="sampleList" :options="{handle: '.item-handle'}">
    <div v-for="item in sampleList" :key="item.order">
      <div class="sample-item">
        <span class="item-handle">::</span>
        {{item.content}}
      </div>
    </div>
  </draggable>
</template>
```
# ちょっとした解説
加えたのは以下2点
- draggableタグに:options="{handle: '.item-handle'}"を追加
- ドラッグ&ドロップを可能とする要素を追加して、クラスに.item-handleを設定

要するにドラッグ&ドロップの取っ手(handle)を設定するイメージですね。
これで通常通りスクロールが可能となり、handleに設定した要素をクリック(or タップ)した時のみVue.Draggableが発動するようになります。
<img width="378" alt="スクリーンショット2.png" src="https://qiita-image-store.s3.amazonaws.com/0/179987/4a72a6b1-075a-d8b9-0f34-edda39d07f4f.png">
# まとめ
非常にシンプルな実装方法でとてもありがたいですね。
気になった点・誤った記載を見かけましたら、ご指摘いただければ幸いです。
閲覧いただき、ありがとうございました。
SATySFiのモジュールのdirectで宣言したinline-cmdの名前が被ったときの対処法

```ml:same.pdf
@require: stdja

module Japanese : sig
  direct \greeting : [] inline-cmd
end = struct
  let-inline ctx \greeting = read-inline ctx {こんにちは}
end

module English : sig
  direct \greeting : [] inline-cmd
end = struct
  let-inline ctx \greeting = read-inline ctx {Hi}
end

in

document (|
  title = {SATySFiのモジュールのdirectで宣言したinline-cmdの名前が被ったときの対処法};
  author = {Seiei MIYAGI};
  show-title = true;
  show-toc = false;
|) '<

  +p { 後勝ちだがモジュール名を含めて参照すれば使える }

  +section{\\greeting}<
    +p { \greeting; }
  >
  +section{\\Japanese.greeting}<
    +p { \Japanese.greeting; }
  >
  +section{\\English.greeting}<
    +p { \English.greeting; }
  >
>
```

## 実行結果

![Screenshot from 2018-10-08 22-13-01.png](https://qiita-image-store.s3.amazonaws.com/0/2074/a27c901e-3674-e794-19a3-43356cd4b7ca.png)
libpqxxでLISTEN

libpqでLISTENを書いてからlibpqxxで書き直したら凄くすっきりしました。

# 単にLISTENする
notification_receiverを継承して

```c++
#include <iostream>
#include <pqxx/pqxx>

class cout_rec : pqxx::notification_receiver
{
public:
	cout_rec(pqxx::connection & conn, const std::string & channel) : notification_receiver(conn, channel)
	{
	}
	virtual void operator() (const std::string & payload, int pid)
	{
		std::cout << payload << std::endl;
	}
};

int main(int argc, char * * argv)
{
	std::string table = "todos";

	pqxx::connection conn("host=localhost user=dev password=password dbname=db_dev");

	cout_rec receiver(conn, table);

	conn.await_notification();

	return 0;
}
```

NOTIFY todos "hello"すると"hello"が標準出力に出ます。

# ある条件を満たす行が最初からあったらそれでいい場合

レシーバはそのままで

```c++
int main(int argc, char * * argv)
{
	pqxx::connection conn("host=localhost user=dev password=password dbname=db_dev");

	cout_rec receiver(conn, "todos");

	pqxx::work tran(conn);
	tran.exec("LOCK TABLE todos"); // You must wait until commit if you want to insert into the table.
	pqxx::result r = tran.exec("SELECT id FROM todos WHERE done=FALSE");
	tran.commit();

	if (0 < r.size())
	{
		std::cout << r[0][0] << std::endl;
	}
	else
	{
		conn.await_notification();
	}

	return 0;
}
```

SELECTとcommit()の間で誰かがINSERTすると取りこぼすので"LOCK TABLE"してます。バグなのか仕様なのかは知りません。
SATySFiでmoduleを宣言したあとdocumentを書いて単に「! [Syntax Error at Parser] at "foo.saty", line 7, characters 0-8:」とエラーが出る場合inつければ直る

moduleを`.satyh`に書かずに以下のように直接`.saty`の中で書いた場合

```ml:foo.saty
@require: stdja

module Foo : sig
end = struct
end

document (|
  title = {単にエラーが出る場合inを忘れていることが多い};
  author = {Seiei MIYAGI};
  show-title = true;
  show-toc = false;
|) '<>
```

コンパイルするとよくわからないエラーがでます

```shell-session
$ satysfi -b foo.saty
 ---- ---- ---- ----
  target file: 'foo.pdf'
  dump file: 'foo.satysfi-aux' (already exists)
  parsing 'foo.saty' ...
! [Syntax Error at Parser] at "foo.saty", line 7, characters 0-8:
```

こういうときはinつけると直る

```ml:foo.saty
@require: stdja

module Foo : sig
end = struct
end

in

document (|
  title = {単にエラーが出る場合inを忘れていることが多い};
  author = {Seiei MIYAGI};
  show-title = true;
  show-toc = false;
|) '<>
```

## なんで

たぶん`in`つけてないときは`nxtopsubseq`が一番上の`nxtoplevel`に行ってて`document`みたいな変数参照だとうまく動かなくてエラーになっている。`in`つけると一番したの`nxlet`にいっててうまく動く（っぽい、詳しくはわからん）

```ml:src/frontend/parser.mly
nxtoplevel:
  | top=LETREC; recdec=nxrecdec; subseq=nxtopsubseq                          { make_letrec_expression top recdec subseq }
  | top=LETNONREC; nonrecdec=nxnonrecdec; subseq=nxtopsubseq                 { make_let_expression_of_pattern top nonrecdec subseq }
  | top=LETMUTABLE; vartok=VAR; OVERWRITEEQ; utast=nxlet; subseq=nxtopsubseq { make_let_mutable_expression top vartok utast subseq }
  | top=LETHORZ; dec=nxhorzdec; subseq=nxtopsubseq                           { make_let_expression top dec subseq }
  | top=LETVERT; dec=nxvertdec; subseq=nxtopsubseq                           { make_let_expression top dec subseq }
  | top=LETMATH; dec=nxmathdec; subseq=nxtopsubseq                           { make_let_expression top dec subseq }
  | top=TYPE; variantdec=nxvariantdec; subseq=nxtopsubseq                    { make_variant_declaration top variantdec subseq }
  | top=MODULE; mdlnmtok=CONSTRUCTOR; sigopt=nxsigopt;
      DEFEQ; STRUCT; strct=nxstruct; subseq=nxtopsubseq                      { make_module top mdlnmtok sigopt strct subseq }
  | top=OPEN; mdlnmtok=CONSTRUCTOR; subseq=nxtopsubseq {
      let (rng, mdlnm) = mdlnmtok in
        make_standard (Tok top) (Ranged subseq) (UTOpenIn(rng, mdlnm, subseq))
    }
;
nxtopsubseq:
  | utast=nxtoplevel     { utast }
  | EOI                  { end_header }
  | IN; utast=nxlet; EOI { utast }
;
```
https://github.com/gfngfn/SATySFi/blob/2c950de6b9d2882bb0afbac1b09e82b4768ce1a4/src/frontend/parser.mly#L531-L550

## 参考

https://github.com/gfngfn/SATySFi/blob/2c950de6b9d2882bb0afbac1b09e82b4768ce1a4/src/frontend/lexer.mll
https://github.com/gfngfn/SATySFi/blob/2c950de6b9d2882bb0afbac1b09e82b4768ce1a4/src/frontend/parser.mly
第3回 WebAuthn もくもく会メモ

# 第3回 WebAuthn もくもく会


先日行われた WebAuthn もくもく会で利用した共用メモです。
https://hackmd.io ってのを使いました。

<https://fido2-workshop.connpass.com/event/100944/>

日時：
- 2018-10-04 17:00~

場所：
- CTC DEJIMA https://dejima.space/news/2018/20181023.html
- Google Map https://goo.gl/maps/s4xoPejAgh82

※13階

Supported by FIDO Alliance

## 注意事項

ゴミについて。

会場のごみは、直接ゴミ箱には入れず、ゴミ箱前のごみ袋に入れてください。

## 当日の流れ

|日時||
|---|----|
|17:00|開場|
|17:30|あいさつ|
|17:30|FIDOの基本プレゼン by @watahani|
|19:30|QAセッション|
|20:00|懇親会|
|21:45|後片付け|
|22:00|完全撤収|

## 資料

### 公式

- [Web Authentication: An API for accessing Public Key Credentials Level 1](https://www.w3.org/TR/webauthn/) 
    - ↑より [最新Draft](https://w3c.github.io/webauthn/)見たほうがよさそう
    - 5章のブラウザAPI,7章のサーバーサイドの責務,あたりから読み始めるのが個人的にはおススメ

- [Client to Authenticator Protocol (CTAP) Review Draft, July 02, 2018](https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html)

### スライド

スライドとか貼る

Beyond Passwords: FIDO2 Demos from Google and Microsoft


<iframe width="560" height="315" src="https://www.youtube.com/embed/CkJf8zv1yBw" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>0

昨日のスライドたち..は connpass で <https://fido2-workshop.connpass.com/event/100866/>

### エンジニア向け

#### おススメDemoサイト

個人的には MS のやつがオプション全部実装してて、オプションを試すにはおススメ

webauthn.org が一番簡単だし、 Advanced クリックすると、バックエンドの通信可視化してくれるんで、APIの動きをみるのはおススメ。

- Microsoft: https://webauthntest.azurewebsites.net
- FIDO: 　　https://webauthn.org/
- Yubico: 　 https://demo.yubico.com/webauthn


@watahani おススメのコード

- https://github.com/fido-alliance/webauthn-demo
    - FIDO Alliance の Yuriy が Workshop 用に作ったサンプルコード
    - U2F ベースだけど、非常にわかりやすいスライドもあるのでお勧め
    - ちょっと改造すれば FIDO2 対応できる

### その他

## Q&A

質問がある方はここに書いてね

- Q. 17:00 に遅れそうなときはどうすればいいですか？
    - A. 20:00 までは会場ビルが開いているそうなので、直接会場までお越しください。

### Yuriy への質問

本日非公式にですが、FIDO Alliance Senior Certification Engineer の Yuriy が来ます。
意見。質問ある人はここに書いておく（誰か英語に訳してくれー）

- ResidentKey 内のユーザ情報の扱いについて
    - 個別削除や、表示させる機構は WebAuthentication API のスコープ外だと思うが、禁止事項などはあるか？
        - A. ガイドラインはあるが、 CTAP/WebAuthn の API に対応していれば、その他の実装は自由。例えばディスプレイがあって、ユーザ情報を個別削除するようなUXの Authenticator とかも可能。YubiKey などディスプレイがない Authenticator はオールクリア(CTAP API?) しかない。 
- Android Safety-net Attestation では、AuthenticatorData と ClientData の SHA256 ハッシュしか検証していないようだが、Authenticator の偽造されているかどうかの検証には使えないのではないか？
    - よくわかる Android Safety-net 動画 --> https://www.youtube.com/watch?v=8lv_9mydrjg
    - SHA256( AuthenticatorData | ClientDataHash ) に対して Android Safety-net の署名方法に基づいて署名している。
    - developer.android に[詳しいドキュメントが](https://developer.android.com/training/safetynet/#compat-check-response)あるのでちゃんと読もう（つらい）
無駄金を取られないようにするために使ってないEC2を自動停止するスクリプトを書いてみた

## はじめに
検証用にマシンに思ったよりパワーが必要だったので、短時間だからいっか、という軽い気持ちで  `m5.xlarge` にパワーアップさせた。
検証自体は無事に終わって、後日ログ採取を取るために起動したのだが、仕事の合間だったのでログ採取してあとに停止するのをすっかり忘れてしまい３日ほど起動しっぱなしに。。。。
さすが `m5.xlarge` たかが３日とは言え請求が結構エグい。
とても悲しい気持ちになったので使っていないEC2を自動で停止するスクリプトを描くことにした。

## TL;DR
### だれ向け？
- 私と同じ悲しみにくれている方
- 個人のAWSアカウントでごにょごにょされること方
- 会社の検証環境のEC2料金が高くて悩んでいる方

### スクリプト

5分毎にCPU、Inbound通信、SSH接続をチェック
10回連続でin-activeだった場合、つまり50分間in-activeな場合にサーバをシャットダウンする例

``` bash:crontab
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/aws/bin:/root/bin:/opt/aws/bin
MAILTO=""

*/5 * * * * cd ~; /bin/bash /root/monitor.sh; [ `tail -n 10 /root/monitor.log | grep -P "^active" | wc -l` -eq 0 ] && halt -h now || echo no shut >> /root/log.txt
```


サーバが利用状態かそうでないかをチェックするスクリプト
`5秒間の平均CPU利用率2%`以上、`10秒間のInbound通信が1024Byte`以上、`SSH接続が有る`場合にActiveと判断する

``` bash:monitor.sh
#!/bin/bash
cpu_usage=2
net_usage=1024
ssh_session=1
status=0
log='monitor.log'

# The first report of vmstat gives averages since the last reboot, drop it.
# Adopt average CPU usage rate for 5 seconds
cpu_usage_usr=$(vmstat 1 10 | tail -5 | awk '{sum+=$13} END {print sum/NR}')

# Adopt inbound traffic received in 10 seconds.
net_usage_usr=$(for i in `seq 1 2`; do cat /proc/net/dev; sleep 10; done | grep eth0 | awk 'NR==1{m=$10}NR==2{print $10-m}')

# Determine whether there is an SSH connection.
ssh_session_count=$(/usr/sbin/ss | grep '[s]sh' | wc -l)

if [ `echo "$cpu_usage_usr > $cpu_usage" | bc` == 1 -o `echo "$net_usage_usr > $net_usage" | bc` == 1 -o $ssh_session_count -ge $ssh_session ]; then
  status=1
fi

[ $status -eq 0 ] && status_str='in-active' || status_str='active'
echo $status_str $cpu_usage_usr $net_usage_usr $ssh_session_count >> $log

exit 0
```



## 解説
元ネタ様はこちらです。
[一定時間利用されていないEC2インスタンスを自動でstopする](https://qiita.com/sonots/items/7800d1de1014630b254d)

何番煎じかわからないですが、EC2のみで実装できてサクッと仕込める方法は見つからなかったのでこちらに記録しておきます。

ほぼ元ネタ記事そのままなのですが、自分用に修正した点は以下

### 要件
- 個人もしくは極少数しか使わない環境なので間違って落ちちゃっても問題にはならない
- コピペレベルで簡単に設定できること（設定の手間が増えると後回しにされて結局[はじめに](https://qiita.com/nori4k/items/3f29af29a5b9313661a5#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)の悲劇が起こるため)
- webアプリがメインのためInbound通信も監視対象にする
- SSHで作業中は停止されたくない

### 方針
- シェルスクリプト＋Crontabのみで実装
- 5秒間の平均CPU使用率が2%を超えている場合はActive
- 10秒間のInbound通信が1024Byteを超えている場合はActive
- SSH接続があればActive
- In-Activeが50分連続して続いてたらサーバシャットダウン

### 課題
- 運悪く起動時にCronが走ると停止されちゃう。起動後10分は監視対象外のような条件付けの検討が必要
- 厳密にはSSHで作業しているときはActiveにしたいだけで、無操作の場合はIn-Activeにしたい。Oubgoing通信も監視するとか、auditlog残すようにしてログのタイムスタンプで判断するとかもう一捻りが必要

## 参考リンク
[【AWS】CloudWatch入門／使っていないEC2を自動シャットダウンしよう](https://dev.classmethod.jp/etc/use-cloudwatch-to-detect-and-shutdown-unused-amazon-ec2-instances/)
[一定時間利用されていないEC2インスタンスを自動でstopする](https://qiita.com/sonots/items/7800d1de1014630b254d)
TRPOのフィッシャー情報行列の解釈

[Trust Region Policy Optimization](https://arxiv.org/pdf/1502.05477.pdf)を[自然勾配](https://pdfs.semanticscholar.org/e1c2/a2fd6a26947e5bbb8df47e30c1199ab1270d.pdf)の観点から見た時に出てくるフィッシャー情報行列について。
色々と調べたので、まとめてみようと思う。
[速習 強化学習 ―基礎理論とアルゴリズム ](https://www.amazon.co.jp/%E9%80%9F%E7%BF%92-%E5%BC%B7%E5%8C%96%E5%AD%A6%E7%BF%92-%E2%80%95%E5%9F%BA%E7%A4%8E%E7%90%86%E8%AB%96%E3%81%A8%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E2%80%95-Csaba-Szepesvari/dp/4320124227)の105ページに言及されている内容についてです。

# 結論
実はこれ計量テンソルっぽい。

#TRPO
通常の方策勾配法は以下の最適化問題を解くことになる。ただし、目的関数は$\rho _{w}$とする。

***maxmize*** $$\rho _{w+\Delta w} - \rho _{w} \approx \nabla _{w}\rho^{T} _{w}{\Delta w}$$ 

***subject to*** $$\Delta w^{T}\Delta w \leq \varepsilon$$

一方、TRPOの肝はKLダイバージェンス$D_{kL}$を用いて、信頼領域を定義し、これを制約条件とした最適化問題の解をもたらす$\Delta w$を使ってパラメータを更新する。

***maxmize*** $$ \nabla _{w}\rho^{T} _{w}{\Delta w}$$ 

***subject to*** $$E\left[ D_{KL}\left( \pi _w\right | \pi _{w+\Delta w})  \right]\leq \varepsilon$$

ただし、ここで期待値をとる分布は方策$\pi _w$によって定まる状態に関する定常分布である。

[この記事](http://seiya-kumada.blogspot.com/2018/03/fisher.html)(かなり詳しく導出しています)を参考にすると、KLダイバージェンスの2次近似がフィッシャー情報行列を使って表せそう（参考にしている記事ではKLダイバージェンスを対称化して、距離の公理を満たすようにしている。TRPOは普通のKLダイバージェンスを使っているので、どうやってやるのかはちょっと分からない）。そうすると、TRPOの制約条件は
***subject to*** $$\frac{1}{2}\Delta w^{T} F _w\Delta w \leq \varepsilon$$
と近似可能。

# 計量テンソル
[この本](https://www.amazon.co.jp/%E3%83%86%E3%83%B3%E3%82%BD%E3%83%AB%E8%A7%A3%E6%9E%90-%E5%9F%BA%E7%A4%8E%E6%95%B0%E5%AD%A6%E9%81%B8%E6%9B%B8-23-%E7%94%B0%E4%BB%A3-%E5%98%89%E5%AE%8F/dp/4785311258)を参考にしている。
内積 $u\cdot v$ は任意のベクトル$u$, $v$に対して実数値を対応させる双線形関数と考えることができる。いま、$u$, $v$を反変ベクトルと考えて、内積を
$$ g\left( u,v\right) = u\cdot v$$ 
と表せば、$g$は2階の共変テンソルと考えることができる。
2つの反変ベクトル$\boldsymbol{u}=\left( u^{i}\right)$, $\boldsymbol{v}=\left( v^{i}\right)$に対して、
$$ g\left( u,v\right) = g_{i,j}u^{i}v^{j}$$ 
となる。ただし、ここでは1つの項の中で上側と下側とに1度ずつ現れているような指標について規約を適用する（これもアインシュタインの総和の規約と言っていいのかな？）。ちなみに、テンソルの成分を扱う時に反変テンソルは上付き文字、共変テンソルは下付き文字で表すのが慣習。
ここで注意すべきなのは内積を計算する時には***2階の共変テンソル$g$の成分を知る必要がある***ということ。

# まとめ
計量テンソルの式を見れば分かる通り、フィッシャー情報行列って計量テンソルなんです。え、じゃあどの空間で計量を計算してるのかというと、今回のケースだと確率的方策の空間の計量を使って、計算してます。自然勾配を使うと、通常のユークリッド空間で計算された勾配よりもうまくいくことを示す様々な研究が存在していて、ユークリッド空間の計量を使った勾配がパラメータ空間の大部分で非常に小さくなってしまったりする一方で、自然勾配は有効だったりする場合があります。つまり、この話はTRPOがうまくいく理由付けの1つと言えます。
ggplotで作成した複数のグラフを１枚にまとめる

ggplotで作成した複数のグラフを１つの画像にまとめて出力します。

色々と複数の図をまとめるパッケージがあるみたいですが、今回はgridExtraパッケージを使います。興味のある方は参考ページを見てください。


まず、各グラフを作成します。作成の仕方は[Rのデータ可視化パッケージggplotの基本](https://qiita.com/suimin123/items/ec78b990a0c27eb32a62)を参考にして下さい。

```r
#パッケージの読み込み
library(ggplot2)
library(gridExtra)
#各グラフの作成
df <- diamonds       #データはdiamondsを使います。
p1 <- 
  ggplot(df,aes(x=carat,y=price))+       
  geom_point()        
p2 <- 
ggplot(df,aes(x=cut,y=price))+
  geom_boxplot()
p3 <- 
ggplot(df,aes(x=price))+       
  geom_histogram()
p4 <- 
ggplot(df,aes(x=price, y = ..density..,fill=cut))+
  geom_histogram(position = "fill",alpha=0.3,color="black")
```

次に、まとめるグラフのレイアウトを指定します。
grid.arrange()関数のlayout_matrix引数にマトリクス形式で指定します。


```r
layout <- rbind(c(1,1,1),c(2,3,4))
```

上記のように指定すると、以下のような出力になります。
1,2,3,4がそれぞれp1,p2,p3,p4が占める領域を表しています。

```
>layout
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    3    4
```
グラフを確認すると、

```r
gridExtra::grid.arrange(p1,p2,p3,p4,layout_matrix=layout)
```

![hoge.png](https://qiita-image-store.s3.amazonaws.com/0/207726/2686440c-a3d2-8f83-6414-79fb9daad351.png)

のように指定したレイアウト通りの図が出力されます。

ちなみに、png形式で出力するには、

```r
png("multiplot.png", height=450, width=800, res=72)
gridExtra::grid.arrange(p1,p2,p3,p4,layout_matrix=layout)
dev.off()
```
とします。


***参考サイト***
[ggplot2 ライブラリで作った複数のグラフを1枚にまとめるには、gridExtra ライブラリが使える](http://id.fnshr.info/2016/10/10/gridextra/)
[ggplot2で複数のプロットをまとめて表示する方法あれこれ](https://qiita.com/nozma/items/cd98ec7938e0783d5d89)
技術書を電子書籍で読むより紙で読むほうが集中できるのはなぜか？

## PDFだと集中しづらいのは気のせいではない？
以前からなんとなく、技術書を紙で読む場合と、PDFで読む場合で集中力に差があるような気がしていました。

具体的には、紙で読む場合はすぐに書いてあることをイメージして没頭できるのに対し、同じ本をPDFで読んでいると目で文字を追っているだけで内容が頭に入ってこない状態になる頻度が高いことに気づき、姿勢や誘惑や照明の色温度の問題かと思いいろいろ試行錯誤していました。

が、このことをツイートしたところ反射光と直接光で認知能力に差が出るとのリプライをいただいたので調べてみたところ、以下の記事を見つけました。
http://blog.livedoor.jp/lunarmodule7/archives/3562467.html


要約すると

* 反射光で文字を読む場合は、脳生理学的に「分析モード」に、心理的に「批判モード」に切り替わる
    * 「分析モード」：文章をドット単位で読み取っていくような情報の受け取り方
    * 「批判モード」：能動的にチェックしつつ取り込むような情報の受け取り方
* 透過光(発光する光)で文字を読む場合は、脳生理学的に「パターン認識モード」に、心理的に「くつろぎモード」に切り替わる
    * 「パターン認識モード」：細部は多少無視して全体の流れを追うような受け取り方
        * 短時間に大量の情報を処理しなければならない場合はこのモードになりやすい
    * 「くつろぎモード」：情報を受動的に、そのまま受け止める受け取り方
* 同じ映画を反射光と透過光で別々のグループに見せた場合に反応は全く異なっていた
    * 反射光グループは理性的に分析・批判的に捉えたが透過光グループは好き嫌いを問題にした
* ディスプレイより紙媒体の方が前頭前皮質(脳内の情報を理解しようとする箇所)の反応が強い

ということでした。

私は電子書籍派なのでkindle版がない場合くらいしか紙の本は買わなかったんですが、初めて知ることを理解するという目的で本を読む場合は発光する画面での電子書籍よりも紙の本の方が良いのかもしれません。
puppeteerを使用してwebページの項目をjsonとして取得してみる

ふと思い立ったので( ˘ω˘)

1. ヘッドレスchromeのpuppeteerでページを読み込み
2. querySelectorで対象のDOMのテキスト内容を取得
3. jsonとして返却

の3つの流れになるのかなと。
やることはシンプルです。

# いざ実装

```web-to-json.js
const puppeteer = require('puppeteer');

const runPuppeteer = async (pageUrl, querySelector) => {
  const browser = await puppeteer.launch({ args: ['--no-sandbox'] });

  const page = await browser.newPage();

  await page.goto(pageUrl);

  const list = await page.$$(querySelector);

  // mapにするとエラーになるので気をつける
  const listTexts = [];
  for (let i = 0; i < list.length; i++) {
    const textContentProp = await list[i].getProperty('textContent');
    const textContent = await textContentProp.jsonValue();

    listTexts.push(textContent);
  }

  await browser.close();

  return listTexts;
};
```

こんな感じでしょうか。
取得したいURLと項目の場所を指定したquerySelectorを設定して、対象のテキストを取得。
一覧データとして返却してあげています。

# yahooのニュースの一覧を取得してみる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/926861b4-18d0-7d3b-7114-88febd7469f3.png)

ここの部分を取得してみます。

```run_yahoo.js
runPuppeteer("https://www.yahoo.co.jp/", "ul.emphasis li")
  .then(console.log)
  .catch(console.error);

/*
[ '正恩氏の訪露調整か 高官協議NEW',
  '飼育員 トラに襲われ心肺停止写真',
  'ノーベル経済学賞に米の2氏写真',
  '純喫茶閉店へ 妻と歩んだ50年写真NEW',
  '接客で魅了 26歳エースの奮闘写真NEW',
  '高橋大輔が3位 素直にヤバい写真',
  'WIN5 払戻金が過去最低を記録写真',
  'まばたきせず 北川景子の4分写真' ]
*/
```

上手く取得できました:relaxed:

# Qiitaの動的な項目を取得してみる。

yahooの場合はサーバサイドレンダリングされているのもあって、DOMの文字列さえあれば取得することは可能でした。
なので、次はQiitaのページ読み込み後に動的に作成されている部分を対象にしてみます。
（HyperAppで画面読み込み後にDOMを構築しているっぽいので、ページのソースを開く、とやってみても対象のDOMが存在しないようです。）
今回は、「いいね」された数の一覧を取得してみようと思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/cc466003-012b-ce88-1cd3-97da3baf811f.png)

```run_qiita.js
runPuppeteer("https://qiita.com/", ".tr-Item_likeCount")
  .then(console.log)
  .catch(console.error);

/*
[ '777',
  '63',
  '149',
  '79',
  '38',
  '39',
  '32',
  '33',
  '37',
  '23',
  '71',
  '33',
  '418',
  '37',
  '15',
  '18',
  '15',
  '56',
  '15',
  '17' ]
*/
```

これも上手く取得できました:blush:
Google ColaboratoryでPyTorch


TensorFlowではなく、PyTorchはいかがでしょうか？という気分。

## 環境の確認

CoLabのNotebook上で、```python --version```してみたら、```3.6.3```だった。
CUDAのバージョンとかがよく分からんけれど、[PyTorchのサイト](https://pytorch.org/get-started/locally/)に従って、```pip install -U torch torchvision```する。

![2018-10-08 21.24.01.png](https://qiita-image-store.s3.amazonaws.com/0/15553/e768da50-08eb-d4f8-ebbb-152d5af9d99f.png "2018-10-08 21.24.01.png")

意外と、あっさりインストールできた。

## チュートリアル実行

そのまま、[チュートリアル](https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html)を、実行してみる。

![2018-10-08 21.40.17.png](https://qiita-image-store.s3.amazonaws.com/0/15553/d884ed4e-a930-8511-5b52-248291fb4285.png "2018-10-08 21.40.17.png")

図のように、trainingも普通に動く。

----

## 本日の結論

GoogleColaboratory上でも、PyTorchをGPU版で動かすことができました、というハナシ。
PHPでリフレクションはこうでしょうが！

テストを書くときにprotected,privateなプロパティを書き換えたいときがあります。
でも、なかなかそらで書けないのです。僕は。

だから、自分への戒めとして書いておきます。
（そもそもアクセスできないテストってどうなの、、、ってのはありますが、、、）

リフレクションはこう！こう書く！！覚えろ！自分！！

```php
        $reflection = new \ReflectionClass($Mailer);
        $property = $reflection->getProperty('oauth');
        $property->setAccessible(true);
        $property->setValue($Mailer, true);
        $this->assertTrue($Mailer->getOAuth());
```
C言語で選択ソート

# 選択ソートとは
最小値（または最大値）を見つけて、先頭に移動。2番目に小さい（または大きい）要素を見つけて、2番目に移動。これを 要素数-1番目 まで繰り返して、整列するアルゴリズム。

分かりやすいが、遅い。安定ではない。
# サンプルコード
ここでは、int型の配列を、選択ソートを用いて小さい順に並べ替える。


```c:selection_sort.c

#include<stdio.h>

/* 値を交換する関数 */
void swap (int *x, int *y) {
  int temp;    // 値を一時保存する変数

  temp = *x;
  *x = *y;
  *y = temp;
}

/* 選択ソート */
void selection_sort (int array[], int array_size) {
  int i, j, min_index;

  for (i = 0; i < array_size-1; i++) {
    min_index = i;   // 先頭要素が一番小さいとする
    for (j = i + 1; j < array_size; j++) {
      if (array[j] < array[min_index]) { min_index = j; }   // 値の比較、最小値の更新
    }
    swap(&array[min_index], &array[i]);   // 最小値と先頭要素を交換
  }
}

int main (void) {
  int array[10] = { 2, 1, 8, 5, 4, 7, 9, 0, 6, 3 };
  int i;

  printf("Before sort: ");
  for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
  printf("\n");

  selection_sort(array, 10);

  printf("After sort: ");
  for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
  printf("\n");

  return 0;
}

```

実行結果

```
Before sort: 2 1 8 5 4 7 9 0 6 3
After sort: 0 1 2 3 4 5 6 7 8 9
```

# 性能

- 要素の移動
1個当たり平均高々1回

- 比較回数

$$(n-1)+(n-2)+\cdots +1=\sum^{n-1}_{i=1}{(n-i)}=n(n-1)/2\to O(n^2)$$

- 交換回数（swap回数）
  - n-1回
  - 要素数が多い場合、実用性は低い
JuliaをJupyter Notebookで使うときに躓いたこと

Windowsに数値計算言語であるJuliaをインストールし，Jupyter Noetebookを用いて環境を用意しようとした際に躓いたことがあったのでメモします．

システム要件
OS:Windows10
Julia:1.0.1

[黒木玄さんが書いてる日本語の資料](https://gist.github.com/genkuroki/81de23edcae631a995e19a2ecf946a4f)が，更新も多く細かい設定についての言及もあるので，参考になる．

Juliaで使用するJupyterのバイナリをAnaconda3のものにしておく．予めインストーラを使ってAnaconda3を

```
E:\\Anaconda3
```
に入れていたとすれば，Windowsに環境変数`JUPYTER`を作成し，

```
E:\\Anaconda3\\Scripts\\jupyter.exe
```
と登録しておく．
Juliaのパッケージを格納するディレクトリも変更可能．環境変数`JULIA_DEPOT_PATH`として登録する．  
自分のWindowsマシンには

```
E:\\JuliaPkg
```
と登録しておいた．
v0.7以前は`JULIA_PKGDIR`だったけど，上記の`JULIA_DEPOT_PATH`に変更された模様  

```
julia> DEPOT_PATH
```
でパスを確認できる．



```julia
julia> ]
```

と入力してパッケージモードに入る．

```julia
(v1.0) pkg> add IJulia
(v1.0) pkg> build IJulia
```
  
# Windows10に入れるときに躓いたこと（ここが本題）
Windows10でAnaconda3を入れるときに，2018-10-08時点での最新のAanacodna3パッケージであるAnaconda3-5.3.0だと，IJuliaのビルド時にエラーが出て追加できななかった．（エラーログをコピーしておくの忘れた...）
とりあえずは最新じゃないけどAnaconda3-5.2.0であれば特に問題なくIJuliaの追加ができた．
過去のAnaconda3のインストーラはここから
https://repo.continuum.io/archive/  
残念ながら根本的な原因が特定できていないけど，対症療法ということで


## Jupyter Notebookの起動
```julia
julia> using IJulia
julia> notebook()
```

# 参考文献
[WindowsでJupyter notebookにJulia v1.0を追加してHello,Worldするまでのメモ](https://qiita.com/SouTakenaka/items/ccfbb5a85330e97af70c)
[[julia] Julia1.0でIJuliaをインストールする](https://piruty.com/?p=631)
[WindowsでJuliaをJupyter notebookから使えるようにするまで](https://qiita.com/10toumushi/items/061d9c40fd534d921b7a)
[Julia 1.0 を Jupyter Notebook から使う](https://ystt.hatenablog.com/entry/2018/08/11/141132)
[JULIA_PKGDIR and Julia-0.7](https://discourse.julialang.org/t/julia-pkgdir-and-julia-0-7/11672)
[Change Package directory in Julia](https://stackoverflow.com/questions/36398629/change-package-directory-in-julia)
[julia Pkg](https://docs.julialang.org/en/latest/stdlib/Pkg/)
lodashで配列から空の値を排除

# 概要
Vue.jsでSPAを作っているときに配列の操作で、値のセットされているものだけに絞り込みたくて調べた内容をめもしておく。

# lodash/transform
Googleで調べてみるとlodashのtransformが配列の加工に使えそうな感じで調べてみる。
下記は、オフィシャルサイトに書かれていた配列を加工する例です。

```js
_.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
  (result[value] || (result[value] = [])).push(key);
}, {});
// => { '1': ['a', 'c'], '2': ['b'] }
```
更に調べてみると、望んでるようなコードが見つかる。

```js
 _.transform(obj, function(result, value, key) {
    if (typeof value === 'object') {
      result[key] = _.removeEmptyObjects(value);
    } else if (!_.isEmpty(value)) {
      result[key] = v;
    }
  });
```
これを踏まえて、下記のコードを作成。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>空の値を取り除く</title>
</head>
<body>
  <div id="app">
    <h2>空の値を取り除く</h2>
    <pre>{{ $data.list }}</pre>
    <pre>{{ $data.result }}</pre>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data(){
        return {
          list: {
            id      : '1',
            name    : 'hoge',
            birthday: null,
            sex     : '',
            items   : [
              'りんご',
              'みかん'
            ],
            empty   : [],
            object  : {}
          },
          result: null
        }
      },
      created() {
        // シャローコピー
        const list = Object.assign({}, this.list);

        // 配列から空の値を取り除く
        this.result = this.removeEmpty(list);
      },
      methods: {
        /**
         * 配列から空の値を取り除く
         * ※ 対象: null, 空文字, 空の配列, 空のオブジェクト
         */
        removeEmpty: function(arr) {
          return _.transform(arr, function(result, value, key) {
            if (!_.isEmpty(value)) {
              if (typeof value === 'object') {
                result[key] = this.removeEmpty(value);
              } else {
                result[key] = value;
              }
            }
          }.bind(this));
        }
      }
    });
  </script>
</body>
</html>
```
# 実行結果
下記のように空の値が取り除かれました。

**<加工前のデータ>**

```json
{
  "id": "1",
  "name": "hoge",
  "birthday": null,  // -> 取り除かれる
  "sex": "",         // -> 取り除かれる
  "items": [
    "りんご",
    "みかん",
    null,            // -> 取り除かれる
    ""               // -> 取り除かれる
  ],
  "empty": [],       // -> 取り除かれる
  "object": {}       // -> 取り除かれる
}
```

**<加工後のデータ>**

```json
{
  "id": "1",
  "name": "hoge",
  "items": [
    "りんご",
    "みかん"
  ]
}
```

以上

# 参考サイト
* [lodash - transform](https://lodash.com/docs/4.17.10#transform)
* [How to remove empty values from object using lodash](https://stackoverflow.com/questions/38275753/how-to-remove-empty-values-from-object-using-lodash)
*
VORTEX CORE 47key のキーボードキーバインド(Web利用削除)

先日、Web上でVORTEXのキーボードマッピングを変更した。
その設定をずっと続けるつもりだったが、~~試しに戻してみる衝動に駆られたため、~~ 今回記録に残す意味で、ファームウェア戻し手順を投稿する。
映画『ターミネータ』で言えば"再起動"みたいな感じかな。

通常のファームウェアを使えば元に戻るだろうと安易に考えていた。
そんなに甘くない。











# 案ずることなかれ
心配しなくても戻す方法があった.
良かった。



## 通常配布のファームウェア
通常は、exeファイルを立ち上げ、OKボタン押下にて、最新版のファームウェアが適用されたキーボードになる。
しかし、今回は、Webアプリケーションにて、キーマッピングファイルをキーボードに反映させるために、違うファームウェアを適用してしまっていたようで、戻せない状態になった。
人ごとのように発言しているが、幾日前に[vortexKeymap.exe起動](https://qiita.com/chesscommands/items/b67102fe3aa870fe5858#vortexkeymapexe%E8%B5%B7%E5%8B%95 "CORE by MPC")して、別ファームウェアに書き換えたのが原因だ。

今回同じexeファイルを用いて戻す。



















# vortexKeymap.exe
前回のようにexeファイルを立ち上げ、そして前回とは違い、"Bin Group:"欄の`CORE by MPC`を選び、OKボタンをクリックする。

![HWPでアップデート.jpg](https://qiita-image-store.s3.amazonaws.com/0/82414/d171f89a-6aba-d610-2b37-45d8548ba8d4.jpeg)


## アップデート完了
きっと障害無く綺麗にアップデートが完了する。

![upgrade.jpg](https://qiita-image-store.s3.amazonaws.com/0/82414/8191b517-ae65-e61e-da0e-1079ffe811f0.jpeg)


## firmware version
前回のアップデートと同じファームウェアバージョンに戻ったことが確認できる。

![アップデート完了.png](https://qiita-image-store.s3.amazonaws.com/0/82414/d32f647a-a8c8-3ff8-d910-89e7b001ea62.png)







# うれしいのかうれしくないのか
ファームウェアのバージョンを戻すが、`Vortex.cys`ファイルはキーボードに残ったままになる。
要は、exeファイルでファームウェアのバージョンを書き換えるだけでキーマッピングの切り替えが出来るということ。





# Webでの変更履歴は消える
1回目は、キーボード単体でキーマップを変更した。
2回目は、Webでキーボードのキーマップを変更した([vortexgearのmpc](http://www.vortexgear.tw/mpc/index.html "変更ページ"))。
ずっと、Web上で変更出来れば良いのだが、Web履歴を削除した場合にキーマップも消えてしまう。
そして、その変更はすべてローカル上にダウンロードしたファイルのみになる。
それは、Webで再変更する場合は、1からキーを変更していかなければならない。非常にめんどくさい。

![vortexgearのmpc.jpg](https://qiita-image-store.s3.amazonaws.com/0/82414/66d739ed-9bee-986d-d625-ea7bfef1e23b.jpeg)

頻繁に変更するならば、Web変更よりキーボード単体で変更出来ることを優先させようと思い、今回やり方を記録するため投稿した。








以上だ。
macコマンド　生粋のメモ

cd cd ../ cd 〇〇/〇〇 cd /
移動系
mkdir touch touch fileName{1...10}
ディレクトリ作成　ファイル作成　複数作成

cp ファイル名/新しいファイル名　  cp ファイル名/ディレクトリパス　cp -R
コピーできる ディレクトリコピー

rm
削除できる

mv ファイル名/新しいファイル名　　mv　ファイル名/ディレクトリ名（パスなど）
同じディレクトリ内だとファイル名を変更できる　　　ファイル移動ができる

cat
ファイルが覗ける

ls　　　ls -a
ディレクトリ内の要素一覧 隠しファイルやディレクトリを全て見ることができる

touch 
ファイル作成ができる

*  *x  x* *x*
*をつけた位置に何が来ていても全て表示

wget url
urlで指定した画像や動画などをカレントディレクトリにダウンロードできる

su-　sudo
スーパーユーザになったり、一時的にスーパーユーザー権限を使える

nano　　　　　　control o  control x
エディットできる セーブ　終了

pstree
現在動いているプログラムを全て表示する

ps ps aux
linuxで動作しているプロセス一覧 auxはオプションで（プロセスとは動作中プログラムのこと）
-A　全てのプロセスを表示する
-a 端末のプロセス
-x 操作外のプロセス
u cpuやメモリの使用率も表示される

top
プロセスをリアルタイムに観測することが出来る


chmod　権限の指定　ファイル名/ディレクトリ名
このコマンドでファイルやディレクトリに対してアクセス権限を指定することができる（パーミッション）
-rw-r--r--
左から順にユーザー　グループ　その他

所有ユーザー　u
所有グループ　g
その他を　　　o

+r（読み込み権限を与える）
+w（書き込み権限を与える）
+x（実行権限を与える）
-r（読み込みを不許可にする）
-w（書き込みを不許可にする）
-x（実行を不許可にする）

この二つの組み合わせで権限を操ることが出来る。
権限を操れるのは所有ユーザーのみなので他のユーザーが書き換えることはできない。

sw_vers
OSのバージョンが知れる

uname -a
linuxのディストリビューションが知れる

echo "文字"　　　echo $x
エコーはその後に続く文字を出力できる
$マークを使うと変数として認識する

expr　1+1
シェル画面上で計算できる
掛け算する場合は \* で認識する


ないコマンドは
brew install ~　　で持ってこれるのもある 

osascript -e 'tell application "Finder" to sleep'
スリープ

osascript -e 'tell application "Finder" to restart'
再起動

osascript -e 'tell application "Finder" to shut down'
シャットダウン

node ファイル名; osascript -e 'tell application "Finder" to sleep'
AWS入門 CloudFrontを使ったデータ配信

前 [AWS入門 Elastic IPを使った独自ドメインでのサイト運用](https://qiita.com/tseno/items/1c6303d778f9089f6f89)
次 [AWS入門 作成中](https://qiita.com/tseno/items/)

## CloudFrontとは

- CloudFrontは、Webコンテンツ（HTML、CSS、JavaScript、画像、動画ファイルなど）を**エッジロケーション**と呼ばれているネットワークを経由して配信する。エッジロケーションとは、CloudFrontやRoute 53を提供するためのデータセンター。
- 要するに、Webコンテンツのキャッシュサーバー。

## CloudFrontを使ったWebコンテンツ配信

- 手順の前に、EC2やS3でWebサイトを構築しておく

### 1/3.CloudFrontの起動

- AWSマネジメントコンソールから、CloudFrontをクリックする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/c003baad-3163-b7d5-fb24-06d0ca8fb78d.png)

### 2/3.コンテンツ配信方法の設定

- Create Distributionをクリックする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/5def17b2-a261-4664-aa9a-1d2c55da7d7e.png)

- Web・・・HTTPやHTTPSを使ってアクセスするWebコンテンツを配信。ここではこちらを選択する。
- RTMP・・・Adobe社が開発しているストリーミング配信プロトコルである、RTMPを使って動画などをストリーミングする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/9c25bb98-c2ca-0de7-cb84-cff90d56b74f.png)

### 3/3.コンテンツ配信の設定

- Origin Domain Name・・・Webコンテンツの配信元のドメインを選択。EC2インスタンスのパブリック DNS (IPv4)を入力した。
- Origin Path・・・トップページのパスを指定。今回は空。
- Origin ID・・・任意のIDを設定。WebSampleと入力した。
- その他にも、キャッシュの設定やHTTPメソッドの設定、SSL証明書の設定、ログの設定などがある。
- 一番下の、Create Distributionをクリックする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/a7185ade-78a5-a790-ec43-a521baae00bc.png)

- StatusがDeployedになったら配信完了。10分くらいかかった。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/90da8d96-f333-e6ee-eef5-a00404106e33.png)

- Domain Nameのアドレスにブラウザでアクセスして、表示されることを確認。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/078c850b-1476-91d8-9629-40ca0effa954.png)

- 削除する場合は、Disable → Deleteの順で削除する。

参考
[Amazon Web Servicesではじめる新米プログラマのためのクラウド超入門](https://www.shoeisha.co.jp/book/detail/9784798144696)
AWS勉強 ~Webサーバーソフトをインストールする~

# Webサーバーソフトをインストールする

前の記事で構築したサーバーにWebサーバーソフトをインストールすることでWebサーバーとしてインターネットに公開する!

## Apache HTTP Serverのインストール

サーバーをWebサーバーとして機能させるためには「Webサーバーソフト」をインストールする.
本書ではWebサーバーソフトとして「Apache HTTP Server(Apache)」を用いる.

### サーバーにApacheをインストールする 

#### 手順1 ~インスタンスにログイン~

SSHでログインしましょう.

#### 手順2 ~Apacheをインストールする~

次のコマンドを入力してインストールする.

```shell
$ sudo yum -y install httpd
```

#### 手順3 ~Apacheを起動する~

次のコマンドを入力してApacheを起動する.

```shell
$ sudo service httpd start
```

#### 手順4 ~自動起動するように構成する~

サーバーを再起動するとまた停止してしまうので,
Apacheも自動的に起動するように構成する.

```shell
$ sudo chkconfig httpd on
```

### Apacheのプロセスを確認する

ここまででhttpdが起動したはずなので,次の2つの方法で確認する.

#### ①プロセスを確認

Apacheはhttpdというファイルが実行コマンドである.
もし実行中ならばこのhttpdのプロセスがサーバー上に存在するはずだ.
Linuxシステムではpsコマンドで確認できる.

```shell
$ ps -ax
```

#### ②ネットワークの待ち受け状態を確認する

エンドユーザーがWebブラウザを通してこのサーバーにアクセスするとhttpdはそれに対応するコンテンツを返す.
そのためhttpdはポートを開けて待機している.
lsofコマンドを使用してポートの状況を調べよう.

```shell
$ sudo lsof -i -n -P
```

次のような結果が返ってくる.

<img width="486" alt="スクリーンショット 2018-10-08 1.51.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/5ec1767d-5da7-a1b0-ef3d-1d35c733a189.png">

Apacheはポート80番で待ち受けていることがわかる.
ポート80番はWeb通信で用いる「HTTP」のウェルノウンポートだ.


## ファイアウォールを設定する

まずは実際にWebブラウザを使用してアクセスしてみる.

### Webサーバーに接続する

<img width="843" alt="スクリーンショット 2018-10-08 20.32.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/323dbff6-704a-997f-0735-2f8290b51912.png">

しかし残念ながらこのままでは接続できない.

<img width="1280" alt="スクリーンショット 2018-10-08 20.37.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/0a6d6a1b-22bf-96b7-a7d5-2665ceae25e9.png">


### ファイアウォールを構成する

接続ができないのはポート80番がファイアウォールによってブロックされているからだ.
ファイアウォールを設定変更してポート80番を開けるには次のようにする.

#### 手順1 ~セキュリティグループの設定画面を開く~

<img width="844" alt="スクリーンショット 2018-10-08 20.48.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/16752d47-a2a8-7186-4137-1f659b4ca67e.png">

#### 手順2 ~ポート80番は全てのホストからの通信を許可する~

<img width="852" alt="スクリーンショット 2018-10-08 20.51.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/a9a7dadd-619b-ba1b-506b-b6ef43474566.png">

からの,

<img width="840" alt="スクリーンショット 2018-10-08 20.56.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/81ad1e68-f480-019f-41ac-1644dce487dd.png">

これでポート80番が通るようになったので,
もう一度Webブラウザで接続してみる.

<img width="1280" alt="スクリーンショット 2018-10-08 20.58.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/180668/f67513c1-96a5-19e1-823d-27c77d969832.png">

### 感想

コマンドを実際に使って見てプロセスを見る方法を知ることができた,
業務中でも処理が重かったりした際にコマンドで何が動いているか確認してうまく対処できるのかなと思った.
ファイアウォールについても理解が深まった.
VirtualBox上のCentOS7にdockerでPostgresql環境を構築

## はじめに
ローカル環境にVirtualBoxを使用して開発環境を構築しようと考えまして、
どうせならdockerを使用してやってみようと思い、その手順をまとめます。

開発環境は、WEBサーバ(PHP),DBサーバ(Postgresql)という構成を考えています。

恥ずかしながら、いままでdockerを使用したことがなかったため、
まずはDBサーバを構築してみようと考え、その手順をまとめます。
かなり基礎的な部分からまとめています。

## 作業環境
- MacOS X Yosemite 10.10.5 

## 1. VirtualBox をインストール
[公式サイト](https://www.virtualbox.org/wiki/Downloads)からVirtualBoxをダウンロードして、インストールをします。

## 2. CentOS7をダウンロード
[公式サイト](https://www.centos.org/download/)からCentOS７のisoをダウンロード。

## 3. VirtualBoxからCentOS7の仮想マシンを作成し、各種設定を実施
久々に構築したため、ちょこちょこ躓いた部分があったため、
以下のURLページを参照して実施
※centosは最小構成でインストールしています。
1. 構築後、解像度変更
https://qiita.com/aminevsky/items/e619669963cb68012755
2. ssh設定
https://qiita.com/ebkn/items/751ed657629ba8d4ab0a
3. root接続許可
https://qiita.com/sugimount/items/ea1a7e28928d58e51e69
4. yumを使用して、アップデートを実施。

```
# yum update
```

## 4. dockerインストール
yum からインストールを実施します。

```
# yum install docker
```

## 5. docker開始
dockerを開始します。

```
# systemctl start docker
```

## 6. OSの起動時にDockerが自動で起動するようにする

```
# systemctl enable docker 
```
## 7. dockerhub から postgresql のイメージをダウンロード
[docker Hub](https://hub.docker.com/_/postgres/)から postgresql のイメージをダウンロードします。

```
docker pull postgres
```

## 8. ダウンロードを確認
ダウンロードされているか、以下のコマンドでイメージ一覧を確認します。

```
# docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
docker.io/postgres   latest              084ec18124c8        3 weeks ago         228 MB
```

## 9. コンテナの作成と実行
以下のコマンドを実行して、コンテナの作成と実行を実施します。

```
# docker run -d --name dev-postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres:latest
```

## 10. 起動確認
作成と起動されたか確認します。

```
# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
18e5e56a13b3        postgres:latest     "docker-entrypoint..."   26 seconds ago      Up 24 seconds       0.0.0.0:5432->5432/tcp   dev-postgres
```
## 11. 起動中のコンテナにアクセス
起動はしましたが、postgresqlにアクセスできるかどうかを確認します。
まずは、起動しているコンテナ(dev-postgres)にアクセスします。

```
# docker exec -it dev-postgres bash
```
## 12. コンテナ内でpostgresqlに接続
コンテナ(dev-postgres)内でpostgresに接続します。

```
psql -U postgres
パスワードは docker run ~ 時に設定したもの
```

## 13. postgresqlでコマンド実行
バージョンを表示するSQLを実行してみます。

```
postgres=# select version();
                                        version                                        
---------------------------------------------------------------------------------------
 PostgreSQL 10.5 on x86_64-pc-linux-musl, compiled by gcc (Alpine 6.4.0) 6.4.0, 64-bit
(1 row)
```

***

まずはdockerでpostgresqlが動作するところまで構築しました。
次はWebサーバをdockerで構築する手順をまとめようと思います。


## 参考URL
https://qiita.com/nagi244/items/10623f509bba6887192d
https://qiita.com/uhooi/items/f8c67a9e716a226e28cd