OmniAICreator/Qiita-1.07M huggingface dataset:
WP on cloudfront で利用時に Gutenberg が機能しない。

#課題
Gutenberg エディターが表示されるも、ブロックの追加や、画像アップロードなどできない状態で、
ブロックエディターが機能していない様子。

#解決策
CloudFront で Request Headers が書き換えられてたのが原因でした。
Whitelist に User-Agent を加えて上げることで解決しました。

<img width="869" alt="aa.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6531/f1dca097-a3cc-b7e3-d6aa-21e58cf9708a.png">


開発コンソールなどにエラーがでてなくハマる予兆がして焦ったが、以下の記事がヒットして直ぐに解決できてよかった。
先人の方に感謝です。

参考：
https://qiita.com/kooohei/items/4dcdb506745a6a1eef66
https://hisa-tech.site/invalid-gutenberg/
[C++]Ubuntuで外部ライブラリBoostの導入からサンプル実行まで

#はじめに
Ubuntuの場合、どうやらaptで入手できるらしいのですが、今回は公式サイトからダウンロードしてきました。
個人的に`main.cpp`と同じフォルダに入れておきたかったので、下のようなディレクトリの構成にしました。

#環境
 - OS : Ubuntu 18.04 LTS
 - コンパイラ : g++ 7.4.0
 - 他 : GNU Make 4.1

# Boostの入手
[公式](https://www.boost.org/users/download/)からダウンロード。

#解凍
`tar -zxvf boost_1_72_0.tar.gz` (2020/1/30現在のバージョン)

#セットアップ
1. 解凍したフォルダ内の`bootstrap.sh`を実行。
2. `boost_1_72_0`フォルダ内に`hogehoge`フォルダ作成。
3. `./b2 install -j2 --prefix=hogehoge`。

#ディレクトリの構成
上の`hogehoge`を`boost_ws1`に移動させました。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246294/a846608b-18da-29c1-38cb-84660eaf8acc.png)

#Makefile
```
build:
	g++ \
	 -L ./hogehoge/lib \
	 -I ./hogehoge/include \
	 -o main main.cpp

run:
	./main
```

#サンプル
```main.cpp
#include <iostream>
#include <boost/version.hpp>

using namespace std;

int main(void){

	cout << BOOST_VERSION << endl;

return 0;
}
```

#コンパイル&実行
`boost_ws1`フォルダで端末を開き、
`make build`
`make run`

#実行結果
`107200`

#おわりに
外部ライブラリたのC++。
Android Vulkan で ValidationLayers をインストール, 有効にするメモ

https://developer.android.com/ndk/guides/graphics/validation-layer

## 環境

* NDK r21(検証レイヤーがひとつにまとまって便利)
* Android9 or later(Android 10(Pixel4) で動作確認)

.so を apk に含めるか, Android9 以降では .so をアプリ固有ストレージに置いて, 実行時に validation layer(.so) をロードすることができます.
 
## gradle に指定して apk にパッケージングする設定

https://developer.android.com/ndk/guides/graphics/validation-layer#ilp

特段問題なくできるかと思います.

gradle で ndk のディレクトリは android.ndkDirectory で取得できます.

https://stackoverflow.com/questions/32751398/how-can-i-access-sdk-ndk-paths-in-my-gradle-build-scripts

Android Studio を使っている場合, `local.gradle` に NDK のパスを自動で設定してくれると思いますが, gradle 直でビルドする場合はこのファイルで NDK のパスを設定しておく必要があると思われます.

## NDK から prebuild をコピってくる場合

ドキュメントにあるように, jniLibs フォルダをコピってくれば apk に含んでくれます.
git などでアプリを管理したいときはこの方法が管理が楽になりいいかもしれません.

ただ, arm64-v8a だけで 40MB あります. 全てのアーキテクチャを含めると 140MB くらいになるので, 必要なものだけ追加しましょう. 2020/01 時点では実質 arm64-v8a 一択でよいでしょう(x86, x86-64 で Vulkan 動く Android 実機はあるのかしらん...? x86 系はエミュレータでのデバッグ用?)

NDK のバージョンが上がったりしたらアップデートが必要です.

きちんと apk にファイルが含まれているかどうかは, Android Studio 使っている場合 `Build` -> `Analyze APK` でパッケージ内容を確認することができます.

## 自前でビルド

ソースコードからビルドしたいときもあります.

https://github.com/KhronosGroup/Vulkan-ValidationLayers

の `build-android` で `build_all.sh` を叩くのが楽でしょう.

ANDROID_SDK_HOME, ANDROID_NDK_HOME 環境変数を設定し,
aapt, zipalign, jarsigner など build-tools と, ndk-build へのパスを設定しておきます.

あとはスクリプト実行すればそのまま .so などビルドされるはずです.
(ちなみにこのスクリプトは gradle を使わずに apk を作っており本当に素晴らしいですね)

### validation layer .so をアプリ固有ストレージから読む(Android9 or later)

https://developer.android.com/ndk/guides/graphics/validation-layer#layers-local-storage

にあるように, いったん `/data/local/tmp` にファイルを置いてからアプリ固有ストレージに push します.
一度アプリの apk をインストールしておく必要があるかと思います.

いったん `/data/local/tmp` にファイルを置く必要がある理由は, こちらを参照ください.

Android C/C++ でアクセスできるストレージのメモ
https://qiita.com/syoyo/items/f3919209b5355a57fd88


## 他の APK から validation layer を読む(Android 10)

この方法は adb install するだけなので, 多少手間が減って便利... かもしれません.
もしくは, リリースに近い APK でテストするため, validation layers .so を含めたくないときなど.

Android の Developer options などで validation layers を有効にします.

T.B.W.

## 動作確認

validation layers の利用は PC と同じです.
C/C++ コード側で明示的に有効にする必要があります.

Android Vulkan document や, Vulkan tutorial

https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers

あたりを参照ください.
.so を APK に含める場合は, Developer options などで validation layer 有効は不要です.

NDK r21 以上では, `VK_LAYER_KHRONOS_validation` だけ指定で OK です.

うまくロードできると(APK jniLibs に追加する方法で試しました), adb logcat で

```
 I/vulkan: Loaded layer VK_LAYER_KHRONOS_validation
```

というのを確認できるはずです.

そのままでは error などあっても logcat に表示されないようなので, https://developer.android.com/ndk/guides/graphics/validation-layer#debug を参考に debug log を出す必要があります.


Sascha 先生の Vulakn サンプルが参考になると思います.

https://github.com/SaschaWillems/Vulkan

また, Validation layers が有効で, Vulkan API が適切に呼ばれてエラーやワーニングが無ければ `I/vulkan: Loaded layer` 以外はなにも出力されません.

## TODO

* [ ] debug callback https://developer.android.com/ndk/guides/graphics/validation-layer#debug を利用して, validation layer のエラーを logcat に渡す.
【備忘録】AWS-QuickSight簡易手順書

# はじめに
社内でQuickSightを使う機会があり先輩に色々教わったけど絶対忘れる、、、
 → 忘れたとき用に、簡易手順や備忘録を残します。

# QuickSight 分析の作成
### 1．QuickSightを開きましょう
AWSのコンソールで「quicksight」と検索するとサービスがヒットする。
※AWSに吸収?されたから、他のAWSサービスとは異なり独立したGUIで開かれる。
　（別タブで開かないと、もともとのAWSコンソールが持っていかれる。二要素認証しんどい。。）


こんな画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443963/10a6848d-652e-5add-63fc-abf2136983bf.png)

### 2．「新しい分析」で新規作成
左上にある青いボタンをポチりましょう。

### 3．「新しいデータセット」でクリック
これもまた左上にある「新しいデータセット」をクリックしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443963/ba053744-838b-50be-5ca3-236b3e4dc2d8.png)

### 4．使いたいデータセットを選択
RDSやS3、Athenaなど色々と選択肢があります。
今回はAthenaを使ってみます。
※Athena - S3のデータに対してSQLでクエリ出来るサービス。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443963/72d32ddc-0c8d-f57b-1786-5d73055f6e8c.png)

### 5．Athenaでいろいろ設定
Athenaをクリックするといくつか入力が求められます。
入力したら「データソースを作成」をクリック。
以下参考までに。

[データソース名] - 任意の名前
[Athena workgroup] - Athena側でworkgroupを作っていなければ [primary]



### 6．Athenaのテーブルを指定
Athena(glue)側でDBを作成している場合はプルダウンで選択可能。
※カスタムSQLを用いて選択することもできる。


### 7．データセットの作成を終了する
この画面で2つのパターンから選択を迫られる。
選択したらvisualizeをクリック。

【備忘録】
・SPICEもしくはデータクエリ直接実行の2パターンがある。
① データクエリ直接実行は、quicksightで集計する都度でクエリを実行する。
② SPICEはメモリにデータを持たせることができるパターン。
　無償ライセンスでの利用の場合には**メモリ上のデータは暗号化されないよう**なので要注意。
　※有償ライセンスだとメモリ上を暗号化できるそうな？


------
**ここまでが分析の作成方法、これ以降は分析画面上の備忘録**

## 分析画面の操作方法など
#### 追加
・グラフを追加できる。
・追加した画面はドラッグすることで簡単にカスタマイズ可能。


#### 視覚化

・グラフのY軸、値、グループ/色 を指定することができる。
・データセットを選びなおすことも可能。

