OmniAICreator/Qiita-1.07M huggingface dataset:
Lambdaでの開発を楽にする。zipアップロードのシェルスクリプト

# はじめに
`node.js`と`lambda`での開発で`aws-sdk`以外のライブラリ(例えば`firebase-admin`)を使おうとすると、
**ライブラリごと**lambdaにアップロードしないといけません。そしてたいてい、サイズが大きすぎてAWSのウェブサイト上でのコードの編集ができなくなり開発効率が悪くなってしまいます。

少しでも手間を軽減するためにzipに固めるのと関数のアップロードを自動でやってくれるシェルスクリプト(`upload.sh`)を書きました。`node.js`でなく`python`などでもフォルダ名などが変わるだけでやることは同じです。

<font color="red">
※**2020/5/5追記 [AWS Lambda レイヤー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html)を使うのがおそらく賢いやり方です。** layerが何らかの理由で使えない時(仮にそんなときが有るとして)だけこの記事は参考にしてください。
</font>

## 細かい設定
なお、ここでは`firebase-admin`の秘密鍵ファイル([参考](https://firebase.google.com/docs/admin/setup?hl=ja#initialize_the_sdk))をprivatekey.jsonとしておいてあります。またaws-cliをインストールしてあり、デフォルトのprofileでlambdaアップロードができることが前提です。別のプロファイルを使いたい場合は`--profile YYY`を追加しましょう。`npm install XXX`でほしい`node.js`モジュールが`node_modules`下にインストールされていることも前提です。

## upload.sh

```bash
zip -rq XXX.zip node_modules/ index.js privatekey.json
aws lambda update-function-code \
    --function-name FXXXX \
    --zip-file fileb:///home/xxx/Documents/xxx.zip \
    --publish
```

- XXX.zip: アップロードするzipファイルの名前です。
- `node_modules/`, `index.js`, `privatekey.json`が今回zipに固めたいフォルダ/ファイルです。お使いの環境に合わせて変えてください。
- FXXXX: アップロードする関数の名前です。
- fileb:///home/xxx/Documents/xxx.zip: 作成したzipファイルの**絶対パス**です。`fileb:///`から始まります。

## フォルダ構造
```
├── index.js
├── invoke.sh
├── node_modules/
├── package-lock.json
├── privatekey.json
└── upload.sh
```

## 使い方
```
bash upload.sh
``` 

# 実行もシェルスクリプトから行う

## invoke.sh
```bash
aws lambda invoke --function-name FXXX --payload '{"text":"hello"}' out --log-type Tail --query 'LogResult' --output text | base64 -d 
cat out
```

## 実行

```bash
bash invoke.sh
```
Eclipse ~.xlsxが読み込めずbuildエラー



```
The project was not built due to "Could not read file: C:\Users\projects\pay-setting\~$pay-setting.xlsx.". Fix the problem, then try refreshing this project and building it since it may be inconsistent
```
解決方法

Go to:

Project > Properties > Resource -> Resource Filters -> Add

Select:

Exclude all
Files
All children (recursive)
Name matches: ~*
android 足し算ができない！


3/9　kotlinを勉強し始めてドットインストールのkotlin入門を履修終了
　　（foreachからあんまり理解してない）

3/12　androidアプリ開発のテキストに沿ってアプリ開発の勉強開始。

テキストで学んだことを使って簡単なアプリ開発を使用と思い
摂取したカロリーをひたすら計算していくアプリを作ってみる。


しかし、うまくいかない・・・！
EditTextに数字を入力して追加を押すと、下のTextViewに追加した数字が表示され、
もう一度EditTextに数字を入力して追加を押すと、下のTextViewに表示された数字と足されて表示される仕組みが作りたかったが
なぜか追加ボタンを押すとイミュレーターがアプリが落ちる。。。
forを使うのか？とかも考えたけどその構文が分からず・・・

解決方法分かる方いたら教えてください。。。


```kotlin:qiita.rb

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val btClick = findViewById<Button>(R.id.btClick)
        val listener = CalListener()
        btClick.setOnClickListener(listener)
    }

    private inner class CalListener: View.OnClickListener{
        @SuppressLint("SetTextI18n")
        override fun onClick(view: View) {

                val input = findViewById<EditText>(R.id.etKcal)
                val output = findViewById<TextView>(R.id.tvSumKcal)
                var inputInt = input.text.toString().toInt()
                var outputInt = output.text.toString().toInt()

                var sum :Int
                sum  = inputInt+outputInt
                output.text = sum.toString() + "Kcal"
        }
    }
}

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528355/9b6b9e8c-567d-4a17-88df-dc1ad07b38f2.png)
【Microsoft Intune】Auto Pilot 案件でハマったポイント【パート1】

#・目的
皆さんこんにちは、アイネットテクノロジーの上口です。
今回は実際 Auto Pilot 案件でハマったポイントをご紹介します。
設定箇所やお伝えしたい内容が多いため、パートを分けたいと思います。
まずはパート１！！

#・要件
今回の要件はIntunewinでアプリ展開が必要。
インストールが一部動作しなかったアプリがあるため、GPOを使用する。
また、別要件で社内ドメイン環境に参加させる必要があったため、<font color="Red">***Hybrid Azure AD join***</font> 
が必要、且つ、デバイスの<font color="Red">***メーカーまたはモデル毎でMDMポリシーを分けたい。***

この、***メーカーまたはモデル毎でMDMポリシーを分けたい。***　←　※この一言が今回ハマりポイント

#・Hybrid Azure AD joined Auto Pilot

***Auto Pilot Deployment Process URL***
https://docs.microsoft.com/en-us/windows/deployment/windows-autopilot/deployment-process

Auto Pilotプロセスについては上記URLを参考にしていただければよいと思いますが、いくつかの案件に
参画させていただいて分かったことは、Auto Pilot と言ってもいろんなパターンがあるのでパターン毎に
設定を見直す必要があるということです。

#・事前準備

まず下記の通りAuto Pilotの事前準備をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/31c936bc-a989-ff2f-efa1-702b9c78d0f0.png)

***①HWIDインポート***
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/eef62066-c2d8-8b0f-fdcd-adf8456f5786.png" width=70%>
※今回はMEMのAdminCenterではなく、AzureADデバイスの確認を行いたい為、AzurePortalを使用します。

***・Azure ADデバイスと関連付けされました。***
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/3eb4ffc2-e044-c211-5401-22557717dd62.png"width=70%>


***②デバイス登録（Azure AD 自動登録）***
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/ce9b48aa-b132-b3e3-321e-9442cce93f0d.png"width=70%>
デバイスは無効状態、Azure AD joined　となります。

***③動的デバイスグループデバイス追加（動的メンバー自動登録）***
※ここでは、要件に基づき、<font color="Red">***メーカーまたはモデル毎でMDMポリシーを分けたい。***</font>ということで
動的デバイスグループのメンバーシップグループに下記の通り追加しました。

***■動的メンバーシップルール***
参考URL：https://docs.microsoft.com/ja-jp/azure/active-directory/users-groups-roles/groups-dynamic-membership

***(device.deviceManufacturer -eq "LENOVO")*** とルールを追加。

これで、動的デバイスにAzure AD デバイスからメンバー追加されればOK！待ちましょう！

#・動的デバイスにメンバー追加されない。
<font color="Red">***待てど暮らせど動的デバイスメンバーに追加されない。。。***</font> 
※サポートにも聞いてみました。
***動的デバイスのメンバーシップに追加されるのは最大24時間かかる可能性がある。***との回答。。。

んー、まじっすか？！！！

強制コマンドなどは存在しないそうです。

ってことで、仕方なく24時間待ってみました。。。。

が、、、、

登録されません。。。

***ということで、基本に立ち返り、Docsを再度確認。***
すると、、、、、　

**｀;:ﾞ｀;:ﾞ;｀(ﾟДﾟ*)ｶﾞﾊｯ**


<img src= "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/1b5e3f92-fb23-efcf-fe69-937aed72aa16.png"width=70%>

赤枠の部分、しか、使えないのでは？？

ってことで、。。。

#・解決方法
基本に立ち返り、Docsの通り、動的デバイスをdevicePhysicalIDsに変更。
**(device.devicePhysicalIDs -any _ -contains "[ZTDId]")**

※うまく登録されない場合、下記でも大丈夫です。
**device.devicePhysicalIDs -any (_ -contains "ZTDId"))**

<font color="Red">**設定完了！！**</front>

すると、5分以内で、メンバーシップに登録されました！！

***④Auto Pilot プロファイル割当（自動割当）***
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521349/c5ee929a-1ccb-55df-ccce-eeaef8b625a8.png"width=70%>


※関連付けられるIntuneデバイスについては、Auto Pilot 実施中 に Intune　にデバイス登録され、
関連付けられます。

#・結論
<font color="Red">***Hybrid AD Join Auto Pilot を行う場合、動的デバイスはdevicePhysicalIDsを設定してください。***</Front>

余談ですが、今回のようにHWIDを登録し、新規でHybrid Azure AD Join Auto Pilotを行うのではなく
すでにAzure ADデバイスとして登録されているデバイスをAuto Pilotする場合などにおいてはdeviceManufacturerでも問題なくAuto Pilotプロファイルに関連づけられます。

***要件については、
別途、動的デバイスグループを作成し、deviceManufacturerやModelなどで分け、ポリシーを適用してください。***

それでは、パート２をお楽しみに。

弊社HP
https://www.inet-technologys.com/
windowsでdlibインストールで詰まったときに(CUDA編)

# はじめに
CUDAを利用する場合のdlibのインストール方法。
CUDAを利用しない場合は[こちら](https://qiita.com/taungyeon/items/0afa3a5580c7521d54d1)

# 環境
windows 10
anaconda env

# 概要
CUDA利用時のdlibインストールについて調べる複雑な処理をするように指示するサイトがたくさん出てきます。

具体的には、cmake、dlibをpipでインストールするのではなく、個別ファイルとしてそれぞれダウンロードした後に各種パラメータファイルを調整し、cmakeコマンドで多くの引数を与え、buildするように指示される記事などなど・・・でしたがもっと簡単にできました。


# やったこと
1. 事前にCUDA、ducnnを使える状態にしておく。※
1. 上記の状態でdlibインストールをする　[インストールの仕方Link](https://qiita.com/taungyeon/items/0afa3a5580c7521d54d1)

※使えない状態のまま、dlibの設定をしてしまった方は一度dlibを消し去った方が手軽です。

# 解説
雑にいうと事前に CUDA & ducnn 設定しているか否かでコンパイル時判定が変わるため、特に意識せずにdlibインストール手順を踏めば問題なくインストールできます。
Win10で"docker-machine"コマンドを使う方法

#はじめに

最近docker for Windowsを用いてやっとdockerの勉強を始めたのですが
いろんなサイトを参考にしてると”docker-machine”コマンドをつかって
dockerの停止・起動をされていました。

でも、powershellから”docker-machine”コマンドがデフォルトでは使えないので
なんでやねん…！と思い調べて対処した結果をまとめてます。


#動作環境
OS：Win10Pro(Hyper-V)

#docker-machineダウンロード
以下からダウンロードしました。
https://github.com/docker/machine/releases/


#環境調整
##①docker-machine配置
ダウンロードしてきた"docker-machine-Windows-x86_64.exe"を"docker-machine"に
リネームして「C:\Git」に配置。
※配置するフォルダはどこでもよいです。わかりやすいとこで・・

もうこの時点でdocker-machineは使えるのですが、いちいちC:\Git\docker-machine.exeと
打つのはめんどくさいので環境変数Pathを指定しておきます。


##②環境変数指定
Powershellを起動し以下コマンドを実行

```
$env:Path += ';C:\Git'
```

以下コマンドを実行し、追加されているか確認

```
PS C:\Users\ユーザ名> $env:Path
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Docker\Docker\resources\bin;C:\ProgramData\DockerDesktop\version-bin;C:\Program Files\Git\cmd;C:\Users\ユーザ名\AppData\Local\Microsoft\WindowsApps;C:\Users\ユーザ名\AppData\Local\GitHubDesktop\bin;C:\Git
```

ただこのままだとPowershell再起動すると消えてしまうので以下のファイルを作成する。

```
C:\Users\ユーザ名\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
```

ファイルに$env:Path += ';C:\Git'と記入し保存。
これで再起動後にもこのファイルを自動的に読み込み、docker-machineコマンドを楽に使えます。

最後に確認としてPowershellからdocker-machine versionを実行してdockerバージョンが表示されることを確認してください。

```
PS C:\Users\ユーザ名> docker-machine version
docker-machine.exe version 0.12.2, build 9371605
```

これでOKです。


#参考
https://qiita.com/ohhara_shiojiri/items/98573b074185381d46c8
初心者でも簡単！SNS認証を実装（Google編）

#API側の設定
ではやっていきましょう。

まず、
https://console.cloud.google.com/apis/credentialsにアクセスします。

アクセス後ヘッダーに[プロジェクトの選択]という欄をクリックします。（私は１つアプリを作りましたのでアプリ名になっています。）
そうすると以下のような画面が表示されますので、[新しいプロジェクト]をクリックします。

<img width="1280" alt="スクリーンショット 2020-03-15 13.41.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/d7f58065-0daf-2e5d-7689-7a7b6043d10d.png">


以下のページに移動したら、以下の欄に自分のプロジェクト名を記入します。
<img width="1280" alt="スクリーンショット 2020-03-15 13.46.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/f11b8c07-ecad-1778-c807-179672ed3d46.png">

プロジェクト名記入後は、[作成]をクリックしましょう。

[APIとサービス]→[認証情報]→[OAuth同意画面]の順に選択して、移動した先のページでアプリケーション名を記入します。記入後はスクロールし[保存]をクリックしましょう。

<img width="1280" alt="スクリーンショット 2020-03-15 13.50.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/4c1a4351-5615-b315-5296-e2a114eec51f.png">

<img width="1280" alt="スクリーンショット 2020-03-15 13.51.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/b7a66f9a-fe64-4dde-e91b-067a5dcf1e6f.png">


移動したページから以下の画面に戻り[認証情報]→[認証情報を作成]をクリックし[OAuthクライアントID]を選択します。
<img width="1280" alt="スクリーンショット 2020-03-15 14.09.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/41fa0717-a886-3910-8809-fd1493eb67f2.png">

移動したら、今回は、[ウェブページ]を選択します。

<img width="1279" alt="スクリーンショット 2020-03-15 14.16.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/068f6293-04ac-e929-6f29-aee72b5f84be.png">

以下のページに移動したら、「名前」、「承認済みのリダイレクトURI」を記入して、「作成」をクリックします。
なお、「承認済みのリダイレクトURI」は、
私は「http://localhost:3000/users/auth/google_oauth2/callback」
を利用しました。

<img width="1280" alt="スクリーンショット 2020-03-15 14.20.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/d2b5ff27-8e0b-9579-5840-4c4a69e6f178.png">




<img width="1280" alt="スクリーンショット 2020-03-15 14.20.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/1621217e-db36-734b-77e8-1fe7a6889e8f.png">

移動したページのに[クライアントID]と[クライアントシークレット]がそれぞれ表示されています。
両方ともあとで使いますので、メモしておいてください。

<img width="1278" alt="スクリーンショット 2020-03-15 14.27.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/4337e16b-bb71-1c14-93c9-077b336fefde.png">

最後に、Google+ APIを有効にする必要があるので、以下のように「Google+Google+ API」と検索して、「有効にする」を選択しましょう。

<img width="1278" alt="スクリーンショット 2020-03-15 14.42.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/412b2b06-2539-7fe0-bd7f-5ce3bd3ddaa7.png">

<img width="1280" alt="スクリーンショット 2020-03-15 14.45.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/3a7ecf10-071e-a170-90a9-8197f8c85fb0.png">


以上です！！
標準偏差とは。。。？僕がわかるから、誰でもわかる！！

資料やグラフで標準偏差というものは、一度は目にした事があると思いますが、実際なんなの？と思っている方もいると思います。

今はExcelなどで、標準の機能としても使用できます。統計資料作成やデータを分析して活用する際に、もっとも簡単なきっかけの部分に出来ると思います。

# 標準偏差とは？
標準偏差はデータのばらつきを示す値です。
![d1f8e0ba633077a78d2d82a5b0142abf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406727/075a864e-eb40-b8d1-bc3b-f91ee8710ffe.png)

もう少し、定義すると分散の正の平方根の事を、標準偏差と言います。

![quicklatex.com-e34003a778736726969f2e255bc3e103_l3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406727/59221dab-01f2-f099-0678-a5befbfc2cca.png)

まーでも、実際はそんなことはどうでも良いです。どんな時に使えて何が出来るかです。

# どんな時に使えるか？

例えば、年収平均500万の会社があったとします。

|　内訳　 |A  |B  |C  |D |平均
|---|:---:|:---:|:---:|:---:|:---:|
|A社　|　510|　480|　520|　490|　500
|B社　|　100|　100|　900|　900|　500

どちらも、平均を見ると500となりますが、中を見るとひどいものです。
こういう数字を見ると平均が必ずしも信用できない事がわかります。

この時、**平均との誤差がどれくらいかなのか？**がわかれば、**平均のデータがどれくらい信用出来るか**がわかります。
その発想から生れたのが**分散**です。

# 分散

分散はデータのばらつきを示す値です。
標準偏差と同じやんけ！と思われると思いますが、違いは後でご説明します。

![unnamed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406727/9a04be94-e238-e93f-3c8f-770ccf794fb5.png)

分散は何故、対象データの２乗なのか？
これは、やって見るとわかります。

平均との誤差を求めようとすると、

|　内訳　 |A  |B  |C  |D |平均
|---|:---:|:---:|:---:|:---:|:---:|
|A社　|　510|　480|　520|　490|　500|
|平均との誤差| +10| -20| +20| -10 |**0**|
|B社　|　100|　100|　900|　900|　500|
|平均との誤差| -400| -400| +400| +400|**0**|

平均との誤差の平均は０になってしまいます。それは、プラスの値とマイナスの値で相殺されるからです。

この状況を避ける為に、平均との誤差の値を２乗します。

|　内訳　 |A  |B  |C  |D |平均
|---|:---:|:---:|:---:|:---:|:---:|
|A社　|　510|　480|　520|　490|　500|
|平均との誤差| +10| -20| +20| -10 |0|
|平均の誤差^2|100|400|400|100|**250**| 
|B社　|　100|　100|　900|　900|　500|
|平均との誤差| -400| -400| +400| +400|0|
|平均の誤差^2|160000|160000|160000|160000|**160000**|

この250と160000が分散です。

ただ、これではしっくり来ません。何故なら、元データに対して２乗してしまっているので、単位が異なってしまっています。

その為に、元データの単位に戻す為に、分散に平方根します。
ここが、標準偏差と分散の違いです。**対象データと同じ基準で比較する為のものが標準偏差**というイメージです。

|内訳 |A  |B  |C  |D |平均|分散|標準偏差|
|----|:---:|:---:|:---:|:---:|:---:|:----:|:-----:|
|A社 　|　510|　480|　520|　490|　500|   250|**15.8**|
|B社 |　100|　100|　900|　900|　500| 160000|**400**|

これで、誤差の平均がわかりますね。
### 標準偏差の値が小さい程、平均値が信用出来るという指標となります。
競プロ入門にあたって勉強すること

# はじめに
最近思い立ってAtcoderを始めることにした。
それに当たってアルゴリズムについて勉強すべき項目をここにまとめておくと効率的かと思い、執筆に至る。
随時更新予定。
（追加すべき項目などアドバイスあれば嬉しいです）

# 自分の現状
というわけで早速[パナソニックプログラミングコンテスト2020](https://atcoder.jp/contests/panasonic2020)に参加してみた。(ちゃんとコンペに参加するのは初めて)
自分の出来としては全６問でこんな感じ。

1. 基本、割愛
2. W=1 or H=1の場合が思いつかなかった知人がいた
3. 式変形をせずに苦労してる知人がいた
4. 競プロの知識はないが解けた
5. TLEを解消できなかった
6. 余裕もなく問題文をさらっと読んで理解せず放置

パフォーマンス的には水色くらいという感じ。
自分はpythonを使用したが、５問目以降はpythonで正解してる人はいなかった。
理由としては以下のどっちかかな〜と予想。

- pythonのパフォーマンスの限界
- 強い人がC++を使用してpythonにいなかった

当面はアルゴリズムの勉強はしつつ、必要があればC++に慣れる予定。


# 勉強すべきもの

- [ ] 深さ優先探索
- [ ] 幅優先探索
- [ ] ビットループとか
- [ ] 貪欲法
- [ ] 動的計画法(かなり種類ありそう)
- [ ] 木・二分木
- [ ] プライオリティーキュー・ヒープ
- [ ] 二分探索
- [ ] Union-Find
- [ ] グラフ問題に慣れる
- [ ] 余り計算
- [ ] 冪乗計算
- [ ] しゃくとり法
- [ ] 反転
- [ ] 男性衝突
- [ ] 半分全列挙
- [ ] 座標圧縮
- [ ] セグメント木
- [ ] Binary Indexed木
- [ ] バケット法・平方分割
- [ ] ネットワークフロー問題
- [ ] 平面幾何問題


# 今後
この項目を潰しながら適宜新項目を追加していって青色を目指す。
今の所感として青と水色にかなり壁を感じる、、、
GitHub Pagesを活用して擬似REST APIサーバーを作る

## はじめに
[Qiita - GitHub Actionsを活用して擬似APIサーバーを用意する](https://qiita.com/Kanahiro/items/e7021b05199ae52e818b)
こちらの記事で、Actionsを用いてjsonファイルを自動更新でき、それをPagesで読み込めるという事は、それはすなわち擬似的なAPIサーバーとして運用できるという事では、という提案をしました。
ただこれでは、膨大なデータのうち欲しいデータはごく一部なのに、毎回全部取得して、keyから辿っていく必要があります。

じゃあjsonファイルを分割すれば良かろう、どうやって？

## REST API
[Qiita - 0からREST APIについて調べてみた](https://qiita.com/masato44gm/items/dffb8281536ad321fb08)
巷でよく聞くREST API、これは要するにデータに準拠したURLルーティングの事だと理解出来ました、これを基準にして分割してみます。

```json:sample.json（データの出典：北海道オープンデータポータルから取得したデータを加工したもの）

{
    "data": [
        {
            "no": "1",
            "date": "2020-01-28T00:00",
            "place": "中国武漢市",
            "age": "40代",
            "sex": "女性"
        },
        {
            "no": "2",
            "date": "2020-02-14T00:00",
            "place": "札幌市",
            "age": "50代",
            "sex": "男性"
        }
    ],
    "last_update": "2020-03-14T23:14:01.849130+09:00"
}
```

ホスティングURLをhttp://{HOSTING}/とします。

|  取得するデータ  |  REST APIのURL  |
| ---- | ---- |
|  sample.jsonの全データ  |  http://{HOSTING}/sample  |
|  sample.jsonのlast_update  |  http://{HOSTING}/sample/last_update  |
|  sample.jsonのdataの1つ目の要素  |  http://{HOSTING}/sample/data/0  |
|  sample.jsonのdataの2つ目の要素  |  http://{HOSTING}/sample/data/1  |
|  sample.jsonのdataの2つ目の要素のno  |  http://{HOSTING}/sample/data/1/no  |

となっていればRESTな訳です。

## GitHub Pagesで擬似REST APIをつくる
GitHub Pagesでは、ディレクトリへのアクセスはindex.htmlへ差し向けられます。
つまり、http://{HOSTING}/sampleにアクセスした場合は、gh-pagesブランチのルート/sample/index.htmlにsample.jsonの全データを書き込んでおけば、欲しいデータのJSON文字列を返す訳です。
http://{HOSTING}/sample/last_updateの場合はルート/sample/last_update/index.htmlに「2020-03-14T23:14:01.849130+09:00」という文字列を書き込んでおく。

以上の手順でホスティングすれば、擬似的にREST APIサーバーが出来ていると言えるのではないでしょうか。

## 実装
[Kanahiro/gh-pages-rest-api](https://github.com/Kanahiro/gh-pages-rest-api)
こちらのスクリプトは、masterへのプッシュ時にActionsによりmain.pyが実行されます。
main.pyは、jsonフォルダ内のjsonファイルを読み出して、gh-pagesに前述のとおり細分化されたディレクトリにindex.htmlを配置します。

上記リポジトリのjsonフォルダ内には前述のsample.jsonが格納されています。
gh-pagesのホスティングURLはhttps\://kanahiro.github.io/gh-pages-rest-api/なので

|  取得するデータ  |  REST APIのURL  |
| ---- | ---- |
|  sample.jsonの全データ  |  https://kanahiro.github.io/gh-pages-rest-api/sample  |
|  sample.jsonのlast_update  |  https://kanahiro.github.io/gh-pages-rest-api/sample/last_update  |
|  sample.jsonのdataの1つ目の要素  |  https://kanahiro.github.io/gh-pages-rest-api/sample/data/0  |
|  sample.jsonのdataの2つ目の要素  |  https://kanahiro.github.io/gh-pages-rest-api/sample/data/1  |
|  sample.jsonのdataの2つ目の要素のno  |  https://kanahiro.github.io/gh-pages-rest-api/sample/data/1/no  |

以下のとおり、masterへのプッシュ後に自動的にホスティングされます。
出来るリクエストはGETのみですが、まさしくREST APIがGitHub Pagesに実装されていると言えるのではないでしょうか。

そして[Qiita - GitHub Actionsを活用して擬似APIサーバーを用意する](https://qiita.com/Kanahiro/items/e7021b05199ae52e818b)で紹介したように、Actionsによるスケジューリングでjsonファイルを自動的に更新できれば、データが自動的に更新されるREST APIサーバーとなります。

## 再利用
1. 上記のリポジトリをフォークする
2. ホスティングしたいjsonをjsonフォルダに入れる
3. masterにプッシュする（→自動的にgh-pagesにデータが出力される）

※手動でActionsとPagesをActivationする必要があります

## 注意事項
- まだ作ったばかりなのでフロント側でちゃんと読み込めるか試していません
- まだ作ったばかりなのでどんな不具合があるかわかりません
- jsonのkeyは、英字のみを推奨（日本語でURLがどのようにエスケープされるか未確認）
C言語　関数のおおよその実行時間を表示させるコード

コマンドを使って実行する方法もあるけれど、
__おおよその実行時間__を出すコード。
あくまで大体の時間なので、目安として使う時だけ。


```c
#include <stdio.h>
#include <time.h>
//時間計測
clock_t cpu_time_start;
clock_t cpu_time_end;
double sec_start;
double sec_end;
double result_time;

int	main(void)
{
    //計測開始
    cpu_time_start = clock();
    sec_start = (double)cpu_time_start/CLOCKS_PER_SEC;
    printf("開始時間 : %f\n\n",sec_start);

    // ここに処理を書く

    //計測終了
    cpu_time_end = clock();
    sec_end = (double)cpu_time_end/CLOCKS_PER_SEC;
    printf("\n終了時間 : %f\n",sec_end);
    //処理時間
    result_time = sec_end - sec_start;
    printf("処理時間 : %f\n",result_time);

    return (0);
}


```


##2020/04/19　追記
関数をひとつずつ調べない場合はこっちの書き方の方でOK。


```c
#include <stdio.h>
#include <time.h>

int main(void)
{
    // ここに処理を書く

    printf("%f秒\n", ((double)clock()) / CLOCKS_PER_SEC);
    return 0;
}
```
Pythonで毎日AtCoder #6

### はじめに
[前回](https://qiita.com/taxfree_python/items/742657cac1943212f1af)
6日目です。[昨日のコンテストのC](https://atcoder.jp/contests/panasonic2020/tasks/panasonic2020_c)に惨敗したtax_freeです。

### #6
[問題](https://atcoder.jp/contests/abc095/tasks/arc096_a)

**考えたこと**
Aピザ、Bピザ、ABピザの組合せの最小値を求める問題です。for文でABの枚数を指定して最小値を更新していく手法で解きました。

```python
a, b, c, x, y = map(int,input().split())

price = a * x + b * y
for i in range(max(x,y)+1):
    price = min(price,c * 2 * i + max(a * (x - i),0) + max(b * (y - i),0))

print(price)
```
ABピザを0枚買ったときの値段を初期値にして、forで回しています。pythonのforはstop値-1で止まるので、+1するのを忘れるとサンプルケース3のように全部ABを買う場合が通りません。

```python
c * 2 * i + max(a * (x - i),0) + max(b * (y - i),0))
```
x < i or y < iのときに、a * (x - i)、b * (y - i)が負になることを防ぐためにmax(0,計算結果)を取って負にならないようにしています。

### まとめ
このくらいのCはできるようになったのかな。本番のコンテストでもこれくらい解けるようになりたい
では、また
Codeforces Round #627 Div.3 E. Sleeping Schedule : 周回するDP

https://codeforces.com/contest/1324/problem/E

# 概要
- 1日はh時間であり、$l$から$r$時の間に寝ると`良い睡眠`である
- あなたは今からn回ねることを計画しており、それぞれi回目の睡眠は$a_i$時間あるいは$a_i - 1$時間後に取る。
    - 訳注: h=24として、3,4,5となっている場合(もし、全部-1しないなら)3, 7, 12時になることになる。(何時間寝るかはここで問題にならないらしい)
- あなたは最大で何回の`良い睡眠`をとれるか？

# こう考えた
DPで考える。

- dp[寝た回数][時間] = 良い睡眠の数。として考える。
- 次の睡眠をとると、$a_{i}$時間後あるいは$a_{i}-1$時間後に、その`良い睡眠の数`を引き継げる。これは最大を取ればいい(max)。
- 各DPの計算後、計算したDP列の`良い睡眠`の時間に値が入っているなら1加算する。
    - 値が入っているなら、がポイントで、その時間に到達しないのに加算すると変なことになる

# コード
```Python
from pprint import pprint
n, h, l, r = map(int, input().split())
data = list(map(int, input().split()))
dp = [[-1] * h for i in range(n+1)]
dp[0][0] = 0
for i in range(n):
    x = data[i]
    for j in range(h):
        if dp[i][j] == -1: # not visit
            continue
        dp[i+1][(j + x    ) % h] = max(dp[i][j], dp[i+1][(j + x    ) % h] )
        dp[i+1][(j + x - 1) % h] = max(dp[i][j], dp[i+1][(j + x - 1) % h])
    x = 0
    for j in range(h):
        if dp[i+1][j] == -1: # not visit
            continue
        if l <= (j + x    ) % h <= r:
            dp[i+1][(j + x  ) % h] += 1
print(max(dp[n]))
```
https://codeforces.com/contest/1324/submission/73264598
factory_botでモデルのenum別のtraitをまとめて書く

## はじめに
enumのtraitをひとつずつ書いていたところ、[factory_botでモデルのenum別のtraitを一発で書く小ネタ](https://qiita.com/TeruhisaFukumoto/items/ede89b66e00fa11937ed)を見つけました。

今回、この記事とは異なる書き方でtraitを書く方法が分かったので、まとめていきます。

## コード

### モデル

例えば、UserがSpotifyのプランごとのステータスを持っていたとします。

```rb:app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
  enum :plan { free: 0, individual: 1, family: 2, student: 3 }
end
```

この`plan`それぞれにtraitを作ってもいいのですが、enumの数に比例して行数が増えます。</br>
さらに、Spotifyにプランが追加されたときに、設定を忘れる恐れがあります。

### ファクトリ

上記のモデルのtraitの行数を減らすために、このように書くことができます。

```rb:spec/factories/user.rb
FactoryBot.define do
  factory :user do
    name { "hoge" }

    User.plans.keys.each do |plan|
      trait :"#{plan}" do
        status { plan }
      end
    end

  end
end
```


##### 【ポイント】

1. enumにつけた名前を複数形にする</br>
この例では、`plans`と複数形に直しています

2. enumの名前(複数形)のkeyを取り出す</br>
コンソールで表示すると以下のとおりになります。

`keys`で取り出すと、enumのkeyとしての名前でtraitを作ることができます！

```rb
[1] pry(main)> Tag.statuses
=> {"free"=>0, "individual"=>1, "family"=>2, "student"=>3}
[2] pry(main)> Tag.statuses.keys
=> ["free", "individual", "family", "student"]
[3] pry(main)> Tag.statuses.values
=> [0, 1, 2, 3]
```
Unity入門：今週悩んだことと。単純なバグに長時間時間を取られてしまった。

##はじめに
今週勉強したことをまとめています。
初めまして、HITOMI(男)です。現在Unityを勉強しています。今週勉強したこと、悩んだことをここに書き残します。

先週悩んでいた、UIのアニメーションをうまく実装することができました。うまくいかなかった原因は私の操作ミスだと考えています。できるだけこういったミスを少なくしていきたいなと考えています。


さて、私はUnityの勉強のため3D横スクロールゲームを開発しています。そこで今週悩んだことや、詰まったとこをここに書き残そうと思います。
今週(3月8〜3/14日)詰まったところ。
・読み込みクラスの単純なバグの解決に１日以上ほどかかった。
・GUIのアニメーション遷移でのバグ。
・イベント読み込みクラスについて


##単純なバグの解決に１日以上かかった。

データ読み込みクラス(前回紹介した<Element></Element>の部分)でうまく読み込めないバグが発生しました。結論から言うとバグは解決したのだが、バグの場所の特的と修正に１日以上時間かかってしまった。そのバグの原因はfor文の Length-1の　−１をつけ忘れていたと言う単純なミスでした。こんな単純なミスで時間を取られた時は、「うわーーーーーー」ってなります。今後こんな単純なミスはできるだけ無くしていきたいと思います。何か対策を取らなくては。

```
//ここが抜けていた。
for(var i; I<m_List.Count -1; i++)
{

} 
```

##GUIのアニメーション遷移でバグが発生した。
漫画などによく使われている、吹き出しのアニメーションをプログラムで実装しています。内容は吹き出しがフェードインしたとに、テキストが一定間隔で表示され、テキストが終了するとフェードアウトする。といったものです。今回発生したバグは２周目のフェードインの時にフェードインが終わった際に吹き出しが消えるといったものだ。Unity上で再生を一時中断してCanvasを確認したところ、ImageのRectTransformのscaleが0,0,0になっていた。アニメーション部分がうまく動いていることを考えると、コルーチンとsetActiveの部分に問題がある思っている。実際setActiveを常にtrueにすると問題なく動く。色々悩んだ末、画面から非表示にする処理をsetActiveを使わずにscale0を用いることにした。こうするとうまく動くことができた。この部分はまた、全体が完成してからもりもり作り込んでいこうと考えている。



##イベント読み込みクラスに改良

外部のテキストから以下のようなファイルを読み込み
イベント等を実装するクラスを作っています。
(ゲームプログラマになる前に覚えておきたい技術参考)

```
<EventData　name=“event01”,type = “count”,trigger=“”,nextEvent=“event02”>
        <CountDown position = "hairScreen,hairScreen,0.0f">
</EventData>

<EventData　name=“event02”,type = “speak”,trigger=“”,nextEvent=“event03”>
        <TriggerObject type = “box” , event=“event”, position = "12.4,7.0,0.0”, size="1.0,1.0,1.0"></TriggerBox>
        //行動制限
        <SpeechBubble position="12.4,7.0,0.0">
                    <Speech speech="左右の矢印を押すと移動できるよ” , type=“timer”></Speak>
                    <Speech speech="上ボタンを押すとジャンプできるよ” , type=“wait”></Speak>
                    <Speech speech="下ボタンを押しても何もないよ。” , type=“wait”></Speak>
        </SpeechBubble>
</Event>
<EventData　name=“event03”,type = “clear”,trigger=“”,nextEvent=“none”>
      略
</Event>
```

前回考えていたテキストの内容をプログラムに反映しました。その結果、カウントダウンからスタートクリアまで外部テキストで調節できるようになりました。と言っても、実際はカウントダウンとクリアは一枚絵を貼り付けただけで実際にアニメーションまでは実装できていません。来週はこれにカメラの制御とプレイヤーの動きを制御できるよう機能を追加したいと考えています。


##さいごに
今週は思っていたよりも進捗が遅れています。多分３月中の完成はちょっと難しいのかなと考えています。来週はスタートからクリアまで一通り遊べるようにすることと、メモリリークをなくすところまで進めたいと考えています。
Rails勉強中　EC_siteカート機能　同一商品追加時のcreate

#　はじめに
現在Rails勉強中の人が備忘録として書いてます。
こうした方がいい、あーした方がいいといった点があれば教えてください

#　コード
<img width="542" alt="スクリーンショット 2020-03-15 14.03.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594090/b9e42e85-020a-025f-6afd-356d05bd7d27.png">


# 内容
viewは比較的スムーズに実装できると思うので割愛
コード見れば分かると思うが、自身が誤っていないかの確認
↓
始めに、isExistとIdのデフォルト値の定義
each end内で追加した商品IDとカートに追加されている商品IDが同じかif文で記す
if isExistではeach内の変数を持っていけないので、前に定義したIDを持ってくる

sumで新たに追加したい値と既にカートに保存されている値を計算
updateするのは追加する商品の個数だけなので(ここではcount)、
update_attributesでカラム指定して実行
※update_attributeもあるが、これはvalidationチェックされずにupdateが実行される
個数をupdateしたいが、仮に文字が入ったとしてもupdateされてしまう。


# 最後に
modelとかhelperを使えばもう少しコントロールの記述量が減るかもしれないが、
勉強不足のため日々精進していきたい
PHP: dompdf の使い方

```php:dompdf01.php
#! /usr/bin/php

<?php
require_once "vendor/autoload.php";
use Dompdf\Dompdf;

$str_out = '<h1>Hello World</h1>';
$str_out .= '<blockquote>';
$str_out .= 'Good Morning<p />';
$str_out .= 'Mar/15/2020<p />';
$str_out .= '</blockquote>';

$dompdf = new Dompdf();
$dompdf->loadHtml($str_out);

$dompdf->setPaper('A4', 'portrait');

$dompdf->render();

file_put_contents("test01.pdf", $dompdf->output());
?>
```


次のような PDF が作成されます。
![dompdf_mar1501.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/917a66a1-8113-b491-0284-1491817695fa.png)

PDF の確認方法

```bash
evince test01.pdf
```


ライブラリーのインストール　(Ubuntu 21.04)

```bash
sudo apt install php7.4-xml
composer require dompdf/dompdf
```

実行コマンド

```bash
./dompdf01.php
```
【個人開発】VueのCDNで育成ゲームのようなものを作った記録【Vue.js】

[Webサービスを1週間で作ろう](https://crieit.net/posts/Web-1)というイベントがあったので、参加しました。
せっかくなので、どのように作ったか記録として残しておこうと思います。

## 作成物

私は「ひきこもりのいちにち」という育成ゲーム的な何かを作ってみました。
以下、ネタバレを含みますので、初見の方は是非一度遊んでいただきたいです。
こちらのリンクからどうぞ。

https://aiandrox.github.io/hikikomori_oneday/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/d65c5aac-2dbf-3767-3999-6600e4e94406.png)

### ゲームについて

点数は最大150点くらいになるようになっています。
ゲームオーバーのフラグは3つあります。コメントはゲームオーバー含めて全13種類です。ぜひコンプリートを目指してください。

## 技術的なこと
### 使用したもの

- HTML
- CSS
- Vue.js（CDN版）
- GitHub Pages
- [ress.css](https://github.com/filipelinhares/ress)（リセット用CSS）
- [Google Fonts](https://googlefonts.github.io/japanese/)（タイトルに使用）
- [Googleマテリアルアイコン](https://material.io/resources/icons/?style=baseline)（時計アイコンに使用）

Google Fontsはタイトルをかわいい感じにしたかったので使用。
FontAwesomeではなくマテリアルアイコンを使った理由は、前者をCDNで使おうとすると登録が必要で面倒だったから。

### 構造
`index.html`にVue.jsのCDNを取り込んで、全てのコードを詰め込んでいます。コンポーネントとか知りません。
画面は、最初の画面、ゲーム画面、結果画面2種類、活動記録の5つです。これを`gameStatus`の値と`flag`によって表示し分けています。
メソッドは9つでした。一応、行動コマンドを`action(index)`で一括できたのでよかったです。
総評は条件にごとにcomments配列にpushして最後にjoinしています。ゴリ押しが過ぎる。

## 作成記録

入れたかった機能は、ゲームオーバーと総評コメント機能です。
初見の人には是非ゲームオーバーになってほしかった。
また、せっかく遊んだなら、遊ぶたびに違う結果になってほしいので、総評を入れることにしました。そして、結果を点数も出たらおもしろいのでは？ということで点数も追加しました。
ステータスの増減値をランダムにできたのでわりと満足です。

### 作業時間

3/13 約7.5時間
ひたすらindex.htmlにHTMLとVueを書く
3/14 約8時間
CSSで肉付けしながら手直し

### 作成の流れ

3月9日に「Home」というテーマが発表されました。
最初は「家から出られないあなたはどのように１日を使いますか？」というコンセプトでノートにメモしていました。
![1584198070504.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/a596b114-0e0b-3e36-3c2d-8ec248d7817a.jpeg)
この時点では、JavaScriptを使えば実装できるだろうという程度の認識でした。Vue.jsを少し写経したことがある程度でデータをビューに同期させる方法が全くわからなかったので、案は考えたけど作るのは無理だろうと思っていました。

ただ、進行形でJavaScriptを勉強しており、[JS-Pro](https://js-pro.jp/)というサイト使っていました。ここのVue.js Iを終えたところでデータの渡し方がなんとなくわかり、行けそうと思ったので作成することにしました。
「行ける」というのは「まあ大体思った通りの挙動をしてくれる」という意味でしかありませんが、「出せばOK」の精神でやりました。

## 感想

作業時間は意外とそんなにかからない。ただし、機能が明確になっていて、許容範囲が広い場合のみ。
GItHub Pagesは初めて使ったのですが、設定が簡単で驚きました。まじで数分でできます。
とにもかくにも提出できたのでよかったです。楽しく制作させていただきました。

最後になりますが、このような機会を設けてくださった主催者のだら様に感謝申し上げます。

### 課題

- index.htmlの長さがやばい
- 24時を越えると時計のレイアウトが崩れる
- 時計を右寄せにしたかった
- ランダム値の範囲が固定なので、ある程度融通きかせたかった

### 追加したかった機能

- データベースを使ったランキング
- コマンドを増やす（筋トレを追加しました）
- コマンドに応じて棒人間の画像を変える
- ステータスを増やす（たくましさを追加しました）
- ステータスをレーダー表示する
- レスポンシブ対応（スマホ幅対応しました）
LGTMに半狂乱な人々

次のような変更がありましたね。

[Qiitaの「いいね」が「LGTM」に変わります](https://blog.qiita.com/like-to-lgtm/)

一番重要なポイントはこちら。

> 前提として、Qiitaの「いいね」は他のSNSにある「いいね」とは少し異なる意味を持っています。Qiitaでは、技術発信を行い、それを見て役に立った、面白かったということを「いいね」を介して評価し、その評価が発信をした人のエンジニアとしてのアイデンティティを確立する世界を目指しています。他のSNSではあまりない、コメントや投稿した記事、編集リクエストを送った記事などについた「いいね」の重み付けされた総量が「Contribution」として表現されることからもその意図は伝わるかと思います。
> 
> Qiita運営としても、流れてきた記事に「いいね」するのではなく、しっかりその内容を読んで、その内容が少なくとも自分にとって良いものだと思ったときに「LGTM（Looks Good To Me）」と言ってもらった方が良いと考えました。これまでと同じように緑色のボタンを押すというインターフェースは変わっていませんが、反射的に押すのではなく、一度その対象をよく見てから押してもらえるようになると幸いです。

より運営意図に近づけたいと考える施策と言えますし、運営の苦悩が見え隠れしていますね。

そこで、この変更に対する反応についてまとめてみました。

## LGTMに対する否定的な反応

積極的に現場維持、というか巻き戻そうと努力する人たち。

[LGTMを戻す](https://qiita.com/sapi_kawahara/items/4e05845e285ac087feb5)

[[ネタ]強制的にLGTMをいいねに戻す方法[Chromeエクステンション不要]](https://qiita.com/Andhy/items/de9d7430ffc5b30670f5)

[LGTMはいやだ - Qiita](https://qiita.com/HirosuguTakeshita/items/f015fee48f42a41045ef)

ネタとしても拒否感が露わ。現状維持バイアスの代表格。

## LGTMに対する肯定的な反応

Qiita運営の主旨を理解して、むしろTwitterも巻き込んでいくスタンス。

[Twitterの「いいね」を「LGTM」にするChrome Extensionを作ってみた](https://qiita.com/H_Crane/items/079d3021c36f00e60b2c)

主旨に積極的に合わせていくスタンス。

[Qiitaで「LGTM」していない投稿のLGTMを外す](https://qiita.com/hanachin_/items/660aa3b68f004ceb6c16)

## 今回のLGTM論争はこんなもんじゃないぞ

Qiita/SNS/ブログ記事など、もっと沢山の反応について下記でまとめました。

[QiitaのLGTMボタンに対する反応をまとめた](https://takulog.info/how-about-qiita-lgtm/)
[![QiitaのLGTMボタンに対する反応をまとめた](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182842/6f7a3f53-1aec-c13c-cc14-027bde4c06cc.png)](https://takulog.info/how-about-qiita-lgtm/)

LGTMの意味がどうだからとか、Qiita運営の施策がどうだから、という気はありません。

ただ、こんなことで荒れたりするんだな、と。

Qiitaユーザーやエンジニアというのは、とてもセンシティブな生き物なんだな、と。

ホントにそこまで嫌か？とも。

個人的には、「いいね」だろうが、「Good」だろうが、「同意」だろうが、「役に立った」だろうが、そこまで言わなくてもよいし、皆意識して使い方変わるかな？と思いますし、そこまでイヤイヤ言わずに試してみりゃいいやんと思わなくはありません。正直どっちでも良い。

そんなわけで、今後もQiitaを応援しながら、楽しんでいきたいと思います。
【絶対消し忘れるな！】AWS初学者が高額請求を避けるために消すべき設定３選

## 概要
AWSを使う上で、不要になった設定は消しとこうねというお話です。

## はじめに
AWSを学び始めてしばらくすると、無料枠以外の機能も使いたくなってきます。そしてそういう時期には新しいサービスに目移りし、「まぁこれぐらいの請求なら」と、作ったサービスを放置しがちです。

僕もそんな初心者のうちの1人でした。そして放置し続けた結果...

<img width="128" alt="スクリーンショット 2020-03-15 13.01.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223014/5a6668a5-4372-071d-fd24-d357f536dd2f.png">

**ひゃ、　120ドル！？？？　な　なんじゃこりゃあああああああ！！！！**

僕のようにならないように、本記事では不要になったら消しておくべき設定3選をまとめました。

## 不要になったら消して置くべき設定３選

### 1. EC2, RDS
AWSを学び始めたら、まず最初に作る構成は、「EC2コンテナ上でアプリケーションサーバーをたて、DBはRDSで構築」というパターンだと思います。
この構成は小さいサイズだと（AWSのアカウントを作成してから１年間は）無料で作れるのですが、無料枠を少しでも超えた設定だと、途端に高額な請求がくるので注意しましょう。

注意しなければいけないのが例えばEC2の場合、無料枠は「t2.microを**750時間**分」であるということです。
たとえば、t2.microサイズのインスタンスを２台たてていた場合、AWS側では「**t2.microを1500時間たてていた**」という認識になり、しっかり750時間分の請求がきます。小さいサイズとはいえ地味に痛いです。


### 2. ALB
AWS初心者を少し脱却した頃になると、「ALBを使った、負荷分散を意識した構成」を作りたいと思うはずです。
ただ、こいつがくせもの。ALBの料金は「**LCU時間ごとの従量課金と使用時間あたりの従量課金の合計**」できまります。
LCU時間ごとの課金はごく簡単に言えば、「**ALBに接続することによって起こる課金**」なので、今回は問題になりません。問題は「使用時間ごとの従量課金」。おおよそ0.024USD/時間なので、１ヶ月放置し続けるとおよそ**2000円**も取られてしまいます！た　たけえ！
ALBはEC2やRDSに比べて「課金されている」という感覚がなくなりがちです。不要になったら忘れずに削除しましょう。

### 3. Elastic IP Address
デフォルト設定だと、EC2のパブリックIPアドレスは固定されていません。つまりEC2を停止して再度起動するような場合、パブリックIPアドレスが変わってしまい「あれ、なぜか接続できない...」という事案がおこります。
これを避ける一つの方法が**Elastic IP Addressという、EC2専用の固定のIPアドレスを保持しておいて、使用するEC2に紐づけてあげる**という方法です。

ただ、これがまたまたくせもの。例えば、Elastic IP AddressをEC2に紐付ずに放置していた場合、時間あたり0.005USD, １ヶ月で**400円**かかってしまうのです。
これだけ聞くというほど高くないように感じますが、もちろんこれはElastic IP Addressごとに課金されるので、５つ保持していた場合、これの5倍の2000円がかかります...考えたくないですね。
不要になったElastic IP Addressはかならず開放してあげましょう。

## 高額課金をさけるための対策
では、このような消し忘れを防ぐためにはどうしたらよいのでしょうか

### AWSの請求アラートを有効にする
AWSでは高額請求を防ぐためのしくみとして、「**特定の請求額を超えた場合、メールで通知してくれるシステム**」が存在します。消し忘れが不安な方は設定しておきましょう。
設定の仕方に関しては以下の記事がわかりやすかったです。

[AWSで請求アラートを設定する](https://qiita.com/Soh1121/items/fbd9e13cd050bcefbe55)

### 請求書を逐一確認する
AWSの請求書には「何にいくら使ったか」が詳しく書いています。「今月の利用料高え！」と思った時には、請求書を確認し、同じ失敗をしないようにしましょう。
（請求書は「[My請求ダッシュボード](https://console.aws.amazon.com/billing/home#/)」の左側にある「Billing > 請求書」から確認できます）





## 最後に
不要な課金をせず、賢く自己投資しましょう！
LARAVEL/PHPでよく使うデバッグ方法

# はじめに

当記事は筆者が**Lravel/PHP**で開発している際によく使う**デバッグ方法**のまとめです。



##dump()

```php:dump.php
    $array = array(1,2,3,'いち','に','さん');
    dump($array);
```

```php:dump.php
array:6 [▼
  0 => 1
  1 => 2
  2 => 3
  3 => "いち"
  4 => "に"
  5 => "さん"
]
```
**dump()**はシンプルに中の情報を表示するだけですね。
なお、処理は止まらずに死にません。

##verdump()

```php:verdump.php
    $array = array(1,2,3,'いち','に','さん');
    var_dump($array);
```

```php:verdump.php
array (size=6)
  0 => int 1
  1 => int 2
  2 => int 3
  3 => string 'いち' (length=6)
  4 => string 'に' (length=3)
  5 => string 'さん' (length=6)
```
**ver_dump()**は**dump()**と違って`型が出力`されます。
なお、こちらも処理は止まらず死にません。
##dd()
```php:dd.php
    $array = array(1,2,3,'いち','に','さん');
    dd($array);
```

```php:dd.php
array:6 [▼
  0 => 1
  1 => 2
  2 => 3
  3 => "いち"
  4 => "に"
  5 => "さん"
]
```
一見**dump()**と似ていますが、**dd()**は処理の実行が止まって死んでいます。
要するにdd()関数がある行以降の処理は行われません。

下記の例でいうと、2行目で処理が止まっているため、三行目が実行されることはありません。

```php:dd.php
            $array = array(1,2,3,'いち','に','さん');
            dd($array);
            array_push($array, 'よん');//←実行されない。
```   
dd()とは**dump and die** の略です。

###Debugbar
実務でもよく使うのがDebugbarだと思います。
特にAJAXなどを利用して内部のAPIを使う場合は**dump()**や**dd()**が使えないので重宝します。

導入に関しては下記記事を参照してください。

[Laravel5.7: Laravel Debugbarを使う](https://qiita.com/sutara79/items/9fd442a81001842aeba1)

```php:Debugbar.php
    public function store(Request $request)
    {
        $like = new Like;
        \Debugbar::info(1);
        $like->user_id = $request->user;
        \Debugbar::info(2);
        $like->post_id = $request->post;
        \Debugbar::info(3);
        \Debugbar::info($like);
        $like->save();

        return;
    }
```

```
info
1
info
2
info
3
info
App\Like {#322 ▶}
```

1,2,3は処理がどこまで実行されているか確認するためのtipsです。
4つ目のinfoで$likeの情報が取得できましたね。

#viewはどうしたらいいの？
Viewに関してはテンプレートエンジンの仕様を確かめてみてください。
筆者が利用しているBladeではphpディレクティブ（@php）が利用できました。

```php:debug.php
@php
    Debugbar::info(1);
    dump(1);
    ver_dump(1);
    dd(1);
@endphp  
```

#終わりに

この四つさえ知っとけば、デバッグ作業で困ることはないと思います（多分）。
FullCalendarをRailsに導入

#FullCalendarについて
カレンダー機能付きのアプリを作りたく調べてみました。
こんな感じのが出来ます。
![UNADJUSTEDNONRAW_thumb_9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510412/8117c92b-c245-ff5f-e6ce-1ffcdca7c253.jpeg)

FullCalendarはjQueryのプラグインでrailsに導入する際は、gemで導入しました。
今回はScaffoldを使って簡単なEventモデルを作り、カレンダーに反映出来るところまでやります。

では、
#1.Gemの追加

```Gemfile.
gem 'jquery-rails', '4.3.3'
gem 'fullcalendar-rails'
gem 'momentjs-rails'
```
そして、
`bundle install`
#2.application.jsに記述
```app/assets/javascript/application.js
//= require jquery
//= require moment
//= require fullcalendar

$(function () {
    // 画面遷移を検知
    $(document).on('turbolinks:load', function () {
        // lengthを呼び出すことで、#calendarが存在していた場合はtrueの処理がされ、無い場合はnillを返す
        if ($('#calendar').length) {
            function eventCalendar() {
                return $('#calendar').fullCalendar({
                });
            };
            function clearCalendar() {
                $('#calendar').html('');
            };

            $(document).on('turbolinks:load', function () {
                eventCalendar();
            });
            $(document).on('turbolinks:before-cache', clearCalendar);

            $('#calendar').fullCalendar({
                events: '/events.json'
            });
        }
    });
});
```
一つ目の関数ではFullCalendarの設定を読み込み、二つ目の関数ではFullCalendarを削除します。
その下に呼び出すコードを2行書き最後にイベントを表示させるためのコードを書きます。
その他、説明は少しはしょります。


#3.application.cssに記述
```app/assets/stylesheets/application.css
...
 *= require_tree .
 *= require_self
 *= require fullcalendar
 */
```
これで、あとはviewのerbファイルに
```<div id="calendar"></div>```
と書き込むとカレンダーが表示されます。
#4.イベントを表示する
Fullcalendarにイベントの情報を表示するには、JSONファイルを使ってあげます。
イベントにはタイトル、説明、開始日、終了日が必要です。今回はscaffoldで作りました。
```rails generate scaffold Event title:string description:text start_date:datetime end_date:datetime```
そして、
```rails db:migrate```

JSONを渡すために、Railsのjbuilderというものを使っていきます。scaffoldによってjson.jbuilderファイルが自動で作られています。
以下のコードを追加

```app\views\events\index.json.jbuilder
json.array!(@events) do |event|
  json.extract! event, :id, :title, :description   
  json.start event.start_date   
  json.end event.end_date   
  json.url event_url(event, format: :html) 
end
```
こうすることで、{"id":"1", "title":"タイトル", "description":"説明", "start":"日付1", "end":"日付2", "url":"some_address"}のようにjsonファイルが作られ、カレンダーが読み込めるデータになります。
url項目があることで、カレンダーの予定にurlが埋め込まれ、クリックすると予定の詳細に飛ぶことができます。

現状、ルーティングはこのようになっています。

```routes.rb
Rails.application.routes.draw do
  resources :events
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root 'events#index'
end
```

一旦、これで表示は出来るようになりました。
あとは、カレンダーのオプションで色々触ってみて下さい。

$('#calendar').fullCalendar({ });の{　}内にオプションを加えることで、カレンダーのタイトルをYYYY年MM月のようにしたり、レイアウト、時間の表示を設定できます。

公式ドキュメントには色々な使い方、機能が載っていますので確認してみて下さい。
[FullCalendarの使い方](https://qiita.com/imp555sti/items/ee9809768f6dc9439ab5)
https なサイトを cURL したらメモリリークするから注意

## はじめに

「サーバー監視所(非公式)」は、`cURL`を使用して監視対象に  "https" リクエストを定期的に行うシンプルな死活監視を行うウェブサイトです。

 - [ColorfulBox サーバー監視所(非公式)](https://www.cloudremix.net/colorfulboxstat/)
 - [ConoHa WING サーバー監視所(非公式)](https://www.cloudremix.net/conohawingstat/)
 - [mixhost サーバー監視所(非公式)](https://www.cloudremix.net/mixhoststat/)
 - [エックスサーバー サーバー監視所(非公式)](https://www.cloudremix.net/xserverstat/)

最近この監視を行っているサーバがメモリ枯渇でダウンしました。

## 「NSS」ライブラリが原因

[1044666 - Can curl HTTPS requests make fewer access system calls?](https://bugzilla.redhat.com/show_bug.cgi?id=1044666)

`libcurl`が使用する NSSライブラリ（SSL/TLS通信を行うライブラリ）のバグが原因で、メモリキャッシュが肥大化し、サーバダウンにつながったようです。

対策としては環境変数に`NSS_SDB_USE_CACHE=YES`を設定する必要があるようです。
~~FIXになっているので今後ずっと必要の模様。根本的に修正してほしい~~

具体的には下のコマンドを叩くとよいです。

 - `export NSS_SDB_USE_CACHE=YES`
 - `sudo echo 'NSS_SDB_USE_CACHE=yes' >> /etc/environment`
サクラエディタで重複削除

#サクラエディタで重複削除する方法
DBからデータを取ってきて重複してる分を省きたいってときに便利だなと思った
サクラエディタを使った重複削除の方法です。

###①全選択 Ctrl+A
　まずサクラエディタに重複削除したいデータをコピーあんどペーストです。
　それからCtrlキーとAを同時押しで全データを選択します。
###②並べ替え Alt+A(D)
　全選択したデータを並べ替えます。
　Alt+Aで**昇順**、Alt+Dで**降順**に並べ替えられます。
###③マージ Alt+M
　最後に並べ替えたデータをマージします。
　これで重複削除完了です！
ブロックチェーンの魅力

<h1>■なぜ私がブロックチェーンに魅了されたか？​</h1>

<br>
**「世界を変える力を持っているから」​**

#■概要
今回はブロックチェーンの難しい技術のお話ではなく、
ブロックチェーンの魅力と考え方に着目しました。

#■IT4種の神器
IT4種の神器の中にブロックチェーンが含まれている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164302/8ff03c11-058f-c12b-1439-93419896e717.png)

#■私のブロックチェーンの勝手なイメージ
クラウド・IoT・AIはよく取り上げられることが多く耳にする機会が多いが、ブロックチェーンのことはあまり見かける機会が少ないような気がする。<br>私も正直最近までブロックチェーンに対して疎かった。が、正直ブロックチェーンのことを知らない = 電子レンジの存在を知らないと同等と感じた。
今後の生活・世界を変える力を持つであろうブロックチェーンについてこの場をお借りして少し調べようと思いました。(私にとって電子レンジは生きるための必需品でです。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164302/b0011131-e5de-a768-f456-05728646b4be.png)
※家電の対応は私の勝手なイメージです

#■4種の神器の状況
| 4種の神器 | 主要国| 主要企業 |  主要製品   | 発展日 |
|:-:|:-:|:-:|:-:|:-:|
| クラウド  | アメリカ  | アマゾン<br> マイクロソフト<br>グーグル |  AWS<br>Azure<br>GCP |  2006年頃 |
| IoT  | アメリカ<br>中国<br>ドイツ |  独占企業なし | AppleWatch<br>自動運転自動車  | 1999年頃  |
|  AI |アメリカ<br>中国<br>イギリス | グーグル<br>アップル<br>ソフトバング等  |  自動運転<br>Siri<br>エコー |  2000年頃 |
| ブロックチェーン| 中国<br>エストニア  | 独占企業なし  | ビットコイン<br>Fintech<br>イーサリアム| 2008年頃  |

#■なぜブロックチェーンが誕生したのか
ある特定の企業が世界のお金や私たちの情報を支配している状況にある。
しかし、明らかに特定の企業に偏り過ぎている・本当に我々の情報はしっかり管理されているのか・現在の社会の仕組みを変えたいという思いからブロックチェーンという技術が誕生
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164302/a60f6d35-7b66-8edc-8776-2d73acb81338.png)

#■ブロックチェーンによって生まれる未来
ブロックチェーンによって世界の仕組みを変えることができる。
なぜならば、絶対的で中心的な存在によって管理がされている現在の世界から、
ブロックチェーンによってみんなで世界を管理していこうという思想に変わる。
つまり、上下な関係ではなく平等な関係に世界を変えようとする仕組みがブロックチェーンである。
管理者である国家や企業が存在しない、私たちが見たことない世界の誕生です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164302/72a45b68-f317-1cfb-d8b8-d5db52f1ea9b.png)

#■今後の未来構造
私たちの世界・社会はほとんどが中央集権型で構成されているが、今後は少しずつ分散されたコミュニティが出来上がり、最終的には誰も管理者がいない非中央集権型の世界が訪れるかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164302/f9ebfd08-76b7-c774-f38f-62e08ffb4513.png)

#■まとめ
GAFAのようなある特定の大企業が私たちの情報を管理している現在の世界。

そんな世界観に違和感を感じ登場した技術それが「ブロックチェーン」である。

ブロックチェーンによって強固な管理者は存在せず、自立した世界を作り上げることができる。

私たちが見たことのないような、国家や企業が存在しないような世界が待っているかもしれない。
WiresharkでLuaスプリクトを使うための初期設定

# はじめに

過去にWiresharkでLuaスクリプトを使う記事を書いたにも関わらず導入の仕方には全く触れていなかった。
Wiresharkのバージョンが3.xになった今、改めて導入してみたので備忘録替わりに残しておきます。


# と思ったが

今のバージョンだと**init.luaの設定を弄らずともデフォルトでLuaスプリクトを使えるようになっている**。
なんだこれ、凄いじゃないか。

↓以前はinit.luaのここがfalseになっていたのでtrueに書き換える必要があった(他にも何ヵ所か対応が必要だった)
![lua1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112253/d223a8e5-542c-8be6-e5e8-1161794043ea.png)


今はWiresharkをインストールしたフォルダにあるpluginフォルダに作ったスクリプトを入れるだけで問題なく動く。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112253/5434c945-3a9a-a6bf-fb14-aab80db257b9.png)



# と思ったが

デフォルトのパスでWiresharkをインストールすると`C:\Program Files\`の直下にインストールされてしまい
スクリプトを弄ると権限のアラートがバンバン出る。
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112253/96048329-1c47-1e07-8a81-bb485920e337.png)


`C:\Program Files\`を避けてインストールすれば良いが既にインストールしてある場合はどうするか(~~読み書きの権限を付ければいいじゃない~~)

`C:\Users\[ユーザ名]\AppData\Roaming\Wireshark`にフォルダがあると思うのでここに`pluginsフォルダ`を作り
その中にスクリプトファイルを入れると権限に悩ませられずに作業が出来る。
**あとはこの場所のリンクをデスクトップにでも作って置こう。**

![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112253/f8228209-ba84-9bd5-ffdf-7d923f001e1a.png)
Raspberry PiのwifiのAP/Clientを切り替え 

# 概要

Raspberry Pi 3/4/zero wに搭載されているwifiモジュールは、クライアントとしてwifiに接続することも、アクセスポイント(AP)として他の機器からRaspberry piに接続することもできます。
アクセスポイントとして起動すれば、キーボードやモニタを用意せずにスマホからSSH接続して設定を行うことができます。

ここでは、AP⇔wifiのそれぞれのモードを相互に切り替える手順を記載します。


以前同じ手順を説明する以下の記事を書いたのですが、より適切と思われる手順を確認したので再度投稿しています。

https://qiita.com/yamato225/items/4c17bfdbda6ce57104de

以下、

* wifi=Raspberry Pi以外のアクセスポイント
* AP=Raspberry PiのwifiモジュールをAPとして動作させるもの

という意味で書いています。（若干ニュアンスが不正確ですがご容赦ください）

# セットアップ

今回検証した環境

|項目|内容|
|---|---|
|ハード|Raspberry Pi 4|
|OS|Raspbian GNU/Linux 10 (buster)|

hostapd(APとして動作させるデーモン)とdnsmasq(簡易DHCPサーバ)をインストール。

```bash
sudo apt install hostapd dnsmasq
```

hostapdの設定
APとして動作させる場合の設定を記します。

```:/etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
ssid=<SSID名>
hw_mode=g
channel=6
ieee80211n=1
wmm_enabled=1
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_passphrase=<パスワード>
rsn_pairwise=CCMP
```

dnsmasq(DHCPサーバの設定)


```:/etc/dnsmasq.conf
interface=wlan0
dhcp-range=172.24.1.100,172.24.1.200,255.255.255.0,1h
```

hostapdのサービスを有効化します。ただし、自動起動されたくないので、disableにします。

```
sudo systemctl unmask hostapd
sudo systemctl disable hostapd
```

wpa_supplicantの設定

```:/etc/wpa_supplicant/wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="<wifiのSSID名>"
    psk="<wifiパスワード>"
}
```

この設定をした状態で以下コマンドを実行すると、wifiに接続します。


```
sudo systemctl restart dhcpcd
```

蛇足：
wifiへの接続を行うサービスはwpa_supplicantですが、wpa_supplicantがwifiに接続するよう設定を行っているのはdhcpcdです。
この処理は/lib/dhcpcd/dhcpcd-hooks/10-wpa_supplicantというシェルスクリプトがdhcpcdが起動するとき一緒に起動することで実現されています。

dhcpcd自体はDHCPのクライアントなのに、wifi接続の設定をやっているという、モジュール化という観点で言えば看過し難い設計になっています。

# wifi→APへの切り替え

wpa_supplicantとdhcpcdを停止します。

```
sudo systemctl stop wpa_supplicant
sudo systemctl stop dhcpcd
```

固定IPをipコマンドで設定します。この方法なら設定ファイルを編集せずにすみます。

```
sudo ip addr add 172.24.1.1
sudo ip route add default via 172.24.1.1
```

DHCPサーバを起動します。

```
sudo systemctl start dnsmasq
```

hostapdを起動します。

```
sudo systemctl start hostapd
```

以上でその他の機器から、hostapd.confにて設定したSSIDに対して接続可能となります。


# AP→wifi

hostapdを停止。

```
sudo systemctl stop hostapd
```

dnsmasqを停止

```
sudo systemctl stop dnsmasq
```

固定IP設定を削除

```
sudo ip addr flush dev wlan0
```

wpa_supplicantを起動

```
sudo systemctl start wpa_supplicant
```

dhcpcdを起動

```
sudo systemctl start dhcpcd
```
Android StudioでAPIレベルを下げる

#はじめに
最近とあるプロジェクトに参加しAndroidアプリ開発をしていたのですが，渡されたタブレットで実行しようとしたら，APIが古いよと怒られてしました．解決するまでに色々調べて結構時間がかかったので，今回はその解決方法をメモしておきたいと思います．
今回のアプリ開発ではSonyさんの`Xperia Z4 Tablet SO-05G`のタブレットを使用しました．

##どんなエラーが出たのか？
```
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_OLDER_SDK
The application's minSdkVersion is newer than the device API level.
```
原因としては，デバイスのAPIよりプロジェクトのAPIのほうが新しいからだそう．シンプルにプロジェクトのAPIをデバイスのAPIに合わせて下げれば解決できます．

ちなみに実行時には**Sony SO-05G(minSdk(API 23) > deviceSdk(API 21))**というエラーがデバイス選択欄に書かれていました．

では解決方法を記していきます．

###解決方法
1. Android Studioの上部タブ**File**から**Project Structure**を選択
<img width="240" alt="pj_structure.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495465/fd89bda8-0dc9-9bd0-fc58-753beb17011d.png">

2. **Modules**の上部タブ**Default Config**を選択
3. **Min SDK Version**から指定したいversionを選択
<img width="713" alt="min_sdk.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495465/3e7c8aff-15ef-eb7d-4dbc-dc27bbf5f999.png">
**※ここで注意※**
選択したいAPIがインストールされていない場合は，プルダウンメニューに表示されません．そのためまずは，選択したいAPIのSDKをインストールしなければなりません．次にSDKのインストール方法を記します．

###SDKのインストール方法
1. Android Studioの上部タブ**Tools**から**SDK Manager**を選択
<img width="240" alt="tools.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495465/b227b2ff-8bfc-871c-a5a8-aca000bee94f.png">

2. **Android SDK**の**SDK Platforms**からインストールしたいSDKをチェックし，インストール
<img width="766" alt="sdk_manager.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495465/5f9941a0-71e3-c0db-7239-d8b85becdddc.png">

これで**Min SDK Version**にインストールしたSDKのAPIレベルが表示されるので，選択することが可能になります．

#最後に
以上がAPIレベルの下げ方になります．ぱっと見簡単そうに見えるけど，解決するまでに結構時間を食っちゃいました．同じところで躓いている人がいたら参考にしてみてください．環境設定が得意になりたい．
Next.jsをGCP Cloud Run上で実行する方法

Next.jsのチュートリアルをGCP Cloud Run上で動かすための方法をメモ。

# 概要
0. Next.JSの6 fetching dataチュートリアルをやる
1. Docker 化する
2. Cloud Container Registryにpushする
3. Cloud Runにdeployする
4. アクセスして動ていることを確認

# next.jsのtutorialをcloneする

```bash
git clone https://github.com/zeit/next-learn-demo.git
```

# Tutorialをやる
今回はserverless設定を試したかったので、`6-fetching-data`を使います。

```bash
cd next-learn-demo/6-fetching-data
```

Tutorial自体は下記を見ながらやってください。
https://nextjs.org/learn/basics/fetching-data-for-pages

詳細の説明は省きますが、映画情報APIから情報をとってきて成形するチュートリアルになってます。

# Docker化する
手元の環境に合わせてnode12でDokcerコンテナを作ります。

```Dockerfile:Dockerfile
FROM node:12.16.1-alpine

WORKDIR /app

ENV PATH /app/node_modules/.bin:$PATH

COPY . .
RUN npm install && npm run build

# start app
CMD [ "npm", "run", "start" ]
```

# Cloud Run用に公開するポートを指定する
Cloud Runは`PORT`環境変数が公開されることを期待するので、package.jsonを書き換えます。
`"start": "next start -p ${PORT}"`がミソ。

```json:package.json
{
  "name": "hello-next",
  "version": "1.0.0",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start -p ${PORT}"
  },
  "license": "ISC",
  "dependencies": {
    "isomorphic-unfetch": "^3.0.0",
    "next": "latest",
    "react": "^16.12.0",
    "react-dom": "^16.12.0"
  }
}
```

ここで、いったんちゃんと動くか試しておくと良さそうです。
shusaku-next-cloudrunは適当な名前なので好きな名前を付けてください。

```bash
docker build . -t shusaku-next-cloudrun:latest
PORT=8080 docker run -p8080:${PORT} shusaku-next-cloudrun
```

localhost:8080にアクセスしてレスポンスがあればOKです。

# Cloud Registryへ登録
Buildしたdockerにtagを打って、Cloud Registryへ登録します。google cloud sdkはインストールしておいてください。

```bash
docker tag shusaku-next-cloudrun gcr.io/${PROJECT_NAME}/shusaku-next-cloudrun:latest
docker push gcr.io/${PROJECT_NAME}/shusaku-next-cloudrun:latest
```

# Cloud Runへdeploy

この時いくつかコツがあります。

-  --allow-unauthenticated を付けておくと、デプロイした後に振られたURLで動作確認できます。
- --projectはなくても動きますが、複数のprojectをgcloudコマンドで使っていると、defaultのconfigを読みに行ってしまってうまくいきません
- 初めて実行する場合は、認証情報に関するエラーが出るので `gcloud auth configure-docker`を実行する必要があるかも。

```bash
gcloud beta run deploy --image gcr.io/${PROJECT_NAME}/shusaku-next-cloudrun --project ${PROJECT_NAME} --platform managed --allow-unauthenticated
```

# Browserからアクセス

URLが最後表示されるのでそこからアクセスしたらOK