OmniAICreator/Qiita-1.07M huggingface dataset:
Capybaraを使う！！！(Rails + Rspec + Capybara)

[**Rspecの導入がまだの方はこちら**](https://qiita.com/tksh8/items/f0b5b656580334181e3c
)


Rails + Rspec + Capybaraを前提として進めていきます。

# Capybara


テストのためのrubyフレームワークです
これを使うと画面表と同じ様な感覚でE2Eテストを実施できます。


## インストールする
#### 1.Gemfileに追加

```ruby:Gemfile
group :development, :test do
 gem 'capybara'
 gem 'selenium-webdriver'
end
```
インストールします、

```
$ bundle install
```

#### 2.spec_helper.rbに`require 'capybara/rspec'`を追加


```ruby:spec_helper.rb
require 'capybara/rspec'
RSpec.configure do |config|
```

#### 3.テストを書く
<img width="364" alt="スクリーンショット 2020-04-17 17.23.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355517/d096c7d6-58c6-5645-bdbf-a5f69ee39cdf.png">
のような
一般的なログイン画面で
メールアドレス`（name="email")`,
パスワード`（name="password"）`
でログイン（ログインを押したら"ログインしました"）
するまでのテストです。


```ruby:spec/system/user_spec.rb
require 'rails_helper'

RSpec.feature 'login' do
  background do
    # ユーザ作成
    User.create!(name:'testuser', email: 'foo@example.com', password: '123456', password_confirmation: '123456')
  end
  scenario 'ログインする' do
    # ログインページを開く
    visit login_path

    # ログインフォームにメールアドレスとパスワードを入力する
    fill_in 'email', with: 'foo@example.com'
    fill_in 'password', with: '123456'
    # ログインボタンをクリック
    click_on 'ログイン'
    # ログインに成功したことを検証
    expect(page).to have_content 'ログインしました'
  end
end
```

画面上のような操作でテストができるので便利です！！！



※RSpecでヘルパーを作成する方法
こちらの記事が参考になります
https://breakthrough-tech.yuta-u.com/rspec/how-to-make-spec-support/
個人アプリ（heroku）

# 本番環境でWe're sorry, but something went wrong.が表示されていた

```ruby:config/assets.rb
Rails.application.config.assets.precompile += %w( admin.js admin.css )
```
をコメントアウトを解除

`git add -A`
`git commit -m "Update application"`
`git push heroku master`
`heroku run rails db:migrate`
修正してから上二つのコマンドを実行していなかったため本番環境に反映されなかった。

エラーログ確認方法
`heroku logs -t`
出ていたエラー
https://gyazo.com/4516eafeb719b90861883d76e3150976

参考サイト
https://qiita.com/jnchito/items/a1833b48c3b47a955bdf


`git status`
インデックスに追加されている変更修正、されていない変更修正を確認することができる

`git add`
インデックスに追加して、変更修正記録の対象とすることができる

`git commit`
インデックスに追加されている変更修正を、コミットするためのコマンドです。-mのオプションはコミットメッセージと呼ばれ、どのような変更を行ったのかメモを残せます。このコミットメッセージをしっかり書くことによって、「いつ、どのような修正をしたのか」が明瞭になり、いざという時に遡りやすくなる
-m "タイトル"
Windows10でMagic Mouse 2のスクロール機能が使えるようになった覚書