#### フィルタ
・グラフごとにいらない値などを絞ることができる。
・パラメータでいじったものをグラフに反映させるには、"カスタムフィルタ"の設定が必要。

#### パラメータ
・コントロール(グラフプロット部分の上に出てくるバー)を作成するもの。

#### アクション
・グラフをクリックしたときのアクション設定が可能。
・取得データに応じたアクションという凝ったことも実現できるそうな。
pyenvのバージョンインストール時に、「zipimport.ZipImportError: can't decompress data; zlib not available」が出た場合

```
pyenv install x.x.x
```

をしたら、以下のエラーが出た。

```
zipimport.ZipImportError: can't decompress data; zlib not available
```

以下のコマンドを、bashで流したらOKになった。

```
bash
CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install 3.7.2
```
tkinterで子ウィンドウを出すときに、複数作成できてしまうので防止する方法

## 事の発端
tkinterでサブウィンドウを作っていたら、サブウィンドウ内のラジオボタンがバグってしまい、表示した瞬間に２つ選択されているような状態になったので、原因を探っていった結果、以下のコードのようにすれば、うまくバグも出なく待ったし、他の問題点も発見できました。

## バグった原因
たぶん、親windowのmainloop()と子windowのmainloop()が、Toplevelで親子の関係付けをしていなかったために、意図しない表示になったと思われます。

## 参考
https://qiita.com/koji-hirono@github/items/df9a40dd3351bfbd0d9a
↑このページのコードを参考にしました。非モーダルでsingletonにするということらしいです。

## 以下のコードのポイント
親ウィンドウと子ウィンドウをToplevel()で紐付けするのですが、ボタンのcommandでコールバックさせた場合はうまくいくが、そうでない場合は、子ウィンドウが何個でも作成できてしまうという違いを発見しました。

## サンプルコード
以下のコードをコピペすればサンプルを実行できます。
追記）バグを見つけたため、this_window_close(self)のメソッドを追加修正しました。

``` python3
import tkinter


# 子ウィンドウ
class ChildWindow:
    def __init__(self, parent):
        self.parent = parent
        self.window = None
        self.radio_1 = None
        self.radio_2 = None
        self.radio_3 = None
        self.var = tkinter.IntVar()  # チェック有無変数

    def init(self):
        if not self.window:
            self.window = tkinter.Toplevel(self.parent)

        self.var.set(1)  # value=0のラジオボタンにチェックを入れる
        # ラジオボタン作成
        self.radio_1 = tkinter.Radiobutton(self.window, value=0, variable=self.var, text="幅32")
        self.radio_1.place(x=10, y=10)
        self.radio_2 = tkinter.Radiobutton(self.window, value=1, variable=self.var, text="幅140")
        self.radio_2.place(x=60, y=10)
        self.radio_3 = tkinter.Radiobutton(self.window, value=2, variable=self.var, text="幅200")
        self.radio_3.place(x=110, y=10)

        # ×ボタンの処理をカスタマイズする
        self.window.protocol('WM_DELETE_WINDOW', self.this_window_close)
        
        self.window.mainloop()

    def this_window_close(self):
        self.window.withdraw()
        # ↓これをしないと、子ウィンドウを閉じた後に、再度開くことが出来なくなる。
        self.window = None
        return "break"


# 親ウィンドウ
class ParentWindow:
    def __init__(self):
        self.root = tkinter.Tk()
        self.sub_root = ChildWindow(self.root)
        self.sub_root_failure = None

        self.root.geometry(str(320) + "x" + str(200) + "+" + str(200) + "+" + str(200))

        self.btn_parent = tkinter.Button(text="何個も作成できてしまうボタン",
                                         command=self.create_new_window)
        self.btn_parent.place(x=10, y=10, width=300, height=25)

        self.btn_child = tkinter.Button(text="一つだけしか作成できないボタン", command=self.sub_root.init)
        self.btn_child.place(x=10, y=50, width=300, height=25)

        self.root.mainloop()

    def create_new_window(self):
        self.sub_root_failure = ChildWindow(self.root)
        self.sub_root_failure.init()
        self.sub_root_failure.window.title("沢山")


def main():
    ParentWindow()


if __name__ == "__main__":
    main()
```

## 動作結果
以下のイメージの通り、何個でも子ウィンドウが作成できてしまうボタンと、１つしか子ウィンドウが作れないボタンができます。
<img width="533" alt="スクリーンショット 2020-01-30 18.37.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262477/b08140c8-4afd-f130-0d17-ab12eac494a7.png">

## 感想
自分にはどうしてこのような違いが出るのか、ちょっとわかりませんが、結果として、このような違いが出るので、tkinterで子ウィンドウを表示させる場合は、この問題点に引っかかると思われるので、気をつけて頂きたいです。
Raspberry Pi(Python)のテレメトリーをAzure IoT Hubから取得する

# アーキテクチャ

<img width="427" alt="ControllADevice.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/a2477fe9-edd6-3fce-281b-a8f8c6093c40.png">

# 事前準備

## MacOS

### Azure CLI インストール

```bash
brew update && brew install python3
brew link --overwrite python3
brew install azure-cli
```

### Azure CLIログインとAzure CLIのIoT拡張インストール

```bash
az login
az extension add --name azure-cli-iot-ext
```

### Azure IoT Hub 作成

```bash
# AzureサブスクリプションID取得
subscriptionID=$(az account show --query id)

# ロケーション設定(Japan East)
location=japaneast

# リソースグループ設定
resourceGroup={ResourceGroupName}

# リソースグループ作成
az group create --name $resourceGroup --location $location

# IoT Hub名設定
iotHubName={AzureIoTHubName}

# IoT Hub作成 (F1無料)
az iot hub create --name $iotHubName --resource-group $resourceGroup --sku F1 --location $location
```

> https://portal.azure.com/#create/Microsoft.IotHub

### デバイス登録 

```bash
az iot hub device-identity create --hub-name {AzureIoTHubName} --device-id {DeviceName}
```

### デバイス接続情報取得

```bash
az iot hub device-identity show-connection-string --hub-name {AzureIoTHubName} --device-id {DeviceName} --output table
```

### サービス接続情報取得

```bash
az iot hub show-connection-string --policy-name service --name {AzureIoTHubName} --output table
```

# テレメトリー送信（定期と呼び出し）

## Raspberry Pi

### Pythonパッケージインストール

```shell
pip3 install azure-iot-device
```

### サンプルコードのリポジトリクローン

```shell
mkdir -p ~/Source/Repos && cd ~/Source/Repos
git clone https://github.com/Azure-Samples/azure-iot-samples-python/
cd ./azure-iot-samples-python/iot-hub/Quickstarts/simulated-device-2
```

### デバイス接続情報更新

```shell
vi SimulatedDevice.py
```
> <img width="724" alt="CONNECTION_STRING.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/6b803497-ec60-fd3f-42ce-d59400b98bbc.png">

### 実行

```shell
python3 SimulatedDevice.py
```

# テレメトリー確認

## Azureポータル

### Azure Cloud Shell

```bash
az iot hub monitor-events --hub-name {AzureIoTHubName} --device-id {DeviceName}
```

# テレメトリー取得

## MacOS

### Pythonパッケージインストール

```shell
pip3 install azure-iot-hub
```

### サンプルコードのリポジトリクローン

```shell
mkdir -p ~/Source/Repos && cd ~/Source/Repos
git clone https://github.com/Azure-Samples/azure-iot-samples-python/
cd ./azure-iot-samples-python/iot-hub/Quickstarts/back-end-application
```

### サービス接続情報更新

```shell
vi BackEndApplication.py
```
> <img width="718" alt="CONNECTION_STRING.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/482d3c98-959f-3cf9-76bc-ad7ffe65c748.png">

### 実行

```shell
python3 BackEndApplication.py
```

---
> https://docs.microsoft.com/en-us/azure/iot-hub/quickstart-control-device-python
Raspberry Pi(Python)からAzure IoT Hubへテレメトリーを送信する

# アーキテクチャ

<img width="452" alt="SendTelemetry.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/6bfb889b-cb29-957f-4d0f-6401bd1d5cdd.png">

# 事前準備

## MacOS

### Azure CLI インストール

```bash
brew update && brew install python3
brew link --overwrite python3
brew install azure-cli
```

### Azure CLIログインとAzure CLIのIoT拡張インストール

```bash
az login
az extension add --name azure-cli-iot-ext
```

### Azure IoT Hub 作成

```bash
# AzureサブスクリプションID取得
subscriptionID=$(az account show --query id)

# ロケーション設定(Japan East)
location=japaneast

# リソースグループ設定
resourceGroup={ResourceGroupName}

# リソースグループ作成
az group create --name $resourceGroup --location $location

# IoT Hub名設定
iotHubName={AzureIoTHubName}

# IoT Hub作成 (F1無料)
az iot hub create --name $iotHubName --resource-group $resourceGroup --sku F1 --location $location
```

> https://portal.azure.com/#create/Microsoft.IotHub

### デバイス登録 

```bash
az iot hub device-identity create --hub-name {AzureIoTHubName} --device-id {DeviceName}
```

### デバイス接続情報取得

```bash
az iot hub device-identity show-connection-string --hub-name {AzureIoTHubName} --device-id {DeviceName} --output table
```

# テレメトリー送信

## Raspberry Pi

### Pythonパッケージインストール

