OmniAICreator/Qiita-1.07M huggingface dataset:
ArduinoでOLEDを動かす(u8g2libライブラリを使用)

# 概要
Arduinoでu8g2libライブラリを使用してOLEDに文字列を表示する。
関数を整理したサイトが見つからなかったので、調べた内容を整理。
※u8g2libライブラリ以外の関数でも便利なものがあれば合わせて記載
※動作確認が取れたものを随時追加中

# 実行環境
MCU：Arduino nano v3.0（HiLetgo製互換品）
OLED：Vivan-Star I2C 0.96インチOLED(SSD1315使用)

# 参考サイト
https://lang-ship.com/blog/work/grove-beginner-kit-08-oled/
https://jumbleat.com/2016/09/07/how_to_use_u8glib_part_3/

# サイズ別フォント一覧
https://github.com/olikraus/u8g2/wiki/fntlistall

# 配線
省略

# 基本のプログラム
u8g2libはSSD1315をサポートしていないが、SSD1306用のライブラリを使用することで以降に記載する関数が使えることを当方の環境で確認済み。
画面描画の流れとしては、バッファと呼ばれる領域に表示したい内容を入力していき、sendBuffer()でそれまでに入力した内容で画面を更新、となる。

```c++
#include <U8g2lib.h>

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);

void setup(void) {
  u8g2.begin();          // OLEDの初期化
  u8g2.setFlipMode(0);   // 画面の向きを設定、数字を変えると向きが変わる
}

void loop(void) {
  u8g2.clearBuffer();                    // バッファのクリア
  u8g2.setFont(u8g2_font_ncenB08_tr);    // フォント設定
  u8g2.drawStr(0, 10, "Hello World!");   // バッファに文字列を格納
  u8g2.drawLine(0, 16, 128, 64);         // バッファに直線の情報を格納
  u8g2.sendBuffer();                     // バッファの内容で画面を更新
  delay(1000);
}
```

# 関数一覧
※クラス名を上記プログラムと同じく「u8g2」に設定したと想定
## 初期設定
### インスタンス生成
```c:構文
オブジェクトの型名 u8g2(引数);
```

オブジェクトの型名と引数はスケッチ例 → U8g2 → full_buffer → HelloWorld等で動作確認しつつ実行環境にあったものを選ぶ。
### 初期化
```c:構文
u8g2.begin();
```
### 画面の向きを設定
```c:構文
u8g2.setFlipMode(画面の向きを表す数字);
```

引数のデフォルトは0で、1に変更すると180°回転する。
## 文字列
### フォントを設定
```c:構文
u8g2.setFont(フォント名);
```

u8g2libで使用できるフォントはGithubの下記リンク先。
https://github.com/olikraus/u8g2/wiki/fntlistall#7-pixel-height
※文字の大きさでカテゴリ分けされている

### 文字列を表示
```c:構文
u8g2.drawStr(x座標, y座標, 文字列);
```

指定した座標の位置に文字列を表示する。
原点は画面左上なので、左端から右に何ピクセル、上端から下に何ピクセル、という形で指定。
文字列の左下の座標を指定するので、文字の高さを見越して座標を指定する。
例えば (0, 0, "Hello World") と指定すると文字が画面からはみ出すことになるので何も表示されない。

また返り値で文字列の幅を取得できる。
※実際は(文字列の幅+1文字分の幅)が返ってくる
数字＋単位という表示をしたいが数字の桁数が変わることがある、というときに便利。

```c:例
byte a = 0;
a = u8g2.drawStr(0, 10, "Hello");　//"Hello"をバッファに格納すると同時に文字幅をaに代入
u8g2.drawStr(a, 10, " World");     //取得した幅の分だけ右に移動した座標で"World"を表示
```

### 数値を文字列に変換(標準ライブラリ)
```c:構文
dtostrf(数値, 全体の長さ, 小数点以下の表示数, 文字列変数);
```

数値を文字列に変換して文字列変数に代入する関数。
sprintfでも数字を文字列に変換することはできるが、Arduinoでは小数(float型、dobble型)をsprintfで変換するとエラーになるので、その解決のために作られたと思われる関数。
センサの値や計算結果を表示するときに便利

例)
a = 3.1415;
char str[10];
dtostrf(a, 4, 2, str);

str ⇒  3.14  ※頭に0はつかない

### 文字列の幅を取得
```c:構文
byte 変数 = u8g2.getStrWidth(文字列変数);
```

文字列の幅を調べる。文字列のセンタリングや右寄せ・右詰めに便利。

```c:センタリングの例
char str[20] = {"Hello World"};
byte x = u8g2.getStrWidth(str);
u8g2.drawStr(64-(x/2), 10, str);
```

解説)
画面の幅が128ピクセルであれば、中心のx座標は64。
64から文字列の幅の半分を引くと、センタリングしたときの文字列の左側の座標が算出できる。
右寄せは(128-x)となる。

## 図形
### drawLine
```c:構文
u8g2.drawLine(始点のx座標, 始点のy座標, 終点のx座標, 終点のy座標);
```

直線を描画する
始点と終点を引数に代入して使用
Python: dict型の操作まとめ

## valueが最大値、最小値のkeyを取得

max(dict)とするとkeyの最大値を取得してしまうためmax(dict, key=dict.get)とする

```Python
d = {'a': 5, 'b': 3, 'c': 4}

print(max(d))
print(max(d, key=d.get))
```

```
実行結果
c
a
```

minも同様にして取得できる

```Python
d = {'a': 5, 'b': 3, 'c': 4}

print(min(d))
print(min(d, key=d.get))
```

```
実行結果
a
b
```

## valueの値でソートする

sorted(dict)とするとkey基準でソートされる。valueの値でソートする場合は以下のようにする。 
reverse=Trueで降順

```Python
print(dict(sorted(d.items(), key=lambda x: x[1])))
print(dict(sorted(d.items(), key=lambda x: x[1], reverse=True)))
```

```
実行結果
{'b': 3, 'c': 4, 'a': 5}
{'a': 5, 'c': 4, 'b': 3}
```


## valueの合計の取得

valuesに対してsumを使う

```Python
print(sum(d.values()))
```

```
実行結果
12
```

## 存在しないkeyを参照した時にエラーを出さないようにする

d.get(key)を使用する

```Python
print(d.get('d'))
```
```
実行結果
None
```

defaultdictを使用する

```Python
from collections import defaultdict
d_i = defaultdict(int)
print(d_i['a'])
d_l = defaultdict(list)
print(d_l[0])
```

```
実行結果
0
[]
```

defaultdictの引数には初期化時に実行する関数を指定する。
お天気アプリ

Python学習の一環として、Tkinterを使って天気ｱﾌﾟﾘ作成しました。

環境：
Window10
Gooble Colaboratory
参考動画：
Pythonアカデミー【エンジニアVtuber凛】

天気情報取得する為、Openweatherから取得しています。
取得方法について今回省略します。
https://openweathermap.org/


tkinterはPYTHONで自由にGUIアプリを作れるというので、Tkinterをベースにインポートします。

```python
import tkinter as tk
お天気API取得する為
import requests
``` 

####メインウインド作成

```python
Tkinterでメインウィンドを作る基本記述。
canvas = tk.Tk()
####アプリのサイズを決めている。
canvas.geometry('700x500')
canvas.title('Todays Weather')
# 最高・最低気温を表す文字フォント
a = ('Arial black', 20, 'bold')
# 都市入力・天気の結果を表す文字フォント
b = ('Arial black', 40, 'bold')
```

#### お天気情報を得るためのget_weather関数

````python
# 関数名getWeatherで、上で書いたcanvasを入れる
def getWeather(canvas):
    city = textField.get()
    # openweather情報を取得する。
    api = 'https://api.openweathermap.org/data/2.5/weather?q='+city+'&appid= パスワード'
　　#APIの情報は、JSON形式になるのでJSONデーターを読み込みことになっている。
    json_data = requests.get(api).json()
    #json形式でapiのweather情報を取得する
    weather = json_data['weather'][0]['main']
    # 気温なのでINT型で取得、-273.15 気温の表記に合わせるパレメーターになっている。
    temp = int(json_data['main']['temp']-273.15)
    min_temp = int(json_data['main']['temp_min']-273.15)
    max_temp = int(json_data['main']['temp_max']-273.15)

    # アプリに表示する項目
    final_info = weather + '\n' + str(temp) + '°C'
    final_data = '\n' + '最低気温:' + str(min_temp) + '°C'+'\n' + '最高気温:' + str(max_temp)+ '°C'
    # テキストデーターとしてfinal_infoに入れた値を入れている。
    label1.config(text=final_info)
    label2.config(text=final_data)
````


####テキストボックス作成
```python
# メインウィンド示すcanvas, 文字列が中央揃え、font=bと示すことで、上で書いた文字列を再度書く必要はない。
textField = tk.Entry(canvas, justify='center', width=20, font=b)
#pady=外側の縦の隙間　テキストボックスの余白
textField.pack(pady=30)
#APIの天気情報を返す(表示する)　アプリ上で行われるイヴェントを設定することができる。bindﾒｿｯﾄﾞを書いて（）の引数にreturn, returnするものはgetWeatherですと示す
textField.bind('<Return>', getWeather)   

label1 = tk.Label(canvas, font=b)
label1.pack()
label2 = tk.Label(canvas, font=a)
label2.pack()
```

