OmniAICreator/Qiita-1.07M huggingface dataset:
OSの状態を知る


無用なトラブルを避けるためにOSの状態を確認する最低限の方法を知っておきましょう。

## 前提

* Virtualbox上に「最小限のインストール」でCentOS7.7を構築
* ポートフォワーディングでホストの8888番ポートをゲストの80番ポートに転送(http)
* ポートフォワーディングでホストの2222番ポートをゲストの22番ポートに転送(ssh)
* ゲストOSからインターネット接続が可能

## OSにログインする

まず調査したい対象OSにログインします。

```bash
ssh -p 2222 devuser@localhost
```

>ユーザー名はインストール時に作成したユーザー名とする。わからなければrootでも可。

## OSの状態を知る

### OSのバージョン

まずはOSのバージョン。CentOSは6.x, 7.x, 8.xが実運用されており、バージョン毎に操作法がやや異なります。
自分の利用しているOSのバージョンを確認できるようにしましょう。

```bash
cat /etc/redhat-release

CentOS Linux release 7.7.1908 (Core)
```

### timezone

運用に置いて重要なのがTimezoneです。標準ではUTCになっていることも多いため確認しておくと無用なトラブルを避けられます。
JSTになっていることを確認します。

```bash
timedatectl

      Local time: 火 2020-03-31 07:19:50 JST
  Universal time: 月 2020-03-30 22:19:50 UTC
        RTC time: 月 2020-03-30 22:19:49
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
```

変更が必要な場合は下記のようにする。

```bash
sudo timedatectl set-timezone Asia/Tokyo
```


### locale

ロケール（言語設定）に起因するトラブルは多くはないですが、どのような設定になっているかを知っておくといいでしょう。

```bash
localectl

   System Locale: LANG=ja_JP.UTF-8
       VC Keymap: jp
      X11 Layout: jp
```

変更が必要な場合は下記の様にする。

```bash
sudo localectl set-locale LANG=ja_JP.utf8
```

### メモリ容量

メモリ容量の確認方法です。

```bash
free

              total        used        free      shared  buff/cache   available
Mem:        1882152      151292     1515104        8808      215756     1578448
Swap:        839676           0      839676
```

### ディスク容量

ディスク容量の確認方法です。
Linux（UNIX）系のOSでは標準で複数のパーティションが設定されることがあります。
ここで重要なのはrootパーティションです(/)。

```bash
df

ファイルシス            1K-ブロック    使用  使用可 使用% マウント位置
devtmpfs                     929116       0  929116    0% /dev
tmpfs                        941076       0  941076    0% /dev/shm
tmpfs                        941076    8808  932268    1% /run
tmpfs                        941076       0  941076    0% /sys/fs/cgroup
/dev/mapper/centos-root     6486016 1200856 5285160   19% /
/dev/sda1                   1038336  152476  885860   15% /boot
tmpfs                        188216       0  188216    0% /run/user/0
tmpfs                        188216       0  188216    0% /run/user/1000
```

### CPUの状態

CPUの負荷状況の確認。

```bash
top
```

>vmstat等も利用される。


### SELinuxの状態

セキュリティー（アクセス制御）設定を行う機構。多くの場合OFF(disabled)にする。

>httpによる公開ファイルの不正改竄等を防止する機能があるためONのままだと、Web関連のファイルの編集でトラブルの原因となる。

```bash
getenforce

Enforcing
```

EnforcingとなるのはONの状態です。
変更が必要な場合は/etc/selinux/configを編集

```bash
sudo vi /etc/selinux/config
```

>設定をdisabledにする（詳細の手順は後述しますので、ここでは設定変更不要です）。

### (OSの)Firewallの状態を確認

OS搭載のfirewallの状態も確認しておきます。

```bash
sudo firewall-cmd --state

running
```

>sudoを実行した際、パスワードを聞かれる可能性があります。

動作しているようです。
どういう設定か見てみます。

```bash
sudo firewall-cmd --list-all

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp0s3
  sources: 
  services: dhcpv6-client ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks:
```

sshが許可されています。

>webを確認するには80番ポートをopenする必要があります（後述）。

## 考えよう

* SELinuxとは何か？
* firewall-cmdとは何か？
* swap領域とはなにか？
jQuery でスクロール量や、コンテンツの高さの取得

jQuery で下記ができれば、一般サイトでよく見かけるような、少し動きのあるサイトが作れる。
これらとif文使えば、ある程度のことができるかも。
自分で学習した構文をメモ。

###●高さや量の取得

```
//スクロール量の取得
$(window).on('scroll', function () {
  var sc = $(this).scrollTop(); //スクロール量を変数に格納
}

or

$(window).scrollTop();
```


```
//ウィンドウの高さ
$(window).height();
```


```
//指定ブロックコンテンツの高さ取得
//取得する値：コンテンツ + padding + border + margin
$('.class').outerHeight(true);

```
参照
https://uxmilk.jp/40801

```
//コンテンツのページ上の位置の取得
$('.class').offset().top;
```
ページの左上の角からの位置。
`.offset()` でコンテンツの左角の位置（x軸、y軸）の位置が取れる。
`.offset().top` でy軸だけ、
`.offset().left` でx軸だけ取得できる。



###●表示・非表示
・非表示クラスの付加・削除
・フェードイン・フェードアウト

```

//非表示クラスの追加
$('.xxx-area').addClass('is-hidden');

//非表示クラスの削除
$('.xxx-area').removeClass('is-hidden');


//フェードイン
$('.class').fadeOut(fade_speed);

//フェードアウト
$('.class').fadeOut(fade_speed);

```
Vue/Vuex/Nuxtのformでinput type='file'を指定するとv-modelが使えない

## きっかけ

Nuxt.jsとRails APIを使用してアプリを作っています。
画像アップロード機能をformで作成中、v-modelでひっかかってしまったので
その対処法を載せたいと思います。

## 問題
formで画像をアップロードする場合、HTMLタグのinputを使うと
typeとしては`file`を選ぶことになると思います。
そしてそこで取得したデータをdata()内のObjectに格納しようと思い、
v-modelを指定しました。

```vue
<!-- ... は省略を示す -->

<template>
...
  <input type="file" v-model="submittedArticle.image" style="display: none;" />
...
</template>

<script>
...
  data() {
    return {
      submittedArticle: {
        title: "",
        description: "",
        image: null
      },
      ...
    }
  }
...
</script>
```

するとVSCodeからnoticeが

![スクリーンショット 2020-03-31 6.51.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583955/17bff88c-9834-75c9-8b85-7b6c665e98a7.png)

`'v-model' directives don't support 'file' input type.`

v-modelはtype="file"をサポートしていない、とのことです。


## 対処法

`@change`を使用して対処しました。
画像をアップロードするとこのtype="file"のinputに変化が生じるので、それを見逃さないようinputに`@change`をつけて監視します。
そして`@change`に画像データを取得するメソッド(下記では`onImageUploaded`)を結びつけることで、画像アップロード時に画像データを取得できるようにします。
あとは画像データを作成・保存するメソッドも作って、それを画像取得後に呼び出します。そこでできたObjectをdata()に格納します。

```vue
<!-- ... は省略を示す -->

<template>
...
  <input type="file" @change="onImageUploaded" style="display: none;" />
...
</template>

<script>
...
  data() {
    return {
      submittedArticle: {
        title: "",
        description: "",
        image: null
      },
      ...
    }
  },
  methods: {
    onImageUploaded(e) {
      // event(=e)から画像データを取得する
      const image = e.target.files[0]
      this.createImage(image)
    },
    createImage(image) {
      const reader = new FileReader()
      // imageをreaderにDataURLとしてattachする
      reader.readAsDataURL(image)
      // readAdDataURLが完了したあと実行される処理
      reader.onload = () => {
        this.submittedArticle.image = reader.result
      }
    },
    ...
  }
...
</script>
```
Mysql2::Error::ConnectionErrorが出たときの解決法

#MySQLエラー発生
PCを再起動した後`rails s`でアプリケーションサーバを起動ようとしたところMySQLエラーが発生しました。

```
Mysql2::Error::ConnectionError
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
```

エラーを見ると「/tmp/mysql.sockを通じてローカルのMySQLサーバーに接続できませんでした。」と書いてあります。

**mysql.sockが無い！？**
sockというのは、ファイルシステムソケットのことで、ローカルシステム内で通信を行う際に、このsockファイルを仲介役にしてMySQLとRuby/Rails間での通信を行っています。
このsockファイルは**MySQLが起動した時に生成され、MySQLが停止すると削除される**ファイルです。

#MySQLエラー解決に必要なこと
MySQLエラーには色々な原因があるので、今起きている問題は何なのか要素を切り分けて考えることが必要です。

１．MySQLサーバーが起動しているか
２．起動に必要な権限があるか
３．ソケットのパスが正しく通っているか
４．ソケットの生成場所が正しく設定されているか
５．MySQLサーバーが複数起動していないか

この記事では１と２の解決方法について解説します。

# 1.MySQLサーバーを起動させる
PCを再起動したときにMySQLが停止してmysql.sockが削除されてしまっています。
なのでMySQLを起動させてsockファイルを生成しましょう。

```
# MySQLを起動
$ mysql.server start
```

###`mysql.server start`でダメなら
原因不明ですがMySQLを起動する権限が現在のユーザーでなくなっていることがあるようです。
この場合でもsudoコマンドを使ってroot権限でMySQLを起動させることができます。