```shell
pip3 install azure-iot-device
```

### サンプルコードのリポジトリクローン

```shell
mkdir -p ~/Source/Repos && cd ~/Source/Repos
git clone https://github.com/Azure-Samples/azure-iot-samples-python/
cd ./azure-iot-samples-python/iot-hub/Quickstarts/simulated-device
```

### 接続情報更新

```shell
vi SimulatedDevice.py
```
> <img width="724" alt="CONNECTION_STRING.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/6b803497-ec60-fd3f-42ce-d59400b98bbc.png">

### 実行

```shell
python3 SimulatedDevice.py
```

# テレメトリー確認

## Azureポータル

### Azure Cloud Shell

```bash
az iot hub monitor-events --hub-name {AzureIoTHubName} --device-id {DeviceName}
```

---
> https://docs.microsoft.com/en-us/azure/iot-hub/quickstart-send-telemetry-python
beautifulsoup4 Xpath指定で要素を取得

## やり方
* lxmlを使えばOK
  * beautifulsoup単体ではXpath指定不可

## 流れ
1. beautifulsoupでhtmlをパースして、
2. lxmlで変換すると、
3. xpath指定できる！

```.py
import urllib2
from lxml import html
from bs4 import BeautifulSoup

data = urllib2.urlopen("http://example.com")
soup_parsed_data = BeautifulSoup(data, 'html.parser')

lxml_coverted_data = html.fromstring(str(soup_parsed_data))

# あとはお好きにどうぞ
lxml_coverted_data.xpath('xxx/yyy/...')

```