####メインウェインドをアプリに配置してmainloopで動作を待機する。

```python
canvas.mainloop()
```


次回は、お天気アプリをベースにLINEにお天気情報を送信できるアプリを作成しようと思います。
【Neos VR】BlendShapeで視線制御するアバターの設定方法

# 概要
Neos VRでは目のボーンが無いモデルをアバター化した際に，目の自動セットアップがされません．
そこで手動でComponentを追加して設定する方法を紹介します．

# 設定方法
### ProjectionPlenePointを作成する
Headの子になるようにスロットを作成し，目の前に配置します．
![2021-04-20 01.04.26 - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/00ccc1a6-7297-e143-c592-b8e1bab4acca.jpeg)
![2021-04-18 11.47.01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/d039e94a-704b-5f96-9668-6a16f10a4756.jpeg)

### コンポーネントを追加する
Users/Common Avatar System/Face/EyeManager
Users/Common Avatar System/Face/AvatarEyeDataSourceAssigner
Users/Common Avatar System/AvatarUserReferenceAssigner
Users/Common Avatar System/Face/EyeLinearDriver
を追加します．

EyeLinearDriverのEyeManagerにEyeManager
AvatarEyeDataSourceAssignerのTargetReferenceにEyeDataSource
AvatarUserReferenceAssignerのReferencesにSimulatingUser
をそれぞれ登録します．
![2021-04-20 01.04.30 - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/781223e8-7f83-ec00-a59f-b4349c229742.jpeg)

### 視線制御のBlendShapeを登録する
EyeLinearDriver/Eyes内の
ProjectionPlanePointに作成したProjectionPlenePointのスロット
LookLeft,LookUp,Look,Right,LookDownに設定したいBlendShape
を登録します．
LookMultiplyで目の動きやすさの感度を調整できます．
![2021-04-20 01.04.26 - コピー - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/4f06b0c9-fff9-dab9-6d97-8961857e7db2.jpeg)

### まばたきの設定をする
EyeLinearDriver/Eyes/OpenCloseTargetに
目閉じのBlendShapeを登録することでまばたきが出来るようになります．
Widen(目を見開く),Squeeze(ギュッと閉じる)に関しても同様です．
![2021-04-20 01.04.40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/21cfdf90-33ee-6979-1ee3-b6049ece5205.jpeg)

# 動作確認
アバターを着るとEyeManagerへDataSouceが入り，目が動くようになります．
![目線.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/4419d129-3cd7-08c9-ce3c-153400d48da8.gif)
JavaでCoincheckのpublicAPIを呼び出す

##呼び出したいAPI
https://coincheck.com/ja/documents/exchange/api#ticker

このpublicAPIのtickerを試しに呼び出してみる。

呼び出す情報は次の通り。　
ticker情報
>last 最後の取引の価格
bid 現在の買い注文の最高価格
ask 現在の売り注文の最安価格
high 24時間での最高取引価格
low 24時間での最安取引価格
volume 24時間での取引量
timestamp 現在の時刻

##Javaで実装
以下のコードでAPIの疎通チェックを行っています。
まだいくつかのAPIがありますが、apiUrlを変更するだけで疎通確認ができます。

``` java:qiita&#x20;sample.java　
		//CoinCheckのAPIの接続チェック
		String apiUrl = "https://coincheck.com/api/ticker";
		URL connectUrl = new URL(apiUrl);
		HttpURLConnection con = (HttpURLConnection) connectUrl.openConnection();
		System.out.println("レスポンスヘッダ:");
		System.out.println("レスポンスコード[" + con.getResponseCode() + "] " +
				"レスポンスメッセージ[" + con.getResponseMessage() + "]");
```

resultにGETの結果をJSON形式で格納する

``` java:qiita&#x20;sample.java　
		//GETした結果をjson形式で出力する
		InputStream in = con.getInputStream();
		String encoding = con.getContentEncoding();
		if (null == encoding) {
			encoding = "UTF-8";

		}
		StringBuffer result = new StringBuffer();
		final InputStreamReader inReader = new InputStreamReader(in, encoding);
		final BufferedReader bufReader = new BufferedReader(inReader);
		String line = null;

		// 1行ずつテキストを読み込む
		while ((line = bufReader.readLine()) != null) {
			result.append(line);
		}

		bufReader.close();
		inReader.close();
		in.close();

		System.out.println(result);

```

JSONから抽出したデータをリストに格納して出力する

``` java:qiita&#x20;sample.java　
		 JSONObject json = new JSONObject(result.toString());
		 int last = json.getInt("last");
		 int bid = json.getInt("bid");
		 int ask = json.getInt("ask");
		 int low = json.getInt("low");
		 double volume = json.getDouble("volume");
		 int timestamp = json.getInt("timestamp");

		 List<Object> ticker = new ArrayList<Object>(Arrays.asList(last,bid,ask,low,volume,timestamp));

		 System.out.println(ticker);
```

分析に使う為にCoinCheckのAPIを取得する実装を試しに書きました。とても冗長なのでまた綺麗にしておきます。

Github：https://github.com/YUJIjs/get-coincheck-api-value
AppSync の filter で指定できる検索条件一覧 [WIP]

日本語でまとまっているところが見つからなかったので埋めていきたい
AppSync 使い始めたばかりで抜けとか間違いがあるかもなのでWIP

## field に対して
ref:
- https://docs.amplify.aws/lib/graphqlapi/query-data/q/platform/js#using-aws-appsync-sdk
- https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html

| operator | description |
|--|--|
|eq  | 指定した値に一致する |
| ne | 指定した値に一致しない |
| gt | 指定した値より大きい |
| ge | 指定した値より大きい、もしくは同じ(以上) |
| lt | 指定した値より小さい |
| le | 指定した値より小さい、もしくは同じ(以下) |
| between | 指定した1つ目の値よりも大きく、2つめの値よりも小さい |
| contains | 指定した値が含まれる |
| notContains | 指定した値が含まれない |
| beginsWith | 指定した値で先頭一致 |

## 複合条件
- https://docs.amplify.aws/lib/graphqlapi/query-data/q/platform/js#filtered-and-paginated-queries

| operator | description |
|--|--|
|and | すべての条件を満たす |
|or  | いずれかの条件を満たす |
|not | 指定した条件を満たさない |
[Chapter-6]ACM(AWS Certificate Manager)でSSL証明書を取得