# 要約
Windows10でもMagic Mouse 2のスクロール機能を使いたい！と思い調べてみました。いろんな情報がある中で、最終的には下記サイトが有用でしたのでご紹介します。
[Apple Magic Mouse 2をWindows10で使う](https://hiro7216.mydns.jp/blog/?p=3799)
注意点としては、事前に7-Zipをインストールしておく必要があります。（入ってないと途中でコケます(>_<)）
[圧縮・解凍ソフト 7-Zip](https://sevenzip.osdn.jp/)
スクロールが使えるようになり快適です♪

# 手順
0. [7-Zip](https://sevenzip.osdn.jp/)をインストールする。
0. 以降は記事"[Apple Magic Mouse 2をWindows10で使う](https://hiro7216.mydns.jp/blog/?p=3799)"に記載の手順でドライバをインストール。(コマンドプロンプト使用)

# メモ
やっぱりスクロールが使えると快適です！
ようやく有用な情報を得ることができたので、今回初投稿を兼ねてご紹介させていただきました。
普通にBluetooth接続しただけではスクロールは使えず、メーカーサイトから入手したBootCamp用ドライバを入れても変わらずという状態でした。そんな時に上記サイトに辿り着きました。
コマンドプロンプトからexeファイルを実行しています。最初実行した時にエラーで止まってしまい、メッセージをよく読むと7-Zipが必要なようなのでインストール。後でダウンロード元のGitHubを見てみると7-Zipが必要、的な記載がありました。
今回インストールに至った動機は中古でWindowsマシンを購入したことでした。普段はMacBookProを使用していて、半年ほど前にBootCampでWindows10をインストールするも動作がおかしく結局断念。。。
Excel VBAを使用したい時があり、結局Office系はWindowsが使いやすいので安い中古を探して購入。
BootCampの時もMagicMouse2のスクロールに挑戦しましたが、その時点で紹介記事は上がっておらず結局挫折。。。
苦節半年余り、ようやく実現することができました♪
快適なPCライフを！
Wrap_ContentなTextViewに動的に長いテキストを設定して表示できない部分は…にする

# やりたいこと
高さがwrap_contentなTextViewに動的にテキストをセットして、長すぎて全文表示できない時にandroid:ellipsizeの設定を反映して…にしてほしい。
※maxLinesは機種ごと、端末の表示文字サイズ設定ごとに異なり、なるべく無駄なくたくさんテキストを表示したいので設定できないというとき。

cf )  何もしないと
以下のようなTextViewに何も考えず長いテキストをセットすると、…は表示されず表示できるだけ表示して、UI上では入りきらなかった部分はなかったかのようになってしまう。場合によっては最後の行は文字が下の方見切れたりする。

```xml
<TextView
                android:id="@+id/text1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:textSize="10sp" />
```

# 解決法
テキストをセットした後に、今の環境での見切れず表示できるmaxLineを計算してやってTextViewにセットする。

```kotlin
 val text1 = findViewById<TextView>(R.id.text1)

 if (text1.layout.height > text1.measuredHeight) {
            // textが見切れるようだったら、maxlineを設定して長すぎる部分が...になるようにする。

            // text.layout.height : 設定されてる文字がかかれてる高さ。ここにかかれている文字が実際の画面上ですべて表示されているわけではない。
            // text1.measuredHeight : 実際に画面上で表示されている高さ。
            //  text1.measuredHeightを設定しても、maxLineを設定しない限りbody.layout.heightまでは変わらないらしい。
            // text1.lineHeight : 一行の高さ。
            // text1.paint.fontSpacing : 行間の大きさ。
            text1.maxLines = text1.measuredHeight / (text1.lineHeight + text1paint.fontSpacing.roundToInt())
        }

```


# 解説
コードにも書いてあるが、各プロパティは

- text1.layout.height : 設定されてる文字がかかれてる高さ。ここにかかれている文字が実際の画面上ですべて表示されているわけではない。
- text1.measuredHeight : 実際に画面上で表示されている高さ。
- text1.lineHeight : 一行の高さ。
- text1.paint.fontSpacing : 行間の大きさ。

で取得できる。

ここで注意したいのは、TextView#measureで変えたり、TextView#getMeasuredHeightで取得出来たりする大きさはテキストがかかれている部分の大きさとイコールではないということ。text1.layout.heightのうち、text1.measuredHeightで表示できる部分のみ切り取られてUI上に描画されるイメージである。なので長いテキストをセットしてしまうとtext1.layout.heightだけ長くなるので途中で(下手すると最後の行は下が見切れた状態で)表示が切れてしまう。

しかし、maxLinesを設定すると、text1.layout.heightもそれに合わせて大きさが変わり入りきらない部分があったときはandroid:ellipsizeの設定が反映される。

なので、長さがwrap_contentなTextViewに動的にテキストをセットして、長すぎて全文表示できない時にandroid:ellipsizeの設定を反映させるには、text1.layout.height > text1.measuredHeightか調べてtrueの時はtext1.measuredHeightを一行の高さと行間の大きさの和で割ってやって動的にmaxLinesを出してやってセットしてやればいい。

# 注意点
layoutファイルでTextViewにandroid:ellipsizeを何も設定してやらないと、maxLinesを設定してやった後にテキストが何も表示されなくなった。なので**layoutファイルでのandroid:ellipsizeの設定は必須**
【Git】特定のbranchのコミットだけ表示させたい時に便利なコマンド

#Gitのコマンドを使って集計を楽にしたい
現在職場で使用している検収用のエクセルシートには案件毎のコミット番号と修正があったファイルを入力する欄があるのだけど、毎回手で集計するのが面倒なので対象のブランチのログからコミットIDと修正変更のあったファイルのリストだけ出力するようなGitのコマンドを考えてみた。

```text:gitコマンド
$ git log --stat --no-merges  --name-only --oneline --first-parent BRANCH_NAME > log.txt
```

上記コマンドを実行するとlog.txtに結果が出力されます。

```tex:log.txt【コマンド実行結果サンプル】
99d2f729 コミットメッセージ
src/scss/pc/sample.scss
85df73ff コミットメッセージ
lib/system_common.php
4e568d5d コミットメッセージ
lib/form/complete/sample.php
lib/form/sp/complete/sample.php
d99dfe5a コミットメッセージ
htdocs/form-complete/sample.php
htdocs/sp/form-complete/sample.php
69958429 コミットメッセージ
lib/form/sp/complete/sample.php
808f351e コミットメッセージ
htdocs/form-complete/sample.php
htdocs/sp/form-complete/sample.php
lib/system/sample.php
```

##出力したファイルを加工する
出力したGitのログファイルを加工して必要な情報を見やすく整形します。

```php
<?php

//コミットIDとファイル名だけ表示されるように整形
$file = fopen("log.txt", "r");
while ($line = fgets($file)) {
	$array[] = trim($line);
}
foreach ($array as $val) {
	if(strpos($val,' ') !== false){
		//コミットIDとメッセージを分割。
		//今回欲しいのはコミットIDだけなので$val[0]を連結する。
		$val = explode(' ', $val);
		$res .= "<br>" . $val[0] . "<br>";
	} else {
		$res .= $val . "<br>";
	}
}
echo $res;
fclose($file);
```

```tex:PHP実行結果サンプル
99d2f729
src/scss/pc/sample.scss

85df73ff
lib/system_common.php

4e568d5d
lib/form/complete/sample.php
lib/form/sp/complete/sample.php

d99dfe5a
htdocs/form-complete/sample.php
htdocs/sp/form-complete/sample.php

69958429
lib/form/sp/complete/sample.php

808f351e
htdocs/form-complete/sample.php
htdocs/sp/form-complete/sample.php
lib/system/sample.php
```

#まとめ
なかなかコミットのIDと編集したファイル名だけ欲しい状況って無いと思うけど、とりあえず自分用として書いたものを公開しておきます。
Gitでpushをした後にコメントを変更する方法

# 目的
pushをした後にコメントが変更をしたい場面があったため、その方法を残しておきます。

# 注意点
- 時系列などがバラバラになってしまいます。
- 他の人との共有のブランチで実行すると他の人が<br>
  push出来ない等の不具合が発生する可能性があります。

# 実行方法

## 1.コメントを変更したいcommitを指定する。
過去のcommitを指定するためには、rebaseコマンドを使用する。

### 参考
```
$ git rebase -i HEAD~5
```
HEAD~◯に数字を入れることで◯個前のcommitを指定するか選べる。

### 実際の実行例
```
pick xxxxxx1 hoge1
pick xxxxxx2 hoge2
pick xxxxxx3 hoge3
pick xxxxxx4 test4
pick xxxxxx5 test5

# Rebase xxxxxx1..xxxxxx5 onto xxxxxx5 (5 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
```

上の画面では、対象のcommitに対して行いたいコマンドを選ぶことが出来る。
編集を行いたい場合は、コマンドを[pick]→[e]or[edit]に変更し閉じる。

## 2.commitのコメントを変更する。
commitのコメントを変更したい場合は、**git commit –amend**を実行する。

### 実際の実行例
```
hint: Waiting for your editor to close the file...
test5

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      xxx xxx x xx:xx:xx 2020 +0900
#
# interactive rebase in progress; onto xxxxxx5
# Last command done (1 command done):
#    edit xxxxxxx5 test5
# Next commands to do (4 remaining commands):
#    edit xxxxxx1 test1
#    edit xxxxxx2 test4
# You are currently editing a commit while rebasing branch 'branch' onn 'xxxxxx5'.
#
# Changes to be committed:
#
```
例の場合だと一番上の「test5」を変更したいコメントにし閉じる。

以下のような画面が出てくれば変更が成功している。
```
 [detached HEAD xxxxxx5] test6
  Date: xxx xxx x xx:xx:xx 2020 +0900
  1 file changed, 1 insertions(+)
```

## 3.コメントの変更を終了する。
コメントの変更を確定するには**git rebase --continue**を実行する。

以下のような画面が出てくれば変更が確定している。
```
Successfully rebased and updated refs/heads/branch.
```

## 4.変更をpushする。
最後に変更をpushをして完了。
※注意点としては普通のpushだと正常にpushが出来ないため、<br>　-fコマンドをつけて実行する。

### 参考
```
$ git push -f origin branch名
```
Linux コマンド 自分用work

# コマンド
## sed
### sed -i
```sed -i 's/変換前文字列/変換後文字列/' 対象ファイル```
-i テキストの挿入・上書き。
's' で置換
※sedコマンド全般、実施時には応答なしに上書きされるためバックアップ必須

### sed -n **'p'**
```sed -n '/aaaa/,/bbbb/p' filename```
対象filenameのaaaaを含む行からbbbbを含む行までを **表示**

### sed -n **'!p'**
```sed -n '/^BEGIN$/,/^END$/!p' filename```
対象filenameのBEGINのみ の行から ENDのみ までの行を **表示しない**

### grep -v | sed -n 'p'
```grep -v -e "除外文字" /tmp/list/HOSTNAME_????????.txt | sed -n '/表示対象文字列開始/,/表示対象文字列終わり$/p'```
・grepで除外文字を除きつつ、HOSTNAME_*.txtをすべて表示しつつ、表示対象文字列～表示対象文字列終わり まで(の行)を表示。 ※$ は行の終わり(後尾)
・除外文字は、-e "aaa" -e "bbbb" -e "cccc" のように複数指定可能。
・用途：listディレクトリにサーバーの情報を取得してきたテキストが大量にある場合(サーバー台数分)に、その中の特定情報を抜き出す。最後に``` >> list_file.txt```などをつければ出力。



## sed s/A/B/ のB(置換後文字列)で使える記号
### &
マッチした文字列全体

例：0001 を no0001 にしたい場合
```sed -i 's/0001/no&/' filename.txt```
例：server を #server にしたい場合
```sed -i 's/^server/#&/' filename.txt```
例：server1 と server2 と server3 の文字列を #server1～#server3 にしたい場合
```sed -i 's/^server[1-3]/#&/' filename.txt```



# キャパシティ
### df
ディスク容量表示
```df -h``` バイト
```df -hk``` キロバイト
```df -hm``` メガバイト
```df -hT``` 詳細
### sar
```sar -u``` CPU
```sar -r``` memory
```sar -b``` diskI/O
```sar -n DEV``` NW使用量





# 使うやつ
### mkdir
```mkdir -p -m 777 dirname```
フル権限でディレクトリ作成

### rsync
```rsync 対象ファイル 他サーバIP:格納ディレクトリ```
```rsync /tmp/shell/*.sh 192.168.10.3:/tmp/shell/```
自サーバーのシェルを他サーバーへコピー。Windowsで言うrobocopy
送信先のディレクトリは既に無いとNG。





# その他
### /etc/fstab
ディスクパーティションや様々なブロックデバイス、リモートファイルをどのようにファイルシステムにマウントするか記載されたファイル
今月の日付を出す。

来月の日付を出すにはどうしらしいんだろう？

```php:output2.php
puts 'code with syntax'
<form action="output2.php" method="get" accept-charset="utf-8">
<dl>
<dt>日にち</dt>
<dd>
<select name="day" id="day">
<?php for ($day=1; $day<=date('t'); $day++) {
    print('<option value="' .$day. '">' .$day. '日</option>');
    }
?>
</select>
</dd>
</dl>
</form>
```
GAS　でアップロードし、GoogleDrive に保存した画像ファイルが破損？！

# なんか画像ファイルが壊れてるっぽいんです
　以下のようなGASプロジェクトで、スマホからカメラで撮影した画像ファイルを、GoogleDriveに保存させていたのですが、2020年２月下旬あたりから、アップロードされている画像ファイルが閲覧できないことに気づきました。

```html:upload.html
<form action="" enctype="multipart/form-data" id="photoForm">
  <input type="hidden" name="photoBarcode" id="photoBarcode"/>
  <input type="file" accept="image/*" capture="environment" name="photo" id="photo" onClick="$('#photo').val('')" onchange="cameraSend($('#photoForm').get(0))" style="display:none;"/>
</form>
```


```javascript:camera.js
function cameraSend(data){
  google.script.run.withSuccessHandler(cameraFinish).withFailureHandler(cameraError).recievePhoto(data);
}
```

```javascript:GAS
function recievePhoto(data){
  if(data && data.photo){
    var file = DriveApp.getFolderById('XXXXXXXXXXXX').createFile(data.photo);
    file.setName(data.name + '.jpg');
  }
}
```

# ファイルはできていて、ファイル名もちゃんと登録されているけど、ファイルは開けない
GoogleDriveは、通常、ファイルをシングルクリックすると、プレビューが表示されるんですが、このファイルはプレビューも表示されず、GIMPでファイルとして開くと、以下のような感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366986/ecc80b14-97d0-d5b1-2820-533084e7ed90.png)

# 結論
　**Chrome V8 を搭載した新しい Apps Script ランタイムを無効化する**
　こいつがバグがあるみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366986/66727c0f-2937-4991-1de0-6522f0ffd082.png)
　設定したら、公開するのを忘れないでね。


以下、私の右往左往をご覧になりたい方は読み進めてください。
---