```
$ sudo mysql.server start
```

`Starting MySQL`
`.. SUCCESS! `
と表示されればOKです。

# ２．必要な権限を与える

###権限の確認
１．MySQLのあるディレクトリまで、cdコマンドで移動します。

```
$ cd /usr/local/var
```

２．pwdコマンドで今居るディレクトリを表示して正しく移動できたか確認します。

```
$ pwd
# /usr/local/varと表示されればOKです。
```

３．ディレクトリの状態を確認します。

```
$ ls -l
```

usr/local/varの配下で起動中のプロセスが表示されます。

```
total 0
drwxrwxr-x   4 yamazaki  admin   128  8  7  2019 homebrew
drwxr-xr-x   3 yamazaki  admin    96 11  8 23:22 log
drwxr-xr-x  13 _mysql    _mysql  416  3 19 06:40 mysql
drwx------  25 yamazaki  admin   800  3  5 01:02 postgres
drwx------  24 yamazaki  admin   768 10 30 00:34 postgresql@10
```
mysqlの所だけユーザー名ではなく_mysqlとなっています。

4.chownコマンドでディレクトリの権限を変更させます。

```
$ sudo chown -R [ユーザー名] mysql
```

5.[ユーザー名]の部分に任意のユーザー名を入れます。

```
$ sudo chown -R yamazaki mysql
```

6.変更を確認します。

```
$ ls -l
```

```
total 0
drwxrwxr-x   4 yamazaki  admin   128  8  7  2019 homebrew
drwxr-xr-x   3 yamazaki  admin    96 11  8 23:22 log
drwxr-xr-x  12 yamazaki  _mysql  384  3 21 17:45 mysql
drwx------  25 yamazaki  admin   800  3  5 01:02 postgres
drwx------  24 yamazaki  admin   768 10 30 00:34 postgresql@10
```

権限がユーザーに変更されました。
この状態でMySQLを起動してみましょう。

```
＄　mysql.server start
```
無事起動できればOKです。
Salesforce デバッグログ反映のメモ

デバッグログ取得の際につまづきがちなので。

ユーザ追跡フラグのUSER_DEBUGで時間設定すればデバッグログを取ってくれるが、
USER_DEBUGでデバッグレベルを変更しても変更が適用されない。

この時の解決方法は以下です。
開発者コンソールからDebug→Change Log Levelsを選択し
<img width="449" alt="スクリーンショット 2020-03-31 23.28.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611302/894591e7-df85-9094-fe6f-a0e610358e34.png">
General Trace Settings for Youを設定する
<img width="802" alt="スクリーンショット 2020-03-31 23.29.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611302/d39730da-952a-f569-a015-cc7b17eaeb41.png">
<img width="859" alt="スクリーンショット 2020-03-31 23.29.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611302/ac4766c0-3d6a-3922-6fc1-90298b5091fb.png">

→デバッグログ画面を開くとDEVELOPER_LOGのデバッグレベルが変更されており、
　デバッグレベルの変更が適用されている
LaravelでjQueryを使ってAjax通信する時のURLの書き方は注意！

こんにちは、Web初心者のはるまきです。Qiita初投稿！

LaravelでJavaScriptを記述する時のパスの書き方には少し注意が必要だなと思ったので、メモしておきます。単純な話ですけど:sunny:

<h3>ルーターに合わせてパスを書こう！</h3>

初心者あるあるだとは思うんですが、「お手本通りやってもうごかな〜い！」。私の場合はjQueryのAjax通信が、それでした。お手本のコードはこんな感じでした。

```javascript:hoge.js
$.ajax({
  type: "GET",
  url: "some.php", 他にも[../aaa/bbb/ccc.php]とか
}).done(function( msg ) {
  alert( "データ保存: " + msg );
});
```

htmlでスタイルシートやjsを読み込む時のパスは、「aaa/bbb/ccc.js」のような書き方ですよね。でもphpファイルを読み込む時（？）はどうやら違うようでした。web.phpファイルにあるルートのまま記述すれば、きちんと動きました。jsファイルとルーター(web.php)。

```php:web.php
Route::get('selectedCategoryHoge', 'hogeController@getHogeAnotherhoge');
```


```js:hoge.js
$(function(){
    $('#hoge').click(function dojQueryAjax() {
        $.ajax({        
            url:'selectedCategoryHoge',
            type:'GET',
        }).done(function(data){
            //省略
        }).fail(function(data){
            //省略
        });
    });
});
```

URLはルーターさんに従おう！
以上になります。何かご指摘点があれば是非よろしくお願いします！

今回、生まれて初めて、hogeってヤツを使いました。fuga,piyo,foo,barとかも使ってみたい。。
最後まで読んで頂きありがとうございました。
簡単セットアップのための dotfiles のススメ

# はじめに

`.vimrc` や `.zshrc` など、設定ファイル、いわゆる dotfiles を git で管理している方は多いと思います。ですが、それらのファイルは簡単にインストールできるでしょうか。マシンが変わると、手動でコピーするのは面倒だと感じませんか？　この記事では、簡単にインストールできる dotfiles の書き方について説明します

# やるべきこと

## dotfiles は github で管理する

言うまでもありませんね。これにより、ネットワークにアクセスできる PC であれば同じファイルにいつでもアクセスできます。

## ファイルはシンボリックリンクで配置する

不便だなと感じたとき、こうすればよいのではと思いついたとき、新しい言語を初めてシンタックスハイライトを入れたいときなど、dotfiles は頻繁に変更しますし、生産性を上げるためにも頻繁に変更するべきです。しかし、いちいちコピーしていると、面倒に感じてしまい、あるいは変更をやらなくなってしまいます。

シンボリックリンクにすることで、変更しやすくなり、また git へのコミットが簡単になります。手動でコピーしていると、実際のファイルと github のファイルが乖離することも多く、せっかく github に置いた意味がなくなってしまいます。

## コマンド一つでインストールできるようにする

dotfiles も数が多くなってくると、シンボリックリンクを手動で設定するのは大変です。大抵のファイルは `$HOME` に置くことになるので、専用ディレクトリをつくり、その中のファイルすべてのシンボリックリンクを作成するスクリプトを書きましょう。

## 短く覚えやすい URL でダウンロードできるようにする。

まず、自分用のドメインを取りましょう。多少のお金はかかりますが、ドメインを持っていると何かと便利です。

そして、そのドメインにスクリプトを置き、ダウンロードして実行するだけでセットアップできるようにしましょう。

# 私の dotfiles 構成

そうは言っても具体的にどうすればいいのか分かりづらいと思うので、私の dotfiles について解説します。

リポジトリは https://github.com/zakuro9715/dotfiles です。

home ディレクトリにあるファイルとサブディレクトリは、自動的にホームディレクトリにシンボリックリンクが張られます。xdg_home は ~/.config 内です。

インストールスクリプトには bootstrap.ts と install.zsh があります。bootstrap.ts ではシンボリックリンクを貼ったり、go のパッケージをインストールしたりし、install.zsh では deno のインストールなどを行ったあと bootstrap.ts を呼び出します。

`https://za.kuro.red/install.zsh | zsh` というコマンド一つで、私の使っている環境のほぼすべてがインストールできます。もちろん、私以外の人でも使えます（もっとも、環境がかなり特殊なので、私以外に便利に感じる人はいないでしょうが）。

5 年間継ぎ足してきたこの dotfiles にはかなり限界が来ており、現在リファクタリング中です。もともとは bootstrap も zsh だったのですが、あまりにカオスだったので deno と ts で書き直しました。

また、それほど支障はないものの、微妙に壊れている箇所がいくつかありますし、zsh と git だけは手動でインストールする必要がありますし、未だにあとから apt 等からインストールすることも多いので、それを自動化するのが課題です。

また、仕組み自体は構築したのですが、`.vimrc` や `.zshrc` など、設定ファイル自体は非常にカオスになっています。これもいつかはリファクタリングしたいところです。

# さいごに

自分の環境をいつでも再現できると、OS を簡単に壊せるという安心感があり、とても便利です。ある日突然 PC が壊れても、ハードウェアさえ調達できれば環境構築は一瞬で終わります。

みなさんも、コマンド一つでインストールできる dotfiles を作ってみてはどうでしょうか。
Azureを新規開始したらサイズの選択ができず仮想マシン(VirtualMachine)が作成できない場合の対応（2020年3月時点）

最近、顧客にAzureを提案する必要が発生し、
学習のためにAzureのアカウントを新規に作成しました。
その際に、Azureで仮想マシン(VM)が作成できない状況となり、
苦戦しました。
新規のAzureユーザが同じ苦労をしないために、本件記事にしました。

#事象
Azureのアカウントを新規に作成して、
まずは仮想マシン(VM)を作成しようとしました。
「VMサイズの選択」画面を表示すると、
以下の通りすべてのサイズが非活性になっている状況でした。

![VMサイズの選択画面_加工.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561572/016579f4-f7f0-4aea-50af-1d06d9094a0b.png)

#調査：設定の確認
このアカウントは全く設定を実施していない状況でした。
ただし、その前にマイクロソフトのe-ラーニングを実施しており、
その際にe-ラーニング用のサブスクリプションを使用していたので、
間違えて自分の本番用のサブスクリプションに設定を実施したことを疑いました。
その為、ネット情報等を駆使して一通り設定を確認しました。
結果として、私が誤って新規設定したことはない、との認識となりました。

