OmniAICreator/Qiita-1.07M huggingface dataset:
【Pandas】基礎1(DataFrame, Series)

# はじめに
機械学習や深層学習が人気の昨今、
データを加工し、前処理を行う機会が非常に多くなってきた。

データ処理方法は様々存在するが、そのデータ処理ツールの一つとしてpythonのpandasが存在する。

そこで、今回は[公式のpandasのintro記事](https://pandas.pydata.org/docs/getting_started/index.html#intro-to-pandas)を参考に
pandasの基礎にDaraFrame、Seriesについて記していく。

# そもそもPandasはどのようなデータを扱うのに適しているのか？
表形式のデータを扱うのに非常に適している。
例えば、エクセルやSQLといったデータだ。

pandasを利用することでデータの検索やデータの処理などを行うことができる。

# DataFrame
pandasが使えるデータテーブルのことである。

下の図のように、行（rows）列(columns)で構成されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/f62b9115-112b-46d6-0bd0-cb905a20f0d2.png)

## pythonでの記述方法

手動でdataframeを作成するには、pythonのdictonaryを使用する。

dictonaryのキーがDataFrameの列のheadとして、　dictonaryのリストがDataFrameの行となる。

```python
df = pd.DataFrame({
        "Name": ["Braund, Mr. Owen Harris",
                 "Allen, Mr. William Henry",
                 "Bonnell, Miss. Elizabeth"],
        "Age": [22, 35, 58],
        "Sex": ["male", "male", "female"]}
     )
```
### 出力結果
![スクリーンショット 2020-11-28 21.35.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/f49646e2-6041-4f61-9370-2183a29ddda8.png)


# Series
SeriesとはDataFrameの各列のことを言う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/8cf99469-8ab6-7ca1-4e83-3ffe06ddda62.png)

イメージは以下の通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/3be90d47-c6af-fba7-e99b-152dfbbf4908.png)

## pythonでの記述方法
例として、上記のDataFrameから'Name'を取得してみる。

```python
series = df['Name']
```
もしくは、手動で作成することもできる。

```python
series2 = pd.Series(["Braund, Mr. Owen Harris",
                     "Allen, Mr. William Henry",
                     "Bonnell, Miss. Elizabeth"],
                     name = 'Name'
          )
```
### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/887e295e-8cfd-b1d1-abb5-c949cc37c885.png)

# まとめ
- DataFrame
    - pandasで扱うデータのテーブル
- Series
    - DataFrameの各列のこと
    
# 参考
- https://pandas.pydata.org/docs/getting_started/index.html#intro-to-pandas
Windows10で CUDA10.2をインストール

#はじめに
Windows10にCUDAドライバを以前入れていたものの、TensorflowやPyTorchでうまく動作しなくなり、しばらくGPUなしで動かしていたが、いい加減バージョンアップしてみた。

#きっかけ
ある日PyTorchでこんなエラーが。よし、上げよう。

```
RuntimeError: The NVIDIA driver on your system is too old (found version 10010). Please updat							
							
e your GPU driver by downloading and installing a new version from the URL: http://www.nvidia							
							
.com/Download/index.aspx Alternatively, go to: https://pytorch.org to install a PyTorch versi							
							
on that has been compiled with your version of the CUDA driver.							
```

#現状調査
そもそもインストールされているPyTorchのバージョンはというと、

```
pytorch                   1.7.0           py3.7_cuda110_cudnn8_0    pytorch						
torchvision               0.8.1                py37_cu110    pytorch						
```
なんかしらんが11用が入っている。

現状インストールされてCUDAは？

```
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver					
Copyright (c) 2005-2017 NVIDIA Corporation					
Built on Fri_Sep__1_21:08:32_Central_Daylight_Time_2017					
Cuda compilation tools, release 9.0, V9.0.176					

```

9.0だ。

#WindowsでPyTorchを使うための最適なCUDAのバージョンは？

PyTorchのホームページを見てみる。これによると、
PyTorch1.7, CUDA 10.2の組み合わせがよさそう。よって10.2をインストールすることにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329816/fb2d7722-043e-8408-608b-c1d454ce45bf.png)

#インストール
NVIDIAのホームページより、Windows10用の10.2のドライバをダウンロードしインストールする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329816/dbeae4ac-fd3e-9a74-ee46-3fdf9011d483.png)

上記よりBase Insataller、Patch1, Patch2を順にダウンロード、インストールしていくだけ。

#インストール後の確認

```
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Wed_Oct_23_19:32:27_Pacific_Daylight_Time_2019
Cuda compilation tools, release 10.2, V10.2.89
```

10.2がインストールされている。

環境変数も以下の通り、10.2がCUDA PATHに設定されている。

```
CUDA_PATH='C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2'								
CUDA_PATH_V10_2='C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2'								
CUDA_PATH_V8_0='C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0'								
CUDA_PATH_V9_0='C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0'								
CUDA_PATH_V9_1='C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.1'								
```

#PyTorchのインストール
```
conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch
```

無事CUDA 10.2用のものがインストールされていることを確認。

```
$ conda list |grep torch
pytorch                   1.7.0           py3.7_cuda102_cudnn7_0    pytorch
torchaudio                0.7.0                      py37    pytorch
torchvision               0.8.1                py37_cu102    pytorch
```


この後はPyTorchのモデルを実行するなりして、実際に動作することを確認すればよい。
SteamVRでOculus Riftが認識されなくなった際の解決方法

#目次
・概要
・環境
・不具合の状況
・解決方法

#概要
SteamVRでOculus Riftが認識されなくなった際の解決方法です。

#環境
Windows10
Oculus Rift
Oculus Quest(パソコンに繋げて使用した事がある状態)

#不具合の状況
Oculus Riftを使用していて、SteamVRを起動した際に
「ヘッドセットがスタンバイ中
　ヘッドセットを復帰させるには、動かしてください。」
の表示がでて、SteamVRのルームセットアップの「トラッキングを確立する」の画面でも「ヘッドセット障害物あり」で「次へ」ボタンが押せない状況が発生しました。

![ヘッドセットがスタンバイ中.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126821/c9bde0c6-36c3-bed3-f099-f096b745a6d6.png)

![ルームセットアップでヘッドセットを認識しない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126821/21c7a822-cea4-ca84-9728-84c8819f1b75.png)


Oculusアプリ、Steam、SteamVR、パソコンの再起動、各種ケーブルの差しなおし、SteamVR、Steamの再インストールなどを試しましたがどれも効果なし

SteamVRトラブルシューティング
(https://support.steampowered.com/kb_article.php?ref=8566-SDZC-9326&l=japanese)
の項目を全て試すもどれも効果なしでした。

この状況でもOculusのアプリでは正常に認識されている状態で、OculusのVRアプリは起動して正常に動作しており、SteamのVRゲームも「Oculusモードで起動」ができるゲームであれば正常に動作していました。


#解決方法
Oculusアプリのアンインストール後、再インストール、再セットアップで直りました。
Oculusアプリは以下のURLからダウンロード可能です。
https://www.oculus.com/rift/setup/?locale=ja_JP

以下の画像はRiftでSteamVRを起動している際の画像ですが、不具合が発生している時のSteamVRのアイコンの画像をよく見ると確かにRiftのアイコンではなくQuestのアイコンが表示されていました。

![SteamVRHomeプレイ中rift.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126821/8e147f40-c82e-2f10-e31a-0b821188a3fd.png)
↑がOculus Riftと接続している場合のアイコン。
↓がOculus Questと接続している場合のアイコン。
![ヘッドセットがスタンバイ中.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126821/948391cc-d956-af32-ce1d-bb72d611d599.png)



そこに気がつければもう少し早く解決できたかもしれません。
もしOculusアプリの再インストール以外で解決できた方がいたらコメントなどして頂けると幸いです。
もしくはOculusアプリかSteamVRのアップデートで接続するHMDを選択できるようになれば解決しそうですが、それまではこの方法が誰かの役に立てばと思います。
Unityで可読性の高いアプリケーション開発をする方法

# はじめに
Unityは自由度が高いため、人によってヒエラルキー構成であったり、スクリプトの実装方法などに大きなばらつきが生じます。
これにより、誰かが作ったUnityプロジェクトを見る際に、処理のフローが掴みづらく、この機能はなんで動いているんだろう？といった疑問を持った経験がある方は少なくないかと思います。
この問題を解決すべく、どのようなフローで処理が行われているかを把握しやすくした、普段私が実際に行っているUnityでのアプリケーション開発手法についてご紹介します。


# まず結論
- エントリーポイントを定義する
- ヒエラルキー構成を階層化し責務を明示化する
- エントリーポイントを定義したMainスクリプトで処理をハンドリングする


# なぜわかりにくいのか？
Unityの処理のフローが分かりづらい要因として、エントリーポイントが明示的にないことが挙げられます。
例えば、至るスクリプトでStart()が記述されている場合、Start()の実行順序はランダムであるため、どのスクリプトのStart()から呼ばれるかは保証されません。
そのため、スクリプトからはどういう処理フローになっているかを読み解くことは非常に困難です。


# 解決策
そこで、エントリーポイントとなるStart()を一つのスクリプトのみで記述し、その他のスクリプトではInitialize()といったメソッドを用意して、Start()からInitialize()を呼びます。
これをすることにより、Start()は一つしか存在しないため、そこから処理をたどっていくことが可能となります。

※GameObjectのライフサイクルの問題などで、処理上どうしてもStart()が複数必要になるケースは棚上げします。


# 実装例
実際どのように実装するか一例をご紹介します。

## 開発環境
- Windows 10 Version 20H2
- Unity 2020.1.14f1
- UniTask Ver.2.0.37

## ヒエラルキー構成
Mainと命名したGameObjectをルートに作成し、その配下にGameObjectを役割ごとに階層構造に配置します。個人的には以下のような構成にするのが分かりやすくておすすめです。
ここで少し話が逸れますが、細かくプレファブ化をすることで、チームで一つのUnityプロジェクトをGitを使って開発する際に、同時に同じプレファブをいじらないようにすることで競合が起こりにくくすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156022/8775ad0c-18bc-f0c3-c539-721997488cd8.png)