| タイトル |
|:-|
|  [[Chapter-1]VPCの設定](https://qiita.com/Jackson123/items/c7b0a7a6ae659fe48a3b) |
|  [[Chapter-2]EC2の設定](https://qiita.com/Jackson123/items/53cc698b1b7cfdbfe368) |
| [[Chapter-3]EC2のサーバー環境構築](https://qiita.com/Jackson123/items/821d89184d87b6020df5)  |
|  [[Chapter-4]EC2にRailsアプリの配置](https://qiita.com/Jackson123/items/e91eec2f76774717bdee) |
|  [[Chapter-5]ロードバランサー(ELB)の作成](https://qiita.com/Jackson123/items/a739525d0084747405d7) |
| [[Chapter-6]ACM(AWS Certificate Manager)でSSL証明書を取得](https://qiita.com/Jackson123/items/eb586c33fe3c5b7d9dad)  |
|  [[Chapter-7]Route53の設定](https://qiita.com/Jackson123/items/6b41ebde0eec072a283e) |
|  [[Chapter-8]https化に向けたロードバランサーの設定](https://qiita.com/Jackson123/items/d6819d3dbf304aebd459) |
|  [[Chapter-9]https化によるRoute53の設定](https://qiita.com/Jackson123/items/9ceae188a53f646e55e9) |
|  [[Chapter-10]https化によるNginxの設定](https://qiita.com/Jackson123/items/255263a260f7a833bf1d) |
## はじめに
自分の手順書としてのメモですので画像はありません。あしからず。
今回はACMでSSL証明書を取得します。
ロードバランサー(ELB)を作成しているとACMが使用できます。
ACMではSSL証明書を無料で利用することができます。

ロードバランサーの設定は以下をご覧ください

https://qiita.com/Jackson123/items/a739525d0084747405d7

この記事ではドメインを使うので作っていない方はドメインを取得してください。
著者は以下のサイトで取得しました。

https://www.onamae.com/

Route53も使いますので作成していない方は作成してください

またSSLって何？って方は以下をご覧ください

https://ssl.sakura.ad.jp/column/ssl/
## 1. 手始めに
AWSの画面左上のサービスを開き、検索欄に「ACM」と入力してください。

表示される「Certificate Manager」を選択します。

画面左側の「証明書のプロビジョニング」の「今すぐ始める」ボタンを選択します。

## 2. 証明書のリクエスト
「パブリック証明書のリクエスト」を選択

画面右の「証明書のリクエスト」ボタンを選択する。

## 3. ステップ 1: ドメイン名の追加
ドメイン名の追加欄に「取得したドメイン名」を入力
例 hogehoge.jp

その下の「この証明書に別の名前を追加」ボタンを選択
ドメイン名の追加欄に「*.取得したドメイン名」を入力
例 *.hogehoge.jp

「次へ」ボタンを選択
## 4. ステップ 2: 検証方法の選択
「DNS の検証」を選択
「確認」ボタンを選択

## 5. ステップ 3: タグを追加
追加してもしなくてもどちらでもOKです。
追加しておくと証明書の管理がしやすくなります。

## 6. ステップ 4: 確認とリクエスト
入力した項目を確認して良ければOKを押します。

## 7. ステップ 5: 検証
2つのドメインの検証状態はそれぞれ「検証保留中」となっています。
Route53を使用しておりますので、用意されているボタンを使用していきます。
「Route53でのレコードの作成」ボタンをそれぞれのドメインで選択して「作成」ボタンを選択します。
「成功」と表示されればOKです。
「続行」ボタンを選択してください。

## 8.発行の確認
Certificate Managerの画面に戻ります。
取得したドメイン名レコードの「状況」が「発行済み」になれば、無事にSSL証明書の発行が完了です。
※発行済みになるまで時間がかかる時は数秒毎にリロードを押して様子をみましょう
【SpringJdbc】ConversionServiceを用いてRowMapperによるマッピング時に値を変換する

# TL;DR
- `BeanPropertyRowMapper`/`DataClassRowMapper`/`SingleColumnRowMapper`は`ConversionService`を登録することで値の変換ができる[^rowmapper]
- 何も指定していない状態でも、`DefaultConversionService.getSharedInstance()`の取得結果が利用されている

[^rowmapper]: タイトルが長くなりすぎるため省きましたが、`org.springframework.jdbc.core`に定義された`RowMapper`でも`ConversionService`を登録できないものが存在します。

# 本文
`SpringFramework`には`ConversionService`を用いた型変換の仕組みがデフォルトで用意されており、`RowMapper`の中でもそれを利用した型変換を行うことができます。

以下のように、数値で年月を表したカラムを`java.time.YearMonth`に変換して取得する場面を例にします。

```sql:取得対象テーブル
CREATE TABLE IF NOT EXISTS `foo_table` (
  `year_month` MEDIUMINT UNSIGNED NOT NULL,
  PRIMARY KEY (`year_month`)
);
```

以下のように、何も設定せずに取得処理を行うとエラーが発生します。

```java
SingleColumnRowMapper<YearMonth> mapper = new SingleColumnRowMapper<>(YearMonth.class);

// この取得処理でTypeMismatchDataAccessExceptionが発生する
YearMonth actual = template.queryForObject("SELECT year_month FROM foo_table", mapper);
```

`ConversionService`を設定することで、この取得処理を行えるようにします。
今回は`DefaultConversionService`に`Converter`を設定し、更にそれを`RowMapper`に登録することでこれを行う例を示します[^conv]。

```java
SingleColumnRowMapper<YearMonth> mapper = new SingleColumnRowMapper<>(YearMonth.class);

// Converterの登録処理
DefaultConversionService defaultConversionService = new DefaultConversionService();
defaultConversionService.addConverter(new Converter<Integer, YearMonth>() {
    @Override
    public YearMonth convert(@NotNull Integer source) {
        return YearMonth.of(source / 100, source % 100);
    }
});
mapper.setConversionService(defaultConversionService);

YearMonth actual = template.queryForObject("SELECT year_month FROM foo_table", mapper);
assertEquals(YearMonth.of(2021, 1), actual);
```

[^conv]: `Converter`は`FunctionalInterface`であるためラムダでも書くことができますが、`Generics`関連の問題により自分の環境では実行時エラーになったため、例では匿名クラスを用いた書き方をしています。

# 補足: DefaultConversionServiceについて
`Spring`全体で、`ConversionService`を設定しなかった場合は`DefaultConversionService.getSharedInstance()`で取得される`static`な`ConversionService`が利用されます。

このインスタンスに`Converter`を設定すれば、デフォルトではアプリケーション全体でそれを使い回すことができます。

```java:DefaultConversionServiceに設定する例
DefaultConversionService sharedInstance =
        (DefaultConversionService) DefaultConversionService.getSharedInstance();
sharedInstance.addConverter(new Converter<Integer, YearMonth>() {
    @Override
    public YearMonth convert(@NotNull Integer source) {
        return YearMonth.of(source / 100, source % 100);
    }
});
```

また、`SpringFramework`内で`String` -> `Enum`のような変換が行われるのはこの`sharedInstance`の働きによるものです。
どのような変換が行われるかはソースコードから読み取ることができます。

https://github.com/spring-projects/spring-framework/blob/dc6f63f610ab0278c8c9d2c5c7cbbebb9928ec91/spring-core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java
「github cliのコマンドを`git ~`でタイポする」問題の解決法

# こんなことありませんか？
```bash:issueのリストとってきたろ！
$ git issue list
> git: 'pr' is not a git command. See 'git --help'. # ｱ゛ｱ゛ｱ゛ｱ゛ｱ゛
```

## tldr
`.gitconfig`に⬇を追記

```bash:gitconfig
[alias]
    issue = !"f() { local s=$1; shift; \
      while [ $# -gt 0 ]; do s=\"$s $1\"; shift; done;\
      gh issue $s; }; f"
```

## 解決法（失敗）
`fish`を使っているので`abbr`でやろうとした。

```bash:config.fish
$ abbr "git issue" "gh issue"
> abbr --add: Abbreviation 'git issue' cannot have spaces in the word
```
スペース込はできないらしい。

## 解決法（あまりうれしくない）
```bash
alias gis "git issue"
```
打ち慣れてないコマンドを新しく覚えたくない（怠惰）

## 解決法
`.gitconfig`に以下を追記。(dotfileで管理したかったので私は`~/dotfiles/.gitconfig_shared`に書いてます）

```bash:gitconfig
[alias]
    issue = !"f() { local s=$1; shift; \
      while [ $# -gt 0 ]; do s=\"$s $1\"; shift; done;\
      gh issue $s; }; f"
```

嬉しくなったので`issue`だけじゃなくて`pr`とかも登録しました。
√n の小数部分全体が区間 [0, 1] の中で稠密であることの証明

# 問
集合

```math
S = \left\{\left\{\sqrt{n}\right\} \mid n \in \mathbb{N}\right\}
```

は区間 $[0, 1]$ の中で稠密であることを示せ。

# 記号、用語

## 小数部分

$\left\\{x\right\\}$ で（実数）$x$ の小数部分を表す。

## 稠密

位相空間における稠密集合のちゃんとした定義はおググりください。

実数の集合 S が区間 $[0, 1]$ の中で稠密であるとは、S が次の条件を満たすことを言う。

```math
\forall a, b \in [0, 1], a < b \implies \exists x \in S\ s.t. a < x < b
```

# 証明

## 方針

方針としては、基本的には有理数が実数の中で稠密であることの証明と同じである。
まず、数直線上に 点 $a$, $b$ がある情景を思い浮かべる。
この数直線上を小人が $a$ より左側から右側へ歩いていく。
歩幅が $b-a$ より小さければ、小人は $a$ と $b$ を同時に飛び越えることが出来ない。
必ず $a$ と $b$ の間の点を踏むことになり、この点が求めたい点である。

有理数の場合と異なるのは、歩幅が場所によって異なることであり、ここに一工夫が必要である。

$\sqrt{n^2} 〜 \sqrt{(n+1)^2}$ の間には $2n + 1$ 個の数がある。隣り合う数の差はそれぞれ

```math
\begin{align}
\sqrt{n^2 + 1} - \sqrt{n^2} & = \frac{1}{\sqrt{n^2 + 1} + \sqrt{n^2}}, \\
\sqrt{n^2 + 2} - \sqrt{n^2 + 1} & = \frac{1}{\sqrt{n^2 + 2} + \sqrt{n^2 + 1}}, \\
& ... \\
\sqrt{(n+1)^2} - \sqrt{(n+1)^2 - 1} & = \frac{1}{\sqrt{(n+1)^2} + \sqrt{(n+1)^2 - 1}} \end{align}
```

であり、このうち最大は

```math
\sqrt{n^2 + 1} - \sqrt{n^2} = \frac{1}{\sqrt{n^2 + 1} + \sqrt{n^2}}
```

である。

この、一番大きい幅 が $b - a$ より小さくなるような n を選べば、$\left\\{\sqrt{n^2}\right\\}, \left\\{\sqrt{n^2 + 1}\right\\}, ... \left\\{\sqrt{(n+1)^2 - 1}\right\\}$ の並びは a と b を同時に飛び越えることができない。つまり a と b の間に $S$ の元が含まれることになる。

## 証明

まず、任意の $n$ について、 $\sqrt{n^2}, \sqrt{n^2 + 1}, ... \sqrt{(n + 1)^2 - 1}$ の整数部分は 等しく $n$ であり、この数列は単調増加であるから、これらの小数部分の数列 $\left\\{\sqrt{n^2}\right\\}, \left\\{\sqrt{n^2 + 1}\right\\}, ... \left\\{\sqrt{(n + 1)^2 - 1}\right\\}$ も単調増加である。

$a, b \in [0, 1], a < b$ を 任意に取る。

```math
n > \frac{1}{2(b-a)}
```

となる自然数 $n$ を 1 つ取ると、

```math
\frac{1}{b-a} < 2n = n + n < \sqrt{n^2 + 1} + \sqrt{n^2} \\
\therefore \sqrt{n^2 + 1} - \sqrt{n^2} = \frac{1}{\sqrt{n^2 + 1} + \sqrt{n^2}} < b - a.
```

次に、 $\left\\{\sqrt{n^2}\right\\}, \left\\{\sqrt{n^2 + 1}\right\\}, ... \left\\{\sqrt{(n+1)^2 - 1}\right\\}$ のうち、 a 以下で最大のものを選び、 $\left\\{\sqrt{n^2 + i}\right\\}$ と書く。

[追記] $a$ 以下で最大のものは $\left\\{\sqrt{(n+1)^2 - 1}\right\\}$ にはならない。なぜなら、$\left\\{\sqrt{(n+1)^2 - 1}\right\\}$ であると仮定すると

```math
\begin{align}
b - a & \leq 1 - \left\{\sqrt{(n+1)^2 - 1}\right\} \\
& = \Bigl(n + 1\Bigr) - \Bigl( n + \left\{\sqrt{(n+1)^2 - 1}\right\} \Bigr) \\
& = \sqrt{(n+1)^2} - \sqrt{(n+1)^2 - 1} \\
& < \sqrt{n^2+1} - \sqrt{n^2}
\end{align}
```

となって、もとの $n$ の設定と矛盾する。

したがって、$\left\\{\sqrt{n^2 + i + 1}\right\\} < 1$ が存在して、 $a$ より真に大きくなる。
すると、

```math
\begin{align}
\left\{\sqrt{n^2 + i}\right\} \leq a < \left\{\sqrt{n^2 + i + 1}\right\} &= \left\{\sqrt{n^2 + i}\right\} + \left\{\sqrt{n^2 + i + 1}\right\} - \left\{\sqrt{n^2 + i}\right\} \\
& = \left\{\sqrt{n^2 + i}\right\} + \Bigl( n + \left\{\sqrt{n^2 + i + 1}\right\}\Bigr) - \Bigl( n + \left\{\sqrt{n^2 + i}\right\}\Bigr) \\
& = \left\{\sqrt{n^2 + i}\right\} + \sqrt{n^2 + i + 1} - \sqrt{n^2 + i} \\
& \leq a + \Bigl( \sqrt{n^2 + i + 1} - \sqrt{n^2 + i} \Bigr) \\
& \leq a + \Bigl( \sqrt{n^2 + 1} - \sqrt{n^2} \Bigr) \\
& < a + (b - a) = b \\
\end{align}
```

が成り立つ。
よって、 $\left\\{\sqrt{n^2 + i + 1}\right\\} \in S$ は $a < \left\\{\sqrt{n^2 + i + 1}\right\\} < b $ を満たす。
$a, b$ は任意であったから、 $S$ は稠密である。
テスト用のキャリア携帯電話番号作成

自分用メモ

テスト用のキャリア携帯番号（※）を作成するシンプルなコード


※ キャリア携帯番号
090XXXXXXXX、080XXXXXXXX、070XXXXXXXX

コード

```python
import random
import string

phone_number = '0' + str(random.choice([7, 8, 9])) + '0' + ''.join(random.choices(string.digits, k=8))
print(phone_number)
```

出力

```
08039962693
```
[Chapter-5]ロードバランサー(ELB)の作成

| タイトル |
|:-|
|  [[Chapter-1]VPCの設定](https://qiita.com/Jackson123/items/c7b0a7a6ae659fe48a3b) |
|  [[Chapter-2]EC2の設定](https://qiita.com/Jackson123/items/53cc698b1b7cfdbfe368) |
| [[Chapter-3]EC2のサーバー環境構築](https://qiita.com/Jackson123/items/821d89184d87b6020df5)  |
|  [[Chapter-4]EC2にRailsアプリの配置](https://qiita.com/Jackson123/items/e91eec2f76774717bdee) |
|  [[Chapter-5]ロードバランサー(ELB)の作成](https://qiita.com/Jackson123/items/a739525d0084747405d7) |
| [[Chapter-6]ACM(AWS Certificate Manager)でSSL証明書を取得](https://qiita.com/Jackson123/items/eb586c33fe3c5b7d9dad)  |
|  [[Chapter-7]Route53の設定](https://qiita.com/Jackson123/items/6b41ebde0eec072a283e) |
|  [[Chapter-8]https化に向けたロードバランサーの設定](https://qiita.com/Jackson123/items/d6819d3dbf304aebd459) |
|  [[Chapter-9]https化によるRoute53の設定](https://qiita.com/Jackson123/items/9ceae188a53f646e55e9) |
|  [[Chapter-10]https化によるNginxの設定](https://qiita.com/Jackson123/items/255263a260f7a833bf1d) |
## はじめに
自分の手順書としてのメモですので画像はありません。あしからず。
今回はhttpでロードバランサーを作成します。
ロードバランサーって何って方は以下をご覧ください

https://www.kagoya.jp/howto/network/loadvalancer/

## 1. 手始めに
1. EC2の画面左の「ロードバランサ」を選択し、ページ左上の「ロードバランサーの作成」を選択します。
2. 「Application Load Balancer(HTTPとHTTPSを提供する)」の「作成を選択」

## 2. 手順 1: ロードバランサーの設定　
以下の通りに記述  
**基本的な設定**
  名前：「アプリ名-ELB」
  スキーム：「インターネット向け」にチェック
  IP アドレスタイプ：「ipv4」
 
**リスナー**
 デフォルトの状態

**アベイラビリティーゾーン**
VPC:「VPC_for_アプリ名」
アベイラビリティーゾーン: 「ap-northeast-1a」,「ap-northeast-1c」

**アドオンサービス**
選択なし
**タグ**
記入なしでもOK、記入しておくと後で管理しやすくなる
「次の手順：セキュリティ設定の構成」を選択し手順２に移動
## 3. 手順 2: セキュリティ設定の構成
設定はデフォルトのまま
「セキュリティグループの設定」を選択
## 4. 手順 3: セキュリティグループの設定
以下の通りに記述
セキュリティグループの割り当て:「既存のセキュリティグループを選択する」にチェック
「アプリ名-SecurityGroup」のレコードにチェック
「次の手順：ルーティングの設定」ボタンを選択する。

## 5. 手順 4: ルーティングの設定
以下の通りに記述  
**ターゲットグループ**
1. ターゲットグループ：「新しいターゲットグループ」
2. 名前：「アプリ名-Target-Group」　
3. ターゲットの種類：「インスタンス」にチェック
4. プロトコル：「HTTP1」
5. ポート：「80」

**ヘルスチェック**
1. プロトコル：「HTTP」
2. パス：「/」

**ヘルスチェックの詳細設定**
1. ポート：「トラフィックポート」
2. 正常のしきい値：「5」
3. 非正常のしきい値：「2」
4. タイムアウト：「5」
5. 間隔：「10」
6. 成功コード：「200」

「次の手順：ターゲットの登録」を選択

## 6. 手順 5: ターゲットの登録

下部の「インスタンス」欄から、
「アプリ名-instance」にチェック
「登録済みに追加」ボタンを選択する

「アプリ名-instance」が上部の「登録済みターゲット」欄に
移動した事を確認

「次の手順：確認」ボタンを選択する。
「作成」ボタンを選択する。

ロードバランサーの画面に戻り、一定時間経過後、状態が「active」なら完了。
#6 試験を終えて振り返り

この記事はシリーズものです。トップはこちらから。

 - [ネットワークスペシャリスト試験を受けることにしました【令和3年春季】](https://qiita.com/foxtail1979/items/5e333d28f2e93acb552b)

# 試験を終えて
試験当日から1週間あいてしまいました。せっかくなので感想をまとめておきたいと思います。

# 勉強のモチベーションは３ヶ月くらいが限度か
ネットワークスペシャリストを受けるぞと決めて約３ヶ月、途中で勉強に身が入らない期間もありました。なんだかんだ過去問も全てをこなすことはできず、それでも8年分くらいは解くことができていました。
これ以上長い期間学習ができるか？と考えると、実は結構難しいかもしれません。
平日は本業に取り組まないといけませんし、土日は完全にフリーな訳でもないです。働きながら資格試験の勉強を継続するのは難しいんだなあと感じています。

# 高度情報処理試験の意義
資格はとってもしょうがない、実務で経験をつむのが大事。
よく言われていることだと思いますし、その通りな面もあると思います。しかしながら知識を持って実務に取り組むと、それまでとは違った視点で業務を見ることができる・・・と思います。
ネットワークスペシャリスト試験の学習でもしなければ、無線LAN認証方式の違いについて聞かれてもチンプンカンプンだったんじゃないかな。
結局、実践も大事、知識も大事、バランスよく進めることでお互いの効果が最大化されるんじゃないかなと感じています。

# 合格の自信は正直、微妙
午前Ⅱはいけてると思います。過去問で十分に対策ができていました。
午後Ⅰもおそらく６割は取れていると思います。
午後Ⅱが、ちょっと自信がないです。前半は点数稼げていると思いますが、設問６がなかなかはっきりした回答が導けなかったように思います。
まあ、もう受けてしまったのでなるようにしかならないと思いますので、6月の合格発表をじっと待ちたいと思います。

# 次の目標は
ネットワークの知識がホットなうちに、CCNPでも挑戦してみようかな？と思っています。
２０２０年に改定されてからだいぶ様変わりしているので、試験情報を調べるのにも情報が少なくて苦労しますが、、
AWSでWordPressブログをはじめてみた

# はじめに
awsを勉強として軽く触っていたのですが、1年間無料ということだったのでwordpressによるブログを開設してみました。その時に行ったことを軽くメモしました。

# 独自ドメインの取得 ~ wordpressの開設
基本的に以下の記事を参考に行いました。

* https://katsuhiroblog.com/aws-wordpress

* https://qiita.com/nakanishi03/items/25278fb4dfad60ebfac4
 
* https://100webdesign.jp/services/web_knowhow/aws-site/web_knowhow-21161

参考記事の通り、行えば基本的に誰でもwordpressのブログを開設できます。

大まかな手順は以下の通りです。

**1.　独自ドメインの取得**

　今回は「お名前.com」を利用。

**2.　EC2インスタンスの起動**

　AMIは、「AWS Marketplace」の「WordPress Certified by Bitnami and Automattic」を利用。

　また、インスタンスタイプは、1年間の無料利用枠対象の「t2.micro」を利用。

**3.　wordpressへログイン（確認）**

　サーバが作成されたので、wordpressのadminでログインできるか確認。

**4.　Elastic IP の割り当て**

　Route 53で独自ドメインとインスタンスを結びつけるために、Elastic IPアドレスを取得しておく必要があります。

**Elastic IPアドレス**とは、特定のリージョンのAWSアカウントに関連づけられた静的 IPv4アドレスです。自動割り当てされたパブリック IP アドレスとは異なり、Elastic IP アドレスは Virtual Private Cloud (VPC) でインスタンスを停止および開始した後も保持されます。

EC2インスタンス起動後に得られる、パブリックIPv4アドレスを独自ドメインを結びつけることも可能です。

しかし、パブリックIPv4アドレスは、インスタンスを停止して再起動するたびに、値が変わってしまい、その都度、ドメインと結びつけるIPv4アドレスを変更する必要があるので、値が変わらないElastic IPを用いる必要があります。

なお、Elastic IPは「EC2 ダッシュボード」から割り当てることができます。 

**5.　Route 53 で独自ドメインとインスタンスの紐付け**

お名前.comで取得した独自ドメインとインスタンスを紐付けすることで、サイトにアクセスできるようになります。

このとき、「レコードを作成」でインスタンスのElastic IPを入力するのを忘れないように！！(Elastic IP と ドメインをAレコードで対応づけ）

**6.　独自ドメインでwordpressにアクセス**

最後に、取得した独自ドメインでブログにアクセスできるか確認してみます。何か間違った操作を行っていなければアクセスできるはずです。

# まとめ
今回は、独自ドメイン取得からwordpressでブログ開設までを行いました。次は、セキュリティを強化するためにSSL化（httpからhttpsに）していきたいと思います。

# 参考
* https://katsuhiroblog.com/aws-wordpress

* https://qiita.com/nakanishi03/items/25278fb4dfad60ebfac4
 
* https://100webdesign.jp/services/web_knowhow/aws-site/web_knowhow-21161

* https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-associate-static-public-ip
GitHub - Read Me 画像をセンタリング(中央に配置)

# はじめに
若干, 苦戦をしたので共有します. 他のやり方・ご指摘があればコメントなどで教えていただけたら幸いです.

# 画像を中央に表示する方法.
結論からは, 以下の方法が1つ考えられる.

```
<p align="center">
  <img src="https://user-images.githubusercontent.com/(略)/test.jpg" />
</p>
```
コピペして使用する場合は"src="の部分に掲載したい画像のリンク(https~)を書けばよい.

# [補足]画像のリンクの取得.
以下の手順で画像リンクを取得できる.

```
1 . 自分のプロジェクトのIssuesをクリック.
2 . そこでNew Issueをクリック.
3 . そこで, 画像をドラッグアンドドロップ.
4 . すると, 画像リンクに変換してくれるので, そのリンクからhttps~の部分をコピペする.
5 . 上記のフォーマットに貼り付ければ, 画像をReadMeで中央配置できる.
```
Raspberry Piで自宅内のWindows機を起動させる (Wake-on-LAN)

# Wake-on-LANとは
Wikiをみると「Wake-on-LAN（ウェイク・オン・ラン、略称WoLあるいはWOL）は、コンピュータネットワーク（主にLAN）に繋がっているコンピュータの電源を遠隔で投入する技術あるいはその行為を指す。」らしいですね。

と。最近WindowsのVMWareで運用しているのですが、ちょいちょいフリーズしていることが多くて、WOLをつかってみました。結果便利でしたわｗ。

# やりたいこと
Rasberry Pi を VPNサーバとしているのでマジックパケットを送って立ち上げたい。マシンそのものがフリーズしたときは電源を落としたい！。Rasberry Piも同じようにしたい！！とまあ簡単に図で書くとこんな感じ。
ちなみに電源落とすには、後記しますがリブーターっていう装置が必要。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/8e5aef1e-0c94-55ea-75f2-edbcf4b69207.png)



## Windows側でWOLを設定する
その前にBIOSでWOLを受け入れてくれるように設定をする。メーカーによりBIOS設定する方法は違えど同じようでしょう。ちなみにLenovoはデフォルトでWOLが有効になっていた。

・[PCの電源が自動でオンになる事象を無効にする - ThinkPad](https://support.lenovo.com/hn/ja/solutions/ht105352)

### BIOSの設定
内蔵の有線LANのみ有効なのだろうか。。USBー有線LANからはWOLできなかった。まあいいか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/e3e99f3b-d2b6-0867-da49-dd7b0da5c19c.png)

### Windows側の設定
デフォルトで有効になっていたのでそのまま使うが忘れそうなのでメモっておきます。
ウエイク・オン・パターン・マッチ＝有効、ウエイク・オン・パターン・マッチ＝無効、にするという情報もあったがどちらも有効で問題なさそう。

・[RemoteView WOL設定ガイド](https://files.rsupport.com/jp/remotewol/documents/user-guides/remotewol-configuration-userguide-jp.pdf)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/96fec7e9-6279-6444-8aca-76b32ed5138c.png)

## Raspberry PiのWake on LANのクライアントの設定
``wakeonlan``っていうパッケージがあったのでそれをインストールする。
とりあえず使い方はシンプルで簡単ですな。 MACアドレスは ":" で区切る。

```text
% sudo apt-get install wakeonlan
% wakeonlan <マシンのMACアドレス>
Sending magic packet to 255.255.255.255:9 with XX:XX:XX:XX:XX:XX
```
## とりあえずWOLを試してみる
電源OFFして Pi から wakeonlan 叩いて起動確認してみる。ドキドキ・・・立ち上がってこないｗｗ
もしや？と思ってBIOSで起動メディアの順位を確認すると・・・「IPv4」が先頭になっていたので起動ドライブを先頭に修正したらあっさりうまくいった。

```text
>> Checking Media Presense......
>> Media Present......
>> Start PXE over IPv4. Press ESC key to abort PXE boot.
```

# 電源を切りたいんだよ！私は
Linuxは非常に安定しているのでフリーズなんてめったに発生しないですが、Windowsは長時間起動していると割とフリーズするイメージ（実際、半年に１度くらいはそうなる）なので物理的に電源を切りたいと思っていたら世の中には「リブーター」っていう製品があるんですね。

・[リブーターRPC-M2CSを買ってみた](https://d44.jp/?p=2568)

リッチな製品なのでヤフオクであるかな？と探してみると結構あるのですね。私は中古で 2000円位のを落札してみました。

## Raspberry Pi もWOLで起動したい
と思ったら、Raspberry Pi は、NICが内部的にUSB接続されているためダメだそうだ。あPCでも「USBー有線LANからはWOLできない」これか。。とりあえず Pi4 は落ちないからあきらめたｗ　※やり方はあるらしい

・[Raspberry Piの電源をリモートからOnにする方法](https://loneb.net/archives/2366)

# WOL送るツール
linux からでも リブーターからでも WOL送れるが、[nWOL](https://n-archives.net/software/nwol/) も便利そう。

WO
Pythonの再帰関数における出力パターン４つ

#はじめに
はじめて記事を書かせていただきます。
趣味で競プロをしている初心者プログラマです。
お見苦しい点などあるかと思いますがよろしくお願いいたします。

#きっかけ
競技プログラミングの勉強をしていて再帰関数というものに出くわしました。
自身を呼び出すという構造はなんとか理解しはじめているのですが、回数や総数をカウントして出力する方法がうまく咀嚼できませんでした。

#やったこと
検索してみるといくつか方法があるようで、人によって使いやすいものが異なるようです。
そこで調べて見つけた４つのパターンを整理のためにまとめてみました。

例として、１からｎまでの総和を考えます。


※この記事をはじめて投稿した際に例が特殊でわかりづらいとのコメントを頂きました。
　一度削除して修正したものとなります。ご指摘ありがとうございました。

※2021/4/26
　コメントにて各コードの短所ならびにもっと簡潔な書き方のご教示を頂きました。
悪い例示と自戒の意味もこめてコードの修正は初投稿からしておりません。
コメントありがとうございました。

#環境
Python 3.7.9

#パターン１：関数を戻り値とする
```python
def saiki(n):
    if n == 1:
        return n
    return saiki(n-1) + n

print(saiki(10))#55が表示される。
```
#パターン２：関数内で変数（ここではcnt）を定義して戻り値とする
```python
def saiki_cnt(n):
    if n == 1:
        return n
    cnt = 0
    cnt += saiki_cnt(n-1) + n
    return cnt

print(saiki_cnt(10))#55が表示される。
```
#パターン３：カウンターとなる引数を与える
```python
def saiki_arg_cnt(n, cnt):
    if n == 1:
        return cnt + n  
    return saiki_arg_cnt(n-1, cnt+n)

print(saiki_arg_cnt(10,0))#55が表示される。
```
#パターン４：グローバル変数でインクリメントする
```python
cnt = 0
def saiki_global_cnt(n):
    global cnt
    cnt += n
    if n == 1:
        return
    saiki_global_cnt(n-1)

saiki_global_cnt(10)
print(cnt)#55が表示される。
````
#所感
個人的にはパターン４のグローバル変数を使う方法が比較的わかりやすかったです。
答えとして別に変数を用意するというのが私にとって直感的なのだと思います。

間違いや改善点などあればご指摘いただけると幸いです。
railsを使ってapiを作成する時に特有の振る舞いをどうかいたらいいのか学んだことの備忘録

## この記事で書く事
railsを使って外部から参照されるapiを実装しようとしたときに、モデルに書きたくない処理が必要になり、それをどこにおくか、を考えた時に学んだ事。

## この記事で書かない事
細かいrailsでのそもそものapiの実装方法について

## 悩んだこと、考えたこと
アプリケーションA自体が持つモデルに対しての処理に関係ない、外部アプリケーションBから呼び出されるapiに対しての処理を、モデルに書いてもいいのかどうか。
限定的に呼び出される処理を隔離したかった。

### moduleに切り出す方法が最初はパッと浮かんだ。
ただ、それをやると、他のapiでもそのモデルに対しての処理でその内容が参照されてしまう。
そしてアプリケーションで使用されるこのモデルのインスタンス全てにその属性が参照可能になってしまう。

### active_model_serializersを使ってみる

https://github.com/rails-api/active_model_serializers

```ruby:controller
class API::UsersController
  def index
    render json: @users, serializer: ActiveModelSerializers,
           each_serializer: user_client_serializer
  end
end
```

```ruby:model
# :id, :name, :imageを列にもつ
class User
  # 細かいmodelの中身は省略
end
```

```ruby:serializer
class UserClientSerializer
  attributes :id, :name, :image # 全てのuserにひもづくattrを参照可能に
  attribute :user_type # このserializerだけが必要とするattrを追加

  def user_type # 特定のapi固有の属性で、モデルには書きたくない....
    return 0 if object.image.present?
    1
  end  
end
```

簡易な表記にしたのでこのままでは動きませんが、こうすることで、model自体にapi固有の処理を書かずに済みました。
別のapi経由でもuserを渡すことになったときに、今回例としてあげたuser_typeが不要だった場合は、以下のserializerを準備してあげることで、モデルに手を加えることなく、対応が可能です。

```ruby:serializer
class UserSerializer
  attributes :id, :name, :image
end
```

この作業をするまで、active_model_serializersを使ったことはなく、勉強になりました。
MicronautでLombokを利用する

# やりたいこと

MicronautでLombokを利用して開発する.
Java16でRecordが正式対応したのですが、まだ11を使っているし、Lombokはなんだかんだで便利なので使いたい.

# 設定方法

基本的なことは、公式サイトに記載されています.
[13.1.3 Using Project Lombok](https://docs.micronaut.io/latest/guide/index.html#lombok)
私は、Mavenを使っているので、Mavenでの説明します.

## lombokをdependency追加

```xml:pom.xml
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.20</version>
      <scope>provided</scope>
    </dependency>
```

## lombokのannotationの処理をmaven-compiler-pluginに追加

```xml:pom.xml
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <annotationProcessorPaths combine.self="override">
            <path>
              <!-- must precede micronaut-inject-java -->
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <version>1.18.20</version>
            </path>
            <path>
              <groupId>io.micronaut</groupId>
              <artifactId>micronaut-inject-java</artifactId>
              <version>${micronaut.version}</version>
            </path>
            <path>
              <groupId>io.micronaut</groupId>
              <artifactId>micronaut-validation</artifactId>
              <version>${micronaut.version}</version>
            </path>
          </annotationProcessorPaths>
        </configuration>
      </plugin>
```

あとは、LombokをIDEで使うための設定をします.
私は、Java開発もVS Codeを使うようになったので以下の拡張機能をインストールすることで対応可能です。
[Lombok Annotations Support for VS Code](https://marketplace.visualstudio.com/items?itemName=GabrielBB.vscode-lombok)
【HTML】リストについて簡単に整理

#HTMLで使われるリスト
本記事ではHTMLで使われるリストについて、私が勉強した範囲で簡単にですが、記録しておきます。
※2021/5/31　説明リストについて追記

#1.普通のリスト（liタグだけでの使用はNG）
`<li>　</li>`タグで囲むとリストとして箇条書きで羅列される。
~~単純にこれだけの記載はあまり使わないのでしょうか。~~

```HTML
<li>ノート</li>
<li>鉛筆</li>
<li>消しゴム</li>
<li>定規</li>
```
結果は以下。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584833/f886902f-4a4b-9079-562e-b9c4f60265a8.png)

#2.順序なし ul要素、順序あり ol要素
`<li>　</li>`タグで作っているリストを`<ul>　</ul>`タグで囲むと、順序なしのリストになる。
・ul：Unordered Listの略

```HTML
<ul>
  <li>ノート</li>
  <li>鉛筆</li>
  <li>消しゴム</li>
  <li>定規</li>
</ul>
```
結果は以下。
見た目的には1.の単純なリストとあまり変わらない印象。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584833/0861e569-074f-3f29-703c-899c431e22a8.png)

次に、`<li>　</li>`タグで作っているリストを`<ol>　</ol>`タグで囲むと、順序ありのリストになる。
・ol：ordered Listの略

```HTML
<ol>
  <li>ノート</li>
  <li>鉛筆</li>
  <li>消しゴム</li>
  <li>定規</li>
</ol>
```
結果は以下。
各項目の頭に番号がついた。
![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584833/a80b366b-f400-4cbd-306f-fbbb9090e3f6.png)

#3.入れ子にしたリスト
下記のような書き方をすれば、入れ子として使うこともできる。
ulとolを混ぜて使うことも可能。

```HTML
<ul>
  <li>ノート</li>
  <li>
    鉛筆
    <ol>
      <li>HB</li>
      <li>B</li>
      <li>2B</li>
    </ol>
  <li>消しゴム</li>
  <li>定規</li>
  </li>
</ul>
```
結果は以下。
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584833/b77d5fa6-ad28-5f5a-0fce-5663716e1450.png)


#3.説明リスト
用語とその説明をリスト化したもの。
複数の`<dt>`要素に対して一つの`<dd>`要素とすることもできる。


```HTML
<dl>
  <dt>Firefox</dt>
  <dt>Mozilla Firefox</dt>
  <dt>Fx</dt>
  <dd>
    A free, open source, cross-platform,
    graphical web browser developed by the
    Mozilla Corporation and hundreds of
    volunteers.
  </dd>
</dl>
```
結果は以下。
`<dd>`要素で囲った説明内容が少しインデントされて表示される。

![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584833/95cadc95-7cc7-5665-e7a3-a0e2febfb902.png)


こんな感じで理解しています。
これからも勉強記録として記事を書きたいと思うので、認識違いなどがあれば、コメントいただけますと幸いです。
GASで動的なサイトをスクレイピングする方法

## GASによるスクレイピング
ふと「GAS（Google Apps Script）でスクレイピングってできるのかな？」って思い調べてました。GASにはParserというスクレイピング用のライブラリが用意されていて、それを使うとスクレイピングが可能です。またGASには定期実行機能があるので、スクレイピングをするのに向いています。

「試しにスクレイピングしてみよう」と思ったら、1つ問題点がありました。スクレイピング用のParserライブラリですが静的なサイトのスクレイピングしかできず、JavaScriptが使われているような動的なページはスクレイピングできません。「困ったなー」と思い、調べてみると、PhantomJsCloudを使うことで動的なサイトのスクレイピングができることがわかりました。

## PhantomJsCloudとは
[PhantomJsCloud](https://phantomjscloud.com/index.html)とは、ヘッドレスブラウザのクラウドサービスです。公式には以下のような記載がありました。

> A web-browser hosted as a service, using Chrome (via Puppeteer or PhantomJs) to render your javascript heavy webpages as HTML, PDF, JPEG, PNG, or JSON.

元々PhantomJSがどういうものか知っていたので、「こんな感じのサービスかな〜」と名前を聞いて思いました。
これを使うことで、GASでも動的なサイトのスクレイピングが可能になります。



## GASとPhantomJsCloudを使ったスクレイピング
### PhantomJsCloudに登録
[PhantomJsCloud](https://phantomjscloud.com/index.html)にアクセスして、Sign upするとAPIキーを取得することができます。

![スクリーンショット 2021-04-10 21.11.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/af5f5b92-f02e-84bf-d4a3-8563f66e48cc.png)

1日500ページの取得までは無料らしいです。

### GASを書く
APIキーを取得したら、GASのスクリプトプロパティという機能を使って、APIキーを保管しましょう。
以下の関数を実行して、保存することができます。

```js:set_property.gs
function set_property(){
  // API_KEYを保存する
  PropertiesService.getScriptProperties().setProperty("API_KEY", "YOUR_API_KEY");
  // 確認用
  Logger.log(PropertiesService.getScriptProperties().getProperty("API_KEY"));
}
```

保存したら、実際にスクレイピングしてみます。
スクレイピングの関数は、以下です。

```js:scraiping.gs
function scraping(target_url) {
  // optionsを設定
  var options = {
    url: target_url,
    renderType: "HTML",
    outputAsJson: true
  };
  var pay_load = encodeURIComponent(JSON.stringify(options));
  // API_KEYの呼び出し
  const API_KEY = PropertiesService.getScriptProperties().getProperty("API_KEY");
  // リクエストを行うURLを設定
  var api_url = "https://phantomjscloud.com/api/browser/v2/"+ API_KEY +"/?request=" + pay_load;
  // 結果を取得
  var response = UrlFetchApp.fetch(api_url).getContentText();
  // JSONデータをパースして、欲しいデータを取得
  var data = JSON.parse(response)["content"]["data"];
  
  return data;
}

```

定義した関数を使って実際に動的なページのスクレイピングをやってみます。
今回は[自分のQiitaのページ](https://qiita.com/zumi0)をスクレイピングしてみます。

```js:scraiping.gs
function myFunction() {
  // QiitaのTOPページをスクレイピングする
  var url = 'https://qiita.com/zumi0';

  // 結果を取得し、確認してみる
  var html = scraping(url);

  // Parserライブラリと正規表現を使って、タイトルを取得する
  // 上手くタイトルが取得できなかった…
  var titles = Parser.data(html).from('<a href="https://qiita.com/zumi0/items/').to('/a>').iterate();
  var first_title = Parser.data(titles[0]).from('>').to('<').build();

  Logger.log(first_title);
}
```


## 最後に
今回はGASとPhantomJsCloudを使って、動的なページのスクレイピングをやってみました。スクレイピングの内容は拙いものでしたが、今後勉強してレベルアップしていきます！
Docker Desktop for mac を cli から削除する

# 背景
docker が mac で起動しているときってタスクバーにこの画像があると思うんですが
![スクリーンショット 2021-04-23 16.33.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94194/147be251-e876-3d15-2f90-810a2c1be9eb.png)

docker がなぜだか完全にクラッシュしてしまい、起動もしない、タスクバーにもない、再インストールしても動かない。アンインストールしたいけどアンインストーラも起動しない。
そんな状態になったときの対処が日本語の情報がなかったのでメモしておきます。

# 何に困るか
docker に限らないと思うんですが、うんともすんともいかなくなった時最終的には再インストールをすると思います。
しかし、docker for mac のアンインストールについて調べて出てくる日本語のほぼ全ての記事がGUIからアンインストールしましょうというものなので、
今回のようにタスクバーにも出てこなくなるとどうしようもなくなりました。

## 解決策
cliから関連ファイルすべてを削除することでアンインストールと同じ状態にします。
手順は以下の記事にありました。ちなみにベストアンサーはこちらもGUIでの削除なので、ベストアンサーは今回使えません。

https://stackoverflow.com/questions/44346109/how-to-easily-install-and-uninstall-docker-on-macos

そのため、下の方にあるcliでの手順を実施することでアンインストールできました。手順を書いておきます。
気をつけてほしいんですが、<font color="Red">コンテナもイメージもすべて消えるのでご承知おきください。</font>
また、`sudo` での　`rm`　を含みます。十分注意してください。私は一切の責任を持ちません。
以下すべてのコマンドをターミナルで打ちます。

```bash
sudo rm -Rf /Applications/Docker.app
sudo rm -f /usr/local/bin/docker
sudo rm -f /usr/local/bin/docker-machine
sudo rm -f /usr/local/bin/docker-compose
sudo rm -f /usr/local/bin/docker-credential-desktop
sudo rm -f /usr/local/bin/docker-credential-ecr-login
sudo rm -f /usr/local/bin/docker-credential-osxkeychain
sudo rm -Rf ~/.docker
sudo rm -Rf ~/Library/Containers/com.docker.docker
sudo rm -Rf ~/Library/Application\ Support/Docker\ Desktop
sudo rm -Rf ~/Library/Group\ Containers/group.com.docker
sudo rm -f ~/Library/HTTPStorages/com.docker.docker.binarycookies
sudo rm -f /Library/PrivilegedHelperTools/com.docker.vmnetd
sudo rm -f /Library/LaunchDaemons/com.docker.vmnetd.plist
sudo rm -Rf ~/Library/Logs/Docker\ Desktop
sudo rm -Rf /usr/local/lib/docker
sudo rm -f ~/Library/Preferences/com.docker.docker.plist
sudo rm -Rf ~/Library/Saved\ Application\ State/com.electron.docker-frontend.savedState
sudo rm -f ~/Library/Preferences/com.electron.docker-frontend.plist
```

自分は上記コマンドですべて削除した後にdockerを再インストールすることができました。
Fusion360でProperty Change Failedエラー

![Screen Shot 2021-04-24 at 23.54.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/c54bbf90-39d5-8625-a7d0-414bebbe04dc.png)

`Push Violators`モードに入っているのでそれを解除すればよい。
`Ignore Violators`をクリックすれば変更できるようになる。

## 参考

https://forums.autodesk.com/t5/fusion-360-electronics/property-change-failed-a-k-a-proactive-drc/td-p/9682405
OCIでsambaサーバを立てたら接続がなんか遅い

# はじめに
当記事の内容はかなり限定された環境のため、余り役に立たないかもしれません。

## 環境

 - OCI上でhost1を作成。Oracle Linuxを使ってsamba AD-DCを構築、Windowsドメインネットワークを作成
 - 同じくOCI上でhost2を作成。Freenasを使ってSMBファイル共有用で構築、host1のドメインに参加
 - host1、host2ともに同一のvcnプライベートサブネットに接続

## 現象

FreenasでのSMB接続が遅い。転送は遅くない。
host1、またはhost2でsmbclientコマンドをFreenasに向かって実行するとコマンドの返りに3秒程度かかる。

```
@host1# smbclient -L host2 -U administrator
約3秒待つ...
        Sharename       Type      Comment
        ---------       ----      -------
        share           Disk
        IPC$            IPC       IPC Service (host2 Server)
NetBIOS over TCP disabled -- no workgroup available 
```
上記の様な感じ。応答内容は至って正常。
host2はドメインにも正しく参加出来ているため、名前解決回りは考え難そうだが、症状としては名前解決が遅い感じ。

## 原因

VCNのサブネットに設定しているDHCPオプションに登録していた検索ドメインでhost2の名前を解決できなかったから。
host2はwindowsドメインに参加していたため、リゾルバがhost1に向いていた。且つ、host1で稼働させていたsamba AD-DCのDNSフォワーダを適当に `8.8.8.8`とかにしてしまっていたため。
上記環境だとVCNの検索ドメイン `hogehoge.oraclevcn.com`が探せなくなり、タイムアウトを待つしかなくなる。

## 解決方法
下記のいずれかを実行する。

 - host1のsamba AD-DCのDNSフォワーダを `169.254.169.254`にしてあげる。
 - host2の `/etc/hosts`に対象ホスト名を記述する。  
    例)127.0.0.1 host2.hogehoge.oraclevcn.com

この他、VCNのDHCPオプションで何かやれば上手くいくかもしれないけど、ちょっと分かりません:sweat:

## まとめ
VCNの内部DNSは有用なものとは思いますが、使い方をキチンと把握していないとこのような目に遭います。
オンプレでは出なかった問題なので解決するまでに時間を要しました。

# おわりに
パブリッククラウドを使うときは闇雲に使わず、ちゃんと使い方を学ばないとアカンですね。
【Go】gormで外部キー制約を貼れない時は、従属テーブルの型を確認する

# なにこれ
筆者がgolangとgormで遊んでる時に、数時間も↓のエラーに悩まされたため、備忘録として残します。

`
Error 3780: Referencing column 'book_id' and referenced column 'id' in foreign key constraint 'book_details_book_id_books_id_foreign' are incompatible. 
`

# 結論
従属テーブルの型を`uint`型に変更すると解消する。

# 経緯
下記の`Book`テーブル（親）と`BookDetail`テーブル（子 or 従属）がありました。

```.go
type Book struct {
	gorm.Model
	BookDetail BookDetail
}

type BookDetail struct {
	gorm.Model
	BookID      int
}

```

↑の状態で、gormの`AddForeignKey`をやるとエラーを吐きます

```migrate.go

func Migrate() {
	db.AutoMigrate(&model.Book{})
	db.CreateTable(&model.BookDetail{})
	db.Model(&model.BookDetail{}).AddForeignKey("book_id", "books(id)", "CASCADE", "CASCADE")
}

```

↓結果

`Error 3780: Referencing column 'book_id' and referenced column 'id' in foreign key constraint 'book_details_book_id_books_id_foreign' are incompatible. `

訳）エラー3780：外部キー制約「book_details_book_id_books_id_foreign」の参照列「book_id」と参照列「id」に互換性がありません。

簡単にまとめると、mysqlでIDの型が一致しない場合に起きるエラーです。

## 試したこと
`BookDetail struct`の`BookID`の型を`int`型から`uint`型に変更しました。

```.go
type BookDetail struct {
	gorm.Model
// 	BookID      int
    BookID      uint 	
}
```

## 理由
`Books`テーブルの`ID`の型は、↓の画像の通り`int unsigned`になってるから。
そちらに合わせてあげれば、型が一致するので解決します。
![スクリーンショット 2021-04-24 23.46.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629015/69fa7082-f2ca-05bd-142d-6d240d756e43.png)

### 余談
`unsigned`とは

> 整数型は正の数と負の数を扱うことができますが、データ型の後に UNSIGNED を付けると 0 と正の数しか格納できなくなります。このようなデータ型を符号なし整数型といいます。

参考：[整数型(TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT)](https://www.dbonline.jp/mysql/type/index1.html#section2)

gormがuint型でIDを作成するから、それに合わせる必要があるって感じでした。

## 感想
Goを触り始めて2週間ほどですが、
以外にもMySQLのエラーでハマるとは思ってませんでした！
まだまだ知らないことがたくさんありました。
Dockerでrailsを開発している時のwebpackerを更新する時の道のり

## この記事で書く事
- Dockerを使用したrailsアプリケーション開発で、webpackerを更新するときに発生した躓きポイントについて

## この記事で書かない事
- そもそもwebpackerって何？
- Dockerを使ったRailsアプリケーション開発の一般的な情報。


## 基本的なステップについては公式を確認する。 :cat2: 
https://github.com/rails/webpacker#upgrading

このupgradingに沿って進めていた所、

```
rails webpacker:install
```

こちらを実行した所、node.jsが古いと言われた。

## Node.jsを更新する。

Node.jsの安定版は現在以下。
https://nodejs.org/ja/



今回使用しているイメージがlinuxなので、bashコマンドを使用します。


```
docker container exec -it コンテナ名 bash
```

```
# バージョンはその都度変わるかと思います。
curl -sL https://deb.nodesource.com/setup_14.x | bash
```



```
apt-get install -y nodejs
```


```
# node -v
v14.16.0
```

OK. 無事にバージョンを更新できた。
height以外の方法も！？高さを指定できる7つの方法

#どうも7noteです。要素に高さを持たせる方法を紹介。

HTMLの要素に高さを持たせるならCSSでheightを指定するのが一般的。
ですが、**heightを使わなくても高さを指定する方法もあります。**


いろいろな高さの設定方法を紹介。
マニアックな高さをもたせる指定方法もあります。

## ① height

```style.css
div {
  height: 100px; /* 高さ指定 */
}
```

まずは通常のheightの指定方法です。
pxやvhなどで指定ができます。

## ② min-height, max-height

```style.css
div {
  min-height: 100px; /* 最低高さを指定 */
  max-height: 500px; /* 最大高さを指定 */
}
```

通常のheightの指定とは違い、最低と最大を指定できます。基本的には親要素や子要素に準じますが、指定値を超えようとすれば制限がかかるようにできます。


## ③ padding

```style.css
div {
  padding: 30px 0; /* 余白を指定 */
}
```

余白を上下に取る事で高さを保持できます。
これはボックスモデルというHTMLのルールから高さを持つようになっています。
ボックスモデルでは、borderも高さに含まれるので要注意。

ボックスモデル、詳しくは→https://qiita.com/7note/items/ddce7f23cd075ad9431e

## ④ line-height

```style.css
div {
  line-height: 1.5; /* 行間を指定 */
}
```

line-heightは文字の行間を指定するものです。
文字も高さを持っていますが、さらにこの行間も高さを持っています。
大きい数字を指定すればそれだけ上下に余白(正確には行間)ができ、高さを調整することができます。
ただし行間なので、文章が2行になってしまうところには使えないかも。


## ⑤ table

```index.html
<table>
  <tr>
    <th></th>
    <td></td>
    <td></td>
  </tr>
</table>
```

テーブルはヨコ一列同じ高さになるようにできています。
そのため他の横にある1番高い要素に合わせて高さが変わります。


## ⑥ flexbox

```style.css
div {
  display: flex; /* 横並びにする */
}
```

flexboxもテーブルと似たような効果があり、横並びにした場合、要素の高さは1番高いものに揃うようになります。

ただし、align-itemsを指定してしまうと高さが揃う効果が解除されてしまうので注意！


## ⑦ jsのライブラリなど

jsを使う事で高さを揃えたり、変更したりすることができます。
基本的にはheightの指定をjsで行なっているだけのものが多いかなと思います。
高さを揃えるライブラリなどもありますよ。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
[Swift5] XMLParserでXML解析

##XMLParserの使い方メモ
・XMLParserDelegateを継承する
・メソッドの実装(didStartElement/foundCharacters/didEndElement)

```Swift
class ViewController: UIViewController,XMLParserDelegate,UIViewControllerTransitioningDelegate {
    
    var userName = String()
    var profileImageUrl = URL(string: "")
    @IBOutlet weak var meigenLabel: UILabel!
    @IBOutlet weak var toFeedButton: UIButton!
    @IBOutlet weak var profileImage: UIImageView!

    var parser = XMLParser()
    
    var feedItem = [FeedItem()]
    var currentElementName:String!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        toFeedButton.layer.cornerRadius = toFeedButton.frame.width/8
        self.navigationController?.isNavigationBarHidden = true
        
        //XML解析
        let url = "http://meigen.xxxxx.xxx/"
        let urlToSend = URL(string: url)
        parser = XMLParser(contentsOf: urlToSend!)!
        parser.delegate = self
        parser.parse()
    }
    
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        
        currentElementName = nil
        
        if elementName == "data"{
            self.feedItem.append(FeedItem())
        }else{
            currentElementName = elementName
        }
    }
    
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        
        if self.feedItem.count > 0{
            //meigenとautherを処理していく
            let lastItem = self.feedItem[self.feedItem.count - 1]
            
            switch self.currentElementName {
            case "meigen":
                lastItem.meigen = string
            case "auther":
                lastItem.auther = string
                meigenLabel.text = lastItem.meigen + "\n" + lastItem.auther
            default:
                break
            }
        }
    }
    
    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        currentElementName = nil
    }
}
```
【WordPress】カスタムスタイル追加方法

WordPressのグーテンベルグで、デザイン違いのパーツを作成したい場合にはカスタムスタイルを追加する方法で簡単に作成することが可能です。  
## functions.php
functions.phpに`register_block_style（）`を追加します。

```php:functions.php
// カスタムスタイル追加
register_block_style(
    'core/paragraph', // ブロック名
    [
        'name'         => 'attention', // スタイルで付けるクラスに使う名前
        'label'        => '注意文',
    ]
);
```

register_block_style()を記述することで管理画面の投稿画面で「注意文」のスタイルが選択できるようになります。
![altText](https://i.gyazo.com/96f40044f6ce5124c965883722d14d1e.png)

labelの値が画面に表示されます。注意文のスタイルを選択することでis-style-attentionのクラスがHTMLに付与されるので、CSSを調整することでデザイン違いのパーツを作成出来ます。
クラス名はis-style-hogeとなるのでhogeの箇所をnameで指定しましょう。
ブロック名を指定することでデフォルトで用意されているブロックは指定できます。

カスタムブロックを新規で作成するより、カスタムスタイルは手間なく追加できるので
この方法で対応できる場合はカスタムスタイルを使いましょう。
FastAPIにCognito認証を導入する

FastAPIにCognito認証を導入していきます。結論から言うと[FastAPI Cloud Auth](https://github.com/tokusumi/fastapi-cloudauth)というパッケージを使用するだけで簡単にできます。ありがたいですね。Cognitoの設定については触れないので別の方の記事をご参照ください。

##FastAPIサンプルコード
基本的にはgithubのREADMEを読んでいただければわかると思いますが、参考までにサンプルコードです。リージョンとユーザープールIDは事前に環境変数に設定しておきます。

```sample_auth.py

import os

from fastapi import FastAPI, Depends
from fastapi_cloudauth.cognito import Cognito


app = FastAPI()
auth = Cognito(region=os.environ["REGION"], userPoolId=os.environ["USERPOOLID"])

@app.get("/", dependencies=[Depends(auth.claim())])
def sample():
    return 'Success!'
```

##動作確認
###IDトークンの取得

```get_token.py
import base64
import getpass
import json

import boto3


def cognito_auth(user, passwd):
    # 認証開始
    try:
        cognito_idp = boto3.client('cognito-idp')
        cognito_result = cognito_idp.admin_initiate_auth(
            UserPoolId = "your user pool id",
            ClientId = "your client id",
            AuthFlow = "ADMIN_NO_SRP_AUTH",
            AuthParameters = {
                "USERNAME": user,
                "PASSWORD": passwd,
            }
        )
        return cognito_result
    except:
        # 認証失敗
        return None

if __name__ == '__main__':
    # cognito認証
    username = input('cogito username: ')
    password = getpass.getpass('cogito password: ')
    cognito_result = cognito_auth(username, password)
    print(cognito_result["AuthenticationResult"]["IdToken"])
```

###Swagger UIで確認
docsの「Authorize」ボタンから上で取得したIDトークンを入力。入力後に実行できればOKです。
![qiita-cloudauth01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051954/02495521-1eda-e31a-90d3-1710173cf7f6.png)
FizzBuzz関数

```php
<?php

    function fizzbuzz($num){
        
        if(($num%3==0) && ($num%5==0)){
         return 'FizzBuzz';
        }
        elseif($num%3==0){
            return 'Fizz';
        }
        elseif($num%5==0){
            return 'Buzz';
        }
        else{
            return $num ;
        }
       
    }
  
     
    $max=100; 
    for ($i=1; $i<=$max; $i++){
        print fizzbuzz($i).PHP_EOL;

    }
 ?>
```