OmniAICreator/Qiita-1.07M huggingface dataset:
TensorFlow2でのモデルファイルの保存と読み込み


Tensorflow2 (とkeras) でのmodelファイルの形式・保存方法が色々あってむずかしいのでメモ

## modelファイルの種類
- .h5: KerasでSequentialモデル全体を一括保存したファイル
   - モデルの構造、重み、訓練の設定、optimizerの情報がHDF5ファイルにまとまってる
- SavedModel (ディレクトリ): TensorFlowのSavedModel形式
   - 重みを含むチェックポイントファイルとモデルのグラフ構造を持ったprotoファイルが一つのディレクトリに作られる
  

開発時は基本的にSavedModel形式で保存しておき、デプロイする環境に応じてフォーマットを変えるのが一般的っぽい？
TensorFlow ServingにはこのSavedModelを使うらしい

## 1. Kerasで訓練済のSequential modelをsave/load

[Save and serialize models with Keras](https://www.tensorflow.org/guide/keras/save_and_serialize#weights_only_saving_in_savedmodel_format) の要約:

### save

#### モデル全体を単一ファイルに保存

```python
model.save('path_to_my_model.h5')
```

HDF5形式でモデルの構造、重み、訓練の設定、optimizerの情報が1つのファイルに保存される


#### SavedModel形式で保存

```python

model.save('path_to_saved_model', save_format='tf')
```

`path_to_saved_model` ディレクトリに重みを含むチェックポイントファイルとモデルのグラフのpbファイルが保存される

SavedModel保存についてはより低レベルで高機能な `tf.saved_model` を使う方法もある:

```python
tf.saved_model.save(my_trained_model, "mymodel/1/")
```


#### モデルの構造や重みだけ保存する

モデルの構造だけ欲しい場合 `model.get_config()` で学習済みモデルの構造だけ取得し、 
`keras.Model.from_config(config)` で新しいモデルを作って保存する。詳細は公式ガイドの[Architecture only saving](https://www.tensorflow.org/guide/keras/save_and_serialize#architecture-only_saving)など参照

### load

#### h5ファイルからモデルをロード

```python
new_model = keras.models.load_model('path_to_my_model.h5')
```

#### SavedModelからモデルをロード

```python
new_model = tf.keras.models.load_model("mymodel/1/")
```

自動で判別してくれるみたいなのでh5ファイル or SavedModelディレクトリのパスを渡すだけ

## 2. Kerasで訓練の過程でSequential modelをsave/load

[Save and load models](https://www.tensorflow.org/tutorials/keras/save_and_load)

### checkpointを使った重みの保存

checkpoint機能を使うことで訓練途中の重みを随時保存できる。
model.fitの際にcallbackを指定しておくことで、訓練中に更新される重みがファイルに保存される

```python

cp_callback = tf.keras.callbacks.ModelCheckpoint(
    filepath='training_1/cp.ckpt', 
    save_weights_only=True)

model.fit(train_images, 
          train_labels,  
          epochs=10,
          validation_data=(test_images,test_labels),
          callbacks=[cp_callback])
```

詳細は [Checkpoint callback usage](https://www.tensorflow.org/tutorials/keras/save_and_load#checkpoint_callback_usage) 参照


#### 明示的に保存

例えば訓練前の最初の重みも保存する場合

```python

model = create_model()
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
model.save_weights(checkpoint_path.format(epoch=0))
```

**補足**

> Note: the default tensorflow format only saves the 5 most recent checkpoints.

最新5つのチェックポイントだけ保存されるらしい


### checkpointファイルから重みをロード

1. 未訓練の新しいmodelを作る
2. `model.load_weights(checkpoint_path) で保存したチェックポイントファイルから重みをロード

当然ながら保存した時とネットワークの構造が同じでないとloadできない
CloudFormationで CodeCommit リポジトリに最初のコミットを作成

https://aws.amazon.com/jp/about-aws/whats-new/2019/05/aws-codecommit-now-supports-the-ability-to-make-an-initial-commit/

CloudFormation スタックに AWS CodeCommit リポジトリを作成する際に最初のコミットを作成できる

- README ファイルやサンプルコードなど、新しく作成した CodeCommit リポジトリに追加したいコンテンツを含めた ZIP ファイルを作成できるようになった。

AWS::CodeCommit::Repository

```
{
  "Type" : "AWS::CodeCommit::Repository",
  "Properties" : {
      "Code" : Code,
      "RepositoryDescription" : String,
      "RepositoryName" : String,
      "Tags" : [ Tag, ... ],
      "Triggers" : [ RepositoryTrigger, ... ]
    }
}
```
【基本】実装速度を上げたい初級エンジニアが考えた工夫

#1.記事を作成した理由
・より早くプログラム実装をするために、デバック方法などの具体的な技術以前に、
「プログラミングをするときの考え方」
　を言語化できたので、他の人にも役立つかと思い、本記事を作成した。　

#2.参考図書
以下の図書を元に本記事を作成
平山尚 著、株式会社秀和システム、「プログラムはこうして作られる」、2013年10月

#3.考え方
###A)プログラムとは
　プログラムという単語の意味は、「何をどういう順でやるかが書かれたもの」である。
　例：演奏会の進行表、教育計画、etc...

###B)ソースコードの理解の仕方
　ソースコードを理解しようとしたら、具体的な数値を入れて動かしてみると良い。
　九九無しに乗算を理解することは難しいし、30°、60°、直角という具体例無しに角度や三角関数を理解することは困難である。「こうやったらこうなった」をいくつか見ることは、遠回りではない。

###C)メモリの０始まりの理由
　メモリは０始まりなのは、便利だからである。
　例えば、世紀表記は1世紀から始まっているおかげで、19xx年は20世紀になっているなど、19+1という計算が必要。
　基準点からの離れ具合を計算する際は、0始まりが便利である。
　１始まりは、物を数えるときに便利だからである。
　例えばりんごの数をカウントする際は、１個以上目の前にある事が前提になっているからである。
###D)デバッグのしかた
　プログラムは書かれた通りにしか動作しない。意図しない動作をしている場合は、大別して２つのアプローチがある。
　1.「現状のプログラム」では、１行１行動作を確認して、どこで意図しない動作をしているかを調査。
　2.「現状の結果」から、「現状のプログラム」ではどのような機能が「意図されず」実装されているか、可能性を考える。いわゆる「推理」である。

　a)動かしてみて、理想と現実がどう違うのかを把握する
　b)このような現実になっているのが何故なのかを考える
　c)理想と現実を一致させるために必要なものは何かを考える

###E) ソースコードの拡張性
　「繰り返し処理」などを導入して、プログラムの行数を減らすと、改造しやすくなる。

###F) 「注釈」の記載基準 
　ソースコード中に、注釈は無い方が良い。でも、時間がたってからわかるかどうか、などを考慮すると、書いた方が良い場合もある。読み手の個性やケースバイケースで書くかどうかを決めた方が良い。
　目標「わかりやすくするために、短くする」
　→目標「短くするために、繰り返し処理を１つにする」
　->目標「処理を分かりやすくするために、コメントを追加する」
　->最後の「コメントを追加する」が、初期目標に一致しているかを常にチェックする。
　　「コメントを追加する」ことで「短く」はならなくても「分かりやすく」なれば初期目標を達成していることになる。
　正解は１つでは無い。記憶力が良い人にとっては長いコードでも問題ないだろうし、頭が良い人にとってはややこしくても短い方が良いと考えるだろう。
　
　「単純だが長い」と「複雑だが短い」のバランスをとっていく事は永遠の課題。

###G) 部分プログラミング
　「部分プログラミング」を導入し、機能を小分けにして書いていくと、分かりやすい。
　改造もしやすい。入力と出力の理解に注力できるためである。

###H) 処理の細分化
　あるプログラムを書く際に、処理を子処理、孫処理とブレイクダウンして、クラス化・関数かした方が、チェックしやすい。
　 

#終わりに
・自身の開発速度向上のために、気になった点をメモした。
セル範囲を画像として保存するExcelマクロ

#### これは
選択したセル範囲をPNG画像として保存するだけの、ちょっとしたExcelマクロです。

#### コード
```vb
'参照設定:
' Microsoft Scripting Runtime
' Windows Script Host Object Model

Function RangeToPng(r As Range, Optional fn As String = vbNullString)
    With New FileSystemObject
        If fn = vbNullString Then fn = .BuildPath(DesktopFolder, Replace(.GetTempName, "tmp", "png"))
    End With
    With New Excel.Application
        With .Workbooks.Add
            With .Worksheets(1).ChartObjects.Add(0, 0, r.Width, r.Height).Chart
                r.CopyPicture
                .Paste
                .Export fn, "png"
            End With
            .Close False
        End With
        .Quit
    End With
End Function

Private Function DesktopFolder()
    With New WshShell
        DesktopFolder = .SpecialFolders("Desktop")
    End With
End Function
```
#### 使用例
```vb
Sub セル範囲を画像にする()
    Dim fn As String
    RangeToPng ActiveWindow.RangeSelection, fn
    MsgBox fn
End Sub
```
GuardDuty? Inspector? Macie?

## 参考
https://cloud-textbook.com/8/#guardduty

### GuardDuty
ログを分析し、異常と思われる挙動がある場合警告を行う仕組み。例えば以下のような警告例がある。2018/1 時点、EC2 と IAM のみが警告対象。 

### Inspector
EC2 の脆弱性自動チェックサービス。対象範囲はネットワーク・OS・ミドルウェアで、あらかじめ AWS が CVE などを元に準備したチェック項目に従い、不正アクセスができたりしないかなどを実際にチェックする。EC2 に専用のエージェントをインストールする必要あり。対象 OS は Windows または Linux 系 OS。EC2 以外に対して脆弱性チェックを行うことはできない。自作の Web アプリケーションの脆弱性チェックをしてくれるわけではない。

### Macie
S3 や CloudWatch にあるデータについて、不審と思われるアクションが行われた場合に通知する仕組み。 「不審」とは、例えば
- 通常とは異なる IP アドレスから大量のダウンロードがあった
- 通常機密コンテンツにアクセスしないユーザーが大量のソースコードをダウンロードした
など。なお、できることは通知のみで、遮断・保護はできない (検知したら Lambda 起動はできるので即時に権限変更やユーザ削除などはできなくはないが、実質的には難しいのでは?)。
sealed classでのParcelizeの使い方と動く仕組み

以下のようにすることで実装してくことができます。
ポイントはsealed class自体にはParcelizeをつけないで、サブクラスで実装させることです。

```kotlin
    sealed class Sealed(open val sealedClassProperty: String) : Parcelable {
        @Parcelize
        data class SubDataClass(val subClassProperty: String, override val sealedClassProperty: String) : Sealed(sealedClassProperty)

        @Parcelize
        class SubClass(val subClassProperty: String, override val sealedClassProperty: String) : Sealed(sealedClassProperty)

        @Parcelize
        object SubObject : Sealed("test") {
            val objStr: String = "test"
        }
    }
}
```

確認コード

```kotlin
        val p = Parcel.obtain()
        val bundle = Bundle()
        val subDataClass = Sealed.SubDataClass("a", "b")
        bundle.putParcelable("SubDataClass", subDataClass)
        val subClass = Sealed.SubClass("a", "b")
        bundle.putParcelable("SubClass", subClass)
        val subObject = Sealed.SubObject
        bundle.putParcelable("SubObject", subObject)
        p.writeBundle(bundle)

        p.setDataPosition(0)
        val restoredBundle = p.readBundle(Sealed::class.java.classLoader)
        println(restoredBundle!!.getParcelable<Sealed>("SubDataClass"))
        println(restoredBundle.getParcelable<Sealed>("SubClass"))
        println(restoredBundle.getParcelable<Sealed>("SubObject"))

        p.recycle()
    }
```

実行結果

```
I/System.out: SubDataClass(subClassProperty=a, sealedClassProperty=b) 
I/System.out: com.github.takahirom.sealedparcelable.MainActivity$Sealed$SubClass@3a66f1d 
I/System.out: com.github.takahirom.sealedparcelable.MainActivity$Sealed$SubObject@1265592
```

# CREATORを指定しなくてなぜうまく動くのか？
デコンパイルしてみて見るとParcelizeはCREATORなどを自動生成してくれるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/42aa60f4-d071-564f-2b8e-4fd21c7922b4.png)

しかし以下のコードでは親クラスでgetParcelableを呼ぶだけで、サブクラスのCREATORを指定していません。

```kotlin
println(restoredBundle!!.getParcelable<Sealed>("SubDataClass"))
```

なぜCREATORを指定しなくてなぜうまく動くのでしょうか？

Parcelは以下のようなバイト列を持っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/8c215779-0761-5c8e-bb28-912a2d3f30cf.png)

以下のようにすることで見ることができます。

```kotlin
        p.setDataPosition(0)
        File(dataDir, "parcelable").outputStream().write(p.createByteArray())
```


まずここから4というのを取り出してこれがParcelableだということを取得し、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/f19cbbc9-30f8-eadc-804e-1b077fedd10c.png" width=500 />
またその後にクラス名を取得し、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/ea617490-c829-b81a-067c-ae42f7c52258.png" width=500 />
そこからCREATORクラスを取得します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/c9efc77d-35ca-e7e8-3001-ce464bbdf547.png" width=500 />

このように**Parcelの中に保存するときにクラス名が入るため**、取得するときにシールドクラスの親クラスを指定していても、うまくCREATORを使ってくれて動くようです。
Amazon CloudSearch とは

## 参考
https://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/what-is-cloudsearch.html

### Amazon CloudSearch とは
- Amazon CloudSearch はクラウドにおける完全マネージド型サービスであり、ウェブサイトまたはアプリケーション向けの検索ソリューションを容易に設定、管理、拡張縮小できます。

- Amazon CloudSearch を使用して、ウェブページ、ドキュメントファイル、フォーラムの投稿、製品情報など大規模なデータコレクションを検索できます。検索機能を迅速に追加できます。検索の高度な知識を習得したり、ハードウェアの準備、設定、およびメンテナンスについて考える必要はありません。データやトラフィックの変動に伴い、Amazon CloudSearch はニーズに合わせてシームレスにスケーリングします。
curl で Cloud Firestore のデータを取得

Cloud Firestore の RestAPI を使ってデータを取得します。

## project-aaa の cities の t0921 を取得 ##

```bash
export GOOGLE_APPLICATION_CREDENTIALS="***.json"

ACCESS_TOKEN=`gcloud auth application-default print-access-token`
#
project_id=`jq .project_id $GOOGLE_APPLICATION_CREDENTIALS | sed "s/\"//g"`
echo $project_id
URL='https://firestore.googleapis.com/v1/projects/'$project_id'/databases/(default)/documents/cities'
#
#
curl -H "Authorization: Bearer $ACCESS_TOKEN" $URL"/t0921"
```

実行結果

```text
{
  "name": "projects/project-jan25-2020/databases/(default)/documents/cities/t0921",
  "fields": {
    "population": {
      "integerValue": "81235"
    },
    "name": {
      "stringValue": "宇都宮"
    },
    "date_mod": {
      "stringValue": "1950-9-24"
    }
  },
  "createTime": "2020-01-25T06:14:38.983529Z",
  "updateTime": "2020-01-25T06:23:16.019805Z"
}
```

Httpie の場合

```bash:get_single.sh
#
export GOOGLE_APPLICATION_CREDENTIALS="***.json"

ACCESS_TOKEN=`gcloud auth application-default print-access-token`
#
project_id=`jq .project_id $GOOGLE_APPLICATION_CREDENTIALS | sed "s/\"//g"`
echo $project_id
#
collection="cities"

URL_BASE='https://firestore.googleapis.com/v1/projects/'$project_id'/databases/(default)/documents'
URL=${URL_BASE}'/'${collection}
#
echo $URL
#
http GET $URL"/t0921" "Authorization: Bearer $ACCESS_TOKEN" 
```

## Collection 内の全てのデータを取得 ##

```bash
export GOOGLE_APPLICATION_CREDENTIALS="***.json"

ACCESS_TOKEN=`gcloud auth application-default print-access-token`
#
project_id=`jq .project_id $GOOGLE_APPLICATION_CREDENTIALS | sed "s/\"//g"`
echo $project_id
URL='https://firestore.googleapis.com/v1/projects/'$project_id'/databases/(default)/documents/cities'
#
curl -H "Authorization: Bearer $ACCESS_TOKEN" $URL
```

Httpie の場合

```bash:get_all.sh
#
export GOOGLE_APPLICATION_CREDENTIALS="***.json"

ACCESS_TOKEN=`gcloud auth application-default print-access-token`
#
project_id=`jq .project_id $GOOGLE_APPLICATION_CREDENTIALS | sed "s/\"//g"`
echo $project_id
#
collection="cities"

URL_BASE='https://firestore.googleapis.com/v1/projects/'$project_id'/databases/(default)/documents'
URL=${URL_BASE}'/'${collection}
#
echo $URL
#
http GET $URL "Authorization: Bearer $ACCESS_TOKEN"
```

## 参考 ##

サービスアカウントキー　(GOOGLE_APPLICATION_CREDENTIALS)　の取得方法
　（サービスアカウントを作成しておく必要があります。）

```bash
gcloud iam service-accounts keys create example_2022.json \
 --iam-account project-2022@appspot.gserviceaccount.com
動画ファイルをndarrayに変換

# 動画ファイルをndarrayに変換

```python:readClip
import cv2
import numpy as np

def readClip(filepass):#ファイルパスを取得しndarrayを返す
    cap = cv2.VideoCapture(filepass)
    print(cap.isOpened())#読み込めたかどうか
    ret,frame = cap.read()
    array = np.reshape(frame,(1,int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),3))
    while True: 
        ret, frame = cap.read()#1フレーム読み込み
        if ret == False :#フレームが読み込めなかったら出る
            break
        frame = np.reshape(frame,(1,int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),3))       
        array = np.append(array,frame,axis=0)
    cap.release()
    return array
b_array = readClip("./clip/battle.mp4")
print(np.shape(b_array))
o_array = readClip("./clip/ordinary.mp4")
print(np.shape(o_array))
```

# 注意
めっちゃ時間かかる
コード内で環境名 (dev,stg,prod) を使用しないことのすすめ

サービスを運用する場合、開発、運用で複数の環境でサーバーを動かしている場合がよくあると思います。このとき、パラメータ設定の口が柔軟でないと設定値の変更がしにくかったり、サーバーのビルドを環境毎にしなければならなず(特に docker 使っている場合)、デプロイに時間がかかったりします。
そうならないために環境名 (dev,stg,prod) を使用して動作変更するのをやめることをおすすめします。記事内では以下のような環境があると想定し、Javascript (Node.js) でいくつかの例を示します。

- 開発時ローカル PC
- ステージングサーバー環境
- 本番サーバー環境

# 変数を環境名に依存させるのをやめよう
サーバーでエラーが起きたときに管理者にメールを送るというケースで送り先を分ける場合で説明します。

##悪い例（コード内で環境ごとのメールアドレスを決めている）
コード内で設定されているアドレスにしか送ることができません、送信するメールアドレスが変更になったときはコードの変更が必要。

```js
// process.env.NODE_ENV に環境名が指定されている
function sendErrorMail() {
  let email = 'default@example.com';
  switch(process.env.NODE_ENV) {
  case 'development':
    email = 'dev@admin.com';
    break;
  case 'staging':
    email = 'stg@admin.com';
    break;
  case 'production':
    email = 'prod@admin.com';
    break;
  default:
    break;
  }
  // sendMail は email アドレスとメール本文を指定してメールを送る関数
  sendMail(email, 'Server Error Occurred');
} 
```

##良い例（環境変数としてメールアドレス自体を指定している）
メールアドレスが変更になったときでも環境変数の指定を変更するだけで送信先が変更できる

```js
// process.env.ADMIN_EMAIL_ON_ERROR にエラー時のメール送り先が指定されている
function sendErrorMail() {
  // sendMail は email アドレスとメール本文を指定してメールを送る関数
  sendMail(process.env.ADMIN_EMAIL_ON_ERROR, 'Server Error Occurred');
} 
```

# 動作を環境名に依存させるのをやめよう
次も似た例ですが、ログのレベル設定を例に説明します。 ```logWarn``` という警告ログを出力する関数があるとします。開発環境だったら debug ログを出す、というパターンはよくあると思いますが、一つの環境変数としてログレベルを設定すると柔軟です。

悪い例（コード内で環境名でレベルを決めている）

```js
// process.env.NODE_ENV に環境名が指定されている
function logWarn(message) {
  if (process.env.NODE_ENV == 'development') {
    console.warn(message);
  }
}
```

良い例（ログレベルを環境変数として設定する）

```js
const LogLevel = {
  DEBUG: 0,
  INFO: 1,
  WARN: 2,
  ERROR: 3,
  TRACE: 4,
};

// process.env.LOG_LEVEL にログレベルが設定されている
function logWarn(message) {
  if (process.env.LOG_LEVEL <= LogLevel.WARN) {
    console.warn(message);
  }
}
```

# 最後に
この話は主流にありつつある(すでに主流？) Docker でのサーバーデプロイの背景が大きいです。Docker image を build して デプロイしてという流れで運用している場合、ちょっとした動作の変更によって Docker image の build し直ししなければならないとか、環境毎に image を build し直さなければけ無いとなると、build 時間はわりとかかるケース（色々なケースがありますが、数分から10分は最低でもかかると思います）が多いので、build し直ししなくてもいいように（実行時に環境変数として設定すればいいだけにするために）設定類は個別の設定毎に外出ししていくと便利だと考えています。
CFn NoEcho で parameter をマスク

## 参考
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html

### NoEcho
パラメータ値をマスクして、コンソール、コマンドラインツール、または API に表示されないようにするかどうか。NoEcho 属性を true に設定すると、CloudFormation は、スタックまたはスタックイベントを記述するすべての呼び出しに対して、アスタリスク (*****) としてマスクされたパラメータ値を返します。

#### 重要
AWS CloudFormation テンプレートに直接機密情報を埋め込むよりも、以下のいずれかを実行するように強くお勧めします。

- **NoEcho プロパティを使用してパラメーター値を難読化**  することにより、スタックを作成または更新するたびに入力パラメーターを使用して情報を渡す。

- スタックテンプレートで動的なパラメータを使用して、Systems Manager パラメーターストアや Secrets Manager など、CloudFormation の外部で保存および管理される機密情報を参照する。
flutter用の参考サイトまとめ

## 概要
flutter用の参考サイトのURLをまとめていきます！

## サイトURL

### マテリアデザイン

- https://material.io/
    - マテリアルデザインの公式サイト

### Flutterデザイン関連

- http://flutterexamples.com/
    - flutterのレイアウトサンプルをまとめてくれています。

- https://stackoverflow.com/questions/43348254/automatically-scroll-multiline-textformfield-when-it-extends-the-maxlines-attrib/48712128
    - TextField(TextFormField)のスクロール化が書かれている

- https://medium.com/flutter-jp/icon-935d637d2da0
    - 環境毎にアイコンを作成する方法
### Android
- https://github.com/hemanthrajv/flutter_home_screen_widget_example
    - AndroidでApp Widgetのサンプルソース
- https://flutter.dev/docs/deployment/android
    - Flutter公式のAndroidリリース手順

### iOS
- https://flutter.dev/docs/deployment/ios
    - Flutter公式のiOSのリリース手順
        - https://i-app-tec.com/ios/app-release.html
        - https://docs.repro.io/ja/dev/sdk/push-notification/setup-ios.html#apns-ios
            - iOSのリリース手順の参考サイト

### Google Fonts
- https://github.com/google/fonts
AWS OpsWorks スタックのスタックコマンドの実行

## 参考
https://docs.aws.amazon.com/ja_jp/opsworks/latest/userguide/workingstacks-commands.html

### Linux ベースのスタックでのみ、任意のスタックに対して以下のスタックコマンドを実行できます。

#### Install Dependencies
インスタンスのパッケージをインストールします。Chef 12 以降、このコマンドは使用できなくなります。

#### Update Dependencies
(Linux のみ。Chef 12 以降、このコマンドは使用できなくなります。) 定期的なオペレーティングシステム更新とパッケージ更新をインストールします。詳細はインスタンスのオペレーティングシステムによって異なります。詳細については、「セキュリティ更新の管理」を参照してください。
Vue.jsをサブディレクトリで運用する時の注意

ちょっと調べることがあったのでメモ書き

`vue.config.js` というファイルを作りその中で

``` js
module.exports = {
  publicPath: '/subdirectory'
}
```

と`publicPath`を設定するとbuild時にうまく書き出してくれるようです。
また画像のパスも相対パスにするなどで間違いのないようにしましょう。
PowerAutomateでOutlookの予定表をエクセルに抜き出す(もうちょっと改良したい)

手順がかなりイモいのでもうちょっと何とかしたい。

#1.OneDriveにエクセルファイルを作る
「予定表エクスポート.xlsx」とかを作る。
#2.テーブルの作成フローを作成
出力するフローの「表に行を追加」を実行するにはテーブルが必要なので先に作っておいてやる。
![テーブルの作成フローを作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65842/2d922420-12d7-75e0-158c-33b3d01c83ce.png)
#3.出力するフローを作成
開始と終了を指定して手動でトリガーする方式。
トリガーの入力は日付だけなので
　開始時刻には「T00:00:00Z」(当日の0:00)を、
　終了時刻には「addDays(triggerBody()['date_1'],1,'yyyy-MM-ddTHH:mm:ssZ')」(入力された終了日の翌日の0:00)
みたいにする。
foreach的なフローは「イベントの取得(V3)」で「value」を選ぶと勝手にforeachになる。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65842/632b0466-345b-2ae9-7cb6-f01c8f78fdc6.png)
#こうしたいメモ
- 「ファイルの保存ダイアログ」的な感じに出力を選べるようにして、フローを1つにまとめたい。
- 今回は「イベントの取得(V3)」を使ったけど「イベントの取得(V4)」ならfilterが使えるのでもっとシンプルになりそうなんだけど、filterの指定方法がよくわからなかったので断念。
- 本文がHTML形式で出るのでせめて<body>タグだけ抜き出したい。できたらプレーンテキストにしたい。
VoIP Push着信時にSIPサーバーから応答が返らない場合の対応

iOS13 で PushKit(VoIP Push)の縛りがきつくなった件、みなさんお悩みですよね。
　参考：[VoIP Push (PushKit) は着信通知専用になりました・・・](https://qiita.com/sunskysoft/items/34665541d9bec438ee36)
　
VoIPアプリでは、プッシュ着信を受けた後に、セッションを張って通話を開始します。
特にSIP電話の場合、これまでは以下のような流れでした。

```
①　プッシュ受ける（pushRegistry）
②　SIPサーバーへ登録（REGISTER）
③　SIPサーバーからOK
④　SIPサーバーから着信（INVITE）
⑤　CallKitに着信を通知（CallKit:reportNewIncomingCall）
⑥　CallKitの着信画面表示
⑦　着信応答（CallKit:provider CXAnswerAction）
⑧　SIPサーバーへ応答（200 OK）
⑨　通話画面表示
```
しかし、xcode11 & iOS13 からは、VoIP Push を受信したらすぐにCallKitに通知（[reportNewIncomingCall](https://developer.apple.com/documentation/callkit/cxprovider/1930694-reportnewincomingcall)）することが義務付けられました。そのため、処理は以下のように変わることになります。

```
①　プッシュ受ける（pushRegistry）
②　CallKitに着信を通知（CallKit:reportNewIncomingCall）
③　CallKitの着信画面表示
④　SIPサーバーへ登録（REGISTER）
⑤　SIPサーバーからOK
⑥　SIPサーバーから着信（INVITE）
⑦　着信応答（CallKit:provider CXAnswerAction）
⑧　SIPサーバーへ応答（200 OK）
⑨　通話画面表示
```
##問題点
問題は③〜⑤です。
SIPサーバーとのやりとりが素早く終わればほとんど問題はないかもしれません。
しかし、SIPサーバーとの間のネットワークに問題(遅い、ロストしやすい、不通など)があった場合、標準的には REGISTER のタイムアウトだけでも３２秒程度かかる可能性があります。
結果、ユーザーが操作する時間が十分にあるため、以下のような流れも考えられます。

```
①　プッシュ受ける（pushRegistry）
②　着信画面表示（CallKit:reportNewIncomingCall）
③　SIPサーバーへ登録（REGISTER）
④　着信応答（CallKit:provider CXAnswerAction）
⑤　通話画面表示
⑥　SIPサーバーからOK
⑦　SIPサーバーから着信（INVITE）
⑧　SIPサーバーへ応答（200 OK）
```
つまり、通話画面となってから実際に会話できるまでの⑥〜⑧は、通話画面なのに無音の状態となってしまいます。
最終的にネットワーク不通で⑥が返ってこなかった場合、ユーザーから見ると
　「着信に応答操作してもなぜか会話できずに切れてしまった」
という体験となってしまいます。
　
その他にもいろいろなパターンが考えられ、世のVoIP(SIP)電話アプリを作っている方はりんごさんに怒り心頭でしょう。。。

##SIPサーバーから応答が返らない場合の対応
色々と課題と対応はありますが、とりあえず一つ、「通話画面なのに無音の状態」の対応を見つけました。
>[Responding to VoIP Notifications from PushKit](https://developer.apple.com/documentation/pushkit/responding_to_voip_notifications_from_pushkit)
>　→Respond to Call Hang Ups and Failures

以前からこのドキュメントがあったのかどうか分かりませんが、ユーザーが応答した際に呼ばれる [provider(CXAnswerCallAction)](https://developer.apple.com/documentation/callkit/cxproviderdelegate/1648270-provider) で、SIPのコネクションが確立するまで（⑧を受け取るまで） fulfill() を返さないことだそうです。
これによって、CallKitの通話画面の表示は以下のようになり、ユーザーに接続中だと知らせることができるようになります。
![IMG_0051.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177438/d234e1ce-355f-9dae-e12d-217597bdc051.png)

**なるほど！**　~~（って、ユーザー気づくかこれ？？）~~
　
しかし、これはロック画面からの応答の際の話で、ロック解除中（操作中）に着信が入った際は、応答すると電話アプリが開きます。したがって、上記対応を入れつつ、アプリ画面でも接続中であることを知らせる画面を別途用意する必要があります・・・
　
その他、相手が先に切ったり、接続確立できなかった場合は [reportCall(with:endedAt:reason:)](https://developer.apple.com/documentation/callkit/cxprovider/1930701-reportcall) で失敗の理由をシステムに伝えるように書かれてますので、それもしっかり対応しましょう。

##最後に
上記で紹介した対応は、iOS13 による変化点対策の一部です。
準正常系、異常系の判断が大きく変わることになるので、修正は注意して行わなければならないです。
その他にも、チャットなど通話以外の機能でVoIP Pushを利用しているケースでは、通常のAPNs Pushに置き換えたりと大きな修正を余儀なくされているベンダーも多いことでしょう。
　
最近のモバイルアプリはセキュリティの観点から大きすぎる仕様変更が多いです。
開発者としては予想外の工数・費用がかかるため本当にやめて欲しいです。
セキュリティは大事ですが、影響の小さな仕様を考えて欲しいものです。。。
AWS OpsWorks Stacks のオペレーティングシステム

## 参考
https://docs.aws.amazon.com/ja_jp/opsworks/latest/userguide/workinginstances-os.html

- スタックのインスタンスは、Linux または Windows を実行できます。

- Linux インスタンスと Windows インスタンスを混在させることはできません。

- どのスタックでも、時間ベースの自動スケーリングを使用できます。Linux スタックでは、負荷ベースのスケーリングも使用できます。

- AWS OpsWorks スタックを使用して Amazon EC2 インスタンスを作成するだけでなく、AWS OpsWorks スタックの外部で作成された インスタンスを Linux スタックに登録することもできます。
  - **これには、Amazon EC2 インスタンスと、独自のハードウェアを実行するインスタンスが含まれます。**
creation policyとは

## 参考
https://aws.amazon.com/jp/blogs/devops/use-a-creationpolicy-to-wait-for-on-instance-configurations/

### creation policyとは
- AWS CloudFormationスタックでAmazon EC2インスタンスをプロビジョニングする場合、ソフトウェアパッケージのインストールやbootstrap処理など、追加のアクションを指定してインスタンスを設定できるようにするもの。

- 通常、CloudFormationは、インスタンスが正常に作成された後、（たとえ内部でinitスクリプトが完了していなくても）スタックの作成を続行する。

- CreationPolicyを使用するとアクションが完了した後にのみ、CloudFormationがスタックの作成を続行できるように設定が可能。
  - つまり、スタックの作成が成功後にアプリケーションが準備完了であることを確実にするためにCreationPolicyを使用する。

- CreationPolicyは、CloudFormationが指定された数のシグナルを受信するまでインスタンスを待機するようCloudFormationに指示する。このポリシーは、CloudFormationがインスタンスを作成するときにのみ有効となる。
  - 下記の例の場合、5分後に3つの信号が受信されない場合、CloudFormationはスタックの作成をすぐに停止し、Auto Scalingグループに作成に失敗したというラベルを付ける。したがって、インスタンスとアプリケーションをデプロイするのに十分な時間を与えるタイムアウト期間を指定する。

```
"AutoScalingGroup": {
  "Type": "AWS::AutoScaling::AutoScalingGroup",
  "Properties": {
    ...
  },
  "CreationPolicy": {
    "ResourceSignal": {
      "Count": "3",
      "Timeout": "PT5M"
    }
  }
}
```

#### リソースのシグナリング
- プロビジョニングしているインスタンスから信号を簡単に送信できる。これらのインスタンスでは、EC2ユーザーデータスクリプトのcfn-initヘルパースクリプトを使用して、アプリケーションをデプロイする必要がある。 cfn-initスクリプトの後に、次の例のように、cfn-signalヘルパースクリプトを実行するコマンドを追加する。

```
"UserData": {
  "Fn::Base64": {
    "Fn::Join" [ "", [
      "/opt/aws/bin/cfn-init ",
      ...
      "/opt/aws/bin/cfn-signal -e $? ",
      "  --stack ", { "Ref": "AWS::StackName" },
      "  --resource AutoScalingGroup " ,
      "  --region ", { "Ref" : "AWS::Region" }, "n"
    ] ]
  }
}
```

- CloudFormationにシグナルを送るとき、どのスタックとどのリソースにシグナルを送るかを知らせる必要がある。この例では、cfn-signalコマンドは、インスタンスをプロビジョニングしているスタック、リソースの論理ID（AutoScalingGroup）、およびスタックが作成されているリージョンを指定する。

- CreationPolicy属性とcfn-signalヘルパースクリプトを使用すると、アプリケーションが正常にデプロイされたときにのみスタックが正常に作成されるようにすることができる。
Eclipse + ERMasterで既存DBからER図をリバース

# 既存DBからER図をリバース

本稿では、`Eclipseプラグイン`の`ERMaster`を使用し、`JDBC接続`した既存DBから`ER図`をリバースする手順について紹介する。

## インストール

1. Eclipseをインストールする。

1. ERMasterをインストールする。

    ※`ERMaster 1.0.0.v20150619-0219`のRDBMS対応状況

    |RDBMS|クラス名|
    |---|---|
    |DB2|com.ibm.db2.jcc.DB2Driver|
    |H2|org.h2.Driver|
    |HSQLDB|org.hsqldb.jdbcDriver|
    |MSAccess|sun.jdbc.odbc.JdbcOdbcDriver|
    |MySQL|com.mysql.jdbc.Driver|
    |Oracle|oracle.jdbc.driver.OracleDriver|
    |PostgreSQL|org.postgresql.Driver|
    |SQLServer|com.microsoft.sqlserver.jdbc.SQLServerDriver|
    |SQLServer 2008|com.microsoft.sqlserver.jdbc.SQLServerDriver|
    |SQLite|org.sqlite.JDBC|

1. `JDBCドライバ`(`JARファイル`)をダウンロードし、適当なパスに配置する。
    ※1つのRDBMS/クラス(上表の各行ごと)に複数の`JARファイル`を指定可能

1. データベースを用意し、接続情報を確認しておく。

    ※参考：データベース接続情報

    |項目|MySQL|Oracle|MSSQL|PostgreSQL|
    |---|---|---|---|---|
    |サーバー名|localhost|localhost|localhost|localhost|
    |ポート番号|3306|1521|1433|5432|
    |データベース名|world|master|Northwind|(任意)|
    |ユーザ名|root|scott|SA||
    |パスワード|password|tiger|(任意)||

    ※参考：サンプルDB

    |RDBMS|サンプルDB情報|
    |---|---|
    |MySQL|https://dev.mysql.com/doc/index-other.html|
    |Oracle|$ORACLE_HOME/rdbms/admin/utlsampl.sql|
    |MSSQL|https://github.com/microsoft/sql-server-samples/tree/master/samples/databases|
    |PostgreSQL||

## セットアップ

### JDBCドライバ

1. Eclipseの`環境設定`を開く。

1. `ERMaster`-`JDBCドライバー`を開く。

1. `追加`ボタンをクリックする。

1. `JDBCドライバのパス`ダイアログが開く。

1. `参照`ボタンをクリックする。

1. ダウンロードした`JDBCドライバ`を選択する。  

## ER図を作成

### 新規作成

1. `Javaプロジェクト`を新規作成する。

1. `プロジェクト名`を右クリックし、`ERMaster`を新規作成する。

1. `新規ER図作成ウィザード`が開く。

1. `データベース`プルダウンから、登録済みの`JDBCドライバ`を選択し、`完了`ボタンをクリックする。

1. `ERMaster`エディタで`.erm`ファイルが開く。

### 既存データベースからリバース

1. `ERMaster`エディタ上を右クリックする。

1. `インポート`-`データベース`メニューをクリックする。

1. `データベース`プルダウンから`JDBCドライバ`を選択する。

1. 上記の表を参考に、`データベース接続情報`を入力し、`次へ`ボタンをクリックする。

1. `デフォルトのドライバを使用する`にチェックを付ける。

1. `次へ`ボタンをクリックする。

1. `インポートするスキーマの選択`ダイアログが表示される。

1. スキーマを選択し、`次へ`ボタンをクリックする。

1. `インポートするオブジェクトの選択`ダイアログが表示される。

1. `オプション`を選択する場合はチェックを付ける。

1. オブジェクトを選択し、`OK`ボタンをクリックする。

1. オプションの`現在のER図の情報をクリアする`にチェックを付けると、ダイアログが表示される。問題なければ、`OK`ボタンをクリックする。

1. 既存データベースからリバース処理が開始され、スキーマ/オブジェクトがER図にインポートされる。
第1回Microsoft Learnもくもく会@関西を開催しましたレポ

##イベント情報
開催日: 2020/01/25
日時:13:00-17:00
参加人数：13人
ページURL：https://mslearn.connpass.com/event/159600/

##主催しての感想
- IgniteTheTour Osaka でのmslearnブースをきっかけに来てくださり嬉しかったです。
- Twitter上では、やり取りしてるけど実際に会って話すのは初めての方が居たのも嬉しかったです。
- 席の配置や、受付も早く来た方が手伝って頂いて大変助かりました。
- 北海道の主催者の方がIgniteTheTour Osakaの後と言うこともあり？自己紹介だけして弾丸で帰って行かれましたが、リアルでもコミュニケーションが取れて良かった。

##同時開催
品川とは日程が被る予定という話はしていたのですが、気が付いたら4拠点になってました。😊
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270447/2bd9afc1-ec0e-7246-88e0-8eca52723cff.png)

##参加者の声
- 楽しかったです！各拠点参加したいです！
- 大阪の土日開催を増やしてください
- 他の人が視界に入らないような座席を選べるようになるともっといいかも！
- 勉強する環境ときっかけをいただきありがとうございました。
  - IgniteTheTour→Learn の流れはきっかけづくりに最適ですね

##開催まで
父親が倒れて以降、実家に帰省する機会が増え、関西でも勉強する機会を作りたいなと思って何をやろうかなと思ってた時に
Microsoft Learnもくもく会@名古屋などが立ち上がってるのをみて主催している@__akiyoshi__（https://twitter.com/__akiyoshi__) に相談してOKをもらい開催する方向へと動き出しました。
場所についても相談に乗って頂き、ものすごく立地条件の良い場所を提供して頂くことが出来ました。
そのおかげもあり、心配だった参加者の数も初回にしては13人の方に参加して頂いて嬉しかったです。
Twitterなどで、IT業界では女性のエンジニアはまだ少なく、女性枠についての話題も流れてきたりして悩んだりしました。
で、ぼやいていると凄腕の女性エンジニアの方が手伝って頂けてることになって、マジで感謝しかない！！

アンケート結果を見て、継続開催したいなぁという意欲が強くなりました。
今回の日程は、IgniteTheTour Osakaの日程が分かってたので、その前後で実施したいなぁと思っており、「Power Platform Day Winter '19 Osaka」の予定のところを1部屋譲って頂き開催することが出来ました。
本当、多くの人に支えってもらって開催出来て、恵まれてるなぁ俺！って気持ちでいっぱいです。

##懇親会の様子
茶琥屋 福島店にて
https://chakoya-fukushima.owst.jp/
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">みんなで懇親会！🍻🧆←たこ焼きに見える絵文字 <a href="https://twitter.com/hashtag/mslearn?src=hash&amp;ref_src=twsrc%5Etfw">#mslearn</a> 関西 <a href="https://t.co/IYQf2LJqUS">pic.twitter.com/IYQf2LJqUS</a></p>&mdash; dz づ (@dz_) <a href="https://twitter.com/dz_/status/1220992203507392512?ref_src=twsrc%5Etfw">January 25, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【CSS】topScrollアイコン 背景黒丸矢印型 CSSだけ

#fontawesomeや画像を用いずCSSだけで矢印アイコンを表現する
##ggってもなかなか検索で見つからないので自作してみた。

```html:filename.html
<div class="topScroll">
 <a href=""></a>
</div>
```

```css:filename.css
.topScroll {
  width: 70px;
  height: 70px;
  background-color: black;
  border-radius: 50%;
  position: fixed;
  bottom: 50px;
  right: 50px;
}

.topScroll a {
  width: 100%;
  height: 100%;
  position: relative;
  display: block;
}

.topScroll a::before {
  content: "";
  border-left: 3px solid grey;
  border-top: 3px solid grey;
  width: 25px;
  height: 25px;
  transform: rotate(45deg);
  position: absolute;
  top: 30px;
  left: 21px;
}
```
Angular９とFirebaseでブログを作ってみる８（Twitterタイムラインを埋め込んでみる）

[前回](https://qiita.com/teracy55/items/9b6ed3b557a412549d20)、Qiitaの更新履歴を出しました。

今回はTwitterのタイムラインを埋め込んでみようかと思います。


ブログ：https://teracy-blog.firebaseapp.com/



# Twitterタイムラインの埋め込み方

以下のサイトから埋め込み用のコードを生成します
https://publish.twitter.com/#


## 埋め込み対象のTwitterURLを入力します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/b5c051af-52d7-7041-be46-f03956415070.png)


## 埋め込みタイムラインを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/3dd348c8-b548-b1a4-cdb1-de42069e2e2b.png)

## 生成されるコードをコピー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/f4a063cd-603f-407d-2b62-08f5b6eeec5f.png)

下の方にプレビューが表示されます。


# Angularへの組み込み

- 生成したコードをそのまま貼り付けるだけです

```src/app/top/twitter/twitter.component.ts
<div class="top-contents">
  <h4 class="title">Twitter</h4>

  <a class="twitter-timeline" href="https://twitter.com/teracy55?ref_src=twsrc%5Etfw">Tweets by teracy55</a>
  <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
```


# 確認

表示されないですね。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/ea15d9fa-ccf9-a565-d280-6aa035c20482.png)



# 解決策？

こちらを参考にさせていただきました。
[FacebookとTwitterの公式シェアボタンをSPAで表示する方法](https://qiita.com/jshimazu/items/0c8f4ddcaf27b0e39eeb)

- 生成された`<script>`タグをindex.htmlの`<head>`タグ内に移動します

```src/index.html
<html lang="ja">
<head>
  ・・・
  <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
```

- タイムライン表示をしたい画面のHTMLファイルで`<a>`タグのみを配置します

```src/app/top/twitter/twitter.component.html
<div class="top-contents">
  <a *ngIf="!isLoading" class="twitter-timeline" data-lang="en" data-width="300" data-height="500"
    href="https://twitter.com/teracy55?ref_src=twsrc%5Etfw">Tweets by teracy55</a>
</div>
```

- TwitterComponentでTwitterウィジェットのload()を呼び出します
    - `https://platform.twitter.com/widgets.js`が読み込めている場合は`twttr`が見れるようになっています

```src/app/top/twitter/twitter.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-top-twitter',
  templateUrl: './twitter.component.html',
  styleUrls: ['./twitter.component.scss']
})
export class TopTwitterComponent implements OnInit {
  ngOnInit() {
    // Twitterウィジェットの読み込み
    if (window['twttr']) {
      window[`twttr`].widgets.load();
    }
  }
}
```

Twitterの仕様が変わったら動かなくなる可能性が高いので、おいおい考えることにします。


# こんな感じになりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/9f599149-4f79-64dc-1272-9f782b93a100.png)

がたがたですが、これは後々調整していきます


# まとめ

モヤモヤは残りますが、とりあえずTwitterのタイムラインも表示できました。
次はNews部分を表示して、TOPページをFixしたいと思います。


次回：[Angular９とFirebaseでブログを作ってみる９（Analyticsを使ってみる）](https://qiita.com/teracy164/items/b78bdc6339d3f814752e)
技術的負債について考えてみた

## 技術的負債とソフトウェアの品質


TODO：ストーリーがまだ練り切れてない状態ですので、折を見て修正します


技術的負債は、システムの品質が劣化する原因だと考えることができます。

技術的負債というと、ソースコードの保守性についてフォーカスが当たりがちですが、パフォーマンス劣化など、影響はさまざまかと思うので広くとらえることとします。

この記事ではちょっと乱暴かもしれませんが、「ソフトウェアの品質が劣化している」＝「技術的負債が蓄積している」＝「欠陥がある」とみなします。





## そもそも品質とは

### ソフトウェアの品質の種類

一口に品質といっても多岐にわたるので、議論するときはどの品質を指しているのかを気を付ける必要があります。

例えば[ISO/IEC 9126](https://ja.wikipedia.org/wiki/ISO/IEC_9126) というソフトウェア品質特性のモデルがあります。（漢字多いんで読まなくていいです。）

とりあえず、このモデルではソフトウェアの品質は、機能性、信頼性、使用性、効率性、保守性、移植性に分けていて、さらにこれを細分化しています。

### サービスの品質：狩野モデル

[狩野モデル](https://ja.wikipedia.org/wiki/%E7%8B%A9%E9%87%8E%E3%83%A2%E3%83%87%E3%83%AB) は、『顧客が製品やサービスに対して要求する品質について、「当たり前品質」「一元的品質」「魅力的品質」「無関心品質」「逆品質」の品質要素に分類する』ものです。

やみくもにサービスの品質にコストをかけても、顧客満足度が上がる（≒お金になる）かどうかは別問題ということです。

たとえば、軽微なバグは直さないという判断は、サービスの品質に影響を及ぼすかどうかによって判断するべきで、その結果として直さないという判断は大いにありえます。

もちろん、サービスの品質という観点でいえばすぐ直すべきという場合もあるかもしれません。（ボタンが押しにくい、など）

### システムの品質を作りこむ手法

システムの品質を議論するうえで、以下の２つの工学手法があります。

それぞれ、織り込む品質の種類によって分けられます。

- 信頼性工学
    - 設計時点で想定される、システムが安定して稼働するための条件を考える。
- 生産工学
    - 製造過程における作業効率の向上、ミスの予防について考える

信頼性（システムが安定して稼働するための条件）の問題については、安価に発見するためには設計レビュー・コードレビューが適切です。

もちろん、ソフトウェアテストでも可能ですが、信頼性に関するテストは環境を準備したり、時間を要したりします。そのため、特にアジャイル開発の文脈ではレビューで欠陥の発見を目指すのがコスト的に適当かと思われます。

作業プロセスにおけるミスは、コードレビューでも発見しますが、チェックリスト化したり、静的解析ツールによる自動チェックする仕組みを考えるべきです。

なお、不吉なにおいについての指摘は、(たぶん）作業効率の向上やミスの予防のための指摘にあたりますが、自動チェックする仕組みだけでは簡単には検知できない場合があります。

例えば重複コードの検知を行うツールは存在しますが、それが１つのメソッドなどに集約可能であるかは人手で判断する必要があります。
自己流のlatexにソースコード貼り付け術

自分が論文に使った時のテクをメモ代わりに残しておきたい.

条件としてはレポートを図扱いしてキャプションを図同様に扱いたい、ラベルも普通に使いたいなどである．

パッケージはこんな感じ

環境はオンラインLatex IDE、overleafを使用

```latex

\documentclass[a4paper,xelatex,ja=standard]{bxjsarticle}

\usepackage{listings}
\usepackage[dvipdfmx]{graphicx}
\usepackage{here}
\usepackage{amsmath}
```


```latex
\begin{figure}[H]
\begin{lstlisting}
    float test(int hoge){
    retrun hoge*hoge;
    }
\end{lstlisting}
\caption{サンプルコード}
\end{figure}
```

ソースコードをfigure扱いすることで図と同じ扱いにします。私と同学の人間だとレポート提出時、ソースコードは図扱いになると思うので参考にしてください
Windows×Eclipse×freeglutでOpenGLを使いたい

#はじめに
こんにちはZeniZeniです。
大学の課題でOpenGLを触ることになったのですが、その際の環境構築でえらく躓いたので、これ以上の犠牲者が出ないようにその方法を共有しようと思います。

#環境
- Windows10
- MinGW (version 8.2.0)
- Eclipse (Version: 2019-12 (4.14.0))

C言語のコンパイル環境構築とEclipseのインストールは省略します。
より詳しい方法は下記のサイトを参考にしてください。
[2020年版 C言語/C++ 入門者のための環境構築 (Windows編)](http://lyncs.hateblo.jp/entry/2018/03/11/032127)
[【ゼロからわかる】Eclipseのインストールと初歩的な使い方](https://eng-entrance.com/java-eclipse-install)

# freeglutの準備
ではOpenGLを扱いやすくするためのライブラリ、freeglutの準備をしていきます。
まずfreeglutのMinGWパッケージを下記のサイトからダウンロードしてください。
[freeglut Windows Development Libraries](https://www.transmissionzero.co.uk/software/freeglut-devel/)
![bandicam 2020-01-26 15-00-10-622.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/bdd7b707-f3ad-be8b-bf14-b6c7a894aab0.jpeg)
そしてダウンロードしたzipファイルを解凍してください。

## dllファイルの移動
解凍したら、中のファイルを移動していきます。
まずbinフォルダ内のfreeglut.dllをどこかPATHの通っているところに移動します。ここでfreeglut.dllにはbin\freeglut.dll(32bit版)とbin\x64\freeglut.dll(64bt版)の二つ存在しどちらを使えばいいのか迷うと思います。パソコンが64bitなんだからx64の方かと思うかもしれません。**違います。** MinGWのコンパイラは64bitのwindowsプラットフォームでも32bitで動いているのでここではbin\freeglut.dll(32bit版)を使います。それではこのfreeglut.dllをPATHの通っているところに移動します。多くのサイトでwindowsが32bitならC:Windows\System32へ、64bitならC:Windows\SysWOW64へ移動しろと書いてあります。ここは素直にSysWOW64の方へ移動しましょう。

## includeフォルダの移動
freeglut\include\GLフォルダの中に入っているヘッダーファイル群は、MinGWディレクトリ内のinclude\GLフォルダ内に追加しましょう（MinGWでのインストールと一緒にGLフォルダは生成されているはずです。）
移動するとこのようになっていると思います。
![bandicam 2020-01-26 15-55-48-406.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/743499b5-0e32-1d67-a06e-ebb748e83071.jpeg)


## libフォルダの移動
freeglut\libフォルダ内のlibfreeglut.a、libfreeglut_static.aファイルも移動します。これらもlib直下にあるのと、lib\x64内にあるやつとで2種類ありますが、dllファイルと同様に32bitのもの(lib直下のやつ)を移動します。移動先はMinGW\lib直下です。
![bandicam 2020-01-26 16-02-47-127.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/c2489a36-d021-2f6e-18ca-d4604637f275.jpeg)

これでfreeglut側の準備は完了です。

#Eclipseの設定
次にEclipseでの設定です。
適当にプロジェクトを作成して、OpenGLを使うコードを書いておきます。
コードは[An Eclipse / CDT Tutorial with OpenGL](https://bohr.wlu.ca/cp411/eclipseCDT.php)で使われている赤いCubeを描画する[コード](https://bohr.wlu.ca/cp411/cube.c)にします。

その後プロジェクトパネルで自分が今触っているプロジェクトを左クリックしてPropertiesを開きます。
Propaties内のC/C++Build\Settingsを選択し、Tool Settings内のMinGW C Linkerを選択し、Librariesを編集していきます。
右上の+マークからライブラリ名を追加していきます。
上から順に"opengl32"、"glu32"、"freeglut"となるように追加してください。順番が違うとコンパイル時にエラーが吐かれます。
![bandicam 2020-01-26 16-00-52-428.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/6dbcd416-bbda-22d2-6212-eccfcda8210d.jpeg)

これでEclipseの設定は完了です。ビルドしたファイルを実行すれば赤いCubeが描画されているウィンドウが出現します。
![bandicam 2020-01-26 16-18-37-541.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281560/045226ca-595e-9e41-13f2-974af88e7062.jpeg)

#参考文献
- [An Eclipse / CDT Tutorial with OpenGL](https://bohr.wlu.ca/cp411/eclipseCDT.php)
- [freeglut Windows Development Libraries](https://www.transmissionzero.co.uk/software/freeglut-devel/)
【Pythonやってみた！】タイタニックデータ編_vol.1（棒グラフ，散布図，相関係数）

本日は，あまり難しいことは考えずに，
とりあえず「タイタニックデータ」を使って，
統計的分析をしていきます．
※本日は，超初心者向けです！
（棒グラフ，散布図，相関係数　程度まで）


##■はじめに
###＜私の実行環境＞
Microsoft Windows Version：10.0
Python Version：3.8.1
※コマンドプロンプト使用
（Linuxの方が適しているという噂を聞いたのですが，私が持っているのはwindowsのPCだし...
ということでとりあえず，windowsで頑張っています．）

↓（参考）windowsのバージョン確認

```
C:\Users\ユーザ名>ver
```

↓（参考）Pythonのバージョン確認

```
C:\Users\ユーザ名>python
```

###＜仮想環境について＞
Pythonは仮想環境上で実行していくと都合がいいらしいので，
私も仮想環境を使っています．
※仮想環境の作り方についてはまた後日紹介できればと思います．

↓（参考）仮想環境の立上げ

```
C:\Users\ユーザ名>仮想環境名\scripts\activate
```
↓（参考）仮想環境を立上げたらこのように表示される

```
(仮想環境名)C:\Users\ユーザ名>
```


##■必要なパッケージのインストール
今回使用するパッケージは，
・numpy
・pandas
・matplotlib
・seaborn
です．

↓インストール

```
(仮想環境名)C:\Users\ユーザ名>pip install パッケージ名
```

↓インストール済みのパッケージ一覧表示

```
(仮想環境名)C:\Users\ユーザ名>pip list
```

↓結果はこんな感じ．
![インストール済ライブラリ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573636/ded5d4b2-5cb0-0634-154b-75f04c9be10a.png)


##■pythonの起動

```
(仮想環境名)C:\Users\ユーザ名>python
```

↓（参考）Pythonが起動したらこのように表示される
（>>>しか表示されなくなった...）

```
>>>
```


##■データの読込み
今回は，世界的なデータコンペ「Kaggle」から入手可能な「タイタニックデータ」を使います．
※こちらも詳細は後日紹介できればと思います．

###＜データの保存フォルダ＞
私自身が超初心者なもので，よく分からなかったので，
一旦，「C:\Users\ユーザ名」フォルダ直下にデータを保存しました．
（絶対パスとか相対パスとか試したのですが，なぜか上手くいきませんでした...（TT））

###＜データ読込み＞
↓パッケージのインポート

```
import pandas as pd
```
※完了すると，再び「>>>」が出てくる．

↓「train.csv」を，「pandas（pd）」の「read_csv」クラスを使って，
「df」に格納する．

```
df = pd.read_csv("train.csv")
```


##■いよいよデータ分析をやってみる！
ここまで来たら，あとは，好きなようにデータを見ていきます．

###＜生存・死亡者数＞
必要なパッケージをインポートをしてから，
「df」に格納したデータの項目「Survived（生存者=1，死亡者=0）」を棒グラフに表示してみます．

```
import seaborn as sns
import matplotlib.pyplot as plt
sns.countplot("Survived",data=df,palette='rainbow')
plt.show()
```
↓「plt.show()」実行結果
　上下左右のずれの調整とか，画像の保存もここからできて便利でした！
![Figure1イメージ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573636/082e70bb-61ab-226a-aa75-cf285c0f9c49.png)

###＜相関係数行列（ヒートマップ）＞

```
sns.heatmap(df.corr(),annot=True,cmap='RdYlGn',vmin=-1,vmax=1,fmt=".2f",square=True)
plt.show()
```
![ヒートマップイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573636/3c2ec421-e6a1-1341-909c-f962b0f165f2.png)


###＜ペアプロット図＞

```
sns.pairplot(df)
plt.show()
```

![ペアプロットイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573636/10c9b65e-3f8b-df28-daed-5dab073caa72.png)

##■最後に
本日はお読みいただきありがとうございました．
本投稿が初投稿なもので，いろいろ分かりにくいところもあったかと思いますが，
ご容赦ください．
ご指摘があれば受け付けますので，（受付方法がよくわかっていませんが...）
どうぞよろしくお願いいたします．
自分でも誤りを見つけましたら都度修正します．
ご質問もできる限り回答しますので，（これも受付方法がわかりませんが...）
どうぞご自由にご質問ください．
ではまたどこかでお会いしましょう～（^^）♪
PythonでflacをaacやALACに変換する。

flac形式がiphone対応してないため、変換するツール作りたい。

## 事前準備
pydubとffmpegをインストールする。
### 開発環境は以下
- Windows10 64bit Pro
- VS Code

## 実装
```python
from pydub import AudioSegment

sound = AudioSegment.from_file("C:/Project/audio/music.flac", format="flac")
# AAC形式への変換
sound.export("convert320k.m4a", format="ipod", codec="aac", bitrate="320K")
# ALAC(AppleLossless)形式への変換
sound.export("convert.alac", format="ipod", codec="alac")

```

## はまった点
formatにalacを指定するとエラーとなり、ffmpeg側から怒られた。
mp3ならmp3で通るので拡張子と同じ設定だなと思いこみで、半日潰れた。

```python
    sound.export("convert.alac", format="alac", codec="alac") # NG
    sound.export("convert.alac", format="ipod", codec="alac") # OK
```

## 参考
- [pydubを今すぐ動かしたい](https://qiita.com/nyohei_freelance/items/cb7c90734d1dbdfe6174)
- [pydubの概要を勉強したサイト](https://githubja.com/jiaaro/pydub)
- [ffmpegでalacに変換](https://qiita.com/kokifpen/items/bfb5f2feda2ac17de1bb)
- [ffmpeg 公式](http://trac.ffmpeg.org/ticket/2768)
花モゲラ語と日本語

#初めに
花モゲラ語はニッポンの方言である。
明確に使っている人や地方は未確認である。

なお、この記事は私の妄言である。

#花モゲラ語とは
花モゲラ語とは色々言われるが、端的に言って、
音の聞き手や文の解読者等、取得者にダイナミックバインディングする自然の仕組みである。
それを端的に言うなら万華鏡である。

#花モゲラ語の共有
基本的に花モゲラ語は一人用である。
例えば文書が「花モゲラ語」であった場合、単語選択の乱数に真の乱数を使うので再現性が無い。
エンターテイメントなら使い捨てのそれもいいが、共有には向かない。
なので、共有の向きには単語選択に疑似乱数を使い、シードを共有することで再現性を得る。


#花モゲラ語の用途
主にエンターテインメントだが、公文書もたまにこれで書く人がいるらしい。やめろ。
逆に、厳格に一意性を保持するコンテンツ全般には向いていない。

んで、乱数さえ再現されれば、通信なんかにも使える。と思ったが、イタ電がかかってきて検証してみた結果、大失敗だったのでやめておきましょう。
非同期通信すると色々ぶっ壊れることが解りました。

#花モゲラ語と記憶構造
花モゲラ語は万華鏡である。故、点にすれば色々分岐に使えるのである。
そして、疑似乱数によってその分岐は再現性を得るのである。
そこで、それを記憶しておけば確かに記憶構造としてはかなり安くなるはずなのだ。
そして、忘れてはいけないのが、花モゲラ語の単語に照射するデータである。
照射するデータが分岐を産むが根拠にもなる。
これを忘れるとボケた機械になるので「データ」には絶対触ってはいけない。

#花モゲラ球
花モゲラ球とは花モゲラの単語がちりばめられて作られる、球である。球なので、Z方向も使えなくはないようだ。
花モゲラ野という地平がありそれを立体化した程度のものである。
用途は主に体に負荷をかける向きだが、読める人は意識で読めるかもしれない。私は読めない。
主に、体の負荷生成への福祉が目的である。

作るに際して誕生時に与えて人生の終焉まで持つくらいの分量を作ることができる。でも球である。

自分の周囲では、3000語程度内包した試供品を各所に試供したところ、好評を得ているらしい。サービスは自然がやっている。ここにいる。

#花モゲラDB
花モゲラデータベースというモノを考えた。
単純にデータのフローを書けばいいものについて、ツリー構造のC++テンプレートのN分木の接点に「クラス・花モゲラワード」を設定するというモノですが、どう書けばいいのかちょっとわからないですね。難しい。

#終わりに
読み物としてみていただければ幸いです。
C++11 PEG パーザーライブラリ PEGTL のメモ 

https://github.com/taocpp/PEGTL

Version 2.x ですと C++11 で動きます.

## 利点

template プログラミングであるが, コンパイルが早めな気がする.

https://github.com/yhirose/cpp-peglib

すくなくとも cpp-peglib よりはコンパイルが早い感じがします.

ヘッダーオンリー.

## 使いかた

ルールは template で定義します.

```cpp

using namespace tao::pegtl;

struct sign : one< '+', '-' > {};
struct integer : seq< opt< sign >, plus< digit > > {};
```

`<`, `>` の間のスペースは空いていても空いていなくても問題ありません.

https://github.com/taocpp/PEGTL/blob/master/doc/Rule-Reference.md

最初はちょっと手間取りますが, サンプルなど見て慣れればだいたい C++11 の仕組みで書けます.

## 文字列に対して parse する.

memory_input で入力データを作ってから parse に渡します.

```
std::string uri = ...;
pegtl::memory_input input( uri, "uri" );
pegtl::parse< grammar, uri::action >( input, *this );
```

ファイルや stdin から入力を受け付ける関数もあります.

## action を設定する

ルールにマッチしたときに呼び出す関数(callback)も template で定義します.


```
   // 必須
   template< typename Rule > struct action {};

   // 個々のルールに対して apply でアクションを定義.
   template<>
   struct action< pegtl::uri::opt_userinfo >
   {
      template< typename Input >
      static void apply( const Input& in, URI& uri )
      {
         if( !in.empty() ) {
            uri.userinfo = std::string( in.begin(), in.size() - 1 );
         }
      }
   };
```

まずはベースとなる action のテンプレートを定義し, そのあと各ルールごとに template を定義します. ベースの template を定義していないとうまく動きません(なにも起こらない)ので注意です.

また, apply の第二引数と, parse で渡す型が違うととこれもまた何も起こらないので注意です.
e.g.

```
 std::string ctx;

 // action は `URI` に対して定義しているので, なにもおこらない.
 pegtl::parse< grammar, uri::action >( input, ctx );
```

## 問題点

template programming なので, パターンマッチしないときはエラーを出さず何も処理されないので注意です.

したがってデバッグはちょっとめんどいかもしれません. cpp-peglib などで先に grammar を記述してテストしておくのがよいかもしれません.

## TODO

* [ ] ast について調べる https://github.com/taocpp/PEGTL/blob/master/doc/Parse-Tree.md
量子アニーリングに最短距離で入門する (1. 組み合わせ最適化問題とは)

## 量子アニーリングを実務で使いこなせることを目標に
パラシュート学習的に, 最短で必要な知識を集めたいと思います.
前提知識は, 量子アニーリングと量子ゲート方式があるというのを聞いたことがある程度です.

### 参考
https://quantum.fixstars.com/techresouces/
このサイトを参考にまとめています.

## 量子アニーリングは組み合わせ最適化に特化した量子アルゴリズム
だそうなので, まずは組み合わせ最適化問題とは何かを学習します.
>[量子アニーリング方式は、組合せ最適化問題に特化した量子アルゴリズムの一つです](https://quantum.fixstars.com/techresouces/annealing-method/)

## 組み合わせ最適化問題とは
その名の通り, 最適な組み合わせを探す問題です. 
### 巡回セールスマン問題を例に
学習してみます.
巡回セールスマン問題とは, セールスマンが複数の都市をそれぞれ一回づつ訪問する際の, 最短経路を求める問題で, 以下の式で表せます.

```math
C = \sum_{i{\neq}j}c_{ij}x_{ij}
```
$c_{ij}$ は都市iと都市jの距離, $x_{ij}$ は都市ij間を移動する場合に1, そうでない場合は0となります. すると, $C$ は総移動距離になるので, コスト関数やエネルギー関数, 目的関数などと呼ばれます.

都市の数が$n$ だとすると, 組み合わせの数は$n!$ となりますが, これは都市の数$n$が増えるにつれて組み合わせの数が爆発してしまいます.

- [10! = 3628800](https://www.google.com/search?client=firefox-b-d&sxsrf=ACYBGNTfn2zpfTtv5ahAzYrBJMI-bavjsQ%3A1580017851381&ei=uygtXuThFor7-Qa6vL_wBw&q=10%21+%E9%9B%BB%E5%8D%93&oq=10%21+%E9%9B%BB%E5%8D%93&gs_l=psy-ab.3..0i7i30l8.2876.2876..3105...0.0..0.105.301.1j2......0....1..gws-wiz.......35i39j0i4i37j0i5i30.PFj2GYxIgro&ved=0ahUKEwikq5SWyaDnAhWKfd4KHTreD34Q4dUDCAo&uact=5)
- [20! = 2.432902e+18](https://www.google.com/search?client=firefox-b-d&sxsrf=ACYBGNQJ3DwR0_rbK0u6WdL2IU2P1P2Jcg%3A1580017627110&ei=2yctXumkBpHm-AaZh6bYCw&q=20%21+%E9%9B%BB%E5%8D%93&oq=20%21+%E9%9B%BB%E5%8D%93&gs_l=psy-ab.3..0i4i37j0i30j0i8i30l3j0i5i30l3.916.1922..2133...0.0..0.126.1212.1j10......0....1..gws-wiz.......35i39j0j0i67j0i131j0i4i3j0i4j0i4i30j0i8i4i30j0i5i4i30.BQPR6t5nkuo&ved=0ahUKEwip_puryKDnAhURM94KHZmDCbsQ4dUDCAo&uact=5)
- [30! = 2.6525286e+32](https://www.google.com/search?client=firefox-b-d&sxsrf=ACYBGNT1bcXqURaYOfU1ayC2v0wqlxiKrA%3A1580017693526&ei=HSgtXqHjH4K6wAPc_I24CQ&q=30%21+%E9%9B%BB%E5%8D%93&oq=30%21+%E9%9B%BB%E5%8D%93&gs_l=psy-ab.3..0i4i37j0i8i30l6j0i8i7i30.1546.1630..2208...0.0..0.125.405.2j2......0....1..gws-wiz.......35i39j0i30j0i5i30.SOsDdj2aHVc&ved=0ahUKEwjh5fHKyKDnAhUCHXAKHVx-A5cQ4dUDCAo&uact=5)

このような問題は現実的な時間で最適解を厳密に求めることが困難なので, 最適解に近い近似解を求めることで対応することがあり, その近似解を求める方法の一つが量子アニーリングである.

とのことです.

## 巡回セールスマン問題を量子アニーリングで解くには
どうすれば良いでしょうか. 
> [量子アニーリングを実行するためには、解きたい問題をイジング模型に変換する必要があります。ある程度は機械的に行うこともできますが、量子コンピュータのリソースや制約を踏まえて適切な変換を実行することがソフトウェアエンジニアの仕事です。](https://quantum.fixstars.com/techresouces/annealing-method/)

とのことなので, 巡回セールスマン問題をイジング模型に落とし込む必要がありそうです。ここまで読んで全くイメージが沸かないうえに, 全く量子アニーリングにたどり着きませんでしたが、休憩したいのでこの先は次回に回します... 次はイジング模型あたりを調べます. (絶対にここでやめないと誓って)
SSHポートフォワーディングを利用したログイン方法

# 概要
AWSに限らずですが、パブリッククラウドを使っていて、グローバルIPがなかったり、ネットワークACLで許可されていないサーバにSSH接続したいことってありませんか？
そんな場合のTIPSになります。

尚、このやり方であれば、SFTPやSCPも直接接続できるので、いちいち踏み台サーバにファイルを置かなくてもやり取りができるので作業が捗ります。

# 前提
・ローカル環境からSSH接続できるUNIXもしくはLinuxOSのインストールされたサーバ(以下、**サーバA**とする)が1台存在すること。
・サーバAからプライベートアドレスでSSH接続できるサーバ(以下、**サーバB**とする)が1台以上存在すること。尚、サーバBはインターネットなど外部との接続は許可されていないものとする。

# やり方
## 事前準備
### (1) Tera termで**サーバA**に接続
Tera termを使って、ローカルからインターネット越しに接続できるサーバにSSHで接続、ログインします。
![WS000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/1d3c7006-31b5-fdf1-134c-115908779310.jpeg)

### (2) SSH転送設定を開く
Tera termの「設定」から、「SSH転送」を選択します。
![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/fc94b1ea-5413-db1c-2bbb-75595caf528a.jpeg)

### (3) SSH転送設定追加
SSHポート転送画面で「追加」をクリックします。
![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/40db02bb-3352-e62a-4abb-e24a827d6d5a.jpeg)

### (4) SSH転送設定実施
以下のように入力し、OKをクリックします。

|ローカルのポート|リモート側ホスト|ポート|
|:------|:------|:------|
|任意のポート番号(例＞SSHのポート番号(22)+10000)|**サーバB**の内部IPアドレス|22|

![WS000005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/e9ea9a1d-2789-4151-0e64-6e26179e59df.jpeg)

### (5) SSH転送設定確認
以下のようになっていれば設定は完了です。
![WS000006.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/73f87432-e5f8-4f7c-1f21-c6d0c95b6101.jpeg)

## Tera termでの接続方法
### (1) 新しい接続設定
Tera termを起動し、接続画面で以下のように入力し、OKをクリックします。

|ホスト|サービス|TCPポート|
|:------|:------|:------|
|localhost|SSH|任意のポート番号(例＞SSHのポート番号(22)+10000)|

![WS000007.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/23bac14c-99f3-dd9b-9430-d4db4bb263a5.jpeg)

### (2) ユーザ名、パスフレーズ、鍵の入力
SSH認証画面で必要に応じて、ユーザ名、パスフレーズ、秘密鍵を入力し、OKをクリックします。
![WS000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/bb210c67-bfd5-3f52-ccb6-ef868bde16ab.jpeg)

### (3) 接続確認
対象のサーバに接続できればOKです。
![WS000009.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/46a6563b-e06f-d7c5-2323-e0fde060d193.jpeg)

## WinSCPでの接続方法
### (1) 新しい接続設定
WinSCPを起動し、接続画面で以下のように入力し、ログインをクリックします。
秘密鍵を使っている場合は設定から追加してください。

|転送プロトコル|ホスト名|ポート番号|ユーザ名|パスワード|
|:------|:------|:------|:------|:------|
|SCP|localhost|任意のポート番号(例＞SSHのポート番号(22)+10000)|**サーバB**の所定のユーザ名|**サーバB**の所定のパスワード|

![WS000012.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/ac3c57dc-3463-11d7-4335-d09acee00833.jpeg)

### (2) 接続確認
うまく接続できればOKです。
![WS000014.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/aa4b0b79-8489-0d1c-7873-e862ad0a9614.jpeg)

# 雑記
どこにでもある情報ですが、いざ説明しようとすると初心者向けの説明はなかなか見つからなかったので、記載しました。