## Mainスクリプトの作成
Main.csを作成し、そこでエントリーポイントとなるStart()を記述します。Start()の中でその他のスクリプトのInitialize()を呼び、初期化処理を行います。また、それぞれの機能を実装したスクリプトのメソッドをMain.csから呼ぶことで、処理のフローの管理もしやすくなります。
これにより、Main.csを見れば大体の処理のフローを掴めるようにすることができました。
（今回の例では、カスタマイズ性が高いので、UniTaskでUpdate処理を置き換えています。）


```csharp:Main.cs
using Cysharp.Threading.Tasks;
using System.Threading;
using UnityEngine;

public class Main : MonoBehaviour
{
    [SerializeField] private PlayerController m_PlayerController = null;
    [SerializeField] private AudioManager m_AudioManager = null;
    [SerializeField] private DataManager m_DataManager = null;
    [SerializeField] private InputManager m_InputManager = null;
    [SerializeField] private UIManager m_UIManager = null;
    [SerializeField] private XRManager m_XRManager = null;

    /// <summary>
    /// エントリーポイントです。
    /// </summary>
    private async UniTask Start()
    {
        await InitializeAsync();

        UpdateLoop(this.GetCancellationTokenOnDestroy()).Forget();
    }

    /// <summary>
    /// 初期化処理を実行します。
    /// </summary>
    private async UniTask InitializeAsync()
    {
        m_PlayerController.Initialize();
        m_AudioManager.Initialize();
        m_DataManager.Initialize();
        m_InputManager.Initialize();
        m_UIManager.Initialize();
        m_XRManager.Initialize();

        await UniTask.Yield();
    }

    /// <summary>
    /// Update処理を実行します。
    /// </summary>
    private async UniTaskVoid UpdateLoop(CancellationToken cancellationToken)
    {
        while (true)
        {
            // Updateで実行する処理をここに記述します。

            await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken);
        }
    }
}

```


# まとめ
Mainスクリプトを読めば大体の処理のフローが分かるという安心感は、実装者側も読む側もハッピーにしてくれます。Unityは作るアプリケーションによって、適した構成も変わるので一概には言えませんが、処理のフローを分かりやすく作りたいと思っている方は参考にしてみてください。
すべてのUnity使いに幸あれ。
FizzBuzz(通常 / 再帰 / クラス)

# はじめに

なんか書き殴りたくなったので書きます。

プログラム始めたばかりの時は、

**「オブジェクト指向…？？」**

**「再帰？？？」**

みたいな印象だったのですが、気付いたら書けるようになってました。嬉しい。

備忘録的に残しておきます。
壮大なもの書こうかと思ったんですが、初心に帰ってFizzBuzzで

## 補足

①この記事では「これがFizzBuzzだ」みたいな話はしません
定義は下記に記しますがその定義があっているかどうかは議論しません。

②再帰的な書き方だったりクラスの書き方はもっと良い方法あると思います。
そんな時は是非マサカリが欲しいです。

> 定義
・1~100を順番に表示する
・3と5の倍数の場合[FizzBuzz]と表示する
・3の倍数の場合[Fizz]と表示する
・5の倍数の場合[Buzz]と表示する

## 通常ver

```js
for (let i = 1; i <= 100; i++) {
  const Fizz = 3;
  const Buzz = 5;
  if (i % (Fizz * Buzz) === 0) {
    console.log(i, "FizzBuzz");
  } else if (i % Fizz === 0) {
    console.log(i, "Fizz");
  } else if (i % Buzz === 0) {
    console.log(i, "Buzz");
  } else {
    console.log(i);
  }
}
```

まぁ他にも書き方あると思いますがとりあえず次。

## 再帰ver

```js
const FizzBuzz = (i, lastNum) => {
  const Fizz = 3;
  const Buzz = 5;
  if (i % (Fizz * Buzz) === 0) console.log(i, "FizzBuzz");
  if (i % Fizz === 0) console.log(i, "Fizz");
  if (i % Buzz === 0) console.log(i, "Buzz");
  if (i === lastNum) return;
  console.log(i);
  return FizzBuzz((i += 1), lastNum);
};

FizzBuzz(1, 100);
```

書いてから気付いたんですがFizzBuzzが再帰に向いてない気がする。
なんか書いてて再帰の良さみたいなものを表現できなかった…

## クラスver

```js
class CheckNumbers {
  constructor(i, Fizz, Buzz) {
    this.i = i;
    this.Fizz = Fizz;
    this.Buzz = Buzz;
  }

  main() {
    this.checkFizzBuzz();
    if (this.i === 100) return;
    return this.main((this.i += 1));
  }

  checkFizzBuzz() {
    if (this.i % (this.Fizz * this.Buzz) === 0) console.log(this.i, "FizzBuzz");
    if (this.i % this.Fizz === 0) console.log(this.i, "Fizz");
    if (this.i % this.Buzz === 0) console.log(this.i, "Buzz");
    if (this.i !== 100) console.log(this.i);
  }
}

new CheckNumbers(1, 3, 5).main();
```

なんかもっとよく書こうと書いてるうちに飽きてしまった…


もっとええ書き方あるで！っていう場合は是非教えてくださいm_ _m
Cloud9 の nodejs をバージョンアップ


AWS Cloud9 は環境構築直後、古い`nodejs`のバージョンが入っていたりする。
なので自分が使いたい任意のバージョンを入れる。

```bash
# 環境を確認
$ cat /etc/system-release
Amazon Linux AMI release 2018.03

# インストール前のバージョンを確認
$ node -v
v10.23.0

$ npm -v
6.14.8

# インストール可能なバージョンを確認
$ nvm ls-remote
:
       v12.20.0   (Latest LTS: Erbium)
:

# インストール
nvm install v12.20.0
nvm alias default v12.20.0
npm update -g npm
npm install -g npm

# インストール後のバージョンを確認
$ node -v
v12.20.0

$ npm -v
6.14.9
```
MatlabでLINEにメッセージを送る

# はじめに

最近、MATLABで機械学習もどきを行っている。
そうすると、いつ学習が終わるのかとソワソワしてしまうので、それの予防に重宝する。

# できること

メッセージ・画像・スタンプの通知ができる。
なお、ここでのコードではメッセージの送信のみを想定している。

また、こちら(自分のLINEアカウント)からのメッセージには反応しない(APIの制限)。

# 環境
* MATLAB R2020a

# 準備
事前にアクセストークンを発行しておく。
参考: [アクセストークンの発行](https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E7%99%BA%E8%A1%8C)

# 実装

```MATLAB:LINE_Notify.m
function status_code = LINE_Notify(token, msg)
% input->token: YOUR access token for LINE Notify
%        msg: your message

    arguments 
        token (:, :) char = 'YOUR ACCESS TOKEN'
        msg (:, :) string = "test message from MATLAB"
    end

    url = "https://notify-api.line.me/api/notify";
    
    opt = weboptions('HeaderFields', {'Authorization', ['Bearer ', token]});
    response = webwrite(url, 'message', msg, opt);
    status_code = response.status;
end
```

## (申し訳程度の)解説
MATLABにはWEBアプリ操作に、HTTPインターフェースとRESTful Web サービス関数のどちらかを使える。
今回使用した`weboptions`や`webwrite`はRESTful Web サービス関数の一種。
なお、HTTPインターフェースのほうが複雑なことができるらしい。

LINE NotifyのAPIを叩くには、認証して貰う必要があるので、`opt =`以下のヘッダの設定が必要となる。
あとは、URLとメッセージ、`opt`を`webwrite`の引数にして渡す。
実行できたかの確認に、一応HTTPステータスコードを返している。いらないかもね。

HTTPインターフェースを使ってもできるんだろうけど、
僕がやるとメッセージを渡していても「メッセージが空だよ」とコード400を返されたので諦めた。
誰か、こっちでできた人いたらコメントください。