[Xpath書き方](https://gogodiet.net/z/xml/7.htm#c5)
NFSでCentOS7サーバー間ファイル共有

# NFSでサーバー間ファイル共有

複数サーバーでのファイル共有は、[以前書いた記事](https://qiita.com/rui-watanabe/items/ef15f4fe97a55c0f51f3)でlsyncdを紹介しましたが、今回は**NFSというサーバー間ファイル共有**について紹介していきたいと思います

# NFSとは

NFSとは**ネットワークを介して、サーバに公開されたディレクトリをローカルにマウントし共有することができる技術**です。

NFSを利用すると、複数のホストから同じファイルを共有することができるなどの利点があります。


# 前提条件
・NFSサーバとNFSクライアントの2台のCentOS７サーバー

# NFSの実装

ここからNFSを実装するための手順について、紹介していきたいと思います。

##NFSサーバー側の設定
## パッケージインストール

yumで、nfsに必要なパッケージnfs-utilsをインストールし、/mnt下に共有するディレクトリを作成します。

```
# yum -y install nfs-utils
# mkdir /mnt/nfsserv/

共有確認のためテキストファイル作成
# cd /mnt/nfsserv/
# vi test.txt
test
```

##権限設定と起動

/etc/exports下に、ファイルの権限の設定を記載します。

権限は、全員読み込み書き込み可能の設定にし、その後サービスの起動をします。

```
# vi /etc/exports
/mnt/nfsserv/ *(rw,async,no_root_squash)

# systemctl enable rpcbind
# systemctl start rpcbind
# systemctl enable nfs-server
# systemctl start nfs-server
```

##NFSクライアント側の設定

## パッケージインストール、共有ファイル作成、起動

NFSサーバー側同様、nfs-utilsをインストールして、共有ファイルを作成し、起動します。

```
# yum -y install nfs-utils
# mkdir /mnt/nfsclient/
# systemctl start rpcbind
```

## マウント設定

/etc/fstabを編集して起動時のマウント設定をし、マウントします。

```
# vi /etc/fstab
NFSサーバーのIPアドレス:/mnt/nfsserv/ /mnt/nfsclient/ nfs defaults 0 0

# mount -v NFSサーバーのIPアドレス:/mnt/nfsserv/ /mnt/nfsclient/
```

マウント元であるNFSサーバーのtest.txtが/mnt/nfsclient/に共有されていたら、NFSのサーバー間共有設定は無事完了です。


#参考URL
https://qiita.com/sugimount/items/1c1ab9b45b0d862a7dd6#nfs%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A
https://qiita.com/rikudai/items/f9900e4865ce25a8464e
https://www.designet.co.jp/faq/term/?id=TkZT
https://eng-entrance.com/linux-mount
html.erbで属性を追加する方法

html.erbで属性を追加する方法の備忘録

# 背景
`class` や `data` 属性の追加方法しか検索に引っかからなかったので。（検索方法が悪い）


# HTML

```html

<button area-label="閉じる">✕</button>
```

このHTMLをerbに置き換えると↓

# erb

```erb

<%= button_tag "aria-label" => "閉じる" do %>✕<% end %>
```

#参考
https://stackoverflow.com/questions/26892895/erb-form-text-area-attribute-name-format
複数のプライベートVPCに、1台の YAMAHAルーター RTX1210 からVPN接続する

# やりたかったこと

複数のプライベートVPC（AWSアカウントも別々）に
1台のRTX1210からVPN接続したい

# 環境

YAMAHAルーター RTX1210
ファームウェア： Rev.14.01.33

# 方法

カスタマーゲートウェイの BGP ASN を、同じ番号で揃える。

# 解説

RTX1210 １台につき、BGP ASN は1個しか設定できない、とのこと。

ならばと、
それぞれのVPCへのVPN設定をRTX1210に施すときに、
作成するカスタマーゲートウェイの BGP ASN を
強引に同じ番号で揃えてみたら、行けました。

AWSの「サイト間VPN接続」そのものの説明は、ここでは割愛させて頂きます！
Railsチュートリアルで作ったsample_appにFacebookログイン機能をつける際の注意点



deviseの導入について


https://qiita.com/mailok1212/items/74e6dae08c1bafb874ec
この記事の通りに進めていくと

```
SQLite3::SQLException: duplicate column name: email: ALTER TABLE "users" ADD "email" varchar DEFAULT '' NOT NULL
```

とかいうエラーにあたと思うのでそれを回避できる手順を紹介します。

まずはdeviseを導入するためにGemfileに

```
gem 'devise'
```

と入力します。


そして

```
$ bundle install
$ rails g devise:install
```

と入力します。

次にusersテーブルに以下のカラムを入力するために、

```
$ rails g migration AddColumnsToUsers uid:string provider:string
```

と入力してください。
このコマンドはstring型のuidというカラムとstring型のproviderというカラムをusersテーブルにいれる
というコマンドです。

あとは、

```
rails db:migrate
```

を実行し、https://qiita.com/mailok1212/items/74e6dae08c1bafb874ec

の通りに進作業をすれば実装できるかと思います。






https://qiita.com/mailok1212/items/74e6dae08c1bafb874ec
https://qiita.com/w-tdon/items/53ba2a0c663c1303374a
【Laravel 6.x】authorizeResource() の罠とその対処法

Laravel の `authorizeResource()` を使って認可の実装をしようと思ったとき、index ページの403エラーが消えなくなって困ったことがあったからここに書いておく。

## 環境
- Laravel 6.x

## authorizeResource() とは
[Laravel6.x 認可](https://readouble.com/laravel/6.x/ja/authorization.html)

例えば、とあるCRUDアプリケーションに記事投稿用のコントローラがあったとする。
アクションごとに権限を変えたりしたいときには、Policy を使って認可すると思う。

```PostController.php
public function show(Request $request, Post $post)
{
    $this->authorize('view', $post);

    // 処理を書く
}

public function create(Request $request)
{
    $this->authorize('create', Post::class);

    // 処理を書く
}

public function update(Request $request, Post $post)
{
    $this->authorize('create', $post);

    // 処理を書く
}

```

.....しかし、いちいち `$this->authorize('xxxx', xxxx);` と書くのは面倒くさい。
こんなときに `authorizeResource()` が使える。
コンストラクタに下記のように書けば、`$this->authorize('xxxx', xxxx);` の記述なしで自動で各アクションごとの Policy を見に行ってくれる。

```PostController.php
public function __construct()
{
    $this->authorizeResource(Post::class, 'post');
}
```

<b>※`authorizeResource()` はリソースコントローラを使用しているときのみ使用可能</b>


## authorizeResource() の罠 (Laravel6.x~)
index アクションは認可を必要としていないはずなのに、index ページにいくと、403エラーになっていた。

結論から書くと、今回かかった罠は Laravel6.x アップグレードガイドに書かれていた。

> authorizeResourceメソッドを用いてコントラーへ付加している認可ポリシーは、viewAnyメソッドを定義する必要があります。コントローラのindexメソッドへユーザーがアクセスする時に呼び出されます。定義しないと非認可扱いとなり、コントローラのindexメソッドへの呼び出しは拒否されます。

[Laravel6.x アップグレードガイド 認可リソースとviewAny](https://readouble.com/laravel/6.x/ja/upgrade.html#authorized-resources) より


index アクションの認可が不要なときも、Policy に index アクション用のメソッド `viewAny()` を書かなければいけなくなったのだ。

```PostPolicy.php
class PostPolicy
{
    public function viewAny(User $user)
    {
        return true;
    }

    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}
```

`viewAny()` メソッドが定義されていない場合、非認可扱いとなり、私の時と同じように index ページで403エラーとなる。

<b>※ Policy のアクション名は `index` でなく、`viewAny()` なことに注意</b>
#### メソッド名対応表
| コントローラメソッド       |       ポリシーメソッド |  
|:-----------------:|:------------------:|
| index             |              viewAny |  
| show           |            view |     
| create             |              create |       
| store               |                create |     
| edit             |             update |  
| update          |           update |  
| destroy | delete |  

## まとめ
- Laravel 6.x 以上で `authorizeResource()` を使っている人は気を付ける
- アップグレードガイドはよく読む
第３回東京公共交通オープンデータチャレンジで審査員特別賞を頂きました。

本日行われた第3回東京公共交通オープンデータチャレンジにて、審査員特別賞を頂きました。
今後、東京公共交通オープンデータチャレンジなどのコンテストに応募する人に向け、反省点などを共有させて頂きます。
技術的な話よりは、このアプリを作成することになった動機などがメインです。

## 作成したもの：いついく？くらべる。Powered by Worker Step

下の図のような、経路検索システムです。一般的な経路検索との違いは、出発時間を１分ずつずらし、１時間分の複数経路を一括で検索してグラフ化することです。

![](https://gyazo.com/04e64f1818e359f7446cbf8bc48b2695.png)

上・下の図は、ある経路における東京駅から渋谷駅までの所要時間を表した図です。

![](https://gyazo.com/e341a23ee1d3e1277096c634c5d349fc.png)

列車の接続が良い時は待ち時間が少なくなるので、最短22分で到着します。一方、列車の接続が悪い場合には、39分掛かってしまいます。

１つ目のグラフのように、出発時間によって、中央線経由で行った方が早い場合や山手線で行った方が早い場合なども異なります。

本システムは、「定期券を買う場合、一般的にどちらの経路の方が早いか」といった疑問を一気に可視化できるツールとなっています。

## なぜこれを作ったか

他のコンテストで予想より忙しくなってしまったこと、大学の試験期間と完全に重なってしまったことから、〆切1週間前に、当初計画していたアプリの開発は不可能であると判断し、全く異なる方向性に切り替えました。

元々はチームで行っていたのですが…。第４回コンテストも開催されるとのことで、そちらの方で再挑戦したいと思います。

ということで、完全に方向性を変えてから、残された時間は僅か１週間。しかも、試験前。そんな絶望的なタイミングでしたが、既に持っている強みを活かせるアイデアを再検討していました。そんな中、学校へ行く途中で列車を1本乗り過ごしただけなのに到着が15分程遅くなるという事件が発生（２か月に1度くらいあります）。いつ家を出るのが一番お得なのだろうかと思い立ち、第２回コンテストで作成した経路検索エンジンを用いて、多くの経路検索を行う（第2回の混雑シミュレーションの方が遥かに数は多いです）このシステムを作成しようという方針に決めました。


## スケジュール

[第二回コンテスト以前のスケジュールはこちら](https://qiita.com/takoyaki3/items/edcf3c2d03b2f03f8a95#スケジュール)

|日時|進捗|
|---|---|
|2019年4月|始動|
|2019年5月～8月|なあなあで方針が決まらず…|
|2019年9月|製作に取り掛かるも、なかなか進まず…|
|2019年11月|方針変更|
|2019年11月9日・10日|なんとか形にする。|
|2019年11月14日・15日|修正・動画作成など|

## システム構成

システム構成は、次のようになっています。

![](https://gyazo.com/a64813f458b01b9c2c99685652960178.png)

今回追加したのは、左下の「60分一括検索」及び「Web Server」部分です。
制作にかける時間を短縮するため、既存のリソースを最大限生かせる構成にしました。

その分無駄が多く、60分一括検索をするのであれば、同じ列車に乗るときは前回の検索結果を利用するなどの効率化ができるはずですが、今回の作品では「9:00発」と「9:01発」の発車は、全くの別物として検索しています。

今回のサーバー側のプログラムは、基本的にPHPとC++で作成しているのですが、個人的に最近始めたGoなどで書いてみたいなとも思います。

### 60分一括検索プログラム（C++）
ユーザからの検索クエリを受け取り、複数経路の60分の検索クエリを後述の経路検索プログラムに投げる役割をしているプログラムです。今回、新たに開発しました。~~（開発といっても、クエリを投げるためのforループを回して、結果をJacaScriptで扱いやすいように、１時間分のデータをまとめてJSONに変換するだけですが。）~~

### 経路検索プログラム（C++）
第２回東京公共交通オープンデータチャレンジで使用したものを、データ構造などを改良したバージョンです。できることは基本的に変えていませんが、複数経路での所要時間を取り出せるように、他のプログラムとの通信部分を若干改良しました。

経路検索に関する大まかな仕組みは、
[第2回東京公共交通オープンデータチャレンジで優秀賞をいただきました。](https://qiita.com/takoyaki3/items/edcf3c2d03b2f03f8a95#アルゴリズム)の記事をご覧ください。

### 遅延推定プログラム（C++）
今回は使用していません。

### 混雑推定プログラム（C++）
今回は使用していません。

## 感想
他の受賞者の方々の作品も、東京をデジタル空間上に再現したものや、駅構内の経路検索など、非常に面白い作品が多かったです。他の参加者との歓談会、とても楽しませていただきました。
公共交通系のLT会などがありましたら、プロフィールに記載してあるメールアドレスにお誘いいただけると嬉しいです。
応募期限直前での計画変更ということで、目的ありきではなく、既存のプログラムありきになってしまったことを申し訳なく思います。しかし、昨年応募させて頂いたプログラムにわずかに手を加えただけで、「リアルタイム遅延情報を考慮した経路検索アプリ」から「１時間分の経路を検索し、比較できるアプリ」へと、見せ方をかなり変えることができたことには満足しています。
第4回では、今回ドタバタして完成まで漕ぎ着けなかった元々の計画を、仲間と共に応募できるよう、頑張りたいと思います。

デバッグ等が間に合わず、若干動作が不安定ですので、春休みに改良しようと思います。
試してみていただけると幸いです。

WebアプリURL：
[https://kuraberu.workerstep.work](https://kuraberu.workerstep.work)

[第４回東京公共交通オープンデータチャレンジ](https://tokyochallenge.odpt.org/)も開催されるようです。
挑戦してみてはいかがでしょうか。
【GKE】 kubectl top pod で Metrics not available のエラーが出た時の解決法

## はじめに

`kubectl top pod` でCPUリソースを確認することがあるかとは思います。
その時にエラーが起きたので、備忘録として残してます。


## 事象

下記のようにコマンドを打つとエラーが出ました。

```
$ kubectl top pod
W0130 09:00:54.156097    5615 top_pod.go:192]
Metrics not available for pod hoge, age: XXhXXmXX.XXs
error: Metrics not available for pod huga, age: XXhXXmXX.XXs
```

## 解決策

バージョンを確認すると

```
$ kubectl version -o json
{
  "clientVersion": {
    "major": "1",
    "minor": "9",
    "gitVersion": "v1.9.7",
    "gitCommit": "dd5e1a2978fd0b97d9b78e1564398aeea7e7fe92",
    "gitTreeState": "clean",
    "buildDate": "2018-04-19T00:05:56Z",
    "goVersion": "go1.9.3",
    "compiler": "gc",
    "platform": "darwin/amd64"
  },
  "serverVersion": {
    "major": "1",
    "minor": "12+",
    "gitVersion": "v1.12.10-gke.17",
    "gitCommit": "27b48e2b4c9535d185ec945c6a513537e4d116cf",
    "gitTreeState": "clean",
    "buildDate": "2019-10-21T20:10:26Z",
    "goVersion": "go1.12.11b4",
    "compiler": "gc",
    "platform": "linux/amd64"
  }
}
```

バージョンが異なっているので、エラーが起きていると思い、
バージョンを合わせてみました。

```
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.12.10/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl $(which kubectl)
```

これで、もう一度 `kubectl top pod` を打ってみます。

```
NAME                         CPU(cores)   MEMORY(bytes)
hoge1                        2m           755Mi
huga1                        0m           0Mi
hoge2                        1m           229Mi
huga2                        1m           28Mi
hoge3                        2m           1Mi
```

うまくいきました！

## 最後に

最後に、弊社の宣伝をさせていただければ、と思います！
現在弊社では、HRモンスターと呼ばれる
採用の新しいスタイルを提供するサービスをローンチいたしました。

ローンチ後のさらなる機能追加、改善などのPDCAサイクルを回すべく、
エンジニアを募集しております。
https://www.wantedly.com/projects/406086

Kubernetes、Vue.js（Javascript）、Django（Python）といったモダンな技術を使って、
開発しておりますので、もしご興味がある方はぜひ、ご応募お待ちしております。
YAMAHAルーター RTX1210 で、接続端末をMACアドレス制限

# 追記: 2020-02-05

以下のコマンドを忘れていたので追加しました。

```
dhcp server rfc2131 compliant use-clientid
```

`use-clientid` がミソらしいです。

---------

# やりたかったこと

インターネットおよびプライベートネットワーク参加を、特定の端末だけに絞りたい！
（例： 他部署の人がノートPC持ち込んでLANに繋いでも、通信できないようにしたい）

# 環境

YAMAHAルーター RTX1210
ファームウェア： Rev.14.01.33
`DHCPサーバー機能を有効にしていること。`

（同シリーズの機種なら、同じ方法で通用するかも？）

# 方法

以下の管理コマンドを、RTX1210で実行する。

```
dhcp server rfc2131 compliant use-clientid
dhcp scope lease type 1 bind-only

dhcp scope bind 1 192.168.100.10 01 aa bb cc dd ee ff
dhcp scope bind 1 192.168.100.11 01 a1 b1 c1 d1 e1 f1
・
・
・
save
```

-------

# ハマったこと

## `ethernet filter` コマンドは不要

```
ethernet filter 1 pass-nolog dhcp-bind 1
ethernet lan1 filter in 1
```

は不要でした。（WEBマニュアルとかあちこちのWEB文献には書いてあったのだが…）
むしろ、実行すると完全不通になり、ルーターを初期化するハメに…
豆粒みたいな物理ボタンを3つも押しながら電源をOFF/ONする指が痛い:sob:

## `dhcp scope bind` コマンドの、MACアドレスの書き方

```
dhcp scope bind <dhcpスコープ番号> <振りたいプライベートIPアドレス> 01 <MACアドレス>
```

### ポイント１： `01`

これが必須…！
出所は何かと言うと、

```
show status dhcp
```

を実行すると端末情報一覧が表示されます。

```
DHCPスコープ番号: 1
   ネットワークアドレス: 192.168.100.0
               割り当て中アドレス: 192.168.100.10
          (タイプ) クライアントID: (01) aa bb cc dd ee ff
                         ホスト名: yamada-MBP
                     リース残時間: 89日 22時間 25分 8秒
               割り当て中アドレス: 192.168.100.11
          (タイプ) クライアントID: (01) a1 b1 c1 d1 e1 f1
                         ホスト名: yoshida-Windows
                     リース残時間: 89日 23時間 13分 48秒
・
・
・
```

もちろん、その中に MACアドレス もあります。

だがしかし！
冒頭に、謎の固定値 `(01)` が…

これを `dhcp scope bind` にも漏れなく入れないと、ちゃんと動きません。
しかも、もう一味必要で、カッコを省いて `01` として、です…！

これは Client-Identifier という値だそうです。
http://www.rtpro.yamaha.co.jp/RT/manual/rt-common/dhcp/dhcp_scope_bind.html

> コマンドの第 1 書式を使う場合は、あらかじめ dhcp server rfc2131 compliant on あるいは use-clientid 機能を使用するよう設定されていなければならない。また dhcp server rfc2131 compliant off あるいは use-clientid 機能が使用されないよう設定された時点で、コマンドの第 2 書式によるもの以外の予約は消去される。
コマンドの第 1 書式でのクライアント識別子は、クライアントがオプションで送ってくる値を設定する。type パラメータを省略した場合には、type フィールドの値も含めて入力する。type パラメータにキーワードを指定する場合には type フィールド値は一意に決定されるので Client-Identifier フィールドの値のみを入力する。

今回は `use-clientid` 機能を使用なので、コマンド書式は第1書式、typeパラメータのキーワード`ethernet`を省略して`01`（0x01）のみを記入、ということでこうなるわけでした。

これはハマるｗ

### ポイント２： `<MACアドレス>`

これもWEB文献には諸説あってハマりました。

* MACアドレスの区切り文字は `:` だとか、そうでないとか
* 前に、おまじない `ethernet` を付けるとか、付けないとか

これは、文献によって `use-clientid` 機能を使用・不使用 がまちまちだったりもあって混乱しました。

結論は、ポイント１と同様で

```
show status dhcp
```

を実行して出力されたMACアドレスと全く同じ書き方、が正解！

クライアントのOSによっては`(01) XX XX XX XX XX XX`（第1書式）ではなく`XX:XX:XX:XX:XX:XX`（第2書式）を通知してくるようです。その場合は、そのクライアントだけ第2書式（`01`を書かず、コロンで連結）で書けばと良いようです。
nuxt-buefyでMaterialDesignIconsのCDN読み込みをやめる

Nuxt.jsのプロジェクト作成時にBuefyを選択した場合、[nuxt-buefy](https://github.com/buefy/nuxt-buefy)を使うようになります。
何も設定せずにMaterialDesignIcons(mdi)が使えるんですが、デフォルトのままではcssをCDNで読み込んでしまいます。
[GithubのIssue](https://github.com/buefy/nuxt-buefy/issues/48)で回避方法が紹介されているんですが、紹介した方はこのやり方に納得していないようです。
それにこのやり方だと、mdiのcssをコミットに含めてしまうため、あまり得策とは言えません。

という事で、コミットにcssを含めずCDNを使わない方法を~~考えてみました。~~紹介します。
IssueのやりとりでjtommyさんがmaterialDesignIconsをfalseにしろって言ってますね(^^;;

まずmdiのパッケージを追加します。

```sh
yarn add @mdi/font
```

nuxt.config.js(ts)のcssにmdiのパスを追加しnuxt-buefyのCDN読み込みを止めます。

```nuxt.config.js
css: [
	'@mdi/font/css/materialdesignicons.min.css'
],
modules: [
	[
		'nuxt-buefy',
		{
			materialDesignIcons: false
		}
	]
],
```

buefyのcssをカスタマイズしてる場合、そのcssより先にmdiのcssを読み込む必要があります。

```nuxt.config.js
css: [
	'@mdi/font/css/materialdesignicons.min.css',
	'~/assets/style.scss'
],
modules: [
	[
		'nuxt-buefy',
		{
			css: false,
			materialDesignIcons: false
		}
	]
],
```

これだけでパフォーマンスが若干向上するはずです。

それでは良い[nuxt-buefy](https://github.com/buefy/nuxt-buefy)ライフを🤘
CentOS7でGitLab CE構築

# CentOS7でGitLabサーバー構築

[前回](https://qiita.com/rui-watanabe/items/32340c3fd441b2e83be4)SVNリポジトリを、GitLabのリポジトリに移行する手順について紹介しました。

しかし移行先はGitLab上のサーバーだったため、今回はGitLabの特徴でもある**セルフホスト（自前のサーバー）で、SVNリポジトリをGitLabのリポジトリに移行する手順**について紹介したいと思います。

# 前提条件
・すでにSVNのローカルレポジトリ作成済み
・yum update済みのCentOS7サーバー 

# GitLab CE

**GitLab CE（GitLab Community Edition）はセルフホスト用にインストールできるOSS**です。

他にも、GitLab EE（GitLab Enterprise Edition） という、有料版があります。

ただ、GitLab EEはサポートや大規模開発などにならないと必要になるオプションがないので、今回はGitLab CEを使用していきたいと思います。


# GitLab CEの構築

ここから、GitLab CEを構築する手順について紹介していきたいと思います。

## GitLab CE構築に必要なパッケージ確認

まず、GitLab CE構築に必要なsshとpostfix（メール転送ソフトウェア）が起動しているか確認します。（CentOS7ではデフォルトで起動していました）

```
# systemctl status sshd
# systemctl status postfix
```

## GitLab CEインストール

 GitLab CEのリポジトリーを追加し、インストールします。

```
# cd /usr/local/src
# curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

# EXTERNAL_URL="IPアドレス" yum install -y gitlab-ce
```
EXTERNAL_URLにCentOS７のIPアドレスを記載することで、そのIPアドレスでGitLabにアクセスできます。

その後、設定を反映するために以下のコマンド記載し、指定したIPアドレスにGitLabのパスワード設定ページが出ればGitLab CEの構築完了です。

```
# gitlab-ctl reconfigure
```

パスワードは再設定が必要なので、rootでログインするパスワードをサイド入力してSign inしてください。

# SVNリポジトリをGitLabリポジトリに移行

すでにSVNリポジトリをGitLabリポジトリに移行は、前回の記事で紹介しています。

しかし今回はMacではなく、**CentOS7のローカルサーバーから構築**して、少しエラーなどを吐いたので、その解決方法に関して記載していきます。

## CentOS7にGitインストール

CentOS7にインストールされているデフォルトのGitでは、git svnコマンドなどが使えないので、最新版のGitをインストールします。

```
すでにあるGitをremove
# yum remove git 

Gitのライブラリインストール
# yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker autoconf

wgetコマンド使用のためのパッケージインストール
# yum install -y wget

最新版のGitインストール
# wget https://www.kernel.org/pub/software/scm/git/git-2.9.5.tar.gz
# tar vfx git-2.9.5.tar.gz
# cd git-2.9.5
# make configure
# ./configure --prefix=/usr
# make all
# make install

バージョン確認
# git --version
git version 2.9.5
```

## 前回同様ローカルのSVNリポジトリからGitLabリポジトリにプッシュ

GitLabで空のリポジトリを作成後、ローカルのCentOS７サーバーでSVNリポジトリをクローンします。

しかし前回同様に進めていったら、git svn initでCan't locate SVN/Core.pm in @INCというエラーがでました。

また、git svn fetchでは、can't locate digest/md5.pm in @INCというエラーが。

これを解消するために、前もってyumでパッケージをインストールしておきます。

```
# yum install -y subversion perl
# yum install -y perl-Digest-MD5
```

その後、前回同様、SVNリポジトリ作成。

```
# mkdir svn_repo
# cd svn_repo
# git svn init --prefix=svn/ http://SVNリポジトリ名
# git svn fetch
```

SVNリポジトリを作成したらこれも前回同様、空のGitLabリポジトリにプッシュする。

```
$ git remote add origin GitLabクローンURL
$ git push -u origin master
```

GitLabにアクセスしリポジトリとコミット履歴が引き継がれていることを確認できたら、GitLab CEの構築、CentOS7でのSVNリポジトリをGitLabリポジトリに移行は完了です。


# 参考文献
https://qiita.com/homines22/items/7572cdba2d60a00a3ffc
https://qiita.com/You_name_is_YU/items/34a09ab130e89fbfc459
https://github.com/termux/termux-packages/issues/2516
https://qiita.com/msakamoto_sf/items/78c322cb8656615ce134
Vue CLI 4.0でCache Bustingにクエリストリングを用いる

vue.config.jsを特に編集していなければbuild時にハッシュ付きのファイルが生成されると思いますが、様々な理由によりハッシュ付きのファイルが生成されるのは不味い時、人はクエリストリングでキャッシュバスティングを行いたくなるものでしょう。

```js:vue.config.js
module.exports = {
  filenameHashing: false,
  chainWebpack: config => {
    config.output.filename('js/[name].js?[contenthash:8]');
    config.output.chunkFilename('js/[name].js?[contenthash:8]');
    config.plugin('extract-css').tap(args => {
      (args[0].filename = 'css/[name].css?[contenthash:8]'),
      (args[0].chunkFilename = 'css/[name].css?[contenthash:8]');
      args[0].allChunks = true;
      return args;
    });
  }
};
```

`filenameHashing: false` でハッシュ付きファイルの生成を無効にします。
chainWebpackでwebpackの設定を上書きします。

この設定でいざbuildすると、Vue CLIの場合head内にpreloadが追加されますが
同時に `.map` ファイルもpreloadに追加されてしまいます。

```js:vue.config.js
config.plugin('preload').tap(args => {
  args[0].fileBlacklist = [/\.map\?(.+?)$/, /hot-update\.js$/]
  return args
});
```

同様に上記の設定を追加すれば良いと思っていたのですがエラーで解決出来なかったため `productionSourceMap: false` を追加しました。
build時にsourcemapファイルは特に必要ないしpreloadから`.map`の文字列は消え去ったのでこれで良しとします。
Office 365のformsでアンケート作成方法のメモ

会社にMicrosoftが入っていたので、forms使ってアンケートしてみた話
アンケート分析については別で記事を書く予定
備忘録

# formsとは

Office 365にあるアンケート・クイズにつかえるアプリ
何がいいかというとExcelでエクスポートできるので分析にも使えるし、人に渡すときにフィルタとかピボットテーブルを書いて渡しやすい。

# 新しいクイズの作成

![form.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/03647826-09fa-184c-8b19-bd34938caf8f.png)

アンケート内容は直接打ち込んで編集できる。
項目追加も視覚的にわかりやすい

![for2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/9ac5b987-adad-54ae-0d14-93b0ca400fe4.png)

選択肢によって最終頁まで飛ばすときは分岐を選ぶ


![for3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/6e1d2bdb-6068-be3b-0e10-07470fa6f901.png)

フォームの末尾にすると最後に飛ばされる。
他にも項目があれば、その項目まで飛ばすようにできる。


![for5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/090ac8ad-a204-b234-3056-6f6cf6a4e900.png)

結果はエクセルに出力できる。
回答項目がそのまま文字として入力されるので、結果を統計ソフトで分析に使いたい時には、選択肢の頭文字に数字を入れておくと、頭文字だけを切り出して因子か文字列に変換して主成分分析に使えたりするので便利

# 結果の分析方法はまた別の記事で。
今更ながらJavaScriptの復習をしてみる

# はじめに
某プログラミングスクールでJavaScriptを学びましたが、あまり理解できないまま卒業してしまいました。
今更ですが、もう一度勉強し直した事をまとめていきます。

# 内容
[1. 基本情報](https://qiita.com/myktmht/items/703d4a379e6801f6e2e9) (JavaScriptとは？などの基本的な情報について)
[2. 基本文法](https://qiita.com/myktmht/items/53a45b5e8015152ebcca) (どこにどのように描けばいいのか、ブラウザで動作をみながら勉強していく)
[3. 画面上の表示を変える](https://qiita.com/myktmht/items/04da17d84e67cf740ec6) (簡単な機能を実装してページを変化させてみる)
[4. ライブラリを軽く使ってみる](https://qiita.com/myktmht/items/a6af3325b0785310d074) (jQuery, React, Vue.jsについて、それぞれの書き方の違いを見てみる。)
[5. jQueryを使ってブラウザ情報を取得して操作する。](https://qiita.com/myktmht/items/065f120b4ac1e7553aab) (jQueryを使用して、基本的なブラウザ情報とイベントを実装する。)

~随時追加中~

# 最後に
プログラミング初心者がまとめている内容となっています。
間違っていること、不明点などありましたらよろしくお願いします。
（優しく教えてくださると幸いです。）
初心者からはじめるプロセス改善の基本

#1.概要
ソフトウェア開発を改善する上で、プロセスの改善は最も基本となる活動だと思っております。今回はそのプロセス改善の基本となる考え方や、進め方を記載したいと思います。

#2.なぜプロセスを改善するのか
改善活動は大きく2つの活動に分かれると思っております。

- プロセス改善（手順書を作る、運用フローを作る、ドキュメントフォーマットを作るなど）
- プロダクト改善（新しいフレームワークを導入する、技術者に勉強会に参加してもらうなど）

このうち基本となるのがプロセスです。なぜプロセス改善が大事かというと、改善することで以下のような効果があるからです。

- **一度作れば何度でも使える**
- 誰か一人ではなく複数人に効果があるので、**費用対効果が高い**
- フォーマットがあればすぐに導入可能（即日実施可能）

そのため、コンサルタントが改善を行う場合、目に見えて効果が表れやすい「プロセス」から改善していくことが多いです。

ただ、私の考えでは**「プロセス改善は赤点を取らない方法」**だと考えております。
そのため、どんなに改善しても**最大で100点満点中40点**ぐらいしか取れず、もっと改善するには必ずプロダクト改善が必要となります。
⇒（プロセスは一定の手順を実施するので、**一定の品質**しか担保できない。。。）

#3.プロセス改善の進め方（基本編）
プロセス改善は大きく2つの進め方があります。

- ボトムアップアプローチ（課題から改善していく）
- トップダウンアプローチ（あるべき姿から改善していく）

この中で最も取り入れやすいのが**ボトムアップアプローチ**です。ボトムアップアプローチの進め方は単純で、以下のように進めていきます。

1. 各現場の課題をヒアリングし、課題一覧にまとめる
2. 課題から改善すべきプロセスを考え、改善を行う
3. うまくいったかどうかをヒアリングしPDCAを回す

目の前の課題がどんどん解決していくので、目に見えて成果が出てきます。そのため、**現場の協力を得やすく**なり、さらなる改善へと進めることができます。

また、トップダウンアプローチの場合は以下のように進めます。

1. あるべき姿のモデルを調査する（CMMi、PMBOK、TPI-Next@など）
2. モデルが決定したのち、そのモデルと現場とのギャップを分析する（モデルと現場の運用フローを比較する）
3. ギャップがある部分について改善活動を行う
4. うまくいったかどうかをヒアリングしPDCAを回す

こちらはベストプラクティス集から改善を行うので、うまくいけばボトムアップより大きな成果を上げられる場合があります。ただ、あるべき姿なので**理想論となりやすく**、現場が受け入れてくれない場合もあります。


#4.プロセス改善のあるある失敗事例
以下プロセス改善中に起きやすい失敗談をまとめます。

- 大きく改善しすぎて現場から締め出される

改善を無理に進めるあまり、一気にすべてを変えてしまおうとすることがあります。この場合、大抵その変化に耐えきれず、現場から総スカンを食らいます…
改善は**小さく初めて協力者を作ること**を心がけてください。

- 知らない人から中止命令が出る

プロセス改善を進めると話したこともない人から、いきなり中止命令が出て終わることがあります。これは、プロセス改善が複数人に影響がある＝ネゴを事前に取っておかなければならない人が多い、という意味でもあります。

そのため、事前に影響力のある人をリストアップしておき、改善する内容については事前に交渉しておく必要があります。

- 作ったものが使われない

いいフロー、いいドキュメントフォーマットを作っても、1回だけ使いすぐに使われなくなることもあります…。これは、作ったものが間違っていたか、**推進者がいない**ことによって使われなくなったかのどちらかであることが多いです。

特に重要なのは推進者の方で、必ず改善を始める前に誰が今後運用していって、誰が修正していくのか、は決めておくべきだと思います。


#5.まとめ
ボトムアップ、トップダウンが一般的ですが、双方を掛け合わせたような方法も行われています。つまり、**課題一覧をまとめあるべき姿と比較することで重要なものから改善していく**、ということです。

■参考文献
[あなたに捧げる～
TPI Nextを活用したチームメンバーの問題意識から始めるテストプロセス改善
【導入時：改善計画立案編】リターンズ」]
http://www.jasst.jp/symposium/jasst19tokyo/pdf/D2.pdf
Ubuntu で Processing 

# 環境

- Ubuntu 18.04 (2020/1/30 に検証) & 20.04 (2021/01/11 に検証) 
- Processing 3.5.4

# インストール

apt には無く、公式サイトからダウンロード
https://processing.org

からDownloadを辿り、3.5.4 (17 January 2020)を選ぶ。
 Linux 64 版を processing-3.5.4-linux64.tgz としてダウンロードした。

~/Downloads に保存したので

$ cd ~/Downloads
$ tar xzvf processing-3.5.4-linux64.tgz 
$ cd processing-3.5.4/
$ ./processing

で起動した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a84e9df2-02c3-322c-752b-cb6394693bfe.png)

# コード中の日本語の文字化け

以前作ったプログラムをロードするとエディタ画面中で文字化けした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a5a34680-c823-25bc-ca7a-45a63610e08f.png)

本来は、「ファイル」-「設定」でフォントを指定したらいいはずなのだけれど・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/7e828133-ec2f-2752-9655-b00c111a71bb.png)

何故かグレーアウトして選択できない。



「Lubuntu 18.10でprocessingのフォント設定」
https://qiita.com/ToruKahata/items/05e18abcb02ceebe3fe1

を参考に、以下のようにした。


リンク先では IPAゴシックフォントを使ってますが、今回は自分の環境にあわせて以下のようにしました。

まず Ubuntu 日本語環境に元々入っている NotoSansフォントをコピー。

```

$ cp /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc ~/Downloads/processing-3.5.4/lib/fonts/

```

このフォントファイルのフォントフェイスは何かな？

```

$ fc-list | grep -i noto | grep -i mono
/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: Noto Sans Mono CJK TC:style=Bold
/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: Noto Sans Mono CJK SC:style=Bold
/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: Noto Sans Mono CJK KR:style=Bold
/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: Noto Sans Mono CJK HK:style=Bold
/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: Noto Sans Mono CJK JP:style=Bold
/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf: Noto Mono:style=Regular
/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans Mono CJK SC:style=Regular
/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans Mono CJK TC:style=Regular
/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans Mono CJK HK:style=Regular
/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans Mono CJK KR:style=Regular
/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans Mono CJK JP:style=Regular
```
とりあえず、ここで出てきた "Noto Sans Mono CJK JP:style=Regular" を使って、

```

$ cd ~/.processing/
$ vim preferences.txt
```

として、

```

editor.font.family=Noto Sans Mono CJK JP:style=Regular
editor.font.size=12
```
としてみた。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ed3723f2-7cd1-e53b-8644-fce416a0994c.png)

うまく表示できたが・・・再度preferences.txtを開くと

```

editor.font.family=Monospaced
editor.font.size=12
```
となっていた。うーむ。しかしながら、一度設定すると
editor.font.family=Monospaced
となっていても日本語はうまくひょうじされたままだったのでこれで使用するようにしました。
Ruby基礎(条件分岐)

#条件分岐について
前回までは書いたコードをそのまま表示させるだけでした。
しかし、実際は条件によって処理を変更しなければいけないケースが多々出てきます。
そんな時に役立つのが**条件分岐**です！
では、さっそく実際に書いて動かしてみましょう！

##条件分岐規則
条件分岐をする際は今まででてこなかった、**インデント**と呼ばれるものも意識して書いていきましょう。
###インデント
文章の行頭に空白を挿入して先頭の文字を右に押しやること。
文書のスタートを揃えることが、プログラミングでいう所のインデントになります。


if文の規則は下記に書いてある通りです。

```
if 条件
  結果
else(ifで定義した条件以外だった場合)
  結果
end(if文はこれで終了と定義)<br>
※endは忘れがちなので注意
```

実際に**新規ファイルを作成(conditions.rb)**して**条件分岐**を使用したコードをみてみましょう！

```ruby:conditions.rb
name = "hoge"

if name == "hoge"
  puts "あなたの名前は"+name+"です。"
else
  puts "あなたはhogeではありませんね。"
end
```
<font color="blue">※今回でいうと赤線を引いているところが**インデント**になります。ここを役割ごとに揃えないとエラーがでたり、後々見直した時に見辛くなってしまうので、常にここは意識して揃えるようにしましょう！
![インデント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429158/707f9296-5cf2-6f53-ed34-e143d72d2e2c.png)

今回コード内容を解説すると。
**1.nameという変数に、文字列のhogeを定義します。
2.もしnameという変数の中身が文字列のhogeだったら、あなたの名前はname(hoge)です。と表示します。
3.それ以外だったら、あなたはhogeではありませんね。と表示します。**

といった処理が走っています。

##elsif
if文のルールでこの**ifを2回使ってはいけない**というのがあります。

```
if 条件
  結果
if 条件
  結果
end
```
このようにif文にまたifが入っていますね。
これでは構文エラーと怒られてしまいます。

なので、細くした条件を2個以上書きたい場合は以下のように**elsif**を使います。

```
if 条件
  結果
elsif 条件
  結果
end
```

これなら1つのif文で、複数の条件式を書くことが可能です！

では、実際に下記のelsifを使ったコードを書いて実行してみましょう！

```ruby:conditions.rb
LastName = "Hoge"
FirstName = "Taro"

if LastName == "Taro"
  puts "苗字はTaroです"
elsif FirstName == "Taro"
  puts "名前はTaroです"
else
  puts "そんな人は存在しません"
end
```

かけましたでしょうか？？
急に書くコード量が多くなって、タイプミス等ありがちですので、慎重に書いていきましょう！

実行結果は以下の通りだったら成功です！

```ruby:ターミナル
名前はTaroです
```

今回のif文では2つめの条件式があっていたので、**名前はTaroです。**が表示されました！

#終わり
今回は条件分岐について学びました。
だんだん使う機能が増えてきて、それに伴いコード量も増えて混乱してきてるかと思います。
しかし、今度こういうの反復で自然と身についていくものなので、焦らず、深く理解せずに次へ次へと不安だと思いますが、進めていきましょう！

では、本記事はこちらで以上になります。

お疲れ様でした！
Ruby基礎(変数)

#変数とは
**変数**とは文字は数値に**命名**する、といった意味合いになります。

全然これだけじゃ何いってるかわかりませんね笑

では毎度のごとく実際にコードを書いていきましょう！

##実際に書いて動かしてみよう
まず、**新しいファイルを作成してください。**
ファイル名は**variable.rb**とします。

保存したら以下のコードを書いてください。

```ruby:variable.rb
name = "hoge"
puts name
```

書けましたか？
では、このファイルを実行してみましょう。

```ruby:ターミナル
hoge
````
このように**hoge**という文字が表示されました！

また、変数は文字列の中に混ぜ使うことができます！

```ruby:variable.rb
name = "hoge"
puts ("私の名前は"+name+"です。")
```
```ruby:ターミナル
私の名前はhogeです。
````
このように文字列に対して、**+**で連結することで**変数**と**文字列**を混合させながらの使用が可能です！


##変数の役割
このように、**変数(今回でいうname)**に値を代入して、代入した変数を**putsで表示する**コマンドでできることがわかりました。

では、なんでわざわざ変数に代入するのか？
今まで通り直接putsと表示したいものを書けばいいのでは？

と思う方もいらっしゃるかもしれません。

確かに現状はそのままの方がコードみやすく、シンプルなわかりやすい書き方でした。

しかし、今後実際にアプリ作っていく段階では
**変数はめちゃめちゃ使います!!**

なので、今の段階から知って、慣れていただこうと思っています。

##練習
そこで、今まで習ったことの復習と応用を兼ねて問題です。
**・sample2.rbファイルを作成してください。**
**・iという変数に答えが10になる計算を代入してください。(結果10になる計算であれば中身なんでも大丈夫です。)**
**・iという変数をputsを使って表示させてください。**

<font color="red"><details><summary>**正解はこちら！！**</summary><div></font>

```ruby:sample2.rb
i = 5+5
puts i
```

```ruby:ターミナル
ruby sample2.rb
```

</div></details>

#終わり
今回は**変数**について学びました。
変数は色々な情報に対して、なるべく短く命名して見返したときに、
この変数にはこんな情報が入っているというのわかりやすくなるよう、
今後自分で変数を作成するときは意識して命名してみましょう！

本記事こちらで以上になります！

お疲れ様でした！
Ruby基礎(文字列・計算)

#文字列について
前回は**hello!**という**文字**を表示しました。
プログラミングでは**数値**と**文字列**を区別してあげないといけません。

今のままではピンとこないと思うので、実際に書いて動かして体験していきましょう

##文字列規則
これは計算ではなく文字ですよ。
と定義するには

<font color="red">**``**</font> or  <font color="red">**""**</font>

<font color="red">**シングルクォーテーション**</font>,<font color="red">**ダブルクォーテーション**</font>

でかこうする必要があります

そこで前回作成したコードをみてみましょう

```ruby:ターミナル
puts "hello!"
```

hello!という表示したい**文字列**に対して、規則通り**ダブルクォーテーション**で囲まれていますね！

次にシングルクォーテーションではどうでしょうか？？
試しに

**シングルクォーテーションで「おはようございます！」と表示させるコードを書いて実行して表示までしてみましょう！**

<font color="red"><details><summary>**正解はこちら！！**</summary><div></font>

```ruby:hello.rb
puts 'こんにちは！'
```

```ruby:ターミナル
ruby hello.rb
```

```ruby:ターミナル
こんにちは！
```
</div></details>

いかがでしょうか？？
書き方は若干違えど表示自体は問題なくできたと思います！
Rubyで文字列を表示するときは**'',""**をつける習慣をつけましょう！

#計算
次は計算を内容を表示コードを書いていきます。
**文字列**と**計算**では処理が変わってきますので、その辺の違いも確認しながらやっていきましょう！

##文字列との書き方の違い
文字列同様に表示することに代わりはないので、**puts**は使います
では、何が変わってくるかと言うと、

**'',""を使わない**

というところになってきます

##実際に書いて動かしてみよう
言葉で書いてあるだけはわかりずらいので、実際に書いていきましょう！

**計算と新しいことをやるので、新しいファイルを作成してください！**
ファイル名は**calculation.rb**とします。

<details><summary>**やり方忘れかたはこちら！！**</summary><div>

1. command + n
2. command + s
3. 保存先(PCトップ)指定
4. ファイル名をsample2.rbと書いて保存！
</div></details>

保存したら以下のコード書いてください

```ruby:calculation.rb
puts 1+1
```

コードを記載して、保存できましたら実行してみましょう
すると

```ruby:ターミナル
2
```
ちゃんと計算してくれましたね！
このように文字列と違って何も囲わないことで**数値**として認識し、計算してくれます

###計算式一覧
+→足し算
-→引き算
*→掛け算
/→割り算
%→あまり

##計算に文字列規則を適用せると
前章では計算には**'',""**は使わないと解説しました。
では、計算式に適用したらどうなるかやってみましょう。

**新しファイルを作成してください**
ファイル名は**string_test.rb**とします

```ruby:string_test.rb
puts "1+1"
puts '1+1'
puts  1+1
```
比較しやすいように文字列規則、計算規則全部書いてみました。
これを実行してみると

```ruby:ターミナル
1+1
1+1
2
```
このように文字列規則を適用させると、**計算式そのものを表示**してくれます

#終わり
今回は**文字列**と**数値**について学びました
最初はどっちに**'',""**をつけていいかわからなくなると思いますが
今後いろんなコードを書くことで勝手に身についていきますので、次の記事で新しいことをどんどん学んでいきましょう！

では、本記事はこちらで以上になります

お疲れ様でした！
Visual Studio 2019 の C++/CLI で出力するバイナリのパスを変更する

## 背景

Visual C++ プロジェクトではデフォルトでソリューションと同じ階層にプラットフォームのフォルダ（ Win32 とか x64 とか）や構成フォルダ（ Debug とか Release とか）が作られるが、色々構成を切り替えているとフォルダがいっぱいできて鬱陶しかったので bin フォルダを置いてその中に作るようにしたかったのだが、意外とハマったのでメモ。

## ファイルの出力先を変更する

今回はソリューションの階層に bin フォルダを置いてその下に従来のファイルを置きたかったので、ファイルの出力先を変えてやればできるだろうと思い、プロジェクトのプロパティから [構成プロパティ]-[リンカー]-[全般]-[出力ファイル] を下記のように変更した。

 `$(OutDir)$(TargetName)$(TargetExt)` ⇒ `$(SolutionDir)bin\$(IntDir)$(TargetName)$(TargetExt)` 

![HogeAppProp002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58491/33b9e720-967a-6d16-963f-95bfa76c3a0e.png)

ここ以外にも、下記も同様に変更した。

1.  [リンカー]-[デバッグ]-[プログラムデータベースファイルの生成]
2.  [リンカー]-[最適化]-[ガイド付きデータベースのプロファイル]
3.  [XML ドキュメント ジェネレーター]-[全般]-[出力]

## MSB8012 の警告が出る

これでビルドすると下記の警告が発生した。

>warning MSB8012: TargetPath(C:\以下略) does not match the Linker's OutputFile property value (C:\以下略). This may cause your project to build incorrectly. To correct this, please make sure that \$(OutDir), \$(TargetName) and \$(TargetExt) property values match the value specified in %(Link.OutputFile).

## 出力ディレクトリを変更する

ここでしばらくハマったが、後述の参考サイトを見つけて、 [構成プロパティ]-[全般]-[出力ディレクトリ] を同様に変更することで解決した。

![HogeAppProp003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58491/56629a87-0b1d-bda2-a07e-5f7a6d3efde0.png)

参考
[erio_nk://memo - ライブラリの出力名を変える。](https://erio-nk.hatenadiary.org/entry/20110519/1305819066)
Raspberry Pi 4Bは公式にオーバークロックできるらしい

#はじめに
クロックアップは処理速度向上に直接つながるので、リアルタイムエンコーディングしてストリーミングとか実時間より速く処理しないといけないようなシーンでは有効かとおもわれます。
Raspberry Pi 4Bに限らずできるみたいで、もちろんアンダークロックもできます。

##あなたのラズパイが傷物にならないために知っておくこと
raspi-configで設定できる範囲であれば保証範囲内です。
/boot/config.txtで直接パラメータをいじる場合は、保証対象外になる場合がある(SoCにフラグが立てられる)ので注意
force_turbo=1にして電圧をすこしでも上げるとダメみたい。

あと、公式サイトに**オーバークロックはあなたのラズパイの寿命を縮めるかもしれないので気をつけて**(Be aware that overclocking may reduce the lifetime of your Raspberry Pi.)って書いてありますので、念のため。

#オーバークロックのやりかた
まだ自分では試してないので、取り急ぎ公式のリンクを紹介します。
##その１：対話形式　→　だめでした
raspi-configで設定できるのは、**Pi 1 or Pi 2**だけだそうです。
![raspberry pi 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418454/e3ac5621-0f92-3b33-d756-4d2164a07ab1.png)
https://www.raspberrypi.org/documentation/configuration/raspi-config.md#overclock

##その２：設定ファイルにパラメータを書く
/boot/config.txtにパラメータを直接書きます
https://www.raspberrypi.org/documentation/configuration/config-txt/overclocking.md

#よくばりすぎて起動しなくなった場合
よくばりすぎてクロック上げすぎたりすると起動しなくなりますが、shiftキーを押しながら起動すればその設定は無視され、通常状態で起動します。
あるいは、パソコンにmicroSD刺して、config.txtをエディタで直接編集するのでも良いです。
LambdaのNode.js 12.xでimageMagickを使用する

# 初めに
Webアプリケーションから画像をアップロードする際にS3にファイルをputし、Lambdaでサムネイルを生成して公開用のバケットに保存する処理を構築していました。(前任者が・・・)
新たに同じようなシステムを構築するのに参考にしようとLambdaの関数のコンソールにアクセスすると以下のメッセージが表示されていました。
![FireShot Capture 494 - createRecipeThumbnail - Lambda_ - https___ap-northeast-1.console.aws.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412592/e29157a3-ee88-059c-e56c-df23b0e98485.png)
Node.js 8.10を使っているので変更しないといけないよう。(把握しとけよ)
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtime-support-policy.html

# 対応内容
まずは新しい関数を作り、ランタイムをNode.js 12.xにしてindex.jsに保存。
index.jsの内容はAWSのサンプルを参考にしています。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-example-deployment-pkg.html

### いざ実行
特に内容を変えずに実行すると以下のエラーが発生しました。
<pre>
Error: write EPIPE   2020-01-29T11:33:50.941Z a84631dc-38d7-4b16-958c-8c88a85535c0  
INFO  In transform::: Error: write EPIPE
    at afterWriteDispatched (internal/stream_base_commons.js:150:25)
    at writeGeneric (internal/stream_base_commons.js:141:3)
    at Socket._writeGeneric (net.js:770:11)
    at Socket._write (net.js:782:8)
    at doWrite (_stream_writable.js:431:12)
    at writeOrBuffer (_stream_writable.js:415:5)
    at Socket.Writable.write (_stream_writable.js:305:11)
    at gm._spawn (/var/task/node_modules/gm/lib/command.js:253:18)
    at gm._exec (/var/task/node_modules/gm/lib/command.js:190:17)
    at gm.proto.<computed> [as size] (/var/task/node_modules/gm/lib/getters.js:68:12) {
  errno: 'EPIPE',
  code: 'EPIPE',
  syscall: 'write'
}
</pre>
AWSのフォーラムに同じような投稿があり、内容をみると、どうやらNode 12.xではimage Magickがそのままでは使えないみたいです。
https://forums.aws.amazon.com/thread.jspa?threadID=314320
`write EPIPE`でググってもヒットしなかったのですがat afterWriteDispatched～でググると全部英語の記事の中、上記のフォーラムがヒットしました。

なかなかややこしそうな内容が書いてあるのでNode.jsをあきらめてJAVAかPythonで書き直そうかと思ったのですがぺちぱーの僕には時間がかかりそうだったのでどうにかこのまま使える方法を探し続けた結果、以下の記事を発見。
[AWS lambda(Python 3.8)でimagemagickを使う](https://tsukada.sumito.jp/2019/12/29/imagemagick-on-aws-lambda-python-3-8/ "AWS lambda(Python 3.8)でimagemagickを使う")

# 無事解決
上記の記事のあるように`image-magick-lambda-layer`をdeployしてLambdaのLayersに設定することでコードを何も変えずに実行できた。

LambdaのLayersってのを初めて使ったんでこれきかっけにもうちょっと勉強しないと

# 参考
ここに行き着くまでに色々紆余曲折しました。
http://aws-mobile-development.hatenablog.com/entry/2016/11/25/152052

https://forums.aws.amazon.com/thread.jspa?threadID=314320
PHPでDBの外部キー制約を無視する方法

PDO経由でMySQLの外部キー制約を無視する方法です。
データ移行をするときに使いました。

```php
$pdo = new PDO('mysql:host=localhost;charset=utf8', 'root', '');
$pdo->query('SET foreign_key_checks = 0');
```