OmniAICreator/Qiita-1.07M huggingface dataset:
【PostgreSQL】外部キー指定時のMATCH matchtype[FULL | PARTIAL | SIMPLE]について

テーブル作成時の外部キー指定の際に「matchtype」が不明だったので調べました。

##CREATE時に外部キーを指定する構文

###列に指定する場合
```sql
CREATE TABLE table(
column INTEGER REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ]
);
```

###表に指定する場合
```sql
CREATE TABLE table(
column INTEGER,
CONSTRAINT fkey_name FOREIGN KEY ( column [, ... ] )
 REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ]
);
```
##matchtypeの種類
公式ドキュメントからの引用です。
> 
1.FULL
　全ての外部キー列がNULLとなる場合を除き、複数列外部キーのある列がNULLとなることを許可しません。それらがすべてNULLであれば、その行は被参照テーブル内で一致があることは要求されません。
2.PARTIAL
　まだ実装されていません。
3.SIMPLE（デフォルト）
　外部キーの一部がNULLであることを許可します。それらの一部がNULLであれば、その行は被参照テーブル内で一致があることは要求されません。
（PostgreSQL 9.4.5文書：https://www.postgresql.jp/document/9.4/html/sql-createtable.html）

外部キーに複数のカラムを指定した場合の制約ですね。
`FULL`は[外部キー列が全てNULL]または[外部キー列が全てNULL以外の値]であることを保証する制約です。
`SIMPLE`は特に制約しない、ということですね。
最低限度的 Docker with PHP

Docker 的初心者，最近因為想要弄一些東西就來摸 Docker 了。
公司後端的專案雖然有頻繁的在用 Docker ，但是身為一個行動端 (iOS) 的工程師，對於要怎麼開始動手寫一個 Dockerfile 還真的是不知道（笑）。

這篇就是看完 [這部影片](https://youtu.be/YFl2mCHdv24) 之後，如何用最低限度的設定和內容建置 Docker 的筆記。

## 環境

**OS:** macOS Mojave 10.14（18A391）
**Docker:** 18.06.1-ce-mac73 (26764)

## 資料夾結構

```
├── Dockerfile
└── src
    └── index.php
```

很簡單，就一個 PHP 的檔案，和 docker 的設定檔即可，
PHP 檔案則放在 `src` 這個資料目錄下。

### index.php

``` php:src/index.php
<?php
echo "hello world";
```

這裡放個 echo 出字串即可。

## Dockerfile 設定檔

接著就來動手寫 Dockerfile，
推薦可以用 Visual Studio Code 寫，會有上色和自動完成等功能很方便。

先來看完成的檔案內容：

``` Dockerfile:Dockerfile
FROM php:7.2.10-apache-stretch
COPY src/ /var/www/html/
EXPOSE 80
```

### PHP 設定檔

``` Dockerfile
FROM php:7.2.10-apache-stretch
```

因為我們要執行的是 PHP 應用程式，所以就直接用 PHP 就可以了。

https://hub.docker.com/_/php/

連結是從 Docker Hub 上 php 官方所推出的設定檔。
在當前的時間點(2018/10/6)，除去 7.3 RC 的檔案，最新的就是 7.2.10 了
要搭配 web server 的關係，所以就選了有 `apache` 字眼的設定檔：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/41979/3f5bc908-8e34-c877-f07f-15c9520867c7.png)

### 複製檔案到 Container （容器）裡

``` Dockerfile
COPY src/ /var/www/html/
```

就是把 `src` 資料夾裡面的東西複製到 docker 容器裡的 `www/html` 資料目錄。

### 暴露 80 port

``` Dockerfile
EXPOSE 80
```

讓外界可以透過 80 port 來存取頁面

## 建置

``` bash
docker build -t hello_world .
```

這個指令可以根據 Dockerfile 的內容建置出對應的映像檔，
而透過 -t 這個 flag ，就可以來自定像是 `hellow_world` 這樣的名稱。

＊ 參考： https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t

## 運行

``` bash
docker run -p 8080:80 hello_world
```
在運行的時候，加上 publish flag `-p` 就可以進行 port 相關的設定

`8080:80`

- **前者** 對應到的是主機開放出來的 port ，就是在瀏覽器存取 server 的時候可以存取到的 port
- **後者** 對應到的是 docker container 開放出來的 port ，在這邊的範例就是前面寫的 `EXPOSE 80` 的 `80`