# 参考
* [LINE Notify公式](https://notify-bot.line.me/ja/)
* Pythonでやるなら[こちら](https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9)
【Tips】TerraformでAPI Gatewayを構築しているときに出る ConflictException の回避手段

# はじめに
Terraform で API Gateway を構築していて、メソッドや統合を多用していると、たまに

```
Error: error deleting API Gateway Integration Response (xxxx-xxxxxxxxxx-xxxxxx-PUT-500): ConflictException: Unable to complete operation due to concurrent modification. Please try again later.
```

みたいな感じでエラーが出て悩まされることがある。

これはおそらく、API Gateway を更新する API(Terraform が裏で叩いていると思われるもの)が、並列処理に対応していない(処理を排他している)と考えられる。
Terraform はお利口なので、依存関係のないリソースについてはなるべく並列で処理をして高速化をしてくれる。この仕様が仇になって、排他処理しているところに並列でAPIを叩きんでエラーになっているようだ。

# 対処策
## その1: もう一度 ```terraform apply``` する
一番原始的な方法。別に HCL が悪いわけではないので、ConflictException が出ている限りは何度も apply すれば良い。でもこれ、他のエラーとか見落としてしまうとかありそうだよね……。

## その2: Terraform の実行並列度を下げる
こんな感じ。

```shell-session
$ terraform destroy --parallelism=1
```

別に 1 多重まで落とす必要はないのかもしれないけど、冪等性を考えるなら絶対に処理が並列にならない 1 を指定すべき。リソースがいっぱいあるとめちゃくちゃ遅くなるので選択したくない案。

## その3: 排他される処理については ```depends_on``` で順序性を持たせる
仕方がないので、```aws_api_gateway_integration_response``` のように排他されるリソースについては、全部 ```depends_on``` で他の ```aws_api_gateway_integration_response``` の名前を書いて順序を持たせる。

```HCL
resource "aws_api_gateway_integration_response" "example1" {
  depends_on = []
  (中略)
}

resource "aws_api_gateway_integration_response" "example2" {
  depends_on = [aws_api_gateway_integration_response.example1]
  (中略)
}

resource "aws_api_gateway_integration_response" "example3" {
  depends_on = [aws_api_gateway_integration_response.example2]
  (中略)
}
```

分かりにくい！

これ、後になって知らない人が見たら「なぜ関係のないリソースに依存関係を持たせるんだろう……」と思ってしまうよね。

# 結論
どの案もイマイチだったので、作っている人の好みに合わせれば良いのではないかと思う。
ただ、いずれも初めてこの問題にあたる人は悩むことになるだろうから、ちゃんとドキュメンテーションはしておいてあげよう(めちゃくちゃ悩んだ)。
フロントエンドやるなら入れておくべきESlintってなに？

# プログラミング勉強日記
2020年11月28日
[昨日の記事](https://qiita.com/mzmz__02/items/12d198b696efa8b29bda)でPrettierについて扱ったが、Prettierと合わせて使用することのできるESlintについて紹介する。

# ESlintとは
　ESlint(読み方：「イーエスリント」)は、JavaScriptやTypeScriptなどの静的解析ツールである。ESlintを導入することで、単純な構文エラーやプロジェクト固有のコーディング規約を定義することができる。厳密なルールを定義することで、複数人で開発する場合でもシステム全体のコードの一貫性を維持することができる。

# ESlintの特徴

- 自由に多くのルールを設定できる
- 独自ルールを作成するAPI
- 固有のライブラリー、フレームワーク、および実践のルールを持つ多数のプラグイン
- ES6、ES7、JSXの内蔵サポート
- 迅速に開始できるように、推奨ルールだけでなくサードパーティの設定利用が可能
- Sublime、Vim、JetBrainsの製品およびVisual Studio Codeなどの、複数のエディタやIDEとの統合が可能

(参考文献：[JSプログラマーのイラッとする「クセ」はESLintを導入して対処しよう](https://www.webprofessional.jp/up-and-running-with-eslint-the-pluggable-javascript-linter/))

# ESlintの導入方法

## 1. ESlintを使ってTypeScriptを解析するためのライブラリをインストールする
　nodeのルートディレクトリに移動して、eslint, @typescript-eslint/parser, @typescript-eslint/eslint-plugin, eslint-plugin-reactの4つをインストールする。

```:コマンドプロンプト
npm install --save eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react
```

## 2. ファイルを作成して設定する
　eslintrc.jsonファイルを作成して、以下のように設定する。

```json:.eslintrc.json
{
  "parser": "@typescript-eslint/parser", 
  "extends": [
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true // Allows for the parsing of JSX
    }
  },
  "rules": {
    "react/prop-types": "off",
    "@typescript-eslint/no-empty-interface": 0
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}
```

## 3. package.jsonにscriptを追加する
　package.jsonにESLintが実行できるようにscriptsタグに以下のコマンドを追加する。今回は拡張子が`.ts`と`.tsx`のみを対象に解析する。

```json:package.json
"lint": "eslint . --ext .ts,.tsx"
```

## 4. ESlintの実行

```:ターミナル
npm run lint
```

# PrettierとESlintが連携してフォーマットを適用させる場合
　Prettierはリントツールと組み合わせて利用することができるので、すでにESlintを使用してるプロジェクトでも使用することができる。
　PrettierとESlintと組み合わせて使用するためには、prettier-eslintとprettier-eslint-cliが必要になる。

　※Prettierの導入方法は[こちらの記事](https://qiita.com/mzmz__02/items/12d198b696efa8b29bda#%E5%B0%8E%E5%85%A5%E6%96%B9%E6%B3%95)で扱っている。

## 1. インストールする
　Google JavaScript Style Guideに従ってeslint-config-googleをインストールする。

```:コマンドプロンプト
npm install -D prettier-eslint prettier-eslint-cli eslint-config-google
```

## 2. ESlintの設定をする
　プロジェクトフォルダのルートに、`.eslintrc.json`というファイルを作成して以下の内容を記述する。(Google JavaScript Style Guideに準拠したECMAScript 2018の仕様でリントチェックを行うように定義)

```json:..eslintrc.json
{
  "extends": ["google"],
  "parserOptions": {
    "ecmaVersion": 2018
  }
}
```

　次に、pakage.jsonに定義したscriptをprettier-eslintを使用したコマンドに変更する。

```json:package.json
{
  "scripts": {
    "format": "prettier-eslint --write 'src/**/*.js'"
  },
  "devDependencies": {
    "eslint-config-google": "^0.13.0",
    "prettier-eslint": "^8.8.2",
    "prettier-eslint-cli": "^4.7.1"
  }
}
```

## 3. 実行する
　コマンドプロンプトから以下のコマンドを実行して、Prettierで直されたコードがESlintに渡されてESlintの整形も適応される。

```:コマンドプロンプト
npm run format
```


# 参考文献
[Next.jsを勉強してみる その⑤ 〜ESLintを導入する編〜](https://liginc.co.jp/509582)
[Prettierの導入方法
フロントエンド開発で必須のコード整形ツール](https://ics.media/entry/17030/)
「レガシーコードからの脱却」読書メモ その5(最終回)

レガシーコードからの脱却
ソフトウェアの寿命を延ばし価値を高める9つのプラクティス

David Scott Bernstein 著
吉羽 龍太郎、永瀬 美穂、原田 騎郎、有野 雅士 訳
オライリー・ジャパン 2019年
https://www.oreilly.co.jp/books/9784873118864/

---
第Ⅱ部　ソフトウェアの寿命を延ばし価値を高める9つのプラクティス
　13章　プラクティス9 レガシーコードをリファクタリングする
　14章　レガシーコードからの学び
を読んだメモ

---
# プラクティス9 レガシーコードをリファクタリングする

---
もしかしたらあったかもしれない会話

エンジニア「リファクタリングがしたいです。」
マネージャー「いいね！ それで、どんな機能が増えるの？」

---
# ビジネスにとっての意味

ソフトウェアは資産であり保守が必要。
保守のコストを低減させるためのリファクタリング。
変更要求が来るのは顧客にとって価値がある証拠。
→**素早く、低リスクで変更要求に応えることで顧客に価値を提供する。**

---
# 技術的負債

技術的負債は変更のたびに累積していく。
できるだけ早く返済するのが正しい選択。
金銭的負債と同じ。利子が付くので返済できるならすぐする。

---
# 技術的負債とビジネスのトレードオフ

完璧なコードを作ることはできない。
コードに問題があっても出荷することもある。
**技術的負債は必要悪。許容しないと仕事が成り立たないが、過剰でも成り立たない。**

---
# どこをリファクタリングするか？

レガシーコードも(変更する必要がない限り)価値を生み出せる。
レガシーコードは**地雷**。必要がなければそのままにしておく。
**「変更が必要なコード」**をリファクタリングする。

---
# リファクタリングで良い習慣を身に着ける

保守可能なコードを書く訓練の場。
リファクタリングをしていると、最初から保守可能なコードを書くようになる。

---
# リファクタリングのテクニック

---
## 1. ピンニングテスト
全体的なふるまいに対するテスト。
粒度は非常に粗いが、まずは小さく始めることが必要。

## 2. 依存性の注入
ソフトウェアをテスト可能にするための方法。
インターフェースクラスを使用したりなど、オブジェクト指向的な実装にする。

---
## 3. ストラングラーパターン
少しずつサービスを置き換えていくやり方。
Strangler Fig(絞め殺しの木)の比喩。

## 4. 抽象化によるブランチ
バージョン管理からブランチをなくすためのテクニック。
※フィーチャーブランチの統合がリスクになる。
開発中の機能はフィーチャーフラグで隠す。

---
# オープン・クローズドの原則
新しい機能の追加は**新しいコードの追加**と**最小限の既存コード変更**で済むようにする。

拡張対象の既存コードのリファクタリング
↓
コードを追加(テストファーストで！)
↓
追加したコードのリファクタリング
※一度にいろいろやるとかえって間違えやすい。

---
# レガシーコードからの学び

---
# 技術を大切に
開発者は多くの時間をコーディング**以外**に費やしている。
テストは欠かすことのできないコードであり、テスト駆動開発により開発者はコーディングに集中できる。

> しかし、アジャイルとスクラムはマネジメントプラクティスに変わってしまい、技術的なプラクティスにそれほど重きを置かなくなってしまった。

---
# 間違いと付き合う
私たちは人間なので小さな間違いをたくさん犯す。
バグの検出がQAプロセスまで先送りになると、コードを思い出すのに時間がかかる。
→テストを自動化して早くバグを見つける方がムダが少ない。

---
# 品質は作り込むのが基本
品質を**保証**するだけでなく、良いプラクティスで品質を**作り出す**。
従来型開発でオーバーヘッドになっていた時間を取り戻し、コードを「CLEAN」にして品質を作り込む。
※QAが不要というわけではない。

---
# 教条主義に陥らない
ソフトウェア開発には万能のやり方はない。
オブジェクト指向、テスト駆動開発、アジャイル...これらはツールにすぎない。

> 私たちはソフトウェア開発者だ。現在利用可能なツールを最大限に活用して、ソフトウェアを開発している。

---
# 視野を一つ拡げる
ソフトウェアはビジネスを動かす中心にある。
一方、私たちはドメインを正確に理解しモデル化する方法をトレーニングされてこなかった。
一歩下がって自分たちが何をしているのか考えてみる。
**自分たちが何を、どのように、なぜやっているかを考えるほどより良い仕事ができる。**

---
# おわり
【swift】google admobを実装した際に「[UIView setAdUnitID:]: unrecognized selector sent to instance」が出力した場合の対応

swiftでgoogle admobを実装している際に下記エラーが出力した。

##エラー内容
```swift
Thread 1: "-[UIView setAdUnitID:]: unrecognized selector sent to instance 0x7fce3a70abc0"
```

![スクリーンショット 2020-11-28 21.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60753/885afa85-a38a-6fc2-c217-fcf057fe9f67.png)

##対応方法
広告の枠としたいUIViewと「@IBOutlet weak var bannerView: GADBannerView!」をドラッグアンドドロップなどで紐付けるのだが、その際UIViewのCustom ClassのClass名に「GADBannerView」が記載されておらず実行時エラーとなっていた。

UIViewのCustom ClassのClass名に「GADBannerView」を記載することで、無事エラー回避できた。

###修正前
![スクリーンショット 2020-11-28 21.36.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60753/55ecf185-abfa-177c-a28e-49369850af89.png)

###修正後
![スクリーンショット 2020-11-28 21.40.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60753/57c803d9-2dc8-ecdd-acd7-49efdae49ec0.png)

##最後に
コードを先に書いたあとに、UIViewにドラッグアンドドロップで紐付けると、UIViewのCustomClassは更新されないんですね。。。
ともあれ解消したのでよかったです。
[TypeScript]オブジェクト型を配列にする

# 一行で配列にする

一行でかけたのでこちらが良さそうです。
詳しくは、[Object.entries() を使ってObject → 配列変換 - Qiita](https://qiita.com/kws9/items/6ce80ae1c0fd28a3a9d7) を参考にしてみてください。
2020/11/29更新

```ts
type Data = {
    a: string,
    b: string,
};
const data: Data = {
    a: 'A',
    b: 'B',
};

Object.entries(data).map(([key, value]) => ({key, value}));

console.log(Object.entries(data)); // [["a", "A"], ["b", "B"]] 
// mapメソッドは配列の全要素を呼び出して新たな配列を作る
// ([key, value])で、data[0]の場合は"a"をkey、"A"をvalueとして呼び出し
// ({key, value})で、{'key': key, 'value': value}として配列に格納する
console.log(Object.entries(data).map(([key, value]) => ({key, value})));
// [{
//  "key": "a",
//  "value": "A"
// }, {
//  "key": "b",
//  "value": "B"
// }] 
```

更新前はこちら。

オブジェクト型を配列として定義し直すのに簡単な方法を探していたところ
[Object.keysの型がstring[]になってしまう問題の対策 - Qiita](https://qiita.com/mizuki_r/items/1950dfc27824b3ecd6c7)
を見つけました。
すごく助かりましたがTypeScript初心者として、どういう挙動か具体的に確かめたらなるほどとなったため記事にしました。

```ts
type Data = {
    a: string,
    b: string,
};
const data: Data = {
    a: 'A',
    b: 'B',
};

// オブジェクト型を配列にする
const rows = (Object.keys(data) as (keyof typeof data)[]).map((key) => {
    return { key, value: data[key] }
});

console.log(rows); 
// [{
//  "key": "a",
//  "value": "A"
// }, {
//  "key": "b",
//  "value": "B"
// }] 

// 挙動の確認
type dataType = keyof Data; // 'a'|'b'
console.log(Object.keys(data)); // ["a", "b"]
// キーの列挙型でキーの配列をキャストする
// typeof data は、Dataと同値
console.log(Object.keys(data) as (keyof typeof data)[]); // ["a", "b"]

// 普通は、キーを指定して出力する
console.log(data['a']); // 'A'
console.log(rows[0].value); // 'A'

```

keyof 演算子
オブジェクトの型からキーを抜き出す。

typeof 演算子
通常の式では渡された値の型の名前を文字列として返す。
型のコンテキストでは変数から型を抽出してくれる。
ネットワークスペシャリスト試験の合格体験記

# はじめに
これはAdvent Calendar 2020の資格試験攻略 4日目の記事です。

# この記事の対象者
- [情報処理技術者試験](https://www.jitec.ipa.go.jp/)についてどのようなものか理解している人
- 応用情報技術者試験に合格している人
- ネットワークに興味のある人

# ネットワークスペシャリスト試験とは
- [ネットワークについての資格](https://www.jitec.ipa.go.jp/1_11seido/nw.html)です（通称ネスぺ）
- ちなみにサブタイトル(?)は

>～ネットワーク社会を担う花形エンジニア～

# 私が取り組んだ勉強法
全体的にアウトプット多めの過去問演習が中心です。
過去問は8年分（8回分）解きました。

## 午前対策
### 午前I(50分/四肢択一)
 - ※応用情報技術者試験、または他の高度試験に合格して2年以内の場合は免除となり、[情報処理安全確保支援士試験に合格](https://qiita.com/akihanari/items/4e436a2e3f0cd5992c50)していたので免除でした。


### 午前II(40分/四肢択一)
- まず、[徹底攻略 ネットワークスペシャリスト教科書](https://www.amazon.co.jp/%E5%85%A8%E6%96%87PDF%E3%83%BB%E5%8D%98%E8%AA%9E%E5%B8%B3%E3%82%A2%E3%83%97%E3%83%AA%E4%BB%98-%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AA%E3%82%B9%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8-%E4%BB%A4%E5%92%8C2%E5%B9%B4%E5%BA%A6/dp/4295008443/ref=tmm_pap_title_0?_encoding=UTF8&qid=1606565927&sr=8-5)で支援士についての全般的なネットワークの知識を頭に軽く入れました。この本は買うと電子版がダウンロードできるので、iPadに入れて読んでいました。
- また、[ネットワークスペシャリストドットコム](https://www.nw-siken.com/)を利用しました。勉強方法としては午前Iと同じ流れです。
- 基本的には[情報処理安全確保支援士試験](https://qiita.com/akihanari/items/4e436a2e3f0cd5992c50)と同じように勉強しました。

## 午後対策
- 基本的には問題用紙を印刷[(※IPA公式サイトにあります)](https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_mondai.html)して過去問を解く→理解出来なかったところを見直す　という流れです。そのため解説本（[ネスぺシリーズ](https://www.amazon.co.jp/%E3%83%8D%E3%82%B9%E3%83%9AR1-%E6%9C%AC%E7%89%A9%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E6%9C%80%E3%82%82%E8%A9%B3%E3%81%97%E3%81%84%E9%81%8E%E5%8E%BB%E5%95%8F%E8%A7%A3%E8%AA%AC-%E5%B7%A6%E9%96%80-%E8%87%B3%E5%B3%B0/dp/4297113279/ref=sr_1_1_sspa?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AA%E3%82%B9%E3%83%88&qid=1606565927&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExSTVJRTQ4Qzg4VDNDJmVuY3J5cHRlZElkPUEwMzYwNjcxMThOVkVJUDI4QzdFRiZlbmNyeXB0ZWRBZElkPUFSVTVWNEVOOEFPN04md2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl) など）を購入して学習しました。
- 問題文を読む中で気になったところに下線を引いたり、怪しいところを囲ったり、図で頭を整理したりしながら解くと問題文を読み直す手間が省けるのでオススメです。
- 自己採点するときも、考え方の間違いや、知らない単語についても問題用紙に直接書き込んで理解を深めました。

### 午後I(90分/記述式)
- 3問中2問を選択します。練習では全問解いて、自分の得意・不得意分野を理解しながら進めて行きました。
- 本番では少しでも解けそうな問題を選択しました。
- 過去問で見かけなかったような新しい技術は丁寧な説明があるので、意外と解きやすかったりします...!

### 午後II(120分/記述式)
- 2問中1問を選択します。練習では両方解いていましたが、本番では午後Iと同じように問題を選定しました。

## 他使用したサイト
- [ネットワークスペシャリスト -SE娘の剣-](http://nw.seeeko.com/)
 - ネットワークに関する記事が分野別にまとまっていて、解説も分かりやすかったため教科書と併用して使用しました。また、ブログ形式なのでスマホでも勉強ができるのでオススメです。
## 結果（※2回目の受験で合格しました）
| 区分 | 点数 |
|:-:|:-:|
|午前I | 免除  |
|午前II | 92.00点  |
|午後I | 74点  |
|午後II | 65点  |
やっぱりギリギリでした。それでも合格は合格です...!

# おまけ
- ネットワークとセキュリティは密接に繋がっているので、連続で受験すると相乗効果があるなと感じました
- 最後にどの問題を選択したのか、ちゃんと○を付けているのか確認しましょう
- 合格に向けて頑張ってください！！
ポートフォリオにiframeタグでyoutubeの動画を組み込むときのすゝめ

#本記事の概要
初投稿になります！
本記事は、ポートフォリオにyoutube動画を組み込んだ時におきた問題についての記事になります。


##問題点
ポートフォリオにyoutube動画を大量に組み込んだ際に、下記問題点が起こりました。

- 埋め込みyoutubeの動画の含まれるHTMLの読み込みと表示が非常に遅い
- リクエストが途中で途切れる・一瞬で遮断される
- コンソールでエラーがまれに発生する

埋め込みタグのコードは下記になります。

```html
<div class="youtube">
  <iframe src="https://www.youtube.com/embed/<%= @video_id %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
```
htmlにyoutubeの動画を埋め込む際にiframeタグを使うことになります。
[youtubeの公式リファレンス](https://developers.google.com/youtube/player_parameters?hl=ja)

しかし、iframeタグを用いるとhtmlのレンダリングを行う際、全体のページを読み込んだ後に、iframeタグ（動画）の読み込むを行うようです。
作成したポートフォリオでは、大量のyoutube動画の読み込みをする必要があったので、見事に、問題に直面しました。

##改善策


```html
<div class="youtube">
  <iframe data-src="https://www.youtube.com/embed/<%= @video_id %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
```
まずiframeタグのsrc属性でyoutubeURLを読み込んでおりましたが、data-src属性にすることで、htmlのレンダリングで、読み込むをすることなく、JavaScriptコードやCSSで使用できる追加データを格納することができます。

つまり、iframeタグ内の属性の読み込みをスルーするかつ、データは、一旦避難しておくことでHTMLの読み込みと表示が、スムーズにいくということです。（間違っていたらご指摘ください）
 

次にJavaScript（jQuery）の記述です。

```js
$(function(){
  $('.youtube').each(function() {
    let iframe = $(this).children('iframe');
    let url = iframe.attr('data-src');
    let id = url.match(/[\/?=]([a-zA-Z0-9_-]{11})[&\?]?/)[1];
    iframe.before('<img src="http://img.youtube.com/vi/'+id+'/mqdefault.jpg" />').remove();
    $(this).on('click', function() {
      $(this).after('<div class="youtube"><iframe src="https://www.youtube.com/embed/'+id+'" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>').remove();
    });
  });
}); 
```
こちらでは、data-src属性で格納したyoutubeURLを、src属性に置き換える動作を加えています。　
5・6行目の記述が重要です。
５行目では、変数idに、youtubeURLに含まれるvideo_id（動画情報）を正規表現とmatchメソッドを使って、引っ張り出しています。
６行目では、取得した動画情報を変数idとして、imgタグに代入します。ここでbeforeメソッドでiframeタグに表示されるのは、youtubeのサムネイル画像になります。　
HTMLで動画を読みこむ代わりに、動画のサムネイルをとりあえず表示することになります。

サムネイル画像をクリックアクションで、再度iframeタグを読み込み、負荷なくレンダリングがスムーズに行われました。

ポートフォリオの一部例です。
当初、HTMLの読み込みに30秒〜１分ほどかかる時もありましたが、数秒程度に改善されました。

![musclegram.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643402/ccf6ed32-d558-925e-05a5-4097dd99a57f.gif)

[ポートフォリオサイト](https://musclegram.net/)

参考になりますと幸いです。
以上になります！
[GCP] - Serverless Architecture -- Getting Start[1] -- At first.

#At first.

This content is written by GCP Begineer.
So, this content may isn't Best Practice.
Please read this content as reference information.

# What I want to achieve in this article. 
* Understand GCP's Serverless Architecture.
* Understand GPC's Local Programing Environment.
* Recall specifications of Spring Boot2.
* Recall specifications of Vue.js 
* Understand OpenIDConnect.

# Serverless configuration to be adopted.
* GCP CloudRun (Backend) -- No Kubernetes
* Vue.js (Frontend)
* Java + Spring Boot2
* Doma2
* MYSQL on CloudSQL


# Configuration.
* Frontend Layer is Static Html files with Vue.js on Firebase Hosting.
* Backend Layer is RestAPIs.
* Used Doma2 for Database Access
 
![20201128-architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916869/3351d24d-90e2-d4a9-89e5-45491db29e99.png)


# At the end.
First of all, I will create this configuration.
After that, if this configuration is run short I will change or I will added components.

Next time, Start Create Configuration.

thanks for reading this contents.

kazuya.

# ◆Related arcticle
* [[AWS] -- Architecture Supporter[1]](https://qiita.com/kazuya-ho/items/9adad0e2e81c117a2830)
* [[AWS] -- Architecture Supporter[2] -- Setting Local Development Environment](https://qiita.com/kazuya-ho/items/59d7353034f4337728c4)
* [[【AWS/GCP】クラウド初学者が、Google Cloud Certified PCA・AWS CP・AWS SAAを１か月で取得した方法]](https://qiita.com/kazuya-ho/items/109f356ba7b0d5e6ddc0)
Raspberry Pi Zero WHで動画撮影がハングアップするなら試してみて

#概要
ラズパイゼロを使ってドラレコを作ってみようと一念発起。GPSや加速度センサー、ジャイロセンサー、RTCを搭載。いざ、raspividで動画撮影を開始すると数分でハングアップ。ヒートシンクを大型化し、小型ファンまで搭載するも症状が改善せず。電源電圧や電流も問題なし。なぜ？
ググってみると、コア電圧かも。で、コア電圧を少し上げてあげるとあら不思議、安定して動くようになりました。動画撮影で動作不安定で困っている方は、お試しあれ。

#環境
Raspberry Pi Zero WH ： Raspbian GNU/Linux 10 (buster)
Smraza Raspberry Pi用 カメラモジュール hdmi 160度FoV 1080p 高解像度 魚眼レンズ
64GB Micro SDカード (HIDISC製 microSDXC CLASS10)

#現象
`raspivid`や`motion`を使い動画撮影を実行すると、数分でカーネルエラーが出てプロセスが終了したり、ラズパイがハングアップして無反応になるなど不安定に。解像度を上げたりフレームレートをあげると数秒で不安定になる。

#解決策
`nano`などを使い、`/boot/config.txt`を開く。

~~~
$ sudo nano /boot/config.txt 
~~~

`/boot/config.txt`を開いたら、最後に以下の行を追加

~~~
over_voltage=4
~~~

あとは、リブートすればOK。これだけです。

over_voltageは、-16〜8の範囲で値が設定できます。
この設定に従い、CPU coreに共有される電圧が以下の式で決まります。

~~~
core電圧 ＝ 1.2[V] ＋ 0.025[V] × over_voltage
~~~

いろいろ調べると、人によっては2でも動いたり、設定しなくても問題ない場合などあるようです。
私の場合は、これに加えて、

~~~
core_freq=250 
~~~

も設定してCPU core周波数を落としています。
CPU負荷を測定したところ20%〜40%程度でしたので電力消費を抑えるつもりで入れました。

#おまけ
ちなみに、作ったドラレコはこんな感じ↓
![IMG_3086.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882503/224bfdc8-f71b-65e5-baf1-246296c8e626.jpeg)
カメラの横に0.96インチ128x64ドットの有機ELディスプレイ。
カメラの下で光っているのが、加速度センサー(LIS3DH)、その下がENC-03Rを使った圧電振動ジャイロモジュールです。
ジャイロの横で淡く光っているのが、GPS受信機キット(「みちびき」３機受信対応)です。

#参照記事
[www.raspberrypi.org : my zero w system lockups when using the camera [solved]](https://www.raspberrypi.org/forums/viewtopic.php?p=1489997)
[Qiita：Raspberry Piをオーバークロックする。](https://qiita.com/MasaR014/items/10a08048486d71c42148)
【swift5】APIを叩くときは「HTTP」を「HTTPS」に直しましょう

※本記事が筆者の初投稿です!　優しい目で参考程度にご活用ください！

#はじめに
なーんにも考えずに、AlamoFireでAPIを叩いたりなどでHTTP通信をすると、
「エラーが出る」とか「想定より少ないデータしか取れない」
って問題が発生したりします。

HTTP通信は暗号化されていない安全性の低い通信のため、
appleがデフォルトでブロックさせています。

この状態でrequestを出しても、セキュリティでブロックされてる状態なので、
responseは返ってきません。
キャッチボールしようとしてるのに、二人の間に壁があるようなものです。
これでは投げても相手に届かないので投げ返してくれませんね。

壁に邪魔されない形式の通信に変更しましょう。

#解決策

例えばAPIを使おうとして、サイトに載ってるサンプルクエリをコピペしてみます。
そうするとありがちなのが以下みたいなURL。
「http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?key=[APIキー]&large_area=Z011」

このデフォルトで文頭が「http://」になってるのが引っかかりポイント。
単純に「http://」を「http<font color='red'>s</font>://」に直してあげましょう。

これで壁に邪魔されない、安全性の高い通信形式に変更できました。

#それでもダメな場合は
API側が、http通信しか対応していない場合があります。
「httpsに直してもダメだ〜」って時は、そもそもの壁を取っ払ってやりましょう。


###①ATSを無効化する （簡易版）
下記URLの「info.plistの編集」を参照してください。
[【swift】XcodeでiOSアプリのhttp通信を許可する方法](https://fukatsu.tech/permit-http-ios)


`Info.plist `に飛んで、ATSを無効化しましょう。
![スクリーンショット 2020-11-28 18.49.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/881110/4116ba64-bebf-45f1-c516-c39466e05e4e.png)
ただ、上記の方法は全てのHTTP通信を許可しているため、安全性に欠けます。
審査に提出するとなると、apple様はこの方法では通してくれません。

特定のボール（ドメイン）だけ、壁（ATS）を通り抜けるようにしましょう。

###②特定のドメインのみ許可する （発展版）
下記URLを参照して、特定のドメインだけ許可してあげましょう。
[お菓子検索アプリ：iOS10でのATS設定について](https://swiftbg.github.io/swiftbook/tips/ios10ats.html)

これで指定したボール（ドメイン）だけは通り抜けられるようになりました。

ただATSという壁を設けている時点で、そもそもHTTP通信をappleは推奨していないことには留意してください。
2020年11月現在でも審査に通るかは未検証です。




##終わりに
何がハマったって、これやらなくても「少量ならレスポンスが返ってきた時があった」のが、
１番のハマり&誤認ポイントだった。

「無制限にデータ受け取りたいのに、取得データが少ない」とか、
「１０件くらいの少量なら大丈夫だけど、１００件とか多量のデータを受け取ろうとするとエラー吐く」
とかいう方は「http通信になっていないか」、もしくは「ATSはどうなっているか」を確認してみてください。

自分と同じくらいの初学者さんの助けになれれば。


###参考文献
 - [【swift】XcodeでiOSアプリのhttp通信を許可する方法｜新卒エンジニアの開発日記](https://fukatsu.tech/permit-http-ios)
 - [お菓子検索アプリ：iOS10でのATS設定について｜これからつくるiPhoneアプリ開発入門 Swiftではじめるプログラミングの第一歩［Swift3/Xcode8対応］公式サポートサイト #swiftbg](https://swiftbg.github.io/swiftbook/tips/ios10ats.html)
 - [ホットペッパー｜APIリファレンス｜リクルートWEBサービス](https://webservice.recruit.co.jp/doc/hotpepper/reference.html)
PySide2でWebブラウザをウィジェットとして使う

この記事は[Takumi Akashiro ひとり Advent Calendar 2020](https://qiita.com/advent-calendar/2020/takumi_akashiro)の1日目の記事になります。Yeh!

## 前置き

どうも！皆さんは最近、PySide2を触ってますか？
私は……まあボチボチですね！

[Houdini](https://www.sidefx.com/ja/docs/houdini/hom/cb/qt.html)でも[Maya](http://help.autodesk.com/view/MAYAUL/2020/JPN/?guid=__developer_Maya_SDK_MERGED_Maya_Python_API_Working_with_PySide_in_Maya_html)でも標準で入っているPySide2。  

PySide2で標準で使えるウィジェットにWebブラウザがあるのは御存知でしょうか？
ご存じですよね？既にタイトルを見てクリックしてるはずですからね！

と茶番はさておいて。
PySide2のラップ元であるQtにはQt WebEngineと呼ばれるモジュールが存在します。

> Qt WebEngineはWebコンテンツをレンダリングするための機能を提供します。
 [Qt WebEngine 5.15.2 - PySide2公式ドキュメントより](https://doc.qt.io/qt-5/qtwebengine-index.html)

## Qt WebEngine とは

Qt WebEngineはChromiumをベースとしたウェブブラウザを扱えるモジュールであり、
PySide2でも標準で組み込まれています。

つまり、PySide2でウェブブラウザを使えるということです！

ちなみに過去にはWebKitベースのQt WebKitもあったようですが、
こちらはQt 5.5以降非推奨になっており、
現在、PySide2ではビルドしなおさない限りは使えないようです。[^1]

[^1]: ちなみに自分はPySide2はビルドしたことないので、この説明が正しいのかすら…分からん！

では試しに使ってみましょう！

## 試してみた

```python

#!python3
# encoding:utf-8

from PySide2 import QtCore
from PySide2 import QtWidgets
from PySide2 import QtWebEngineWidgets

class WebDemo(QtWidgets.QWidget):
    URL = "https://google.com/"
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setGeometry(500, 300, 250, 110)
        self.setWindowTitle('Web Demo')
        
        hbox = QtWidgets.QHBoxLayout()

        webview = QtWebEngineWidgets.QWebEngineView()
        webview.setUrl(self.URL)

        hbox.addWidget(webview)
        
        self.setLayout(hbox)

if __name__ == "__main__":
    app = QtWidgets.QApplication()
    webdemo = WebDemo()
    webdemo.show()
    exit(app.exec_())

```

### Google.com
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294868/ccfa8931-b4ca-7f5d-e452-5e428f57f117.png)

### three.js examples
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294868/89f508dc-8517-3f84-2f05-c118d365143d.png)

three.jsも問題なく表示できてますね！

RedmineやShotgunを開いたり[^2]、
ツールのマニュアルを載せたりするときには便利なんじゃないですかね？

[^2]: 世の中に出てくる記事を見る限り、専用のツールでAPI叩いて、<br>フローを整えてるところも多そうですけどね！


## 締め
というわけで、今回紹介した技術の評価としては以下の通りですね。

|評価ラベル|ランク(5段階)|
| --:| :--: |
|おすすめ度|★★|
|難易度|★★|
|ニッチ|★★★|
|汎用性|★★★★|
|キュート度|★★★★★|

個人的にはツールに依存していない部分は、分離して実装しておくと、
DCCツールを移行したり、新フローを構築する際に、
簡単に流用できたりするので、ウェブ技術を組み込むのは結構アリな気がしますね！

----

「あー、このWebブラウザ、表示するだけかぁ……
WEBでUI作って、DCCツールの関数を実行出来るようになれば楽なのになー……」とお考えの貴方。[^3]

**出来ます！** 詳細は明日の記事で！！！
それでは、シーユーアゲイン！！！！！！

[^3]: そんな人いる？
【実績作り】Githubで書いたコード数を数える

会社での報告書や転職時のPRのために、自分の書いたコード数を説明しないといけない時があります。
Githubは変更したファイル数を出してくれるんですけど、自分が書いたコードは何行かわからないんですよね💦


ってことで、コード数が数えられる方法をお伝えしますmm


#Git Bashでコミット行数を数える
1. .gitのあるフォルダに移動
2. git pull最新化しておく
3. 以下のコマンドを実行

```
git log --numstat --pretty="%H" --author='あなたの名前' --since=YYYY-MM-DD --until=YYYY-MM-DD --no-merges | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("%d (+%d, -%d)\n", plus+minus, plus, minus)}'
```
>--authorは対象のユーザ名
--sinceと--untilには集計期間

##結果
1600 (+600 -800)　のように左から、
合計行数（+追加行数 -削除行数）　が表示されます。



#リポジトリ内で自分が書いた行数を数える
```
git ls-files | xargs -n1 git --no-pager blame -f -w|grep 自分のgitユーザ名 |wc -l
```

>git ls-files：リポジトリ管理下のファイル名一覧を獲得
git --no-pager blame：全部の行の作者を行単位で吐き出し
grep：自分が作者になってる行を洗い出し
wc -lでカウント
ラジオボタンの一例

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="momonoki1990" data-slug-hash="ExgaPqj" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ExgaPqj">
  <span>See the Pen <a href="https://codepen.io/momonoki1990/pen/ExgaPqj">
  ExgaPqj</a> by 熊瀬川直也 (<a href="https://codepen.io/momonoki1990">@momonoki1990</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

* デフォルトのラジオボタン(```input[type="radio"]```)は```display: none``で消す
* ラベルと消したラジオボタンの```input```は```for```属性で繋がっているので、ラベルだけ残しても大丈夫(ラベルをクリックしてもラジオボタンがクリックされたことになる)
* ラジオボタンのラベル(```label.radioLabel```)は```padding-left```で右に寄せて、スペースを空けておく
* ラジオボタンのラベル(```label.radioLabel```)に```:before```を指定して、上記で空いたスペースにカスタムのラジオボタンを挿入する
* ```input[type="radio"]:checked + .radioLabel:after```でチェックされたラジオボタンの直後にあるラジオボタンのラベルに、```:after```を指定して、チェックされたマークを挿入する。
* ラジオボタンのラベル(```label.radioLabel```)に```position: relateve```を、カスタムのラジオボタンやチェックされたマークには```position:absolute```を指定して、ラベルに対する相対位置でカスタムのラジオボタンやチェックされたマークの位置を定める。
* チェックされたラジオボタンの値は、```getElementByIdで取得したform要素.ラジオボタンのname.value```で取得できる
* ```innerHTML```はメソッドではない(x 要素.innerHTML()  o 要素.innerHTML = "")


## 参考
CSSでラジオボタン・チェックボックスをデザイン装飾する
https://web.runland.co.jp/blog_cate2/post-2650

ラジオボタンの値を取得する方法
https://lab.syncer.jp/Web/JavaScript/Snippet/30/
Angular(Ionic)で非同期通信を実装する



フロントエンドアプリケーションフレームワークである__Angular(Ionic)で非同期通信を実装する方法__をサンプルアプリとして紹介します。動作確認用にPythonで作成したバックエンドコード付きです。

Angularの場合、非同期通信を実装するにはHttpClientModuleをapp.module.tsに追加して、tsファイルで呼び出して使うだけです。AngularはReactと異なりフルスタックなので、この辺の安心感はReactにはるかに勝ると思います。

[あまりにもアクセスが少ないので移動しました💦](https://np-sys.com/general/angularionic%e3%81%a7%e9%9d%9e%e5%90%8c%e6%9c%9f%e9%80%9a%e4%bf%a1%e3%82%92%e5%ae%9f%e8%a3%85%e3%81%99%e3%82%8b/)
MAMPのPHPのexec()からpython3を簡単実行。

MAMPのpythonはversion2なので、ずっとこの壁にぶつかってたんですが、

```php
$command = "python test.py";
exec($command, $output, $return_var);
```

python→python3でできました。意外と簡単でした。

```php
$command = "python3 test.py";
exec($command, $output, $return_var);
```
アジャイル検定レベル１を受けてみた

[アジャイルソフトウェア開発技術者検定試験](http://agilecert.org/) のアジャイル検定レベル１を受けてみました。

# なんで受験したか？
アジャイル開発やスクラム開発に興味があって独習していました。
本当はスクラムマスターが欲しかったのですが、受講料が高かったので探してみたところ最もお手軽だったので受験しました。
持っていて意味あるの？という声もあると思いますが、知識に自信を付けるためにやっています。

# 勉強方法
基本的にアジャイルの書籍を読んでいたので、公式テキストを２～３回読んで例題を解きました。
ふんわりしたアジャイルの知識や、なんちゃってアジャイルの現場で学んだ知識の場合は公式テキストを見直しておいた方がよいです。
もし、現場でアジャイルやスクラムを使ったことがある人は、公式テキストの知識と照らし合わせてみると理解が深まると思います。

# 受験してどうだったか？
テスト中に「どうだったか・・・？」とにわか知識であることを痛感できます。
今後、アジャイル開発やスクラム開発を本気で使っていこうという方は受験することでもっと深く理解したい気持ちになります。
また、基礎知識としてもちょうどよいのでメンバーみんなで受験してみると楽しそうです。
【NeosVR】回る20ルピー【基礎練習】

はじめに
---
この記事は「[NeosVR reso Advent Calendar 2020](https://qiita.com/advent-calendar/2020/neosvr_reso)」の2日目です！
昨日は、@piacerexさんの「[Advent Calendarの参加／書き方ガイド（NeosVR resoの解説も）](https://qiita.com/piacerex/items/15b21f39c228a95d2bda)」でしたω

---

僕(https://twitter.com/TewiEwi_no96) がNeosVRで人にモノづくり教える時に説明する内容を記します。
この基礎が終われば後はコンポーネントとLogiXの知識だけです。
NeosVRが好きになるキッカケになってもらえると嬉しいです。
必要知識
---
・デブチップの使い方(https://neosvrjp.memo.wiki/d/DevToolTip)
・ロジックスチップの使い方(https://neosvrjp.memo.wiki/d/LogiX)
ルピーを作ってみよう！
---
先ずはデブチップを装備してコンテキストメニューを開き『新規作成』をトリガー。
ブラウザが出現しますので、空オブジェクトをトリガーします。

選択されているオブジェクトの黄色い☆ボタンを押すと
子オブジェクトが追加されますので、以下のような階層構造にしてください。

object
┣Visual
┃┗Render
┃ ┣Mesh
┃ ┗Material
┗Moduals
　┗roll logix
![20201128205642_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556177/ce943c76-30e8-d449-a396-61ccd12cff8f.jpeg)
<b>下記のオブジェクトにAttach Componentをトリガーしてコンポーネントを追加していきます。</b>
<b>・Mesh</b>
Assets -> Procedual Meshes -> Neos UI -> BevelSoliPlaneMesh　(メッシュを決めます)
設定値変更
Width:0.5
Height:1 → 0.5
Thickness:0.05 → 0.25
TopLeftCut:0.1 → 0.25
BottomRightCut:0.1 → 0.25

<b>・Material</b>
Assets -> Materials -> PBS_Metallic　(マテリアルを決めます)
設定値変更
EmissiveColor:
 R:0 → 1

<b>・Render</b>
Renderering -> MeshRenderer　(レンダリングします)
設定値変更
Mesh: null → BevelSoliPlaneMesh
Materials(list):add
0:null → PBS_Metallic

Physics -> Colliders -> MeshCollider　(メッシュにコライダーを付けます)

<b>・object</b>
Transform -> Interaction -> Grabbable　(つかめるようにします)
設定値変更
Scalable: ☐ → ☑　(サイズを変更できるようにします)

<b>【途中経過】</b>
45度傾いたルピーが出来ました！
![20201128200333_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556177/91b6c2cc-ac70-5dde-e986-c6412e6ee8d2.jpeg)
LogiXで回してみよう！
---
ノードブラウザを開いて以下のようにつないでみましょう！
Input -> T*10
Input -> float
Operators -> X
Operators -> Puck xyz
Math -> Rotation -> From Euler
![20201128195809_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556177/1b54cfab-be33-a4c9-81a1-811afb640ee5.jpeg)
オブジェクトのroll logixにロジックスチップを装備してパッキングすれば完成です！

お疲れ様でしたω
動画も撮りましたので参考にどうぞ～
---
https://www.youtube.com/watch?v=XRFCwDgDkFM&feature=youtu.be
FUNBOXで支援してもらえると記事を書く励みになります。
---
https://frick.fanbox.cc
終わりに
---
・明日は、@kazu0617さんの[[NeosVR] Logixを用いた外部データの取得と活用（パンツパッチから）[HTTP GET String]](https://qiita.com/kazu0617/items/665633f4c32827f49e32)です
Vue-CLI + webpackでscssをビルドするときのつまずき


## abstract

Vue-CLIに限った話ではないかもしれないですが、Vue-CLIにsassを導入しようとしてつまづいたところの覚え書きです。

```
$npm i sass-loader node-sass
```

でscssを使おうとしたところ、ビルドエラーが発生。

結論から言うと、主な原因は下記の通りでした。

* node.jsのバージョンが新しすぎる
* css-loaderのバージョンが新しすぎる
* その他バージョンの互換性

ここでは以上3つの対処法を記載します。

## node.jsのバージョンが新しすぎる

筆者の場合v14でしたが、nodeのバージョンが新しすぎるととnode-sassが動作しなくなる。
なのでnode-sassが動くバージョンにnode.jsをダウングレード。
筆者は`v11.15.0`にしました。

### バージョン確認

```
$node -v
```

### nodeのバージョンを切り替える

新しすぎるようであればバージョンを切り替えます。
なお、node.jsはアンインストールしなくてもバージョンのみ切り替えることができます。

#### 現在installされているバージョンを確認する

```
$ nodebrew ls
v11.15.0
v13.9.0
v14.15.1

current: v14.15.1
```

currentが今現在のバージョンです。

切り替えたいバージョンがない場合はinstallします。

```
$ nodebrew install <version>
```

#### バージョンの切り替え

```
$ nodebrew use v11.15.0
```

#### 確認

```
$node -v
v11.15.0
```

公式ドキュメント：https://github.com/hokaccha/nodebrew

## css-loaderが新しすぎる

css-loaderのバージョンが新しすぎると動かないようです。
今回はv2をインストールしなおします。

### アンインストール

```
$npm uninstall css-loader
```

### 再インストール

```
$npm i css-loader@2.0.0
```

### 確認

すみません。
ここは自分でも理解できないのですが、下記コマンドでバージョンを確認すると`5.0.1`となっていました。

```
$npm view css-loader version
5.0.1
```

しかし、package.jsonを確認すると2.0になっています。

```js:package.json
// 抜粋
{
  "dependencies": {
    "css-loader": "^2.0.0",
  },
}
```

結果的には、上記の工程でv.2.0をインストールすることでビルド時のエラーを解消できました。
※なにかわかる方がいましたら、教えてください🙇‍♂️


## その他のバージョンの互換性

その他インストールしたパッケージのバージョンは下記の通りです。

```
$npm i sass-loader@7.3.1
$npm i node-sass@4.13
```

### おわり

同じ境遇にあった人は少ないかもしれません。
調べるのに時間がかかったので、誰かの役に立てれば幸いです。
DockerでPHP開発をしている際に、vscodeでの実装変更が反映されない。

#環境
macOS
DockerでPHPを使用
#解決方法
順序1

```
Docker コンテナの停止・削除
$docker-compose down
```
順序2

```
Docker コンテナの起動
$docker-compose up -d
```
これだけでした汗

#発生状況&原因
#####発生状況
vscodeでいつものようにPHPの勉強をしていた際に、vscodeで新たな実装変更を行いました。ターミナルで動作確認すると実装変更が反映されない状況になってしまいました。

このような状況に、、、汗

```
ss@saaaMPro src % docker-compose exec app php book_log.php
Could not open input file: book_log.php
```

なので原因を探るため
ターミナルでのディレクトリの位置が間違っていないか？
ファイル名が間違っていないか？
エラー内容が、入力ファイルが開けないと言っている、、、、なぜ、、（泣）

#####原因

ここでは、server-sideディレクトリのpart2の中のディレクトリで作業を行っていました。
一旦、ファイルの中を確認！
![スクリーンショット 2020-11-28 19.51.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474793/48bd7afd-e99a-5421-21f3-80e079d81746.png)

ここで気になったのは、codeディレクトリの中に違う階層ではあるものの、同じpart2のディレクトリがあり、原因はここではないのか？と何の根拠もないのに自分の中で原因を発見できたと思ってしまいました。汗

---
記憶をたどると、作業前にFiderを開き、code/part2の中の<strong>ファイルを直接コピー</strong>し、server-side/part2のファイルにペーストし、作業に取り掛かっていました。

<strong>その間、Dockerコンテナは最初から作動中だったので、移動前の状況のままになります（恐らく、、、）</strong>

なので、コピーしたファイルを移動し変更しても、Dockerコンテナの中は以前のままで反映さていないので、最初の項目(解決方法)を実行し、最新の状態にしてから、作業を行ったところ無事変更を行えました。

---


前提知識の不足や認識の間違いなど、ご指摘やアドバイスなどいただけましたら凄く有り難いので
お願いします！！！
docker mysql接続時に「Illegal mix of collations」エラーが発生


開発環境にdockerを導入し、``docker-compose up``をした後にログインをしようとしたところエラーが発生。データベースに接続できなくなってしまったので、その時の対処法を記録として残します。



## エラー内容

```ruby

 ActiveRecord::StatementInvalid (Mysql2::Error: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='):
```

latin1という文字コードとutf8という文字コードが混在していることが原因で起きているエラーのようです。

本当に混在しているか確認するため、[こちらの記事](https://qiita.com/ymstshinichiro/items/01f6a4c299fdb4b832a2)を参考にDocker上でMySQLにログインしてみました。

![3fc1ae307c06f5d7926694734fbcbf6b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700117/3292d5f2-3ebc-2945-8145-28647f258ef0.png)


確認してみるとlatin1とutf8が混在しているのが分かります。
そしてlatin1という文字コードは日本語を扱うことができないためこれをutf8に変更する必要があります。

## 解決方法
``docker-compose.yml``を以下のように変更しました。（[こちらの記事](https://qiita.com/neko-neko/items/de8ea13bbad32140de87)、およびdockerhub内mysqlの [公式リファレンス](https://hub.docker.com/_/mysql)参照）



```docker-compose.yml
version: '3'

services:
  db:
    image: mysql:5.7

    ↓↓↓# 文字コードをutf8に指定 この１行を追加する↓↓↓
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    
　　 environment:
      MYSQL_USER: root
      MYSQL_PASSWORD:
      # 仮想コンテナにアクセスするためのポート番号
    ports:
      - "3306:3306"
      # データを永続化する(ホスト側のdb/mysql/volumesをコンテナ側の/var/lib/mysqlに同期する)
    volumes:
      - mysql-data:/var/lib/mysql

```



dbにcommandを追加することで文字コードの設定を渡せます。

再度dockerを立ち上げたところエラーが起きることなく、無事問題は解決しました！

## 最後に
dockerを始めたばかりの初心者でわからないところがわからない状態ですが、１歩づつ進んでいきます！！
[Oracle Cloud] LB を使って、HTTPS リダイレクトをしてみた

# はじめに

Oracle Cloud Infrastructure(以下 OCI) のロードバランサーに関する記事です。Webサイトを HTTPS で提供するときに、HTTP でアクセスしてきたリクエストを HTTPS にリダイレクトをしたい時があります。リダイレクトすることで、HTTPS を強制出来てセキュリティを向上出来たり、Google などによる検索エンジンの評価を向上しやすくする効果があります。検索エンジンの評価では、HTTP と HTTPS のページは別のページと認識して評価するため、同一のコンテンツが分散されて評価されてしまうようです。そのため、HTTP を HTTPS へリダイレクトすることで、評価を分散させない効果があると言われています。

リダイレクトするときには、Apache や Nginx 側で設定することも出来ますが、多少面倒です。OCI ロードバランサーでリダイレクト設定が簡単に設定できるため、手順を紹介します。



# Rule Sets の作成

まず、ロードバランサーの詳細画面で、HTTPS へリダイレクトするための Rule Sets を作成します。

![1606562144724.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/07c6bc5c-d6aa-30ad-f956-000ecb2ce54a.png)



各種パラメータを入れます。Source Path は、アクセスの中から、どのアクセスをリダイレクトの対象にするかの指定です。今回は、全ての HTTP のアクセスを HTTPS へリダイレクトしたいため、`/` を入力します。

![1606570443773.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/2f36d43c-c562-bfd4-eee5-437a32cd1831.png)



Close

![1606562365215.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/2d8380e8-d36b-931f-ee5b-0c0670669017.png)



Rule Sets が作成されています

![1606562390988.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/b9e552ae-813f-3c07-d078-f8a120f3c3e3.png)



# Listener に Rule Sets を紐づけ

Rule Sets を作成しただけでは、何の効果もありません。Listener に Rule Sets を紐づけることで、はじめてリダイレクトが出来るようになります。というわけで、HTTP(80) Port の Listener に、HTTPS(443) へリダイレクトの Rule Sets を紐づけます。

![1606559186139.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/6c33fdc1-88f6-479c-eab7-be2d514ea8db.png)



Additional Rule Set

![1606559482380.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/6a596813-0f0f-35cc-9346-b02da6aae581.png)



Redirect_to_HTTPS を確認して、Update を押します。

![1606559508747.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/cde2b0db-246b-a687-5782-1d1a75711528.png)



Close

![1606559349700.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/b24a7fc9-9e3b-7666-22d3-92de8748d045.png)



Work Requests が In Progress のものが表示され、すぐに Succeeded になります。

![1606562696599.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/66d97c0b-c34c-73e0-caa4-2e7fd484e8b8.png)



# HTTPS リダイレクトの確認

まず、Linux の curl コマンドで、リダイレクトの挙動を確認します。

```
> curl -I http://web01.sugioci.tokyo/
HTTP/1.1 301 Moved Permanently
Date: Sat, 28 Nov 2020 11:29:12 GMT
Content-Type: text/html
Content-Length: 173
Connection: keep-alive
Location: https://web01.sugioci.tokyo:443/
```



http(80) にアクセスしてみると、Status `301 Moved Permanently` が返ってきています。そして、リダイレクト先の Location が `https://web01.sugioci.tokyo:443/` となっています。正常に HTTPS へリダイレクトが出来ていますね。



Web ブラウザ上でも、確認してみましょう。http://web01.sugioci.tokyo/ にアクセスしてみると、正常に HTTPS ページが表示されます。

![1606563113323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/604fbdfe-e6d0-465d-32b2-ba5c9319ab21.png)





# 参考URL

https://docs.cloud.oracle.com/en-us/iaas/Content/Balance/Tasks/managingrulesets.htm#redirect

https://blogs.oracle.com/cloud-infrastructure/http-url-redirect-on-oracle-cloud-infrastructure

https://dev.classmethod.jp/articles/alb-redirects/