OmniAICreator/Qiita-1.07M huggingface dataset:
【AWS】VPCの概要を解説します。no.6

![AWS (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/0d505d63-309f-cb5a-0366-615ba03e08b8.png)
こんにちは。まゆみです。

AWSについての記事をシリーズで書いています。

今回は第6回目になります。

今回と次回の記事を使って、<font color="Red">AWSサービスを動かしている仕組みの概要</font>について説明していきます。

どんな仕組みになっているのか大局を見てから、細かな部分を解説していきますね。

今回は、 <font color="Red">AWSのVPCについての概要</font>を書いていきます。

ではさっそく始めていきますね。

#VPCとは？
![AWS (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/380c0299-b219-4cb6-dfc3-4ed25f361dee.png)

VPCとは、より大きなネットワーク(AWS)の中に作るプライベートネットワーク(Virtual Private Cloud)のことです。

このVPC内に、AWSのリソースであるEC2やデータベース等々...を配置することができ、それらをあなた自身がコントロールすることができます。


身近な例でイメージしやすい物で言えば、例えばInstagram やFacebook。

より大きなネットワークの中に、あなたのページを作り

>写真や動画を投稿したり

>削除したり

>アクセスをコントロールしたり

することができますよね。

そしてそのあなたのページ内に置いては完全にコントロール権を持つことになります。


それと同じように、<font color="Red">AWSではあなた自身のプライベートネットワーク(VPC)を作る</font>ことができます。

また、後述するネットワークセキュリティについて、『subnet』という用語もでてくるので、ここでsubnetの説明を軽くしておきますね。

subnetとは、あるネットワークのなかのサブセクションになります。

VPCの中にさらに作るネットワークがsubnetになります

![スクリーンショット 2021-05-01 093435.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/6cd62b28-ad9a-468a-86ac-ed9087a85b3e.jpeg)
引用元：[Amazon Virtual Private Cloudユーザーガイド](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Subnets.html)

#ネットワークセキュリティについて

subnet レベルと、EC2インスタンスレベルにおいて、ファイアーウォールを設定する事ができます。

![ファイアーウォールって何？.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/8899b2df-58c1-7105-5f86-4b29bca12ccf.png)


>ファイアウォール（英: Firewall）は、コンピュータネットワークにおいて、ネットワークの結節点となる場所に設けて、コンピュータセキュリティ上の理由、あるいはその他[注釈 1]の理由により「通過させてはいけない通信」を阻止するシステムを指す。[Wikipediaより引用](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB)


ファイアーウォールを身近な例えで言えば、

>手紙・メールは受けてもらえるが

>実際に会うことはできない

など、<font color="Red">受けることができるものと、受けることができないことを設定する</font>事です。

上記の例で言えば、あなたに物理的に会えないようにしている門番が『ファイアーウォール』であり、手紙・メール・実際に会いにいくと言った、手段がプロトコールとして例えることができます


![No.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/6dcfe9b2-678f-0f01-f94d-35a3c1c6cc5c.png)


そのようなファイアーウォールを

>サブネットレベルで設置するのが『Network Access Control　Lists(ACL)』

>EC2(インスタンス)レベルで設置するのが『Security Group(SG)』


になります。


#まとめ
VPCの概要はこれくらいで締めくくらせていただきます。

次回の記事では、EC2についてのざっくりした内容を書いていきますね。

その後、VPCやEC2の細かな内容を書いていきます
DatadogによるDatabricksクラスター監視

[Databricksにおけるクラスター管理](https://qiita.com/taka_yayoi/items/991aae376c089df58504#datadog%E3%81%AE%E3%83%A1%E3%83%88%E3%83%AA%E3%82%AF%E3%82%B9)で触れているように、Sparkクラスターのメトリクスやログ情報をDatadogで監視することができます。

サンプルノートブックは[こちら](https://github.com/taka-yayoi/public_repo/tree/main/datadog)です。

# Datadog APIの取得

[Datadog](https://www.datadoghq.com/)でアカウントを作成し、APIキーを取得します。以下の画面の`DD_API_KEY=`以降がAPIキーです。
![](https://sajpstorage.blob.core.windows.net/demo20210501-datadog/get-API-key.png)

# init scriptの作成

DBFS上にinit scriptを作成するので、サンプルノートブックのセルの4行目の`<init-script-folder>`に格納先を指定してください。

```python
dbutils.fs.put("dbfs:/<init-script-folder>/datadog-install-driver-workers.sh","""
```

ノートブックのセルを実行して`datadog-install-driver-workers.sh`を作成します。

> **注意**
デフォルトではログが出力されないので、`echo "logs_enabled: true" >> /etc/datadog-agent/datadog.yaml`でログを有効化する必要があります([サンプルノートブック](https://github.com/taka-yayoi/public_repo/tree/main/datadog)の31行目)。

# init scriptの設定

クラスターのinit scriptとして、`datadog-install-driver-workers.sh`を指定します。
![](https://sajpstorage.blob.core.windows.net/demo20210501-datadog/set-init-script.png)

クラスターの**Advanced Options**の**Spark > Environment Variables**にDatadogのAPIキーを、`DD_API_KEY=<your-api-key>`の形式で指定します。
![](https://sajpstorage.blob.core.windows.net/demo20210501-datadog/Env.png)

# クラスターの起動

クラスターの起動に合わせてエージェントが起動し、Datadogにメトリクスとログが送信されます。
![](https://sajpstorage.blob.core.windows.net/demo20210501-datadog/Dashboards.png)
![](https://sajpstorage.blob.core.windows.net/demo20210501-datadog/Datadog-logs.png)

# サンプルノートブック

- [Datadogによるクラスター監視](https://github.com/taka-yayoi/public_repo/tree/main/datadog)

# 参考情報

**Databricks参考情報**
- [Manage clusters \| Databricks on AWS](https://docs.databricks.com/clusters/clusters-manage.html#view-cluster-logs)
- [Apache Spark Cluster Monitoring with Databricks and Datadog \- The Databricks Blog](https://databricks.com/blog/2017/06/01/apache-spark-cluster-monitoring-with-databricks-and-datadog.html)

**Datadog参考情報**
- [Databricks](https://docs.datadoghq.com/integrations/databricks/?tab=driveronly)
- 最新のinit scriptはこちらから取得できます。 [Spark](https://docs.datadoghq.com/integrations/spark/?tab=host)

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
whereの使い方

whereの使い方
-

|■whereの基本形|
|--|

```rb
モデル名.where(カラム名: 値)」
User.where(age: 20)
```

「Userテーブルの中でageカラムが20のレコードを検索」という意味になります。
※複数ヒットすれば複数のレコードを返します。なお、ヒットするidのレコードが見つからない場合は、ActiveRecord_Relationクラスの空配列を返します。

条件の指定（最初のヒットデータ）
-

```rb
モデル名.where(カラム名: 値).first」
User.where(age: 20).first
```

条件の指定（最後のヒットデータ）
-

```rb
モデル名.where(カラム名: 値).last」
User.where(age: 20).last
```

条件の指定（選んで取り出す２）
-

```rb
モデル名.where(カラム名: 値).offset 整数」
User.where(age: 20).offset 5
```

20才のデータを1から５番目までは飛ばして６番目から取り出す

条件の指定（選んで取り出す）
-

```rb
モデル名.where(カラム名: 値).limit 整数」
User.where(age: 20).limit 5
```

20才のデータを５つ取り出す

条件の指定（並び順）
-

```rb
モデル名.where(カラム名: 値).order(asc/desc)」
User.where(age: 20).order(asc)
```

|asc|小さいものから順に並べる|
|--|--|
|desc|大きいものから順に並べる|

条件の複数指定（AND検索）
-

```rb
#whereの引数には、複数の条件を指定することができます。 
User.where(age: 20, sex: 'male', payment: true)
```

上記は「Userテーブルの中でageが20かつsexがmaleかつpaymentがtrueのレコードを検索」という意味になります。

|and|論理積と呼ばれ、両方がtrueならtrueを返す|
|--|--|
|falsならor|論理和と呼ばれ、両方ともfalseならfalseあとは成り立てばtrueを返す|
|xor|排他的論理和。両方が異なる値ならtrue、異なるならfalseを返す|
|not|これはこれまでのものと違いnotの後に値を指定するだけ。trueならfalseを示す|

LIKEであいまい検索
-

```rb
#Stringのカラムを指定する場合、指定した文字列を含むレコードを検索することができます。
User.where('email like ?', '%@gmail.com%')
```

上記は「Userテーブルの中でemailに@gmail.comが含まれるレコードを検索」という意味になります。

|%|任意の0文字以上の文字列|
|--|--|
|_|任意の1文字|

ORでいずれかを含む検索
-

```rb
#whereの後に.orをつけることで、条件1または条件2に該当のような検索ができます。※Rails5からの機能です
User.where(family_name: '山田').or(User.where(first_name: '太郎'))
```

「Userテーブルの中でfamily_nameが山田またはfirst_nameが太郎のレコードを検索」という意味になります。

NOTで否定検索
-

```rb
whereの後に.notをつけることで、条件に当てはまらないレコードを返すようになります。
User.where.not(status: 'reject')
```

「Userテーブルの中でstatusがreject以外のレコードを検索」という意味になります。

whereの使い方まとめ
-

|基本の条件指定|【モデル.where(カラム名: 値)】|
|--|--|
|AND検索|【モデル.where(カラム名1: 値1, カラム名2: 値2)】|
|あいまい検索|【モデル.where('カラム名 like ?', %値%)】|
|否定検索|【モデル.where.not(カラム名: 値)】|
rbenv で欲しいバージョンがない

# rbenvでインストール可能なrubyバージョン確認

```
% rbenv install -l
2.6.7
2.7.3
3.0.1
```

ver2.7.1が欲しいのだが、ない。

# rbenv をアップデートしてみる

https://qiita.com/_am_/items/c1dbeb11f40bbbac8fd9
↑こちらの記事を参考。
欲しいバージョンがないときはアップデートするように書いてある。

下記実行

```
$ brew update
$ brew upgrade rbenv ruby-build
```

結果：
変わらず。

```
% rbenv install -l
2.6.7
2.7.3
3.0.1
```

# インストールしてみる

下記実行

```
% rbenv install 2.7.1
```

結果:

インストール出来た。

# 結論

`rbenv install -l`に直接書いてなくても、最新のものより前のバージョンなら、DLできるっぽい。
たった3日で手軽に始める高コスパSwift入門

私はMENTAでSwiftやNext.js(React)・Firebaseなどを中心にプログラミングを教えております。
そこで、初心者の方にいつもオススメしている市販の参考書を使った学習方法について紹介致します。

教材選び、これはとても難しい問題です。
良い教材があったとしても時間が経つと、内容が古くなり悪い教材になってしまう場合もあります。

また、どれが良い本かというのも初学者だからこそ判断がつきにくいと思います。
この記事では、書店で実際にいくつか比較した２冊のおすすめ書籍を紹介いします。

この記事だけではなく、常に情報が何月何日に書かれたものかかなり気にしてください。
鮮度が悪いジャンルでは1年以内が望ましく、2年で限界ぐらいで考えても良さそうです。

Swiftに関わらず「文法書と応用書」この2冊以上の組み合わせで勉強するのが良いと考えています。
そのあと、すぐに何かを作ってみるというステップを私はオススメしています。

## 文法書

とっつきやすさという点で、こちらの書籍をオススメします。
※ 7-9章は応用でゲームを作る章なのでスキップしても良いかなと思います

[たった1日で基本が身に付く! Swift アプリ開発 超入門](https://gihyo.jp/book/2019/978-4-297-10480-1)

## 応用書

たった2日でマスターできるiPhoneアプリ開発集中講座シリーズをオススメします。

[SwiftUI対応 たった2日でマスターできるiPhoneアプリ開発集中講座 Xcode 12/iOS 14対応](https://ticklecode.com/swiftbook2020/)
[たった2日でマスターできるiPhoneアプリ開発集中講座 Xcode 11　Swift 5対応](https://ticklecode.com/swiftbook2019/)

最新版は、Xcode12と書いてある前者です。
ただ、SwiftUIで書いてある点が悩みどころなんですね...

賛美両論あるところではあると思われますが
SwiftUIは発展途上であるため
いまSwiftUIに関する部分を初学でやるというのが
素直におすすめできないと考えております。

そのため、控えめに後者のXcode11版をオススメします。

ただし、古いので読み替えないといけない部分がある可能性があり
そこは苦労する可能性があります。

## でも教科書でハマってしまったら？

市販の参考書＋ハマったら質問、これがおそらく高コスパを実現します。
MENTAなどのご利用をおすすめします。
私もプランを公開しています。

https://menta.work/?nic=owAl5EbX7N3uIo7i&ref=ni
https://menta.work/plan/88

## 教科書が終わったら？

なにか作ってみましょう！
企画が思いつかなければ誰かに相談してみましょう。
こちらもCodeQAが活用できますよ。
JavaScriptで数当てゲームを作りました

Javascript、HTML/CSSで数当てゲームを作りました。

ルール
・1から50までの数字を入力し、5回以内に正解の数を当てるゲームです。
プログラミングコード

```HTML
<!-- 数当てゲーム-->
<!-- 新規作成 2021/04/30 -->
<!-- author 乃木坂好きのITエンジニア -->
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>数当てゲーム</title>
<style>
    h1 {
        color:plum;
        font-size:100px;
    }
    h2 {
        color:#4f7911;
        font-size:50px;
    }
    body {
        background-color:whitesmoke;
    }
</style>
</head>
<body id = "test">
<header>
<div class="container">
<h1>数当てゲーム</h1>
<h2>数を当ててみよう</h2>
</div><!-- /.container -->
</header>
<main>
<div class="container">
<section>
    
</section>
</div><!-- /.container -->
</main>
<footer>
<div class="container">
</div><!-- /.container -->
</footer>
<script>
'use strict';
let message;
let count = 1;
let flag = 0;
//乱数を発生させる。0~49まで数字がランダムに表示されるので1を足す。
const number = Math.floor(Math.random() * 50) + 1;
//数当てゲームは5回挑戦できるようにする。
while (count <=5){ 
    const answer = parseInt(window.prompt('数当てゲーム。1〜50の数字を入力してね。5回まで挑戦できます'));
    window.alert(count + "回目です。")
    //正解、数が小さい、数が大きい、1から50以外の数字が入った時の条件式
    if(answer === number) {
        message = 'あたり！';
        window.prompt(count + "回目で正解しました。おめでとうございます!");
        document.querySelector("h1").innerHTML = "<h1>数当てゲーム、正解です!</h1>";
        document.querySelector("h2").innerHTML = "<h2>おめでとうございます！</h2>";
        flag = 1;
        break;
    } else if((answer < number) && (answer >= 1)) {
        message = '残念でした！もっと大きい';
    } else if((answer > number) && (answer <=50)) {
        message = '残念でした！もっと小さい';
    } else {
        message = '1〜50の数字を入力してね。';
    }
    //入力した数字に応じてメッセージを出力する。
    window.alert(message);
    //
    count = count + 1;
}
//5回挑戦して不正解だったら正解をアラートで表示する
if (flag === 0){
    window.alert("正解は" + number + "です");
}         
</script>
</body>
</html>
```

本来ならCSSとスクリプトファイルは別のほうが良いのですが、今回はまとめて1ファイルで作成いたしました。
[備忘録]ConoHa VPSでLaravel使おうとしたらDBがつながらなかった件

## 該当ケース
- ConoHa VPSでサーバー稼働。イメージタイプ「Laravel」で起動。
- Laravelでデータベースを利用。.envにてDB_HOST=localhost、DB_USERNAME=root、DB_PASSWORD=デフォルトのパスワード
- マイグレーションは動く
- Modelを経由して動かそうとすると、「[HY000] [1698] Access denied for user 'root'@'localhost'」となる

## ポイント
- マイグレーションは動いた = usernameやパスワードはあってるはず　→　DBは大丈夫と思った
- Laravel側の設定のほうがどちらかといえば経験が少なかったので、なんか変なことしたかな？と思った
- デバッグするとPDOの接続でコケる　→　マイグレーションは動いているのになんでだ…と無限ループ

## 結果
コンソールからDBにログインし、
select user,host,password from mysql.user;
とすると、passwordがinvalidになってました。

どうやらこのケースはパスワード再設定するといけるっぽいので、
SET PASSWORD FOR root@localhost=password('パスワード');
としました。

結果、動くようになりました。


## 一言
ちなみにこれで4時間無駄にしました。
Rangeクラスのオブジェクトの指定

Rangeクラスのオブジェクトの指定にはリテラル記法を用います。

|n..m|n以上m以下の範囲|
|--|--|
|n...m|n上m未満の範囲|

>公式リファレンスも役に立ちます：class Range (Ruby 3.0.0 リファレンスマニュアル)
>https://docs.ruby-lang.org/ja/3.0.0/class/Range.html
MQL4によるFXの最適ストラテジーの検証

#はじめに

4月からFXやCFDで最適なストラテジーを検証する、という一風変わった依頼を受けることになりました。
一般に、FXや短期の株取引はゼロ和ゲームと言われていますが、本当のところはどうなのか調べたことはなかったので、検証する良い機会だと思い、MQL4でストラテジー毎の成績を調べてみた次第です。
なお、AI は未使用です。

#ストラテジーの構築

### この稿での「ストラテジー」とは

まずは用語の定義から。
この稿における「ストラテジー」とは、以下の一覧の操作をルール化したものを言います。

* あるルールに従って買い、または売りポジションを持つ。
* 損切りルールを満たしたら、持っているポジションを全て解消する。
* 一定のルールを満たしたら、持っているポジションを全て解消する。

3番目のルールは損切りになることもありますし、利確になることもあります。

### ATR(Average True Range)と掛け金

```
TR = min(高値-安値, 前日終値-安値, 高値-前日安値)
```
と定義します。TRの20周期指数平滑移動平均を ATR として定義します。
1回の掛け金は ATR の逆数に比例するように決定します。すなわち、値幅がある場合は小さく、値幅が小さい場合は大きくベットします。VIX 指数の逆数と正の相関があるように賭けていることになります。

### 勝率とプロフィット・ロス
勝率、およびプロフィット・ロスを次式で導入します。

```
win_lose = 勝ちトレード回数 / 総トレード数
profit_loss = 勝ちトレードの利益 - 負けトレードの損失
```

win_lose が大きくても profit_loss が負の場合がありえます。なるべく profit_loss が大きくなるストラテジーを探ることが課題となります。

### 新高値ブレーク・新安値ブレーク

過去何周期かの高値を突き抜けた場合を新高値ブレーク、逆に何周期かの安値を突き抜けた場合を新安値ブレークと呼びます。

### 標準ストラテジー

お疲れ様でした。ようやく「標準ストラテジー」定義することができます。FX, CFD で巷間で囁かれているストラテジーは以下のようなものです。

* Xb周期新高値ブレークならば買いポジションを持つ。Xs周期新安値ブレークならば売りポジションを持つ。
* 順張り方向に Na * ATR 動いたら買い増しする。数量は当初のポジションと同じ。
* Nl * ATR 逆方向に動いたら全ポジションを損切りする。
* Yb周期新安値ブレークなら買いポジション解消。Ys周期新高値ブレークならば売りポジション解消。

### デッドクロス

一般に買いよりも売りの方が足が速いことから、買いは新高値で行い、売りはデッドクロスで行う方法が考えられます。

# 4つのストラテジー

今回検証するにあたり、4つのストラテジーを用意しました。

|ストラテジー名|内容|
|---|---|
|標準ストラテジー|上記説明の通り|
|売りポジションデッドクロス|売りポジションの決定のみデッドクロスを採用|
|全てデッドクロス|全ての売りでデッドクロスを採用|
|Xs2周期新安値ブレーク|Xs2(<Xs)新安値ブレークで売り|

# バックテスト

2021/4/1 から 2021/4/28 までの15分足で検証を行いました。
MT4は最小チックで検証しますが、計算量が膨大になってしまうため、1時間ごとに各ストラテジーが与えるプロフィット・ロスを算出しました。ストラテジーの計算期間は過去90周期としました。

各ストラテジー計算において、当初はポジションを持っていないと仮定します。本当はこの仮定は正しくないのですが、修正しようとするとかなりプログラムが煩雑化するので諦めました。結果は第1近似にはなると思います。
初期費用は 1000 万円とし、1時間ごとに最適と思えるストラテジーを選択し、資金がどれだけ減るか（増えるか）観察します。

なお、ADX および +DI, -DI 両方が 25 以下の時はトレードしない、という機能を実装しています。

|通貨ペア|結果|
|---|---|
|USDJPY|もっとも儲かった通貨ペア。標準シナリオの圧勝。|
|EURJPY|ドローダウン3割を記録し、もっとも成績が悪い通貨ペア。デッドクロスが有効。|
|GBPJPY|可もなく不可もなしと言う感じ。標準シナリオ優勢。|
|EURUSD|USDJPYに続いて2番目に儲かった通貨ペア。標準シナリオ優勢。|

本当は原油 CFD や金 CFD でもやってみたかったのですが、楽天 FX さんは5月からサービス提供開始と言うことなので、開始されたら検証項目に追加してみようと思います。

# おわりに

結果を見ると伝統的な標準ストラテジーが意外に健闘していることが分かります。
EUCJPY だけはストラテジーが全て裏目に出てボロボロになります。

相場は一般に以下の様相に分かれると考えられています。

* 取引及び方向性がほとんど振れない「なぎ」の時期
* 参加者が多く、方向性がない「カオス」の時期
* 何らかのニュースが出て一方向に動く「トレンド」の時期

MQL4 には外部プログラムとの連携機能があるようなので（@amenbo さんの [AI「scikit-learn」によるFXテクニカル分析をやってみた](https://qiita.com/amenbo/items/71e93cfb7642c0945b40) 参照）、各様相を AI に学習させてトレンド時期だけトレードするようにすると面白いのではないかと思います。
PostmanでGmailを取得する

# 目的
PostmanでGmailを取得したい。

# 手順
##### 1. [Google Cloud Platfrom](https://console.cloud.google.com/?hl=ja)にアクセスし、Gmail APIを選択する
![step1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/b1e1d963-a31d-161e-d700-1040dfc526cc.jpeg)

##### 2. Gmail APIを有効にする
![step2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/547b6bd2-0ad4-2b85-51b8-74cf29cbe578.jpeg)
 
##### 3. OAuth クライアントを取得する
1. 「認証情報を作成＞OAuth クライアント ID」を選択する
![step3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/1198a8d0-2ffb-dddc-bf88-181c078dbdb1.jpeg)
2. 「OAuth クライアント IDの作成」画面で、以下の内容を選択し「作成」ボタンをクリックする

・アプリケーションの種類：ウェブアプリケーション
・承認済みのリダイレクト URI: https://oauth.pstmn.io/v1/callback
![step3-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/b53798fd-fc13-72e1-db6e-2feca8c9064b.jpeg)
3. OAuthクライアントのクライアントIDとクライアントシークレットをコピーしてメモ帳に控える
![step3-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/81b19416-011a-6fd8-8637-9faaaca1f28f.jpeg)

##### 4. Postmanを起動し、新規コレクションを作成する
まず、サンプルとして[users.getProfile](https://developers.google.com/gmail/api/reference/rest/v1/users/getProfile)リクエストを叩いてみる。
以下のようなレスポンスが返ってくれば成功：

```json:sample.json
{
  "emailAddress": string,
  "messagesTotal": integer,
  "threadsTotal": integer,
  "historyId": string
}
```

![step4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/5fcda52b-e4f2-cafd-39fa-a6c433040759.jpeg)

##### 5. 認証情報を設定する
1. Authorizationタブを開き、TypeをOAuth 2.0で選択する
![step5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/1c271945-b0a1-327a-4aea-fe1ed3952439.jpeg)

2. Access Tokenを取得する
「Configure New Token」に以下の内容を入力し、「Get New Access Token」ボタンをクリックする。
ブラウザが起動し、「許可しますか」的な画面が表示されるので許可すると、Access Tokenを取得できる

| 項目 | 値 |
|:-----------|:------------|
| Grant Type | なんでもよい |
| Callback URL | 「Authorize using browser」にチェックを付与する |
| Auth URL | https://accounts.google.com/o/oauth2/v2/auth |
| Client ID | メモ帳に控えたもの|
| Client Secret | メモ帳に控えたもの |
| Scope | https://mail.google.com/ (ほかのAPIを叩く場合は[APIドキュメント](https://developers.google.com/gmail/api/reference/rest/v1/users/getProfile)のAuthorization Scopesの記載に従って適宜入力すること) |
| State | 空欄 |
| Client Authentication | send client cledentials in body |
![step5-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/5aacdd90-61a5-8498-89bf-248d3271288f.jpeg)

##### 6. リクエストを実行する
画面右上の「Send」ボタンをクリックするとリクエストが実行される。
ドキュメント通りのレスポンスが返ってくればOK
![step6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/b12c740c-87e3-10fd-7c9a-fedb6411a5c3.jpeg)

##### オマケ：メール一覧を取得し、最新のメールの詳細を取得する
おまけっていうかこっちが本題なんだけど、どちらかというと知りたかったのはstep1-6の流れなので、まぁオマケといえばおまけだと思う。
GitHubにCollectionファイル置いておくので、興味あればどうぞ（[リポジトリ](https://github.com/hideshis/gmail_api_sample/tree/main)）。
![step_omake.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/1b9f9fff-90bb-bd23-0c1c-16d501aba139.jpeg)
HTTPS通信でアクセス ハンズオン

##HTTPS通信
HTTPと比べてHTTPSは通信が**暗号化**されており、第三者によって通信の中身を見ようとしても見れず、セキュリティ対策となり個人情報が守られます。
他にも、ページの表示速度が速くなるといったメリットもあります。

##準備
・EC2,RDSが起動していること
・[前回のハンズオンで作成したブログ](https://qiita.com/tr76aquarius/items/721bfa5aa04fb0b0fa9e)がドメイン名で正常にアクセスできること

###AWS Certificate Manager(ACM)とは
https通信をするのに証明書が必要だが、このサービスは証明書を管理できるサービス
AWSで無料の証明書を作成して、ELBにアタッチをすることでクライアントはhttps通信が可能となります。

![ハンズオン5.005.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207512/2de3a597-2972-300b-3611-a98419748795.jpeg)

利用する際は、

・通信を受け付ける設定でhttpsを追加、
・ELBのセキュリティグループでhttps通信を許可する設定が必要です

---

###ロードバランサーでリスナーを追加
**リスナー**・・・通信を受け付けるポートの許可設定のこと

EC2< ロードバランシング< ロードバランサー< タブにあるリスナーからリスナーを追加を選択

プロトコル:ポートに
HTTPSを選択
転送先にターゲットグループ(TG-1)を選択
新しいACM証明書をリクエストを選択

ドメイン名の追加フォームでドメイン名にblog.aws-demo.gaを入力して次へを選択
検証方法の選択とは、証明書を発行するにあたって、本人確認のようなものが必要で方法が2種類あります
1, DNSの検証　（←今回はこちらを選択)
2, Eメールの検証

タグの追加では証明書のタグを作成できます。

確認画面の後、確定とリクエストを選択

検証方法はRoute53でのレコードの作成というところでCNAMEのDNSレコードを作成したRoute53のポストゾーンに追加する
検証状態が準備完了となればOK

ボタンで自動的にレコードが作成されて追加される

Route53の画面に切り替え、更新してみると
今回検証用のDNSレコードが自動的に追加されていることが確認できます。

ELBのリスナー追加フォーム画面に戻り、デフォルトのSSL証明書に、先ほど作成したACMが選択項目にあがる
保存を選択して成功ELBはHTTPS通信を受け付けられるようになります。

##セキュリティグループの設定
現状HTTP通信しか受け付けられないので設定を変更します
EC2< ネットワーク＆セキュリティ< セキュリティグループを開く
ロードバランサー用に作成したセキュリティグループを選択後、インバウンドルールを編集を選択します

インバウンドルール< ルールを追加を選択
タイプ< プロトコルの選択フォームでHTTPSを選択、
ソース元(通信してくる元)は0.0.0.0/0(全て)でルールを保存を選択

以上でHTTPS通信の設定は完了

##補足1: httpsでwordpressを閲覧する
wordpressの表示の仕様により表示が崩れます。(注: wordpressの詳しいことは分かりません)

```console
# EC2にsshで接続します
ssh -i キーペアファイル名 ec2-user@パブリックIPアドレス

# 接続したら今回は権限をroot権限に切り替えておきます
sudo su -

# ディレクトリ移動 & 内部確認
cd /var/www/html/
ll

# viコマンドでwp-config.phpを編集
vi wp-config.php
```


```wp-config.php
...
if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $_SERVER['HTTPS'] = 'on';
  $_ENV['HTTPS'] = 'on';
}

/* ↑にコードを貼り付ける */
/* 編集が必要なのはここまでですと書かれた行があります　~~ */
```
この作業を別に稼働しているEC2にもログインしてコードの貼り付けを行います。

##補足2: セキュリティ面向上
動作確認の都合上同時に行わなかったが、
このままだとロードバランサーがHTTP通信を受け付ける状態なので設定を削除していきます
EC2< セキュリティグループ< インバウンドルールを編集を選択
HTTP通信を削除し、ルールを保存します。

続いてリスナーの設定
ロードバランサーの画面< リスナー
HTTPの方を選択し、削除を行う

以上で完了

##
##参考・注意
この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。
https://aws-cloud-tech.com 

このハンズオンでは料金が約10〜11円/時間かかります。
sketchupでruby その18

# 概要

sketchupでrubyやってみた。
練習問題やってみた。

# 練習問題

面だけで、球を作れ。


# 写真

![tama.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a8bc3351-0003-d0b4-6cb6-387f759bfeca.png)

# サンプルコード

```

def tama
   p1 = Geom::Point3d.new 0, 0, 0
   p2 = Geom::Point3d.new 10, 10, 10
   entities = Sketchup.active_model.entities
   radius = p2.distance(p1)
   dtheta = dphi = 360.0 / 16
   -90.step(90, dtheta) do |theta|
      0.step(360, dphi) do |phi|
         group = entities.add_group
         pts = []
         x = radius * Math::cos(theta.degrees) * Math::cos(phi.degrees)
         y = radius * Math::cos(theta.degrees) * Math::sin(phi.degrees)
         z = radius * Math::sin(theta.degrees)
         pts << (p1 + [x, y, z])
         x = radius * Math::cos((theta + dtheta).degrees) * Math::cos(phi.degrees)
         y = radius * Math::cos((theta + dtheta).degrees) * Math::sin(phi.degrees)
         z = radius * Math::sin((theta + dtheta).degrees)
         pts << (p1 + [x, y, z])
         x = radius * Math::cos((theta + dtheta).degrees) * Math::cos((phi + dphi).degrees)
         y = radius * Math::cos((theta + dtheta).degrees) * Math::sin((phi + dphi).degrees)
         z = radius * Math::sin((theta + dtheta).degrees)
         pts << (p1 + [x, y, z])
         if theta > -90 && theta < 90
            x = radius * Math::cos(theta.degrees) * Math::cos((phi + dphi).degrees)
            y = radius * Math::cos(theta.degrees) * Math::sin((phi + dphi).degrees)
            z = radius * Math::sin(theta.degrees)
            pts << (p1 + [x, y, z])
         end
         begin
            group.entities.add_face pts
            rescue
         end
      end
   end
end

```

以上。
PlatformIO + VSCode のショートカットキー


- `ctrl+alt+b`: ビルド
- `ctrl+alt+u`: ファームウェアを書き込む (Upload)
- `ctrl+alt+s`: シリアルモニタを開く (Serialmonitor)
- `cmd-shift-d`: デバッグ実行 (Windows はたぶん `ctrl-shift-d`)

https://docs.platformio.org/en/latest//integration/ide/vscode.html#key-bindings
IVEC エントリーレベル

オフィシャル: http://www.ivia.or.jp/item/38/

エントリーレベル
レベル1: 
テスト実行の工程全体を通して、テスト実行と期待値確認及び不具合報告を実施することができる技術者を目標としています。
テスト実行に必要な準備のほかに自己のスケジュール管理や「報告」「連絡」「相談」などのコミュニケーションの能力や実務に必要なソフトウェアテストの用語の理解。

レベル2: 
テスト実行の工程全体を通して、テスト実行とテスト実行の管理ができる技術者を目標。
レベル1の「スキル」「知識」に加え、「テスト実行の管理(「リソース」「工程」「目標」「要員」「リスク」「テスト実行の品質」)などと、実務に必要なコミュニケーションの能力やソフトウェアテストの用語理解。


【テスト実行計画】
テストに入る前に
<b>マニュアル、仕様書、テストケース、実機などからテスト対象の仕様や操作方法を確認する。</b>

テスト前に入手するマニュアル、仕様書、テストケースから得られる情報として、画面の動き、機能などが挙げられてます。
完全に覚える必要はないが、テスト中に困らないように、どこに情報があるかは確認して、理解しておく必要があります。

<b>旧バージョンがある場合、そのバージョンのテスト仕様書を入手し、差分を把握する。</b>

旧バージョンで起きていたバグ、旧バージョンの仕様書、新/今バージョンで追加された機能を理解しておく必要があり。

<b>競合製品が存在する場合、仕様の調査・分析を実施</b>

競合製品の差分など、予備情報として得られることができます。
事前に競合の使い勝手など性能を知っておくと、比較なども行えます。

<b>テストの目標</b>
テスト実行エリア、テストの目的によってテストケースの優先度が変わる場合、またテストサイクルやフェーズでテスト目標が設定されます。テスト実行担当者に周知させることによって、よりまとまったチームを組むことができます。


<b>テスト実行スケジュールを作成</b>
作業の振り分け、どのテストサイクルで行うテストなのか、またどの種別のテストを行うのかによってスケジュールを立案することができます。
実行中にスケジュールが修正されることが頻繁に起こるプロジェクトのテストチームでは柔軟に対応できるスケジュールを組む必要があります。

また気が向いたら、更新かな。
ブロック変数


````rb:ブロック変数①
1.upto(10) do |i|
 print i, "¥n"
end
```

````rb:ブロック変数②
1.downto(10) do |i|
 print i, "¥n"
end
```

````rb:ブロック変数③
１０.times do |i|
 print i, "¥n"
end
```

````rb:ブロック変数④
10.step(limit[.step]) do |i|
 print i, "¥n"
end
```

戻り値は全てselfとします。

|メソッド名|戻り値|説明|
|--|--|--|
|upto(max) do I i I|self|selfからmaxまで整数を１繰り上げながらブロック引数iとして処理内容を実行|
|downto(min) do I i I|self|selfからmaxまで整数を１繰り下げながらブロック引数iとして処理内容を実行|
|times do I i I|self|0（ゼロ）からself-1まで整数を１繰り上げながらブロック引数iとして処理内容を実行。selfが負の場合には何もしない。|
|step(limit[, step]) I i I|self|selfからlimitまで整数をstepで指定した数だけ繰り上げながらブロック引数iとして処理内容を実行。stepを省略した場合は１を指定したものとする|
Regexpクラスとは？

Regexpクラスとは？を調査します。

>@shizumaさん　ものすごく参考になりました。
>https://qiita.com/shizuma/items/4279104026964f1efca6

##/(スラッシュ)で囲むと正規表現オブジェクトを生成

メタ文字「繰り返し」を表現
-

|メタ文字列|意味|
|:--:|:--:|
|*|0回以上|
|+|1回以上|
|?|0回か1回|
|{n}|n回|
|{n,}|n回以上|
|{,n}|n回以下|
|{n,m}|n回以上m回以下|

メタ文字「ワイルドカード」
-
|.|改行以外の任意の1文字の文字列を表す|
|:--:|:--:|

範囲を用いた文字クラス
-

|表記|表す文字|範囲|
|--|--|--|
|[a-z]|小文字英字|[abcdefghijklmnopqrstuvwxyz]|
|[A-Z]|大文字英字|[ABCDEFGHIJKLMNOPQRSTUVWXYZ]|
|[0-9]|1桁数字|[0123456789]|


省略記法「文字クラス」
-

|メタ文字列|意味|
|--|--|
|\w|単語を構成する文字 [a-zA-Z0-9_]|
|\W|単語を構成しない文字 [^a-zA-Z0-9_]|
|\s|空白文字 [ \t\r\n\f]|
|\S|空白でないような文字 [^ \t\r\n\f]|
|\d|10進数の数字 [0-9]|
|\D|10進数の数字でないような文字 [^0-9]|
|\h|16進数の数字 [0-9a-fA-F]|
|\H|16進数の数字でないような文字 [^0-9a-fA-F]|

(注１)否定文字クラス　^(ハット)・・・文字クラスの[の後に^を付けると先ほどとは逆にどの文字にもマッチしないというパターンを作成出来ます。

（注２）バックスラッシュ()と文字で改行などの特殊な文字を表現する
改行やタブなど特殊な文字にマッチさせるためにバックスラッシュ(\)と文字を組み合わせたメタ文字が利用できます。

|\f |改ページ|
|--|--|
|\n |改行|
|\r |復帰|
|\t  |タブ|
|\v  |垂直タブ|

文字列「文字列の先頭、文末等を表現」
-

|メタ文字列|意味|
|--|--|
|^|行頭|
|$|行末|
|\A|文字列の先頭|
|\z|文字列の末尾|
|\Z|文字列の末尾（末尾が改行文字ならばその手前にマッチ）|


?=
-

?=の直後に設定した文字でチェックをかけて、設定した文字が続く**文字列が存在**するか確認します。

*?
-
「*」は、直前の1文字が**0回以上**続くとマッチします。例えば、「camp*」とした場合、「cam」「camp」「campp」「camppp」などがマッチします。この「*」の後に?をつけることで、チェックした文字列の中で、?の直後の文字が出てきた段階でその1文字のみ返します。

iオプション
-

iオプションを加えることで大文字・小文字を区別せずに検索します。

具体例
-

|全て数値（全角）|
|:--:|
|/\A[０-９]+\z/|


表示「\A」:先頭文字
表示「[0-9]」:数字で
表示「＋」：１回以上繰り返して
表示「\z」:終わる
Microsoft Graph API を利用した Azure AD B2C のユーザー操作（更新編）

Microsoft Azure 上でクラウドネイティブなシステムを作る際は、ユーザー情報管理や認証処理を Azure AD B2C を利用して実現することが一般的です。
本記事では、Microsoft Graph API を利用して Azure AD B2C 上のユーザー情報を作成、更新、削除する方法を紹介します。

## 前提条件
- Azure AD B2C テナントが作成済みであること
- [Azure AD B2C テナントに Azure AD B2C 用ユーザーが作成されている](https://qiita.com/ksper/items/66961c66d3447f59c24a)こと
- [Microsoft Graph アプリケーションを登録されている](https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/microsoft-graph-get-started?tabs=app-reg-ga)こと
- クライアント側は Spring-Boot ベースの Java アプリケーション  

## pom.xml
[作成編](https://qiita.com/ksper/items/66961c66d3447f59c24a#pomxml)を参考にしてください。

## Azure AD B2C ユーザーの ObjectId を確認する
Azure AD B2C ユーザーの更新は、対象ユーザーの ObjectId が必要になります。
ObjectId は、ユーザーのプロファイル画面から確認できます。
![スクリーンショット 2021-05-01 3.26.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408709/185e7889-242f-c74f-b6ce-845405d93abb.png)


## Azure AD B2C ユーザーの更新
```java:TestGraphApi.java
   @Test
    void updateUser() {

        /**
         * ユーザーインスタンスの作成
         */
        User user = new User();


        /**
         * ユーザー属性の設定
         */
        user.displayName = DISPLAY_NAME_FOR_UPDATE;
        ObjectIdentity objectIdentity = new ObjectIdentity();
        objectIdentity.signInType = "username";
        objectIdentity.issuer = ISSUER;
        objectIdentity.issuerAssignedId = ISSUER_ASSIGNED_ID_FOR_UPDATE;
        List<ObjectIdentity> identities = new ArrayList();
        identities.add(objectIdentity);
        user.identities = identities;

        /**
         * Azure AD B2C 上のユーザーを更新
         */
        createIGraphServiceClient(
                CLIENT_ID,
                CLIENT_SECRET,
                DOMAIN_NAME).users(OBJECT_ID_FOR_UPDATE) 
                .buildRequest().patch(user);  //  (*1)(*2)

    }
```
(*1) IGraphServiceClient オブジェクトの users メソッドの引数は、更新対象ユーザーの ObjectId になります。
(*2) ユーザー作成時は post メソッドでしたが、ユーザー更新時は、patch メソッドになります。

##サインインタイプについて
[作成編](https://qiita.com/ksper/items/66961c66d3447f59c24a)で、サインインのタイプを選択できるとお伝えしました。
objectIdentity.issuerAssignedId で設定した値は、サインイン時にアカウント名として利用されます。サインインのタイプによって、指定できる値が異なります。

- ユーザー名認証
  - テナント内でユニークな文字列 
- メールアドレス認証
  - テナント内でユニークな文字列
  - {文字列} @ {Active Directoryのドメイン} の形式 (*1)
- フェデレーション連携認証
  - テナント内でユニークな文字列
  - @ マークを含むメールアドレスとして正しい形式

(*1) Active Directory のドメインは、カスタム ドメインを追加していない場合、{テナント名}.onmicrosoft.com のみになります。他のドメインのユーザーを設定したい場合は、Active Directory B2C の[カスタム ドメイン](https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/custom-domain?pivots=b2c-user-flow)を有効にしてください。


##実行結果
上記を実行すると、Azure AD B2C 上に指定した属性のユーザーが更新されていることが確認できます。
![スクリーンショット 2021-05-01 4.02.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408709/e20b4f7c-842e-4548-a880-327e861ed908.png)

次回は、ユーザー情報の削除方法について記述します。
読んで頂きありがとうございました。

####検証コード
https://github.com/ksper911/graphapi-for-azureadb2c

####Graph API リファレンス
https://docs.microsoft.com/ja-jp/graph/api/user-update?view=graph-rest-1.0&tabs=http
Rubyで利用できる型

|型名|リテラル表記名|意味|
|:--:|:--:|:--:|
|integer|234|整数|
|Float|3.14159|浮動小数点|
|String|"Hello World!"|文字列|
|Array|[1,2,3,4]|配列|
|Hash|{"Lemon" => 100, "Orange" => 150}|ハッシュ|
|Range|1..10|範囲|
|Symbol|data[:name]|シンボル|
|Regexp|/\A[ぁ-んァ-ン一-龥]/|正規表現|
|NilClass|nil|何もない|
|TrueClass|true|真|
|FalseClass|false|疑|
C#のDebug/Releaseコンパイルはどう違うの？

# はじめに
　こんにちは、九島茶にゃです。
　今回の記事は開発者向けになります。
　ILかアセンブリ言語についての知識があるといいでしょう。

# Debug/Releaseの違い
　簡単に言えば、以下のコードがあったとします。

~~~cs:Sample.cs
class Sample {
    static void Main() {
        int a = 10 * 5;
        System.Console.WriteLine(a);
    }
}
~~~

　次に、`Sample.cs`と全く同じ動作をする、以下の様なコードがあるとします。

~~~cs:ImprovedSample.cs
class Sample {
    static void Main() {
        System.Console.WriteLine(50);
    }
}
~~~

　もしコードに対し逐次的に処理が行われる（コンパイラ、仮想マシン、CPU等での改変がない）としたら、明らかに`10 * 5`の計算や変数`a`への`store/load`を行っていない`ImprovedSample.cs`の方が速いに決まっていますよね？

　ちなみに、`Sample.cs`をDebug/Releaseでコンパイルするとこう解釈されます。（処理の部分のみ抽出します。assembly等の属性の付加も見たい人は<a href="https://sharplab.io/#v2:CYLg1APgAgTABAZQIYFsAOAbApnA3gWACg4S4oBGANjIBY4BZJASwDsAKASjyNN7lYAucJHAC8ccgAY4AKjgBWANw8+JCgDoKATjZIOy4qQC+RI0A===">こちら</a>）

* Debugコンパイル

~~~cs:DebugSample.cs
using System;

internal class Sample
{
    private static void Main()
    {
        int value = 50;
        Console.WriteLine(value);
    }
}
~~~

* Releaseコンパイル


~~~cs:ReleaseSample.cs
using System;

internal class Sample
{
    private static void Main()
    {
        Console.WriteLine(50);
    }
}
~~~

　以上のコードを見ると、Debugでは領域が確保され、代入の処理が行われるのに対し、Releaseでは領域が確保されず、`WriteLine`メソッドに直接値が渡されている（不要な処理が省かれている）事がわかります。そのため、Releaseでは一部ブレークポイントをつけても認識されない所があります。ただし、不要な処理が省かれるので明らかに速いです。

# IL的な相違
　一般的に、Debug/Releaseには最大スタック数(サイズ)、ローカル変数のサイズ、コードサイズにて以下のような関係性があります。

### Debug・Releaseにおけるサイズの関係性

* 最大スタック数
    * Debug ≦ Release (Debug < Release のとき Release = 8)
* ローカル変数のサイズ
    * Debug ≧ Release
* コードサイズ
    * Debug ＞ Release

### 関係性の理由

　最大スタック数は基本的に同じです（1,2か引数の数だけ確保される）。しかし、ローカル変数を用いないときはデフォルトのサイズ(8 Bytes)が確保されるので、以上のようになります。
　ローカル変数は`ReleaseSample.cs`の通り、最適化によって領域が確保されない可能性があるからです。
　コードサイズは、Debugコンパイラは`DebugSample.cs`のようにコードを逐次的にILに変換し、（ブレークポイントのため？）`nop`をいくつか追加します。Releaseコンパイラは出来るだけ軽く、短いコードを生成します。勿論、基本的に`nop`は生成しません。そのため、以上のようにDebugの方がコードサイズが大きくなります。
NilClass,TrueClass,FalseClass

これらは擬似変数と呼ばれます。nilは存在しないオブジェクトを示す特別なオブジェクトです。falseとも0とも違う概念となっているため注意しましょう。また論理演算や条件分岐でtrueは真、false、nilは偽を表します。


>参考：変数の種類を知っておこう！Rubyで変数のスコープを使う方法【初心者向け】
>https://techacademy.jp/magazine/9704#sec6
10進数の桁数確認プログラム

unsigned long型で10^20までの桁数を確認するプログラムです。
素数判定プログラムで巨大数を扱ったときに0を数えるのがめんどくさいので作りました。
[最速の素数判定プログラム C# Java C++](https://qiita.com/asksaito/items/76b71602dd956b79dbf7)
実用性重視でリファクタリング無しの駄作です。

```c:WhatDecimal.c
/*
 ============================================================================
 Name        : WhatDecimal.c
 Author      : mio
 Version     : 1.0
 Copyright   : mio
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define UNSIGNEDLONG_MAX 10000000000000000000
//18,446,744,073,709,551,615

int main() {
	while (1) {
		unsigned long input;
		unsigned long data;
		int cnt;

		scanf("%lu", &input);
		printf("data=%lu\n", input);

		for (cnt = 0, data = input; data > 0; data /= 10)
			cnt++;

		cnt--;
		printf("cnt zero=%d\n", cnt);

		printf("1");

		int flag = 1;
		for(;cnt>0;cnt--) {
			switch (cnt) {
			case 4 + 3 * 0:
				printf("man\n");
				cnt = 0;
				break;
			case 4 + 4 * 1:
				printf("oku\n");
				cnt = 0;
				break;
			case 4 + 4 * 2:
				printf("tyo\n");
				cnt = 0;
				break;
			case 4 + 4 * 3:
				printf("kei\n");
				cnt = 0;
				break;
			case 3 + 4 * 4:
				printf("gai\n");
				cnt = 0;
				break;
			case 3 + 4 * 5:
				printf("sen\n");
				cnt = 0;
				break;
			default:
				printf("0");
				break;
			}
		}
	}

	return 0;
}

```
[PostgreSQL]PostgreSQLのバージョン確認方法

##はじめに
PostgreSQLのバージョン確認方法をいくつかメモしておきます。

**psqlで確認する**

```
$ psql --version
```

**SQL文で確認**

```:(ログイン後)
select * From version();
```

**バージョン番号のファイルから確認**

```
$ cat /usr/local/aipo/postgres/data/PG_VERSION
```
[PostgreSQL] psql: could not connect to server: No such file or directory 	Is the server running locally and accepting 	connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?　エラーが発生した

## 環境
Amazon linux2
postgre 11.5

## 起きたエラー
postgreにログインしようとしたところ以下のようなエラーが発生

```
$ psql -U postgres
psql: could not connect to server: No such file or directory
	Is the server running locally and accepting
	connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
```

## 解決策を探る
エラーを検索してみたところサーバーが起動していないことが原因の場合があるらしい、以下のコマンドで起動する

```
$ sudo /etc/init.d/postgresql start
```
そしてまたログインを実行
しかし、ログインできず、、

次にこっちのコマンドで起動してみました。
するとエラー内容が表示！

```
$ sudo -u postgres postgres -D /var/lib/pgsql/data
 LOG:  skipping missing configuration file "/var/lib/pgsql/data/postgresql.auto.conf"
2021-04-23 07:29:45.763 UTC [10472] FATAL:  データベースファイルがサーバと互換性がありません
2021-04-23 07:29:45.763 UTC [10472] 詳細:  データディレクトリはPostgreSQLバージョン9.2で初期化されましたが、これはバージョン11.5とは互換性がありません
```
なるほど、理解した！
実は最初に入っていたversionが9.2でその時にpostgresを初期化してしまいその後11.5にアップデートしました。
9.2で作ったサーバーでは11.5では動かせないってことだったんですね。
ここまで解れば大丈夫です

`/var/lib/pgsql/data`フォルダを削除して初期化します。

```
$ sudo rm -fr /var/lib/pgsql/data
$ sudo postgresql-setup --initdb
* Initializing database in '/var/lib/pgsql/data'
* Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log
```

初期化完了！
postgresにログインします。

```
$ sudo su - postgres
$ -bash-4.2$ 
```
ログイン成功！

##結論
PostgreSQLバージョン9.2は古すぎて、それ以降のversionと互換性がない。
この場合は一旦`/var/lib/pgsql/data`フォルダを削除して、最新バージョンで初期化しなければならない。
[PostgreSQL]psql: FATAL: Peer authentication failed for user "postgres"エラーが出たときの対処法

## 起きたこと
以下のようなエラーが発生

```
psql: FATAL: Peer authentication failed for user "postgres"
```

## 原因
postgreSQLのhbaファイル(host base authentication)機能で、**peer認証**がOnになっていたから。

peer認証はローカルでアクセスする時Linuxのユーザーとパスワードがpostgresと同じものでないとエラーになるそうです。

## 対処法
peer認証をOffにします。
まずpeer認証をしているファイル、`pg_hba.conf`を探します。

```
$ find / -print |grep pg_hba.conf
-> /var/lib/pgsql/data/pg_hba.conf
```

vimを使ってファイルを編集しましょう

```
$ vim /var/lib/pgsql/data/pg_hba.conf
```

下にスクロールして以下のように表示されている場所を探します。

```:pg_hba.conf
# TYPE  DATABASE        USER            ADDRESS                 METHOD
 
# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident
```

これを以下のように編集します。

```
# TYPE  DATABASE        USER            ADDRESS                 METHOD
 
# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident
```

その後postgreSQLを再起動

```
$ service postgresql restart
```

すると以下のように接続できるようになりました。

```
psql -q -U postgres
```

## 参考
http://www.koikikukan.com/archives/2020/06/03-235555.php
Pythonの小技

### 配列操作

```py
a = ['aaa', 'bbb', 'ccc', 'ddd']

#　改行分割
res = '\n'.join(a)
```

```text:出力結果
aaa
bbb
ccc
ddd
```

### 前後に任意の文字を連結する
```py
res = ['pre_' + item + '_apre' for item in a]
```
```text:出力結果
#['pre_aaa_apre', 'pre_bbb_apre', 'pre_ccc_apre', 'pre_ddd_apre']
```
### ブランク連結
```py
res = ' '.join(a)
```
```text:出力結果
# aaa bbb ccc ddd
```

### 【zip + f】の大技
```py
a = ['aaa', 'bbb', 'ccc', 'ddd']
b = ['J', 'P', 'K']
for i, j in zip(a,b):
    print(f'{i} : {j}')
```

```text:出力結果
aaa : J
bbb : P
ccc : K
```

### pip upgrade 失敗時
```
 curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
```

### pickleの話（save/load）機械学習にも使われています。

https://www.youtube.com/watch?v=GC50dexQsRo
ターミナルの言いなりになっていたらMacBookの中身を全て失った話

※かな〜り前の話なので細かいコマンド等は忘れてしまっています。

## 本編
以前にHerokuを使ってみたくHerokuCLIを入れようとした際にターミナルくんから

> 「Xcodeのコマンドラインツールが古い！このコマンドでアップデートしてね！」

とアップデートを促されたので言われた通りにコマンドを打つと

> 「このターミナルは最新です！」

的なことを言われたので、よく読むと



> 「もしアップデートできなかったらこのコマンドを打ってコマンドラインツールを入れ直して！」

的なことも書かれていて、2つのコマンドを提示されたので（多分アンストとインスト）これまた言われた通りにまずアンストしようと

> 「sudo rm -r /Library/Developer/CommandLineTools」

と打ったら**全てを失いました。**
文字通りMacbookに入っていたものが全て消えてSafariやシステム環境設定すらまともに動かなくなりました。

Githubに上げていたプロジェクトは復旧できたのですが、画像などのローカルに置いていただけのものはもちろん全て消えてしまいました...




## 後日談と原因
後日なぜ消えてしまったのかはわからないまま、その手の分野に詳しい友人と通話しながら回復後の開発環境の再構築を手伝ってもらっていた際に聞いたのは

> 「sudo rm -r /●Library/Developer/CommandLineTools」

の「●」のところにスペースが入っていたんじゃ無いかというお話（これだと以降のパスは参照されず、ダメらしいですね...）

僕自身としてはターミナルに書かれていたものを直接コピペしただけなので「なぜスペースが？？？」といった感じなのですが...


## 最後に
兎にも角にも脳死でしてしまった僕が悪いんです。
ただ、Github等を使ってこまめにバックアップを取る癖がついたのでいい教訓になったと思っています。

なにかする際は全て調べながらやりましょう。
何事も脳死は良くないという話でした。

被害者が増えないことを祈ります。
Vue.jsでControl+EnterとCommand+Enterどちらでも送信できるようにする

# TL;DR
Vue.jsでControl+EnterとCommand+Enter両方で関数を発火させ、
Enterで発火させないベストプラクティス。

# WindowsとMacのControlキー
アプリケーションにおいて投稿機能を開発する際、
Enterで改行、Control+Enterで送信を実装したいじゃないですか。

ただ、MacにはControlキーとは別にCommandキーというのがついていて、両方に同じ機能を割り当てたい。
そこで少しハマったのでアンチパターンと共に紹介します。

# アンチパターン
keydownをControl, Commandそれぞれについて割り当てる。

``` js
<textarea
    v-model="text"
    ...
    @keydown.enter.meta.exact="[function名]"
    @keydown.enter.control.exact="[function名]"
/>
```

これだとCommand+Enterは発火したがControl+Enterが効かず、Enterで発火してしまう。
同じkeydownがふたつ定義されている時点で気持ちが悪い。

# ベストプラクティス
Enterでイベントを発火させ、イベントオブジェクトからそのとき同時に押しているキーによって場合分けする

``` js
<textarea
    v-model="text"
    ...
    @keydown.enter.meta.exact="[function名]"
/>

---

[function名](e: any) {
    // ControlキーまたはCommandキーが同時に押されているか
    if (e.ctrlKey || e.metaKey) // 処理
},
```

# まとめ
同じイベントハンドラを複数定義するのはよくない。
KeyCodeは推奨されていないので、ctrlKey, metaKeyのプロパティで処理できてよかった。
[Rails]bulletを使ってN + 1問題を解消

##N + 1問題とは
要約するとSQLが沢山発行して動作が重くなってしまう問題
詳しくは以下の記事をご確認ください私も参考にさせていただきました。

https://qiita.com/TsubasaTakagi/items/8c3f4317ad917924b860

## bulletとは
N + 1クエリを自動で検出するgemですうっかりN＋1問題が起こってもすぐに見つけることができます。
ただbulletが検出できないようなN + 1クエリがあるケースがあるので頼りすぎるのもよくないです。↓以下参考記事

https://techracho.bpsinc.jp/yusiro/2019_12_24/85407

## bulletを使う前
自作のアプリケーションでSQLを発行し確認してみたところ以下のようになった

```
Processing by QuestionsController#index as HTML
  User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 18], ["LIMIT", 1]]
  Rendering questions/index.html.erb within layouts/application
  Question Load (1.3ms)  SELECT DISTINCT "questions".* FROM "questions" WHERE "questions"."best_answer_id" IS NULL ORDER BY "questions"."created_at" DESC LIMIT $1 OFFSET $2  [["LIMIT", 10], ["OFFSET", 0]]
  ↳ app/views/questions/index.html.erb:51
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 18], ["LIMIT", 1]]
  ↳ app/views/questions/index.html.erb:52
```

これが100行ぐらい続くのである。。

##bulletをインストール
Gemfileに以下を追加します。

```:Gemfile
group :development
  gem 'bullet'
end
```

`bundle install`を実行します。

```
$ bundle install
```

そしてSQLを発行しているページにいく(筆者の場合indexページ)と以下のように表示された。
![スクリーンショット 2021-05-01 1.21.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/6da52b21-fc82-dec7-6cc2-824307c3dde1.png)

表示の通りコントローラーに`includes[:user])`に書き換える

```
- @questions = @q.result(distinct: true)
+ @questions = @q.result.includes(:user)
```
こうするとポップアップが表示されなくなりSQLがどう発行されているか確認してみた。

```
Processing by QuestionsController#index as HTML
  User Load (1.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 18], ["LIMIT", 1]]
  Rendering questions/index.html.erb within layouts/application
  Question Load (0.7ms)  SELECT "questions".* FROM "questions" WHERE "questions"."best_answer_id" IS NULL ORDER BY "questions"."created_at" DESC LIMIT $1 OFFSET $2  [["LIMIT", 10], ["OFFSET", 0]]
  ↳ app/views/questions/index.html.erb:51
  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3, $4, $5, $6, $7, $8)  [["id", 18], ["id", 17], ["id", 14], ["id", 19], ["id", 13], ["id", 9], ["id", 11], ["id", 3]]
  ↳ app/views/questions/index.html.erb:51
```
70行ぐらいに減っていた！

`includes`を指定することで関連をまとめて取得し、最小限のクエリ回数で読み込みます。

以上です
JavaScript　promiseの備忘録

#この記事の目的
最近知った非同期処理について、初心者（自分）にもわかりやすく噛み砕いたものを紹介します。WEB開発をする際にはAPIを使ったりする機会が非常に多いかと思います。
そんな時に避けては通れない**非同期処理**について説明します。
#非同期って何？
JavaScript(以下js）という言語は並列処理（マルチスレッド）ができない言語です。
ですので、プログラムされた命令を１つずつ処理しています。
この場合、一つ問題が出てきます。

例えば、処理１と処理２、処理３の順番で実行するプログラムがあったとします。
ここで、処理２の処理にすごく時間がかかった場合どうなるでしょうか？
。。。。。
そうです、処理２が完了するまで、処理３に進めません。
病院に例えると、二番目の患者の診察治療が終了するまで、三番目の患者は受付も採血もできないまま待たされると言うことですね。
これでは困ってしまうため、jsでは非同期処理を行っています。
非同期処理では、時間のかかる処理（ここでは処理２）に対して**Promise**を返します。
**とりあえず時間かかりそうなんで、後で何かしら結果を返すね！**という結果を返すのです。
こうすることで、jsはとりあえず処理２でpromiseもらえたので次の処理に移れるのです。

      console.log('処理１');
      var result = new Promise(function(resolve) {
      resolve(new Date);
      });
      console.log(result + 'ここは処理２');
      //new Date()で日付の取得をし、promiseに格納します。
      console.log(’処理３);

このコードの結果は以下の通りです。

```
処理１
[object Promise]処理２
処理3
```


#Promiseの処理
ただ、Promiseが返ってくるのはいいのですが、このままでは中身がわかりません。
病院で例えると、受付をして整理券をもらっただけで、診察をしてもらっておらず結果がわかっていない状態ですね。
最終的な結果を得るためにはさらに、工夫が必要です。
現在の状態は、

処理１
↓
処理２（後で結果を返す**約束をしているだけ**で答えがない）
↓
処理３

ですので、約束を果たしてもらう必要があります。そのためには
promiseの持つ、thenメソッドを使います。

```
  console.log('処理１');
  var result = new Promise(function(resolve) {
  resolve(new Date);
  });

  console.log(result + 'ここは処理２');
  //↑の時点ではpromiseが返される
　
  result.then(function(res){
  console.log(res)
  )};
  //この処理でpromiseが格納されていた変数resultに結果が返されます。

  console.log(’処理３)
```
結果

```
処理１
[object Promise]処理２
処理3
Sat May 01 2021 01:04:05 GMT+0900 (日本標準時)
```
最後の行にSat May 01 2021 01:04:05 GMT+0900 (日本標準時)が表示されています。

#まとめ
**１.jsには非同期処理がある。**
時間のかかる処理はそちら（APIならサーバーなど）に任せてとりあえずpromiseを返して次に行く。

**2.promiseはそのままでは中身がわからない。**
実際に中身を見るにはthenメソッドでresponseの中身を得る必要があります。

今回の例はコンソールに表示するだけでしたが、DOM操作で要素を生成するなりするとブラウザに表示ができます。
Cloudflare PagesにNuxtのSPAアプリをデプロイする（Firebase Hostingから移行）

###なぜFirebase Hostingから移行するのか
Firebase Hostingの無料枠がしょぼすぎるからです。Cloudflare Pages(以下CFP)は転送量無制限でビルド回数も無料枠で500回もあります。Firebase Hostingは無料枠じゃ大したアクセスじゃなくてもきつそうです。

###CFP側でやること
1:nuxt.config.jsにtarget:"static"と加える（SPAなら加えなくてもいい？）
2:Githubにプッシュ
3:CFPにサインアップ
4:Githubアカウントと連携（画面が自動で出てくる）
5:デプロイするリポジトリとブランチを選択しプロジェクト名を書く
6:フレームワークの選択を迫られるので「Nuxt」を選択。（あとは自動でやってくれるので基本はいじらなくていい。distにwebpackでコンパイル後のファイルをおいている設定なら←デフォルト）
7:デプロイボタンを押して数分待つ。
～終了～
初心者でも5分で終わります。体感的にはFirebase Hostingの難易度の半分もないですね

###Firebase Hosting側でやること
1:パワーシェルかコマンドプロンプトでプロジェクトに入る
2:プロジェクト名 > firebase hosting:disable(確認の英文が出たらyをEnter)
3:これで昔のFirebase HostingのURLは無効化されます（~web.appのやつ）（履歴は消えない）
4:firebase.jsonを削除（またHostingを使うときに自動作成される）
～終了～

###Firebase Authを使っていた場合
新しいCFPのドメインを登録しないとだめです。
コンソール > Auth > Sign-in-method（下の方にスクロール）> 承認済みドメイン
に新しいドメインを追加してください。
これを行わないとデプロイ後のCFPドメインではGoogle認証が使えませんので。

Cloudflare Pagesは今後に期待ですね
【Vue.js】vue-textarea-autosizeで改行に合わせて高さを変えてくれるテキストエリアを実装

#vue-textarea-autosizeとは
vue-textarea-autosizeは、改行に合わせて高さを変えてくれるテキストエリアが実装できるコンポーネントライブラリです。

最大の高さを設定するれば、それ以降はスクロールバーに切り替えてくれる機能もあります。

#vue-js-modalの導入方法
以下のnpm、CDNを使ってインストールします。

- npm

```terminal
npm i -S vue-textarea-autosize
```

- yarn

```terminal
yarn add vue-textarea-autosize
```

- CDN

```html
<script src="https://cdn.jsdelivr.net/npm/vue-textarea-autosize@1.1.1/dist/vue-textarea-autosize.umd.min.js"></script>
```

#導入手順

###1.ライブラリの取り込み

```javascript
import VueTextareaAutosize from 'vue-textarea-autosize'
Vue.use(VueTextareaAutosize);
```


###2.メソッドを設定

```javascript
export default {
  data() {
    return {
      value: "", //任意名
      },
    },
 }
```


###3. テンプレートを準備

```html
<div class="profile-contens flex">
   <textarea-autosize name="text" cols="10" rows="1" v-model="selfpr" placeholder="自己紹介" :min-height="70" :max-height="70"></textarea-autosize>
</div>
```

###4.プロパティ

|Props|Required|Type|Default|Description|
|:--|:--:|:--:|:--:|:--:|--:|
|v-model|no|String, Number|''|値のバインディング|
|value|no|String, Number|''|v-modelバインディングの一部|
|autosize|no|Boolean|true|自動サイズ変更を動的に有効/無効にすることができます|
|minHeight|no|Number|null|最小テキストエリアの高さ（反応的な動作）|
|maxHeight|no|Number|null|最大テキストエリアの高さ（反応的な動作）|
|important|no|Boolean, Array|false|http://cleanslatecss.com/!important　を使用する場合など、スタイルプロパティを強制します。許可される値：true、falseまたは下記のように配列で一部を設定['resize', 'overflow', 'height']|


#まとめ

改行に合わせて高さを変えてくれるテキストエリアが実装できるコンポーネントライブラリでした。
NI-DAQmxのエラーコード-229771をMAXデータベースのリセットで解決した

# 現象
前日まで問題なく実行できていたVIを実行しようとしたところ、以下のエラーが出る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1419531/ceb2b111-e8b0-423d-0da2-c6fb450a5f79.png)
どうやら接続されているAD変換器 (NI USB-6229) がNI Device Monitorに認識されていないのが問題のようだった

# 環境
・Windows 10 Education 20H2 64-bit
・NI LabVIEW 2020 SP1 (32-bit)
・NI USB-6229

# 解決策
①スタートメニューに"msconfig"と入力し、システム構成を開く
②システム構成の"サービス"タブの中にある「NI Data Loader」「NI Configuration Manager」の"状態"を確認する

**状態が「停止」になっていた**
※2つとも「実行中」である場合は[こちら](https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z000000P7a7SAC&l=ja-JP)を参考にしてください。

③スタートメニュー >> Windows管理ツール >> サービス を開く
④「NI Data Loder」を選択し右クリックから開始を選択する
⑤「NI Configuration Manager」についても同様に、選択 >> 右クリック >> 開始 の操作を行う（これが出来れば解決）

**ここで、「プロセスが中断されました」というエラーが生じる**

⑥NI MAXアプリを開く
⑦ツール >> 構成をリセット からMAXデータベースの構成のリセットを行う
⑧PCを再起動

以上で解決した。MAXデータベースが破損したことが原因だった。
⑥~⑧のMAXデータベースの構成リセットの方法はバージョンによって異なるため、本手法で解決しない場合は[こちら](https://knowledge.ni.com/KnowledgeArticleDetails?id=kA03q000000YHcVCAW&l=ja-JP)を確認してください。


# 参考になったURL
・[デバイスがMAXでエラー-88705または80040383を発生させるが、WINDOWSデバイスマネージャーでは表示される](https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z000000P8wnSAC&l=ja-JP)
・[ERROR 1067 WITH NI MAX / NI CONFIGURATION MANAGER](https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z0000019YidSAE&l=ja-JP&OpenDocument=)
・[NI MAXデータベースファイルをリセットする方法](https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z000000P8awSAC&l=ja-JP)




# 心当たりのある原因
PCが勝手に再起動を繰り返すので、その時にMAXデータベースが破損した可能性がある

# その他に試したこと
・PC再起動（効果なし）
・DAQmxのドライバーの再インストール（効果なし）
Node.js＋ExpressでWebアプリケーション開発 第２回

#前の記事
https://qiita.com/pocota5260/items/1bc10fcf4f89f6d2a38e

前回はHelloWorldまででした。
今回はGETとPOSTを勉強してきたのでまとめていきます。

#GET
index.ejsに、自分自身にGetパラメータで"name"と"age"を渡し、再度読み込まれたときに"name"と"age"を表示するようなイメージで作りにしました。

```views\index.ejs
        <div>
            <a href="?name=TEST&age=17">GETのテスト！！</a>
            <p>Name:<%= name %></p>
            <p>Age:<%= age %></p>
        </div>
```

サーバサイドのroutes\index.jsの処理です。
router.get関数でGetパラメータの"name"と"age"を受け取り、JSON形式のオブジェクトにセットし、自分自身に返しています。各Getパラメータは"request.query"で取得できます。

```routes\index.js
const express = require('express');
const router = express.Router();
// ここを追加
var resObj = {
    title: 'Sample NodeExpTest',
    message: 'Hello World!',
    name: "",
    age: "",
    sports: ""
};

router.get('/', function (request, response) {
    // response.render('index', { title: 'Sample NodeExpTest', message: 'Hello World!' });
    // ここを追加
    const query = request.query;
    resObj.name = query.name;
    resObj.age = query.age;
    response.render('index', resObj);
});
```

##動作確認
初期表示時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189598/d6276047-97b6-ac64-53ee-0970b748a3f8.png)

リンククリック後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189598/f5e12c44-0d77-8b74-6d2b-44fce8c162a9.png)

#POST
index.ejsに入力フォームを作成し、自分自身にPOSTすると、サーバサイドでフォームのデータを受け取り、JSON形式のオブジェクトにセットし、自分自身に返しています。各フォームデータは"request.body"で取得できます。

```views\index.ejs
        <div>
            <form action="/" method="POST">
                <p>好きなスポーツは何ですか？</p>
                <input type="text" name="sports">
                <input type="submit" value="POSTのテスト！！"></input>
            </form>
            <p>好きなスポーツは・・・<%= sports %>です</p>
        </div>
```

```routes\index.js
router.post("/", function (request, response) {
    resObj.sports = request.body.sports;
    response.render('index', resObj);
});
```

このままでは"request.body"はundefinedとなり、フォームデータを受け取ることができませんでした。server.jsのappの直下に以下のようなおまじないを追加する必要があるようです。

```server.js
// express の実態 Application を生成
const app = express();
// POSTのクエリーを良い感じに処理する
app.use(express.urlencoded({extended: true}));
```

##動作確認
初期表示時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189598/01625081-2938-f2b2-a5e5-7eec02f3e6cb.png)

好きなスポーツを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189598/c7f3bc1d-d221-826e-f2bf-3d16282e577b.png)

"POSTのテスト！！"ボタンをクリックすると、入力したスポーツが画面に表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189598/50966a1f-cf1e-2f94-5e5b-390269381df7.png)


今回はここまで。
次回は画面遷移について勉強していきたいと思います。
ソースコードはこちら。
https://github.com/pocota5260/NodeExpTest
Gatsby.jsでreact-reduxを使う方法

皆さんこんにちは！

今回はGatsby.jsでreduxを使用する方法を書いていこうかなと思います。

素のReactと実装方法が少しだけ異なるので、ぜひGatsby.jsでreduxを使いたいという方はご覧ください！

それでは説明していきます。

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

まずは必要なパッケージをインストールしてください。

```powershell
npm install --save redux react-redux redux-thunk gatsby-plugin-react-redux
```

#reduxの設定#

次に、``redux``の設定を行っていきます。

```store.js
import { applyMiddleware, combineReducers, createStore as reduxCreateStore } from "redux"
import thunk from "redux-thunk"
import Test from "./test"


export default function createStore() {
  let middleWares = [thunk]

  return reduxCreateStore(
    combineReducers({
      test: Test
    }),
    applyMiddleware(...middleWares)
  )
}

```

#gatsby-configの設定#

次は、``gatsby-config.js``に以下の設定を加えて下さい。

```javascript
module.exports = {
  plugins: [
    // 省略
    {
      resolve: `gatsby-plugin-react-redux`,
      options: {
        pathToCreateStoreModule: "@/store.js" // 先ほど作成したreduxの設定ファイルのパスを入力
      }
    }
  ],
}

```

#Providerの設置#

最後にstoreの情報を扱えるように``Layout.js``のような毎回レンダリングされる要素の配下に``Provider``を設置してあげましょう！

```Layout.js
import React from "react"
import { Provider } from "react-redux"
import createStore from "@/store.js" // reduxの設定を行ったファイル
import { Header } from "../Header"

export const store = createStore()

const Layout = (props) => {
  return (
    <Provider store={store}>
      <Header />
      <main></main>
    </Provider>
  )
}

export default Layout
```

propsとして``store``プロパティに``createStore()``で作成した``store``を渡してあげましょう。

このようにしてstoreの情報を参照することができます！

いかがだったでしょうか？

こうしてみると案外簡単なものですね。

皆さんもぜひ使って下さい！

以上、「Gatsby.jsでreact-reduxを使う方法」でした！

Thank you for reading