OmniAICreator/Qiita-1.07M huggingface dataset:
【エンジニア未経験者が調べる】sshとは何か？

※2022年から技術系の記事は[個人ブログ](https://yamaday0u.net/category/programmer/)に投稿しております。ぜひこちらもご覧ください→[yamaday0u Blog](https://yamaday0u.net/category/programmer/)

## はじめに

やまだゆう（[@yamaday0u](https://twitter.com/yamaday0u)）です。
ぼくは現在、業界未経験で、エンジニアへの転職を目指して勉強・転職活動中です。

今回はsshについて調べてみました。

## きっかけ

プログラミングスクールのカリキュラムでAmazon EC2（[Amazon Elastic Compute Cloud](https://aws.amazon.com/jp/ec2/?ec2-whats-new.sort-by=item.additionalFields.postDateTime&ec2-whats-new.sort-order=desc)）で作成したEC2インスタンスへのアプリケーションのデプロイを実現する過程で、EC2インスタンスにアクセスするために使ったことが、sshに初めて触れたきっかけです。

当時はカリキュラムに書かれているままにsshを使っていたので、sshとは何かを自分で調べもしないままにしていました。

これからエンジニアを目指している身として、IT業界で使われる用語をほったらかしではいけない！と思い、今回調べて記事にすることにしました。

## 今回のゴール

- sshで何ができるかを知る
- 他の似たような用語と何が違うのかを知る

## sshとは

sshはSecure SHell（セキュア　シェル）の略で、暗号化した安全な通信で遠隔からコンピュータを操作する際に使用されるソフトウェアです。

> 　sshとは、主にUNIXコンピュータで利用される、ネットワークを介して別のコンピュータにログインして操作するためのソフトウェアの一つ。通信経路が暗号化されるため、インターネットなどを経由しても安全にアクセスすることができる。
　コンピュータ上で動作しているOSに利用者が指示を与えるためのシェル（shell）と呼ばれるプログラムの一種で、遠隔からコンピュータの操作画面を呼び出し、手元のコンピュータのキーボードなどで入力したコマンド（命令）などを送信して実行し、結果を受信して表示することができる。公開鍵暗号と秘密鍵暗号を組み合わせて通信経路を暗号化し、パスワードなどの認証情報や入力されるコマンド、出力された処理結果などをすべて暗号化して送受信する。（[IT用語辞典](https://e-words.jp/w/ssh.html)より）

ぼくはEC2インスタンスにアクセスするときにsshを使用したのですが、確かにEC2インスタンスはローカルのPCの中ではなくクラウド上にあるため、sshを利用し遠隔から操作をしたというわけですね。

ちなみにAmazon EC2は仮想サーバを構築できるサービスで、EC2インスタンスはOSを載せた仮想サーバです。

参考：[Amazon EC2とは何か？「インスタンス」など関連用語もまとめて解説【保存版】（ビジネス+IT）](https://www.sbbit.jp/article/cont1/46306)

## 似たような用語との違い

### HTTPとの違い

HTTPは「Hyper Text Transfer Protocol 」の略で、インターネット上の情報を転送するときの決まりごとです。

HTTPもsshも「通信で使われる」という面では共通点がありますが、HTTPはテキストデータの転送で使用される「決まりごと」であるの対し、sshは遠隔地にあるコンピュータの「操作」に使われます。

参考：[SSHとHTTPの違いは何でしょうか（teratail）](https://teratail.com/questions/26066)

### SSLとの違い

SSLは「Secure Sockets Layer」の略で、インターネット上のWebブラウザとWebサーバ間の通信を暗号化するプロトコルです。

ざっくり言ってしまえば、**HTTPを暗号化してHTTPSでの通信を可能にしてくれるもの**です。

略称は1文字しか違わないため、ぼくも調べる前はsshとSSLの違いが何かわかりませんでしたが、全然違うものを指しています。

手前味噌な感じですが、過去にHTTPやSSLについて調べてQiitaに投稿した記事があるので、こちらもご参照ください。
[HTTPとHTTPS、SSLについて整理する（Qiita）](https://qiita.com/yamaday0u/items/3606db49af0f35c2fa23)

## 参考資料
[IT用語辞典](https://e-words.jp/w/ssh.html)
[Amazon EC2とは何か？「インスタンス」など関連用語もまとめて解説【保存版】（ビジネス+IT）](https://www.sbbit.jp/article/cont1/46306)
[HTTPとHTTPS、SSLについて整理する（Qiita）](https://qiita.com/yamaday0u/items/3606db49af0f35c2fa23)
[ssh とは何か（Qiita）](https://qiita.com/hanlio/items/689d796ec51fcf4c05aa)
[SSHとHTTPの違いは何でしょうか（teratail）](https://teratail.com/questions/26066)
日記 Visual Studio 2019 C++ 他のアプリケーションのIME状態を取得、ON/OFFの切り替えをする

## 日記

[前回の日記 日記 Visual Studio 2019 C++でSetTimerで定期実行する処理の書き方](https://qiita.com/Yamine1San/items/997b8b9acaf7ecf67d8a)

## 概要

他のアプリケーションのIMEの状態を「ImmGetContext, ImmGetOpenStatus, ImmSetOpenStatus, ImmReleaseContext」を使用して取得/変更できずに困っていたところ、imm32.dllのImmGetDefaultIMEWndでIMEのハンドルを取得し設定できる事を知った。

<b>参考になったサイト</b>
[IMEの状態をAutoHotkeyから知る方法(ジャンキー/ノンプログラマー流)](https://neokixblog.wordpress.com/2018/02/24/ime%E3%81%AE%E7%8A%B6%E6%85%8B%E3%82%92autohotkey%E3%81%8B%E3%82%89%E7%9F%A5%E3%82%8B%E6%96%B9%E6%B3%95%E3%82%B8%E3%83%A3%E3%83%B3%E3%82%AD%E3%83%BC-%E3%83%8E%E3%83%B3%E3%83%97%E3%83%AD%E3%82%B0/)


## 手順

### リンカーにimm32.libを設定

* メニュー - プロジェクト(P) - プロジェクトのプロパティを開く
* 左ペインの構成プロパティ - リンカー - コマンドラインを選択
* 「構成(C)」のデバッグとリリース両方とも「追加のオプション(D)」に「imm32.lib」を追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765459/49c5d13a-0b80-4dba-75a1-a30155e3ae52.png)

### include追加

```Sample.cpp
#include <imm.h>
```

### 処理

例、フォアグラウンドアプリのIMEがONの場合、OFFにする

```Sample.cpp

// フォアグラウンドアプリのハンドル取得
HWND hActWin = GetForegroundWindow();
if (hActWin)
{
    // フォアグラウンドアプリのIMEハンドルを取得
    HWND hIMEWnd = ImmGetDefaultIMEWnd(hActWin);
    if (hIMEWnd)
    {
        // IMEの状態取得
        LRESULT imeStatus = SendMessageA(hIMEWnd, WM_IME_CONTROL, DFCS_SCROLLCOMBOBOX, 0);

        // IMEがONだったらOFFにする
        if (imeStatus)
        {
            // 0x006 は IMC_SETOPENSTATUS
            // 第4引数を0でIMEをOFF(1でON)
            SendMessageA(hIMEWnd, WM_IME_CONTROL, 0x006, 0);
        }
    }
}
```
fuserコマンド (Linux)

## はじめに

今回はfuserコマンドの複雑なoptionについて下記にまとめました。

## fuserコマンド
・fuserとはローカルホストのリソースを使用中のプロセスを検索し、表示、<font color="DodgerBlue">強制終了</font>することのできるコマンド
・由来：「ファイル（File）を使っている人（USER）を調べることができる」とういうところから



## option早見表

|name  |optionの意味  |option内容  |
|---|---|---|
|-k|	kill(<font color="DodgerBlue">プロセス終了</font>) |プロセスにSIG KILLを送信。送りたいシグナルを指定するには-kではなく「-シグナル名」とする|
|-m |	mount |<font color="DodgerBlue">マウント</font>されたファイルシステムを指定|
|-n |	namespace|検索する領域を指定。<font color="DodgerBlue">file、udp、tcp</font>が指定できる|
|-u |	user |検索結果に<font color="DodgerBlue">ユーザー名</font>追加|
|-v |	verbose（詳細） |詳細な<font color="DodgerBlue">情報を表示</font>|
|-a|all|コマンドラインから渡された<font color="DodgerBlue">すべての</font>|ファイルを表示します。|
|-i||プロセスを<font color="DodgerBlue">killする前に確認</font>します。オプション -k と共に使用。|
|-l|ls|使用できるすべての<font color="DodgerBlue">シグナルリストを表示</font>します。|



※最短で覚えたい人はoptionの意味を覚えると早いと思います。
## 書式
```
$ fuser [オプション] 検索対象
```

```
//option別指定項目
[-m mindays] [-M maxdays] [-d lastday] [-I inactive]
[-E expiredate] [-W warndays][-l user]
```

## その他、パスワードの有効期限に関する設定が可能なコマンド
|name  |optionの意味  |
|---|---|
|lsof|ファイルシステムやポートなど、システムのリソースを使用しているプロセスの情報を表示可能|

※lsofコマンドは情報を表示するだけですが、fuserコマンドでは表示だけではなく、検索したプロセスに対してシグナルを送ることが可能

## 参考
https://webkaru.net/linux/fuser-command/
意味があるのか無いのかわからないものが作りたくて


何かを作る時のアイデアがポンポンでてくる人はホントに羨ましい。天才なんだろうか。怪物かお化け？


少し前から何か作りたい、できれば面白いものを。と思いつつも、何も良いアイデアが思い浮かばなかった。「アイデアの出し方」みたいな本を読んでみたりもしたけどどうしても見つからない。そんな時に見つけたのが孫正義の発明ノート。


> 1冊目の単語帳に「時計」、2冊目の単語帳に「冷蔵庫」と出たら、「時計付き冷蔵庫」「冷蔵庫付き時計」の可能性を考えるという具合です。「これはいける！」という可能性のあるアイデアが出るまで続けます。






「なるほどー。複数のカードに単語を書いて、それを組み合わせて考えていけばアイデア出るのかー。じゃあそれを作ってみようかな」


とりあえず作ってみた。



https://5seconds-en.com/en-words/gacha





![ezgif-5-7b68f03a8ed5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635968/fd507994-e834-2b8c-aba0-40be0cc9f3ba.gif)










ガチャガチャ英単語とガチャガチャ日本語!!!

使い方は簡単。ガチャガチャボタンを押して、単語が3つ出てくるので、組み合わせて文章を作ってツイートする。
意味があるのか無いのかわからないけどガチャガチャ英単語は割と意味があるんじゃないかと思う。文章を考えるときは英単語の意味を知っていないといけないし、知らなかったら調べる必要がある。必要に応じて過去形にしたり、未来形にしたり、考えることが必要だから。だから、割と簡単な動詞を中心に登録しています。Twitterに投稿をゴールとした場合、単語が多すぎると140文字以内は難しいかと思ったので3単語に設定しました。


ドメインを取ろうか悩んだけど、以前つくった5秒英作文と関連があるしドメイン取らずにそのまま引っ付けて作りました。フロントはVueでバックはLaravel。非同期でLaravelからのデータを渡せるのか、どうやってデータをTwitterに渡すのかも知らなかったので、作る前はできるか少し不安だったけど思ったよりも全然簡単でサクッとできました。まだTwitterに渡す部分でwarningがでてる(´;ω;｀)動くけども(´;ω;｀)
改善がんばります。
【Macbook】Chromeのフォント設定をデフォルトに戻す

# はじめに
Google Chromeのフォント設定を誤って変更してしまいました。
デフォルト値の「カスタム」に戻そうとすると、「カスタム」が見当たらない…

直すのに結構手間取ってしまったので、備忘録として書き留めておきます。

## 参考
以下の記事を参考にしました。ほぼ下の記事の通りですが、設定ファイルの位置などが自分の場合と異なっていたため、本記事を書こうと思いました。
https://qiita.com/RinGoku/items/b0943c4bc1099a340735

## 環境
MacBook Pro (13-inch, 2020)　Big Sur 11.2.3
Google Chromeのバージョン: 92.0.4515.107（Official Build）

# 方法
1.Google Chromeを閉じる
2.設定ファイルを編集する
設定ファイルですが、自分の場合は `~/Library/Application Support/Google/Chrome/Profile 1/Preferences`でした。
Chromeで使用しているユーザーごとに場所が異なると思われるので注意してください。（2番目のユーザーなら `Profile 2`以下にある）  
ファイルを何らかのエディタで開いて、末尾にある `"webkit"` で始まる部分を編集します。

```json:変更前
"webkit":{"webprefs":{"fonts":{"fixed":{"Zyyy":"Ricty Diminished"},"sansserif":{"Zyyy":"Hiragino Maru Gothic ProN"}}}},"zerosuggest":{"cachedresults":""}}
```

今回は誤って「ヒラギノ丸ゴ ProN」にしてしまったsansserifの設定をデフォルトに戻したいので、 `"sansserif":{"Zyyy":"Hiragino Sans"}`を`"sansserif":{"Zyyy":""}`に変更します。


```json:変更後
"webkit":{"webprefs":{"fonts":{"fixed":{"Zyyy":"Ricty Diminished"},"sansserif":{"Zyyy":""}}}},"zerosuggest":{"cachedresults":""}}
```

3.Google Chromeを再起動するとフォントが戻っている

以上です。
記事候補リスト

記事候補というか自分の調べたいことまとめ

#swift関連
- コンプレーション（_を入力すると引数なし？）　コンプリーション？コンピレーション？
- 列挙型　.から始まってるやつ
- google map SDK
- コアイメージ　CIimage UIimage
- OperationQueue
- クロージャ
- 画面遷移
- 外部からファイル取り込んだ時の対応
- ピンチインピンチアウト
- スレッド

#いかしたテーマ
- クイックタイムプレイヤー
- git
- UI準拠

#趣味レベル
- ジンバルロック
CDKでThe expected type comes from property 'timeout' which is declared here on type 'FunctionProps'が出た

## 問題

CDKでAPIを作成しておりLambdaにtimeoutの設定をしたら下記のようなエラーが表示されビルドできない

```

The expected type comes from property 'timeout' which is declared here on type 'FunctionProps'

```

またリファレンスを幾ら見ても使い方に誤りは見受けられなかった。

https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.FunctionOptions.html

## 解決策

どうやらライブラリごとのバージョンが微妙に異なっていた模様。
package.jsonのライブラリの @aws-cdk/〇〇 で定義されているもののバージョンをちゃんとstableでリリースされているものに整理して、下記コマンドを実行したところ解決した。

```sh

//古い node modules を削除
rm -rf node_modules

//新しい node modules をインストール
yarn install

```

自分の場合ちゃんとpackage.jsonに定義されていて上記のコマンドを実行するだけで解決したので、他のエラー解決するために`yarn add` どっかで変なモジュールをインストールしてたんだと思います。
ちゃんと定義できている人も一度上記のコマンドを実行してみるといいかもしれません。

## 参考

https://wp-kyoto.net/should-check-packagejson-when-npm-run-budil-failed/
CDKでthis CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version. (Cloud assembly schema version mismatch: Maximum schema version supported is 7.0.0, but found 13.0.0)

## 問題

CDKでデプロイしようとしたところ下記のようなエラーが表示された

```

his CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version.
(Cloud assembly schema version mismatch: Maximum schema version supported is 7.0.0, but found 13.0.0)

```

## 解決策

とりあえずaws-cdkのバージョンアップを行うことで解決
グローバルでaws-cdkを扱うのはあまり良くないが急ぎなのでまあしょうがない。

```sh

yarn global upgrade aws-cdk@latest 

```
AtCoderログ：0050 - ABC 212 A

# 問題

https://atcoder.jp/contests/abc212/tasks/abc212_a

## 問題文
> 高橋くんは $A$ グラムの純金と $B$ グラムの純銀 $(0 \le A, B, 0 < A+B)$ をよく溶かした上で混ぜ合わせ、新たな金属を生成しました。
> 生成された金属は「純金」「純銀」「合金」のいずれでしょうか？
> なお、生成された金属は
> ・$0<A$ かつ $B=0$ なら「純金」
> ・$A=0$ かつ $0<B$ なら「純銀」
> ・$0<A$ かつ $0<B$ なら「合金」
> であるとみなします。

## 制約
> ・$0 \le A,B \le 100$
> ・$0 < A+B$
> $A,B$ は整数

# 回答
## 回答1 (AC)
オリンピックにちなんだ問題ですね。問題文通りにコードにすれば良いでしょう。コードは以下のようになりました。

```C++:abc212a-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int a, b;
  cin >> a >> b;
  
  if ( 0<a && b==0 ) {
    cout << "Gold" << endl;
  } else if ( a==0 && 0<b ) {
    cout << "Silver" << endl;
  } else {
    cout << "Alloy" << endl;
  }
}
```

## 回答2 (AC)
$A=0, B=0$ はあり得ないので、$B=0$ なら「純金」、$A=0$ なら「純銀」と判別することができます。この考察を用いるとコードはちょっとだけ短くなります。

```C++:abc212a-2.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int a, b;
  cin >> a >> b;
  
  if ( b==0 ) {
    cout << "Gold" << endl;
  } else if ( a==0 ) {
    cout << "Silver" << endl;
  } else {
    cout << "Alloy" << endl;
  }
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc212/tasks/abc212_a/editorial) → [公式解説](https://atcoder.jp/contests/abc212/editorial/2361)
回答1と同じ方針でした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0049 - AGC 025 A](https://qiita.com/RoadLynton/items/d8b0dec4d519931856f2)
- 次の記事 → [AtCoderログ：0051 - ABC 156 B](https://qiita.com/RoadLynton/items/855e9c695ebd66218d5f)
AtCoderログ：0049 -  AGC 025 A

# 問題

https://atcoder.jp/contests/agc025/tasks/agc025_a

## 問題文
> 高橋君は $2$ つの正の整数 $A$ と $B$ を持っています。
> それらの和が $N$ であると分かっているとき、 $A$ の各位の和と $B$ の各位の和の合計として考えられる最小の値を求めてください。

## 制約
> ・$2 \le N \le 10^5$
> ・$N$ は整数

## 収録されている問題セット
- [AtCoder に登録したら次にやること](https://qiita.com/drken/items/fd4e5e3630d0f5859067) ([第05問類題](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-5-%E5%95%8F--abc-083-b---some-sums-200-%E7%82%B9))

# 回答
## 回答1 (AC)
問題文が少し理解しにくいですが、要は整数 n を2つの整数の和 a+b と表した時に、a と b の各桁の値の和の最小値を求めなさいということです。処理としては、変数 a を $1$ から順番に増大させ、整数 n を a+b に分割し、a と b の各桁の和を計算し、その最小値を求めれば良いでしょう。なお、a+b と b+a の各桁の和は同じなので、変数 a は $1$ から $n/2$ まで変化させれば十分です。計算量は $O(N/2)$ です。
コードでは各桁の和を計算する際に変数の値を変更してしまうので、変化させる変数 a に対し、分割には変数 aa と bb を使用しました。コードは以下のようになりました。

```C++:agc025a-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n;
  cin >> n;
 
  int dmin = 10e8;
  for ( int a=1; a<n/2+1; a++ ) {
    int aa = a, bb = n-aa, sum = 0;
    while ( aa>0 ) {
      sum += aa%10;
      aa  /= 10;
    }
    while ( bb>0 ) {
      sum += bb%10;
      bb  /= 10;
    }
    dmin = min( dmin, sum );
  }

  cout << dmin << endl;
}
```

aa と bb の各桁の合計を計算する処理を関数にすることもできますが、処理内容が簡単なため、上では関数を使用しませんでした。


# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/agc025/tasks/agc025_a/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/agc025/editorial.pdf)
上記回答のようにループを回す必要がなく、最小になる場合があらかじめ求められるとのことでした。これなら計算量 $O(1)$ なので、一瞬ですね。なるほど。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0048 - ABC 212 に参加しました](https://qiita.com/RoadLynton/items/583fdabb4805aaeb87c2)
zshプロンプトの設定[色変更・太文字・branch名]

### この記事の目的

初期設定のPCにて、ターミナルのプロンプトの設定に少し苦戦したので、現状の設定をここに記しておきます。
私の設定では、プロンプトは以下のように表示され、こだわりポイントは以下3点です。

1. 二行プロンプトとし、入力するコマンドを常に左端に表示させることで、目の移動を最小限に抑える
2. gitで管理下のディレクトリでは、branch名とその状態（add済、など）を表示させる
3. 現在のディレクトリを太文字・ユーザーとホスト名をシアンにすることで見やすくする（自分なりに

![プロンプト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/779676/68510fd0-7958-5ac7-be47-edaeb8950787.png)


### ~/.zshrc

以下がプロンプトの表示設定ファイルであり、`source ~/.zshrc`で変更を反映させることができます。

```bash
$ cat  ~/.zshrc
# ここら下はbranch名を表示させるメソッドの設定-----------------------------
function rprompt-git-current-branch {
  local branch_name st branch_status

  if [ ! -e  ".git" ]; then
    # gitで管理されていないディレクトリは何も返さない
    return
  fi
  branch_name=`git rev-parse --abbrev-ref HEAD 2> /dev/null`
  st=`git status 2> /dev/null`
  if [[ -n `echo "$st" | grep "^nothing to"` ]]; then
    # 全てコミットされてクリーンな状態
    branch_status=""
  elif [[ -n `echo "$st" | grep "^Untracked files"` ]]; then
    # gitに管理されていないファイルがある状態
    branch_status=" !"
  elif [[ -n `echo "$st" | grep "^Changes not staged for commit"` ]]; then
    # git addされていないファイルがある状態
    branch_status=" *"
  elif [[ -n `echo "$st" | grep "^Changes to be committed"` ]]; then
    # git commitされていないファイルがある状態
    branch_status=" +"
  elif [[ -n `echo "$st" | grep "^rebase in progress"` ]]; then
    # コンフリクトが起こった状態
    echo "%F{red} !!"
    return
  else
    # 上記以外の状態の場合は青色で表示させる
    branch_status=""
  fi
  # ブランチ名を色付きで表示する
  echo "($branch_name${branch_status})"
}

# プロンプトが表示されるたび、毎回プロンプトの文字列を評価し、置換する
setopt prompt_subst

# ここら下はプロンプトの表示設定-----------------------------
PROMPT='%F{cyan}[%n@%m]%F{white}: %B%~%b `rprompt-git-current-branch`
$ '
```

### 簡単な解説

上記のファイルは2段構成に分かれています。

#### gitのbranchの状態表示

この.zshrcファイルは、ほとんどgitのbranchの状態を表示させるメソッド`rprompt-git-current-branch`の設定が大体を占めています。
ほとんど参考記事のコピペですが、私の場合は状態によって色の表示ではなく、末尾のマークを変更しています。

クリーンな状態　　`[user@host]:  ~/www/ccc (999_branch_name)`
Untracked filesがある状態　　`[user@host]:  ~/www/ccc (999_branch_name !)`
addされていない状態　　`[user@host]:  ~/www/ccc (999_branch_name *)`
コミットされていない状態　　`[user@host]:  ~/www/ccc (999_branch_name +)`

この設定は上記のファイルの`branch_status=" !"`の部分で変更しています。ここで状態毎に色や太字など変化させることが可能です。

#### PROMPTの設定

プロンプトの表示設定はここだけです

```ruby
PROMPT='%F{cyan}[%n@%m]%F{white}: %B%~%b `rprompt-git-current-branch`
$ '
```

まず2段に分けることで、2行プロンプトにしています。
それぞれのコードの意味は、以下に示しますが、基本的に`%`を先頭に置き、それに続く文字により表示内容が変化します。

`%n`：ユーザー名
`%m`：ホスト名
`%~`：カレンとディレクトリ
`%F{color}`：色の表示変更、colorの部分に自分の場合はwhiteやsyanを入れています
`%f`：色の表示変更終了
`%B`：文字の太文字表示
`%b`：文字の太文字表示終了

### 参考記事

gitのbranch名を表示させるメソッド

https://suwaru.tokyo/1箇所コピペするだけでgitブランチ名を常に表示【-zshrc/

プロンプトの表示設定

https://qiita.com/araki-yzrh/items/421d75dde0bec8a28c69

以上です！最後までお読み頂きありがとうございました！
UnityでビルドしたiOSアプリをTestFlightで配信する

# 全体の流れ
1. App Store Connectにアプリを登録
1. Unityでビルド
1. Xcodeでアップロード
1. テストユーザーの招待

# App Store Connect にアプリを登録
1. バンドルIDがない場合は[Apple Developer](https://developer.apple.com/account/resources/identifiers/bundleId/add/)で作成する。
1. https://appstoreconnect.apple.com/ にアクセス & ログイン
1. マイApp→新規Appからアプリケーションを作成

# Unityでビルド
1. Build Settings > Player > Identification > BundleIdentifierに先ほど登録したバンドルIDを入力
1. Build Settings > Player > Icon > Marketing Icons を登録
1. ビルド
 
# Xcodeでアップロード
1. Xcodeでプロジェクトを開く
1. Signing & Capabilities > Team を入力
1. Build Settings > Signing > Development Team を入力
1. 画面上部のProduct > Archive をクリック
1. Validate App をクリック
1. Distribute App をクリック

アップロードに成功するとApp Store Connect上でアプリのTestFlight に表示されます。
Xcode上でUploadに成功しているのにApp Store Connectに表示されない場合はメールにエラーの内容が届きます。
Archive一覧はXcodeの Window > Organizerで開くことができます。
# テストユーザーの招待
1. App Store Connect > ユーザーとアクセス > メールアドレスを入力して招待
1. App > TestFlight から内部テストを作成
1. 内部テストにユーザーを招待

# テストプレイする側
1. メールアドレスを開発者に伝える
1. ユーザー招待メールのリンクから参加
1. TestFlightをインストール
1. アプリケーション招待メールからTestFlightでテスト
[Ruby on rails]タグ付け機能② タグをリンクにしてタグで検索（複数タグ）

<h2>やりたいこと</h2>
①投稿に対して複数タグを付けれるようにする（別記事で実装済）
<h6>②タグをリンクにして、検索できるようにする。リンクになってるタグを押すと、
そのタグを付与してる記事一覧が表示される</h6>

:fist:複数タグの投稿
![スクリーンショット 2021-08-02 14.02.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/d4dbb3f1-e343-c84e-9bf0-62e85deb1d82.png)
:fist:投稿一覧画面でタグの一覧と、記事数の表示
![スクリーンショット 2021-08-02 14.02.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/8445fd36-0244-02c4-bc88-0fc446c80fa4.png)
:fist:タグを押すと、検索ができ、そのタグがついてる投稿を検索できる
![スクリーンショット 2021-08-02 14.02.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/e537a70b-a6f6-99a1-8b3f-15fcb4f31851.png)
:fist:投稿詳細画面
![スクリーンショット 2021-08-02 14.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/62bdc75a-5019-7494-d230-af43f0b7a8fa.png)

①の複数のタグをつけて記事を投稿する機能については以下の記事で行っています。
今回はその続きです。

https://qiita.com/ki_87/items/a344ea566c88b10b950c


<h2>ルーティング記述</h2>

```perl:route.rb
# タグの検索で使用する
  get "search_tag"=>"posts#search_tag"
```

<h2>コントローラー記述</h2>

```posts_controller.rb
 def search_tag
    #検索結果画面でもタグ一覧表示
    @tag_list=Tag.all
　　　　　　　#検索されたタグを受け取る
    @tag=Tag.find(params[:tag_id])
　　　　　　　　#検索されたタグに紐づく投稿を表示
    @posts=@tag.posts.page(params[:page]).per(10)
  end
```



<h2>表示してるタグをリンクにする</h2>

```perl:index.html.erb
<!--タグリスト-->
<% @tag_list.each do |list|%>
<%=link_to list.name,search_tag_path(tag_id: list.id) %>
<%="(#{list.posts.count})" %><% end %>
```

```show.html.erb
 <!--タグ-->
  <% @post_tags.each do |tag| %>
  <%= link_to tag.name,search_tag_path(tag_id: tag.id)%><%="(#{tag.posts.count})" %><% end %>
```

<h2>view（検索結果の表示</h2>

```
<div class="container">
<h5>タグが<%=@tag.name%>の投稿一覧</h5>

<!--タグリスト-->
<% @tag_list.each do |list|%>
<%=link_to list.name,search_tag_path(tag_id: list.id) %>
<%="(#{list.posts.count})" %><% end %>
<% @posts.each do |post| %>
<!--投稿はカードで囲む-->
<div class="card">
  <div class="card-body">
    <!--タイトル表示される文字数は２５文字までにしてます-->
    <h6 class="card-title">
      <%=link_to post_path(post.id) do %><%= post.title.truncate(25) %>
      <% end %>
    </h6>
    <!--お気に入り、コメント数、投稿者は部分テンプレ-->
      <div id="<%=post.id %>"><%= render 'favorites/favorite', post: post %></div>
    
    
  </div>
</div>
<% end %>

<div class="pagination pagination-sm justify-content-center">
       <%= paginate @posts %></div>

</div>


<style>
.card{
  padding:0;
  margin:0;
  border:none;
}



h6 {
  /*線の種類（実線） 太さ 色*/
  border-bottom: solid 3px black;
}
</style>
```

<h2>終わり</h2>
以上で完了です。

<h2>とても参考にさせていただきました！</h2>

https://qiita.com/kurawo___D/items/e9a2dd0bf46cca706e5c
Flourishで陸上競技をモチーフにしたチャートを使い、過去のオリンピック陸上女子5000mのラップタイムデータを利用

##Sports raceチャートを試す

データの可視化機能を提供する[「Flourish」](https://flourish.studio/)の画面を見ていて、**「Sports race」**というチャート（グラフ）のメニューがあること尾に気づきました。
人がレースしているような振る舞いを再現しています。
以下は標準で付属しているサンプルの画面例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/2d11ca86-2b36-2c26-0e74-f6c71ac71258.png)

このチャートに使えるデータがないか探しました。
過去のオリンピックの「女子陸上5000m競技」のラップタイムを公開している**「日本陸上競技連盟公式サイト」**を見つけ、そのデータを使ってみることにしました。

https://www.jaaf.or.jp/news/article/15271/

##女子陸上5000m競技のデータを利用

数値をExcelにコピペします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/05ac81df-f2c9-f158-fc24-2db4a282b63a.png)

1000mごとのラップタイムなので、足し合わせます（表の右側）。
なお、元データの「3.06.15」という形式では「時間」の型にならないので、「3:06.15」という所世紀に変更しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/4c8e4c20-3623-4a04-0091-823c0a017d38.png)

下記のデータをFlourishにインポートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0cc287e7-0f0d-354b-6722-c0e5669a2644.png)

インポートし、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/9d26fde3-fdfe-c847-d553-2b4fbe58262f.png)

右パネルで設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0837fa98-1e23-e0ed-9874-91757c33bc9c.png)

「Preview」でアニメーションが再生されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0da9839d-3022-4716-cc2e-db793e6be481.png)

GIFアニメーションにしました。
下記のような感じで動きます。

![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/ab6580e0-e00c-a15c-bfcd-dbbec6f8e09d.gif)

**了**
Visual Studio Codeの日本語化

もう絶対誰かしら書いてるけど、一応書いておく。

---

## Visual Studio Codeをインストールして起動したら英語なんだけど？
って人。安心して欲しい。公式で日本語化出来る手段あるよ。
今回参考にするのは、↓このサイト。

https://www.javadrive.jp/vscode/install/index4.html

なんだけど、一応手順も書いとく。

1. VisualStudioCodeを起動する

2. View -> Command Palette を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/fc8df768-d551-ff8f-71ba-7c79df2be228.png)

3. 出てきたとこに Display と入力すると、 Configure Display Language が出るので選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/e8d49144-89e4-0290-e33d-d5aed5bfff6c.png)

4. Install Additional Languages... を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/af97b6f4-92c6-c935-d587-1df5d44cb533.png)

5. 何かいっぱい一覧が出るので Japanese Language Pack for Visual Studio Code を Install する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/c41ec831-4974-0e5e-6eeb-01c6d8d3df1b.png)

6. VSCodeの再起動を促されるので再起動する
7. 起動すると、日本語になってる。おわり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194966/95e45abd-ba63-70f5-cbf4-23f287bba180.png)

## 参考
- Visual Studio Codeを日本語化する
  - https://www.javadrive.jp/vscode/install/index4.html
「コンピュータシステムの理論と実装」の実習

#概要

自分の記事で、「コンピュータシステムの理論と実装」の実習を組んでみた。


#1章: ブール論理　2章: ブール算術　3章: 順序回路

https://qiita.com/ohisama@github/items/8422efab112fa9b71369

https://qiita.com/ohisama@github/items/ade51b6360dcb7730f7f

https://qiita.com/ohisama@github/items/b6262f448df6c8bfe587

https://qiita.com/ohisama@github/items/db7c6d02a56c40dca8b5

https://qiita.com/ohisama@github/items/e1199a40a6591aa22823

#4章: 機械語

https://qiita.com/ohisama@github/items/5246b65189a9f5600871

https://qiita.com/ohisama@github/items/90fc17064279901d0cd6

#5章: コンピュータアーキテクチャ

https://qiita.com/ohisama@github/items/728b23e629b4c091f93f

https://qiita.com/ohisama@github/items/44307bb7b00e77976829

#6章: アセンブラ

https://qiita.com/ohisama@github/items/6cc1be0304c5fe9a2bf1

https://qiita.com/ohisama@github/items/f08a06784890a65a13cf

https://qiita.com/ohisama@github/items/f8c8315b906598c3d3f9

https://qiita.com/ohisama@github/items/8e2679325e724b913059

https://qiita.com/ohisama@github/items/ec52b2c53ce00bd36a43

#7章・8章: バーチャルマシン（スタック操作・プログラム制御）

https://qiita.com/ohisama@github/items/22e35c8a00bd23010469

https://qiita.com/ohisama@github/items/ab6283540ae1ba0ad890

#9章: 高水準言語

https://qiita.com/ohisama@github/items/e64e717a738aea1dd59a

#10・11章:コンパイラ（構文解析・コード生成）

https://qiita.com/ohisama@github/items/d1b3b0350a1487ecd995

https://qiita.com/ohisama@github/items/dfcdaa9fb13cdb198df0

https://qiita.com/ohisama@github/items/53e4cf5a51fd421c1b52

#12章: オペレーティングシステム

https://qiita.com/ohisama@github/items/d18ca704c5f56a8fd74b

https://qiita.com/ohisama@github/items/92cd1332a28bb7264907

https://qiita.com/ohisama@github/items/b550517b8f41e3234bc6

https://qiita.com/ohisama@github/items/145d617dad6b6e6c00f0

#13章: さらに先へ

以上。
pixi.jsのcontainerからテクスチャーを作る

pixi.jsのcontainerからtextureをつくるやり方です。
こんな感じのクラスを作ってみました。

```typescript
class ContainerToTexture {
  private width: number;
  private height: number;
  private texture: PIXI.RenderTexture;
  constructor(width: number, height: number){
    this.resize(width, height);
  }
  /**
   * コンテナをテクスチャーに変換する
   * @param container 変換するcontainer
   * @returns 生成したテクスチャー
   */
  public convert(container: PIXI.Container){
    core.app.renderer.render(container, this.texture);//rendererをお使いにの場所に変えてください
    return this.texture;
  }
  //テクスチャーのサイズを変更
  public resize(width: number, height: number){
    this.width = width;
    this.height = height;
    this.texture = new PIXI.RenderTexture(
      new PIXI.BaseRenderTexture({width: width, height: height})
    );
  }
}
```
幅と高さを指定してクラスを作ってconvert()で変換したいcontainerを渡してやるとテクスチャーになって返ってきます。

## おまけ
★pixi.jsの基本的な使い方の記事
▷ [【PixiJS入門】基本的な使い方まとめ](https://javascript-game.com/basic-pixijs/)
CodeBuild でテストツール使ってみた

## 初めに

過去にデプロイしたが動かなかった経験があるため、デプロイ前のビルドでテストを行えるようにした。

## BuildSpec

YAML形式で、コードサンプルは以下の通り。
注意点としては、ソースコードのトップに置かないと認識しない。
また、Testツール（以下のpytest）は結構ややこしいので、詳細は後ほど記載する。

```yaml
version: 0.2
phases:
  install:
    runtime-versions:
      python: 3.8
    commands:
      - pip install pipenv
  pre_build:
    commands:
      - pipenv install --dev flake8 pytest urllib3
      - export VENV_HOME_DIR=$(pipenv --venv)
      - . $VENV_HOME_DIR/bin/activate
      - flake8 xxx.py
      - python -m pytest
```

## Test Tools

### flake8

構文チェックツールで、基本的にPEP8に準拠するようにするものと思っている。
以下のラッパーとのこと。

- pycodestyle
- pyflakes
- Ned Batchelder’s McCabe script

### pytest

UnitTestツールで、ディレクトリや設定が結構ややこしい。
簡易的にまとめたので参考程度に留めたい。
screenコマンドチートシート

毎回忘れて調べてるので自分用にメモ :pencil: 

## screenとは

リモートで長時間かかるスクリプトなんかを実行したいときに使います。
screen 上でスクリプト実行することで、 ssh 接続切れによるスクリプト実行中断を防ぐことができます。

## screen 起動

```
$ screen
```

`$ screen -S <sessionname>` でセッション名をつけることもできます。そんな使わない。

## screen を抜ける

`Ctrl+A d` で screen を抜けられます。
実行中のプロセスは継続し、 detached 状態になります。

## screen上のプロセス一覧確認

screen 上で実行中プロセスの pid, attached/detached 状態を確認できます。

```
$ screen -ls
```

## screen 上のプロセスを attach

detached 状態の pid を指定することで attach できます。

```
$ screen -r <pid>
```

:::note warn

attached な pid を指定するとエラーになります。

:::

## screen 上のプロセスを detach

attached 状態の pid を指定することで detach できます。

```
$ screen -d <pid>
```

:::note info

detach してから attach することで横取りできます :sunglasses:

:::
vmにIt works! を表示する。

vmに
http://192.168.33.10/index.html
It works! を表示するには？

#vm
・vagrantファイルいじらないと
192.168.33.10が見れない。
ネットワーク通っていないことになる。
・ vagrantファイルを編集したら、vagrant reload　読み込みし直す。
・ ifconfig　でinet 192.168.33.10  が出ていることを確認する。

#apache2
・インストールする。
・apache2起動を確認する。
起動していなければ、見れない。
$ ps aux | grep apache2
・ドキュメントルート、見る場所を設定する。
/etc/apache2/sites-available$ vi 000-default.conf　ファイルに、

```apache
<Directory "/var/www/html">
 AllowOverride All
</Directory>
```

追加。
・設定ファイルをいじったら、sudo service apache2 restart　再起動する。
・/var/www/html　にファイルなんかあることを確認する。
EKS上のfluentdからs3へログ転送する設定


## サービスアカウントを作成

```
eksctl create iamserviceaccount --name fluentd-s3 --cluster vamdemic-cluster --namespace thanos --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess --approve
```

## fluent.conf

```
   <store>
        @type s3
        s3_bucket vamdemic-fluentd
        s3_region ap-northeast-1
        path logs/
        <buffer tag,time>
          timekey 3600 # 1 hour partition
          timekey_wait 10m
          timekey_use_utc true # use utc
        </buffer>
      </store>
```

## めも
- IAMUserを作成しなくて良い
- eksctl経由でサービスアカウントを作成位するとIAM-IDプロバイダに登場する
- NodeにIAMを割り当てる必要はない
[自分用メモ] Hiveのテーブル作成

## テーブル作成例

```sql
create table customer (
  `c_custkey` bigint COMMENT '', 
  `c_name` string COMMENT '', 
  `c_address` string COMMENT '', 
  `c_nationkey` bigint COMMENT '', 
  `c_phone` string COMMENT '', 
  `c_acctbal` double COMMENT '', 
  `c_mktsegment` string COMMENT '', 
  `c_comment` string COMMENT '')
STORED AS PARQUET
LOCATION 'gs://bucket-1/customer';
```

## テーブルの作成 Avro バージョン

```
CREATE  TABLE `customer`(
  `c_custkey` bigint COMMENT '', 
  `c_name` string COMMENT '', 
  `c_address` string COMMENT '', 
  `c_nationkey` bigint COMMENT '', 
  `c_phone` string COMMENT '', 
  `c_acctbal` double COMMENT '', 
  `c_mktsegment` string COMMENT '', 
  `c_comment` string COMMENT '', 
  `null` binary COMMENT '')
  STORED AS AVRO
  LOCATION 'gs://bucket-2/customer'
  TBLPROPERTIES("avro.compression"="SNAPPY");
```

## 他のテーブルからのデータの挿入

```
insert overwrite table customer select c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_mktsegm
ent, c_comment from db1.customer;
```

## テーブルの作成 PRC パーティションあり

```
CREATE TABLE `lineitems`(
  `l_orderkey` bigint, 
  `l_linenumber` bigint, 
  `l_quantity` double, 
  `l_extendedprice` double, 
  `l_discount` double, 
  `l_tax` double, 
  `l_returnflag` string, 
  `l_linestatus` string, 
  `l_shipdate` date, 
  `l_recieptdate` date, 
  `l_shipinstruct` string, 
  `l_shipmode` string, 
  `o_orderkey` int, 
  `o_custkey` int, 
  `o_orderdate` date, 
  `o_totalprice` double, 
  `o_orderstatus` string, 
  `o_orderpriority` string, 
  `o_shippriority` int, 
  `o_clerk` string, 
  `c_custkey` bigint, 
  `c_nationkey` bigint, 
  `c_acctbal` double, 
  `c_mktsegment` string)
PARTITIONED BY (year int, month int, day int)
STORED AS ORC
LOCATION 'gs://bucket-3/';
```
AndroidStudioの自動インポートを有効にする(Windows)

## 自動インポートを有効にすると....

- インポートを毎回記述しなくて良くなる
- 使用していないインポートは自動的に削除される

## 自動インポート設定方法　(Windowsの場合)

**AndroidStudioのバージョン**
AndroidStudio version 4.2.1

「File」>「New Projects Settings」>「Setting For New Project...」を開くと、「Settings for New Projects」が開く。
「Other Settings」>「Auto Import」を開き、Java、Kotlinの両方のセクションにおける下記項目の設定をオンにする。

- [x] Add unambiguous imports on the fly (import文の自動追加)
- [x] Optimize imports on the fly (for current project) (使用されていないimport文の自動削除)

「Apply」で変更を適用し「OK」を押して設定を閉じる。
SREチームで社内GameDayを実施しました

## GameDayとは

起源はAWSが毎年行っているAWS re:inventの中で開催される行事の1つです。
チームを組んでクラウド・アプリケーションを襲う謎の障害や悪意のある攻撃に対処し、**トラブルシューティング能力**を競うコンテストとなっています。
のちに様々な企業が社内でも実施するようになり、今では*AWS Well-Architected*のセキュリティ項目でもその実施が推奨されています。

> ### ゲームデーを実施する
> - ゲームデーを実施する: さまざまな脅威について、インシデント対応イベントのシミュレーション (ゲームデー) を実施します。このゲームデーには、主要なスタッフや管理者を参加させてください。
> - 教訓から学ぶ: ゲームデーの実行から得られた教訓は、プロセスを改善するためのフィードバックに含まれている必要があります。

https://wa.aws.amazon.com/wat.question.SEC_10.ja.html

## GameDayの手順

今回社内で行なったGameDayの流れです。


### 1. 発生させる障害を決める

本来であれば、障害対応者たちはその内容を事前に知らされずに対応します。
しかし初回ということもあり、事前にチームで相談して発生させる障害を決めました。
話し合いの結果、今回はAWS側の障害で最も頻繁で有名なAvailability Zone(AZ)障害を選択しました。


### 2. 事前に障害対応のドキュメントを作成する

想定される障害に関しては、事前に対応手順をドキュメント(復旧手順書)にしておきます。
障害に関するドキュメントは、そのシステムにとって重要な仕様書です。
また、実際の障害発生時に、ベンダーのリファレンスからリソースを一から探したり、他のメンバーを呼んで議論することは、復旧が遅れる原因にもなります。
事前に整理された手順書を参考にしながら対応することで、障害対応のスピードとクオリティを大幅に向上させることができるのです。


### 3. 対応リソースごとにチーム分けをする

弊社のSREのオンコール対応は、2週間ごとに当番の一名が担当するシフト制です。
しかし、AZ障害のような大きな障害は、複数のリソースに影響を及ぼすので、一人で全てを復旧するには負担が大きいです。
なので今回は、影響のあるリソースごとに以下のように担当者を割り振りました。

- ECS: 2名
- RDS: 1名
- ElastiCache: 1名

### 4. 実際に障害を発生させる

本番で障害を発生させて可用性を測るカオスエンジニアリングとは違い、GameDayはチームのトラブルシューティング能力を測るのが目的です。
なので今回は、Production環境ではなくStaging環境で障害を発生させます。
Gremlinなどの障害発生ツールを使うのが理想ですが、今回はVPCの特定のAZのルートテーブルに紐づくサブネットをデタッチすることで、擬似的にAZ障害を再現します。


### 5. 障害に対応する

各自アラートに気付き次第、実際に障害対応を行います。
今回はリモートワーク下での実施ということもあり、各々の作業を[SpatialChat](https://spatial.chat/)というチャットツールで画面共有しながら行います。
また、障害対応中はスクリーンショットやSlackの特定のチャンネルへのメモなどで、できるだけログを残しておきます。

https://spatial.chat/


### 6. 反省会

各々の障害対応の内容を、オペレーションログ兼報告書として提出します。
また、ドキュメントの手順書通りに対応してうまくいったかどうかを照らし合わせ、内容に不備がないかを確認します。


## 事前準備

GameDay当日までに、以下の準備を行いました。

### Staging環境の冗長化

できるだけProduction環境に近い構成で行うために、事前にStaging環境のリソースもProduction環境同様に冗長化させておきます。
今回は各リソースを複数のAZに配置するようにしました。


### ドキュメントの作成

自分の担当ではないリソースのドキュメントを、各々事前に書いておきます。
また、不足の事態を再現するため、このドキュメントは当日はまで担当者は見れないように設定します。


## GameDay当日

### 1. 障害を発生させる

障害発生担当の方が、VPCのルートテーブルからサブネットをデタッチしました。



### 2. メンバーを招集

Datadogのアラートに気づいたメンバーが緊急性の高い障害であると判断し、SpatialChatに集まるよう指示しました。


### 3. 障害対応

各々の作業画面を表示させて、それぞれ対応にあたりました。
ECSは担当が二人だったので、一方はドキュメントを見ながら指示を出し、もう一方はそれに従って作業をするようにしました。


### 4. 問題発生

RDSとElastiCacheとFargateはドキュメント通りに復旧できましたが、ECSのEC2インスタンスでは想定外の問題が起こりました。
ECSのEC2インスタンスは、aとcの二つのAZに冗長化させており、今回は障害が起きていない方のcにALBを一時的に寄せようとしました。
しかし、[ALBは「最低二つのsubenetの指定が必要」「指定できるsubnetは各AZに一つだけ」という制約](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html#configure-load-balancer)があったので、復旧には元々三つのAZが必要でした。
結果、ECSのEC2インスタンスの復旧に関しては、失敗という形に終わりました。

https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html#configure-load-balancer


### 5. 反省会

**よかったところ**

- 事前にドキュメントを準備していたおかげで、スムーズに復旧ができた。
- 画面共有で作業を可視化することで、お互いの作業を助け合えた。


**反省点**

- ドキュメントがより詳細だとなおよかった(Terraformのファイルパスなど)。
- 他のメンバーへの作業確認を一部怠っていたところがある。
- 作業ログは時間ベースでもっと残しておくべきだった。

**課題点**

- 3AZでなければALBが復旧できないので、次回は3AZ状態で検証する。
- オンコール対応の場合、一人で全てのサービスを復旧できるかどうか。
- オンコール対応の場合、対象のサービスの復旧優先順位を事前に決めておく必要がある。

## まとめ

今回のGameDayでは、チームの各サービスに対する理解度や、障害対応の手順などが再確認ができたことが大きいと思います。
次回は実際のRTOの計測のためにも、オンコール対応者のみで実施する予定です。
Nuxt.jsでtsconfig.jsonのpathsに追加してもインポートできないでハマったときの備忘録

以下のような構成のシステムでフロント／バックエンドでファイルを共有するためにtsconfig.jsonを弄り回してたんですが、Nuxt.js側でハマったので備忘録として残しておきます。

- フロント：Nuxt.js
- バックエンド：NestJS
- 共通プロジェクト：Typescriptプロジェクト


# エディタ上ではパスが通ってるのにビルドが通らない。。

tsconfig.jsonを以下のように修正したところ、NestJSはすぐにインポートできるようになったのですが、Nuxtの方は`Module not found: Error: Can't resolve '@shared/`となってしまいビルドが通りませんでした。。。
（VSCode上ではエラーは出ずにちゃんとパスやJSDocが参照できる状態でした）

```tsconfig.json
{
  "compilerOptions": {
    "target": "ES2018",
    "module": "ESNext",
    "moduleResolution": "Node",
    "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "@shared/*": ["../shared/lib/*"],
      "~/*": ["./src/*"],
      "@/*": ["./src/*"]
    },
    "types": ["@nuxt/types", "@nuxtjs/axios", "@types/node", "./types", "../shared/lib/types"]
  },
  "exclude": ["node_modules", ".nuxt", "dist"],
  "references": [
      { "path": "../shared" }
  ]
}

```



# 結論

nuxt.config.jsのaliasに定義が必要でした。
参考：https://ja.nuxtjs.org/docs/2.x/configuration-glossary/configuration-alias

pathsと以下の対応でビルドが通るようになりました！！！！
（tsconfig.jsonの方も上記の対応をしないとVSCodeがパス解決できないので必要でした）

```nuxt.config.js
import { resolve } from 'path';

export default {
  ・・・
  alias: {
    '~/*': resolve(__dirname, 'src/*'),
    '@/*': resolve(__dirname, 'src/*'),
    '@shared': resolve(__dirname, '../shared/lib'),
  },
}
```
「HTTP」と「HTTPS」の違い

「HTTP通信（Hypertext Transfer Protocol）」
→webページの転送に利用するプロトコル。webブラウザを使ってHTMLで記述された文書を受信するときなどに使う。

「HTTPS（Hypertext Transfer Protocol Secure）」
→HTTPと同じプロトコル（通信規格）の1つ。
HTTPS　の最後の「S」はセキュア（Secure）のことで、HTTPSではSSL（Secure Sockets Layer）というプロトコルを使用しする。

「HTTP」と「HTTPS」の違い
HTTP」と「HTTPS」の大きな違いは、「通信内容が暗号化されているかどうか」
HTTPSに対応するサーバーでは、ウェブサイトの通信内容を暗号化してくれるので、ウェブの情報を安全にやり取りできる。
Goのインストールとチュートリアルメモ

Go使ったことない人間がGoのインストールしてから[公式](https://golang.org/doc/install)のチュートリアル進めて行くにあたって躓いた点などをメモ。
なおMac前提。(随時追記)

# インストール
* [公式](https://golang.org/doc/install)から最新版をダウンロードしてインストールする
* よくわからんけどgoコマンドが `command not found` になってしまうっ……！ってなったので、~/.bash_profileをいじいじしてパスを通す。

```~/.bash_profile
# goのインストール先は/usr/local/goになる
export PATH="/usr/local/go/bin:$PATH"
```

そんでもってターミナル再起動かsourceで再読み込み

```
$ source ~/.bash_profile
```

これでようやくgoコマンドが動いた

```
$ go version
go version go1.16.6 darwin/amd64 
```

`$GOPATH` もなかったので指定しとく

```~/.bash_profile
# GOPATHは適当に指定してもOK
export GOPATH=$HOME/.go
```

sourceで読み込んで準備完了。

```
$ source ~/.bash_profile
$ echo $GOPATH
/Users/xxxxx/.go
```

# チュートリアル1: Get started with Go
前半について。
`package main` の意味とか、 `go run` 時の動作とかは[このサイト](https://nununu.hatenablog.jp/entry/2016/09/20/210000)がすごくわかりやすかった。
`go mod init (path)`については、作成したmoduleをpublishする際には注意が必要ってことっぽい。

> The name is the module's module path. In most cases, this will be the repository location where your source code will be kept, such as github.com/mymodule. If you plan to publish your module for others to use, the module path must be a location from which Go tools can download your module.


後半について。
`go mod tidy` で `rsc.io/quote` のモジュール本体がどこに行ったのかというと、 `$GOPATH` 配下にダウンロードされてた。なるほどね。

```
$GOPATH ── pkg ─┬─ mod   ─┬─ cache
                │         ├─ golang.org
                │         └─ rsc.io ── quote@v1.5.2 
                └─ sumdb 
```

`go run .` で結構時間かかるのはコンパイルしてるから。上に貼ったサイト参照。

※以降のチュートリアルは環境整っちゃえば大丈夫そう
CertbotでSSL証明書を更新する2ステップ

## 概要
EC2サーバーのSSL証明書を更新するための手順を記録として残しておきます。

## 手順
SSL証明書の更新にCertbotを使っている前提です。
### 1. EC2にログイン
```bash:ターミナル
ssh -i 秘密鍵ファイル名 ユーザー名@ipアドレス
```
### 2. EC2上でコマンドを実行
root権限で実行してください

```bash:ターミナル
sudo certbot renew --force-renewal
```
SSL証明書の期限の猶予が十分に残っている場合は、``certbot renew``のみでは失敗します。
ですので、``--force-renewal``オプションでSSL証明書の有効期限の猶予を無視して強制的に実行しています。
## 最後に
Qiitaではなく、ドキュメントなどの一次情報を参照することが大事だと再認識しました。
英語に立ち向かいます:sob:
## 参考記事
[User Guide — Certbot 1.16.0.dev0 documentation](https://certbot.eff.org/docs/using.html)
mediapipeを含んだファイルをexe化するときに発生するエラーの原因とその対策

#エラーの発生

Google Mediapipeを使うプロジェクトをEXE化するとき、下記のようなエラーが発生します。
EXE化するときに、pyinstaller, py2exeのどれを使っても、同様なエラーが発生します。

```
#実行
pyinstaller --onefile GUI-mediapipe-app.py

#エラー
Traceback (most recent call last):
  File "GUI-mediapipe-app.py", line 26, in <module>
  File "mediapipe/python/solutions/selfie_segmentation.py", line 54, in __init__
  File "mediapipe/python/solution_base.py", line 229, in __init__
FileNotFoundError: The path does not exist.
[36342] Failed to execute script pose_edge

```

#エラーの原因

　Mediapipeライブラリーは、プログラムが実行するとき、特定のファイルを必要とします。特定のファイルとは、主にTensorflowファイルで .tflite拡張子を持っているファイルです。これらのファイルは動的に読み込まれるため(```Dynamically loaded```)、PyinstallerなどのEXE化ソフトが、EXE化のコンパイル過程で、これらのファイルをdist フォルダに持ってくることも認識していませんん。

従って、上記のように```FileNotFoundError: The path does not exist.```のエラーが必ず発生します。

#エラーの対策

この問題を解決するためには Pyinsatllerの spec fileのdata属性に、参照するフォルダを指定します。
Python環境(ここではvenv）フォルダ下にある```\\Lib\\site-packages\\mediapipe\\modules```が```mediapipe\\modules```であることを教えます。

```
datas=[(venv\\Lib\\site-packages\\mediapipe\\modules', 'mediapipe\\modules'),]
```

ここで私が作成したspec fileを掲載します。
これで問題が解決します。

```py

# -*- mode: python ; coding: utf-8 -*-
#https://github.com/google/mediapipe/issues/2162

block_cipher = None


a = Analysis(['GUI-mediapipe-app.py'],
             pathex=['.'],
             binaries=[],

             datas=[(venv\\Lib\\site-packages\\mediapipe\\modules', 'mediapipe\\modules'),],

             hiddenimports=[],
             hookspath=[],
             hooksconfig={},
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)

a.datas += [('favicon.ico', '.\\image\\favicon.ico', 'DATA')]

pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)

exe = EXE(pyz,
          a.scripts, 
          [],
          exclude_binaries=True,
          name='Tokyo2020_pictogram_GUI',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True,
          disable_windowed_traceback=False,
          target_arch=None,
          codesign_identity=None,
          entitlements_file=None )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas, 
               strip=False,
               upx=True,
               upx_exclude=[],
               name='Tokyo2020_pictogram_GUI')


```

#実行結果

mediapipeを利用し、自分のWebCamで、東京2020オリンピックのピクトグラムを生成するプログラムを作ってみました。
下記の動画のページに、プログラムダウンロードリンクもありますので、ご興味のある方は、ぜひご覧ください。

https://youtu.be/Xrn7Kjo2Zvk



#課題
Pyinstallerの場合、spec fileのdata属性に参照フォルダの情報を入れることで問題を解決しました。
しかし、py2exeの場合は、どうすればいいかまだ未確認です。py2exeでの、参照フォルダの指定する方法のご存知の方は、メモを残していただければと思います。
LMS简单的例子

```
test文件
<?xml version="1.0" encoding="UTF-8"?>
<LightningMessageChannel xmlns="http://soap.sforce.com/2006/04/metadata">
    <isExposed>true</isExposed>
    <lightningMessageFields>
        <fieldName>docCount</fieldName>
    </lightningMessageFields>
    <masterLabel>test Message Channel</masterLabel>
</LightningMessageChannel>
```


```
发送方
import { LightningElement,api,wire} from 'lwc';
import { publish, MessageContext } from 'lightning/messageService';
import testpub from '@salesforce/messageChannel/test__c';//注意这里的__c，如果不加就会报错

export default class Lms_pub extends LightningElement {
    @api iivalue;
    @api searchBarIsVisible;

    @wire(MessageContext)
    messageContext;

    connectedCallback(){
        //publish(this.messageContext, testpub, { docCount: 12});
    }

    // Respond to UI event by publishing message
    handleContactSelect(event) {
        if (event.keyCode === 13) {   
            publish(this.messageContext, testpub, { docCount: event.target.value});
        } 
        //const payload = { recordId: event.target.contact.Id };
    }

}


```


```
接收方
import { api,wire,LightningElement } from 'lwc';
import { subscribe, MessageContext } from 'lightning/messageService';
import testChannel from '@salesforce/messageChannel/test__c';

export default class Lms_sub extends LightningElement {
  @api searchBarIsVisible;
  @api iiop;
  @wire(MessageContext)
    messageContext;

  connectedCallback(){
    this.handleSubscribe();
  }

  handleSubscribe() {
    this.designDocSubscription = subscribe(this.messageContext, testChannel, (message) => {
      if (message.docCount != undefined) {
       this.iiop = message.docCount;
      }
      if (message.forceRefresh && this.cacheData) {
        refreshApex(this.cacheData);
      }
    });
  }



}




```
非エンジニアにseleniumでスクレイピングをやってもらうまでの軌跡（準備編）

#はじめに
非エンジニアの方（プログラム一切勉強したことない＆GUIしか触ったことないようなレベル）にpythonでスクレイピングが出来るように色々教えた流れをまとめた個人的備忘録です。今後他の人に教える際にも参考にできるかと思いここに残しておきます。
#スクレイピングって何？
情報を取得して加工することです。今回はWEBページから情報を取得します。自動でWEBページからほしい情報をまとめられるようになったら便利ですよね。それを作ります。
#VSCodeとPythonのインストール
【インストールしてほしいもの】
・Visual Studio Code(VSCode)
・Python
以下のサイトを参考にVSCodeとPythonをインストールしましょう。上から順にサイト通りに進めていきましょう。ページ下部まで終わったらnextページに飛んで同様に進めてください。【次のステップ】というページが出てきたらインストールはおしまいです。
参考URL　https://www.python.jp/python_vscode/windows/setup/config_explorer.html
【なにをしているのか】
色々なものを作るためのPyhonというプログラミング言語をあなたのパソコンで使えるようにしています。そのPythonを組み立てるのがVSCodeです。とても雑に例えると鉛筆(Python)とノート(VSCode)みたいなものです。

#仮想環境作成
コマンドラインの触り方をまず勉強しましょう。progateで無料アカウントを利用してレッスンを受講してください
https://prog-8.com/courses/commandline
コマンドラインの操作が分かるようになったら以下のサイトを参考にvenvで仮想環境を作ってください。
参考URL　https://hachian.com/2019/09/19/vscode_venv/
参考URL　https://qiita.com/enya314/items/0e62b68fe70f52a628bf

【なにをしているのか】
Pythonには様々なライブラリがあり、目的別にそれらをインストールして利用します。しかし何でもかんでもインストールしているとうまく動作しなくなったりと問題が多いので仮想環境というものを作って分けて管理します。例えるとキッチンと寝室を分けるみたいなイメージです。キッチン兼寝室はちょっと嫌ですよね・・・？じゃあ部屋（仮想環境）を目的別に作って使い分けたほうがいいよねって感じです。

#Pythonの基礎を知ろう
progateの無料講座を受けてください。決して丸投げではないです。15分調べてみてわからなかったらすぐ聞きましょう。
https://prog-8.com/courses/python

#スクレイピング実践編に続く！！！！！
データを取ってきてスプレッドシートに書き込めたらゴールです。
（LGTM頂けたら励みになります。。）
マイグレーション

# テーブル作成
```sh:sh
# マイグレーションファイルの作成
bin/cake bake migration CreateUsers

# マイグレーションファイルの実行
bin/cake migrations migrate

# マイグレーションファイルの実行取消
bin/cake migrations rollback

```

# データ入力

```
# シードファイル作成
bin/cake bake seed Users

# シードファイルの実行
bin/cake migrations CreateUsers
```
Dockerコンテナ内でmysqlコマンドが使えなかったときの話

<h1>はじめに</h1>
Docker環境で開発中に、コンテナ内で「rails g model ~」や「rails db:migrate」により、テーブルを作成したので、作成したテーブルなどを確認するために、MySQLを起動させようとしたところ、以下のとおり、起動しませんでした。

```
$ mysql -u root -p
bash: mysql: command not found
```

あれ、MySQL入っているはずなのに、なぜだろう？

<h1>開発環境</h1>
・Ruby on Rails 6.1.4
・MySQL 8.0.25
・Docker 20.10.7
・docker-compose 1.29.2

<h1>原因と対応</h1>
私はrailsコマンドを使用するために、Dockerをバックグラウンドで起動させた後、次のコマンドによりコンテナに入って作業をしていました。

```
$ docker-compose exec web bash
```

そうです、webコンテナ（＝railsのコンテナ）の中で、mysqlコマンドを実行しようとしていたのです。

気を取り直して、webコンテナからexitし、以下のコマンドを実行します。

```
$ docker-compose exec db bash
```

これでdbコンテナ（MySQLのコンテナ）に入ることができ、無事、mysqlコマンドが実行できるようになりました。

もちろん、コンテナに入らずに直接、次のコマンドを入力してもOKです。
（これなら、コマンドにコンテナ名が入っているので、最初から気がついていたような気もしますが…）

```
$ docker-compose exec db mysql -u root -p
```

<h1>おわりに</h1>
原因がわかれば何とも単純な話ですが、エラーが出るとあれこれ調べて、よくわからない方向へ行ってしまい、いつの間にか時間ばかりが過ぎているというのは、初心者あるあるかと思います。
同じことをやらかしてしまった人が、この記事にたどり着いてくれれば、嬉しく思います。
[Rails]N+1問題を対処する

N+１問題って聞いたことはありますか？

N＋１問題はかなり怖い問題で、ぼくはポートフォリオ作成のときに、N+１問題に直面しました。

そのときに、調べた内容をぼくの理解の範囲で、アウトプットしていきます。

#N+１問題とは

そもそもN+１問題とはどんな問題のことをいうのでしょうか？

`データベースからデータベースを取り出すときに、大量のSQLが発行されて、動作が重くなる問題`のことです。

たとえば、usersテーブルとpostsテーブルで、下記のようなアソシエーションがあったとします。

```models/user.rb
class User < ActiveRecord::Base
  has_many :posts
end
```

```models/post.rb
class Post < ActiveRecord::Base
  belongs_to :user
end
```

で、投稿の一覧を表示していきます。
Postモデルから全データ取得して、それをeach文で回していきます。

```controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end
end
```

```erb:views/posts/index.html.erb
<%= @posts.each do |post| %>
  <%= post.content %>
  <%= post.user.name %>
<% end %>
```

これで、このビューにアクセスし、ログを確認してみましょう。

```sql:
User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
:
```

このようにPostの数だけ、post.userを探すため、SQLが大量に発行されます。

勉強段階の開発環境等では、データ数もそこまで多くないので、そこまで問題になりませんが、実際に運用していくとなると、投稿数も増えていくことが想定されます。

データ数が、1000になると考えると、毎回1000件のデータ全てにSQLを発行していたら、遅くなるのは明白ですね。

なにも対策をとらないとデータ量が増えるにつれて、動作が遅くなる問題が、N+1問題です。

#対策

では、N+１問題がどんなものか分かったところで、対策方法をみていきましょう！

`includesメソッド`を使っていきます。

`includesメソッド`は、`アソシエーションの関連付けを事前に取得してくれます。

事前に取得ってよくわかりませんよね。
例をあげて考えてみましょう。

基本構文はこうです。

```rb:基本構文
# 関連名はアソシエーションの関連先
モデル名.inculudes(:関連名)
```

```controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    # .allは省略できます
    @posts = Post.includes(:user)
  end
end
```

これで、ログを見てみましょう！

```sql:
User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (?, ?, ?)  [["id", 1], ["id", 2], ["id", 4]]
```

このように、post.userに関するSQLは１行で完了しています。

つまりどういうことかというと、
`Post.allの場合`は、Postのデータを全て取得して、ビューのeach文で表示するときに、postのuser_idとどのユーザーが一致するか全てのユーザーの中から検証していました。

しかし、`Post.includes(:user)の場合`は、postsテーブルからデータを取得するときに、関連するusersテーブルのデータも取得しているので、each文で表示する時に、その都度SQLを発行する必要はなくなったのです。

#まとめ

N+1問題の対策としては、`includesメソッド`を使う！

ポートフォリオ作成時に、N+１問題のことはなにも考えずにコーディングしていて、動作確認のときに「あれ？なんか重たいな」となったのが気づいたきっかけでした。

早いうちにN+１問題に触れられてよかったです。

ただ今回は自分なりに調べてみての結論で、他の記事の中では、`includesメソッド`を使う方法が推奨されていなかったりした記事がありました。

あとしょうがないのかもしれませんが、`includesメソッド`を使うことで、SQLの発行は改善されたのですが、コードの可読性がかなり下がるなと思いました。

まだまだ理解しきれていないことも多いので、これからもっとデータベースの知識を深めていきたいと思います！
AngularでAzure App Configurationの機能フラグを使ってみた


実際に使ってみたので備忘録として残します。

## 環境

Angular v10です

## Azure App Configurationの作成

- 価格：Freeで問題なし

### アクセス情報を取得する

App Configurationを作成したら  
[アクセスキー]→[接続文字列]をコピーしておく。(後で使う)

## 機能フラグの作成

[機能マネージャー]→[追加]からキーを追加する  
機能フラグ名を入力して、他は既定値でOK。  
「FeatureShowText」という名前の機能フラグを追加してみる  
追加すると[機能マネージャー]に列が追加されます。  
列には[有効]の列があるので、ここをクリックすることで機能フラグのON/OFFを切り替えれます。

## Angularアプリ内で機能フラグを使用する

- パッケージをinstallする

```JSON
"@azure/app-configuration": "^1.3.0"
"@azure/identity": "^1.5.0"
```

- 機能フラグを取得する処理をかく
  - 接続文字列を明記(本番環境などにあげる場合はKeyVaultなどから参照する構成にしよう)

```typescript
async getFeatureFlag() {
    const conn = 'コピーした接続文字列を入力'; // 接続文字列 secret
    const client = new AppConfigurationClient(conn);

    const val = await client.getConfigurationSetting({ key: '.appconfig.featureflag/FeatureShowText' }); // .appconfig.featureflag/{先程追加した機能フラグ名}
    return JSON.parse(val.value).enabled;
  }
```

- 参照した機能フラグを保管するfeatureFlagを定義する

```typescript
 featureFlag = this.getFeatureFlag();
```

- 実際のソース  

👇こんな感じ

```html:app.component.html
<div>
  <span *ngIf="(featureFlag | async)">
    機能フラグはいまONになっています。
    <button>新機能のボタン</button>
  </span>
  <span *ngIf="!(featureFlag | async)">
    機能フラグはいまOFFになっています。
  </span>
</div>
```

```typescript:app.component.ts
import { Component } from '@angular/core';
import { AppConfigurationClient } from '@azure/app-configuration';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-test';

  featureFlag = this.getFeatureFlag();

  // tslint:disable-next-line:typedef
  async getFeatureFlag() {
    const conn = 'コピーした接続文字列を入力'; // 接続文字列 secret
    const client = new AppConfigurationClient(conn);

    const val = await client.getConfigurationSetting({ key: '.appconfig.featureflag/FeatureShowText' }); // .appconfig.featureflag/{先程追加した機能フラグ名}
    return JSON.parse(val.value).enabled;
  }

}

```

### 機能フラグをON/OFFして試してみよう

- ng serve -oで起動
- 実際に作成した機能フラグを有効/無効にして動きを見てみる

## まとめ

機能フラグを使用することで
ロールバックや即時バグ修正のリスク回避を行うことができるので使える場面は多そう。