執行了這個指令之後，就可以在透過 8080 port ，也就是 [localhost:8080](http://localhost:8080) ，
來存取從透過 docker container 80 port 所開放出來的頁面：

![image](https://qiita-image-store.s3.amazonaws.com/0/41979/ebb6c773-783f-2e24-c0b8-cfbaa2a6cc0d.png)

而這個時候終端機端會呈現執行中的狀態，如果要終止的時候，按下 `Ctrl`+`C` 即可停止執行。

＊ 參考： https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose

## 反映更新

在這時候運行起來的 server 所回應的頁面， **並不會** 因為 `src/` 裡面的檔案有所改變，頁面重整就會改變。
因此在運行的指令時，加上掛載的 `-v` 這個 flag ，
就可以把 `src/` 掛載到容器裡的 `/var/www/html/` 資料目錄，開發上就會更加方便：

``` bash
docker run -p 8080:80 -v /Users/path/to/project/src/:/var/www/html/ hello_world
```

這時候運行起來的機器，當 src 裡面的檔案有變更，在瀏覽器重新整理就會自動變更了。

＊ 參考： https://docs.docker.com/engine/reference/commandline/run/#mount-volume--v---read-only

## 程式碼與指令總結

最低限度的 Docker 的程式碼的部分沒有很複雜：

``` Dockerfile:Dockerfile
FROM php:7.2.10-apache-stretch
COPY src/ /var/www/html/
EXPOSE 80
```

``` php:src/index.php
<?php
echo "hello world";
```

指令：

``` bash:建置
docker build -t hello_world .
```

``` bash:運行
docker run -p 8080:80 -v /Users/path/to/project/src/:/var/www/html/ hello_world
```

以上

如果有任何回饋或是需要修改的地方，
歡迎在下面留言告訴我～ :hibiscus: 

## 參考

- [Learn Docker in 12 Minutes 🐳](https://youtu.be/YFl2mCHdv24) (YouTube)
Python 円周率を求める

# Python で 円周率を求める
円周率を使いたいとき、標準モジュールである`math`をimportし、`math.pi`を利用すればすぐにでます。

3.1415926535897932384626433832795...

円周率πは無理数ですが、無理数の中で1番役に立つ数だと言っても過言では無いと思います。  
その円周率を求めてみたいとは思いませんか?

ということで、今回は円周率を求めたいと思います。(もしかしたら既出かも...?)

## 円周率πに隠された規則性

無理数は小数点以下が規則性がなく無限に続き、分数で表せない数です...が、実は分数で表すことができます。それがこちら。

π=4(1/1 - 1/3 + 1/5 - 1/7 + 1/9 - ...)

これを展開して...

π=4/1 - 4/3 + 4/5 - 4/7 + 4/9 - ...

これを利用して求めていきます。

## πを求める

規則性があるので簡単に求めることができます。  
次の通りです。

```Python:pi_test.py
A=100
pi=0
for L in range(1,A):
	if L%2==0:
		B=-1
	else:
		B=1
	pi+=(4/(2*L-1))*B
print(pi)
```

Aの値を大きくすれば、時間はかかりますがより詳しくなります。

Aを150にすると、おなじみの3.14が出ます。

僕はiosアプリのPythonista3を使っているのでA=1千万が限界かもです。  
google colaboratoryはインターネット環境が必要ですが、スーパーコンピュータが処理しているので、もしかしたらA=1億でもいけるかもしれません。

## グラフで見てみる
どのように値が変化して円周率が求められるのか見てみましょう。
`matplotlib.pyplot`を使います。

```Python:pi_test2.py
import matplotlib.pyplot as plt
A=100
pi=0
piplot=[]
for L in range(1,A):
	if L%2==0:
		B=-1
	else:
		B=1
	pi+=(4/(2*L-1))*B
	piplot.append(pi)
plt.plot(piplot)
plt.show()
```

実際にAの値を変えながらやってみてください。
***
最後まで見てくれて本当にありがとうございます！
Netlifyに上げたReactアプリのエラーをnetlify.tomlで解決する

# Overview

`React App` を `Netlify` へ上げる際に詰まったことがいくつかあり、Netlifyの公式Docsは英語only( https://www.netlify.com/docs/ )で、qiitaなどの日本語記事があまり見られなかったので共有します。

使用した環境は以下です。

- node.js  v10.7.0
- React.js v16.4.1
- yarn      v1.7.0

# 困りごと①：環境ごとにビルドコマンドを分けたい
Netlifyはかなり便利で、ビルドしたいときにGUIからBuildコマンドを設定するだけで本番環境用ブランチが更新される度に設定されたBuildコマンドを自動で実行してデプロイしてくれます。（しかも無料で！神！）
開発する際は複数の環境を作って開発することがあると思います。（今回は本番環境とステージング環境で開発しようとしていました。）
NetlifyのGUIでのデプロイ設定は複数環境デプロイは対応していないので、 GUI設定を超えたカスタマイズをしたいときには `netlify.toml`　というファイルで設定をする必要があります。 [netlify.tomlの英語DocsはこちらをClick](https://www.netlify.com/docs/netlify-toml-reference/)

netlify.tomlはgitレポジトリのトップに作成し、僕は以下のような設定になりました。

```toml:netlify.toml
# デプロイしたいディレクトリの設定
[build]
  publish = "/dist"

# 本番環境のビルドコマンド
[context.production]
  command = "yarn && yarn prod"

# ステージング環境のビルドコマンド
[context.staging]
  command = "yarn && yarn stg"
```

# 困りごと②：リロードすると404 Not Foundが表示される
SPAの場合は特別に設定しなければいけないみたいです。
デプロイしたいディレクトリに `_redirects` というファイルを作成し、以下のように設定します。

```text:_redirects
/*    /index.html   200
```

また、 `netlify.toml`　をすでに作っているなら、こちらに `_redirects` の内容をマージして設定できるみたいなので、僕は `_redirects` を作成せずに `netlify.toml` に設定をすべて書き込みました。
[詳細はこちらに](https://www.netlify.com/docs/redirects/)

# 最終的な netlify.toml の内容
僕の `netlify.toml`ファイルは以下になりました。

```toml:netlify.toml
# デプロイしたいディレクトリの設定
[build]
  publish = "/dist"

# 本番環境のビルドコマンド
[context.production]
  command = "yarn && yarn prod"

# ステージング環境のビルドコマンド
[context.staging]
  command = "yarn && yarn stg"

# SPA用の設定
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200
```
jsdoでblockly その３

#概要
jsdoでblocklyやってみた。
processingやってみた。

#写真
![](http://jsdo-static-contents.s3.amazonaws.com/images/capture/c/D/p/cDpX.jpg?t=1538776856)


#成果物

http://jsdo.it/ohisama1/cDpX

以上。
jsdoでblockly その２

#概要
jsdoでblocklyやってみた。
fizzbuzzやってみた。

#写真

![](http://jsdo-static-contents.s3.amazonaws.com/images/capture/W/j/L/WjLD.jpg?t=1538813965)


#成果物

http://jsdo.it/ohisama1/WjLD


以上。
jsdoでblockly

#概要
jsdoでblocklyやってみた。
hello worldやってみた。

#写真

![](http://jsdo-static-contents.s3.amazonaws.com/images/capture/U/k/I/UkIq.jpg?t=1538797584)

#成果物
http://jsdo.it/ohisama1/UkIq


以上。
VSCodeでマークダウンを編集するときに制御文字が出てくる問題を解決する方法

## はじめに
環境がMacでエディターがVSCodeのとき、マークダウンを編集してると下記の画像のような制御文字が混ざりこんでしまうことがあります。

![image](https://i.gyazo.com/928b7d0f0e65a6669cfbbadd6a321835.png)

なので制御文字がでないようにVSCodeで設定したことをここに書いていきたいと思います。


## 1. editor.renderControlCharactersを削除する
`settings.json`に

```
"editor.renderControlCharacters": true,
```

と書いてあげることでVSCodeに制御文字を表示することができるので、どこに制御文字があるか分かります。
ただ、今回は制御文字を自動的に削除していきたいので、`settings.json`に

```
"editor.renderControlCharacters": true,
```

の記述がある人は削除してください。
(`settings.json`に`"editor.renderControlCharacters": true,`がない場合は1の手順はスキップしてください）


## 2. Remove backspace control character をインストールする
https://marketplace.visualstudio.com/items?itemName=satokaz.vscode-bs-ctrlchar-remover

VSCodeの拡張機能からRemove backspace control characterをインストールしてください。

Remove backspace control characterをインストールすることで、制御文字を削除することができる設定ができます。


## 3. 保存時に制御文字を削除する設定をする
Remove backspace control characterの[日本語ドキュメント](https://github.com/satokaz/vscode-bs-ctrlchar-remover/blob/master/README_ja.md)にもありますが、`settings.json`に以下の記述を追加したら、保存時(command + s)に制御文字を削除します。

```
"editor.formatOnSave": true
```

以上の設定で保存するたびに制御文字が削除されるので、スムーズにマークダウンで記述をすることができます。


## 参考
[Remove backspace control character](https://marketplace.visualstudio.com/items?itemName=satokaz.vscode-bs-ctrlchar-remover)
[vscode-bs-ctrlchar-remover README](https://github.com/satokaz/vscode-bs-ctrlchar-remover/blob/master/README_ja.md)
プロジェクトごとにcronファイルを分けて管理する

ひとつのサーバに複数のプロジェクトのcron設定を`crontab -e`で管理するのを辞めたいので`/etc/cron.d`配下にcronファイルを設置するようにする。

#cronファイルの設置方法

cronファイルを`/etc/cron.d`に設置します。

```
# touch /etc/cron.d/sample
```

パーミッションを644に変更します。

```
# chmod 644 /etc/cron.d/sample
```

所有者をrootに変更します。

```
# chown root:root /etc/cron.d/sample
```

設置したcronファイルの内容はこのようになります。

```:/etc/cron.d/sample
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# * * * * * [user] [command]
0 * * * * root /path/to/hoge

```

最後にログ`/var/log/cron`で正常に動いているかを確認します。

```
# tail -f /var/log/cron
Oct  3 00:00:00 localhost CROND[9999]: (root) CMD (/path/to/hoge)
```
牛に擬態した人間はAWSのrekognitionで人間であることを見破られないのか？

## AWS rekognitionを使ってみる

最近はTensorflowでサービスを作ってみましたが、今回はAWSのrekognitionを試してみました。

Tensorflowの記事はこちら。

[【まとめ】機械学習初心者がTensorflowでネコの画像認識をつくってみたらどうなったか](https://qiita.com/umeee/items/b35a344815eba735e460)

## はじめに
前提事項です。
こんな状態から使ってみました。

- AWSはEC2を少しさわったことがある程度
- S3は使ったことない
- rekognitionもない

## 試すこと

普通に画像判定してもおもしろくないので、今回はこの牛に擬態した人間が見破られるかどうかを試してみます！
フリー画像よりもってきました。

![__www.pakutaso.com_shared_img_thumb_TSURU170321-85 mm-109.jpg](https://qiita-image-store.s3.amazonaws.com/0/117147/01e0be32-4348-e9e1-1054-a62dfb1d67fb.jpeg)

顔は完全に牛ですが体は人間です。
見破られる可能性は50%くらいでしょうか。


## まずはIAMの設定
まずはIAMの設定です。
「アクセス権限の追加」で「AmazonRekognitionReadOnlyAccess」を追加します。

![68747470733a2f2f71696974612d696d6167652d73746f7265.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117147/ccb63680-4ef9-c195-fbfa-d4e2411f8d21.png)

こんな感じで追加されればOK。

## S3に画像をアップロードする
次に画像をS3にアップロードします。

S3でBucketを作成して、ファイルをドラッグ&ドロップでアップしました。
S3の作成方法はGUIからなんとなくできたので割愛します。

![reko3.png](https://qiita-image-store.s3.amazonaws.com/0/117147/83f56093-f0e4-6608-dab5-9438d7ea10e3.png)

ここでフリー画像の牛人間ちゃんをアップします。

![__www.pakutaso.com_shared_img_thumb_TSURU170321-85 mm-109.jpg](https://qiita-image-store.s3.amazonaws.com/0/117147/01e0be32-4348-e9e1-1054-a62dfb1d67fb.jpeg)

アップした後、オブジェクトの読み取り権限がついていない場合は付与する必要があります。
これがないと後のCLI実行でエラーになってしまいます。


## S3へのアクセス確認

次にコマンドラインからBucketへのアクセス確認をしておきます。

```
$ aws s3 ls s3://{bucketname}/
2018-10-06 16:05:17   11458119 cow.jpg
```
Bucket名を指定するとアップした画像ファイル名が表示されます。
OKですね。

## AWS CLIの設定

いよいよrekognitionの実行！の前に、AWS ALIの設定をしていない場合はまず設定しておきましょう。

aws configure と入力することで対話形式で設定できます。

```
$ aws configure
AWS Access Key ID: {アクセスキーID}
AWS Secret Access Key: {シークレットキー}
Default region name: ap-northeast-1
Default output format [None]: json
```

アクセスキー、シークレットキーを入力します。
Default region, formatも設定しておきます。

## rekognition実行！

いよいよrekognitionで確認です。
以下のコマンドで牛人間ちゃんを指定して実行すると・・・

```
$ aws rekognition detect-labels --image "S3Object={Bucket=rekognitions3ap,Name=cow.jpg}" --region ap-northeast-1
{
    "Labels": [
        {
            "Confidence": 99.1922378540039,
            "Name": "Human"
        },
        {
            "Confidence": 99.19222259521484,
            "Name": "People"
        },
        {
            "Confidence": 99.1922378540039,
            "Name": "Person"
        },
        {
            "Confidence": 77.85262298583984,
            "Name": "Kiss"
        },
        {
            "Confidence": 77.85262298583984,
            "Name": "Kissing"
        },
        {
            "Confidence": 50.69141387939453,
            "Name": "Face"
        },
        {
            "Confidence": 50.69141387939453,
            "Name": "Portrait"
        }
    ],
    "OrientationCorrection": "ROTATE_0"
}
```

結果が出力されました！

Human,People,Person
それぞれConfidenceが99を超えていますね！

残念ながら牛に擬態した人間も、人間であることは見破られてしまったようです。

おそるべしrekognition!

## まとめ
AWS rekognitionは牛に偽装した人間でも容易に見破ることができる。
Vuforia の File Driver Sample をビルドする

## 概要

[Vuforia の External Camera の例として紹介されている File Driver](https://library.vuforia.com/articles/Solution/file-driver.html) のビルドにちょっと手間取ったのでビルドするために必要な作業のログです。

## 手順

環境は Windows 10, Visual Studio 2017 です. mac だとうまくいきませんでした.

1. https://developer.vuforia.com/downloads/samples の 
Advanced Topics の `Download File Driver` からコードをダウンロード
2. ↑と同じページの Core Features の `Download for UWP` をダウンロード
3. ダウンロードした zip を適当に解凍
4. cmake をダウンロード & インストール (3.9.6 を使ったけどおそらくほかのバージョンでも大丈夫だと思います)
5. 解凍した 1 のディレクトリにコマンドプロンプトで入ります
    - `ex) cd C:\Users\miro\Downloads\vuforia-driver-sample-filedriver-android_uwp-7-5-20`
6. この後の作業を少し楽にするためにこのディレクトリの中に `lib` というディレクトリを作って解凍した 2 の中にある `build/` の中の `include` と `lib` をコピーします.
    - 下の画像のようなディレクトリ構造になっていれば大丈夫です.
7. 次に `build.py` を編集します. `build.py` では cmake の generator に `Visual Studio 14 2015` を使っているので Visual Studio 2017 でビルドできません. そこで下のソースコードのように `Visual Studio 15 2017` を使うようにコードを変更します(84行目付近です).
8. そしたら5のコマンドプロンプトで `python build.py -a x64 -vh lib\include uwp` と実行すればビルドが開始されます.

### ディレクトリ構造
    
![ディレクトリ構造](https://qiita-image-store.s3.amazonaws.com/0/17704/ec22ea2e-99a0-b88a-97bb-c940519e40f8.png)

### build.py (一部)

```python
        elif platform == PLATFORM_UWP:
            toolchain_file = os.path.join(android_toolchain_dir, "uwp.toolchain.{0}.cmake".format(arch))
            if arch == "x86":
                generator = "Visual Studio 15 2017"
            elif arch == "x64":
                generator = "Visual Studio 15 2017 Win64"
```

以上です.
pandasのデータフレーム等、表示範囲を変更するメモ

# 参考

[こちらのデータ分析方法が参考になりました！](https://amzn.to/3gBNWl2)

# 方法
```python
# 最大表示範囲を確認
pd.get_option("display.max_columns")
pd.get_option("display.max_rows")

# 表示範囲を指定(お好みで数値を設定)
pd.set_option("display.max_columns",50)
pd.set_option("display.max_rows",50)
```

```python
# その他のオプション
dir(pd.options.display)

#実行結果
['chop_threshold',
 'colheader_justify',
 'column_space',
 'date_dayfirst',
 'date_yearfirst',
 'encoding',
 'expand_frame_repr',
 'float_format',
 'height',
 'html',
 'large_repr',
 'latex',
 'line_width',
 'max_categories',
 'max_columns',
 'max_colwidth',
 'max_info_columns',
 'max_info_rows',
 'max_rows',
 'max_seq_items',
 'memory_usage',
 'multi_sparse',
 'notebook_repr_html',
 'pprint_nest_depth',
 'precision',
 'show_dimensions',
 'unicode',
 'width']
```
dockerでwebpackerが遅い問題を改善する

# 追記
公式のドキュメントが更新されたのでそちらをおすすめします。
https://github.com/rails/webpacker/blob/5-x-stable/docs/docker.md

# 概要
dockerで作った開発環境でwebpackerが遅いので改善できないか試してみました。
ホストOSはlinuxなので他のOSだと起きない問題かもしれません。

なお、完成品はこちらになります。
https://github.com/lisp719/templates/tree/master/rails

# 普通に使ってみる
Dockerfileはひとまず公式の通りにします。
https://github.com/rails/webpacker/blob/master/docs/docker.md

docker-compose.ymlは公式を参考に別のコンテナで動かすようにします。

```yml
  # 必要な部分だけ抜粋
  app:
    command: ./bin/rails s -b 0
  webpacker:
    command: ./bin/webpack-dev-server
```

適当にjavascriptを変更してコンソールでログを確認してみます。

```
webpacker_1  | webpack: Compiling...
webpacker_1  | webpack: Compiled successfully.
app_1        | [Webpacker] Compiling…
app_1        | [Webpacker] Compiled all packs in /home/vagrant/code/sandbox/tut/public/packs
```

2つのコンテナ両方でコンパイルが行われています。
特にappコンテナは画面をリロードしてからコンパイルが始まるので遅いです。

# foremanを使う
どうもそれぞれ別のコンテナで動いているのが原因な気がします。
foremanを使って同じコンテナで動かすようにしてみます。
https://github.com/ddollar/foreman

```Procfile.dev
app: rm -f tmp/pids/server.pid && rails s -b 0
webpacker: ./bin/webpack-dev-server
```

```docker-compose.yml
  # 必要な部分だけ抜粋
  app:
    command: foreman start -f Procfile.dev -p 3000
```

また適当にjavascriptを変更してログを見てみましょう。

```
app_1  | 07:20:35 webpacker.1 | webpack: Compiling...
app_1  | 07:20:36 webpacker.1 | webpack: Compiled successfully.
```

webpack-dev-serverでのみコンパイルされるようになりました。
ファイルが保存されるタイミングでコンパイルされるのでだいぶ速く感じます。

# （追記）環境変数でwebpackerの設定を変える
foreman無しでいけたので追記します。

rails serverのコンテナは `WEBPACKER_DEV_SERVER_HOST` でwebpack-dev-serverを動かすコンテナ名を指定します。
webpackerのコンテナは `WEBPACKER_DEV_SERVER_HOST` で `0.0.0.0` を指定します。

```docker-compose.yml
  # 必要な部分だけ抜粋
services:
  app: &app
    command: ./bin/rails s -b 0
    environment:
      WEBPACKER_DEV_SERVER_HOST: webpacker
    ports:
      - "3000:3000"

  webpacker:
    <<: *app
    command: ./bin/webpack-dev-server
    environment:
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    ports:
      - "3035:3035"
```
オフラインリアルタイムどう書く E27 の問題

オフラインでリアルタイムに「どう書く」をやるイベント( https://yhpg.doorkeeper.jp/events/79705 )を行っています。

問題は「とあるカードゲーム」という名前で、詳細は
http://nabetani.sakura.ne.jp/hena/orde27cardgame/
です。

実装ができた方はこちらのコメント欄からリンクを張っていただくと見つけやすくて助かります。

似たような問題をもっと解きたいという方は、
https://nabetani.hatenadiary.com/entry/yhpg_list
に過去問リンク集がありますので、そちらをご覧になると良いと思います。

次回のイベントは 11/3。
詳しくは
https://yhpg.doorkeeper.jp/events/81346
を御覧ください。
Node.jsで画面遷移を行う

## Node.jsとは？
[[初心者] Node.jsでHello Worldする](https://qiita.com/tetuwo_5555/items/11e7f1a7dd297215b699)
[[初心者向け] [Node.js] fsモジュールを使ってhtmlファイルを返す](https://qiita.com/tetuwo_5555/items/3101f5bb0cf323bc01d0)

わからなければ↑の記事をご参考ください！！

## 画面遷移を行う

Node.jsでは、リクエスト(URL)ごとにレスポンスとして返却する内容を使い分けることにより、結果として画面遷移を実現させる

以下コード

```server.js
var http = require('http');
var fs = require('fs');

var server = http.createServer(function(req, res) {
  var target = '';
  switch (req.url) {
    case '/':
    case '/index':
      target = './index.html';
      break;
    case '/next':
      target = './next.html';
      break;
    default:
      res.writeHead(404, {'Content-Type': 'text/plain'});
      res.end('bad request');
      return;
  }


  fs.readFile(target, 'utf-8', function(err, data) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(data);
    res.end();
  })
});

server.listen(3000);
console.log('サーバーを起動しました。');
```

適当にhtmlファイルを用意する

```index.html
<!DOCTYPE html>
<html lang="ja" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>sample</title>
  </head>
  <body>
    <h1>Hello world</h1>
    <h2>This is First Page</h2>
    <a href="/next">To next page</a>
  </body>
</html>
```

```next.html
<!DOCTYPE html>
<html lang="ja" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>sample</title>
  </head>
  <body>
    <h1>Hello world</h1>
    <h2>This is Next Page</h2>
    <a href="/next">To First page</a>
  </body>
</html>
```

## 解説

また今度書くので記事なる方はいいねしといていただけると通知が行きます！
macOSからUbuntuへのデュアルブート

macOSからUbuntuにデュアルブートしました。
最初、何をすればいいのかを把握するのに時間がかかったので、簡潔にメモしておきます。

## 環境
- MacBookPro (Retina, 13-inch, Early 2015)
  - 2015年以前のMacBook系統なら同じ方法でできる（らしい）。<sup>*[要出典]*</sup>
- もともとのOS: macOS Sierra 10.12.6
- デュアルブートしたいOS: Ubuntu 18.04
<img width="586" alt="スクリーンショット 2018-10-06 14.48.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/145009/c9d9fbfa-b3f7-6cfe-78a7-a9d788735d4b.png">

## 必要なもの
- インターネット接続環境
- 2GB以上のUSBメモリ（4GBあれば十分）
- USBポートがさせること
- 英語を読む能力

## 概要
次のことを行なって、Ubuntuのインストールができた。

- TimeMachineなどで**必ず**バックアップを取っておく。
- 残り容量を鑑みながら、Ubuntuに何GB割くのかを決める。
- パーティション分割をする。
- bootableUSBを作る。
- インストール！

## 流れ
- TimeMachineなどで**必ず**バックアップを取っておく。
- 残り容量を鑑みながら、Ubuntuに何GB割くのかを決める。
  - 基本的なシステムをインストールするだけで5~10GB使う可能性があるので、考慮に入れておく必要がある。
  - 「このMacについて → ストレージで、パージ可能な領域と空き領域を確認できる。」
  - 空き領域だけでなく、パージ可能領域も使いたかったので、パージ可能領域を空き領域にするにあたって、[ここ](https://toripiyo.hatenablog.com/entry/2017/09/23/191858)を参考にして容量を回復した。
- パーティション分割をする。
  - アプリケーション/ユーティリティ/ディスクユーティリティ を開いて、左側からMacintosh HDを選び、上のパーティションを押すと、Ubuntuのための領域を分けて作ることができる。
  - 名前、フォーマット（MS-DOS (FAT)で良いらしい<sup>*[要出典]*</sup>）、サイズを決めて、パーティションを分割する。（この操作は取り消せないはず）3分程度かかった。
<img width="845" alt="スクリーンショット 2018-09-29 23.39.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/145009/d869f1f5-c0c2-cbf7-08da-d7a9efa0ad87.png">
  - 僕の場合は、パーティションが分割できなかった。
<img width="819" alt="スクリーンショット 2018-09-29 22.38.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/145009/fb31041e-d0fa-9eef-7fbb-ec602d8bfe50.png">
  - [ここ（英語）](https://www.howtogeek.com/236978/how-to-repair-disk-and-file-system-problems-on-your-mac/)を見て、上から順番に修復作業を行っていったら、一番下の"Use fsck in Single-User Mode"を実行して、やっと正常にもどった。
  - 結局パーティションが分割できていなかったのが、できるようになった。
  - なぜか名前が"Ubuntu"ではなく、"U"になってしまったが、特には困らないのでそのままにしておいた。（よくあることらしい。<sup>*[要出典]*</sup>）
- bootableUSBを作る。
  - ISOファイルをダウンロードして、それをUSBメモリに書き込むという手順を踏む。
  - ISOファイルをダウンロードするところまでは[ここ](https://www.softantenna.com/wp/tips/create-ubuntu-install-usb-media-on-macos/)を参考にした。
  - [公式ページ（英語）](https://tutorials.ubuntu.com/tutorial/tutorial-create-a-usb-stick-on-macos?_ga=2.146288316.924052820.1529813259-318200388.1529813259#1)に沿って書き込んでいった。
- インストール！
  - 一回電源を切って、bootableUSBを刺し、Optionキーを押しながら起動すると、Macintosh HDで起動するか、EFI Bootで起動するかを選べる。
  - EFI Bootで起動すると、Ubuntuが起動する。
  - インストーラみたいなのがUbuntuのデスクトップにあったので、順番にすすめた。
  - あとは、自分の判断で選択肢を選んでいけば良いのだが、**「インストールの種類」では、「ディスクを削除して...」とかを選ぶとデータが消えるので、必ず「それ以外」を選ぶ。**
    - さっき作ったパーティションを選んで、利用方法「ext4ジャーナリングファイルシステム」、「パーティションの初期化」にチェック、「マウスポイント」は「/」に設定する。
  - これで進んでいくと、インストールできた。
- またmacOSを開きたいときは、Optionを押しながら起動して、Macintosh HDを選べば起動できる。
C++のswitch-caseを便利にしたかった

ふと C++ を完全に理解した気になって「C/C++の本質を掴むための一考察」なる大上段な記事を書き始めたのですが、このまま書き続けると無数のマサカリに切り刻まれてナマスにされそうなので、もう少し手頃な規模の記事を書くことにしました。（いつかは公開したい）

先にお断りしておくと、すっきりした結論が出る記事ではないです。色々試行錯誤してみた記録に過ぎないので、言語仕様やその拡張にロマンを感じる人はどうぞ。

# 発端

きっかけはこんなツイートでした。
https://twitter.com/Serbonis/status/1043305838490804224

```cpp
switch ([a, b, c]) {
case [cond_a, cond_b, cond_c]:
}
```
確かにできたら便利そうです。
case に定数しか書けないのは致し方ないとしても、複数の値の組み合わせぐらいは判定できても良さそうです。現状の C++ で実現できないか検討してみます。

# switch-case の制限事項

真っ先に「std::tuple をそのまま式に使えばいいじゃん、constexpr なコンストラクタもあるし！」と思ったのですが、C++ の switch-case には以下の制限があります。

* switch の式に書けるのは整数型か列挙型のみ
* case ラベルに書けるのは整数型か列挙型の定数式のみ

上記の制約により、std::tuple をそのまま使用することはできません。何かしら代替手段を考える必要があります。

# 考え出した方針

* std::tuple を整数型に連結するヘルパー関数を作る
    * 高々 64bit までしか詰め込めないので費用対効果が薄そう
* std::tuple の値をハッシュ化して評価する
    * 評価式が実行時計算でハッシュ化されるので、そのコストが飲めるか？
    * 衝突のリスクを負ってまで条件分岐書くのを楽したいか？
* 複数の条件式の真偽を std::bitset に詰め込み、その組み合わせを評価する
    * そもそもの趣旨が変わってしまうので有用性に疑問が残る
    * std::bitset 自体は constexpr にできるが、to_ullong()が constexpr じゃない

# 考察

2つ目の **std::tuple を 64bit のハッシュ値化して評価する** が一番筋が良さそうです。
懸念点はハッシュ関数次第になるので、FnvHash あたりを検証してみましょう。

1つ目は整数型の最大サイズ分までという制約が付きますし、
3つ目も、switch 本来の使い方曲げてまでユーティリティ用意しても……と思うのでやめます。

こんな感じで書けるとステキでしょうか……

```cpp
switch (fold_hash(hoge(), fuge(), hage())) {
case fold_hash(1, 2, 3):
  std::cout << "case A" << std::endl;
  break;
case fold_hash(4, 5, 6):
  std::cout << "case B" << std::endl;
  break;
}
```
もはや tuple にこだわる必要もないので、可変引数テンプレートを使う練習がてら、 fold_hash() を実装してみます。

# 畳み込みハッシュ関数の実装

こんな感じでしょうか。

```cpp
static constexpr uint64_t FNV_OFFSET_BASIS_64 = 14695981039346656037U;
static constexpr uint64_t FNV_PRIME_64 = 1099511628211LLU;

constexpr uint64_t fold_hash_core(uint64_t hash) {
  return hash;
}

template<typename T>
constexpr uint64_t fold_hash_core(uint64_t hash, T t) {
  return (FNV_PRIME_64 * hash) ^ t;
}

template<typename T, typename... Args>
constexpr uint64_t fold_hash_core(uint64_t hash, T t, Args... args) {
  return fold_hash_core(fold_hash_core(hash, t), args...);
}

template<typename... Args>
constexpr uint64_t fold_hash(Args... args) {
  return fold_hash_core(FNV_OFFSET_BASIS_64, args...);
}
```

* 本来バイト単位で XOR するべきだが、constexpr 内でうまくやる方法が見当たらず断念
    * バイト単位でやる必要がないなら、実行時のハッシュ化もそこまで重くないのでうれしい
* このままだと列挙型に対応できない
    * type_traits 使って実装分岐して underlying_type にキャストしてやれば、まぁええんちゃうんちゃうん

上記の実装をもって、前述したコードは一応動作します。
また、ハッシュの衝突に関しては、case ラベルで列挙しているものについてはコンパイル時に「同じ定数ラベルが存在しとるで」とエラーにしてくれるので、案外悪くなさそうに見えます。

# 課題

とはいえ、色々と物足りない点や懸念点は残ります。

* ラベル間の衝突はともかく、実行時に評価する値がたまたまラベルにマッチしてしまう可能性はある
* 式とラベルで値の個数や型が不一致の場合でも動いてしまう
* std::tie() で std::ignore を使う場合のように「このケースの場合、ここの値はなんでもいい」みたいな指定ができない

C/C++ の switch-case は静的なジャンプテーブルにコンパイルされることが至上命題なので、その枠内でできることはどうしても限られます。もっとうまい手はないか、もしくはこういうニーズに応える仕様の提案はないものか、今後も折を見て考えていきたいと思います。
[初心者向け] [Node.js] fsモジュールを使ってhtmlファイルを返す

## Node.jsとは？

以下の記事でNode.jsについてとHello Worldする方法をまとめたため参考にしてください。

https://qiita.com/tetuwo_5555/items/11e7f1a7dd297215b699

## htmlファイルを返す

(コードの解説は下にあります。)

hello.jsでhttpサーバーを作成し、htmlを返すします

```hello.js
var http = require('http');
var fs = require('fs'); //　①

var server = http.createServer(function(req, res) {
  fs.readFile('./temp.html', 'utf-8', function(err, data) { //　②
    res.writeHead(200, {'Content-Type': 'text/html'}); // ③
    res.write(data);
    res.end();
  })
});

server.listen(3000);
console.log('サーバーを起動しました。');
```
hello.jsで返されるhtmlファイル

```temp.html
<!DOCTYPE html>
<html lang="ja" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>sample</title>
  </head>
  <body>
    <h1>Hello world</h1>
    <p>This is Template file</p>
  </body>
</html>
```
実行する

```
$ node hello.js
```
http://localhost:3000/
にアクセスして、以下の画像の様に表示されれば成功

<img width="647" alt="スクリーンショット 2018-10-06 15.28.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/222453/b7c16944-8c3f-d78f-9ca1-b61c17a9a655.png">

## 解説

#### ①require関数でfsオブジェクトを生成する
fsオブジェクトはファイルを読み込むためのオブジェクト
https://nodejs.org/api/fs.html

#### ②fsオブジェクトのreadFileメソッドでhtmlファイルを読み込む
- 第一引数：対象のファイルパス
- 第二引数：エンコード
- 第三引数：読み込み完了時に動作するコールバック関数
(コールバック関数では、第一引数にエラーオブジェクト、第二引数に読み込んだデータを受け取る）

#### ③htmlファイル読み込み後にhttpヘッダや読み込み結果を出力させる
readFileメソッドは非同期であるため、コールバック関数で、これらを行わないと、ファイル読み込みが完了する前にレスポンスを返却してしまう。

Content-Typeを「text/html」に変更している
EOSをうごかしてみる(保留)

## コントラクトディレクトリを作成する。

```
cd
mkdir contracts
cd contracts
```

## dockerを起動する。

```
CONTRACTS_DIR=`pwd`
docker run --name eosio \
  --publish 8888:8888 \
  --publish 127.0.0.1:5555:5555 \
  --volume ${CONTRACTS_DIR}:${CONTRACTS_DIR} \
  --detach \
  eosio/eos \
  /bin/bash -c \
  "keosd --http-server-address=0.0.0.0:5555 & exec nodeos -e -p eosio --plugin eosio::producer_plugin --plugin eosio::history_plugin --plugin eosio::chain_api_plugin --plugin eosio::history_plugin --plugin eosio::history_api_plugin --plugin eosio::http_plugin -d /mnt/dev/data --config-dir /mnt/dev/config --http-server-address=0.0.0.0:8888 --access-control-allow-origin=* --contracts-console --http-validate-host=false --filter-on='*'"
docker logs --tail 10 eosio
```

## dockerに接続する。

```
docker exec -it eosio bash
```

## walletの中身を確認する。

```
cleos --wallet-url http://127.0.0.1:5555 wallet list
```


## walletを作成する。

```
#  cleos --wallet-url http://127.0.0.1:5555 wallet create --to-console
Creating wallet: default
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5KYUiVpvfnbjXY4XGdY6bKnMics4QTjPbyUKDx9tM2NSzrAA47R"
```

## walletを開く

```
# cleos --wallet-url http://127.0.0.1:5555 wallet open
Opened: default
```

## walletのリストを一覧する。

```
# cleos --wallet-url http://127.0.0.1:5555 wallet list
Wallets:
[
  "default"
]
```

## walletをアンロックする。

```
cleos --wallet-url http://127.0.0.1:5555 wallet unlock
password:
```

## オープンされたwalletの一覧を表示する。

```
# cleos --wallet-url http://127.0.0.1:5555 wallet list
Wallets:
[
  "default *"
]
```

## キーを作成する。

```
# 
# cleos --wallet-url http://127.0.0.1:5555 wallet create_key
Created new private key with a public key of: "EOS7vP6HatobSfTWM3c5RYmSgccQHUBzRDZH97Q7SqdredsDdgDez"
```

## プライベートキーも見る。

```
# cleos --wallet-url http://127.0.0.1:5555 wallet private_keys
password: [[
    "EOS7vP6HatobSfTWM3c5RYmSgccQHUBzRDZH97Q7SqdredsDdgDez",
    "private keys"
  ]
]
```

## アカウントを作成する。

```
cleos --wallet-url http://127.0.0.1:5555 create account eosio bob EOS7vP6HatobSfTWM3c5RYmSgccQHUBzRDZH97Q7SqdredsDdgDez
cleos --wallet-url http://127.0.0.1:5555 create account eosio alice EOS7vP6HatobSfTWM3c5RYmSgccQHUBzRDZH97Q7SqdredsDdgDez
```
 
https://github.com/EOSIO/eos/issues/4154

と同じようなエラーがでてるので保留。
mapillary_tools を Windows で動かす

「[mapillary_tools を使ってアクションカムで撮った写真をMapillaryに投稿する](https://qiita.com/kudarisenmon/items/e1c0c9fc439dd5ec5a11)」を Windows で動かしてみます。Windows10から新しく使えるようになった Windows Subsystem for Linux (WSL) の機能を使用します。

（2019年5月追記） Mapillary公式で exe 形式の mapillary_tools がリリースされています。WSLはI/Oのパフォーマンスがよくないため、exeのほうが性能がよいと思われます。お試しください。
https://tools.mapillary.com/binary/win/mapillary_tools.exe

# WSL と Ubuntu のインストール
WSLのインストール方法は[WSL（Windows Subsystem for Linux）の導入とUbuntuの初期設定]
(https://qiita.com/kerobot/items/b4f5472d71119506baaa)を参考にしました。
Ubuntu 18.04.3 LTS をインストールしました。

```
＄ lsb_release -d
Description:    Ubuntu 18.04.3 LTS
```
# 環境構築
必要なパッケージをインストールします。動画からアップロードできる機能を使用するために ffmpeg もインストールします。Python  のバージョンは 2.7.15rc1 でした。

```
$ sudo apt update
$ sudo apt install python ffmpeg gcc python-dev
$ python --version
Python 2.7.12
```

## pip のアップデート
pip のバージョン10以上が要求されています。Ubuntu のパッケージは古い(9.0系)ので新しい pip をインストールしました。

```
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ sudo python get-pip.py
$ pip --version
pip 18.0 from /usr/local/lib/python2.7/dist-packages/pip (python 2.7)
```

## 依存ライブラリをインストール
Mapillaryプロジェクトがフォークした Piexif をインストールします。

```
$ sudo pip install git+https://github.com/mapillary/Piexif
```

## mapillary_tools のインストール
mapillary_tools 本体をインストールします。

```
$ sudo pip install --upgrade git+https://github.com/mapillary/mapillary_tools
```
## タイムゾーンの設定を確認する
タイムゾーンが正しいか確認します。私の環境ではなぜか DST になっていましたので、JST ( Asia / Tokyo ) にしました。

```
$ date
Thu Aug 30 12:55:52 DST 2018
$ sudo dpkg-reconfigure tzdata
( Asia / Tokyo にする )
$ date
Mon Aug 25 22:51:20 JST 2018
```
## 動作確認
以下のように表示されればインストール成功です。以降の使い方は [mapillary_tools を使ってアクションカムで撮った写真をMapillaryに投稿する](https://qiita.com/kudarisenmon/items/e1c0c9fc439dd5ec5a11#%E8%AA%8D%E8%A8%BC) と同じです。

```
$ mapillary_tools --version

Mapillary tools version : 0.1.6
```

## 補足
### WSL でWindows のリムーバルメディアを使用する
写真や動画が入ったSDカードなどWindowsが認識したリムーバブルメディアをマウントする方法は「[WSLでSDカードをマウントする](https://qiita.com/moyashimanjyu/items/baf6ebcdd69b24bb5cf2)」の記事が参考になりました。
Grunt  まとめ

https://qiita.com/_masakitm_/items/9d19ef04d82e3f5d2dee



[今更だけどやるgrunt入門編・インストールから基本的な使い方](http://webdrawer.net/javascript/firstgrunt.html)


https://qiita.com/shuntaro_tamura/items/6cf755d408eaad8572ad

https://qiita.com/shunjiro/items/658adf6aff1009144ee3
https://qiita.com/megurock/items/54872c26e45017cd36a1
https://qiita.com/megurock/items/4b0988374df0caa822fd

[Gruntプラグイン](https://ferret-plus.com/4326)
[GruntでWordpressテーマの開発環境を作る](https://whiskers.nukos.kitchen/2014/09/05/grunt-wordpress.html)



https://www.qript.co.jp/blog/technique/1601/

https://www.monster-dive.com/blog/web_creative/20131124_000113.php

Windows7にSass環境を構築する
https://usortblog.com/sassuyokyokusetu/

Sassのご紹介
https://www.willstyle.co.jp/blog/1276/

gruntのsassで文字化けエラーが出る
https://qiita.com/shunjiro/items/82740d999863d7e37abe

scssのファイルで、


```scss
@charset "UTF-8";
```

を先頭につける。


##操作
watch開始

```cmd:cmd
grunt watch
```

停止
Ctrl+C


##プラグイン追加
###ベンダープレフィックス自動付与
runt-autoprefixer

手順
https://www.tam-tam.co.jp/tipsnote/javascript/post4084.html
GruntのCSScomb
https://increment-log.com/csscomb-setting/
mac で高速にファイル検索 / 全文検索するコマンドmdfind

# ファイル名検索の使い方
~/(ホームディレクトリ)から、**ファイル名に** "yamazon"を含むファイルを検索
-name にファイル名を指定します

```sh
# コマンド
mdfind -onlyin ~/ -name yamazon

# 結果(ファイル名に"yamazon"を含むファイルを抽出)
/Users/t-yamamoto/yamazon
/Users/t-yamamoto/Downloads/old/yamazon_work-20181001T081335Z-001.zip

```
# 全文検索の使い方
~/(ホームディレクトリ)から、**ファイルの中身**に"yamazon"を含むファイルを検索
-name を外し、引数にファイルの中身に含む文字列を書きます

```sh
# コマンド
mdfind -onlyin ~/ "yamazon"

# 結果(ファイルの中身に"yamazon"を含むファイルが出る)
/Users/t-yamamoto/yamazon
/Users/t-yamamoto/Library/Mobile Documents/com~apple~Keynote/Documents/powershell勉強会.key
/Users/t-yamamoto/Downloads/old/yamazon_work-20181001T081335Z-001.zip

```


# 組み合わせる(全文検索 + ファイル名検索)
全文検索した結果のファイルリストをgrepするしかないです

```sh
# コマンド
mdfind -onlyin ~/ yamazon |grep -e ".key$"

# 結果(ファイルの中身に"yamazon"を含むファイルのうち、拡張子.keyのファイルが出る)
/Users/t-yamamoto/Library/Mobile Documents/com~apple~Keynote/Documents/powershell勉強会.key
```

以上
[初心者] Node.jsでHello Worldする

## Node.jsとは？
- 「Javascriptで動作するサーバー環境」
- WebサーバーというとApacheやIISなどのHTTPサーバー上でPHPやASPなどを動作させる環境を思い浮かべるが、Node.jsはそれとは異なる
- Node.jsではサーバーを作るところから実装が始まる

#### 特徴
- 非同期I/O、ノンブロッキングI/Oモデルを採用している
- シングルスレッド
- Googleの「V8」という優秀なJavascriptエンジンで動作する


## Hello Worldする

(**Node.jsがインストールされていることを前提としています**)

とりあえずコードを写経する


```hello.js

var http = require('http'); // ①

var server = http.createSever(function(req, res) {  // ②
  res.writeHead(200, {'Content-Type': 'text/plain'}); // ③
  res.write('Hello World');
  res.end();
});

server.listen(3000); // ④
console.log('サーバーを起動しました。');
```

コンソールで以下のコードを実行する

```
$ node hello.js
```

http://localhost:3000/にログインし、以下の画面が表示されれば成功

## 解説

#### ① requireという関数でhttpオブジェクトを生成している

#### ② httpオブジェクトのcreateServerメソッドでサーバーオブジェクトを作成する
- createServerメソッドは引数に、サーバーリクエストを受けたときに動作させるコールバック関数を指定する(コールバック関数は、第一引数にリクエストオブジェクト、第二引数にレスポンスオブジェクトを受け取る)

#### ③サーバーリクエストが発生した際の動作を定義する
- writeHeadメソッドでhttpヘッダを書き出す(第一引数：ステータスコード、第二引数：ヘッダ情報の連想配列）
- writeメソッドでhtmlコンテンツを書き出す
- endメソッドでhttpコンテンツを出力する

#### ④作成したサーバーオブジェクトをlistenメソッドで受け待ち状態にする
引数には使用するポート番号を指定する


#### メモ
- writeHeadメソッドはデフォルト値が「200, {'Content-Type': 'text/plain'}」
- endメソッドは引数にコンテンツ出力内容を受け取ることもできるため以下の用にも記述できる

```javascript

var http = require('http);

var server = http.createServer(function(req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World');
});

```

##終わり
Javascriptが好きなので個人的にNode.jsは結構楽しいです。
Elasticsearchでフィールド有無検索


Elasticsearchでは必要の無いフィールドは存在させないでデータ登録できます。

そんなフィールドの有無を検索したいときの検索例です。

# 指定したフィールドのあるデータの検索

index_nameからfield_nameフィールドが存在するデータの検索をする例

```
GET index_name/_search
{
  "query": {
    "exists": {
      "field": "field_name"
    }
  }
}
```

# 指定したフィールドの無いデータの検索

index_nameからfield_nameフィールが存在しないデータの検索をする例

```
GET index_name/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "exists": {
            "field": "field_name"
          }
        }
      ]
    }
  }
}
```

# いずれかのフィールドのないデータの検索 

index_nameからfield_1かfield_2のいずれかのフィールが存在しないデータの検索をする例

```
GET index_name/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must_not": [
              {
                "exists": {
                  "field": "field_1"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must_not": [
              {
                "exists": {
                  "field": "field_2"
                }
              }
            ]
          }
        }
      ]
    }
  }
}
```
[AWS] Redshiftの便利なクエリまとめ

Redshiftを運用する中で便利なクエリをまとめました。
詳細は"References"をご覧ください。

間違いがあれば、気軽にコメントくださいm(_ _)m

# クエリをキャンセルする
```sql
-- 1. 実行中のクエリを表示し、PIDを取得する。
SELECT pid, trim(user_name), starttime, substring(query, 1, 200) 
FROM stv_recents
WHERE status = 'Running';

-- 2. クエリをキャンセルする。(pid: 12345のクエリをキャンセル)
cancel 12345;
```
- References
    - https://docs.aws.amazON.com/ja_jp/redshift/latest/dg/cancel_query.html


# Superuserキューを使用する
```sql
-- 1. Superuserに切り替える。
set query_group to 'superuser';
-- 2. 実行したいクエリを実行する。
cancel 18764;
-- 3. 元のクエリグループに戻る。
reset query_group;
```
- References
    - https://docs.aws.amazON.com/ja_jp/redshift/latest/dg/cancel_query.html


# 各テーブルのディスク使用量[Mb]を表示する
```sql
SELECT name, mb
FROM (
  SELECT tbl, count(*) AS mb
  FROM stv_blocklist
  WHERE tbl in (
    SELECT id
    FROM stv_tbl_perm
  )
  GROUP BY tbl
) block_list
INNER JOIN stv_tbl_perm
ON block_list.tbl = stv_tbl_perm.id
GROUP BY tbl, stv_tbl_perm.name, block_list.mb
ORDER BY mb desc;
```
- References
    - https://qiita.com/watanata/items/5c474b62c0c1c24df01a


# 各テーブルのソート率を表示する
```sql
SELECT
  percentage_result.id,
  percentage_result.schemaname,
  percentage_result.tablename,
  percentage_result.rows,
  percentage_result.sorted_rows,
  percentage_result.sort_percentage
FROM (
  SELECT
    tbl_perm_info.id,
    pg_catalog.svv_table_info.schema AS schemaname,
    tbl_perm_info.tablename,
    tbl_perm_info.rows,
    tbl_perm_info.sorted_rows,
    CAST(
      CAST(tbl_perm_info.sorted_rows AS double precisiON) / CAST(tbl_perm_info.rows AS double precisiON) AS decimal(10,3)
    ) AS sort_percentage
  FROM (
    SELECT
      id,
      TRIM(name) AS tablename,
      SUM(rows) AS rows,
      SUM(sorted_rows) AS sorted_rows
    FROM
      pg_catalog.stv_tbl_perm
    WHERE
      rows != 0
      AND sorted_rows != 0
    GROUP BY
      id, name
  ) tbl_perm_info
  INNER JOIN
    pg_catalog.svv_table_info
  ON
    tbl_perm_info.id = pg_catalog.svv_table_info.table_id
) AS percentage_result
ORDER BY
  percentage_result.sort_percentage,
  percentage_result.schemaname,
  percentage_result.tablename;
```
- references
    - https://dev.classmethod.jp/cloud/aws/amazon-redshift-useful-sql-require-tables-to-vacuum-again/


#　クエリの同時実行数を変更する
```sql
-- クエリの同時実行数を10に変更
set wlm_query_slot_count to 10; 
```
- Referrences
    - https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/cm-c-defining-query-queues.html
    - https://dev.classmethod.jp/cloud/aws/amazon-redshift-wlm-concurrency-limit-increased/


Posted on 2018-10-06
出向メモ






# Grunt
https://qiita.com/_masakitm_/items/9d19ef04d82e3f5d2dee

# Visual Studio Code
https://eng-entrance.com/texteditor-vscode

http://www.atmarkit.co.jp/ait/articles/1805/18/news032.html
↑で日本語設定したら、

手順
1. Ctrl+Shift+X で拡張機能を呼び出し、japanese　と検索 そのままインストール（左端の一番下にある四角マークをクリック）
2. 次に［Ctrl］＋［Shift］＋［P］キー（Windows／Linux。macOSでは［Shift］＋［Command］＋［P］キー）でコマンドパレットを表示し、
「config」と入力。［Configure Display Language］（［表示言語を構成する］）を選択する。

![l_dt-03.gif](https://qiita-image-store.s3.amazonaws.com/0/284757/12bda6b5-c8a4-6ee3-5213-ca5cb10141a9.gif)

3. https://teratail.com/questions/131962
でインデント設定

Beautifyをインストール
https://marketplace.visualstudio.com/items?itemName=HookyQR.beautify


# GIT

[Gitコマンド早見表](https://qiita.com/kohga/items/dccf135b0af395f69144)

[Gitの基本 初期設定](https://backlog.com/ja/git-tutorial/intro/intro2_2.html)

[今日からはじめるGitHub ](https://employment.en-japan.com/engineerhub/entry/2017/01/31/110000)
ディレクトリ（webpack）

例

```
root/
┣ .gitignore
┣ .git
┃
┣ dest/ (変換されたファイルが格納されたフォルダ）【 public 】
┃　　┣ css/（変換前と同じディレクトリ）
┃　　┣ img/（同上）
┃　　┣ js/ （同上）
┃　　┣ .htaccess
┃　　┣ favicon.ico
┃　　┗ index.php
┃　　
┣ resources (変換前のファイルが格納されたフォルダ）
┃    ┃
┃    ┣ json/
┃    ┃
┃    ┣ assets/
┃    ┃   ┣ img/
┃    ┃   ┃  ┣ common (サイト全体)
┃    ┃   ┃  ┣ キャンペーンページ A
┃    ┃   ┃  ┗ 会社概要ページ B
┃    ┃   ┃
┃    ┃   ┣ js/
┃    ┃   ┃  ┣ jquery.min.js
┃    ┃   ┃  ┣ common.js (サイト全体)
┃    ┃   ┃  ┗ library（ライブラリ別jsファイル）
┃    ┃   ┃
┃    ┃   ┗ sass/
┃    ┃   　  ┣ include
┃    ┃   　  ┃　　┣ キャンペーンページ A
┃    ┃   　  ┃　　┣ 会社概要ページ B
┃    ┃   　  ┃　　┣ module/（ヘッダー・フッター部分）
┃    ┃   　  ┃　　┣ reset.scss
┃    ┃   　  ┃　　┣ setting.scss
┃    ┃   　  ┃　　┗ root/（サイト全体共通）
┃    ┃   　  ┃　　
┃    ┃   　  ┣ キャンペーンページA/（@import用）
┃    ┃   　  ┣ 会社概要ページB/（@import用）
┃    ┃   　  ┗ サイト全体/（@import用）
┃    ┃
┃    ┗ views（phpファイル格納）
┃         ┣ index.php
┃         ┣ include
┃         ┣ キャンペーンページ A
┃         ┗ 会社概要ページ B
┃
┣ package.json
┣ webpack.mix.js
┗ yarn.lock
```
srcフォルダが制作用。
destフォルダが公開用で設定。
Dockerコンテナ内のFlaskサーバにアクセス(Python)

#概要
PythonのライブラリFlaskを用いてミニマルなサーバをたて、それをDockerコンテナ上で動かし、ローカルのパソコンからアクセスする方法について説明します。

私自身Dockerについて勉強中のため、かなり初心者向けの内容になっております。
#準備するもの
以下のようなディレクトリを用意します。
数字が振られているファイルについては、後ほど中身を説明します。

```
/docker-python
┣　Dockerfile (1)
┗　web
    ┣　main.py (2)
    ┗ templates
        ┗ index.html (3)
```
## (1) Dockerfile

```dockerfile
FROM centos:7

#IUSリポジトリを追加
RUN yum install -y https://centos7.iuscommunity.org/ius-release.rpm
#Python3.5をインストール
RUN yum install -y python35u python35u-libs python35u-devel python35u-pip
#Pythonのライブラリrequestsをpip
RUN python3.5 -m pip install requests
#PythonのライブラリFlaskをpip
RUN python3.5 -m pip install flask

COPY web /var/www/html/web/

#コンテナ起動時にFlaskサーバを立ち上げ
CMD ["python3.5", "/var/www/html/web/main.py"]
```
Pythonと必要ライブラリをインストールし、実行時にサーバを立ち上げる設定をしています。
##(2)main.py

```python
from flask import Flask, render_template
  
app = Flask(__name__)

@app.route("/")
def show_page():
    return render_template('index.html', msg='Hello, ', additional_msg="from Python")

app.run(host='0.0.0.0',port=5000,debug=True)
```
全ての要求(`"/"`)に対して、index.htmlのページを返します。

注意が必要なのは、最終行の`host='0.0.0.0'`の部分です。
最初私はこの部分を適当な番号を指定していたのですが、どうやら`0.0.0.0`でなければ外部からのアクセスができないようなので、必ずこの番号にする必要があります。
##(3)index.html

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Hello from Python</title>
        <style>
            #firstMsg{
                font-size: 30px;
                font-family:Impact;
                color:blue
            }
            #secondMsg{
                font-size: 30px;
                font-family:Impact;
                color:yellow
            }
        </style>
    </head>
    <body bgcolor="black">
        <p id="firstMsg">
            {{msg}}
        </p>
        <p id="secondMsg">
            {{additional_msg}}
        </p>
    </body>
</html>
```
main.pyで`{msg}`と`{additional_msg}`に値が埋め込まれます。

#Dockerコマンド
上のフォルダが作成できたら、Dockerのコマンドを打っていきます。
##イメージの作成
Dockerfileのある場所にcdして、

```sh
docker build . -t docker-python -q
```
のコマンドを打ってDockerイメージの作成をします。

`.`でカレントディレクトリにあるDockerfileを指定して、`-t`オプションで名前をつけて、`-q`オプションでログを抑制しています。

`Successfully tagged docker-python:latest`のメッセージが出たら、

```sh
docker images
```
コマンドを打ち、イメージが作成されたことを確認します。

```
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker-python       latest              8febc583700e        27 minutes ago      529MB
```
上記のように出れば、うまく作成できています。
##コンテナの立ち上げ
作成したイメージを基に、コンテナを立ち上げます。

```sh
docker run -it -p 5000:5000 docker-python
```

Dockerfileに、起動時にはFlaskサーバを立ち上げるように記述したため、以下のような出力がされると思います。

```
 * Serving Flask app "main" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
```
これでサーバが立ち上がりました。
#実行
パソコンのブラウザから、`http://localhost:5000/`を叩くと、以下のような画面が出てきます。
![Screen Shot 2018-10-06 at 15.11.37.png](https://qiita-image-store.s3.amazonaws.com/0/283226/73231a04-9504-9dbb-3ad1-de26517fe559.png)




非常に地味ですが、サーバを立ち上げることができました。
偽装されたファイルを作成する。

# 偽装ファイルとは

メール添付などで実行ファイルを例えばほかの拡張子のファイルとしてユーザーにクリックしてもらおうというハッカーなどが利用するやり方です。

このやり方を学ぶことで今後同じようなシチュエーションに出会ったときに適切に対応ができるようになります。
ハッカーは企業などに標的型メール攻撃を仕掛けることがあり今回はその攻撃のうちのひとつである

**標的型メール攻撃**についてご紹介します。

**標的型メール攻撃**とは悪意のあるファイルをメール添付の中に仕掛けて送信するものです。

悪意のあるファイルが一見悪意のなさそうな画像ファイルとして送られることがあります。

しかしOSでは拡張子が開くアプリケーションを決めているはずなので画像ファイルは画像ビューアーのアプリケーションでしか開かないはずです。

ではなぜアプリケーションが実行されてしまうのでしょうか？

# まだまだ知らないユニコードの世界

Unicode(ユニコード)には現在も絵文字などさまざまな特殊文字が追加されかなり深いものになっています。
その中で**右から左に読むことを指定するユニコード**が存在します。

#右から左に読む特殊文字

それはUnicodeの中の「U+202E」です。これは***Right-To-Left-Override***と呼ばれ文字を右から左に読むよう指定するものです。
この特殊文字を使いファイルを偽装します

#ファイルを偽装するやり方

##EXEファイルを作る
![file_malicious.png](https://qiita-image-store.s3.amazonaws.com/0/280363/daa343af-758b-4c06-5652-9858e4ce0390.png)

##アイコンを偽装する。(今回はJPGにしました)
EXEファイルのアイコンの変更は以下のソフトを使用すると便利です。
[ダウンロードリンク](http://angusj.com/resourcehacker/resource_hacker.zip)

アイコンをそれっぽくしました
![malicious2.png](https://qiita-image-store.s3.amazonaws.com/0/280363/7b5f7b7c-8a13-92c2-6d8b-1fef5deafb3d.png)

##いよいよ偽装ファイル作成
***(Windowsの場合です)***charmapを開きます
![u202e.png](https://qiita-image-store.s3.amazonaws.com/0/280363/81a58b54-b85a-5641-b788-485428ff30e7.png)

***「U+202E」***を選択してコピーします。
ファイルの名前を***「malicious_attack.exe」***から***「malicious_attackgpj.exe」***に変更する。
***「g」***の前にさっきの ***「U+202E」***を入れる。すると・・・・・

![malisious_final.PNG](https://qiita-image-store.s3.amazonaws.com/0/280363/27b70dd8-355d-0fc6-1e98-132413558b1a.png)


怪しいファイルができました(笑)


# これで見破れるRLO偽装ファイル

ということで我々は偽装ファイルの作り方を学びました！
これから偽装ファイルでないかどうか以下の項目にチェックしてみてください！

* ***偽装ファイル***はZIPにして格納することができない
* ***偽装ファイル***はファイル種別で実行ファイルだということがわかる
* ***偽装ファイル***はどこかに実行ファイルのファイル拡張子が隠れている

#結論

このRLOで偽装したファイルを開く前にまずはシステム管理者にご連絡ください。こういった初歩的なやり方でも引っかかってしまう個人の被害は後を絶ちません。我々もこの記事のことを社内のメンバーやご家族に伝えるなどして一人でも多くの被害を未然に防げれば本望です。
[Ruby][初心者] yieldについて

## yieldについて
メソッド呼び出しで渡されたブロックをメソッドの中で実行する際に使用するもの

ある特定の処理をブロックという形でメソッドに渡し、メソッド内の任意のタイミングでそのブロックを実行できる

```ruby

def yield_test
  yield(1,2)
end

yield_test { |a, b| a + b }
=> 3
```

明示的にブロックを仮引数で受け取り呼び出すこともできる

メソッドの仮引数の最後に&をつけた仮引数を定義することで、メソッド呼び出しの時に渡されたブロックをProcオブジェクトで受け取ることができる

**ブロックを受け取る変数は仮引数の一番最後でなければならない**


```ruby

def yield_test(&proc)
  proc.call(1,2)
end

yield_test { |a, b| a + b }
=> 3
```

yieldを使った記法は、このProcオブジェクトを受け取ることを省略した記法である。

```ruby

def yield_test
  if block_given?
    yield
  else
    puts 'ブロックがわたされませんでした。'
  end
end

yield_test { puts 'ブロックが渡されました。' }
"ブロックが渡されました。"

yield_test
"ブロックが渡されませんでした。"
```

block_given?メソッドを使うことができる。
ブロックが渡されれば、trueを返し、渡されなければfalseを返す。
【フォーム再送信の確認】が表示された時の対策について

セッションを開始しているところでこのように書く。

```php
session_start();
header('Expires:-1');
header('Cache-Control:');
header('Pragma:');
```
header()でセミコロンの右に何も書かないと、PHPは何も送らない。
session_start()のHTTPヘッダー送出を上書きし、結果的に何も送らない。
WSLでもgitでsshを使いたい

# 背景
WSLで.ssh/configを設定してsshを実行したとき，

```bash
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/mnt/c/ubuntu/home/ユーザ/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/mnt/c/ubuntu/home/ユーザ/.ssh/id_rsa": bad permissions
git@ssh.github.com: Permission denied (publickey).
```
のようなエラーが発生して困ったときのメモ．

# 状況
WSLにおけるホームディレクトリをデフォルトの"/home/ユーザ名"ではなくwindows側の"/mnt/c/ubuntu/home/ユーザ名"にしている．

# 解決策
時間がない人は本命解決策2を見てください

### 解決策1
このようなエラーが出たときはまず最初に```chmod 600 ~/.ssh/config```とすれば解決する．

しかし，これはホームディレクトリがlinux側の場合のみ有効である．

今回はwindows側にホームディレクトリがあるため，これではだめ．(そもそもwindowsは他の人からアクセスされることを想定していないため，パーミッションとかフルオープン)

### 本命の解決策2
#### 追記
シンボリックリンクでも解決することがわかったので
後ろの本命の解決策3で解説しています．

- まず，デフォルト（linux側）のホームディレクトリにいったん移動します．

<he>

```
$ cd /home/ユーザ名
```

ここで，新しくsshkeyを生成します．(古いやつコピーしても大丈夫だと思いますが，試していません)

- sshkey生成

```bash
$ ssh-keygen -t rsa -b 4096 -C　"your_email@example.com"
```

生成されたsshkeyが以下のディレクトリにあることを確認しましょう
```/home/ユーザ名/.ssh/id_rsa```

このファイルのパーミッションを確認してみるとしっかり制限されていることがわかります．

```
$ ls -l /home/ユーザ名/.ssh
total 8
-rw------- 1 ユーザ名 ユーザ名 1675 Oct  6 00:40 id_rsa
-rw-r--r-- 1 ユーザ名 ユーザ名  402 Oct  6 00:40 id_rsa.pub
-rw-r--r-- 1 ユーザ名 ユーザ名  884 Oct  6 00:45 known_hosts
```

- githubに生成したid_rsa.pubを登録します．
ここでは詳細については割愛します．

- 次に，windows側のホームディレクトリに戻り，
先程生成したid_rsaの方を読み込めるように```~/.bashrc```追記します．

```~/.bashrc
#SSH
eval `ssh-agent` > /dev/null
ssh-add /home/ユーザ名/.ssh/id_rsa >& /dev/null
```

ここで> /dev/nullはターミナル起動時にsshkeyが追加されたことお知らせするメッセージを表示しないようにつけました．

あとは，bashrcを再読込するだけでgitのsshが使えるようになっています．

```bash
$ source ~/.bashrc
```

以上です．

## 本命の解説3
linux側でssh-keyを生成するところまでは一緒です．

変更点は，```.bashrc```に追加しないでシンボリックリンクを作成する点です．

- linux側への.sshのシンボリックリンクを作成

```
$ ln -s /home/ユーザ名/.ssh ~/
```
このように設定することで勝手にlinux側の.sshを見に行くので今まで通り使えるようになると思います．
画像生成してOGPに設定する

# 目的

ユーザーによって異なる画像を生成し、OGPに設定する。

# それぞれのやり方のメリット・デメリット

画像生成には下記２つやり方がある。

* クライアントサイドでhtml2canvasを用いて画像生成
* imagemagickでサーバサイドで画像生成

もしアプリ展開してクライアントサイドが複数になる場合はサーバサイドで一括して処理したほうが工数も減り良さそう。html2canvasのほうがcssなどでレイアウトをいじれるので細かい調整は効きそう。

## imagemagicのメリットデメリット

### メリット

* サーバサイド側で処理したらユーザー側の環境の影響受けなさそう。

### デメリット

* 日本語だと折返しの処理を自分で書かないといけないのが面倒だし難しい
* 複数フォントを読み込めない
* 色付きの絵文字フォントを扱えない

## html2canvasのメリットデメリット

### メリット

* imagemagicよりはデザイン調整楽そう

### デメリット

* 対応していないcssがあるので注意
* ユーザーのブラウザによってデザインが微妙に変わる

# html2canvasを用いて画像生成

## 全体設計

* html2canvasで画像を生成
* javascriptからbase64→blobに変換
* hidden_fieldでcarriwave経由でサーバに送る

## そもそもcanvasとは？

ブラウザ上で図を書くための仕様でhtml5で採用されている。<canvas>タグでhtmlのスペースを規定してその中でjavascriptを用いて描画する。

## html2canvasの導入

ドキュメント
http://html2canvas.hertzen.com/documentation

npmで導入する。詳しい導入方法は上記。

## html2canvasで任意のDOMを画像に

```javascript
//ロードされた際の処理として実施：
window.onload = function(){
  //HTML内に画像を表示
  html2canvas(document.getElementById("target"),{
    onrendered: function(canvas){
      //imgタグのsrcの中に、html2canvasがレンダリングした画像を指定する。
      var imgData = canvas.toDataURL();
      document.getElementById("result").src = imgData;
    }
  });
}
```

引用：https://qiita.com/youwht/items/8b681a856f59aa82d671

html2canvasは#targetに指定したidをキャプチャする。

### appendChildについて

appendChildは、特定の親要素の中に要素を追加するためのメソッドです。javascriptで使われるものでjqueryだとappendのみ

「【JavaScript入門】appendと何が違う？appendChild徹底解説」
引用：https://www.sejuku.net/blog/49970


## 画像をbase64→blobに変換

## textform経由で送信

## 生成した画像を保存

https://qiita.com/you8/items/d5f157a428e3fffa35e3

rails+carrierwaveで画像保存する方法は上記。

## ブラウザに表示させたくない場合

隠しDOMで別に作っておいてoverflow:hiddenで隠す方法があるらしい（未確認。誰か教えて）

## retina対応

html2canvasのデフォルト設定では、生成された画像をRetinaディスプレイで見たときに、画質が荒くなってしまいます。 公式対応は現状されていないのですが、なんと有志の手によってRetina対応が可能となりました。 https://github.com/niklasvh/html2canvas/pull/1087

ファイルを一部書き換える手間は生じますが、その後はdpi, scaleオプションを設定することで、生成された画像を綺麗に表示することが可能となります。 ただし、サイズや画質を上げると、その分レンダリング処理に時間がかかり、また上記の描画領域制限に引っかかる可能性があるので、注意が必要です。

引用：https://techblog.kayac.com/html2canvas

# puppeteerを使う（調査中）

https://github.com/GoogleChrome/puppeteer

# svgから生成

https://qiita.com/serinuntius/items/3017fb6ef51cd47352f6#ogp%E8%A1%A8%E7%A4%BA%E5%81%B4cloudfunction%E3%82%B3%E3%83%BC%E3%83%89

「Vue.jsとFirebaseでOGP画像生成系のサービスを爆速で作ろう」を実際に作ってみる」
https://qiita.com/kanye__east/items/6cbcdc8fe5103084c737

この記事ではsvgに文字を出して画像化している。ただこのやり方だとおそらく改行ができない。