#切り分け：サブスクリプションの昇格
サブスクリプションは当初1か月間の「無料試用版」でした。
権限の問題のように思われたので、切り分けの為に「無料プラン」に
切替を実施してみました。
「無料プラン」でも12か月、一部サービスが無料枠で利用可能です。
しかし、「無料プラン」に切り替えても、「VMサイズの選択」は
非活性の状況でした。

#問合せ：マイクロソフトサポート利用を検討する
万策つきて、マイクロソフトサポートに問合せすることとしました。
私は無料の「BASIC」プランなのでテクニカルサポートは受けることができません。
テクニカルサポートを受ける場合は、DEVEROPERに昇格する必要があります。
ただし、DEVEROPERはサポート代として月3,000円が必要になります。
結果としてマイクロソフトが推奨するコミュニティに行って同件調査を
実施したのですが、アカウント作成当初に同じような問題が発生した
情報は見つかりませんでした。

![Azureサポート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561572/0a48f551-30fa-fce0-466b-7daa8dba35bb.png)
※参考※
[Azureサポートプランの比較](https://azure.microsoft.com/ja-jp/support/plans/)

#問合せ：マイクロソフトサポート利用する
マイクロソフトサポートでは、BASIC（無料）でも
「サブスクリプションの問合せ」
は受け付けてもらえるとの記載がありました。

今回、明らかに当初のサブスクリプションに問題があると思われたので、
ダメ元で「新しいサポートリクエスト」から、
サブスクリプションの問題として問合せを実施しました。
全く仮想マシン機能が使えない状況だったので深刻度は「A」としました。
![新しいサポートリクエスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561572/e2415bce-85de-3b86-33c4-cce1e9cd424b.png)

#問合せ：マイクロソフトサポートの対応について
登録すると朝の5：00頃でしたがマイクロソフトから電話がありました。
まずは緊急性を確認するための電話です。
会話した結果、技術担当に緊急度「A」で伝えるとのことでした。

その後、通勤中の7:00～8：00に2回電話がかかってきました。
2度とも電車の中だったため電話に出れず、電話を折り返しても
「技術担当者の内線番号を入力してください」とメッセージが
流れるのですが、内線番号を知らないので接続できない状況でした。
あとからAzureのサポートリクエスト画面で確認すると、
「2度連続で電話に出れなかったため緊急性をA→Bに格下げしました」
とのことでした。
また、内線番号は、有償契約しているユーザのみが使えるそうで、
私は無償での問合せだったので、そもそも折り返しができない状況でした。

その後、16：00頃に再度電話がありました。
サポートからは、
「お客様の環境は制限がかかっておりリソースが使用できない状況です。
　VMで作成したいサイズと利用したいリージョンを教えてください。
　5営業日以内に対応します。」
との話がありました。
どうして新規開始してVMが全く作成できないような制限がかかって
いるのかについては、回答をもらえませんでしたが、
西日本、東日本の2つのリージョンでB4msサイズを使いたいと伝えました。
また、その後サポートページを確認すると、緊急性はB→Cに格下げされていました。

#問合せ：マイクロソフトサポートの対応結果について
数日後、サポートからの回答がありました。

「リージョン制限解除のお手続きを行っておりましたが、
　担当部署より東日本リージョンはお客様の需要が非常に高いため、
　リージョン制限解除を承認することがむずかしいと回答がございました。
　​​そのため、ご要望であった西日本リージョンにて仮想マシンを
　ご利用していただけますと幸いです。」

上記のとおりです。
コロナの影響で利用者が増えて、リソースが枯渇しているのでしょうか？

実際に画面で確認するとB4msまでは活性化されて利用可能となっています。

![画面20200331_VM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561572/77c424b8-1bbe-71a0-c529-4b207f28a8db.png)

1週間色々と試行錯誤しましたが、やっと私のAzureライフが始まりました。


#まとめ
Azure初心者にこのリソース制限はハードル高いと感じました。
普通は、最初から仮想マシンが作成できると思うので・・・・。

私と同じように最近になってAzureを利用しはじめて、
同じ問題に直面して悩んでいる方がいるかもしれないと思い、
今回記事にしてみました。

一助になれば、幸いです。
初心者によるプログラミング学習ログ 277日目

#100日チャレンジの277日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
277日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>277日目<br>・xdデザインカンプからのサイト模写<br>・FLOU設計<br>・sass、git<br>・お問い合わせフォーム作成<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1244717235219775488?ref_src=twsrc%5Etfw">March 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
MySQLのAES_ENCRYPTで暗号化したデータのサイズを計算する

MySQLのAES_ENCRYPTで暗号化を試す機会があり、暗号化後のデータ長を試算したときのメモ。

# 環境
- MySQL5.6

# 想定ケース
- aes-256-cbc
- AES_ENCRYPT関数で暗号化した値はHEXで16進数へ変換
- 初期化ベクトルはRANDOM_BYTES(16)で生成し、HEXで16進数へ変換して暗号化した値に付加 
- 文字コードはutf8

# 計算
MySQLの[公式リファレンスマニュアル](https://dev.mysql.com/doc/refman/5.6/ja/encryption-functions.html#function_aes-encrypt)によると、暗号化後の長さは以下の式で計算できるとある。

```
16 * (trunc(string_length / 16) + 1)
```

今回は暗号化したバイナリの値をHEXで16進数へ変換するので2倍し、
さらに同じく16進数へ変換した初期化ベクトルを付与するので16*2を加算する。

```
16 * (trunc(string_length / 16) + 1) * 2 + 16 * 2
```

string_lengthは、文字数 * 1文字のbyte数で計算。

# 検証
平文「あいうえおかきくけこさしすせそ12345678901234567890」を暗号化。
期待値：16 * (trunc((15 * 3 + 20) / 16) + 1) * 2 + 16 * 2 = 192

```
mysql> SET @iv=RANDOM_BYTES(16);
Query OK, 0 rows affected (0.00 sec)

mysql> select CHAR_LENGTH(CONCAT(HEX(@iv), HEX(AES_ENCRYPT('あいうえおかきくけこさしすせそ12345678901234567890', SHA2('password',512), @iv)))) as length;
+--------+
| length |
+--------+
|    192 |
+--------+
1 row in set (0.00 sec)
```

# 参考
[MySQL 5.6 リファレンスマニュアル - 12.13 暗号化関数と圧縮関数 - AES_ENCRYPT](https://dev.mysql.com/doc/refman/5.6/ja/encryption-functions.html#function_aes-encrypt)
コロナウィルス(コロナウイルス)の死亡率に関するBBC記事

日本のデータサイエンティストの方々は、必死でコロナをアナライズしているのかしら。
この未曾有の国難に。

[この記事](https://www.bbc.com/news/health-51674743) の英語初心者による和訳、翻訳。

**死亡率が0.5-1.0%と言うのは低いように見えるかもしれないけれど、風邪か、それ以上に感染力が強いウイルスの死亡率なので、全く低くはない。**

**風邪をひいたら(症状が出たら)10%の確率で死にます、と言う感覚かな。**

# コロナウィルスで死亡する確率。

By Robert Cuffe
Head of Statistics

2020/3/24

**英国政府の科学アドバイザーはコロナウィルス に感染した場合の死亡する確率を0.5%-1.0%の間だと見積もっている。**

この確率は確認されている確率(WHOで4%, 英国で5%)より小さい。
小さい理由は全ての感染を検査で検知しているわけではないためである。

各国、検査対象について独自の基準を持っている。
そのため、各国の死亡率を横並びに比較するのは、ミスリーディングである。

そして、死亡率は、年齢、基礎疾患、医療サービスへのアクセスの容易性、によっても変化する。

## 年齢による死亡率の変化

![death rates depents on age group](https://ichef.bbci.co.uk/news/624/cpsprodpb/664E/production/_111409162_corona_cases-nc.png)

### 私のような人の危険性は？

年配であったり、不健康である場合、コロナウィルスに感染した場合、より死亡する確率は大きくなる。

Imperial College London(ICL) の今のところの見積もりでは、40歳未満では、平均の1/10程度、
80歳以上で平均の10倍程度の死亡率の変化がある。

英国政府の医療アドバイザー長であるChris Whitty教授によると、高齢者の死亡率は確かに高くなるが、
重症には至らない場合も多い。

彼によると、若年層も油断するべきではないとのことである。
若年層でも集中治療室で死に至るケースも存在する。

死亡率を左右するファクターは年齢だけではない。

中国の44,000以上のケースでは、基礎疾患があることにより、少なくとも5倍程度、死亡率が高まる。
(高血圧、心疾患、呼吸器疾患など)

以上の様々なファクターが相互に作用しており、まだ全容は解明していない。

それに、把握済みのケースにおける死亡の傾向が分かっても、それを全てのケースに適用できるわけではない。

## 基礎疾患による死亡率の変化

![death rates depend on underlying health](https://ichef.bbci.co.uk/news/624/cpsprodpb/14F1/production/_111416350_death_ratio_v2-nc.png)

- cardiovascular: 心疾患
- diabetes: 糖尿病
- respiratory disease: 呼吸器疾患
- High blood pressure: 高血圧

### 把握済みのケースの死亡率は、感染した場合の死亡率ではない

多くの場合、ウィルスの感染はカウントされない。なぜなら、症状が重くない場合、多くの人は病院に行かない。

3/17, 英国の科学アドバイザー長, Sir Patrick Vallanceは英国で55,000程度の感染があると見積もった。
その際の把握済みのケースは2,000であった。

死亡数の母数を2,000にするか55,000にするかで、死亡率は大きく異なる。

![most cases are never counted](https://ichef.bbci.co.uk/news/624/cpsprodpb/581F/production/_111095522_deaths_in_china_v2_x2_640-nc.png)

これが、把握済みのケースの死亡率があまり意味をなさない理由である。把握していないケースにより、大きく見積もってしまうのだ。

しかし、別の撹乱要因がある。コロナウィルス感染者が、別の理由で死亡した場合、少なく見積もってしまうことになる。

## 国によって死亡率が異なる理由は？

Imperial Collegeの研究によると、国によって、重症者を検査対象にする場合もあれば、軽症でも検査する場合もある。

国によってウィルス検査の方法が異なり、さらに検査対象の実施可能数や実施するかどうかのルールも異なる。
それに時間が経過すると、上記のファクターについても、変化していく。

英国政府は当初10,000件/日の検査を準備し、4週間で25,000件/日にまで増やしていく計画を立てている。
このキャパシティが現状の検査数のボトルネックとなっている。


ドイツでは20,000件/日以上の検査キャパシティがある。軽症でも検査する方針を立てている。

つまり、ドイツの死亡率は、上に示した症状ピラミッドの図の異なる部分を切り取ったものになる。

ドイツの確認済みのケースの死亡率はヨーロッパで一番小さい。しかし、検査対象が変われば上昇するかもしれない。

予後についてもまた、提供されている医療の質によって変化する。

そして、エピデミックのステージによって、医療の質は変化する。

医療システムがエピデミックで急増するケースに対応しきれなくなると、死亡率は上がる。

## 本当の死亡率に対する科学者のアプローチ

科学者は上記の設問に対する個々のエビデンスから、死亡率についての一枚絵を組み立てる。

例えば、科学者は症状の度合いの割合を、ある小さなグループを観察することから、見積もる。
送還された飛行機の乗客などが、小さなグループの一例である。

しかし、個々のエビデンスの値が少し変わることによって、最終的な一枚絵は大きく変わる。

そしてここのエビデンスは常に変化している。

Paul Hunter(the University of East Anglia教授)は、死亡率は上昇も下降も起こり得ると指摘する。

「エボラの場合、時間の経過とともに、対処法が向上し、死亡率が下がった。』
しかし、死亡率が上がることもある。
『医療システムが枯渇すると、死亡率は上がる。』

ゆえに、科学者は見積もった死亡率と共に、上限と下限の死亡率をしめす。
mysqldumpでDB移行した際のコマンド

先日、ステージング環境がAmazon EC2からGCEへ移行されました。その際、データベースの移行をしたので手順を書いていきます。

## EC2にssh接続
```terminal
$ ssh -i 使用する鍵のパス ユーザ名@接続先のIPアドレス

例)
$ ssh -i ~/.ssh/hoge.pem ec2-user@xx.xx.xx.xx
```

## DBをdumpする
ssh接続ができたら

```terminal
[ec2-user@ip-xxx ~]$ mysqldump -u ユーザー名 -p -h DBホスト DB名 > 保存したいファイル名

例）
[ec2-user@ip-xxx ~]$ mysqldump -u hoge -p -h hoge.rds.amazonaws.com  hoge_staging > hoge_staging.dump
```
そしてパスワードを聞かれるのでパスワードを入力すればdumpファイルがEC2上に作成されます。ここまでできたらEC2からはログアウトしてください。
ユーザー名等は自分のDB設定ファイルを参照してください。Railsならdatabase.ymlです。

## EC2上に作成したdumpファイルをローカルへコピー
```terminal
$ scp -i 使用する鍵のパス ユーザ名＠接続先のIPアドレス:EC2上のコピー元のファイルのパス ローカルのコピー先のパス

例）
$ scp -i ~/.ssh/hoge.pem ec2-user@xx.xx.xx.xx:/var/www/foo/bar/hoge_staging.dump /Users/mishikun/workspace/
```

これで、EC2上で作成したdumpファイルを手元のPCのworkspace配下まで持ってくることができました。次は移行先のGCEにこのファイルを持っていきます。

## 移行先ににdumpファイルを送信
sftpを使って送信します。

```terminal
$ sftp -i 使用する鍵のパス ユーザ名@接続先のIPアドレス
```
sftpができたらputコマンドでローカルにあるdumpファイルをGCEに送ってあげましょう。場所は適当です。私はホームディレクトリに送信しました。

## GCEにssh接続
GCEにssh接続します。コマンドは上記と同様なので割愛させていただきます。

## 移行先DBにdumpをインポート
```terminal
[xxx@xxx ~]$ mysql -u ユーザ名 -p -h DBホスト dumpをインポートしたいDB名 < dumpファイルのパス

例) 
[xxx@xxx ~]$ mysql -u hoge -p -h xx.xx.xx.xx hoge_staging < ~/hoge_staging.dump
```

これでDBの以降は完了です✌️
もし間違い等があればご指摘のほどよろしくお願いします。

## 参考
[MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.5.4 mysqldump — データベースバックアッププログラム](https://dev.mysql.com/doc/refman/5.6/ja/mysqldump.html)
[scpコマンド チートシート - Qiita](https://qiita.com/rock619/items/2bbbe379ae0fdd2ae00f)
WebMとWebAからmp4をつくる

## ffmpegでいけた
おぼえがき。

- ffmpegを落としてきてパス通す → https://www.ffmpeg.org/
- ↓のバッチファイルを作成
- 作ったバッチにWebMファイルとWebAファイルをD&D → WebMのファイル名.mp4が生まれる

```shell:webm2mp4.bat
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
chcp 65001
cls

SET tmpMovieSrc="%1"
SET tmpAudioSrc="%2"

IF "%tmpMovieSrc%"=="" (
    GOTO :missingArgs
)
IF "%tmpAudioSrc%"=="" (
    GOTO :missingArgs
)
IF not "%3"=="" (
    GOTO :missingKinds
)

IF "%~x1"==".webm" (
    SET movieSource="%1"
    SET fileName=%~n1
) ELSE IF "%~x1"==".weba" (
    SET audioSource="%1"
) ELSE (
    GOTO :missingKinds
)

IF "%~x2"==".webm" (
    SET movieSource="%2"
    SET fileName=%~n1
) ELSE IF "%~x2"==".weba" (
    SET audioSource="%2"
) ELSE (
    GOTO :missingKinds
)

IF %movieSource%=="" ( GOTO :missingKinds )
IF %audioSource%=="" ( GOTO :missingKinds )

SET outputPath="%~dp0%fileName%.mp4"
SET /P ANSWER="変換を実行します。よろしいですか (Y/N)？"

IF /i {%ANSWER%}=={y} (GOTO :yes)
IF /i {%ANSWER%}=={yes} (GOTO :yes)

EXIT
:yes

SET CONTINUEANSWER=n
IF EXIST %outputPath% (
    SET /P CONTINUEANSWER="すでにファイルが存在します。上書きしてよろしいですか (Y/N)？"
    IF /i {!CONTINUEANSWER!}=={y} (GOTO :continueYes )
    IF /i {!CONTINUEANSWER!}=={yes} (GOTO :continueYes )
    EXIT
)

:continueYes

IF EXIST %outputPath% ( del %outputPath% )

ffmpeg -i %movieSource% -i %audioSource% -c:v h264_nvenc -c:a aac -map 0:v -map 1:a %outputPath%

echo 完了しました！
pause>nul
EXIT

:missingArgs
echo 動画ファイルと音声ファイルをまとめてドラッグアンドドロップしてください
pause>nul
EXIT /b 1

:missingKinds
echo .webmと.webaファイルをひとつずつドラッグアンドドロップしてください
pause>nul
EXIT /b 1
```

ダサいコードは見ないふりで。
キモはこの部分。

`ffmpeg -i %movieSource% -i %audioSource% -c:v h264_nvenc -c:a aac -map 0:v -map 1:a %outputPath%`

| 引数 | 意味 |
| :---: | :---: |
| -i %movieSource% | インプットに movieSource(WebM) を指定 |
| -i %audioSource% | インプットに audioSource(WebA) を指定 |
| -c:v h264_nvenc | 変換後動画フォーマットに h264_nvenc を指定<br>(グラボ使えないなら h264 にかえる) |
| -c:a aac | 変換後音声フォーマットに aac を指定 |
| -map 0:v | 0番目のインプット(WebM)の映像ストリーム<br>全てを変換後の映像ソースに割り当て |
| -map 1:a | 1番目のインプット(WebA)の音声ストリーム<br>全てを変換後の音声ソースに割り当て |
| %outputPath% | 出力先を指定 |


## 参考にさせていただいた神記事
- [ffmpeg で動画の音声を差し替える](https://homemadegarbage.com/ffmpeg-audio-change)
- [FFmpegで動画編集をするガイド](http://moriyoshi.hatenablog.com/entry/2015/12/17/224127)
PythonでRiccati代数方程式の解法を実装する

# Riccati代数方程式(ARE)とは
以下の式。ただし$A,Q,P\in \mathbb R^{n\times n},B\in \mathbb R^{n\times m},R\in \mathbb R^{m\times m}$であり、Q,Rは正定値対称行列とし、$A,B,Q,R$が与えられ$P$を求める。

$$
A P + P A^T + Q - P B R^{-1} B^T P = 0
$$

## AREが出てくる場面
現代制御理論のLQRでゲインを求める際に出てくる。LQRとは最適制御理論で、システムが
$$
\frac{dx}{dt} = Ax+Bu
$$
と表すことができるとき、$\min J=\int (x^TQx +u^TRu) dt$を満たす制御則は上のRicati代数方程式を満たす$P$を用いて
$$
u=-R^{-1}B^TPx
$$
と書けるという話。

# 解く
## 方針
有本・ポッターの方法（次項で解説）を実装して解くこととする。その際行列の固有値問題を解くことになるが、これはnumpyなどを用いる。

## 有本・ポッターの方法
手順を説明する。証明は書籍などを参照。
### 1.行列を置く
ハミルトンマトリクスと呼ばれる行列$H\in \mathbb R^{2n\times 2n}$を

$$
H=\left[ \begin{array}{cc} A^T & -B R^{-1} B^T \newline -Q & -A \end{array} \right]
$$

とおく。
### 2.ハミルトンマトリクスを固有値分解
Hの固有値には実部が負であるものがn個存在する。これを$\lambda_1,\lambda_2,...,\lambda_n$と置き、対応する固有ベクトルを$\vec w_1,\vec w_2,...,\vec w_n$とする。
### 3.固有ベクトルを並べて分割した行列を置く
これを用いて$Y,Z\in \mathbb R^{n\times n}$を
$$
\left[ \vec w_1 \vec w_2 ... \vec w_n \right] = \left[ \begin{array}{c} Y \newline Z \end{array} \right]
$$
とおく。
### 4.Pが求まる
$$
P=ZY^{-1}
$$

## 実装
```python
import numpy.linalg as LA

def solve_are(A, B, Q, R):
    # 1. ハミルトンマトリクスを置く
    H = np.block([[A.T, -B @ LA.inv(R) @ B.T],
                  [-Q , -A]])
    # 2.固有値分解する
    eigenvalue, w = LA.eig(H)
    # 3.補助行列を置く
    Y_, Z_ = [], []
    n = len(w[0])//2
    # 固有値をsortしておく
    index_array = sorted([i for i in range(2*n)],
        key = lambda x:eigenvalue[x].real)
    # 実部が小さいものからn個を採用する
    for i in index_array[:n]:
        Y_.append(w.T[i][:n])
        Z_.append(w.T[i][n:])
    Y = np.array(Y_).T
    Z = np.array(Z_).T
    # 4.Pが求まる
    if LA.det(Y) != 0:
        return Z @ LA.inv(Y)
    else:
        print("Warning: Y is not regular matrix. Result may be wrong!")
        return Z @ LA.pinv(Y)
```

## テスト
### テストコード
```python
A = np.array([[3., 1.],[0., 1.]])
B = np.array([[1.2], [1.]])
Q = np.array([[1., 0.2], [0.2, 1.0]])
R = np.array([[1.]])
P = solve_are(A, B, Q, R)
print("P")
print(P)
print("Riccati代数方程式の左辺")
print(A@P + P@A.T + Q - P@B@LA.inv(R)@B.T@P)
```

### 結果
```
P
[[ 69.20010326 -66.19334596]
 [-66.19334596  67.7487967 ]]
Riccati代数方程式の左辺
[[-1.13686838e-13  5.11590770e-13]
 [ 2.55795385e-13 -5.68434189e-13]]
```
解けました。

### 追記
コメント欄で「ハミルトンマトリクスが固有値に0をもつ場合にYが正方行列にならず実行時エラーが出る」という事象をご指摘をいただきました。とりあえず実行時エラーが出ないように変更したのですが、数学的な背景を理解していないためこの実装で正しい解が出るのかはわかっておりません。どなたかコメントをいただければ幸いです。
OAuth2RestTemplateでClientHttpRequestInterceptorの設定を入れたい場合（Bean定義）

# SpringBootばかりでXMLConfigurationのサンプルがない！

SpringBootがメインになってくると`Configuration`クラスを作成して`Annotation`ベースで定義する場合が多いと思いますが、SpringMVCの場合はどうやって書いたらいいねん！で検証してみたので。

結論からいうと以下

```xml:applicationContext.xmlまたはspring-security.xmlまたはoauth-client.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://www.springframework.org/schema/security"
    xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
    xsi:schemaLocation="
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
    ">

  <!-- client, resourceなどは省略 -->

  <oauth2:rest-template id="oauth2RestTemplate" resource="grantResource" access-token-provider="tokenProvider">
    <property name="interceptors">
        <list>
          <ref bean="requestResponseLoggingInterceptor" />
        </list>
    </property>
  </oauth2:rest-template>
```

xsdの見方がわからず1時間ほどやられた、、、

`@Bean`の書き方は思い出したら書くかも
初めてのSpring案件を終えたメモ ～MVC編～

#はじめに
ピュアJavaとDBの基本知識のみスタートからのSpring案件が波乱の末ひと段落したので、所感や覚書などを。
記事の内容としてはチュートリアル以上、実践未満のイメージ。:speech_balloon:
掲載コードは動作確認できていないのであくまで参考で。:pray:
英語は目が滑るので日本語多様してる、許して。:pray::sob::pray:

#開発環境
RedHat(開発環境はCent)7系
Java8
SpringBoot2.1.6
MySQL8系
STS

#MVCについて
ロジック（Model)と、画面（View)とそれを繋ぐコントローラ（Controller)に分けて設計しましょう、という理解。
でもSpringではViewとControllerでやりとりするデータのことをModelと呼んでいる。
自分がそもそもMVCを理解できていたか不安になったけど、言葉の定義はフレームワークごとに異なるので深く考えるのはやめた。:innocent:
https://qiita.com/yo1000/items/a6acbf5f454a7f53aef9
https://qiita.com/takasek/items/70ab5a61756ee620aee6

#コントローラー
**・マッピング**
メソッドには`@GetMapping("test")`とかをつける。`@RequestMapping("/test")`は古いみたい。

カッコの中に記述するのは属性と呼ぶらしい。上記は`@GetMapping(path="test")`の省略。
１つのformタグに複数ボタンを配置してPOSTしたいとき、htmlでnameを指定すると、コントローラーのparams属性とマッピングできる。

```html:view.html
<form method="POST" action="path1">
    <input type="submit" name="param1" />　←こちらを押す
    <input type="submit" name="param2" />
</form>
```

```java:controller.java
@PostMapping(path="path1",params="param1")
```

**・バリデーション**
Springの機能として提供されてる。
`BindingResult`の操作ができると、フレームワークに縛られないバリデーションが実装できる。
でもアノテーションやカスタムバリデーションを駆使すればほとんどのことはできそう。
https://qiita.com/yakumo3390/items/4e47930ba643b45b7430

メッセージは messages.properties で埋め込み文字や多言語対応も提供してるけど、メッセージをDB管理する要件だったので使えなかった。

グループ属性をつけると、バリデーション対象を指定したり外したりできる。
これのために空のクラスを作ったけど、もっとスマートな方法があるんじゃないかという気持ち。
https://tech.asoview.co.jp/entry/2019/12/11/104928

**・return**
基本はViewのPathをあらわす文字列。
redirectやforwardもある。
redirectのときは`RedirectAttributes`に値を詰め込めば遷移先に届く。
http://www.ne.jp/asahi/hishidama/home/tech/java/spring/boot/web/Controller.html#h_forward_attribute

オブジェクトを渡すときは`toString()`が実装されていればそのまま渡せる、そうでないときはひと手間いるみたい。
https://grandbig.github.io/blog/2016/05/28/redirect-parameter-spring-boot/

#ビューについて
thymeleaf（タイムリーフ）を使用。読みもスペルも難しい。:kissing:
いわゆるテンプレート。画面だけでなく、生成されるhtmlを確認しておかないとカッコワルイ記述になってたりするので注意。

th:fieldは便利だけどnameやidを指定したいJavaScriptとかと組み合わせるとき使えないこともある。
何をしているか理解しておくといいかも。
https://qiita.com/beeeyan/items/5bd820e55cb53f176b3e

JavaScript内で変数を使うときは慎重に。
例外が発見しにくいのと、オブジェクト丸ごと使うとhtml上に全て展開されてセキュリティ的に良くないし、見たときびっくりする。
[公式ドキュメント 12.2 スクリプトのインライン処理 (JavaScript と Dart)](https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html#%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E5%87%A6%E7%90%86-javascript-%E3%81%A8-dart)

#サービスについて
ビジネスロジックを書くところ。

今回は原則１テーブルに対して、１つのサービスを作った。あと汎用クラスをいくつか。
DBへアクセスできる層を絞るのが目的だったけど、そうすると１つのクラスが膨れ上がってしまった。:frowning2:
１画面に対して１つのサービスを作って、DBから取得したデータの加工までRepositoryで行うのがいいのかも。
もしくは、１つの画面に対するロジックを記述する層を追加するか。。。？:confused:
![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468958/72a6dfd5-0a1f-88b2-58bd-686df67bfa06.png)

#他のメモ
[初めてのSpring案件を終えたメモ ～Springとは編～](https://qiita.com/FujiwaraKenta777/private/46aeb3fd127ee3b48811)
[初めてのSpring案件を終えたメモ ～データベース編～](https://qiita.com/FujiwaraKenta777/private/e1cc9240f50edcda0ebc)
初めてのSpring案件を終えたメモ ～Springとは編～

#はじめに
ピュアJavaとDBの基本知識のみスタートからのSpring案件が波乱の末ひと段落したので、所感や覚書などを。:speech_balloon:
記事の内容としてはチュートリアル以上、実践未満のイメージ。

#開発環境
RedHat(開発環境はCent)7系
Java8
SpringBoot2.1.6
MySQL8系
STS

#Spring Framework について
 10年もののフレームワークで、大体のことができる、つまり、ごちゃごちゃしてる。
 情報を入手するときは書籍にせよネットにせよ、鮮度を確認する。
 特に設定に関して、XML地獄からはすでに解放され、アノテーションやapplication.propertiesに記述できることが多い。
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html

#application.propertiesについて
 後から知った application.yml のほうが見やすそう。
 設定できるものは↓。暇なときにざっと眺めておくといい、ざっと。
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html

application.propertiesは環境によって切り替えることができる。
コマンドラインから実行するときは --spring.profiles.active 
https://qiita.com/NagaokaKenichi/items/fd9b5e698776fe9b9cc4
STSから実行するときは
![propatiese.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468958/1106b725-b176-0fa7-b6e2-131d46e552bd.png)
奥深いので、ひねった使い方するとハマりそう。シンプルにいこう。:unamused:
https://blog.tagbangers.co.jp/ja/2019/07/12/how-spring-deals-with-properties

# Springで作成するWEBシステムの構成
MVCでDIでAOPな設計を提供している。
それぞれ頭の中で構成図をイメージできるようにしておくと設計やバグ探しのとき役立つ。
リスナーやカスタムバリデーションの実装とか、テストコードの環境とかで、なるほどなぁってなる。
https://qiita.com/kazuki43zoo/items/757b557c05f548c6c5db

#DIについて
結局「コントローラーとDB関連クラスはDI対象にする」くらいの理解。
`@Autowired`していたけど良くないみたい。今はコンストラクタインジェクションを使用するのが主流らしい。
https://qiita.com/jackazu/items/aead50c699fefe56c120
意識しないといけないのは、`@Controller` とかつけるとSpringがDI対象と判断して勝手にインスタンス化するので`new HogeController()` とかしない。nullになるので。

DI対象のインスタンスはシングルトン。
設定によって変えられるらしいけど、変えなければいけないと思ったら設計のほうを疑うべし、らしい。
コントローラーのメンバ変数にユーザの情報を保持したら**別のユーザにどんどん書き換えられちゃった**。:laughing:

#他のメモ
[初めてのSpring案件を終えたメモ ～データベース編～](https://qiita.com/FujiwaraKenta777/private/e1cc9240f50edcda0ebc)
[初めてのSpring案件を終えたメモ ～MVC編～](https://qiita.com/FujiwaraKenta777/private/8c7a8d644f8187d870bf)
チーム開発（本番環境にて表示されないエラー）

ローカル環境
https://gyazo.com/810fa1a24a683af0f8c97c28a2a59181
本番環境
https://gyazo.com/c1370b4a266235edfa3576300c37922d

config/environments/production.rbの記述変更
config.consider_all_requests_local       = false
下に変更
config.consider_all_requests_local       = true


もう一つ
https://gyazo.com/a66bd181590787042adc1bc86145a3ec
動画みたいに表示できなかった
参考にしたサイト
https://kanoe.studio/archives/791

config.assets.compile = false
下に変更
config.assets.compile = true

全ての作業記述変更の際マスターブランチにてcommit pushしてからbundle exec cap production deploy
[devise]現在ログインしているユーザ名が表示されない場合の解決策

#環境
|       |バージョン|
|:----------------:|:-----------------:|
|ruby       |2.6.5|
|rails       |5.2.4.2|
|devise       |4.7.1|

# 目標
現在ログインしているユーザの名前を表示させたい。

# 問題
[@yasuno0327](https://qiita.com/yasuno0327)氏が公開していた[devise にusername カラムを追加し、usernameを登録できるようにする。](https://qiita.com/yasuno0327/items/ff17ddb6a4167fc6b471)を参考にして実装したところ以下のようなエラーを吐いた。

```:Error
undefined method `username' for nil:NilClass

(意訳)
NilClassのnilオブジェクトに`username`メソッドは定義されてないよ
```
# 解決策
```:_current_username.html.erb
<% if user_signed_in? %>
　　<!-- 変更前-->
　　<%= @user.username %>
    <!-- 変更後-->
    <%= current_user.username %>
<% end %>
```

# 解決に至るまでに引っかかったこと
## 1.エラー文はどういう意味を指しているのか？
どうやら、__@userがnilになっている__ことを指しているらしい。
>参考
>>https://qiita.com/gonzaemon111/items/a6d9f3ad0645037125c2

## 2.@userがnilになっているのは何故？
インスタンス変数のスコープ外だから値が参照されない？
``(正直、理解があやふやです。自分なりにかみ砕けたら、追記なり修正なり行います。)``
### [復習]各変数のスコープについて
|種別      |説明|文法|
|:------:|:----------:|:----------:|
|ローカル変数       |それぞれのメソッドの中だけで存在しており、メソッドの処理が終了すると失われてしまう変数です。|通常の変数通り|
|インスタンス変数 |インスタンスに属する変数で、インスタンスの中からであれば、どのメソッドからでも参照・変更できます。インスタンスごとに作られる変数ですので、インスタンスごとに違う値を保持しています。インスタンス生成後、最初に代入された時点で生成されますが、メソッド内でしか生成できませんので、注意が必要です。|変数名の前に「@」|
|クラス変数|クラスで共通の変数として生成されますので、同じクラスから生成されたインスタンスすべてで共通の値を持つことになります|変数名の前に「@@」|
|クラスインスタンス変数 |クラスメソッドからのみアクセスできる変数で、メソッド内ではなく、クラス定義内に定義しなければいけません。クラスが定義されると同時に生成され、クラス変数同様、1つのクラスで共通の値を持っています|変数名の前に「@」|

>引用
>>https://web-camp.io/magazine/archives/15956

## 3.current_userと@userは何が違うのか？
__メソッドか変数か__の違い（...だと認識してます。）

|current_user||@user|
|:--:|:--:|:--:|
|deviseのヘルパーメソッド||userのインスタンス変数|
チーム開発（デプロイをしたらできなくなった）

チーム開発で作業を進め、途中でデプロイをしたらできなくなったエラー

https://gyazo.com/461711b5df9dd85fec8c5b84ea353e48
リポジトリがないエラー
config/deploy.rbの記述でリポジトリ名を間違えていた


https://gyazo.com/c291af8886ba6cc246a7b27bef9c37d7
Gemfileの中の
gem 'sqlite3', '~> 1.3.13'は
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
があればいらないためエラー


https://gyazo.com/ba53f98a5b61f5e342efe534203ff00c
ActiveSupport::MessageEncryptor::InvalidMessageのエラー文を検索
マスターキーの設定に問題がある
１、本番環境のmaster.keyとローカルのmaster.keyの値は同じ物でした。
２、ローカル側、本番環境どちらもアプリケーション（フリマアプリ）のディレクトリにてEDITOR="vi" bin/rails credentials:editを実行した際にcredential.ymlは開くことができない。
３、解決策はcredentials.yml.encを削除して、EDITOR=vim rails credentials:editを実行でcredentials.yml.encの中身を更新する
その際、チーム開発の場合credentials.yml.encとmaster.keyをチーム全員共有する


https://gyazo.com/641bfc48fc77cf97b91a3ee6e5410e8e
エラー文'brand'カラムが二重に記述されている
mysql2::error: duplicate column name 'brand': alter table `items` add `brand` varchar(255)
db/マイグレートを確認し、二重に記述されてるカラムを消しエラー解消
三つくらい重複していいる記述があった


上からエラーを解消していき（４種類）、デポロイ成功
全ての作業記述変更の際マスターブランチにてcommit pushしてからbundle exec cap production deploy
whileをパイプ入力で回したらexitで終わらなかった話

# bashでこんなプログラムを書きました
```text:fruits.txt
apple
banana
orange
```

```bash
#!/bin/bash

cat fruits.txt | while read LINE do
    echo ${LINE}
    if [ $? -ne 0 ] ; then
        echo "エラー:${LINE}"
        exit 1;
    fi
done

echo "正常終了！"
done

```


# 解説
fruit.txtの中身をcatしてwhile文にパイプで渡して標準出力するプログラムです。

#### 実行してみる
例えばbananaのechoで失敗した場合、期待される出力は下記となります。

```text
apple
エラー:banana
```

しかし実際の出力は下記となります。
エラー後にスクリプトが終了せず、後続の処理が続いていますね。

```text
apple
エラー:banana
orange
正常終了！
```

#### 原因
パイプでwhile文に渡す場合、whileループは元スクリプトの子プロセスとして
実行されてしまいます。
したがって、exit 1をしたとしてもあくまでも子プロセスしか終了せず、
メインの処理は続いてしまいます。

#### 解決策１_子プロセスの戻り値を拾う
子プロセスの戻り値1を親プロセス側で拾って親プロセスを異常終了させます。

```bash
cat fruits.txt | while read LINE do
    echo ${LINE}
    if [ $? -ne 0 ] ; then
        echo "エラー:${LINE}"
        exit 1;
    fi
done

if [ $? -ne 0 ] ; then
    exit 1;
fi
```

#### 解決策2_for文を使う
for文のリストにcatの結果を指定すれば解決します。
こうすると別途catの結果を入れる変数を定義する必要もないのでスマートかと。

```bash
for FRUIT in `cat fruits.txt`; do
    echo ${FRUIT} 
done
```
分散共分散行列の公式まとめ

# 分散共分散行列の公式まとめ

Wikipedia の「分散共分散」のページ (https://ja.wikipedia.org/wiki/%E5%88%86%E6%95%A3%E5%85%B1%E5%88%86%E6%95%A3%E8%A1%8C%E5%88%97) には色々な公式があるけど、結局以下の定理１と２を理解していれば、あとは変数を適当に入れ替えるだけ。

分散共分散行列が半正定値行列であることはカーネル回帰におけるカーネルトリックを実現する上で重要。

## 表記ルール

1. スカラー表記：$x$、ベクトル表記：$\boldsymbol{x}$、行列表記：$X$
2. スカラー表記：$E[x]=\mu_x$、ベクトル表記：$E[\boldsymbol{x}]=\boldsymbol{\mu_x}$

## 定理

分散共分散行列 $V[\boldsymbol{x}]$ と $Cov[\boldsymbol{x}, \boldsymbol{y}]$ について、$Cov[\boldsymbol{x}, \boldsymbol{x}] = V[\boldsymbol{x}]$。

### 定理1

$$Cov[A \boldsymbol{x} + \boldsymbol{a}, B \boldsymbol{y} + \boldsymbol{b}] = A Cov\left[\boldsymbol{x}, \boldsymbol{y} \right] B^T$$

$$\fbox{proof}$$

```math
\begin{align}
Cov[A \boldsymbol{x} + \boldsymbol{a}, B \boldsymbol{y} + \boldsymbol{b}]
&= E \left[ \left( A \boldsymbol{x} + \boldsymbol{a}
                  - E[A \boldsymbol{x} + \boldsymbol{a}] \right)
           \left( B \boldsymbol{y} + \boldsymbol{b}
                  - E[B \boldsymbol{y} + \boldsymbol{b}] \right)^T \right] \\
&= E \left[ \left( A \boldsymbol{x} 
                  - E[A \boldsymbol{x} ] \right)
           \left( B \boldsymbol{y} 
                  - E[B \boldsymbol{y} ] \right)^T \right] \\
&= E \left[ A \left( \boldsymbol{x} 
                  - E[\boldsymbol{x} ] \right)
           \left(\boldsymbol{y} 
                  - E[\boldsymbol{y} ] \right)^T B^T \right] \\
&= A Cov\left[ \boldsymbol{x}, \boldsymbol{y} \right] B^T
\end{align}
```

### 定理2

```math
Cov \left[ \boldsymbol{x}_1 + \boldsymbol{x}_2,
           \boldsymbol{y}_1 + \boldsymbol{y}_2 \right]
= Cov \left[ \boldsymbol{x}_1, \boldsymbol{y}_1 \right]
+ Cov \left[ \boldsymbol{x}_1, \boldsymbol{y}_2 \right]
+ Cov \left[ \boldsymbol{x}_2, \boldsymbol{y}_1 \right]
+ Cov \left[ \boldsymbol{x}_2, \boldsymbol{y}_2 \right]
```

### 定理３

分散共分散行列 $\Sigma \succeq 0$ (半正定値行列)

$$\fbox{proof}$$

$Cov[A \boldsymbol{x} + \boldsymbol{a}, B \boldsymbol{y} + \boldsymbol{b}] = A Cov\left[\boldsymbol{x}, \boldsymbol{y} \right] B^T$ において、$\boldsymbol{y}=\boldsymbol{x}$、$\boldsymbol{a}=\boldsymbol{b}=\boldsymbol{0}$、$A=B=\boldsymbol{a^T}$ を代入。

```math
\begin{align}
Cov[\boldsymbol{a}^T \boldsymbol{x}, \boldsymbol{a}^T \boldsymbol{x}]
&= V[\boldsymbol{a}^T \boldsymbol{x}] \\
&= \boldsymbol{a}^T V[\boldsymbol{x}] \boldsymbol{a}
\end{align}
```

$\boldsymbol{a}^T \boldsymbol{x}$ はスカラーなので $V[\boldsymbol{a}^T \boldsymbol{x}] \geq 0$。よって $\boldsymbol{a}^T V[\boldsymbol{x}] \boldsymbol{a} \geq 0 　　\Box$
【Laravel】リレーションがある場合のファクトリによるテストデータの生成

ファクトリでリレーションがあるモデルのテストデータを生成するパターンをメモしています。
[公式リファレンス(データベースのテスト)](https://readouble.com/laravel/5.8/ja/database-testing.html?header=%25E3%2582%25A4%25E3%2583%25B3%25E3%2583%2588%25E3%2583%25AD%25E3%2583%2580%25E3%2582%25AF%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%25B3)
###親子関係
User(親)->Movie(子)のように、二つのテーブル間の親子関係なら公式リファレンスにある方法で簡単にテストデータを生成できます。each()とモデルのリレーションメソッドを利用します。

```php
factory(App\Models\User::class)
    ->create()
    ->each(function ($user) {
         $user->movies()->save(factory(App\Models\Movie::class)->make());
    });
```
###親子孫関係
User(親)->Movie(子)->Review(孫)のように三つ以上のテーブル間に関係がある場合は上の方法をそのまま使うことはできません。なので外部キーとなる属性をオーバライドしてリレーションを構築します。

```php
factory(App\Models\User::class)->create()->each(function ($user) {
    factory(App\Models\Movie::class)->create(['user_id' => $user->id])->each(function ($movie) {
        factory(App\Models\Review::class)->create(['movie_id' => $movie->id]);
    });
});
```
master への push 時に生成物を git push する

## やりたいこと

- ビルド生成物を CI に生成させたい

## 方法


Github Actions で `secrets.GITHUB_TOKEN` を使って 自身に push する


追記: set-url はいらず、自分自身に push するだけでOK

## workflow

```yaml:.github/workflows/gen.yaml
name: Gen
on:
  push:
    branches:
      - master

jobs:
  build:
    name: Gen dump
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v2
      - run: echo 1 > .dump
      - run: git add .dump
      - run: git config --global user.email "CI@example"
      - run: git config --global user.name "CI"
      - run: git commit -m "Gen .dump"
      - run: git push origin master
```


無限ループはしない模様

参考: https://beet-aizu.hatenablog.com/entry/2019/09/05/190123
【Golang】Ginでサブルーティングの定義方法

## やりたいこと

ルーティングを作る時にグルーピングを多段化させたい時ってあると思います。
その方法について記載します。

## 方法

```go
router := gin.Default()

// api
v1 := router.Group("api/v1")
{
  // 以下のようにv1.Groupとしてv1を引き継いでGroupを作成する
  hoges := v1.Group("/hoges")
  {
    hoges.GET("/", func(c *gin.Context) {
      c.JSON(200, gin.H{
        "message": "hello",
      })
    })
  }
}
```
【Rails】連動しないwill_paginateの設定

```static_pages_controller.rb
:
@myfeed_items = current_user.myfeed.paginate(page: params[:page], per_page: 3)
@followingfeed_items = current_user.followingfeed.paginate(page: params[:page], per_page: 3)
:
```
上記のように同様のファイルに`will_paginate`の設定がされているときに、両方とも連動してページが動いてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/e754d16a-839d-f480-1af6-293c3824be85.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/108f17af-1101-3dbc-14e3-ac4421e31814.png)

#解決策
```static_pages_controller.rb
:
@myfeed_items = current_user.myfeed.paginate(page: params[:myfeed_items_page], per_page: 3)
@followingfeed_items = current_user.followingfeed.paginate(page: params[:followingfeed_items_page], per_page: 3)
:
```
上記のように`page: params[任意の値]`に設定することで連動を防ぐことができます。

```erb:_myfeed.html.erb
:
  <%= will_paginate @myfeed_items, :param_name => 'myfeed_items_page', class: "center" %>
:
```

```erb:_followingfeed.html.erb
:
  <%= will_paginate @followingfeed_items, :param_name => 'followingfeed_items_page', class: "center" %>
:
```
それぞれの`html.erb`も修正すれば`will_paginate`で設定されているボタンが単独で動いてくれます。
[PHP]paizaスキルチェック用標準入力取得方法のメモ

##はじめに
paizaのスキルチェックをしている際に複数の標準入力の取得方法が複数あったのでメモとして残します。

##入力値取得方法まとめ

入力値は一律で下記に指定する通りとする

```
1 23 4

```

###1.`fgets`メソッド

```php
$input = fgets(STDIN);
//fgets()はファイルポインタを指定することで文字列を返します。
//STDINを指定することで標準入力を返すようになります。(STDIN:standard inputの略)
var_dump($input);
<<--出力内容-->>
string(7) "1 23 4
"
```
`var_dump()`で`fgets()`の返り値を確認してわかる通り、最後の改行も一緒に取得してしまっていることがわかります。

###2.`trim`メソッド

```php
$input = trim(fgets(STDIN));
//trim()は引数のホワイトスペースを取り除くことができます。
var_dump($input);
<<--出力内容-->>
string(6) "1 23 4"
```
`trim()`を使用することにより、`fgets()`で取得した値の改行を取り除くことができました。

###3.`explode`メソッド

```php
$input = explode(' ', trim(fgets(STDIN)));
//explode()は第２引数の文字列を第１引数で分割し配列に格納します
var_dump($input);
<<--出力内容-->>
array(3) {
  [0]=>
  string(1) "1"
  [1]=>
  string(2) "23"
  [2]=>
  string(1) "4"
}
```

##最後に
今回はpaizaスキルチェックで初めて標準入力というものを知り、ノリで課題をしていたけど頭の中で纏まったのでQiitaでも纏めてみました。
WSL上のLinuxへインストールしたRstudio Serverの起動を楽にする

# 本記事について
- WSL (Windows Subsystem for Linux)上のLinuxにインストールしたRstudio Serverの起動を楽にするスクリプトを作成した。
- スクリプトの詳細と使い方を本記事で紹介している。

# Rstudio Serverとは？
Linux にインストールされた R を使用できる IDE（統合開発環境）。デスクトップアプリ版ではなく、ブラウザベースで動作する Rstudio。

Rstudio Server を利用すれば、WSL にインストールした R を Rstudio から使用することができる。

参考：[RStudio Server: 始めよう](http://memorandum2015.sakura.ne.jp/docs/server/getting_started.html)
インストールはこちら：[Download RStudio Server](https://rstudio.com/products/rstudio/download-server/)

# Rstudio Serverの起動
WSLへインストールした Rstudio Server を起動するためには、以下のコマンドを実行する。
その後、`http://localhost:8787`へアクセスすれば、Rstudio がブラウザで起動する。

```bash
$ sudo service rstudio-server start
```
# 起動をコマンドひとつで行えるようにする

### シェルスクリプトの実装

起動コマンドとブラウザでのアクセスを両方やるの面倒...なので、ひとつのコマンドを実行すればブラウザ起動&アクセスも同時に行えるようなスクリプトを書いた。
スクリプトでは、起動成功時と失敗時にそれぞれ対応するログを吐くようにしている。（ログ出力については、下記の記事中の実装を使用させていただきました）。
参考：[シェルスクリプトのロギングを楽にするtips](https://qiita.com/Ets/items/cd3baa5cecbf553f822d)

`startRserver.sh`

```bash
#!/bin/bash
# -*- coding: utf-8 -*-
​
function log() {
    local fname=${BASH_SOURCE[1]##*/}
    echo -e "$(date '+%Y-%m-%dT%H:%M:%S') ${PROCNAME} (${fname}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $@"
}
​
sudo service rstudio-server start
if [ $? -gt 0 ]; then
    log "[ERROR] Rserver did not start."
else
    log "[INFO] Rserver started successfully!"
    echo "Access the URL Below"
    echo "http://localhost:8787"
    /mnt/c/'Program Files (x86)'/Google/Chrome/Application/chrome.exe http://localhost:8787
fi
```

### エイリアスの設定

直接シェルスクリプトを叩いても良いのですが、より起動を楽にするため、エイリアスを設定する。
`startRserver.sh`をホームディレクトリに配置し、下記のエイリアスを`~/.bashrc`に書く。

```bash
alias rstudio='bash ~/startRserver.sh'
```

その後、設定を反映させる。

```bash
$ source ~/.bashrc
```

### 完了

以上により、`rstudio`コマンド一発で Rstudio Server の起動が可能になりました！

```bash
$ rstudio
```
テスターの使い方（電圧/電流/抵抗）

# テスターの使い方
テスター（マルチメーター）の使い方について書く。
電圧を測るか、電流を測るか、抵抗を測るかでテスターのつなぎ方が異なる。

## 電圧の測り方
電圧は2点間の電位差を測る。
したがって、テスターは電圧がかかる部品の両極で計測する。
![20200331_003124.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/ad7ee7ba-85e9-75cf-9fb1-5dd63b473a03.jpeg)

## 電流の測り方
電流は流れている電気そのものなので、
測りたい電流値をテスター自体に流さなくてはならない。
したがって、電気の通り道にテスターを加える。
![電流.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/8c049c5e-b2c8-662a-2807-5088ec06aa6c.jpeg)

## 抵抗の測り方
抵抗を測る場合は、テスターから出力される電力を使う。
![抵抗.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/de459eeb-9a60-5707-e6be-a40918eda388.jpeg)
SAM+eclipseでaws lambdaのTDD - 環境構築編

## aws lambdaのTDD
- 単体テスト: junit
- 結合テスト: SAM

以上の組み合わせでTDDでlambdaを作成する

## eclipseでlambda project作成
eclipseの「Help」->「install New Software」を選択
`update site https://aws.amazon.com/eclipse - https://aws.amazon.com/eclipse`を入力
以下の画像のようにチェックを入れて`Next`を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301386/0682d156-5039-5268-2496-e7bbfa35bec6.png)

eclipseを再起動する旨のポップアップが出るため、それに従い再起動。

「File」->「New」->「other」より以下のようにlambdaプロジェクトを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301386/1b95ea06-cbee-61fc-0d79-bbcd44a1df86.png)

以下のように入力し、プロジェクトを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301386/094c85e9-6612-a886-583c-02f1d7c8dad1.png)

## SAMlocal環境の構築
以下のAWS公式手順のうち、自分のOSに対応する手順でやれば構築できる
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html

## テスト用CFnテンプレート作成
`src/test/resources`配下に以下のように`template.yml`を作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301386/4dc5ea04-bf4f-4b77-b082-41e9162894cb.png)
このCFnテンプレートに結合テストで使用する他のAWSリソースを記述していく

さらに`src/test/resources`配下に以下のように`event.json`を作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301386/26025f72-52a3-ae93-0045-97b072e77d66.png)
このjsonファイルを結合テストで実行するlambdaのinputとして使う


## SAMテスト実行
「Run」->「Run Configurations」から`AWS SAM Local`を選択し、以下のように入力し`Apply`を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301386/e4cf3106-f481-9a98-0686-f6d98ae8fd79.png)

以下のようにコンソールに出力されればSAMlocalでテストを行う準備はOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301386/365edb42-e5ee-779d-a802-5517df4e5412.png)

次回は実際に単体テスト、結合テストをしながらTDDしていく
## appendix
docker周りの設定で若干詰まった。
SAM localでテストを実行すると以下のエラーが発生した
`docker.credentials.errors.InitializationError: docker-credential-desktop not installed or not available in PATH`

`~/.docker/config.json`を以下のように修正するとエラー解消した

```diff:~/.docker/config.json
{

- "credsStore" : "desktop",
 
  "auths" : {

  },
  "stackOrchestrator" : "kubernetes"
}
```

`Docker Registory`の認証情報保存先消すと上手くいく。
理由はよく分からないけれど。。
VisualStudioCodeにおけるデバッグコンソールへの出力設定

vscodeにてJavaのデバッグ環境を作ろうとしたところ、実行結果をデバッグコンソールに表示させられず、かなりつまづいたので書いておきます。

##デバッグ環境を構築&デバッグ
まずは適当なサイトを参考にしながらJDKや拡張機能をインストール。そして、テストのためにJavaのファイルを作り、デバッグコンソールに文字列を表示するだけの簡単なコードを記述してみました。
![alt](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527091/0879597f-5463-9542-c79c-b648dded4b1c.png)
参考にしていたサイトでは、この段階でデバッグを開始したら実行結果がデバッグコンソールに表示されていましたがここで問題発生。なぜかデバッグコンソールに「hello world」の文字列が表示されないのです。
JDKをインストールし直しても、拡張機能を入れ直しても、ファイルを作り直しても、一向に表示されない…
![alt](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527091/6c21369f-122f-d0d2-f058-18cbf0498161.png)
##解決方法
どんなワードで検索しても解決策が見つからず、萎えてしまい一ヶ月が経過したとき、ふと「そういえばデバッグコンソールへの出力設定とかって無いのか？」と思いつきました。
早速、設定の検索窓に「DebugConsole」と入力してみると
![alt](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527091/ddc37304-49f0-6e32-9cb5-448fda2e826e.png)
それらしき雰囲気の設定項目が見つかった。
英語でよくわからないのでGoogle先生に聞くと

>Javaプログラムを起動するための指定されたコンソール。特定のデバッグセッション用にコンソールをカスタマイズする場合は、launch.jsonのコンソール設定を変更してください。

とのこと、いまいち訳がわかりにくいが恐らく「プログラムの実行結果を表示する場所を変えたいのなら、この設定を変更してください」という感じの意味合いだと思われる。
ということで、デフォルトとして選択されていた *integratedTerminal* から *internalConsole* へと設定を変更。そして試しにデバッグをしてみると…
![alt](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527091/89eaa81f-a4d4-50d4-1529-b4ba0dd3fe62.png)
しっかりデバッグコンソールに実行結果が表示されました。どうやらデフォルトの設定で、実行結果の出力先がターミナルになっていたようです。

##終わりに
皆さんもvscodeなどで何かつまづいたら、まずはソフト自体の設定にそれらしき項目がないか探してみましょう。今回のように意外と簡単な設定ミスかもしれません。