# バイナリエディタで見てみよう
　毎度お世話になります。[バイナリエディタ BZ](https://www.vcraft.jp/soft/bz.html)　です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366986/9347293c-2685-0425-b8e6-37efd623259b.png)
　※あっ、スマホの機種バレ・・・古いの使って何が悪いっ！

　`Exif`　という文字は見えますから、なんとかJPEGファイルでアップロードされようとしている様子はうかがえますが、本来JPEGのバイナリ配列は、`ffd8` から始まって、 `ffd9` で終わっているはずですね。
　このルールに反しています。
　[@kazuaki0213さんの記事「JPEG画像の中をちょっとだけのぞいてみる」より](https://qiita.com/kazuaki0213/items/d3e71fe203b4f1d19abc)
　※いつもありがとうございます

　なんだか、先頭もそうですが、 EF BF BD というのがそそかしこに出てきますね。
　これ検索すると、Chrome がダウンロードしようとしたときに、勝手にUTF-8にエンコードしようとして、バイナリファイルに混ぜ込んでいるとか、そういう記事を見つけました。

# 別ブラウザから行けるのか？
　Edge から操作しても、同様でした。
　やはり EF BF BD が大量に入り込んでいます。

# じゃ、GAS側かっ！
　はい。犯人が割れました。
　[これですっ！](https://teratail.com/questions/245846)
　そういえば、２月頃に、こんなメッセージが表示されるようになっていましたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366986/c2262f87-c7d4-c268-7c19-a5d16faccfbb.png)
　そうです。私はなんのためらいもなく、これを有効にしていました。

# 原因と得られたこと
- Chrome Engine のバグらしい
- GAS側のJavascript は Chrome Engin で動作しているらしい
- GAS側がクライアントからダウンロード（言葉合ってる？）するときに、UTF-8 で解釈しようとしているらしい
- 2020/4/17 現在、このバグはまだ治っていないらしい
- 画像が開けなかったら、バイナリエディタで覗いてみると、答えにたどり着けることがあるらしい（これ基本です？）
Amazon SageMaker Ground Truth を使ってみた


[Amazon SageMaker Ground Truth](https://aws.amazon.com/jp/sagemaker/groundtruth/)を試してみて引っかかったことを

## 概要

[Amazon SageMaker Ground Truth を試してみる](https://qiita.com/SatoshiGachiFujimoto/items/e4ab624d3527237ca9e9)

## 引っかかった点

- (2020/4現在)ワーカーにはファイル名が表示されない  
![GT_probrem.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/eb8d5a65-03bb-1fb1-62db-7af3f6f0ac85.png)
      ⇒ 似たようなものが写っている画像をラベリングする場合、  画像のみで判別できるよう工夫が必要
EC2インスタンスの複製とEIPの作成と割り当て手順

# 概要
RDSのDBエンジンのバージョンアップ作業をやったとき、バージョンアップ前後で挙動変わらないよね確認をする際に必要になった。
またなんかで使うだろうしせっかくなのでまとめておく。



# 手順
以下を参考に実施する。

- EC2の複製
https://qiita.com/murachi1208/items/8be3cd006d31f1f81ee4
- EIPの作成と割り当て:https://qiita.com/toyokky/items/5b94c1fe9610663881c1)


以下の手順は実際に試してみてこうやっとけばもっと効率的だったな、とかそもそも記載されていなかったものについての補足。

## 1. EC2の複製
### 1.1. 実施前にやるべきこと　
あらかじめEC2のコンソールで、コピー元EC2インスタンスの以下の情報を調べて記録しておく。

**確認できる場所:コピー元インスタンスの「説明」タブ**

確認項目|
---|
インスタンスタイプ|
ネットワーク(VPC ID)|
サブネット(サブネットID)|
自動割当パブリックIP|
停止-休止動作|
終了保護|
モニタリング|
ライフサイクル|
配置グループ|
キャパシティの予約設定|
IAMロール|
テナンシー|
Elastic Inference アクセラレーターID|
T2/T3無制限|
ネットワークインターフェース|
セキュリティグループ|

**確認できる場所：コピー元インスタンスの「タグ」タブ**
- キー、値

**確認できる場所：ELASTIC BLOCK STORE > ボリューム**

確認項目|
---|
コピー元のEC2が使用しているボリュームのボリュームタイプ|
コピー元のEC2が使用しているボリュームのサイズ|
コピー元のEC2が使用しているボリュームの暗号化|

**確認できる場所:ELASTIC BLOCK STORE > スナップショット**

確認項目|
---|
作成したEBS(AMI付随)のスナップショットID|
作成したEBS(AMI付随)のサイズ|

### 1.2. AMI作成
「終了時に削除」はチェックを外しておく

### 1.3. AMIからインスタンスを作成
- 自分が実施したときには「作成」ボタンではなく「起動」ボタンだった
- 1. で調べた値を元に設定を入力していき、「確認と作成」を押下する
- 既存のキーペアを選択するか、新しいキーペアを作成しますダイアログで
  - 「既存のキーペアの選択」を選択
  - 「キーペアの選択」でコピー元のEC2で使用しているキーペアを選択

### 1.4. その他

- EC2インスタンス一覧ページへ移動し、Nameを任意の文字列に変更する

## 2. EIPの作成と割り当て
### 2.1. Elastic IPの作成
- ネットワーク&セキュリティ > Elastic Ipと進む
- Elastic IP アドレスの割当を押下
- ElasticIPアドレスの設定項目としてデフォルトのままで「割り当て」を押下
=>新規に発行されたIPアドレスが表示される

### 2.2. Elastic IPの割り当て
- Elastic IP一覧ページへ移動し、割り当てたいEIPを選択
- Actions > Elastic IPアドレスの関連付けと進む
- Elastic IPアドレスの関連付けページで以下の通り入力して「関連付ける」を押下
    - リソースタイプ：インスタンス
    - インスタンス:EIPをセットしたいインスタンス
    - プライベートIPアドレス:空白
    - 再関連付け：デフォルト


## 3. SSH接続
- .ssh/configへssh接続設定を追加する(コピー元インスタンスの設定をコピーして、ホストの情報だけ変更してやればいけるはず)
- SSH接続確認する
Rails テストについて  1 （概要編）

#はじめに
テストに拒否反応があるので、まずは整理したいと思います。
少しづつ記事を書いていきます。

もうすでにご存知の方、省略の仕方等ご存知でしたら、ご助言願います。


#テストとはなんぞや？
- プログラムが意図した通りに動くことを確かめること

#大切なん？
- **超大切**と学びました。
- テストコードを書かなければ、プログラムは**想定していなかった動き**を見せる可能性が高くなる。

##何が起きてまうの？
例えば、毎日1万人が訪れるHPのシステムに、新機能を追加することになりました。
コードが完成し、いよいよ実際に動作しているHPに適用します。
しかし、テストコード無しで、つまりプログラムが想定していない動きをしました。（バグがあった・・・）
そのまま本番のHPに適用してしまったせいで、HPが停止してしまいました。
そして、毎日利用している1万人ものユーザーが迷惑を被ります。
そのことによる金銭的な損失や信用の喪失は、計り知れないものに・・・。
　
##だから必要やねん！
- テストは、上記のような事態を防ぐために必要となる。
- あらゆるケースを想定し、「バグがないことを確かめてから」本番に適用する。
- それこそがテストコードを書く意義なのです！

##ということは、いっぱい書かなあかんのか？
- Railsの場合、モデルやコントローラーのクラス１つにつき、１つのテストコードを書く。

ヒェ〜 Σ（ﾟдﾟlll）

##メリットもあんねんで！

####仕様漏れを減らせる
- 対象のメソッドの作成目的と挙動を洗い出す。
- 結果的に仕様を良く確認することになり、バグを引き起こす仕様漏れを少なくすることができる。

####リファクタリングや機能追加がしやすくなる
- 一度テストを通過してしまえば、最終的な結果を維持しリファクタリングをするのが簡単になる。
- 機能追加の際も、従来の箇所は間違いなく動いていることを確認できているので、その結果を崩さないようにするだけで安全に実装することができる。

####楽しくコードを書ける
- テストを通過するという快適な体験を重ねることで、コードを書く作業が楽しくなる。

書いたのはいいですが、テストが楽しい・・・? (¬_¬)


###意識変えるで！



##とりあえず、必要なGemのインストール！
```
Gemfileに追記

gem 'rspec-rails'
```

その後、bundle installです。


###テスト編、続きます・・・（まだ気持ちが・・・）


#さいごに
日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。
[Android]Google Map でピン立てる


# Google Map上で長押しからピンを立てる

以下の手順となります。
・長押しのイベントを取得
・Google Mapからピン情報を取得
・マーカー立てる

## 長押しのイベントを取得
GoogleMap.OnMapLongClickListener　を使いたいクラスから extends する

```
class MapsActivity : AppCompatActivity(), GoogleMap.OnMapLongClickListener {
mMap.setOnMapLongClickListener(this)
```

## Google Mapからピン情報を取得

```
override fun onMapLongClick(point: LatLng) {
```

overrideメソットからもらった point(LatLng)からマーカー作る

```
var marker = MarkerOptions().position(point).title("目的地")
```

## マーカー立てる

```
private lateinit var mMap: GoogleMap
mMap!!.addMarker(marker)
```

<img width="548" alt="marker_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/a7188853-bc92-abaa-d795-541d90ed83df.png">

![Screenshot_20200417-165102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/ce5b5ccf-5ded-a762-2fc9-94815e1429ec.png)
Leetcode 30 天挑戰, Week 3 Day 2, Valid Parenthesis String, in Swift

資料結構及演算法： `Greedy`

- 題目頁面 - <https://leetcode.com/explore/challenge/card/30-day-leetcoding-challenge/530/week-3/3301/>
- 原題目頁面 - [678. Valid Parenthesis String](https://leetcode.com/problems/valid-parenthesis-string/)

有些部分還不太能夠用自己的話講出來，待理解之後再補。

## 解題方式

因為沒有要判斷到底是誰或是哪個位置的符號會多出來，因此可以不用實際用 stack 去操作和判斷，直接去找規則然後做解法。

1. 先不考慮星號時的解法
2. 把星號考慮進去

### 先不考慮星號

基本概念是：令左括號 `(` 為 +1 ， `)` 為 -1 。只要走訪過整個字串後總和為 0 的話就能說這個字串裡面的括號是合法的。

去算總和值而不是操作資料本身這個概念在這幾天的題目有出現幾次。

``` swift
var sum = 0

for character in s {
    if character == "(" {
        sum += 1
    } else if character = ")" {
        sum -= 1
    }
}

return sum == 0 // 正值代表有多出來的左括號，負值代表有多出來的右括號
```

### 把星號考慮進去

根據題目， `星號` 可以代表 `)` 和 `空字串` 以及 `(` ，因此它可以讓總和有 -1, 0, +1 三種變化。

而總和也從 `單一個值` ，變成了 `一個範圍` 。

歸納之後如下：

| 符號 | 範圍頭 | 範圍尾 |
|:---:|:---:|:---:|
| ( | +1 | +1 |
| ) | -1 | -1 |
| * | -1 | +1 |

## 程式碼

``` swift
class Solution {
    func checkValidString(_ s: String) -> Bool {
        // 總和的可能範圍
        var lowerEnd = 0
        var upperEnd = 0
        
        for character in s {
            switch character {
                case "(":
                    lowerEnd += 1
                    upperEnd += 1
                case ")":
                    lowerEnd -= 1
                    upperEnd -= 1
                case "*":
                    lowerEnd -= 1
                    upperEnd += 1
                default:
                    break
            }
            
            // 代表有多餘的右括號，因為已經無法救回所以直接回傳結果
            if upperEnd < 0 { return false }

            // 切掉負值，這一行還不太知道該怎麼解釋。
            lowerEnd = max(lowerEnd, 0)
        }
        
        return lowerEnd <= 0 && upperEnd >= 0
    }
}
```

## 複雜度分析

令 n 為字串長度。

- 時間複雜度： O(n) 線性時間
- 空間複雜度： O(1) 常數空間

## 執行結果

``` text
Runtime: 4 ms (beats 94.44%)
Memory Usage: 20.9 MB
```
WPF sliderで小数点以下無効にして、整数のみ入力可とする方法

## WPF sliderで小数点以下無効にして、整数のみ入力可とする方法

###Sliderのプロパティで以下の設定をする。

`IsSnapToTickEnabled="True" TickFrequency="1"`




###解決した課題：

最初、Sliderと対応するTextBoxの表示書式を

`{Binding Value, ElementName=sliderLeft1, StringFormat={}{0:0}}`

等として、小数点以下を表示しないようにしていたが、

これだと、小数点以下が四捨五入されて表示されていて、

例えば、「2.8 → 3」になってるケースがあり、

設定値取得側でも小数点以下の扱いについて四捨五入か切り捨てか、など意識しなくてはならなくなり　そこが煩雑になってしまっていた。

上記の設定により、小数点以下は必ず0になるので、切り捨てか四捨五入かの意識をする必要はなくなった。

###確認環境：
- WPF
- .NET Core 3.1 (SDK ver.3.1.201)
- Visual Studio Community 2019 ver.16.5.4

[自ブログURL](https://powttonchaan.wordpress.com/2020/04/17/wpf-slider%e3%81%a7%e5%b0%8f%e6%95%b0%e7%82%b9%e4%bb%a5%e4%b8%8b%e7%84%a1%e5%8a%b9%e3%81%ab%e3%81%97%e3%81%a6%e3%80%81%e6%95%b4%e6%95%b0%e3%81%ae%e3%81%bf%e5%85%a5%e5%8a%9b%e5%8f%af%e3%81%a8%e3%81%99/)
リモートで消滅したブランチを上流にしていたローカルブランチを削除する

## TL;DR

```sh
alias git-gone="git fetch --prune && git branch --format '%(refname:short) %(push:track) %(HEAD)'|awk '\$NF==\"[gone]\"{print \$1}'|xargs -t -r git branch -D"
```

## やりたいこと

* PRの受け入れなどでリモートで削除されたブランチに対応するローカルブランチを削除したい
    * `git fetch --prune` 等でリモート追跡ブランチは削除できる
    * それらをupstreamにしていた作業用のローカルブランチが残る

## やったこと

```sh
# 最新を取ってきて追跡ブランチの削除
git fetch --prune \
# 欲しい情報を整形して取得。以下のどちらかの出力を期待する
# branch/name [tracking_status]
# branch/name [tracking_status] *　※現在チェックアウト中のブランチの場合
&& git branch --format '%(refname:short) %(push:track) %(HEAD)' \
# 最後のフィールドが [gone] になっているブランチ名を取得
# チェックアウト中のブランチは最後に * が来るので外れる
|awk '$NF==\"[gone]\"{print $1}' \
# 全ブランチを強制削除。goneしてるのに未pushがある？知らんがな。
|xargs -t -r git branch -D"
```

上記をエイリアス定義して利用することにした。


### p.s.

同じことができるコマンドがあれば教えていただけると助かります。
簡易パスワード機能(削除制限)

#簡易パスワード機能とは？
webサイト作成にあたって、ログイン機能なしで投稿機能を作りたいという要求もあるかと思います。しかし、誰でも自由に投稿できてしまうと不都合が生じます。削除、編集機能を付ける場合、勝手に他人の投稿をいじることができてしまうためです。したがって、これらの機能は投稿した人のみに制限する必要があります。ここでは、簡易パスワードを投稿者が設定し、ロックをかける仕様を実装したいと思います。一例として投稿(Tweet)に関して、削除キー(半角数字4桁)を設定していきます。
**※投稿機能は一通り実装できている前提で話します。ルーティングはresourcesなどで作っておいてください！**

#概要
1. Tweetテーブルにdeletekeyカラム(string)を追加する
2. modelで、バリデーション(deletekeyのルール)を設定する
3. 投稿フォームにdeletekeyの項目を追加する
4. 投稿詳細ページに、deletekeyの入力フォームと削除ボタンをセットで設定する
5. tweetsコントローラーのdestroyアクションにて、削除ボタンからパラメーターで送信されてきたkeyと、設定されたdeletekey(レコードに保存されているdeletekey)が一致したら、削除するという条件分岐を書く
6. エラー文

#1. deletekeyカラムの追加

ターミナル(コマンドプロンプト)上で以下を実施。(Tweetsテーブルは、必要があれば自分のテーブル名に変更してください)
**※データ型は必ずstring型にしてください。formで送信されるデータは、たとえ数字でも文字列型(string含む)だからです**

```
rails generate migration AddDeletekeyToTweets deletekey:string
```

```rails db:migrate```を忘れずに。これによりカラムを追加できました。

#2. modelでvalidationを設定する

tweet.rbに以下を追加

```models/tweet.rb
validates :deletekey, length: { is: 4}, presence: true
```
長さは4文字、未入力はダメ、というルールを設定します。これは任意にルールを設定してもOKです。

#3. 投稿フォーム
投稿フォーム(newページ)に以下を追加してください。(もちろんform_forとsubmitの間です)

```views/tweets/new.html.erb
<%= f.label :"削除キー(半角数字4桁)" %>
<%= f.number_field :deletekey, :size=> "4" %>
```

長さ4文字で、先ほど作ったdeletekeyカラムに保存できるようにしました。(number_fieldですが、文字列型(string型含む)で送られます。)

※tweetsコントローラーにて、ストロングパラメーターを設定している場合は、privateの中にdeletekeyカラムを追加するのを忘れずに。

#4. 投稿詳細ページ
deletekeyの入力フォームと削除ボタンをセットで実装します。削除ボタンを置きたい場所に以下を追加してください。

```views/tweets/show.html.erb
<%= form_tag({controller:"tweets",action:"destroy"}, method: :delete) do %>
  <%= number_field_tag :key, @word, placeholder: "削除キー(半角数字4桁)" %>
  <%= submit_tag '削除する' %>
<% end %>
```

これにより、tweetsコントローラーのdestroyアクションに```key```という名前で入力内容(半角数字4桁)が送信されます。

※途中の@wordというのは、form_tagにplaceholder(フォーム中に薄く表示される情報)を置くために仕方なく便宜的に書いているだけです。

#5. tweetsコントローラー
destroyアクションを以下のように書いてください。

```tweets_controller.rb
def destroy
  @tweet = Tweet.find(params[:id])
  if @tweet.deletekey == params[:key]
    @tweet.destroy
    redirect_to action: "index"
  else
    redirect_back(fallback_location: root_path)
    flash[:notice] = "削除キーが違います"
  end
end
```
まず、@tweetに投稿詳細ページのtweetレコードを代入します。そのレコードに保存されているdeletekeyがparamsで送られてきた```key```の中身と等しければ(等しいかどうかを判断するときは```==```を書きましょう)、tweet削除、等しくなければ、削除せず投稿詳細ページに戻る、という内容になっています。

※ちなみにもしデータ型が異なる場合、演算子(一致を表す```==```や、大小関係の<>など)で比較ができません。なので、formで送られている文字列型に統一する必要があったわけです。

等しくない場合、エラー文を表示できると親切ですよね。

#6. エラー文
上記のコントローラーにて、```flash[:notice] = "削除キーが違います"```という記述があったかと思います。これは、destroyアクションを実行してdeletekeyが一致しない場合、投稿詳細ページにエラー文を表示してくれます。削除ボタンの下あたりに以下を追加しましょう

```views/tweets/show.html.erb
<%= flash[:notice] %>
```

これにて、良い感じになったかと思います。
Fin-JAWS 第11回 最近の金融AWS事情 ～2020春〜

#[オンライン開催](https://fin-jaws.connpass.com/event/172478/presentation/)
Fin-JAWS#11に初Chime参加させていただきましたので、自分的に参考になった点を備忘録として整理しておきます。

貴重な情報を提供してくださったスピーカーの方々、いつもイベントを企画されているスタッフの方々には、とても感謝しております。しかも資料＆動画を公開している大判振る舞い！ありがとうございます。:bow:

##最近の金融AWS事情 ～2020春〜 
- **ビジネス・インパクトを生みだす**必要がある
- **人材育成・企業文化の革新**の必要性
- 大阪リージョン
 - 21年初頭リリース予定
 - 3AZs
- AWS Data Exchange = データのマーケットプレース
 - 最近はCOVID-19に関するデータが公開されている
 - ソフトウェアのAWS Marketplaceにイメージは近しい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280358/50c9ccef-9362-a35e-1e6d-d72dd5237374.png)

##金融アプリエンジニアが始めるAWS
- **金融機関の事例を知る**・・・情報たくさんあるのに自発的に取りにいってなかった:open_mouth:
- 資格を取ることが目的ではない・・・100% agreeです
- 自分で手を動かす（ハンズオン）
- アプリとインフラの境界線が曖昧に

##金融スタートアップにおける、セキュアなAWSの運用
- [AWSのガードレール戦略](https://medium.com/finatext/finatext-aws-guardrail-2705cd1e3679)
- 参考：[Control Tower](https://docs.aws.amazon.com/ja_jp/controltower/latest/userguide/what-is-control-tower.html)
- [Atlantis](https://www.runatlantis.io/)・・・TeraformをCI/CDするツール（私のイメージ）

##ブロックチェーン向け金融・経済情報サービス
- Quickが持っている情報を外部利用者にブロックチェーン技術で提供するサービス（β版）
- ブロックチェーンの分類
 - ①証跡記録・・・トレーサビリティ
 - ②価値移転・・・仮想通貨
 - ③自動契約執行・・・例えば[相続プラットフォーム](https://www.neweconomy.jp/posts/41040)が当てはまるのかなと思いました
- スマートコントラクト（契約）
- AWSで使えるブロックチェーンのフレームワーク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280358/d79c029e-e8e1-4950-f21f-2c5d5459cbb9.png)

スピーカーの皆さん、資料と説明が分かり易くて感心しました:open_mouth:
自分も発表や貢献できるように頑張ります！
【PowerAutomate】SharePoint フィルタークエリの書き方講座

#・はじめに#
Power Automateでフローを作成する時、SharePointの「複数の項目を取得する」や「項目を取得する」などのアクションを利用することがあると思います。
詳細オプションの中にはフィルタークエリが用意されておりアイテムを絞り込むことができますが、そのクエリの書き方がとても難しい！！
この記事では、利用頻度の高いフィルタークエリをサンプルコード付きで紹介します。

**※本記事は、はてなブログに移行しました。**
**　記事は最新化して情報も追加しています。よろしければそちらをご覧ください。**


**[【PowerAutomate】SharePoint フィルタークエリの書き方講座](https://kurattyodiary.hatenablog.com/entry/StudyspoFilterQuery)**
Kibanaで情報の可視化(初級)

## TL;DR
Elasticsearchのデータを基にKibanaでデータの可視化を行う。

## 本編
自分は普段の業務でElastcisearchを利用しているので、
ElasticsearchとKibanaについて書いていこうと思います。

今回は、Elasticsearchにデータを投入して,それをKibanaで可視化させる感じでいこうと思います。
本当はLogstashでElastisearchにデータを投入する方法が良いかもしれないですが、
長くなってしまうのでKibanaのサンプルデータを使わせてもらいます🙏。

### サンプルデータの投入
Kibana上でボタンポチーでできます。(今回は、Sample eCommerce ordersを入れました。)
投入後に KibanaのDev Toolsをindexを確認して、実際にデータが入っていることを確認します。(以下図参照)
<img width="682" alt="スクリーンショット 2020-04-17 13.59.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/a842c78d-d2e1-a508-22f9-5bed504a06ef.png">

kibana_sample_data_ecommerceというindexが作成されていることが確認できればOK!

### Kibana Visualizerで可視化する。
Elasticsearchにデータが入っていることが,
確認できたので早速Kibanaで視覚化していきましょー🙆‍♂️。
今回は、大陸毎の一時間毎の売り上げを確認したいと思います。（何の為かは不明😢)

Visualizeタブ内のAddからグラフの種類が選べます。(多いですねぇー👀）
<img width="812" alt="スクリーンショット 2020-04-17 14.02.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/e1731cb1-ae69-1411-7ea9-e050ec4af817.png">

Lineを選んで線グラフにしてみることにします。
今回は、総売り上げを確認したいのでY-axisに以下を設定します。
Aggregation : SUM
Field : products.price
Custom Label : 総売り上げ

次にX-axisに以下を設定します。
Aggregation : Date Histgram
Field : order_date
Interval : 1 hour
Custom Label : 注文日時

上記作業で全体の総売上を1時間毎に見ることができます。
<img width="842" alt="スクリーンショット 2020-04-17 14.25.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/5fdd8d23-efe5-c25e-a4a7-6860af571b5a.png">

でも今回は大陸毎に売り上げを見たいらしい(何故?)
なので、大陸毎にグラフを分けてあげましょう。
Split Seriesを一つ追加して以下を設定しましょう。
Sub Aggregation : Terms
Field : geoip.continent_name
Order By : metric:総売上
Custom Label : 大陸名

以上の設定で実行しましょう。
<img width="870" alt="スクリーンショット 2020-04-17 14.38.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/85e3873c-f935-379e-65ad-e931fbe22a9c.png">

これで、大陸別に一時間毎の総売上が見ることができました。
多分、Asiaの売り上げが急に増えているのを見せたかったんでしょうか？（そういうことにしておきます。。)


##　おまけ

KibanaのTimelion(タイムライン)を使用するとクエリで書くことが可能です。
(複数のグラフを重ねることができるので目標線など書くことが可能です。)

```
.es(index =kibana_sample_data_ecommerce,metric=sum:products.price,timefield=order_date,split=geoip.continent_name:10,interval=1h)
,.static(value=300).label("目標値")
```
<img width="839" alt="スクリーンショット 2020-04-17 15.51.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/b47aeb4d-fcaf-fba7-aa0d-f90c3948f019.png">
Docker環境(Debian)からMySQLに接続できない問題


# 本記事の対象読者

* 下記のエラーに悩んでいる人  
2026 (HY000): SSL connection error: error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol

# 問題
アプリをDocker環境で立ち上げ、その中から外部のMySQL（今回の場合、Amazon Aurora）に接続しようとしたときに上記のエラーが発生しました。
ベースとなるDockerイメージによってエラーが出たり出なかったりするのです。。

今回、python環境をDockerで作成する必要があったため、python3.7.4の公式イメージから作成しました。
アプリケーションの内容に深くは言及しませんが、pandasを使用した処理を行うものです。
mysql.connectorを使用して接続を試みています。

エラーが発生するDocker(Debianベース)↓

```Dockerfile:Dockerfile
FROM python:3.7.4-slim

RUN apt-get -y update  && apt-get install -y --no-install-recommends \
   apt-utils \
   python-dev \
   build-essential \
   libpq-dev

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

COPY requirements.txt /tmp/
RUN pip install -r /tmp/requirements.txt

```
エラーが発生しないDocker(Alpineベース)↓

```Dockerfile:Dockerfile
FROM python:3.7.4-alpine3.10

RUN apk --update-cache add \
 bash \
 gcc \
 g++ \
 gfortran \
 postgresql-dev \
 openblas-dev \
 freetype-dev

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

COPY requirements.txt /tmp/
RUN pip install -r /tmp/requirements.txt
```
接続部分のpythonコード↓

```python:main.py
# 一部抜粋
import mysql.connector as my

myconfig = {
    'user': 'user',
    'password': 'your_password',
    'host': 'your_host',
    'database' : 'your_db',
}

conn = my.connect(**myconfig)
```

# 目的
Alpineベースだと、build時にnumpy, pandas等のC系のbuildでかなりの時間がかかるので、DebianベースのDockerイメージにしたかった。


# 原因と解決策

MySQL 5.6/5.7の場合、対応しているTLSバージョンはTLSv1.1までなようです。
<a href="https://dev.mysql.com/doc/relnotes/connector-python/en/news-8-0-18.html">[2] Changes in MySQL Connector/Python 8.0.18 (2019-10-14, General Availability)</a>

Debianでは、opensslのデフォルト設定がTLSv1.2となっており、接続時にエラーが発生していました。

解決策は二パターンあります。

* MySQLのバージョンを変更  
こちらの方が根本的に解決しそうですが、事情があり実施できませんでした。
* Debianのデフォルト設定を変更  
Dockerfileに以下の記述を加えてbuildすると、設定値を変更することができます。
ただし、バージョンを下げることは、将来的なセキュリティ観点であまり望ましくはないでしょう。

```Dockerfile:Dockerfile
FROM python:3.7.4-slim

RUN apt-get -y update  && apt-get install -y --no-install-recommends \
   apt-utils \
   python-dev \
   build-essential \
   libpq-dev

# 変更点
RUN apt-get update -yqq \
    && apt-get install -y --no-install-recommends openssl \
    && sed -i 's,^\(MinProtocol[ ]*=\).*,\1'TLSv1.0',g' /etc/ssl/openssl.cnf \
    && rm -rf /var/lib/apt/lists/*

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

COPY requirements.txt /tmp/
RUN pip install -r /tmp/requirements.txt

```


# 調査内容
DebianのTLSデフォルト設定について
<a href="https://dev.mysql.com/doc/relnotes/connector-python/en/news-8-0-18.html">[1] Debian openssl-1.1.1</a>

PythonのMySQL Connectorのアップデート情報
<a href="https://dev.mysql.com/doc/relnotes/connector-python/en/news-8-0-18.html">[2] Changes in MySQL Connector/Python 8.0.18 (2019-10-14, General Availability)</a>

エラー内容の調査・設定値の変更方法
<a href="https://github.com/microsoft/msphpsql/issues/1023">[3] SSL routines:ssl_choose_client_version:unsupported protocol</a>


Alpineでなぜエラーが発生しないのかはわかりませんでした。
etc/ssl/openssl.cnfの中にTLSのデフォルト設定のような記載は見当たらず。。。
プロトコルの勉強をしろ、と言われそうですが、デフォルト設定がなければ良しなにTLSバージョンを選定して接続してくれる、ということ、、、、、？

もし原因がわかる方がいらっしゃれば、ご教授いただきたいです。
Ruby on Rails チュートリアル 5日目

##5日目
3章をやろうとして、herokuのappが限界を迎えてappの消去の仕方というtutorialとはあまり関係ないところでつまずいてしましました。
herokuが無料で作れるappの限界は5つまでだったんですね。いろいろ作っては、新しく作り直していたので、とうに5つに達していて、limitだとエラーが出てしまって対処方法をしらべるのでかなり手間取ってしましいました。ちなみにherokuで消したいappを選択したあとに、設定を開いた一番下の方に消すボタンが有りました。
今日は殆ど進むことが出来ませんでした。
明日は、もっと進めたいと思います。
Amazon Chimeで開催されるオンラインカンファレンスに参加するときの手順 (参加者編)

Amazon Chimeで開催されるオンラインカンファレンスに参加するときの手順メモです。

- Amazon Chime: https://aws.amazon.com/jp/chime/
- Amazon Chimeの料金: 参加者にはかかりません (https://aws.amazon.com/jp/chime/pricing/)



# 事前準備

カンファレンス参加者に必要なのは、Chimeアプリだけです。(ChimeのBasic機能を利用)

1. Amazon Chimeアプリをインストールする。(ウェブアプリケーションを利用してもOK)
  * https://aws.amazon.com/jp/chime/download-chime/


# カンファレンス参加 (iOS版の例)

1. Amazon Chimeアプリを起動する。
2. "Join a meeting without an account"をタップする。
3. 主催者から伝えられたMeeting IDを"Meeting ID"欄に入力して、矢印マークをタップする。
4. "Valid meeting ID"と"Your name"(名前入力欄)が表示される。
5. "Your name"(名前入力欄)に名前を入力して、矢印マークをタップする。
6. "Join Meeting"アイコンをタップする。
7. "Don't use My Audio"をタップする。(後で変更できる。)
8. ミーティングに参加した状態になる。
json形式のデータをtxtに直す（yolo使用）

yoloを使うためにjson形式のデータをtxt形式のデータに直したい。
#やったこと
jsonをtxtに直すコードはネットに落ちていたが、いまいち使い方がわからなかったので自分で作成することに。
(いろんなコードの一部を切り貼りしてるので見たことあるかも)
#以下コード

```python
import json
import glob

data_path = glob.glob("train_json/*.json")
img_data_path = glob.glob("train_img/*.jpg")
cate_list = ["Car","Pedestrian","Truck","Signal","Signs","Bicycle","Motorbike","Bus","Svehicle","Train"]
box_list  = ["x1","x2","y1","y2"]
input_shape = [640,640]
img_output = "train_img_data"

with open("voc_classes.txt","w") as f:
    f.write('\n'.join(cate_list))

list_file = open("2007_train.txt","w")

def class_encord(class_name):
    cate_id = {"Car":0,"Pedestrian":1,"Truck":2,"Signal":3,"Signs":4,"Bicycle":5,"Motorbike":6,"Bus":7,"SVehicle":8,"Train":9}
    return cate_id[class_name]

def img_box_resize(img_path,input_shape,label_box):
    img = Image.open(img_path)
    iw , ih = img.size
    w, h = input_shape
    scale = min(w/iw,h/ih)
    nw = int(scale*iw)
    nh = int(scale*ih)
    dx = (w-nw)//2
    dy = (h-nh)//2
    img_data = 0 
    image = img.resize((nw,nh),Image.BICUBIC)
    new_image = Image.new("RGB", (w,h), (128,128,128))
    new_image.paste(image, (dx, dy))    
    bax_lx = label_box[0]
    box_ly = label_box[1]
    box_rx = label_box[2]
    box_ry = label_box[3]
    
    new_box_lx = int(box_lx*scale) + int(dx)
    new_box_ly = int(box_ly*scale) + int(dy)
    new_box_rx = int(box_rx*scale) - int(dx)
    new_box_ry = int(box_ry*scale) - int(dy)
    box_list = []
    box_list.append(new_box_lx)
    box_list.append(new_box_ly)
    box_list.append(new_box_rx)
    box_list.append(new_box_ry)
    return new_image , box_list

def convert(data_file,list_file,input_img_path,output_img_path):
    with open(data_file) as j_f:
        load_json = json.load(j_f)
        datas = load_json["labels"]  
        for data in datas:
            box = data["box2d"]
            json_box = []  
            new_img , box_list = img_box_resize(img_path,input_shape,box)
            for i in range(4):
                json_box.append(box_list[i])
            category = data["category"]
            category_num = class_encord(category)
            list_file.write(" "+",".join([str(a) for a in json_box])+","+str(category_num))
            new_img.save(output_img_path+"/"+input_img_path)
            

for data_file in data_path:
    for img_path in img_data_path:
        data = data_file
        list_file.write(output_img_path+"/"+input_img_path)
        convert(data_file,list_file,img_path,img_output)
        list_file.write("\n")

list_file.close()
```

* data_path
* imge_data_path
* cate_list
* box_list
* input_shape
* img_output
* openの後のファイルpath
* cate_id

以上の変数を使う環境に合わせて変えてくださいinput_shapeの大きさに合わせて変換されます。

動くはず:sweat_smile:(僕はこれで動いた)
Amazon Linux 2にApacheをインストール&起動

#Apacheをインストール

yumを使います。

```shell-session:yumのアップデート
sudo yum update
```

```shell-session:Apacheインストール
sudo yum install httpd
```

#Apacheの起動、停止、自動起動

```shell-session:起動
sudo systemctl start httpd.service
```

```shell-session:停止
sudo systemctl stop httpd.service
```

```shell-session:再起動
sudo systemctl restart httpd.service
```

またインスタンス起動時に自動で起動させることができます。

```shell-session:自動起動
sudo systemctl enable httpd.service
```

```shell-session:自動起動停止
sudo systemctl disable httpd.service
```
Go言語のinterface型に対する個人的な見解

#まとめようと思ったきっかけ
Go言語を勉強していてinterfaceについて調べたことがある方、特に自分のような初心者の方。
interfaceについて説明してあるページってなんでこんなに分かりにくい表現を使うの？って思ったことありませんか？

> これがいわゆるダックタイピングです。 

知らねえよ！

> Animalというinterfaceは鳴くことができます。
猫：ミャオ
アヒル：グワッ

いや、わかるけど…！わかるけどさ！
なんかもう少し実装のイメージがつく具体例なかったの！？

> "If it walks like a duck and quacks like a duck, it must be a duck"
（もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルに違いない）

英語の授業ですか！？

#なぜこのような説明が多いのか
ひとえに「高いレベルのもの＝抽象的なもの」であることが理由であるような気がします。
また、「高いレベルの人間でありたい＝抽象的な理解をしたい」という考えは当然です。
単純な算数ドリルを勉強して、難しい応用問題を解けるようになる。
それは当たり前のこと。

#でも、
自分にとってはこの動物の例えとかダックタイピングの話がとても分かりにくかったんです。
実際に自分が実装しているものにinterfaceがどう必要なのか、それを直接的に知りたかった…。
が、調べても「グワッ」とか「ミャオ」とか可愛い話か難しすぎる話ばかり…。

#自分の見解
ここに示す自分の見解はgoで書かれたコードを読みとくとき、また、「interfaceで定義して書いといて」とか言われたときの話です。

###はじめに結論
Go言語におけるinterface型は、なんでも屋さん！
(intやstring等の型を指定しなくて良いもの)
なにを代入しても良いもの。

ただし、「なにを代入しても良い」と言ってもさすがにどんなものを代入しても良いってわけにもいかない時があるので、それを指定することもできるもの。

###なんでも屋さん
例えば型をチェックする「型チェッカー関数」を定義しましょう。
当然、どんな型でもチェックできるように型チェッカー関数の引数はinterface型になります。
![型チェッカー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208979/149a98b8-dc11-6ca9-21fa-f3df14b59f32.png)

コードにするとこんな感じ？

```golang:こんな感じ？
func 型チェッカー(i interface{}) {
  return iの型名 + "です"
}
```

これでどんな変数を入れても型名を返す関数ができました。

###「なにを代入しても良い」わけにはいかないとき
どんな型のものでも良いわけではないけど、ある程度なんでも屋さんを実装したいとき。
そんなときは最低限必要なものを決めたinterface型を定義します。

```golang:例えばメールサービスの例
type メールサービス interface {
  送信(内容) error
}
```

これで「送信」ができるものだったらなんでも良いinterface型ができます。
実際には下記のようにinterface型に適当な構造体が代入され、条件分岐のような処理が行われます。
<img width="608" alt="スクリーンショット 2020-04-17 15.14.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208979/371f8ecb-a373-34fd-de38-e45f0ea7a9cd.png">

初心者の僕らにとっては経験もないし実際の実装のイメージも湧かないので、とりあえず`interface{}`の`{}`の中になにか関数が書いてあれば、「その名前の関数がどこかに定義されていれば、どんなものを代入しても良い入れ物」ができたと認識すれば良いでしょう。
~~**interfaceの`{}`の中身は必ず関数です！関数以外は入りません！**~~
**→関数以外にもinterfaceも入れることができると指摘を受けました。** (詳細はコメント欄)

## こんなときはどう理解する？
### interface型が引数となっている関数
どんなものも引数として扱うことができる関数。
もしくは`interface{なんちゃら}`と`{}`の中身になにか関数が書いてあったら、その名前と同じ名前の関数が定義されている構造体だったらなんでも引数として扱える関数。
>その名前と同じ名前の関数が定義されている構造体

が難しかったらGo言語のメソッドについての記事を調べてみてください。
他の言語でクラスとかやってたら文法の理解は容易なはず…！

### interface型が戻り値になっている関数
どんな型の値でも返す関数。
もしくは`interface{なんちゃら}`と`{}`の中身になにか関数が書いてあったら、おそらく`{}`内の関数をその後に処理するだろうと思われる戻り値を返す関数。

###自分でinterface型を定義するとき
おそらく上記のメールサービスの例のように、同種であるがいくつかの異なるapiサービスを使うことが考えられる状況のとき。考え方としてはif分岐と一緒だと思う。

#まとめ

- interface型はなんでも屋さん。
- なんでも良すぎてもよくない場合があるので、特定の関数名をもつ構造体のみに限定させることもできる。
- ~~`interface{}`の`{}`の中身は必ず関数が入る~~
- `interface{}`の`{}`の中身はだいたい関数が入る。あとインターフェースも入る。

低レベルで結局分かりづらい内容の記事となってしまいましたが、誰かの理解が進めば幸いです。
alsoを使ってインスタンスの初期化処理をスッキリさせる(Kotlin)

## はじめに

スコープ関数のひとつである `also` を使って、インスタンスの初期化処理をスッキリさせる方法を紹介します。

[私が投稿したスコープ関数についての記事](https://qiita.com/uhooi/items/e646a28cea5d916090a9)を先に読んでいただけると嬉しいです。

## 環境

- Kotlin：1.3.61

## インスタンスの初期化処理

### `also` を使わなくても問題はない

まず、 `also` を使わない処理を紹介します。

```kotlin:△alsoを使わなくても問題はない
fun newInstance(columnCount: Int): MonsterListFragment {
    val bundle = Bundle()
    bundle.putInt(ARG_COLUMN_COUNT, columnCount)
    val fragment = MonsterListFragment()
    fragment.arguments = bundle
    return fragment
}
```

Swiftなどのプログラミング言語にはスコープ関数がなく、このような書き方が一般的だと思います。
このままでも特に問題はありません。

### `also` を入れ子にすると読みづらい

次に、 `also` を入れ子にしてワンライナーで表現します。
入れ子にすると `it` がどれを指しているかわかりづらいため、別名を付けています。

```kotlin:△alsoを入れ子にすると読みづらい
fun newInstance(columnCount: Int) =
    MonsterListFragment().also { fragment ->
        fragment.arguments = Bundle().also { bundle ->
            bundle.putInt(ARG_COLUMN_COUNT, columnCount)
        }
    }
```

これで読みやすい人もいると思いますが、個人的には読みづらいです。
Kotlinのスコープ関数に慣れていない人が読むなら、なおさら読みづらいと思います。

### `also` を入れ子にしないで使うと読みやすい

最後に、 `also` を入れ子にしないで使ってみます。

```kotlin:○alsoを入れ子にしないで使うと読みやすい
fun newInstance(columnCount: Int): MonsterListFragment {
    val bundle = Bundle().also { it.putInt(ARG_COLUMN_COUNT, columnCount) }
    return MonsterListFragment().also { it.arguments = bundle }
}
```

行数が少ないこともあり、最も読みやすく感じます。

## おわりに

簡単な例ではありますが、 `also` の使いどころを紹介しました。
他にも有用な例や使いどころがあれば、教えていただけると嬉しいです。
「Apple idサーバへの接続時にエラーが起きました」エラーからのiPhone復旧Tips

iPhoneが数日間使用不能になったので解決方法のメモ。

#### 状況
ある朝突然ネットが使用不能になり、再起動→数時間リンゴループ。
放置したところ夕方には起動。しかし全アプリ使えず。写真は削除されてた。

#### やったこと

- **いらないアプリを削除して容量空ける→変化なし**

Apple IDアカウントにサインインを求められる。
正しいpassを入力する→「apple idサーバへの接続時にエラーが起きました」エラーの繰り返し。
一時削除されてるアプリは再インストールさえもできない。

-  **ソフトウェア・アップデート→×**

そもそもログインしていないためアプデできない。

-  **iTunes経由でバックアップ/ソフトウェアアップデート→×**

どちらも認識はするが、エラーが起きて強制終了させられる。

-  **SIMを取り出してみる→×**

LINE MOBILEのSIMなのでそれが原因かと思い取り出し、再度セット。改善せず。

-  **ネットワーク設定をリセット→◎**
  
「ホーム画面」→「設定アプリ」→「一般」→「リセット」→「ネットワーク設定をリセット」
いきなりリンゴマークが出て焦ったが、何なくログイン成功。よかった…
依然としてWi-Fi接続は不能だが、とりあえず今のうちにバックアップを済ませます！
TECH CAMP入校

4月6日、ついにTECH CAMPへ入校。
それから本日までに教室へ通えたのは2日目のみ。新型コロナの影響で在宅オンライン学習となっています。コミュニケーションはSlackとZOOMで行われます。でも数あるスクールの中からわざわざ教室へ通うスタイルを選んだのに残念‥。

【大まかなここまでの学習内容】
・Webアプリケーションとは
・環境構築（準備）
・HTML&CSS
・Ruby
・Ruby on Rails

約1週間で叩き込まれます。ここまでを基礎カリキュラムとして、そこから中間試験、模試、本試験を実施。本試験に合格し応用カリキュラムへと進みます。まず中間試験が難しすぎて自信が打ち砕かれました。そこから試験に向けて猛勉強ですね。特にRailsの問題が出来なさすぎて課題となりました。

そして本試験。個人的には合格点に達したと思ったのですが、Rubyの動作が確認出来なかったとして配点無しに‥いや確認しなかった自分が悪いんですが、結構この中ではRubyは出来ているほうなので、苦手なRailsやCSSの問題に時間を割こうと思ってこのような結果に。これは今後のプログラミングをやっていく上での教訓とします。
「動作確認はしっかりと」

再試験ではきちんと動きを確かめたので合格しましたが、やはりRailsがほぼダメだったので他の部分で点数を稼いだ状態です。この不安を残したまま応用カリキュラムへと進みます。まるで車庫入れとかガソリンの入れ方とかが曖昧な状態で車の免許を取った時のあの感じですね‥。
Macのターミナルでbrewコマンドを実行できなくなったときの対処法

Macのターミナルで brewコマンドを実行したら、以下のメッセージが表示されました。

```
Error: /usr/local is not writable. You should change the
ownership and permissions of /usr/local back to your
user account:
  sudo chown -R $(whoami) /usr/local

Error: Your Xcode (1) is too outdated.
Please update to Xcode 8.3.2 (or delete it).
Xcode can be updated from
  https://developer.apple.com/download/more/

Error: Your Command Line Tools are too outdated.
Update them from Software Update in the App Store.
```
エラーが３つ出ました。
Google翻訳にかけてみます。
>エラー：/usr/localは書き込み可能ではありません。変更する必要があります
/usr/localの所有権とアクセス権
ユーザーアカウント：
  sudo chown -R $（whoami）/usr/local

>エラー：Xcode（1）は古すぎます。
Xcode 8.3.2に更新してください（または削除してください）。
Xcodeはから更新することができます
  https://developer.apple.com/download/more/

>エラー：コマンドラインツールが古すぎます。
App StoreのSoftware Updateからアップデートしてください。

結論からいうと、
これらのエラーをひとつずつ解消しようとすることに意味はありませんでした。

## 環境
・macOS Catalina 10.15.3

## 解決方法
[Homebrew公式サイト](https://brew.sh/index_ja.html)に記載されている、以下のコマンドを実行し、
再インストールします。

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

先ほどのエラーとは全く関係のない、Homebrewの更新であっさり解決です。

今後もOSのバージョンが上がるたびに同じ現象が起こるかもしれないので、
このことを覚えておきたいと思って記事にしました。

また、エラーを解消しようと試してみたことを、
このあとに記載していますので、ご興味ある方はご覧ください。

## エラー解消のために試したこと
### １．/usr/localの権限変更

メッセージにかかれている指示のとおり、以下を入力して実行しました。

```
sudo chown -R $(whoami) /usr/local
```

パスワードの入力を求められるのでパスワードを入力すると、
以下のようなメッセージが返ってきました。

```
chown: /usr/local: Operation not permitted
```

>操作は許可されていません。

と返ってきてしまいました。
ひとまず、次のエラーの解消を試みます。

### ２．Command Line Tools for Xcodeのアップデート

最初、Xcode本体のことかと思いましたが、バージョンアップしても解決せず、
どうやらコマンドラインのことだったようです。

以下のページで dmgファイルを取得しました。
https://developer.apple.com/download/more/
`command line tools` で検索すると、過去のバージョンを含めて表示されます。

Xcode本体のバージョンは 11.4.1 ですが、
エラーメッセージには`Xcode 8.3.2`と書かれていたので、
まずは、そのバージョンをインストールしてみました。
しかし、OSのバージョンに対応していないということでインストール失敗。
そのあと 11.4.1 をインストールしたのですが、これでもエラーは解消されませんでした。

## 謝辞
執筆にあたり、こちらを参考にさせていただきました。ありがとうございます。
・[HighSierraでHomebrewのbrew install、brew updateに失敗する場合の対処](https://blog.officekoma.co.jp/2018/01/highsierrahomebrewbrew-installbrew.html)
Ruby　配列の平均値に最も近い値を取り出すアルゴリズム

こんにちは、おすしです。

```ruby
ary = [2, 3, 4, 23, 9, 15, 11]

def min_search(ary)
  for i in 1..(ary.count - 1) do
    if ary[0] > ary[i]
      min = ary[i]
    else
      min = ary[0]
    end
  end
  return min
end

def search(ary)
  absolute_val = []
  adds = 0
  ary.count.times {|i| adds += ary[i]}
  center = adds/ary.count

  for i in 0..(ary.count - 1) do
    n = 0
    m = 0

    if ary[i] <= center
      m = center - ary[i]
    else 
      n = ary[i] - center
    end

    if n <= m
      l = m
    else
      l = n
    end
    
    absolute_val.push(l)
  end
  
  min_absolute = min_search(absolute_val)

  for i in 0..(absolute_val.count - 1) do
    if absolute_val[i] == min_absolute
      p "配列の平均値である　#{center}　に最も近い値は　#{ary[i]}　です"
    end
  end
end

search(ary)
```

↑をコピペして実行してください。

配列の平均値に最も近い値を取り出します（正の数）

ご覧いただきありがとうございます！


#追記
コメントでいただきました！
私が作成したアルゴリズムをたったの２行で完結させる美しいコードです。

```ruby
ary = [2, 3, 4, 23, 9, 15, 11]

avg = ary.sum.fdiv(ary.size)
near=ary.min_by{|n| (n - avg).abs }

puts "配列の平均値である　#{avg}　に最も近い値は　#{near}　です"
```
AWSでコスト削減する時の流れ

## 請求書をみる
「Billing → サイドメニューの請求書」で表示する。
IAMユーザーに請求情報のアクセス権限がないと見れないので注意。

　[アカウントの請求情報の表示を IAM ユーザーに許可するにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-billing-access/)

先月を選択して、1ヶ月間でどのサービスにどれくらいのコストがかかっているかを確認する。
使っている心当たりがないサービスがないか確認して、ある場合はリソースを削除するなり機能オフにするなり対応する。たまに、検証のために試しに使ってみたサービスがそのままになっていて課金されている場合がある。

さらに各サービスの詳細を確認する。
例えば、EC2の場合はどのインスタンスタイプを何時間分使っていていくらかかっているか、EBSにいくらかかっているか、ELBにいくらかかっているか等が確認できる。

料金体系を把握していないものがあったらAWS公式ページで確認する。
「〇〇（EC２、EBSなど） 料金」でググれば簡単に探せる。
例えば、EBSはインスタンスにアタッチされていなくても作成されていれば課金される。

## Cost Explorerをみる
「Billing → Cost Explorer → コストエクスプローラーを起動」で表示する。

「サイドメニューの推奨事項 → リソース最適化の推奨」をみて、EC2についてTerminateもしくはインスタンスタイプの変更（安いインスタンスタイプに変更）の推奨があるかどうか確認し、あれば対応する。

リザーブドインスタンスへの変更の推奨事項がある場合は、サービス継続の見通し等を考慮して対応するかどうか検討する。

## Trusted Advisorをみる
「Trusted Advisor → サイドメニューのコスト最適化」で表示する。

使用率の低いEC2インスタンスやLoad Balancer、RDS等がないか確認して、あれば削除できないか検討して対応する。

Cost Explorerは2020年4月時点ではEC2だけにしか対応していないが、Trusted AdvisorはRDS等の他サービスにも対応している。
しかし、インスタンスタイプの変更（安いインスタンスタイプに変更）の推奨事項が表示されるのはCost Explorerだけで、Trusted Advisorには表示されない。
（ちなみにCost ExplorerとTrusted Advisorの違いは色々あるが最大の違いはTrusted Advisorは1つのアカウント上の情報しか見れないがCost Explorerは複数のアカウントの情報をまとめて見れるところ）

## 削減できる箇所を考える
たいてい、コストがかかっているのは、EC2・RDS・ElastiCacheあたり。
それぞれについてサービスに影響がない範囲でコスト削減できないかを考える。

### EC2
インスタンスの数を減らせないか、インスタンスタイプを小さくできないか、インスタンスを停止できる時間帯がないかという観点で検討する。

インスタンスを停止できる時間帯がないかという観点では、夜は縮退稼働しても問題なかったり、検証環境は夜と休日は完全に止めても問題なかったりするので検討する。

インスタンスの自動起動・停止には [AWS Instance Scheduler](https://docs.aws.amazon.com/solutions/latest/instance-scheduler/welcome.html) を使う。

Auto Scalingを使っている場合は、AWS Instance SchedulerではなくAuto Scalingグループのスケジュールされたアクションを使って自動起動・停止を行う。

また、アタッチされていないEBSがないかも合わせて確認し、あれば削除する。

### RDS
検証環境で停止しても問題ない時間帯がある場合はEC2と一緒にRDSも停止する。

インスタンスの自動起動・停止には [AWS Instance Scheduler](https://docs.aws.amazon.com/solutions/latest/instance-scheduler/welcome.html) を使う。

### ElastiCache
ノードタイプを小さくできないか、ノードを減らせないかという観点で検討して対応する。

## その他
請求書の内容をじっくり見て、他にコスパ（コスト削減にかける時間と削減できるコストのバランス）の良い対応を検討して実施する。

記事投稿日：2020/4/17
.NET CoreのDatabase First Migration

.NET Coreでは2020年4月現在、VisualStudioのGUIで既存のDBからモデルを生成できない。

ということで、CUIでデータベースファーストマイグレーションを行う。

DBはSQL Serverです。

## CLIツールをインストールする

EntityFrameworkCoreのCLIツールがインストールされていなければインストールします

```
Install-Package Microsoft.EntityFrameworkCore.Tools
```

## SQLServerをインストール
SQL Serverがインストールされてなければインストールします。

```
Install-Package Microsoft.EntityFrameworkCore.SqlServer
```

## ModelをScafoldするコマンドを実行する
このコマンドを実行することで、DBからエンティティを解析して、DbContextなど、モデル情報を生成してくれます。
2回目以降は`-Force`オプションを付けます。
また、コンパイルが通る状態でないと失敗します。

```
Scaffold-DbContext "{接続文字列}" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
```

## 参考リンク
> [Doesn't mention Database First approach · Issue #16897 · dotnet/AspNetCore.Docs](https://github.com/dotnet/AspNetCore.Docs/issues/16897)
> [EF Coreツールリファレンス（Package Manager Console）-EF Core | Microsoftドキュメント](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell#scaffold-dbcontext)
Cyber Detective CTF proppedup 200

#問題

https://ctf.cybersoc.wales/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/4c448624-3307-c629-71ab-929f4796db12.png)

支えられた
200

私たちは、オフィスのCCTVカメラフィードと思われるものを取得しました。

ターゲットの1つに属するワークデスクの1つを見落としているのではないかと疑う理由があります。

DESK SURFACEの色とDESK LEGSの色を確認できますか。私たちが何を見ているかを確認し、偵察チームにさらにタスクを割り当てることができます。

フラグを次のように入力します。

（表面色）（スペース）（脚色）

注：この人物が誰であるかをうまく判断できない場合は、他のLife Onlineの課題を確認してください。これらの課題は、これらの人物を見つけるためのエントリポイントを提供する可能性があるためです。


#解いてみた

George Watson@GeorgeWatson428のツイートを確認すると以下のツイートがあったのでこれだと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/02b3898f-decd-b9b4-c973-57b6aafa8acf.png)

机表面の色は茶色
脚の色は銀
を英語にして半角スペース区切りで正解でした。
EBSのボリューム確認

#EC2にSSHで接続して以下を実行

```shell_session
df -hT /dev/xvda1
```

こんな結果が返ってきます。

```shell
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/xvda1     xfs   8.0G  3.0G  5.1G  37% /
```

Size：全容量
Used：使用容量
Avail：空き容量
Use%：使用容量（％）
Mounted on：マウントされている場所